2 * Asterisk -- An open source telephony toolkit.
4 * UNISTIM channel driver for asterisk
6 * Copyright (C) 2005 - 2007, Cedric Hans
8 * Cedric Hans <cedric.hans@mlkj.net>
10 * Asterisk 1.4 patch by Peter Be
12 * See http://www.asterisk.org for more information about
13 * the Asterisk project. Please do not directly contact
14 * any of the maintainers of this project for assistance;
15 * the project provides a web site, mailing lists and IRC
16 * channels for your use.
18 * This program is free software, distributed under the terms of
19 * the GNU General Public License Version 2. See the LICENSE file
20 * at the top of the source tree.
26 * \brief chan_unistim channel driver for Asterisk
27 * \author Cedric Hans <cedric.hans@mlkj.net>
29 * Unistim (Unified Networks IP Stimulus) channel driver
30 * for Nortel i2002, i2004 and i2050
32 * \ingroup channel_drivers
36 <conflict>winarch</conflict>
41 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
43 #include <sys/socket.h>
44 #include <sys/ioctl.h>
49 #include <sys/signal.h>
51 #include <netinet/in.h>
52 #include <netinet/in_systm.h>
53 #include <netinet/ip.h>
54 #include <arpa/inet.h>
57 #include "asterisk/paths.h" /* ast_config_AST_LOG_DIR used in (too ?) many places */
58 #include "asterisk/lock.h"
59 #include "asterisk/channel.h"
60 #include "asterisk/config.h"
61 #include "asterisk/module.h"
62 #include "asterisk/pbx.h"
63 #include "asterisk/sched.h"
64 #include "asterisk/io.h"
65 #include "asterisk/rtp.h"
66 #include "asterisk/netsock.h"
67 #include "asterisk/acl.h"
68 #include "asterisk/callerid.h"
69 #include "asterisk/cli.h"
70 #include "asterisk/say.h"
71 #include "asterisk/cdr.h"
72 #include "asterisk/astdb.h"
73 #include "asterisk/features.h"
74 #include "asterisk/app.h"
75 #include "asterisk/musiconhold.h"
76 #include "asterisk/utils.h"
77 #include "asterisk/causes.h"
78 #include "asterisk/indications.h"
79 #include "asterisk/dsp.h"
80 #include "asterisk/devicestate.h"
81 #include "asterisk/stringfields.h"
82 #include "asterisk/abstract_jb.h"
83 #include "asterisk/event.h"
84 #include "asterisk/localtime.h"
86 /*! Beware, G729 and G723 are not supported by asterisk, except with the proper licence */
87 #define CAPABILITY AST_FORMAT_ALAW | AST_FORMAT_ULAW /* | AST_FORMAT_G729A | AST_FORMAT_G723_1 */
89 #define DEFAULTCONTEXT "default"
90 #define DEFAULTCALLERID "Unknown"
91 #define DEFAULTCALLERNAME " "
92 #define USTM_LOG_DIR "unistimHistory"
94 /*! Size of the transmit buffer */
95 #define MAX_BUF_SIZE 64
96 /*! Number of slots for the transmit queue */
97 #define MAX_BUF_NUMBER 50
98 /*! Try x times before removing the phone */
99 #define NB_MAX_RETRANSMIT 8
100 /*! Nb of milliseconds waited when no events are scheduled */
101 #define IDLE_WAIT 1000
102 /*! Wait x milliseconds before resending a packet */
103 #define RETRANSMIT_TIMER 2000
104 /*! How often the mailbox is checked for new messages */
105 #define TIMER_MWI 10000
107 #define DEFAULT_CODEC 0x00
108 #define SIZE_PAGE 4096
109 #define DEVICE_NAME_LEN 16
110 #define AST_CONFIG_MAX_PATH 255
111 #define MAX_ENTRY_LOG 30
114 #define SUB_THREEWAY 1
118 AUTOPROVISIONING_NO = 0,
119 AUTOPROVISIONING_YES,
125 /*! Do not create an extension into the default dialplan */
127 /*! Prompt user for an extension number and register it */
129 /*! Register an extension with the line=> value */
131 /*! Used with AUTOPROVISIONING_TN */
134 #define OUTPUT_HANDSET 0xC0
135 #define OUTPUT_HEADPHONE 0xC1
136 #define OUTPUT_SPEAKER 0xC2
138 #define VOLUME_LOW 0x01
139 #define VOLUME_LOW_SPEAKER 0x03
140 #define VOLUME_NORMAL 0x02
141 #define VOLUME_INSANELY_LOUD 0x07
143 #define MUTE_OFF 0x00
145 #define MUTE_ON_DISCRET 0xCE
147 #define SIZE_HEADER 6
148 #define SIZE_MAC_ADDR 17
149 #define TEXT_LENGTH_MAX 24
150 #define TEXT_LINE0 0x00
151 #define TEXT_LINE1 0x20
152 #define TEXT_LINE2 0x40
153 #define TEXT_NORMAL 0x05
154 #define TEXT_INVERSE 0x25
155 #define STATUS_LENGTH_MAX 28
157 #define FAV_ICON_NONE 0x00
158 #define FAV_ICON_ONHOOK_BLACK 0x20
159 #define FAV_ICON_ONHOOK_WHITE 0x21
160 #define FAV_ICON_SPEAKER_ONHOOK_BLACK 0x22
161 #define FAV_ICON_SPEAKER_ONHOOK_WHITE 0x23
162 #define FAV_ICON_OFFHOOK_BLACK 0x24
163 #define FAV_ICON_OFFHOOK_WHITE 0x25
164 #define FAV_ICON_ONHOLD_BLACK 0x26
165 #define FAV_ICON_ONHOLD_WHITE 0x27
166 #define FAV_ICON_SPEAKER_OFFHOOK_BLACK 0x28
167 #define FAV_ICON_SPEAKER_OFFHOOK_WHITE 0x29
168 #define FAV_ICON_PHONE_BLACK 0x2A
169 #define FAV_ICON_PHONE_WHITE 0x2B
170 #define FAV_ICON_SPEAKER_ONHOLD_BLACK 0x2C
171 #define FAV_ICON_SPEAKER_ONHOLD_WHITE 0x2D
172 #define FAV_ICON_HEADPHONES 0x2E
173 #define FAV_ICON_HEADPHONES_ONHOLD 0x2F
174 #define FAV_ICON_HOME 0x30
175 #define FAV_ICON_CITY 0x31
176 #define FAV_ICON_SHARP 0x32
177 #define FAV_ICON_PAGER 0x33
178 #define FAV_ICON_CALL_CENTER 0x34
179 #define FAV_ICON_FAX 0x35
180 #define FAV_ICON_MAILBOX 0x36
181 #define FAV_ICON_REFLECT 0x37
182 #define FAV_ICON_COMPUTER 0x38
183 #define FAV_ICON_FORWARD 0x39
184 #define FAV_ICON_LOCKED 0x3A
185 #define FAV_ICON_TRASH 0x3B
186 #define FAV_ICON_INBOX 0x3C
187 #define FAV_ICON_OUTBOX 0x3D
188 #define FAV_ICON_MEETING 0x3E
189 #define FAV_ICON_BOX 0x3F
191 #define FAV_BLINK_FAST 0x20
192 #define FAV_BLINK_SLOW 0x40
194 #define FAV_MAX_LENGTH 0x0A
196 static void dummy(char *dummy, ...)
201 /*! \brief Global jitterbuffer configuration - by default, jb is disabled */
202 static struct ast_jb_conf default_jbconf =
206 .resync_threshold = -1,
209 static struct ast_jb_conf global_jbconf;
212 /* #define DUMP_PACKET 1 */
213 /* #define DEBUG_TIMER ast_verbose */
215 #define DEBUG_TIMER dummy
216 /*! Enable verbose output. can also be set with the CLI */
217 static int unistimdebug = 0;
218 static int unistim_port;
219 static enum autoprovision autoprovisioning = AUTOPROVISIONING_NO;
220 static int unistim_keepalive;
221 static int unistimsock = -1;
222 static unsigned int tos = 0;
223 static unsigned int tos_audio = 0;
224 static unsigned int cos = 0;
225 static unsigned int cos_audio = 0;
226 static struct io_context *io;
227 static struct sched_context *sched;
228 static struct sockaddr_in public_ip = { 0, };
229 /*! give the IP address for the last packet received */
230 static struct sockaddr_in addr_from;
231 /*! size of the sockaddr_in (in WSARecvFrom) */
232 static unsigned int size_addr_from = sizeof(addr_from);
233 /*! Receive buffer address */
234 static unsigned char *buff;
235 static int unistim_reloading = 0;
236 AST_MUTEX_DEFINE_STATIC(unistim_reload_lock);
237 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
238 static int usecnt = 0;
239 /* extern char ast_config_AST_LOG_DIR[AST_CONFIG_MAX_PATH]; */
241 /*! This is the thread for the monitor which checks for input on the channels
242 * which are not currently in use. */
243 static pthread_t monitor_thread = AST_PTHREADT_NULL;
245 /*! Protect the monitoring thread, so only one process can kill or start it, and not
246 * when it's doing something critical. */
247 AST_MUTEX_DEFINE_STATIC(monlock);
248 /*! Protect the session list */
249 AST_MUTEX_DEFINE_STATIC(sessionlock);
250 /*! Protect the device list */
251 AST_MUTEX_DEFINE_STATIC(devicelock);
312 struct tone_zone_unistim {
318 static const struct tone_zone_unistim frequency[] = {
358 unsigned short w_year;
359 unsigned short w_month;
360 unsigned short w_day_of_week;
361 unsigned short w_day;
362 unsigned short w_hour;
363 unsigned short w_minute;
364 unsigned short w_second;
365 unsigned short w_milliseconds;
368 struct unistim_subchannel {
370 /*! SUBS_REAL or SUBS_THREEWAY */
371 unsigned int subtype;
372 /*! Asterisk channel used by the subchannel */
373 struct ast_channel *owner;
375 struct unistim_line *parent;
384 * \todo Convert to stringfields
386 struct unistim_line {
390 /*! Like USTM/200\@black */
392 /*! pointer to our current connection, channel... */
393 struct unistim_subchannel *subs[MAX_SUBS];
394 /*! Extension where to start */
395 char exten[AST_MAX_EXTENSION];
396 /*! Context to start in */
397 char context[AST_MAX_EXTENSION];
398 /*! Language for asterisk sounds */
399 char language[MAX_LANGUAGE];
400 /*! CallerID Number */
401 char cid_num[AST_MAX_EXTENSION];
402 /*! Mailbox for MWI */
403 char mailbox[AST_MAX_EXTENSION];
408 /*! MusicOnHold class */
409 char musicclass[MAX_MUSICCLASS];
411 unsigned int callgroup;
413 unsigned int pickupgroup;
414 /*! Account code (for billing) */
415 char accountcode[80];
416 /*! AMA flags (for billing) */
418 /*! Codec supported */
420 struct unistim_line *next;
421 struct unistim_device *parent;
425 * \brief A device containing one or more lines
427 static struct unistim_device {
428 int receiver_state; /*!< state of the receiver (see ReceiverState) */
429 int size_phone_number; /*!< size of the phone number */
430 char phone_number[16]; /*!< the phone number entered by the user */
431 char redial_number[16]; /*!< the last phone number entered by the user */
432 int phone_current; /*!< Number of the current phone */
433 int pos_fav; /*!< Position of the displayed favorites (used for scrolling) */
434 char id[18]; /*!< mac address of the current phone in ascii */
435 char name[DEVICE_NAME_LEN]; /*!< name of the device */
436 int softkeylinepos; /*!< position of the line softkey (default 0) */
437 char softkeylabel[6][11]; /*!< soft key label */
438 char softkeynumber[6][16]; /*!< number dialed when the soft key is pressed */
439 char softkeyicon[6]; /*!< icon number */
440 char softkeydevice[6][16]; /*!< name of the device monitored */
441 struct unistim_device *sp[6]; /*!< pointer to the device monitored by this soft key */
442 char maintext0[25]; /*!< when the phone is idle, display this string on line 0 */
443 char maintext1[25]; /*!< when the phone is idle, display this string on line 1 */
444 char maintext2[25]; /*!< when the phone is idle, display this string on line 2 */
445 char titledefault[13]; /*!< title (text before date/time) */
446 char datetimeformat; /*!< format used for displaying time/date */
447 char contrast; /*!< contrast */
448 char country[3]; /*!< country used for dial tone frequency */
449 struct ind_tone_zone *tz; /*!< Tone zone for res_indications (ring, busy, congestion) */
450 char ringvolume; /*!< Ring volume */
451 char ringstyle; /*!< Ring melody */
452 int rtp_port; /*!< RTP port used by the phone */
453 int rtp_method; /*!< Select the unistim data used to establish a RTP session */
454 int status_method; /*!< Select the unistim packet used for sending status text */
455 char codec_number; /*!< The current codec used to make calls */
456 int missed_call; /*!< Number of call unanswered */
457 int callhistory; /*!< Allowed to record call history */
458 char lst_cid[TEXT_LENGTH_MAX]; /*!< Last callerID received */
459 char lst_cnm[TEXT_LENGTH_MAX]; /*!< Last callername recevied */
460 char call_forward[AST_MAX_EXTENSION]; /*!< Forward number */
461 int output; /*!< Handset, headphone or speaker */
462 int previous_output; /*!< Previous output */
463 int volume; /*!< Default volume */
464 int mute; /*!< Mute mode */
465 int moh; /*!< Music on hold in progress */
466 int nat; /*!< Used by the obscure ast_rtp_setnat */
467 enum autoprov_extn extension; /*!< See ifdef EXTENSION for valid values */
468 char extension_number[11]; /*!< Extension number entered by the user */
469 char to_delete; /*!< Used in reload */
470 time_t start_call_timestamp; /*!< timestamp for the length calculation of the call */
471 struct ast_silence_generator *silence_generator;
472 struct unistim_line *lines;
474 struct unistimsession *session;
475 struct unistim_device *next;
478 static struct unistimsession {
480 struct sockaddr_in sin; /*!< IP address of the phone */
481 struct sockaddr_in sout; /*!< IP address of server */
482 int timeout; /*!< time-out in ticks : resend packet if no ack was received before the timeout occured */
483 unsigned short seq_phone; /*!< sequence number for the next packet (when we receive a request) */
484 unsigned short seq_server; /*!< sequence number for the next packet (when we send a request) */
485 unsigned short last_seq_ack; /*!< sequence number of the last ACK received */
486 unsigned long tick_next_ping; /*!< time for the next ping */
487 int last_buf_available; /*!< number of a free slot */
488 int nb_retransmit; /*!< number of retransmition */
489 int state; /*!< state of the phone (see phone_state) */
490 int size_buff_entry; /*!< size of the buffer used to enter datas */
491 char buff_entry[16]; /*!< Buffer for temporary datas */
492 char macaddr[18]; /*!< mac adress of the phone (not always available) */
493 struct wsabuf wsabufsend[MAX_BUF_NUMBER]; /*!< Size of each paquet stored in the buffer array & pointer to this buffer */
494 unsigned char buf[MAX_BUF_NUMBER][MAX_BUF_SIZE]; /*!< Buffer array used to keep the lastest non-acked paquets */
495 struct unistim_device *device;
496 struct unistimsession *next;
500 * \page Unistim datagram formats
502 * Format of datagrams :
503 * bytes 0 & 1 : ffff for discovery packet, 0000 for everything else
504 * byte 2 : sequence number (high part)
505 * byte 3 : sequence number (low part)
506 * byte 4 : 2 = ask question or send info, 1 = answer or ACK, 0 = retransmit request
507 * byte 5 : direction, 1 = server to phone, 2 = phone to server arguments
510 const static unsigned char packet_rcv_discovery[] =
511 { 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
512 static unsigned char packet_send_discovery_ack[] =
513 { 0x00, 0x00, /*Initial Seq (2 bytes) */ 0x00, 0x00, 0x00, 0x01 };
515 const static unsigned char packet_recv_firm_version[] =
516 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x0a, 0x02 };
517 const static unsigned char packet_recv_pressed_key[] =
518 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x04, 0x00 };
519 const static unsigned char packet_recv_pick_up[] =
520 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x04 };
521 const static unsigned char packet_recv_hangup[] =
522 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x03 };
523 const static unsigned char packet_recv_r2[] = { 0x00, 0x00, 0x00, 0x13, 0x96, 0x03, 0x03 };
525 /*! TransportAdapter */
526 const static unsigned char packet_recv_resume_connection_with_server[] =
527 { 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
528 const static unsigned char packet_recv_mac_addr[] =
529 { 0xff, 0xff, 0xff, 0xff, 0x9a, 0x0d, 0x07, 0x31, 0x38 /*MacAddr */ };
531 const static unsigned char packet_send_date_time3[] =
532 { 0x11, 0x09, 0x02, 0x02, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07,
533 /*Minutes */ 0x08, 0x32
535 const static unsigned char packet_send_date_time[] =
536 { 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07, /*Minutes */
537 0x08, 0x32, 0x17, 0x04, 0x24, 0x07, 0x19,
538 0x04, 0x07, 0x00, 0x19, 0x05, 0x09, 0x3e, 0x0f, 0x16, 0x05, 0x00, 0x80, 0x00, 0x1e,
539 0x05, 0x12, 0x00, 0x78
542 const static unsigned char packet_send_no_ring[] =
543 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00 };
544 const static unsigned char packet_send_s4[] =
545 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff,
546 0x16, 0x05, 0x1c, 0x00, 0x00, 0x17, 0x05,
547 0x0b, 0x00, 0x00, 0x19, 0x04, 0x00, 0x00, 0x19, 0x04, 0x00, 0x08, 0x19, 0x04, 0x00,
548 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
549 0x31, 0x00, 0x00, 0x16, 0x05, 0x04, 0x00, 0x00
551 const static unsigned char packet_send_call[] =
552 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf,
553 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16, 0x0a, 0x38, 0x00, 0x12, 0xca, 0x03,
554 0xc0, 0xc3, 0xc5, 0x16, 0x16, 0x30, 0x00,
555 0x00, /*codec */ 0x12, 0x12, /* frames per packet */ 0x01, 0x5c, 0x00, /*port RTP */
556 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41,
557 /*port RTP */ 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41, /* IP Address */ 0x0a, 0x01,
560 const static unsigned char packet_send_stream_based_tone_off[] =
561 { 0x16, 0x05, 0x1c, 0x00, 0x00 };
563 /* const static unsigned char packet_send_Mute[] = { 0x16, 0x05, 0x04, 0x00, 0x00 };
564 const static unsigned char packet_send_CloseAudioStreamRX[] = { 0x16, 0x05, 0x31, 0x00, 0xff };
565 const static unsigned char packet_send_CloseAudioStreamTX[] = { 0x16, 0x05, 0x31, 0xff, 0x00 };*/
566 const static unsigned char packet_send_stream_based_tone_on[] =
567 { 0x16, 0x06, 0x1b, 0x00, 0x00, 0x05 };
568 const static unsigned char packet_send_stream_based_tone_single_freq[] =
569 { 0x16, 0x06, 0x1d, 0x00, 0x01, 0xb8 };
570 const static unsigned char packet_send_stream_based_tone_dial_freq[] =
571 { 0x16, 0x08, 0x1d, 0x00, 0x01, 0xb8, 0x01, 0x5e };
572 const static unsigned char packet_send_select_output[] =
573 { 0x16, 0x06, 0x32, 0xc0, 0x01, 0x00 };
574 const static unsigned char packet_send_ring[] =
575 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16,
576 0x04, 0x1a, 0x01, 0x16, 0x05, 0x12, 0x13 /* Ring type 10 to 17 */ , 0x18, 0x16, 0x04, 0x18, /* volume 00, 10, 20... */
577 0x20, 0x16, 0x04, 0x10, 0x00
579 const static unsigned char packet_send_end_call[] =
580 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x31, 0x00, 0x00, 0x19, 0x04, 0x00,
581 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
582 0x04, 0x00, 0x00, 0x16, 0x04, 0x37, 0x10
584 const static unsigned char packet_send_s9[] =
585 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x19, 0x04, 0x00, 0x10, 0x16, 0x05, 0x1c, 0x00,
587 const static unsigned char packet_send_rtp_packet_size[] =
588 { 0x16, 0x08, 0x38, 0x00, 0x00, 0xe0, 0x00, 0xa0 };
589 const static unsigned char packet_send_jitter_buffer_conf[] =
590 { 0x16, 0x0e, 0x3a, 0x00, /* jitter */ 0x02, /* high water mark */ 0x04, 0x00, 0x00,
591 /* early packet resync 2 bytes */ 0x3e, 0x80,
592 0x00, 0x00, /* late packet resync 2 bytes */ 0x3e, 0x80
595 /* Duration in ms div 2 (0x20 = 64ms, 0x08 = 16ms)
596 static unsigned char packet_send_StreamBasedToneCad[] =
597 { 0x16, 0x0a, 0x1e, 0x00, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x2b }; */
598 const static unsigned char packet_send_open_audio_stream_rx[] =
599 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
600 0x0e, 0x01, /* Port */ 0x14, 0x50, 0x00,
601 0x00, /* Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
603 const static unsigned char packet_send_open_audio_stream_tx[] =
604 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
605 0x0e, 0x01, /* Local port */ 0x14, 0x50,
606 0x00, 0x00, /* Rmt Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
609 const static unsigned char packet_send_open_audio_stream_rx3[] =
610 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
611 0x06, 0x81, /* RTP Port */ 0x14, 0x50,
612 /* RTCP Port */ 0x14,
613 0x51, /* RTP Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00, /* Dest IP */ 0x0a, 0x93,
616 const static unsigned char packet_send_open_audio_stream_tx3[] =
617 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
618 0x06, 0x81, /* RTP Local port */ 0x14, 0x50,
619 /* RTCP Port */ 0x00, 0x00, /* RTP Rmt Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00,
620 /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
623 const static unsigned char packet_send_arrow[] = { 0x17, 0x04, 0x04, 0x00 };
624 const static unsigned char packet_send_blink_cursor[] = { 0x17, 0x04, 0x10, 0x86 };
625 const static unsigned char packet_send_date_time2[] = { 0x17, 0x04, 0x17, 0x3d, 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */
626 0x06, /*Hour */ 0x07, /*Minutes */ 0x08, 0x32
628 const static unsigned char packet_send_Contrast[] =
629 { 0x17, 0x04, 0x24, /*Contrast */ 0x08 };
630 const static unsigned char packet_send_StartTimer[] =
631 { 0x17, 0x05, 0x0b, 0x05, 0x00, 0x17, 0x08, 0x16, /* Text */ 0x44, 0x75, 0x72, 0xe9,
633 const static unsigned char packet_send_stop_timer[] = { 0x17, 0x05, 0x0b, 0x02, 0x00 };
634 const static unsigned char packet_send_icon[] = { 0x17, 0x05, 0x14, /*pos */ 0x00, /*icon */ 0x25 }; /* display an icon in front of the text zone */
635 const static unsigned char packet_send_S7[] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 };
636 const static unsigned char packet_send_set_pos_cursor[] =
637 { 0x17, 0x06, 0x10, 0x81, 0x04, /*pos */ 0x20 };
639 /*static unsigned char packet_send_MonthLabelsDownload[] =
640 { 0x17, 0x0a, 0x15, Month (3 char) 0x46, 0x65, 0x62, 0x4d, 0xe4, 0x72, 0x20 }; */
641 const static unsigned char packet_send_favorite[] =
642 { 0x17, 0x0f, 0x19, 0x10, /*pos */ 0x01, /*name */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
643 0x20, 0x20, 0x20, 0x20, /*end_name */ 0x19,
644 0x05, 0x0f, /*pos */ 0x01, /*icone */ 0x00
646 const static unsigned char packet_send_title[] =
647 { 0x17, 0x10, 0x19, 0x02, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
648 0x20, 0x20, 0x20, 0x20 /*end_text */ };
649 const static unsigned char packet_send_text[] =
650 { 0x17, 0x1e, 0x1b, 0x04, /*pos */ 0x00, /*inverse */ 0x25, /*text */ 0x20, 0x20,
651 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
652 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
653 /*end_text */ 0x17, 0x04, 0x10, 0x87
655 const static unsigned char packet_send_status[] =
656 { 0x17, 0x20, 0x19, 0x08, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
657 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
658 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 /*end_text */
660 const static unsigned char packet_send_status2[] =
661 { 0x17, 0x0b, 0x19, /* pos [08|28|48|68] */ 0x00, /* text */ 0x20, 0x20, 0x20, 0x20,
662 0x20, 0x20, 0x20 /* end_text */ };
664 const static unsigned char packet_send_led_update[] = { 0x19, 0x04, 0x00, 0x00 };
666 const static unsigned char packet_send_query_basic_manager_04[] = { 0x1a, 0x04, 0x01, 0x04 };
667 const static unsigned char packet_send_query_mac_address[] = { 0x1a, 0x04, 0x01, 0x08 };
668 const static unsigned char packet_send_query_basic_manager_10[] = { 0x1a, 0x04, 0x01, 0x10 };
669 const static unsigned char packet_send_S1[] = { 0x1a, 0x07, 0x07, 0x00, 0x00, 0x00, 0x13 };
671 static unsigned char packet_send_ping[] =
672 { 0x1e, 0x05, 0x12, 0x00, /*Watchdog timer */ 0x78 };
674 #define BUFFSEND unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }
676 const static char tdesc[] = "UNISTIM Channel Driver";
677 const static char type[] = "USTM";
680 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state);
681 static int load_module(void);
682 static int reload(void);
683 static int unload_module(void);
684 static int reload_config(void);
685 static void show_main_page(struct unistimsession *pte);
686 static struct ast_channel *unistim_request(const char *type, int format,
687 void *data, int *cause);
688 static int unistim_call(struct ast_channel *ast, char *dest, int timeout);
689 static int unistim_hangup(struct ast_channel *ast);
690 static int unistim_answer(struct ast_channel *ast);
691 static struct ast_frame *unistim_read(struct ast_channel *ast);
692 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame);
693 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
695 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
696 static int unistim_senddigit_begin(struct ast_channel *ast, char digit);
697 static int unistim_senddigit_end(struct ast_channel *ast, char digit,
698 unsigned int duration);
699 static int unistim_sendtext(struct ast_channel *ast, const char *text);
701 static int write_entry_history(struct unistimsession *pte, FILE * f, char c,
703 static void change_callerid(struct unistimsession *pte, int type, char *callerid);
705 static const struct ast_channel_tech unistim_tech = {
707 .description = tdesc,
708 .capabilities = CAPABILITY,
709 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
710 .requester = unistim_request,
711 .call = unistim_call,
712 .hangup = unistim_hangup,
713 .answer = unistim_answer,
714 .read = unistim_read,
715 .write = unistim_write,
716 .indicate = unistim_indicate,
717 .fixup = unistim_fixup,
718 .send_digit_begin = unistim_senddigit_begin,
719 .send_digit_end = unistim_senddigit_end,
720 .send_text = unistim_sendtext,
721 /* .bridge = ast_rtp_bridge, */
724 static void display_last_error(const char *sz_msg)
730 /* Display the error message */
731 ast_log(LOG_WARNING, "%s %s : (%u) %s\n", ctime(&cur_time), sz_msg, errno,
735 static unsigned int get_tick_count(void)
737 struct timeval tv = ast_tvnow();
739 return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
742 /* Send data to a phone without retransmit nor buffering */
743 static void send_raw_client(int size, unsigned char *data, struct sockaddr_in *addr_to,
744 const struct sockaddr_in *addr_ourip)
747 struct iovec msg_iov;
749 char buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
750 struct cmsghdr *ip_msg = (struct cmsghdr *) buffer;
751 struct in_pktinfo *pki = (struct in_pktinfo *) CMSG_DATA(ip_msg);
753 msg_iov.iov_base = data;
754 msg_iov.iov_len = size;
756 msg.msg_name = addr_to; /* optional address */
757 msg.msg_namelen = sizeof(struct sockaddr_in); /* size of address */
758 msg.msg_iov = &msg_iov; /* scatter/gather array */
759 msg.msg_iovlen = 1; /* # elements in msg_iov */
760 msg.msg_control = ip_msg; /* ancillary data */
761 msg.msg_controllen = sizeof(buffer); /* ancillary data buffer len */
762 msg.msg_flags = 0; /* flags on received message */
764 ip_msg->cmsg_len = CMSG_LEN(sizeof(*pki));
765 ip_msg->cmsg_level = IPPROTO_IP;
766 ip_msg->cmsg_type = IP_PKTINFO;
767 pki->ipi_ifindex = 0; /* Interface index, 0 = use interface specified in routing table */
768 pki->ipi_spec_dst.s_addr = addr_ourip->sin_addr.s_addr; /* Local address */
769 /* pki->ipi_addr = ; Header Destination address - ignored by kernel */
774 char iabuf[INET_ADDRSTRLEN];
775 char iabuf2[INET_ADDRSTRLEN];
776 ast_verbose("\n**> From %s sending %d bytes to %s ***\n",
777 ast_inet_ntoa(addr_ourip->sin_addr), (int) size,
778 ast_inet_ntoa(addr_to->sin_addr));
779 for (tmp = 0; tmp < size; tmp++)
780 ast_verbose("%.2x ", (unsigned char) data[tmp]);
781 ast_verbose("\n******************************************\n");
786 if (sendmsg(unistimsock, &msg, 0) == -1)
787 display_last_error("Error sending datas");
789 if (sendto(unistimsock, data, size, 0, (struct sockaddr *) addr_to, sizeof(*addr_to))
791 display_last_error("Error sending datas");
795 static void send_client(int size, const unsigned char *data, struct unistimsession *pte)
799 unsigned short *sdata = (unsigned short *) data;
801 ast_mutex_lock(&pte->lock);
802 buf_pos = pte->last_buf_available;
804 if (buf_pos >= MAX_BUF_NUMBER) {
805 ast_log(LOG_WARNING, "Error : send queue overflow\n");
806 ast_mutex_unlock(&pte->lock);
809 sdata[1] = ntohs(++(pte->seq_server));
810 pte->wsabufsend[buf_pos].len = size;
811 memcpy(pte->wsabufsend[buf_pos].buf, data, size);
813 tick = get_tick_count();
814 pte->timeout = tick + RETRANSMIT_TIMER;
816 /*#ifdef DUMP_PACKET */
817 if ((unistimdebug) && (option_verbose > 5)) {
818 ast_verbose("Sending datas with seq #0x%.4x Using slot #%d :\n", pte->seq_server,
822 send_raw_client(pte->wsabufsend[buf_pos].len, pte->wsabufsend[buf_pos].buf, &(pte->sin),
824 pte->last_buf_available++;
825 ast_mutex_unlock(&pte->lock);
828 static void send_ping(struct unistimsession *pte)
831 if ((unistimdebug) && (option_verbose > 5))
832 ast_verbose("Sending ping\n");
833 pte->tick_next_ping = get_tick_count() + unistim_keepalive;
834 memcpy(buffsend + SIZE_HEADER, packet_send_ping, sizeof(packet_send_ping));
835 send_client(SIZE_HEADER + sizeof(packet_send_ping), buffsend, pte);
838 static int get_to_address(int fd, struct sockaddr_in *toAddr)
846 struct in_addr address;
849 /* Zero out the structures before we use them */
850 /* This sets several key values to NULL */
851 memset(&msg, 0, sizeof(msg));
852 memset(&ip_msg, 0, sizeof(ip_msg));
854 /* Initialize the message structure */
855 msg.msg_control = &ip_msg;
856 msg.msg_controllen = sizeof(ip_msg);
857 /* Get info about the incoming packet */
858 err = recvmsg(fd, &msg, MSG_PEEK);
860 ast_log(LOG_WARNING, "recvmsg returned an error: %s\n", strerror(errno));
861 memcpy(&toAddr->sin_addr, &ip_msg.address, sizeof(struct in_addr));
864 memcpy(&toAddr, &public_ip, sizeof(&toAddr));
869 /* Allocate memory & initialize structures for a new phone */
870 /* addr_from : ip address of the phone */
871 static struct unistimsession *create_client(const struct sockaddr_in *addr_from)
874 struct unistimsession *s;
876 if (!(s = ast_calloc(1, sizeof(*s))))
879 memcpy(&s->sin, addr_from, sizeof(struct sockaddr_in));
880 get_to_address(unistimsock, &s->sout);
883 ("Creating a new entry for the phone from %s received via server ip %s\n",
884 ast_inet_ntoa(addr_from->sin_addr), ast_inet_ntoa(s->sout.sin_addr));
886 ast_mutex_init(&s->lock);
887 ast_mutex_lock(&sessionlock);
891 s->timeout = get_tick_count() + RETRANSMIT_TIMER;
892 s->seq_phone = (short) 0x0000;
893 s->seq_server = (short) 0x0000;
894 s->last_seq_ack = (short) 0x000;
895 s->last_buf_available = 0;
896 s->nb_retransmit = 0;
897 s->state = STATE_INIT;
898 s->tick_next_ping = get_tick_count() + unistim_keepalive;
899 /* Initialize struct wsabuf */
900 for (tmp = 0; tmp < MAX_BUF_NUMBER; tmp++) {
901 s->wsabufsend[tmp].buf = s->buf[tmp];
903 ast_mutex_unlock(&sessionlock);
907 static void send_end_call(struct unistimsession *pte)
911 ast_verbose("Sending end call\n");
912 memcpy(buffsend + SIZE_HEADER, packet_send_end_call, sizeof(packet_send_end_call));
913 send_client(SIZE_HEADER + sizeof(packet_send_end_call), buffsend, pte);
916 static void set_ping_timer(struct unistimsession *pte)
918 unsigned int tick = 0; /* XXX what is this for, anyways */
920 pte->timeout = pte->tick_next_ping;
921 DEBUG_TIMER("tick = %u next ping at %u tick\n", tick, pte->timeout);
925 /* Checking if our send queue is empty,
926 * if true, setting up a timer for keepalive */
927 static void check_send_queue(struct unistimsession *pte)
929 /* Check if our send queue contained only one element */
930 if (pte->last_buf_available == 1) {
931 if ((unistimdebug) && (option_verbose > 5))
932 ast_verbose("Our single packet was ACKed.\n");
933 pte->last_buf_available--;
937 /* Check if this ACK catch up our latest packet */
938 else if (pte->last_seq_ack + 1 == pte->seq_server + 1) {
939 if ((unistimdebug) && (option_verbose > 5))
940 ast_verbose("Our send queue is completely ACKed.\n");
941 pte->last_buf_available = 0; /* Purge the send queue */
945 if ((unistimdebug) && (option_verbose > 5))
946 ast_verbose("We still have packets in our send queue\n");
950 static void send_start_timer(struct unistimsession *pte)
954 ast_verbose("Sending start timer\n");
955 memcpy(buffsend + SIZE_HEADER, packet_send_StartTimer, sizeof(packet_send_StartTimer));
956 send_client(SIZE_HEADER + sizeof(packet_send_StartTimer), buffsend, pte);
959 static void send_stop_timer(struct unistimsession *pte)
963 ast_verbose("Sending stop timer\n");
964 memcpy(buffsend + SIZE_HEADER, packet_send_stop_timer, sizeof(packet_send_stop_timer));
965 send_client(SIZE_HEADER + sizeof(packet_send_stop_timer), buffsend, pte);
968 static void Sendicon(unsigned char pos, unsigned char status, struct unistimsession *pte)
972 ast_verbose("Sending icon pos %d with status 0x%.2x\n", pos, status);
973 memcpy(buffsend + SIZE_HEADER, packet_send_icon, sizeof(packet_send_icon));
975 buffsend[10] = status;
976 send_client(SIZE_HEADER + sizeof(packet_send_icon), buffsend, pte);
979 static void send_tone(struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
984 ast_verbose("Sending Stream Based Tone Off\n");
985 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_off,
986 sizeof(packet_send_stream_based_tone_off));
987 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_off), buffsend, pte);
990 /* Since most of the world use a continuous tone, it's useless
992 ast_verbose ("Sending Stream Based Tone Cadence Download\n");
993 memcpy (buffsend + SIZE_HEADER, packet_send_StreamBasedToneCad, sizeof (packet_send_StreamBasedToneCad));
994 send_client (SIZE_HEADER + sizeof (packet_send_StreamBasedToneCad), buffsend, pte); */
996 ast_verbose("Sending Stream Based Tone Frequency Component List Download %d %d\n",
1000 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_single_freq,
1001 sizeof(packet_send_stream_based_tone_single_freq));
1002 buffsend[10] = (tone1 & 0xff00) >> 8;
1003 buffsend[11] = (tone1 & 0x00ff);
1004 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_single_freq), buffsend,
1008 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dial_freq,
1009 sizeof(packet_send_stream_based_tone_dial_freq));
1010 buffsend[10] = (tone1 & 0xff00) >> 8;
1011 buffsend[11] = (tone1 & 0x00ff);
1012 buffsend[12] = (tone2 & 0xff00) >> 8;
1013 buffsend[13] = (tone2 & 0x00ff);
1014 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_dial_freq), buffsend,
1019 ast_verbose("Sending Stream Based Tone On\n");
1020 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_on,
1021 sizeof(packet_send_stream_based_tone_on));
1022 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_on), buffsend, pte);
1025 /* Positions for favorites
1026 |--------------------|
1032 /* status (icons) : 00 = nothing, 2x/3x = see parser.h, 4x/5x = blink fast, 6x/7x = blink slow */
1034 send_favorite(unsigned char pos, unsigned char status, struct unistimsession *pte,
1041 ast_verbose("Sending favorite pos %d with status 0x%.2x\n", pos, status);
1042 memcpy(buffsend + SIZE_HEADER, packet_send_favorite, sizeof(packet_send_favorite));
1045 buffsend[25] = status;
1047 if (i > FAV_MAX_LENGTH)
1049 memcpy(buffsend + FAV_MAX_LENGTH + 1, text, i);
1050 send_client(SIZE_HEADER + sizeof(packet_send_favorite), buffsend, pte);
1053 static void refresh_all_favorite(struct unistimsession *pte)
1058 ast_verbose("Refreshing all favorite\n");
1059 for (i = 0; i < 6; i++) {
1060 if ((pte->device->softkeyicon[i] <= FAV_ICON_HEADPHONES_ONHOLD) &&
1061 (pte->device->softkeylinepos != i))
1062 send_favorite((unsigned char) i, pte->device->softkeyicon[i] + 1, pte,
1063 pte->device->softkeylabel[i]);
1065 send_favorite((unsigned char) i, pte->device->softkeyicon[i], pte,
1066 pte->device->softkeylabel[i]);
1071 /* Change the status for this phone (pte) and update for each phones where pte is bookmarked
1072 * use FAV_ICON_*_BLACK constant in status parameters */
1073 static void change_favorite_icon(struct unistimsession *pte, unsigned char status)
1075 struct unistim_device *d = devices;
1077 /* Update the current phone */
1078 if (pte->state != STATE_CLEANING)
1079 send_favorite(pte->device->softkeylinepos, status, pte,
1080 pte->device->softkeylabel[pte->device->softkeylinepos]);
1081 /* Notify other phones if we're in their bookmark */
1083 for (i = 0; i < 6; i++) {
1084 if (d->sp[i] == pte->device) { /* It's us ? */
1085 if (d->softkeyicon[i] != status) { /* Avoid resending the same icon */
1086 d->softkeyicon[i] = status;
1088 send_favorite(i, status + 1, d->session, d->softkeylabel[i]);
1096 static int RegisterExtension(const struct unistimsession *pte)
1099 ast_verbose("Trying to register extension '%s' into context '%s' to %s\n",
1100 pte->device->extension_number, pte->device->lines->context,
1101 pte->device->lines->fullname);
1102 return ast_add_extension(pte->device->lines->context, 0,
1103 pte->device->extension_number, 1, NULL, NULL, "Dial",
1104 pte->device->lines->fullname, 0, "Unistim");
1107 static int UnregisterExtension(const struct unistimsession *pte)
1110 ast_verbose("Trying to unregister extension '%s' context '%s'\n",
1111 pte->device->extension_number, pte->device->lines->context);
1112 return ast_context_remove_extension(pte->device->lines->context,
1113 pte->device->extension_number, 1, "Unistim");
1116 /* Free memory allocated for a phone */
1117 static void close_client(struct unistimsession *s)
1119 struct unistim_subchannel *sub;
1120 struct unistimsession *cur, *prev = NULL;
1121 ast_mutex_lock(&sessionlock);
1123 /* Looking for the session in the linked chain */
1130 if (cur) { /* Session found ? */
1131 if (cur->device) { /* This session was registred ? */
1132 s->state = STATE_CLEANING;
1134 ast_verbose("close_client session %p device %p lines %p sub %p\n",
1135 s, s->device, s->device->lines,
1136 s->device->lines->subs[SUB_REAL]);
1137 change_favorite_icon(s, FAV_ICON_NONE);
1138 sub = s->device->lines->subs[SUB_REAL];
1140 if (sub->owner) { /* Call in progress ? */
1142 ast_verbose("Aborting call\n");
1143 ast_queue_hangup(sub->owner);
1146 ast_log(LOG_WARNING, "Freeing a client with no subchannel !\n");
1147 if (!ast_strlen_zero(s->device->extension_number))
1148 UnregisterExtension(s);
1149 cur->device->session = NULL;
1152 ast_verbose("Freeing an unregistered client\n");
1155 prev->next = cur->next;
1157 sessions = cur->next;
1158 ast_mutex_destroy(&s->lock);
1161 ast_log(LOG_WARNING, "Trying to delete non-existant session %p?\n", s);
1162 ast_mutex_unlock(&sessionlock);
1166 /* Return 1 if the session chained link was modified */
1167 static int send_retransmit(struct unistimsession *pte)
1171 ast_mutex_lock(&pte->lock);
1172 if (++pte->nb_retransmit >= NB_MAX_RETRANSMIT) {
1174 ast_verbose("Too many retransmit - freeing client\n");
1175 ast_mutex_unlock(&pte->lock);
1179 pte->timeout = get_tick_count() + RETRANSMIT_TIMER;
1181 for (i = pte->last_buf_available - (pte->seq_server - pte->last_seq_ack);
1182 i < pte->last_buf_available; i++) {
1184 ast_log(LOG_WARNING,
1185 "Asked to retransmit an ACKed slot ! last_buf_available=%d, seq_server = #0x%.4x last_seq_ack = #0x%.4x\n",
1186 pte->last_buf_available, pte->seq_server, pte->last_seq_ack);
1191 unsigned short *sbuf = (unsigned short *) pte->wsabufsend[i].buf;
1194 seq = ntohs(sbuf[1]);
1195 ast_verbose("Retransmit slot #%d (seq=#0x%.4x), last ack was #0x%.4x\n", i,
1196 seq, pte->last_seq_ack);
1198 send_raw_client(pte->wsabufsend[i].len, pte->wsabufsend[i].buf, &pte->sin,
1201 ast_mutex_unlock(&pte->lock);
1205 /* inverse : TEXT_INVERSE : yes, TEXT_NORMAL : no */
1207 send_text(unsigned char pos, unsigned char inverse, struct unistimsession *pte,
1213 ast_verbose("Sending text at pos %d, inverse flag %d\n", pos, inverse);
1214 memcpy(buffsend + SIZE_HEADER, packet_send_text, sizeof(packet_send_text));
1216 buffsend[11] = inverse;
1218 if (i > TEXT_LENGTH_MAX)
1219 i = TEXT_LENGTH_MAX;
1220 memcpy(buffsend + 12, text, i);
1221 send_client(SIZE_HEADER + sizeof(packet_send_text), buffsend, pte);
1224 static void send_text_status(struct unistimsession *pte, const char *text)
1229 ast_verbose("Sending status text\n");
1231 if (pte->device->status_method == 1) { /* For new firmware and i2050 soft phone */
1232 int n = strlen(text);
1233 /* Must send individual button separately */
1235 for (i = 0, j = 0; i < 4; i++, j += 7) {
1236 int pos = 0x08 + (i * 0x20);
1237 memcpy(buffsend + SIZE_HEADER, packet_send_status2,
1238 sizeof(packet_send_status2));
1241 memcpy(buffsend + 10, (j < n) ? (text + j) : " ", 7);
1242 send_client(SIZE_HEADER + sizeof(packet_send_status2), buffsend, pte);
1249 memcpy(buffsend + SIZE_HEADER, packet_send_status, sizeof(packet_send_status));
1251 if (i > STATUS_LENGTH_MAX)
1252 i = STATUS_LENGTH_MAX;
1253 memcpy(buffsend + 10, text, i);
1254 send_client(SIZE_HEADER + sizeof(packet_send_status), buffsend, pte);
1258 /* led values in hexa : 0 = bar off, 1 = bar on, 2 = bar 1s on/1s off, 3 = bar 2.5s on/0.5s off
1259 * 4 = bar 0.6s on/0.3s off, 5 = bar 0.5s on/0.5s off, 6 = bar 2s on/0.5s off
1260 * 7 = bar off, 8 = speaker off, 9 = speaker on, 10 = headphone off, 11 = headphone on
1261 * 18 = mute off, 19 mute on */
1262 static void send_led_update(struct unistimsession *pte, unsigned char led)
1266 ast_verbose("Sending led_update (%x)\n", led);
1267 memcpy(buffsend + SIZE_HEADER, packet_send_led_update, sizeof(packet_send_led_update));
1269 send_client(SIZE_HEADER + sizeof(packet_send_led_update), buffsend, pte);
1272 /* output = OUTPUT_HANDSET, OUTPUT_HEADPHONE or OUTPUT_SPEAKER
1273 * volume = VOLUME_LOW, VOLUME_NORMAL, VOLUME_INSANELY_LOUD
1274 * mute = MUTE_OFF, MUTE_ON */
1276 send_select_output(struct unistimsession *pte, unsigned char output, unsigned char volume,
1281 ast_verbose("Sending select output packet output=%x volume=%x mute=%x\n", output,
1283 memcpy(buffsend + SIZE_HEADER, packet_send_select_output,
1284 sizeof(packet_send_select_output));
1285 buffsend[9] = output;
1286 if (output == OUTPUT_SPEAKER)
1287 volume = VOLUME_LOW_SPEAKER;
1289 volume = VOLUME_LOW;
1290 buffsend[10] = volume;
1291 if (mute == MUTE_ON_DISCRET)
1292 buffsend[11] = MUTE_ON;
1294 buffsend[11] = mute;
1295 send_client(SIZE_HEADER + sizeof(packet_send_select_output), buffsend, pte);
1296 if (mute == MUTE_OFF)
1297 send_led_update(pte, 0x18);
1298 else if (mute == MUTE_ON)
1299 send_led_update(pte, 0x19);
1300 pte->device->mute = mute;
1301 if (output == OUTPUT_HANDSET) {
1302 if (mute == MUTE_ON)
1303 change_favorite_icon(pte, FAV_ICON_ONHOLD_BLACK);
1305 change_favorite_icon(pte, FAV_ICON_OFFHOOK_BLACK);
1306 send_led_update(pte, 0x08);
1307 send_led_update(pte, 0x10);
1308 } else if (output == OUTPUT_HEADPHONE) {
1309 if (mute == MUTE_ON)
1310 change_favorite_icon(pte, FAV_ICON_HEADPHONES_ONHOLD);
1312 change_favorite_icon(pte, FAV_ICON_HEADPHONES);
1313 send_led_update(pte, 0x08);
1314 send_led_update(pte, 0x11);
1315 } else if (output == OUTPUT_SPEAKER) {
1316 send_led_update(pte, 0x10);
1317 send_led_update(pte, 0x09);
1318 if (pte->device->receiver_state == STATE_OFFHOOK) {
1319 if (mute == MUTE_ON)
1320 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1322 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOOK_BLACK);
1324 if (mute == MUTE_ON)
1325 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1327 change_favorite_icon(pte, FAV_ICON_SPEAKER_OFFHOOK_BLACK);
1330 ast_log(LOG_WARNING, "Invalid ouput (%d)\n", output);
1331 if (output != pte->device->output)
1332 pte->device->previous_output = pte->device->output;
1333 pte->device->output = output;
1336 static void send_ring(struct unistimsession *pte, char volume, char style)
1340 ast_verbose("Sending ring packet\n");
1341 memcpy(buffsend + SIZE_HEADER, packet_send_ring, sizeof(packet_send_ring));
1342 buffsend[24] = style + 0x10;
1343 buffsend[29] = volume * 0x10;
1344 send_client(SIZE_HEADER + sizeof(packet_send_ring), buffsend, pte);
1347 static void send_no_ring(struct unistimsession *pte)
1351 ast_verbose("Sending no ring packet\n");
1352 memcpy(buffsend + SIZE_HEADER, packet_send_no_ring, sizeof(packet_send_no_ring));
1353 send_client(SIZE_HEADER + sizeof(packet_send_no_ring), buffsend, pte);
1356 static void send_texttitle(struct unistimsession *pte, const char *text)
1361 ast_verbose("Sending title text\n");
1362 memcpy(buffsend + SIZE_HEADER, packet_send_title, sizeof(packet_send_title));
1366 memcpy(buffsend + 10, text, i);
1367 send_client(SIZE_HEADER + sizeof(packet_send_title), buffsend, pte);
1371 static void send_date_time(struct unistimsession *pte)
1374 struct timeval tv = ast_tvnow();
1375 struct ast_tm atm = { 0, };
1378 ast_verbose("Sending Time & Date\n");
1379 memcpy(buffsend + SIZE_HEADER, packet_send_date_time, sizeof(packet_send_date_time));
1380 ast_localtime(&tv, &atm, NULL);
1381 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1382 buffsend[11] = (unsigned char) atm.tm_mday;
1383 buffsend[12] = (unsigned char) atm.tm_hour;
1384 buffsend[13] = (unsigned char) atm.tm_min;
1385 send_client(SIZE_HEADER + sizeof(packet_send_date_time), buffsend, pte);
1388 static void send_date_time2(struct unistimsession *pte)
1391 struct timeval tv = ast_tvnow();
1392 struct ast_tm atm = { 0, };
1395 ast_verbose("Sending Time & Date #2\n");
1396 memcpy(buffsend + SIZE_HEADER, packet_send_date_time2, sizeof(packet_send_date_time2));
1397 ast_localtime(&tv, &atm, NULL);
1399 buffsend[9] = pte->device->datetimeformat;
1402 buffsend[14] = (unsigned char) atm.tm_mon + 1;
1403 buffsend[15] = (unsigned char) atm.tm_mday;
1404 buffsend[16] = (unsigned char) atm.tm_hour;
1405 buffsend[17] = (unsigned char) atm.tm_min;
1406 send_client(SIZE_HEADER + sizeof(packet_send_date_time2), buffsend, pte);
1409 static void send_date_time3(struct unistimsession *pte)
1412 struct timeval tv = ast_tvnow();
1413 struct ast_tm atm = { 0, };
1416 ast_verbose("Sending Time & Date #3\n");
1417 memcpy(buffsend + SIZE_HEADER, packet_send_date_time3, sizeof(packet_send_date_time3));
1418 ast_localtime(&tv, &atm, NULL);
1419 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1420 buffsend[11] = (unsigned char) atm.tm_mday;
1421 buffsend[12] = (unsigned char) atm.tm_hour;
1422 buffsend[13] = (unsigned char) atm.tm_min;
1423 send_client(SIZE_HEADER + sizeof(packet_send_date_time3), buffsend, pte);
1426 static void send_blink_cursor(struct unistimsession *pte)
1430 ast_verbose("Sending set blink\n");
1431 memcpy(buffsend + SIZE_HEADER, packet_send_blink_cursor, sizeof(packet_send_blink_cursor));
1432 send_client(SIZE_HEADER + sizeof(packet_send_blink_cursor), buffsend, pte);
1436 /* pos : 0xab (a=0/2/4 = line ; b = row) */
1437 static void send_cursor_pos(struct unistimsession *pte, unsigned char pos)
1441 ast_verbose("Sending set cursor position\n");
1442 memcpy(buffsend + SIZE_HEADER, packet_send_set_pos_cursor,
1443 sizeof(packet_send_set_pos_cursor));
1445 send_client(SIZE_HEADER + sizeof(packet_send_set_pos_cursor), buffsend, pte);
1449 static void rcv_resume_connection_with_server(struct unistimsession *pte)
1453 ast_verbose("ResumeConnectionWithServer received\n");
1455 ast_verbose("Sending packet_send_query_mac_address\n");
1456 memcpy(buffsend + SIZE_HEADER, packet_send_query_mac_address,
1457 sizeof(packet_send_query_mac_address));
1458 send_client(SIZE_HEADER + sizeof(packet_send_query_mac_address), buffsend, pte);
1462 static int unistim_register(struct unistimsession *s)
1464 struct unistim_device *d;
1466 ast_mutex_lock(&devicelock);
1469 if (!strcasecmp(s->macaddr, d->id)) {
1470 /* XXX Deal with IP authentication */
1473 d->codec_number = DEFAULT_CODEC;
1476 d->receiver_state = STATE_ONHOOK;
1481 ast_mutex_unlock(&devicelock);
1489 static int alloc_sub(struct unistim_line *l, int x)
1491 struct unistim_subchannel *sub;
1492 if (!(sub = ast_calloc(1, sizeof(*sub))))
1496 ast_verbose(VERBOSE_PREFIX_3
1497 "Allocating UNISTIM subchannel #%d on %s@%s ptr=%p\n", x, l->name,
1498 l->parent->name, sub);
1502 ast_mutex_init(&sub->lock);
1506 static int unalloc_sub(struct unistim_line *p, int x)
1509 ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name,
1514 ast_debug(1, "Released sub %d of channel %s@%s\n", x, p->name,
1516 ast_mutex_destroy(&p->lock);
1517 ast_free(p->subs[x]);
1522 static void rcv_mac_addr(struct unistimsession *pte, const unsigned char *buf)
1529 ast_verbose("Mac Address received : ");
1530 for (tmp = 15; tmp < 15 + SIZE_HEADER; tmp++) {
1531 sprintf(&addrmac[i], "%.2x", (unsigned char) buf[tmp]);
1535 ast_verbose("%s\n", addrmac);
1536 strcpy(pte->macaddr, addrmac);
1537 res = unistim_register(pte);
1539 switch (autoprovisioning) {
1540 case AUTOPROVISIONING_NO:
1541 ast_log(LOG_WARNING, "No entry found for this phone : %s\n", addrmac);
1542 pte->state = STATE_AUTHDENY;
1544 case AUTOPROVISIONING_YES:
1546 struct unistim_device *d, *newd;
1547 struct unistim_line *newl;
1549 ast_verbose("New phone, autoprovisioning on\n");
1550 /* First : locate the [template] section */
1551 ast_mutex_lock(&devicelock);
1554 if (!strcasecmp(d->name, "template")) {
1555 /* Found, cloning this entry */
1556 if (!(newd = ast_malloc(sizeof(*newd)))) {
1557 ast_mutex_unlock(&devicelock);
1561 memcpy(newd, d, sizeof(*newd));
1562 if (!(newl = ast_malloc(sizeof(*newl)))) {
1564 ast_mutex_unlock(&devicelock);
1568 memcpy(newl, d->lines, sizeof(*newl));
1569 if (!alloc_sub(newl, SUB_REAL)) {
1572 ast_mutex_unlock(&devicelock);
1575 /* Ok, now updating some fields */
1576 ast_copy_string(newd->id, addrmac, sizeof(newd->id));
1577 ast_copy_string(newd->name, addrmac, sizeof(newd->name));
1578 if (newd->extension == EXTENSION_NONE)
1579 newd->extension = EXTENSION_ASK;
1581 newd->receiver_state = STATE_ONHOOK;
1582 newd->session = pte;
1583 newd->to_delete = -1;
1586 newl->parent = newd;
1587 strcpy(newl->name, d->lines->name);
1588 snprintf(d->lines->name, sizeof(d->lines->name), "%d",
1589 atoi(d->lines->name) + 1);
1590 snprintf(newl->fullname, sizeof(newl->fullname), "USTM/%s@%s",
1591 newl->name, newd->name);
1592 /* Go to the end of the linked chain */
1602 ast_mutex_unlock(&devicelock);
1604 ast_log(LOG_WARNING, "No entry [template] found in unistim.conf\n");
1605 pte->state = STATE_AUTHDENY;
1609 case AUTOPROVISIONING_TN:
1610 pte->state = STATE_AUTHDENY;
1612 case AUTOPROVISIONING_DB:
1613 ast_log(LOG_WARNING,
1614 "Autoprovisioning with database is not yet functional\n");
1617 ast_log(LOG_WARNING, "Internal error : unknown autoprovisioning value = %d\n",
1621 if (pte->state != STATE_AUTHDENY) {
1622 if (option_verbose > 2)
1623 ast_verbose(VERBOSE_PREFIX_3 "Device '%s' successfuly registered\n",
1625 switch (pte->device->extension) {
1626 case EXTENSION_NONE:
1627 pte->state = STATE_MAINPAGE;
1630 /* Checking if we already have an extension number */
1631 if (ast_strlen_zero(pte->device->extension_number))
1632 pte->state = STATE_EXTENSION;
1634 /* Yes, because of a phone reboot. We don't ask again for the TN */
1635 if (RegisterExtension(pte))
1636 pte->state = STATE_EXTENSION;
1638 pte->state = STATE_MAINPAGE;
1641 case EXTENSION_LINE:
1642 ast_copy_string(pte->device->extension_number, pte->device->lines->name,
1643 sizeof(pte->device->extension_number));
1644 if (RegisterExtension(pte))
1645 pte->state = STATE_EXTENSION;
1647 pte->state = STATE_MAINPAGE;
1650 /* If we are here, it's because of a phone reboot */
1651 pte->state = STATE_MAINPAGE;
1654 ast_log(LOG_WARNING, "Internal error, extension value unknown : %d\n",
1655 pte->device->extension);
1656 pte->state = STATE_AUTHDENY;
1660 if (pte->state == STATE_EXTENSION) {
1661 if (pte->device->extension != EXTENSION_TN)
1662 pte->device->extension = EXTENSION_ASK;
1663 pte->device->extension_number[0] = '\0';
1666 ast_verbose("\nSending S1\n");
1667 memcpy(buffsend + SIZE_HEADER, packet_send_S1, sizeof(packet_send_S1));
1668 send_client(SIZE_HEADER + sizeof(packet_send_S1), buffsend, pte);
1671 ast_verbose("Sending query_basic_manager_04\n");
1672 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_04,
1673 sizeof(packet_send_query_basic_manager_04));
1674 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_04), buffsend, pte);
1677 ast_verbose("Sending query_basic_manager_10\n");
1678 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_10,
1679 sizeof(packet_send_query_basic_manager_10));
1680 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_10), buffsend, pte);
1682 send_date_time(pte);
1686 static int write_entry_history(struct unistimsession *pte, FILE * f, char c, char *line1)
1688 if (fwrite(&c, 1, 1, f) != 1) {
1689 display_last_error("Unable to write history log header.");
1692 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
1693 display_last_error("Unable to write history entry - date.");
1696 if (fwrite(pte->device->lst_cid, TEXT_LENGTH_MAX, 1, f) != 1) {
1697 display_last_error("Unable to write history entry - callerid.");
1700 if (fwrite(pte->device->lst_cnm, TEXT_LENGTH_MAX, 1, f) != 1) {
1701 display_last_error("Unable to write history entry - callername.");
1707 static int write_history(struct unistimsession *pte, char way, char ismissed)
1709 char tmp[AST_CONFIG_MAX_PATH], tmp2[AST_CONFIG_MAX_PATH];
1710 char line1[TEXT_LENGTH_MAX + 1];
1711 char count = 0, *histbuf;
1714 struct timeval tv = ast_tvnow();
1715 struct ast_tm atm = { 0, };
1719 if (!pte->device->callhistory)
1721 if (strchr(pte->device->name, '/') || (pte->device->name[0] == '.')) {
1722 ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n",
1727 snprintf(tmp, sizeof(tmp), "%s/%s", (char *) ast_config_AST_LOG_DIR, USTM_LOG_DIR);
1728 if (ast_mkdir(tmp, 0770)) {
1729 if (errno != EEXIST) {
1730 display_last_error("Unable to create directory for history");
1735 ast_localtime(&tv, &atm, NULL);
1738 strcpy(tmp2, "Miss");
1740 strcpy(tmp2, "Fail");
1742 strcpy(tmp2, "Answ");
1743 snprintf(line1, sizeof(line1), "%04d/%02d/%02d %02d:%02d:%02d %s",
1744 atm.tm_year + 1900, atm.tm_mon + 1, atm.tm_mday, atm.tm_hour,
1745 atm.tm_min, atm.tm_sec, tmp2);
1747 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", (char *) ast_config_AST_LOG_DIR,
1748 USTM_LOG_DIR, pte->device->name, way);
1749 if ((f = fopen(tmp, "r"))) {
1750 struct stat bufstat;
1752 if (stat(tmp, &bufstat)) {
1753 display_last_error("Unable to stat history log.");
1757 size = 1 + (MAX_ENTRY_LOG * TEXT_LENGTH_MAX * 3);
1758 if (bufstat.st_size != size) {
1759 ast_log(LOG_WARNING,
1760 "History file %s has an incorrect size (%d instead of %d). It will be replaced by a new one.",
1761 tmp, (int) bufstat.st_size, size);
1768 /* If we can't open the log file, we create a brand new one */
1773 if ((errno != ENOENT) && (count == 0)) {
1774 display_last_error("Unable to open history log.");
1777 f = fopen(tmp, "w");
1779 display_last_error("Unable to create history log.");
1782 if (write_entry_history(pte, f, c, line1)) {
1786 memset(line1, ' ', TEXT_LENGTH_MAX);
1787 for (i = 3; i < MAX_ENTRY_LOG * 3; i++) {
1788 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
1789 display_last_error("Unable to write history entry - stuffing.");
1795 display_last_error("Unable to close history - creation.");
1798 /* We can open the log file, we create a temporary one, we add our entry and copy the rest */
1799 if (fread(&count, 1, 1, f) != 1) {
1800 display_last_error("Unable to read history header.");
1804 if (count > MAX_ENTRY_LOG) {
1805 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
1806 count, MAX_ENTRY_LOG);
1810 snprintf(tmp2, sizeof(tmp2), "%s/%s/%s-%c.csv.tmp", (char *) ast_config_AST_LOG_DIR,
1811 USTM_LOG_DIR, pte->device->name, way);
1812 if (!(f2 = fopen(tmp2, "w"))) {
1813 display_last_error("Unable to create temporary history log.");
1818 if (++count > MAX_ENTRY_LOG)
1819 count = MAX_ENTRY_LOG;
1821 if (write_entry_history(pte, f2, count, line1)) {
1827 size = (MAX_ENTRY_LOG - 1) * TEXT_LENGTH_MAX * 3;
1828 if (!(histbuf = ast_malloc(size))) {
1834 if (fread(histbuf, size, 1, f) != 1) {
1838 display_last_error("Unable to read previous history entries.");
1841 if (fwrite(histbuf, size, 1, f2) != 1) {
1845 display_last_error("Unable to write previous history entries.");
1850 display_last_error("Unable to close history log.");
1852 display_last_error("Unable to close temporary history log.");
1854 display_last_error("Unable to remove old history log.");
1855 if (rename(tmp2, tmp))
1856 display_last_error("Unable to rename new history log.");
1860 static void cancel_dial(struct unistimsession *pte)
1863 pte->device->missed_call++;
1864 write_history(pte, 'i', 1);
1865 show_main_page(pte);
1869 static void swap_subs(struct unistim_line *p, int a, int b)
1871 /* struct ast_channel *towner; */
1872 struct ast_rtp *rtp;
1876 ast_verbose("Swapping %d and %d\n", a, b);
1878 if ((!p->subs[a]->owner) || (!p->subs[b]->owner)) {
1879 ast_log(LOG_WARNING,
1880 "Attempted to swap subchannels with a null owner : sub #%d=%p sub #%d=%p\n",
1881 a, p->subs[a]->owner, b, p->subs[b]->owner);
1884 rtp = p->subs[a]->rtp;
1885 p->subs[a]->rtp = p->subs[b]->rtp;
1886 p->subs[b]->rtp = rtp;
1888 fds = p->subs[a]->owner->fds[0];
1889 p->subs[a]->owner->fds[0] = p->subs[b]->owner->fds[0];
1890 p->subs[b]->owner->fds[0] = fds;
1892 fds = p->subs[a]->owner->fds[1];
1893 p->subs[a]->owner->fds[1] = p->subs[b]->owner->fds[1];
1894 p->subs[b]->owner->fds[1] = fds;
1897 static int attempt_transfer(struct unistim_subchannel *p1, struct unistim_subchannel *p2)
1901 *chana = NULL, *chanb = NULL, *bridgea = NULL, *bridgeb = NULL, *peera =
1902 NULL, *peerb = NULL, *peerc = NULL, *peerd = NULL;
1904 if (!p1->owner || !p2->owner) {
1905 ast_log(LOG_WARNING, "Transfer attempted without dual ownership?\n");
1910 bridgea = ast_bridged_channel(chana);
1911 bridgeb = ast_bridged_channel(chanb);
1918 } else if (bridgeb) {
1925 if (peera && peerb && peerc && (peerb != peerc)) {
1926 /*ast_quiet_chan(peera);
1927 ast_quiet_chan(peerb);
1928 ast_quiet_chan(peerc);
1929 ast_quiet_chan(peerd); */
1931 if (peera->cdr && peerb->cdr) {
1932 peerb->cdr = ast_cdr_append(peerb->cdr, peera->cdr);
1933 } else if (peera->cdr) {
1934 peerb->cdr = peera->cdr;
1938 if (peerb->cdr && peerc->cdr) {
1939 peerb->cdr = ast_cdr_append(peerb->cdr, peerc->cdr);
1940 } else if (peerc->cdr) {
1941 peerb->cdr = peerc->cdr;
1945 if (ast_channel_masquerade(peerb, peerc)) {
1946 ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name,
1953 "Transfer attempted with no appropriate bridged calls to transfer\n");
1955 ast_softhangup_nolock(chana, AST_SOFTHANGUP_DEV);
1957 ast_softhangup_nolock(chanb, AST_SOFTHANGUP_DEV);
1963 void change_callerid(struct unistimsession *pte, int type, char *callerid)
1969 data = pte->device->lst_cnm;
1971 data = pte->device->lst_cid;
1973 /* This is very nearly strncpy(), except that the remaining buffer
1974 * is padded with ' ', instead of '\0' */
1975 memset(data, ' ', TEXT_LENGTH_MAX);
1976 size = strlen(callerid);
1977 if (size > TEXT_LENGTH_MAX)
1978 size = TEXT_LENGTH_MAX;
1979 memcpy(data, callerid, size);
1982 static void close_call(struct unistimsession *pte)
1984 struct unistim_subchannel *sub;
1985 struct unistim_line *l = pte->device->lines;
1987 sub = pte->device->lines->subs[SUB_REAL];
1988 send_stop_timer(pte);
1990 sub->alreadygone = 1;
1991 if (l->subs[SUB_THREEWAY]) {
1992 l->subs[SUB_THREEWAY]->alreadygone = 1;
1993 if (attempt_transfer(sub, l->subs[SUB_THREEWAY]) < 0)
1994 ast_verbose("attempt_transfer failed.\n");
1996 ast_queue_hangup(sub->owner);
1998 if (l->subs[SUB_THREEWAY]) {
1999 if (l->subs[SUB_THREEWAY]->owner)
2000 ast_queue_hangup(l->subs[SUB_THREEWAY]->owner);
2002 ast_log(LOG_WARNING, "threeway sub without owner\n");
2004 ast_verbose("USTM(%s@%s-%d) channel already destroyed\n", sub->parent->name,
2005 sub->parent->parent->name, sub->subtype);
2007 change_callerid(pte, 0, pte->device->redial_number);
2008 change_callerid(pte, 1, "");
2009 write_history(pte, 'o', pte->device->missed_call);
2010 pte->device->missed_call = 0;
2011 show_main_page(pte);
2015 static void IgnoreCall(struct unistimsession *pte)
2021 static void *unistim_ss(void *data)
2023 struct ast_channel *chan = data;
2024 struct unistim_subchannel *sub = chan->tech_pvt;
2025 struct unistim_line *l = sub->parent;
2026 struct unistimsession *s = l->parent->session;
2029 if (option_verbose > 2)
2030 ast_verbose(VERBOSE_PREFIX_3 "Starting switch on '%s@%s-%d' to %s\n",
2031 l->name, l->parent->name, sub->subtype, s->device->phone_number);
2032 ast_copy_string(chan->exten, s->device->phone_number, sizeof(chan->exten));
2033 ast_copy_string(s->device->redial_number, s->device->phone_number,
2034 sizeof(s->device->redial_number));
2035 ast_setstate(chan, AST_STATE_RING);
2036 res = ast_pbx_run(chan);
2038 ast_log(LOG_WARNING, "PBX exited non-zero\n");
2039 send_tone(s, 1000, 0);;
2044 static void start_rtp(struct unistim_subchannel *sub)
2047 struct sockaddr_in us;
2048 struct sockaddr_in public;
2049 struct sockaddr_in sin;
2051 struct sockaddr_in sout;
2055 ast_log(LOG_WARNING, "start_rtp with a null subchannel !\n");
2059 ast_log(LOG_WARNING, "start_rtp with a null line !\n");
2062 if (!sub->parent->parent) {
2063 ast_log(LOG_WARNING, "start_rtp with a null device !\n");
2066 if (!sub->parent->parent->session) {
2067 ast_log(LOG_WARNING, "start_rtp with a null session !\n");
2070 sout = sub->parent->parent->session->sout;
2072 ast_mutex_lock(&sub->lock);
2073 /* Allocate the RTP */
2075 ast_verbose("Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
2076 sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, sout.sin_addr);
2078 ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
2079 strerror(errno), ast_inet_ntoa(sout.sin_addr));
2080 ast_mutex_unlock(&sub->lock);
2083 if (sub->rtp && sub->owner) {
2084 sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
2085 sub->owner->fds[1] = ast_rtcp_fd(sub->rtp);
2088 ast_rtp_setqos(sub->rtp, tos_audio, cos_audio, "UNISTIM RTP");
2089 ast_rtp_setnat(sub->rtp, sub->parent->parent->nat);
2092 /* Create the RTP connection */
2093 ast_rtp_get_us(sub->rtp, &us);
2094 sin.sin_family = AF_INET;
2095 /* Setting up RTP for our side */
2096 memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
2097 sizeof(sin.sin_addr));
2098 sin.sin_port = htons(sub->parent->parent->rtp_port);
2099 ast_rtp_set_peer(sub->rtp, &sin);
2100 if (!(sub->owner->nativeformats & sub->owner->readformat)) {
2102 fmt = ast_best_codec(sub->owner->nativeformats);
2103 ast_log(LOG_WARNING,
2104 "Our read/writeformat has been changed to something incompatible : %s (%d), using %s (%d) best codec from %d\n",
2105 ast_getformatname(sub->owner->readformat),
2106 sub->owner->readformat, ast_getformatname(fmt), fmt,
2107 sub->owner->nativeformats);
2108 sub->owner->readformat = fmt;
2109 sub->owner->writeformat = fmt;
2111 codec = ast_rtp_lookup_code(sub->rtp, 1, sub->owner->readformat);
2112 /* Setting up RTP of the phone */
2113 if (public_ip.sin_family == 0) /* NAT IP override ? */
2114 memcpy(&public, &us, sizeof(public)); /* No defined, using IP from recvmsg */
2116 memcpy(&public, &public_ip, sizeof(public)); /* override */
2119 ("RTP started : Our IP/port is : %s:%hd with codec %s (%d)\n",
2120 ast_inet_ntoa(us.sin_addr),
2121 htons(us.sin_port), ast_getformatname(sub->owner->readformat),
2122 sub->owner->readformat);
2123 ast_verbose("Starting phone RTP stack. Our public IP is %s\n",
2124 ast_inet_ntoa(public.sin_addr));
2126 if ((sub->owner->readformat == AST_FORMAT_ULAW) ||
2127 (sub->owner->readformat == AST_FORMAT_ALAW)) {
2129 ast_verbose("Sending packet_send_rtp_packet_size for codec %d\n", codec);
2130 memcpy(buffsend + SIZE_HEADER, packet_send_rtp_packet_size,
2131 sizeof(packet_send_rtp_packet_size));
2132 buffsend[10] = codec;
2133 send_client(SIZE_HEADER + sizeof(packet_send_rtp_packet_size), buffsend,
2134 sub->parent->parent->session);
2137 ast_verbose("Sending Jitter Buffer Parameters Configuration\n");
2138 memcpy(buffsend + SIZE_HEADER, packet_send_jitter_buffer_conf,
2139 sizeof(packet_send_jitter_buffer_conf));
2140 send_client(SIZE_HEADER + sizeof(packet_send_jitter_buffer_conf), buffsend,
2141 sub->parent->parent->session);
2142 if (sub->parent->parent->rtp_method != 0) {
2143 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2146 ast_verbose("Sending OpenAudioStreamTX using method #%d\n",
2147 sub->parent->parent->rtp_method);
2148 if (sub->parent->parent->rtp_method == 3)
2149 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx3,
2150 sizeof(packet_send_open_audio_stream_tx3));
2152 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx,
2153 sizeof(packet_send_open_audio_stream_tx));
2154 if (sub->parent->parent->rtp_method != 2) {
2155 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2156 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2157 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2158 buffsend[23] = (rtcpsin_port & 0x00ff);
2159 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2160 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2161 buffsend[24] = (us.sin_port & 0x00ff);
2162 buffsend[27] = (rtcpsin_port & 0x00ff);
2163 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2165 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2166 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2167 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2168 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2169 buffsend[19] = (us.sin_port & 0x00ff);
2170 buffsend[11] = codec;
2172 buffsend[12] = codec;
2173 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_tx), buffsend,
2174 sub->parent->parent->session);
2177 ast_verbose("Sending OpenAudioStreamRX\n");
2178 if (sub->parent->parent->rtp_method == 3)
2179 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx3,
2180 sizeof(packet_send_open_audio_stream_rx3));
2182 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx,
2183 sizeof(packet_send_open_audio_stream_rx));
2184 if (sub->parent->parent->rtp_method != 2) {
2185 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2186 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2187 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2188 buffsend[23] = (rtcpsin_port & 0x00ff);
2189 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2190 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2191 buffsend[24] = (us.sin_port & 0x00ff);
2192 buffsend[27] = (rtcpsin_port & 0x00ff);
2193 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2195 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2196 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2197 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2198 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2199 buffsend[19] = (us.sin_port & 0x00ff);
2200 buffsend[12] = codec;
2202 buffsend[11] = codec;
2203 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_rx), buffsend,
2204 sub->parent->parent->session);
2206 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2209 ast_verbose("Sending packet_send_call default method\n");
2211 memcpy(buffsend + SIZE_HEADER, packet_send_call, sizeof(packet_send_call));
2212 memcpy(buffsend + 53, &public.sin_addr, sizeof(public.sin_addr));
2213 /* Destination port when sending RTP */
2214 buffsend[49] = (us.sin_port & 0x00ff);
2215 buffsend[50] = (us.sin_port & 0xff00) >> 8;
2216 /* Destination port when sending RTCP */
2217 buffsend[52] = (rtcpsin_port & 0x00ff);
2218 buffsend[51] = (rtcpsin_port & 0xff00) >> 8;
2220 buffsend[40] = codec;
2221 buffsend[41] = codec;
2222 if (sub->owner->readformat == AST_FORMAT_ULAW)
2223 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2224 else if (sub->owner->readformat == AST_FORMAT_ALAW)
2225 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2226 else if (sub->owner->readformat == AST_FORMAT_G723_1)
2227 buffsend[42] = 2; /* 1 = 30ms (24 bytes), 2 = 60 ms (48 bytes) */
2228 else if (sub->owner->readformat == AST_FORMAT_G729A)
2229 buffsend[42] = 2; /* 1 = 10ms (10 bytes), 2 = 20ms (20 bytes) */
2231 ast_log(LOG_WARNING, "Unsupported codec %s (%d) !\n",
2232 ast_getformatname(sub->owner->readformat), sub->owner->readformat);
2233 /* Source port for transmit RTP and Destination port for receiving RTP */
2234 buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8;
2235 buffsend[46] = (htons(sin.sin_port) & 0x00ff);
2236 buffsend[47] = (rtcpsin_port & 0xff00) >> 8;
2237 buffsend[48] = (rtcpsin_port & 0x00ff);
2238 send_client(SIZE_HEADER + sizeof(packet_send_call), buffsend,
2239 sub->parent->parent->session);
2241 ast_mutex_unlock(&sub->lock);
2244 static void SendDialTone(struct unistimsession *pte)
2247 /* No country defined ? Using US tone */
2248 if (ast_strlen_zero(pte->device->country)) {
2250 ast_verbose("No country defined, using US tone\n");
2251 send_tone(pte, 350, 440);
2254 if (strlen(pte->device->country) != 2) {
2256 ast_verbose("Country code != 2 char, using US tone\n");
2257 send_tone(pte, 350, 440);
2261 while (frequency[i].freq1) {
2262 if ((frequency[i].country[0] == pte->device->country[0]) &&
2263 (frequency[i].country[1] == pte->device->country[1])) {
2265 ast_verbose("Country code found (%s), freq1=%d freq2=%d\n",
2266 frequency[i].country, frequency[i].freq1, frequency[i].freq2);
2267 send_tone(pte, frequency[i].freq1, frequency[i].freq2);
2273 static void handle_dial_page(struct unistimsession *pte)
2275 pte->state = STATE_DIALPAGE;
2276 if (pte->device->call_forward[0] == -1) {
2277 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
2278 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Enter forward");
2279 send_text_status(pte, "ForwardCancel BackSpcErase");
2280 if (pte->device->call_forward[1] != 0) {
2281 char tmp[TEXT_LENGTH_MAX + 1];
2283 ast_copy_string(pte->device->phone_number, pte->device->call_forward + 1,
2284 sizeof(pte->device->phone_number));
2285 pte->device->size_phone_number = strlen(pte->device->phone_number);
2286 if (pte->device->size_phone_number > 15)
2287 pte->device->size_phone_number = 15;
2288 strcpy(tmp, "Number : ...............");
2289 memcpy(tmp + 9, pte->device->phone_number, pte->device->size_phone_number);
2290 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
2291 send_blink_cursor(pte);
2292 send_cursor_pos(pte,
2293 (unsigned char) (TEXT_LINE2 + 0x09 +
2294 pte->device->size_phone_number));
2295 send_led_update(pte, 0);
2299 if ((pte->device->output == OUTPUT_HANDSET) &&
2300 (pte->device->receiver_state == STATE_ONHOOK))
2301 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2303 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2305 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Enter the number to dial");
2306 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "and press Call");
2307 send_text_status(pte, "Call Redial BackSpcErase");
2309 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
2310 send_blink_cursor(pte);
2311 send_cursor_pos(pte, TEXT_LINE2 + 0x09);
2312 pte->device->size_phone_number = 0;
2313 pte->device->phone_number[0] = 0;
2314 change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
2315 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
2316 pte->device->missed_call = 0;
2317 send_led_update(pte, 0);
2321 /* Step 1 : Music On Hold for peer, Dialing screen for us */
2322 static void TransferCallStep1(struct unistimsession *pte)
2324 struct unistim_subchannel *sub;
2325 struct unistim_line *p = pte->device->lines;
2327 sub = p->subs[SUB_REAL];
2330 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2333 if (p->subs[SUB_THREEWAY]) {
2335 ast_verbose("Transfer canceled, hangup our threeway channel\n");
2336 if (p->subs[SUB_THREEWAY]->owner)
2337 ast_queue_hangup(p->subs[SUB_THREEWAY]->owner);
2339 ast_log(LOG_WARNING, "Canceling a threeway channel without owner\n");
2342 /* Start music on hold if appropriate */
2343 if (pte->device->moh)
2344 ast_log(LOG_WARNING, "Transfer with peer already listening music on hold\n");
2346 if (ast_bridged_channel(p->subs[SUB_REAL]->owner)) {
2347 ast_moh_start(ast_bridged_channel(p->subs[SUB_REAL]->owner),
2348 pte->device->lines->musicclass, NULL);
2349 pte->device->moh = 1;
2351 ast_log(LOG_WARNING, "Unable to find peer subchannel for music on hold\n");
2355 /* Silence our channel */
2356 if (!pte->device->silence_generator) {
2357 pte->device->silence_generator =
2358 ast_channel_start_silence_generator(p->subs[SUB_REAL]->owner);
2359 if (pte->device->silence_generator == NULL)
2360 ast_log(LOG_WARNING, "Unable to start a silence generator.\n");
2361 else if (unistimdebug)
2362 ast_verbose("Starting silence generator\n");
2364 handle_dial_page(pte);
2367 /* From phone to PBX */
2368 static void HandleCallOutgoing(struct unistimsession *s)
2370 struct ast_channel *c;
2371 struct unistim_subchannel *sub;
2373 s->state = STATE_CALL;
2374 sub = s->device->lines->subs[SUB_REAL];
2376 ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
2379 if (!sub->owner) { /* A call is already in progress ? */
2380 c = unistim_new(sub, AST_STATE_DOWN); /* No, starting a new one */
2382 /* Need to start RTP before calling ast_pbx_run */
2385 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
2386 send_text(TEXT_LINE0, TEXT_NORMAL, s, "Calling :");
2387 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
2388 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Dialing...");
2389 send_text_status(s, "Hangup");
2391 if (ast_pthread_create(&t, NULL, unistim_ss, c)) {
2392 display_last_error("Unable to create switch thread");
2393 ast_queue_hangup(c);
2396 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n",
2397 sub->parent->name, s->device->name);
2398 } else { /* We already have a call, so we switch in a threeway call */
2400 if (s->device->moh) {
2401 struct unistim_subchannel *sub;
2402 struct unistim_line *p = s->device->lines;
2403 sub = p->subs[SUB_REAL];
2406 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2409 if (p->subs[SUB_THREEWAY]) {
2410 ast_log(LOG_WARNING,
2411 "Can't transfer while an another transfer is taking place\n");
2414 if (!alloc_sub(p, SUB_THREEWAY)) {
2415 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
2418 /* Stop the silence generator */
2419 if (s->device->silence_generator) {
2421 ast_verbose("Stopping silence generator\n");
2422 ast_channel_stop_silence_generator(sub->owner,
2423 s->device->silence_generator);
2424 s->device->silence_generator = NULL;
2427 /* Make new channel */
2428 c = unistim_new(p->subs[SUB_THREEWAY], AST_STATE_DOWN);
2430 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", p);
2433 /* Swap things around between the three-way and real call */
2434 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2435 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
2436 send_text(TEXT_LINE0, TEXT_NORMAL, s, "Calling (pre-transfer)");
2437 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
2438 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Dialing...");
2439 send_text_status(s, "TransfrCancel");
2441 if (ast_pthread_create(&t, NULL, unistim_ss, p->subs[SUB_THREEWAY]->owner)) {
2442 ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", p);
2448 ("Started three way call on channel %p (%s) subchan %d\n",
2449 p->subs[SUB_THREEWAY]->owner, p->subs[SUB_THREEWAY]->owner->name,
2450 p->subs[SUB_THREEWAY]->subtype);
2452 ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name);
2457 /* From PBX to phone */
2458 static void HandleCallIncoming(struct unistimsession *s)
2460 struct unistim_subchannel *sub;
2461 s->state = STATE_CALL;
2462 s->device->missed_call = 0;
2464 sub = s->device->lines->subs[SUB_REAL];
2466 ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
2468 } else if (unistimdebug)
2469 ast_verbose("Handle Call Incoming for %s@%s\n", sub->parent->name,
2473 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", sub->parent->name,
2475 ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
2476 send_text(TEXT_LINE2, TEXT_NORMAL, s, "is on-line");
2477 send_text_status(s, "Hangup Transf");
2478 send_start_timer(s);
2480 if ((s->device->output == OUTPUT_HANDSET) &&
2481 (s->device->receiver_state == STATE_ONHOOK))
2482 send_select_output(s, OUTPUT_SPEAKER, s->device->volume, MUTE_OFF);
2484 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
2485 s->device->start_call_timestamp = time(0);
2486 write_history(s, 'i', 0);
2490 static int unistim_do_senddigit(struct unistimsession *pte, char digit)
2493 struct ast_frame f = { 0, };
2494 struct unistim_subchannel *sub;
2495 sub = pte->device->lines->subs[SUB_REAL];
2497 ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit\n");
2501 ast_verbose("Send Digit %c\n", digit);
2504 send_tone(pte, 941, 1336);
2507 send_tone(pte, 697, 1209);
2510 send_tone(pte, 697, 1336);
2513 send_tone(pte, 697, 1477);
2516 send_tone(pte, 770, 1209);
2519 send_tone(pte, 770, 1336);
2522 send_tone(pte, 770, 1477);
2525 send_tone(pte, 852, 1209);
2528 send_tone(pte, 852, 1336);
2531 send_tone(pte, 852, 1477);
2534 send_tone(pte, 697, 1633);
2537 send_tone(pte, 770, 1633);
2540 send_tone(pte, 852, 1633);
2543 send_tone(pte, 941, 1633);
2546 send_tone(pte, 941, 1209);
2549 send_tone(pte, 941, 1477);
2552 send_tone(pte, 500, 2000);
2554 usleep(150000); /* XXX Less than perfect, blocking an important thread is not a good idea */
2555 send_tone(pte, 0, 0);
2556 f.frametype = AST_FRAME_DTMF;
2559 ast_queue_frame(sub->owner, &f);
2563 static void key_call(struct unistimsession *pte, char keycode)
2565 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
2566 if (keycode == KEY_SHARP)
2568 else if (keycode == KEY_STAR)
2572 unistim_do_senddigit(pte, keycode);
2581 TransferCallStep1(pte);
2584 if (pte->device->output == OUTPUT_HEADPHONE)
2585 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
2587 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
2590 if (pte->device->output != OUTPUT_SPEAKER)
2591 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2593 send_select_output(pte, pte->device->previous_output, pte->device->volume,
2597 if (!pte->device->moh) {
2598 if (pte->device->mute == MUTE_ON)
2599 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2601 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
2606 struct unistim_subchannel *sub;
2607 struct ast_channel *bridgepeer = NULL;
2608 sub = pte->device->lines->subs[SUB_REAL];
2610 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2613 if ((bridgepeer = ast_bridged_channel(sub->owner))) {
2614 if (pte->device->moh) {
2615 ast_moh_stop(bridgepeer);
2616 pte->device->moh = 0;
2617 send_select_output(pte, pte->device->output, pte->device->volume,
2620 ast_moh_start(bridgepeer, pte->device->lines->musicclass, NULL);
2621 pte->device->moh = 1;
2622 send_select_output(pte, pte->device->output, pte->device->volume,
2626 ast_log(LOG_WARNING,
2627 "Unable to find peer subchannel for music on hold\n");
2634 static void key_ringing(struct unistimsession *pte, char keycode)
2636 if (keycode == KEY_FAV0 + pte->device->softkeylinepos) {
2637 HandleCallIncoming(pte);
2646 HandleCallIncoming(pte);
2652 static void Keyfavorite(struct unistimsession *pte, char keycode)
2656 if ((keycode < KEY_FAV1) && (keycode > KEY_FAV5)) {
2657 ast_log(LOG_WARNING, "It's not a favorite key\n");
2660 if (keycode == KEY_FAV0)
2662 fav = keycode - KEY_FAV0;
2663 if (pte->device->softkeyicon[fav] == 0)
2665 ast_copy_string(pte->device->phone_number, pte->device->softkeynumber[fav],
2666 sizeof(pte->device->phone_number));
2667 HandleCallOutgoing(pte);
2671 static void key_dial_page(struct unistimsession *pte, char keycode)
2673 if (keycode == KEY_FUNC3) {
2674 if (pte->device->size_phone_number <= 1)
2675 keycode = KEY_FUNC4;
2677 pte->device->size_phone_number -= 2;
2678 keycode = pte->device->phone_number[pte->device->size_phone_number] + 0x10;
2681 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
2682 char tmpbuf[] = "Number : ...............";
2685 if (pte->device->size_phone_number >= 15)
2687 if (pte->device->size_phone_number == 0)
2688 send_tone(pte, 0, 0);
2689 while (i < pte->device->size_phone_number) {
2690 tmpbuf[i + 9] = pte->device->phone_number[i];
2693 if (keycode == KEY_SHARP)
2695 else if (keycode == KEY_STAR)
2699 tmpbuf[i + 9] = keycode;
2700 pte->device->phone_number[i] = keycode;
2701 pte->device->size_phone_number++;
2702 pte->device->phone_number[i + 1] = 0;
2703 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
2704 send_blink_cursor(pte);
2705 send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 + 0x0a + i));
2708 if (keycode == KEY_FUNC4) {
2710 pte->device->size_phone_number = 0;
2711 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
2712 send_blink_cursor(pte);
2713 send_cursor_pos(pte, TEXT_LINE2 + 0x09);
2717 if (pte->device->call_forward[0] == -1) {
2718 if (keycode == KEY_FUNC1) {
2719 ast_copy_string(pte->device->call_forward, pte->device->phone_number,
2720 sizeof(pte->device->call_forward));
2721 show_main_page(pte);
2722 } else if ((keycode == KEY_FUNC2) || (keycode == KEY_HANGUP)) {
2723 pte->device->call_forward[0] = '\0';
2724 show_main_page(pte);
2730 if (ast_strlen_zero(pte->device->redial_number))
2732 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
2733 sizeof(pte->device->phone_number));
2735 HandleCallOutgoing(pte);
2738 if (pte->device->lines->subs[SUB_REAL]->owner) {
2739 /* Stop the silence generator */
2740 if (pte->device->silence_generator) {
2742 ast_verbose("Stopping silence generator\n");
2743 ast_channel_stop_silence_generator(pte->device->lines->subs[SUB_REAL]->
2744 owner, pte->device->silence_generator);
2745 pte->device->silence_generator = NULL;
2747 send_tone(pte, 0, 0);
2748 ast_moh_stop(ast_bridged_channel(pte->device->lines->subs[SUB_REAL]->owner));
2749 pte->device->moh = 0;
2750 pte->state = STATE_CALL;
2751 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Dialing canceled,");
2752 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "switching back to");
2753 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "previous call.");
2754 send_text_status(pte, "Hangup Transf");
2756 show_main_page(pte);
2763 Keyfavorite(pte, keycode);
2766 if (pte->device->output == OUTPUT_SPEAKER) {
2767 if (pte->device->receiver_state == STATE_OFFHOOK)
2768 send_select_output(pte, pte->device->previous_output, pte->device->volume,
2771 show_main_page(pte);
2773 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2776 if (pte->device->output == OUTPUT_HEADPHONE) {
2777 if (pte->device->receiver_state == STATE_OFFHOOK)
2778 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
2780 show_main_page(pte);
2782 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
2788 #define SELECTCODEC_START_ENTRY_POS 15
2789 #define SELECTCODEC_MAX_LENGTH 2
2790 #define SELECTCODEC_MSG "Codec number : .."
2791 static void HandleSelectCodec(struct unistimsession *pte)
2793 char buf[30], buf2[5];
2795 pte->state = STATE_SELECTCODEC;
2796 strcpy(buf, "Using codec ");
2797 sprintf(buf2, "%d", pte->device->codec_number);
2799 strcat(buf, " (G711u=0,");
2801 send_text(TEXT_LINE0, TEXT_NORMAL, pte, buf);
2802 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "G723=4,G711a=8,G729A=18)");
2803 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
2804 send_blink_cursor(pte);
2805 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
2806 pte->size_buff_entry = 0;
2807 send_text_status(pte, "Select BackSpcErase Cancel");
2811 static void key_select_codec(struct unistimsession *pte, char keycode)
2813 if (keycode == KEY_FUNC2) {
2814 if (pte->size_buff_entry <= 1)
2815 keycode = KEY_FUNC3;
2817 pte->size_buff_entry -= 2;
2818 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
2821 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
2822 char tmpbuf[] = SELECTCODEC_MSG;
2825 if (pte->size_buff_entry >= SELECTCODEC_MAX_LENGTH)
2828 while (i < pte->size_buff_entry) {
2829 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = pte->buff_entry[i];
2832 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = keycode - 0x10;
2833 pte->buff_entry[i] = keycode - 0x10;
2834 pte->size_buff_entry++;
2835 send_text(TEXT_LINE2, TEXT_INVERSE, pte, tmpbuf);
2836 send_blink_cursor(pte);
2837 send_cursor_pos(pte,
2838 (unsigned char) (TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS + 1 + i));
2844 if (pte->size_buff_entry == 1)
2845 pte->device->codec_number = pte->buff_entry[0] - 48;
2846 else if (pte->size_buff_entry == 2)
2847 pte->device->codec_number =
2848 ((pte->buff_entry[0] - 48) * 10) + (pte->buff_entry[1] - 48);
2849 show_main_page(pte);
2852 pte->size_buff_entry = 0;
2853 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
2854 send_blink_cursor(pte);
2855 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
2859 show_main_page(pte);
2865 #define SELECTEXTENSION_START_ENTRY_POS 0
2866 #define SELECTEXTENSION_MAX_LENGTH 10
2867 #define SELECTEXTENSION_MSG ".........."
2868 static void ShowExtensionPage(struct unistimsession *pte)
2870 pte->state = STATE_EXTENSION;
2872 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Please enter a Terminal");
2873 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Number (TN) :");
2874 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
2875 send_blink_cursor(pte);
2876 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
2877 send_text_status(pte, "Enter BackSpcErase");
2878 pte->size_buff_entry = 0;
2882 static void key_select_extension(struct unistimsession *pte, char keycode)
2884 if (keycode == KEY_FUNC2) {
2885 if (pte->size_buff_entry <= 1)
2886 keycode = KEY_FUNC3;
2888 pte->size_buff_entry -= 2;
2889 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
2892 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
2893 char tmpbuf[] = SELECTEXTENSION_MSG;
2896 if (pte->size_buff_entry >= SELECTEXTENSION_MAX_LENGTH)
2899 while (i < pte->size_buff_entry) {
2900 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = pte->buff_entry[i];
2903 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = keycode - 0x10;
2904 pte->buff_entry[i] = keycode - 0x10;
2905 pte->size_buff_entry++;
2906 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
2907 send_blink_cursor(pte);
2908 send_cursor_pos(pte,
2909 (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS + 1 +
2916 if (pte->size_buff_entry < 1)
2918 if (autoprovisioning == AUTOPROVISIONING_TN) {
2919 struct unistim_device *d;
2921 /* First step : looking for this TN in our device list */
2922 ast_mutex_lock(&devicelock);
2924 pte->buff_entry[pte->size_buff_entry] = '\0';
2926 if (d->id[0] == 'T') { /* It's a TN device ? */
2927 /* It's the TN we're looking for ? */
2928 if (!strcmp((d->id) + 1, pte->buff_entry)) {
2931 d->codec_number = DEFAULT_CODEC;
2934 d->receiver_state = STATE_ONHOOK;
2935 strcpy(d->id, pte->macaddr);
2936 pte->device->extension_number[0] = 'T';
2937 pte->device->extension = EXTENSION_TN;
2938 ast_copy_string((pte->device->extension_number) + 1,
2939 pte->buff_entry, pte->size_buff_entry + 1);
2940 ast_mutex_unlock(&devicelock);
2941 show_main_page(pte);
2942 refresh_all_favorite(pte);
2948 ast_mutex_unlock(&devicelock);
2949 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Invalid Terminal Number.");
2950 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Please try again :");
2951 send_cursor_pos(pte,
2952 (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS +
2953 pte->size_buff_entry));
2954 send_blink_cursor(pte);
2956 ast_copy_string(pte->device->extension_number, pte->buff_entry,
2957 pte->size_buff_entry + 1);
2958 if (RegisterExtension(pte)) {
2959 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Invalid extension.");
2960 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Please try again :");
2961 send_cursor_pos(pte,
2962 (unsigned char) (TEXT_LINE2 +
2963 SELECTEXTENSION_START_ENTRY_POS +
2964 pte->size_buff_entry));
2965 send_blink_cursor(pte);
2967 show_main_page(pte);
2971 pte->size_buff_entry = 0;
2972 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
2973 send_blink_cursor(pte);
2974 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
2980 static int ReformatNumber(char *number)
2982 int pos = 0, i = 0, size = strlen(number);
2984 for (; i < size; i++) {
2985 if ((number[i] >= '0') && (number[i] <= '9')) {
2990 number[pos] = number[i];
2998 static void show_entry_history(struct unistimsession *pte, FILE ** f)
3000 char line[TEXT_LENGTH_MAX + 1], status[STATUS_LENGTH_MAX + 1], func1[10], func2[10],