[asterisk-commits] russell: branch russell/chan_refcount r89797 - in /team/russell/chan_refcount...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Nov 27 16:20:42 CST 2007
Author: russell
Date: Tue Nov 27 16:20:41 2007
New Revision: 89797
URL: http://svn.digium.com/view/asterisk?view=rev&rev=89797
Log:
more syncing with trunk
Added:
team/russell/chan_refcount/channels/chan_unistim.c (with props)
Modified:
team/russell/chan_refcount/pbx/pbx_lua.c
Added: team/russell/chan_refcount/channels/chan_unistim.c
URL: http://svn.digium.com/view/asterisk/team/russell/chan_refcount/channels/chan_unistim.c?view=auto&rev=89797
==============================================================================
--- team/russell/chan_refcount/channels/chan_unistim.c (added)
+++ team/russell/chan_refcount/channels/chan_unistim.c Tue Nov 27 16:20:41 2007
@@ -1,0 +1,5676 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * UNISTIM channel driver for asterisk
+ *
+ * Copyright (C) 2005 - 2007, Cedric Hans
+ *
+ * Cedric Hans <cedric.hans at mlkj.net>
+ *
+ * Asterisk 1.4 patch by Peter Be
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ *
+ * \brief chan_unistim channel driver for Asterisk
+ * \author Cedric Hans <cedric.hans at mlkj.net>
+ *
+ * Unistim (Unified Networks IP Stimulus) channel driver
+ * for Nortel i2002, i2004 and i2050
+ *
+ * \ingroup channel_drivers
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <net/if.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <sys/signal.h>
+#include <signal.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+
+#include "asterisk/paths.h" /* ast_config_AST_LOG_DIR used in (too ?) many places */
+#include "asterisk/lock.h"
+#include "asterisk/channel.h"
+#include "asterisk/config.h"
+#include "asterisk/module.h"
+#include "asterisk/pbx.h"
+#include "asterisk/sched.h"
+#include "asterisk/io.h"
+#include "asterisk/rtp.h"
+#include "asterisk/acl.h"
+#include "asterisk/callerid.h"
+#include "asterisk/cli.h"
+#include "asterisk/say.h"
+#include "asterisk/cdr.h"
+#include "asterisk/astdb.h"
+#include "asterisk/features.h"
+#include "asterisk/app.h"
+#include "asterisk/musiconhold.h"
+#include "asterisk/utils.h"
+#include "asterisk/causes.h"
+#include "asterisk/indications.h"
+#include "asterisk/dsp.h"
+#include "asterisk/devicestate.h"
+#include "asterisk/stringfields.h"
+#include "asterisk/abstract_jb.h"
+#include "asterisk/event.h"
+
+/*! Beware, G729 and G723 are not supported by asterisk, except with the proper licence */
+#define CAPABILITY AST_FORMAT_ALAW | AST_FORMAT_ULAW /* | AST_FORMAT_G729A | AST_FORMAT_G723_1 */
+
+#define DEFAULTCONTEXT "default"
+#define DEFAULTCALLERID "Unknown"
+#define DEFAULTCALLERNAME " "
+#define USTM_LOG_DIR "unistimHistory"
+
+/*! Size of the transmit buffer */
+#define MAX_BUF_SIZE 64
+/*! Number of slots for the transmit queue */
+#define MAX_BUF_NUMBER 50
+/*! Try x times before removing the phone */
+#define NB_MAX_RETRANSMIT 8
+/*! Nb of milliseconds waited when no events are scheduled */
+#define IDLE_WAIT 1000
+/*! Wait x milliseconds before resending a packet */
+#define RETRANSMIT_TIMER 2000
+/*! How often the mailbox is checked for new messages */
+#define TIMER_MWI 10000
+/*! Not used */
+#define DEFAULT_CODEC 0x00
+#define SIZE_PAGE 4096
+#define DEVICE_NAME_LEN 16
+#define AST_CONFIG_MAX_PATH 255
+#define MAX_ENTRY_LOG 30
+
+#define SUB_REAL 0
+#define SUB_THREEWAY 1
+#define MAX_SUBS 2
+
+enum autoprovision {
+ AUTOPROVISIONING_NO = 0,
+ AUTOPROVISIONING_YES,
+ AUTOPROVISIONING_DB,
+ AUTOPROVISIONING_TN
+};
+
+enum autoprov_extn {
+ /*! Do not create an extension into the default dialplan */
+ EXTENSION_NONE = 0,
+ /*! Prompt user for an extension number and register it */
+ EXTENSION_ASK,
+ /*! Register an extension with the line=> value */
+ EXTENSION_LINE,
+ /*! Used with AUTOPROVISIONING_TN */
+ EXTENSION_TN
+};
+#define OUTPUT_HANDSET 0xC0
+#define OUTPUT_HEADPHONE 0xC1
+#define OUTPUT_SPEAKER 0xC2
+
+#define VOLUME_LOW 0x01
+#define VOLUME_LOW_SPEAKER 0x03
+#define VOLUME_NORMAL 0x02
+#define VOLUME_INSANELY_LOUD 0x07
+
+#define MUTE_OFF 0x00
+#define MUTE_ON 0xFF
+#define MUTE_ON_DISCRET 0xCE
+
+#define SIZE_HEADER 6
+#define SIZE_MAC_ADDR 17
+#define TEXT_LENGTH_MAX 24
+#define TEXT_LINE0 0x00
+#define TEXT_LINE1 0x20
+#define TEXT_LINE2 0x40
+#define TEXT_NORMAL 0x05
+#define TEXT_INVERSE 0x25
+#define STATUS_LENGTH_MAX 28
+
+#define FAV_ICON_NONE 0x00
+#define FAV_ICON_ONHOOK_BLACK 0x20
+#define FAV_ICON_ONHOOK_WHITE 0x21
+#define FAV_ICON_SPEAKER_ONHOOK_BLACK 0x22
+#define FAV_ICON_SPEAKER_ONHOOK_WHITE 0x23
+#define FAV_ICON_OFFHOOK_BLACK 0x24
+#define FAV_ICON_OFFHOOK_WHITE 0x25
+#define FAV_ICON_ONHOLD_BLACK 0x26
+#define FAV_ICON_ONHOLD_WHITE 0x27
+#define FAV_ICON_SPEAKER_OFFHOOK_BLACK 0x28
+#define FAV_ICON_SPEAKER_OFFHOOK_WHITE 0x29
+#define FAV_ICON_PHONE_BLACK 0x2A
+#define FAV_ICON_PHONE_WHITE 0x2B
+#define FAV_ICON_SPEAKER_ONHOLD_BLACK 0x2C
+#define FAV_ICON_SPEAKER_ONHOLD_WHITE 0x2D
+#define FAV_ICON_HEADPHONES 0x2E
+#define FAV_ICON_HEADPHONES_ONHOLD 0x2F
+#define FAV_ICON_HOME 0x30
+#define FAV_ICON_CITY 0x31
+#define FAV_ICON_SHARP 0x32
+#define FAV_ICON_PAGER 0x33
+#define FAV_ICON_CALL_CENTER 0x34
+#define FAV_ICON_FAX 0x35
+#define FAV_ICON_MAILBOX 0x36
+#define FAV_ICON_REFLECT 0x37
+#define FAV_ICON_COMPUTER 0x38
+#define FAV_ICON_FORWARD 0x39
+#define FAV_ICON_LOCKED 0x3A
+#define FAV_ICON_TRASH 0x3B
+#define FAV_ICON_INBOX 0x3C
+#define FAV_ICON_OUTBOX 0x3D
+#define FAV_ICON_MEETING 0x3E
+#define FAV_ICON_BOX 0x3F
+
+#define FAV_BLINK_FAST 0x20
+#define FAV_BLINK_SLOW 0x40
+
+#define FAV_MAX_LENGTH 0x0A
+
+static void dummy(char *dummy, ...)
+{
+ return;
+}
+
+/*! \brief Global jitterbuffer configuration - by default, jb is disabled */
+static struct ast_jb_conf default_jbconf =
+{
+ .flags = 0,
+ .max_size = -1,
+ .resync_threshold = -1,
+ .impl = ""
+};
+static struct ast_jb_conf global_jbconf;
+
+
+/* #define DUMP_PACKET 1 */
+/* #define DEBUG_TIMER ast_verbose */
+
+#define DEBUG_TIMER dummy
+/*! Enable verbose output. can also be set with the CLI */
+static int unistimdebug = 0;
+static int unistim_port;
+static enum autoprovision autoprovisioning = AUTOPROVISIONING_NO;
+static int unistim_keepalive;
+static int unistimsock = -1;
+static struct io_context *io;
+static struct sched_context *sched;
+static struct sockaddr_in public_ip = { 0, };
+/*! give the IP address for the last packet received */
+static struct sockaddr_in addr_from;
+/*! size of the sockaddr_in (in WSARecvFrom) */
+static unsigned int size_addr_from = sizeof(addr_from);
+/*! Receive buffer address */
+static unsigned char *buff;
+static int unistim_reloading = 0;
+AST_MUTEX_DEFINE_STATIC(unistim_reload_lock);
+AST_MUTEX_DEFINE_STATIC(usecnt_lock);
+static int usecnt = 0;
+/* extern char ast_config_AST_LOG_DIR[AST_CONFIG_MAX_PATH]; */
+
+/*! This is the thread for the monitor which checks for input on the channels
+ * which are not currently in use. */
+static pthread_t monitor_thread = AST_PTHREADT_NULL;
+
+/*! Protect the monitoring thread, so only one process can kill or start it, and not
+ * when it's doing something critical. */
+AST_MUTEX_DEFINE_STATIC(monlock);
+/*! Protect the session list */
+AST_MUTEX_DEFINE_STATIC(sessionlock);
+/*! Protect the device list */
+AST_MUTEX_DEFINE_STATIC(devicelock);
+
+enum phone_state {
+ STATE_INIT,
+ STATE_AUTHDENY,
+ STATE_MAINPAGE,
+ STATE_EXTENSION,
+ STATE_DIALPAGE,
+ STATE_RINGING,
+ STATE_CALL,
+ STATE_SELECTCODEC,
+ STATE_CLEANING,
+ STATE_HISTORY
+};
+
+enum handset_state {
+ STATE_ONHOOK,
+ STATE_OFFHOOK,
+};
+
+enum phone_key {
+ KEY_0 = 0x40,
+ KEY_1 = 0x41,
+ KEY_2 = 0x42,
+ KEY_3 = 0x43,
+ KEY_4 = 0x44,
+ KEY_5 = 0x45,
+ KEY_6 = 0x46,
+ KEY_7 = 0x47,
+ KEY_8 = 0x48,
+ KEY_9 = 0x49,
+ KEY_STAR = 0x4a,
+ KEY_SHARP = 0x4b,
+ KEY_UP = 0x4c,
+ KEY_DOWN = 0x4d,
+ KEY_RIGHT = 0x4e,
+ KEY_LEFT = 0x4f,
+ KEY_QUIT = 0x50,
+ KEY_COPY = 0x51,
+ KEY_FUNC1 = 0x54,
+ KEY_FUNC2 = 0x55,
+ KEY_FUNC3 = 0x56,
+ KEY_FUNC4 = 0x57,
+ KEY_ONHOLD = 0x5b,
+ KEY_HANGUP = 0x5c,
+ KEY_MUTE = 0x5d,
+ KEY_HEADPHN = 0x5e,
+ KEY_LOUDSPK = 0x5f,
+ KEY_FAV0 = 0x60,
+ KEY_FAV1 = 0x61,
+ KEY_FAV2 = 0x62,
+ KEY_FAV3 = 0x63,
+ KEY_FAV4 = 0x64,
+ KEY_FAV5 = 0x65,
+ KEY_COMPUTR = 0x7b,
+ KEY_CONF = 0x7c,
+ KEY_SNDHIST = 0x7d,
+ KEY_RCVHIST = 0x7e,
+ KEY_INDEX = 0x7f
+};
+
+struct tone_zone_unistim {
+ char country[3];
+ int freq1;
+ int freq2;
+};
+
+static const struct tone_zone_unistim frequency[] = {
+ {"us", 350, 440},
+ {"fr", 440, 0},
+ {"au", 413, 438},
+ {"nl", 425, 0},
+ {"uk", 350, 440},
+ {"fi", 425, 0},
+ {"es", 425, 0},
+ {"jp", 400, 0},
+ {"no", 425, 0},
+ {"at", 420, 0},
+ {"nz", 400, 0},
+ {"tw", 350, 440},
+ {"cl", 400, 0},
+ {"se", 425, 0},
+ {"be", 425, 0},
+ {"sg", 425, 0},
+ {"il", 414, 0},
+ {"br", 425, 0},
+ {"hu", 425, 0},
+ {"lt", 425, 0},
+ {"pl", 425, 0},
+ {"za", 400, 0},
+ {"pt", 425, 0},
+ {"ee", 425, 0},
+ {"mx", 425, 0},
+ {"in", 400, 0},
+ {"de", 425, 0},
+ {"ch", 425, 0},
+ {"dk", 425, 0},
+ {"cn", 450, 0},
+ {"--", 0, 0}
+};
+
+struct wsabuf {
+ u_long len;
+ unsigned char *buf;
+};
+
+struct systemtime {
+ unsigned short w_year;
+ unsigned short w_month;
+ unsigned short w_day_of_week;
+ unsigned short w_day;
+ unsigned short w_hour;
+ unsigned short w_minute;
+ unsigned short w_second;
+ unsigned short w_milliseconds;
+};
+
+struct unistim_subchannel {
+ ast_mutex_t lock;
+ /*! SUBS_REAL or SUBS_THREEWAY */
+ unsigned int subtype;
+ /*! Asterisk channel used by the subchannel */
+ struct ast_channel *owner;
+ /*! Unistim line */
+ struct unistim_line *parent;
+ /*! RTP handle */
+ struct ast_rtp *rtp;
+ int alreadygone;
+ char ringvolume;
+ char ringstyle;
+};
+
+/*!
+ * \todo Convert to stringfields
+ */
+struct unistim_line {
+ ast_mutex_t lock;
+ /*! Like 200 */
+ char name[80];
+ /*! Like USTM/200\@black */
+ char fullname[80];
+ /*! pointer to our current connection, channel... */
+ struct unistim_subchannel *subs[MAX_SUBS];
+ /*! Extension where to start */
+ char exten[AST_MAX_EXTENSION];
+ /*! Context to start in */
+ char context[AST_MAX_EXTENSION];
+ /*! Language for asterisk sounds */
+ char language[MAX_LANGUAGE];
+ /*! CallerID Number */
+ char cid_num[AST_MAX_EXTENSION];
+ /*! Mailbox for MWI */
+ char mailbox[AST_MAX_EXTENSION];
+ /*! Used by MWI */
+ int lastmsgssent;
+ /*! Used by MWI */
+ time_t nextmsgcheck;
+ /*! MusicOnHold class */
+ char musicclass[MAX_MUSICCLASS];
+ /*! Call group */
+ unsigned int callgroup;
+ /*! Pickup group */
+ unsigned int pickupgroup;
+ /*! Account code (for billing) */
+ char accountcode[80];
+ /*! AMA flags (for billing) */
+ int amaflags;
+ /*! Codec supported */
+ int capability;
+ struct unistim_line *next;
+ struct unistim_device *parent;
+};
+
+/*!
+ * \brief A device containing one or more lines
+ */
+static struct unistim_device {
+ int receiver_state; /*!< state of the receiver (see ReceiverState) */
+ int size_phone_number; /*!< size of the phone number */
+ char phone_number[16]; /*!< the phone number entered by the user */
+ char redial_number[16]; /*!< the last phone number entered by the user */
+ int phone_current; /*!< Number of the current phone */
+ int pos_fav; /*!< Position of the displayed favorites (used for scrolling) */
+ char id[18]; /*!< mac address of the current phone in ascii */
+ char name[DEVICE_NAME_LEN]; /*!< name of the device */
+ int softkeylinepos; /*!< position of the line softkey (default 0) */
+ char softkeylabel[6][11]; /*!< soft key label */
+ char softkeynumber[6][16]; /*!< number dialed when the soft key is pressed */
+ char softkeyicon[6]; /*!< icon number */
+ char softkeydevice[6][16]; /*!< name of the device monitored */
+ struct unistim_device *sp[6]; /*!< pointer to the device monitored by this soft key */
+ char maintext0[25]; /*!< when the phone is idle, display this string on line 0 */
+ char maintext1[25]; /*!< when the phone is idle, display this string on line 1 */
+ char maintext2[25]; /*!< when the phone is idle, display this string on line 2 */
+ char titledefault[13]; /*!< title (text before date/time) */
+ char datetimeformat; /*!< format used for displaying time/date */
+ char contrast; /*!< contrast */
+ char country[3]; /*!< country used for dial tone frequency */
+ struct ind_tone_zone *tz; /*!< Tone zone for res_indications (ring, busy, congestion) */
+ char ringvolume; /*!< Ring volume */
+ char ringstyle; /*!< Ring melody */
+ int rtp_port; /*!< RTP port used by the phone */
+ int rtp_method; /*!< Select the unistim data used to establish a RTP session */
+ int status_method; /*!< Select the unistim packet used for sending status text */
+ char codec_number; /*!< The current codec used to make calls */
+ int missed_call; /*!< Number of call unanswered */
+ int callhistory; /*!< Allowed to record call history */
+ char lst_cid[TEXT_LENGTH_MAX]; /*!< Last callerID received */
+ char lst_cnm[TEXT_LENGTH_MAX]; /*!< Last callername recevied */
+ char call_forward[AST_MAX_EXTENSION]; /*!< Forward number */
+ int output; /*!< Handset, headphone or speaker */
+ int previous_output; /*!< Previous output */
+ int volume; /*!< Default volume */
+ int mute; /*!< Mute mode */
+ int moh; /*!< Music on hold in progress */
+ int nat; /*!< Used by the obscure ast_rtp_setnat */
+ enum autoprov_extn extension; /*!< See ifdef EXTENSION for valid values */
+ char extension_number[11]; /*!< Extension number entered by the user */
+ char to_delete; /*!< Used in reload */
+ time_t start_call_timestamp; /*!< timestamp for the length calculation of the call */
+ struct ast_silence_generator *silence_generator;
+ struct unistim_line *lines;
+ struct ast_ha *ha;
+ struct unistimsession *session;
+ struct unistim_device *next;
+} *devices = NULL;
+
+static struct unistimsession {
+ ast_mutex_t lock;
+ struct sockaddr_in sin; /*!< IP address of the phone */
+ struct sockaddr_in sout; /*!< IP address of server */
+ int timeout; /*!< time-out in ticks : resend packet if no ack was received before the timeout occured */
+ unsigned short seq_phone; /*!< sequence number for the next packet (when we receive a request) */
+ unsigned short seq_server; /*!< sequence number for the next packet (when we send a request) */
+ unsigned short last_seq_ack; /*!< sequence number of the last ACK received */
+ unsigned long tick_next_ping; /*!< time for the next ping */
+ int last_buf_available; /*!< number of a free slot */
+ int nb_retransmit; /*!< number of retransmition */
+ int state; /*!< state of the phone (see phone_state) */
+ int size_buff_entry; /*!< size of the buffer used to enter datas */
+ char buff_entry[16]; /*!< Buffer for temporary datas */
+ char macaddr[18]; /*!< mac adress of the phone (not always available) */
+ struct wsabuf wsabufsend[MAX_BUF_NUMBER]; /*!< Size of each paquet stored in the buffer array & pointer to this buffer */
+ unsigned char buf[MAX_BUF_NUMBER][MAX_BUF_SIZE]; /*!< Buffer array used to keep the lastest non-acked paquets */
+ struct unistim_device *device;
+ struct unistimsession *next;
+} *sessions = NULL;
+
+/*!
+ * \page Unistim datagram formats
+ *
+ * Format of datagrams :
+ * bytes 0 & 1 : ffff for discovery packet, 0000 for everything else
+ * byte 2 : sequence number (high part)
+ * byte 3 : sequence number (low part)
+ * byte 4 : 2 = ask question or send info, 1 = answer or ACK, 0 = retransmit request
+ * byte 5 : direction, 1 = server to phone, 2 = phone to server arguments
+ */
+
+const static unsigned char packet_rcv_discovery[] =
+ { 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
+static unsigned char packet_send_discovery_ack[] =
+ { 0x00, 0x00, /*Initial Seq (2 bytes) */ 0x00, 0x00, 0x00, 0x01 };
+
+const static unsigned char packet_recv_firm_version[] =
+ { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x0a, 0x02 };
+const static unsigned char packet_recv_pressed_key[] =
+ { 0x00, 0x00, 0x00, 0x13, 0x99, 0x04, 0x00 };
+const static unsigned char packet_recv_pick_up[] =
+ { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x04 };
+const static unsigned char packet_recv_hangup[] =
+ { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x03 };
+const static unsigned char packet_recv_r2[] = { 0x00, 0x00, 0x00, 0x13, 0x96, 0x03, 0x03 };
+
+/*! TransportAdapter */
+const static unsigned char packet_recv_resume_connection_with_server[] =
+ { 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
+const static unsigned char packet_recv_mac_addr[] =
+ { 0xff, 0xff, 0xff, 0xff, 0x9a, 0x0d, 0x07, 0x31, 0x38 /*MacAddr */ };
+
+const static unsigned char packet_send_date_time3[] =
+ { 0x11, 0x09, 0x02, 0x02, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07,
+/*Minutes */ 0x08, 0x32
+};
+const static unsigned char packet_send_date_time[] =
+ { 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07, /*Minutes */
+0x08, 0x32, 0x17, 0x04, 0x24, 0x07, 0x19,
+ 0x04, 0x07, 0x00, 0x19, 0x05, 0x09, 0x3e, 0x0f, 0x16, 0x05, 0x00, 0x80, 0x00, 0x1e,
+ 0x05, 0x12, 0x00, 0x78
+};
+
+const static unsigned char packet_send_no_ring[] =
+ { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00 };
+const static unsigned char packet_send_s4[] =
+ { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff,
+0x16, 0x05, 0x1c, 0x00, 0x00, 0x17, 0x05,
+ 0x0b, 0x00, 0x00, 0x19, 0x04, 0x00, 0x00, 0x19, 0x04, 0x00, 0x08, 0x19, 0x04, 0x00,
+ 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
+ 0x31, 0x00, 0x00, 0x16, 0x05, 0x04, 0x00, 0x00
+};
+const static unsigned char packet_send_call[] =
+ { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf,
+ 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16, 0x0a, 0x38, 0x00, 0x12, 0xca, 0x03,
+ 0xc0, 0xc3, 0xc5, 0x16, 0x16, 0x30, 0x00,
+ 0x00, /*codec */ 0x12, 0x12, /* frames per packet */ 0x01, 0x5c, 0x00, /*port RTP */
+ 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41,
+ /*port RTP */ 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41, /* IP Address */ 0x0a, 0x01,
+ 0x16, 0x66
+};
+const static unsigned char packet_send_stream_based_tone_off[] =
+ { 0x16, 0x05, 0x1c, 0x00, 0x00 };
+
+/* const static unsigned char packet_send_Mute[] = { 0x16, 0x05, 0x04, 0x00, 0x00 };
+const static unsigned char packet_send_CloseAudioStreamRX[] = { 0x16, 0x05, 0x31, 0x00, 0xff };
+const static unsigned char packet_send_CloseAudioStreamTX[] = { 0x16, 0x05, 0x31, 0xff, 0x00 };*/
+const static unsigned char packet_send_stream_based_tone_on[] =
+ { 0x16, 0x06, 0x1b, 0x00, 0x00, 0x05 };
+const static unsigned char packet_send_stream_based_tone_single_freq[] =
+ { 0x16, 0x06, 0x1d, 0x00, 0x01, 0xb8 };
+const static unsigned char packet_send_stream_based_tone_dial_freq[] =
+ { 0x16, 0x08, 0x1d, 0x00, 0x01, 0xb8, 0x01, 0x5e };
+const static unsigned char packet_send_select_output[] =
+ { 0x16, 0x06, 0x32, 0xc0, 0x01, 0x00 };
+const static unsigned char packet_send_ring[] =
+ { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16,
+ 0x04, 0x1a, 0x01, 0x16, 0x05, 0x12, 0x13 /* Ring type 10 to 17 */ , 0x18, 0x16, 0x04, 0x18, /* volume 00, 10, 20... */
+ 0x20, 0x16, 0x04, 0x10, 0x00
+};
+const static unsigned char packet_send_end_call[] =
+ { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x31, 0x00, 0x00, 0x19, 0x04, 0x00,
+0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
+ 0x04, 0x00, 0x00, 0x16, 0x04, 0x37, 0x10
+};
+const static unsigned char packet_send_s9[] =
+ { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x19, 0x04, 0x00, 0x10, 0x16, 0x05, 0x1c, 0x00,
+0x00 };
+const static unsigned char packet_send_rtp_packet_size[] =
+ { 0x16, 0x08, 0x38, 0x00, 0x00, 0xe0, 0x00, 0xa0 };
+const static unsigned char packet_send_jitter_buffer_conf[] =
+ { 0x16, 0x0e, 0x3a, 0x00, /* jitter */ 0x02, /* high water mark */ 0x04, 0x00, 0x00,
+/* early packet resync 2 bytes */ 0x3e, 0x80,
+ 0x00, 0x00, /* late packet resync 2 bytes */ 0x3e, 0x80
+};
+
+/* Duration in ms div 2 (0x20 = 64ms, 0x08 = 16ms)
+static unsigned char packet_send_StreamBasedToneCad[] =
+ { 0x16, 0x0a, 0x1e, 0x00, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x2b }; */
+const static unsigned char packet_send_open_audio_stream_rx[] =
+ { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
+0x0e, 0x01, /* Port */ 0x14, 0x50, 0x00,
+ 0x00, /* Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
+};
+const static unsigned char packet_send_open_audio_stream_tx[] =
+ { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
+0x0e, 0x01, /* Local port */ 0x14, 0x50,
+ 0x00, 0x00, /* Rmt Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
+};
+
+const static unsigned char packet_send_open_audio_stream_rx3[] =
+ { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
+0x06, 0x81, /* RTP Port */ 0x14, 0x50,
+/* RTCP Port */ 0x14,
+ 0x51, /* RTP Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00, /* Dest IP */ 0x0a, 0x93,
+ 0x69, 0x05
+};
+const static unsigned char packet_send_open_audio_stream_tx3[] =
+ { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
+0x06, 0x81, /* RTP Local port */ 0x14, 0x50,
+ /* RTCP Port */ 0x00, 0x00, /* RTP Rmt Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00,
+ /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
+};
+
+const static unsigned char packet_send_arrow[] = { 0x17, 0x04, 0x04, 0x00 };
+const static unsigned char packet_send_blink_cursor[] = { 0x17, 0x04, 0x10, 0x86 };
+const static unsigned char packet_send_date_time2[] = { 0x17, 0x04, 0x17, 0x3d, 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */
+ 0x06, /*Hour */ 0x07, /*Minutes */ 0x08, 0x32
+};
+const static unsigned char packet_send_Contrast[] =
+ { 0x17, 0x04, 0x24, /*Contrast */ 0x08 };
+const static unsigned char packet_send_StartTimer[] =
+ { 0x17, 0x05, 0x0b, 0x05, 0x00, 0x17, 0x08, 0x16, /* Text */ 0x44, 0x75, 0x72, 0xe9,
+0x65 };
+const static unsigned char packet_send_stop_timer[] = { 0x17, 0x05, 0x0b, 0x02, 0x00 };
+const static unsigned char packet_send_icon[] = { 0x17, 0x05, 0x14, /*pos */ 0x00, /*icon */ 0x25 }; /* display an icon in front of the text zone */
+const static unsigned char packet_send_S7[] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 };
+const static unsigned char packet_send_set_pos_cursor[] =
+ { 0x17, 0x06, 0x10, 0x81, 0x04, /*pos */ 0x20 };
+
+/*static unsigned char packet_send_MonthLabelsDownload[] =
+ { 0x17, 0x0a, 0x15, Month (3 char) 0x46, 0x65, 0x62, 0x4d, 0xe4, 0x72, 0x20 }; */
+const static unsigned char packet_send_favorite[] =
+ { 0x17, 0x0f, 0x19, 0x10, /*pos */ 0x01, /*name */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, /*end_name */ 0x19,
+ 0x05, 0x0f, /*pos */ 0x01, /*icone */ 0x00
+};
+const static unsigned char packet_send_title[] =
+ { 0x17, 0x10, 0x19, 0x02, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20 /*end_text */ };
+const static unsigned char packet_send_text[] =
+ { 0x17, 0x1e, 0x1b, 0x04, /*pos */ 0x00, /*inverse */ 0x25, /*text */ 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ /*end_text */ 0x17, 0x04, 0x10, 0x87
+};
+const static unsigned char packet_send_status[] =
+ { 0x17, 0x20, 0x19, 0x08, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 /*end_text */
+};
+const static unsigned char packet_send_status2[] =
+ { 0x17, 0x0b, 0x19, /* pos [08|28|48|68] */ 0x00, /* text */ 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20 /* end_text */ };
+
+const static unsigned char packet_send_led_update[] = { 0x19, 0x04, 0x00, 0x00 };
+
+const static unsigned char packet_send_query_basic_manager_04[] = { 0x1a, 0x04, 0x01, 0x04 };
+const static unsigned char packet_send_query_mac_address[] = { 0x1a, 0x04, 0x01, 0x08 };
+const static unsigned char packet_send_query_basic_manager_10[] = { 0x1a, 0x04, 0x01, 0x10 };
+const static unsigned char packet_send_S1[] = { 0x1a, 0x07, 0x07, 0x00, 0x00, 0x00, 0x13 };
+
+static unsigned char packet_send_ping[] =
+ { 0x1e, 0x05, 0x12, 0x00, /*Watchdog timer */ 0x78 };
+
+#define BUFFSEND unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }
+
+const static char tdesc[] = "UNISTIM Channel Driver";
+const static char type[] = "USTM";
+
+/*! Protos */
+static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state);
+static int load_module(void);
+static int reload(void);
+static int unload_module(void);
+static int reload_config(void);
+static void show_main_page(struct unistimsession *pte);
+static struct ast_channel *unistim_request(const char *type, int format,
+ void *data, int *cause);
+static int unistim_call(struct ast_channel *ast, char *dest, int timeout);
+static int unistim_hangup(struct ast_channel *ast);
+static int unistim_answer(struct ast_channel *ast);
+static struct ast_frame *unistim_read(struct ast_channel *ast);
+static int unistim_write(struct ast_channel *ast, struct ast_frame *frame);
+static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
+ size_t datalen);
+static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
+static int unistim_senddigit_begin(struct ast_channel *ast, char digit);
+static int unistim_senddigit_end(struct ast_channel *ast, char digit,
+ unsigned int duration);
+static int unistim_sendtext(struct ast_channel *ast, const char *text);
+
+static int write_entry_history(struct unistimsession *pte, FILE * f, char c,
+ char *line1);
+static void change_callerid(struct unistimsession *pte, int type, char *callerid);
+
+static const struct ast_channel_tech unistim_tech = {
+ .type = type,
+ .description = tdesc,
+ .capabilities = CAPABILITY,
+ .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
+ .requester = unistim_request,
+ .call = unistim_call,
+ .hangup = unistim_hangup,
+ .answer = unistim_answer,
+ .read = unistim_read,
+ .write = unistim_write,
+ .indicate = unistim_indicate,
+ .fixup = unistim_fixup,
+ .send_digit_begin = unistim_senddigit_begin,
+ .send_digit_end = unistim_senddigit_end,
+ .send_text = unistim_sendtext,
+/* .bridge = ast_rtp_bridge, */
+};
+
+static void display_last_error(const char *sz_msg)
+{
+ time_t cur_time;
+
+ time(&cur_time);
+
+ /* Display the error message */
+ ast_log(LOG_WARNING, "%s %s : (%u) %s\n", ctime(&cur_time), sz_msg, errno,
+ strerror(errno));
+}
+
+static void get_localtime(struct systemtime * systime)
+{
+ struct tm *stm;
+ time_t cur_time;
+
+ time(&cur_time);
+
+ if ((stm = localtime(&cur_time)) == 0) {
+ display_last_error("Error in localtime()");
+ return;
+ }
+
+ systime->w_year = stm->tm_year;
+ systime->w_month = stm->tm_mon + 1;
+ systime->w_day_of_week = stm->tm_wday;
+ systime->w_day = stm->tm_mday;
+ systime->w_hour = stm->tm_hour;
+ systime->w_minute = stm->tm_min;
+ systime->w_second = stm->tm_sec;
+ systime->w_milliseconds = 0;
+}
+
+static unsigned int get_tick_count(void)
+{
+ struct timeval tv = ast_tvnow();;
+
+ return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+}
+
+/* Send data to a phone without retransmit nor buffering */
+static void send_raw_client(int size, unsigned char *data, struct sockaddr_in *addr_to,
+ const struct sockaddr_in *addr_ourip)
+{
+#ifdef HAVE_PKTINFO
+ struct iovec msg_iov;
+ struct msghdr msg;
+ char buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
+ struct cmsghdr *ip_msg = (struct cmsghdr *) buffer;
+ struct in_pktinfo *pki = (struct in_pktinfo *) CMSG_DATA(ip_msg);
+
+ msg_iov.iov_base = data;
+ msg_iov.iov_len = size;
+
+ msg.msg_name = addr_to; /* optional address */
+ msg.msg_namelen = sizeof(struct sockaddr_in); /* size of address */
+ msg.msg_iov = &msg_iov; /* scatter/gather array */
+ msg.msg_iovlen = 1; /* # elements in msg_iov */
+ msg.msg_control = ip_msg; /* ancillary data */
+ msg.msg_controllen = sizeof(buffer); /* ancillary data buffer len */
+ msg.msg_flags = 0; /* flags on received message */
+
+ ip_msg->cmsg_len = CMSG_LEN(sizeof(*pki));
+ ip_msg->cmsg_level = SOL_IP;
+ ip_msg->cmsg_type = IP_PKTINFO;
+ pki->ipi_ifindex = 0; /* Interface index, 0 = use interface specified in routing table */
+ pki->ipi_spec_dst.s_addr = addr_ourip->sin_addr.s_addr; /* Local address */
+ /* pki->ipi_addr = ; Header Destination address - ignored by kernel */
+
+#ifdef DUMP_PACKET
+ if (unistimdebug) {
+ int tmp;
+ char iabuf[INET_ADDRSTRLEN];
+ char iabuf2[INET_ADDRSTRLEN];
+ ast_verbose("\n**> From %s sending %d bytes to %s ***\n",
+ ast_inet_ntoa(addr_ourip->sin_addr), (int) size,
+ ast_inet_ntoa(addr_to->sin_addr));
+ for (tmp = 0; tmp < size; tmp++)
+ ast_verbose("%.2x ", (unsigned char) data[tmp]);
+ ast_verbose("\n******************************************\n");
+
+ }
+#endif
+
+ if (sendmsg(unistimsock, &msg, 0) == -1)
+ display_last_error("Error sending datas");
+#else
+ if (sendto(unistimsock, data, size, 0, (struct sockaddr *) addr_to, sizeof(*addr_to))
+ == -1)
+ display_last_error("Error sending datas");
+#endif
+}
+
+static void send_client(int size, const unsigned char *data, struct unistimsession *pte)
+{
+ unsigned int tick;
+ int buf_pos;
+ unsigned short *sdata = (unsigned short *) data;
+
+ ast_mutex_lock(&pte->lock);
+ buf_pos = pte->last_buf_available;
+
+ if (buf_pos >= MAX_BUF_NUMBER) {
+ ast_log(LOG_WARNING, "Error : send queue overflow\n");
+ ast_mutex_unlock(&pte->lock);
+ return;
+ }
+ sdata[1] = ntohs(++(pte->seq_server));
+ pte->wsabufsend[buf_pos].len = size;
+ memcpy(pte->wsabufsend[buf_pos].buf, data, size);
+
+ tick = get_tick_count();
+ pte->timeout = tick + RETRANSMIT_TIMER;
+
+/*#ifdef DUMP_PACKET */
+ if ((unistimdebug) && (option_verbose > 5)) {
+ ast_verbose("Sending datas with seq #0x%.4x Using slot #%d :\n", pte->seq_server,
+ buf_pos);
+ }
+/*#endif */
+ send_raw_client(pte->wsabufsend[buf_pos].len, pte->wsabufsend[buf_pos].buf, &(pte->sin),
+ &(pte->sout));
+ pte->last_buf_available++;
+ ast_mutex_unlock(&pte->lock);
+}
+
+static void send_ping(struct unistimsession *pte)
+{
+ BUFFSEND;
+ if ((unistimdebug) && (option_verbose > 5))
+ ast_verbose("Sending ping\n");
+ pte->tick_next_ping = get_tick_count() + unistim_keepalive;
+ memcpy(buffsend + SIZE_HEADER, packet_send_ping, sizeof(packet_send_ping));
+ send_client(SIZE_HEADER + sizeof(packet_send_ping), buffsend, pte);
+}
+
+static int get_to_address(int fd, struct sockaddr_in *toAddr)
+{
+#ifdef HAVE_PKTINFO
+ int err;
+ struct msghdr msg;
+ struct {
+ struct cmsghdr cm;
+ int len;
+ struct in_addr address;
+ } ip_msg;
+
+ /* Zero out the structures before we use them */
+ /* This sets several key values to NULL */
+ memset(&msg, 0, sizeof(msg));
+ memset(&ip_msg, 0, sizeof(ip_msg));
+
+ /* Initialize the message structure */
+ msg.msg_control = &ip_msg;
+ msg.msg_controllen = sizeof(ip_msg);
+ /* Get info about the incoming packet */
+ err = recvmsg(fd, &msg, MSG_PEEK);
+ if (err == -1)
+ ast_log(LOG_WARNING, "recvmsg returned an error: %s\n", strerror(errno));
+ memcpy(&toAddr->sin_addr, &ip_msg.address, sizeof(struct in_addr));
+ return err;
+#else
+ memcpy(&toAddr, &public_ip, sizeof(&toAddr));
+ return 0;
+#endif
+}
+
+/* Allocate memory & initialize structures for a new phone */
+/* addr_from : ip address of the phone */
+static struct unistimsession *create_client(const struct sockaddr_in *addr_from)
+{
+ int tmp;
+ struct unistimsession *s;
+
+ if (!(s = ast_calloc(1, sizeof(*s))))
+ return NULL;
+
+ memcpy(&s->sin, addr_from, sizeof(struct sockaddr_in));
+ get_to_address(unistimsock, &s->sout);
+ if (unistimdebug) {
+ ast_verbose
+ ("Creating a new entry for the phone from %s received via server ip %s\n",
+ ast_inet_ntoa(addr_from->sin_addr), ast_inet_ntoa(s->sout.sin_addr));
+ }
+ ast_mutex_init(&s->lock);
+ ast_mutex_lock(&sessionlock);
+ s->next = sessions;
+ sessions = s;
+
+ s->timeout = get_tick_count() + RETRANSMIT_TIMER;
+ s->seq_phone = (short) 0x0000;
+ s->seq_server = (short) 0x0000;
+ s->last_seq_ack = (short) 0x000;
+ s->last_buf_available = 0;
+ s->nb_retransmit = 0;
+ s->state = STATE_INIT;
+ s->tick_next_ping = get_tick_count() + unistim_keepalive;
+ /* Initialize struct wsabuf */
+ for (tmp = 0; tmp < MAX_BUF_NUMBER; tmp++) {
+ s->wsabufsend[tmp].buf = s->buf[tmp];
+ }
+ ast_mutex_unlock(&sessionlock);
+ return s;
+}
+
+static void send_end_call(struct unistimsession *pte)
+{
+ BUFFSEND;
+ if (unistimdebug)
+ ast_verbose("Sending end call\n");
+ memcpy(buffsend + SIZE_HEADER, packet_send_end_call, sizeof(packet_send_end_call));
+ send_client(SIZE_HEADER + sizeof(packet_send_end_call), buffsend, pte);
+}
+
+static void set_ping_timer(struct unistimsession *pte)
+{
+ unsigned int tick = 0; /* XXX what is this for, anyways */
+
+ pte->timeout = pte->tick_next_ping;
+ DEBUG_TIMER("tick = %u next ping at %u tick\n", tick, pte->timeout);
+ return;
+}
+
+/* Checking if our send queue is empty,
+ * if true, setting up a timer for keepalive */
+static void check_send_queue(struct unistimsession *pte)
+{
+ /* Check if our send queue contained only one element */
+ if (pte->last_buf_available == 1) {
+ if ((unistimdebug) && (option_verbose > 5))
+ ast_verbose("Our single packet was ACKed.\n");
+ pte->last_buf_available--;
+ set_ping_timer(pte);
+ return;
+ }
+ /* Check if this ACK catch up our latest packet */
+ else if (pte->last_seq_ack + 1 == pte->seq_server + 1) {
+ if ((unistimdebug) && (option_verbose > 5))
+ ast_verbose("Our send queue is completely ACKed.\n");
+ pte->last_buf_available = 0; /* Purge the send queue */
+ set_ping_timer(pte);
+ return;
+ }
+ if ((unistimdebug) && (option_verbose > 5))
+ ast_verbose("We still have packets in our send queue\n");
+ return;
+}
+
+static void send_start_timer(struct unistimsession *pte)
+{
+ BUFFSEND;
+ if (unistimdebug)
+ ast_verbose("Sending start timer\n");
+ memcpy(buffsend + SIZE_HEADER, packet_send_StartTimer, sizeof(packet_send_StartTimer));
+ send_client(SIZE_HEADER + sizeof(packet_send_StartTimer), buffsend, pte);
+}
+
+static void send_stop_timer(struct unistimsession *pte)
+{
+ BUFFSEND;
+ if (unistimdebug)
+ ast_verbose("Sending stop timer\n");
+ memcpy(buffsend + SIZE_HEADER, packet_send_stop_timer, sizeof(packet_send_stop_timer));
+ send_client(SIZE_HEADER + sizeof(packet_send_stop_timer), buffsend, pte);
+}
+
+static void Sendicon(unsigned char pos, unsigned char status, struct unistimsession *pte)
+{
+ BUFFSEND;
+ if (unistimdebug)
+ ast_verbose("Sending icon pos %d with status 0x%.2x\n", pos, status);
+ memcpy(buffsend + SIZE_HEADER, packet_send_icon, sizeof(packet_send_icon));
+ buffsend[9] = pos;
+ buffsend[10] = status;
+ send_client(SIZE_HEADER + sizeof(packet_send_icon), buffsend, pte);
+}
+
+static void send_tone(struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
+{
+ BUFFSEND;
+ if (!tone1) {
+ if (unistimdebug)
+ ast_verbose("Sending Stream Based Tone Off\n");
+ memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_off,
+ sizeof(packet_send_stream_based_tone_off));
+ send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_off), buffsend, pte);
+ return;
+ }
+ /* Since most of the world use a continuous tone, it's useless
+ if (unistimdebug)
+ ast_verbose ("Sending Stream Based Tone Cadence Download\n");
+ memcpy (buffsend + SIZE_HEADER, packet_send_StreamBasedToneCad, sizeof (packet_send_StreamBasedToneCad));
+ send_client (SIZE_HEADER + sizeof (packet_send_StreamBasedToneCad), buffsend, pte); */
+ if (unistimdebug)
+ ast_verbose("Sending Stream Based Tone Frequency Component List Download %d %d\n",
+ tone1, tone2);
+ tone1 *= 8;
+ if (!tone2) {
+ memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_single_freq,
+ sizeof(packet_send_stream_based_tone_single_freq));
+ buffsend[10] = (tone1 & 0xff00) >> 8;
+ buffsend[11] = (tone1 & 0x00ff);
+ send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_single_freq), buffsend,
+ pte);
+ } else {
+ tone2 *= 8;
+ memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dial_freq,
+ sizeof(packet_send_stream_based_tone_dial_freq));
+ buffsend[10] = (tone1 & 0xff00) >> 8;
+ buffsend[11] = (tone1 & 0x00ff);
+ buffsend[12] = (tone2 & 0xff00) >> 8;
+ buffsend[13] = (tone2 & 0x00ff);
+ send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_dial_freq), buffsend,
+ pte);
+ }
+
+ if (unistimdebug)
+ ast_verbose("Sending Stream Based Tone On\n");
+ memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_on,
+ sizeof(packet_send_stream_based_tone_on));
+ send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_on), buffsend, pte);
+}
+
+/* Positions for favorites
+ |--------------------|
+ | 5 2 |
+ | 4 1 |
+ | 3 0 |
+*/
+
+/* status (icons) : 00 = nothing, 2x/3x = see parser.h, 4x/5x = blink fast, 6x/7x = blink slow */
+static void
+send_favorite(unsigned char pos, unsigned char status, struct unistimsession *pte,
+ const char *text)
+{
+ BUFFSEND;
+ int i;
+
+ if (unistimdebug)
+ ast_verbose("Sending favorite pos %d with status 0x%.2x\n", pos, status);
+ memcpy(buffsend + SIZE_HEADER, packet_send_favorite, sizeof(packet_send_favorite));
+ buffsend[10] = pos;
+ buffsend[24] = pos;
+ buffsend[25] = status;
+ i = strlen(text);
+ if (i > FAV_MAX_LENGTH)
+ i = FAV_MAX_LENGTH;
+ memcpy(buffsend + FAV_MAX_LENGTH + 1, text, i);
+ send_client(SIZE_HEADER + sizeof(packet_send_favorite), buffsend, pte);
+}
+
+static void refresh_all_favorite(struct unistimsession *pte)
+{
+ int i = 0;
+
+ if (unistimdebug)
+ ast_verbose("Refreshing all favorite\n");
+ for (i = 0; i < 6; i++) {
+ if ((pte->device->softkeyicon[i] <= FAV_ICON_HEADPHONES_ONHOLD) &&
+ (pte->device->softkeylinepos != i))
+ send_favorite((unsigned char) i, pte->device->softkeyicon[i] + 1, pte,
+ pte->device->softkeylabel[i]);
+ else
+ send_favorite((unsigned char) i, pte->device->softkeyicon[i], pte,
+ pte->device->softkeylabel[i]);
+
+ }
+}
+
+/* Change the status for this phone (pte) and update for each phones where pte is bookmarked
+ * use FAV_ICON_*_BLACK constant in status parameters */
+static void change_favorite_icon(struct unistimsession *pte, unsigned char status)
+{
+ struct unistim_device *d = devices;
+ int i;
+ /* Update the current phone */
+ if (pte->state != STATE_CLEANING)
+ send_favorite(pte->device->softkeylinepos, status, pte,
+ pte->device->softkeylabel[pte->device->softkeylinepos]);
+ /* Notify other phones if we're in their bookmark */
+ while (d) {
+ for (i = 0; i < 6; i++) {
+ if (d->sp[i] == pte->device) { /* It's us ? */
+ if (d->softkeyicon[i] != status) { /* Avoid resending the same icon */
+ d->softkeyicon[i] = status;
+ if (d->session)
+ send_favorite(i, status + 1, d->session, d->softkeylabel[i]);
+ }
+ }
+ }
+ d = d->next;
+ }
+}
+
+static int RegisterExtension(const struct unistimsession *pte)
+{
[... 4594 lines stripped ...]
More information about the asterisk-commits
mailing list