[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