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
37 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
39 #include <sys/socket.h>
40 #include <sys/ioctl.h>
45 #include <sys/signal.h>
47 #include <netinet/in.h>
48 #include <netinet/in_systm.h>
49 #include <netinet/ip.h>
50 #include <arpa/inet.h>
53 #include "asterisk/paths.h" /* ast_config_AST_LOG_DIR used in (too ?) many places */
54 #include "asterisk/lock.h"
55 #include "asterisk/channel.h"
56 #include "asterisk/config.h"
57 #include "asterisk/module.h"
58 #include "asterisk/pbx.h"
59 #include "asterisk/sched.h"
60 #include "asterisk/io.h"
61 #include "asterisk/rtp.h"
62 #include "asterisk/netsock.h"
63 #include "asterisk/acl.h"
64 #include "asterisk/callerid.h"
65 #include "asterisk/cli.h"
66 #include "asterisk/say.h"
67 #include "asterisk/cdr.h"
68 #include "asterisk/astdb.h"
69 #include "asterisk/features.h"
70 #include "asterisk/app.h"
71 #include "asterisk/musiconhold.h"
72 #include "asterisk/utils.h"
73 #include "asterisk/causes.h"
74 #include "asterisk/indications.h"
75 #include "asterisk/dsp.h"
76 #include "asterisk/devicestate.h"
77 #include "asterisk/stringfields.h"
78 #include "asterisk/abstract_jb.h"
79 #include "asterisk/event.h"
80 #include "asterisk/localtime.h"
82 /*! Beware, G729 and G723 are not supported by asterisk, except with the proper licence */
83 #define CAPABILITY AST_FORMAT_ALAW | AST_FORMAT_ULAW /* | AST_FORMAT_G729A | AST_FORMAT_G723_1 */
85 #define DEFAULTCONTEXT "default"
86 #define DEFAULTCALLERID "Unknown"
87 #define DEFAULTCALLERNAME " "
88 #define USTM_LOG_DIR "unistimHistory"
90 /*! Size of the transmit buffer */
91 #define MAX_BUF_SIZE 64
92 /*! Number of slots for the transmit queue */
93 #define MAX_BUF_NUMBER 50
94 /*! Try x times before removing the phone */
95 #define NB_MAX_RETRANSMIT 8
96 /*! Nb of milliseconds waited when no events are scheduled */
97 #define IDLE_WAIT 1000
98 /*! Wait x milliseconds before resending a packet */
99 #define RETRANSMIT_TIMER 2000
100 /*! How often the mailbox is checked for new messages */
101 #define TIMER_MWI 10000
103 #define DEFAULT_CODEC 0x00
104 #define SIZE_PAGE 4096
105 #define DEVICE_NAME_LEN 16
106 #define AST_CONFIG_MAX_PATH 255
107 #define MAX_ENTRY_LOG 30
110 #define SUB_THREEWAY 1
114 AUTOPROVISIONING_NO = 0,
115 AUTOPROVISIONING_YES,
121 /*! Do not create an extension into the default dialplan */
123 /*! Prompt user for an extension number and register it */
125 /*! Register an extension with the line=> value */
127 /*! Used with AUTOPROVISIONING_TN */
130 #define OUTPUT_HANDSET 0xC0
131 #define OUTPUT_HEADPHONE 0xC1
132 #define OUTPUT_SPEAKER 0xC2
134 #define VOLUME_LOW 0x01
135 #define VOLUME_LOW_SPEAKER 0x03
136 #define VOLUME_NORMAL 0x02
137 #define VOLUME_INSANELY_LOUD 0x07
139 #define MUTE_OFF 0x00
141 #define MUTE_ON_DISCRET 0xCE
143 #define SIZE_HEADER 6
144 #define SIZE_MAC_ADDR 17
145 #define TEXT_LENGTH_MAX 24
146 #define TEXT_LINE0 0x00
147 #define TEXT_LINE1 0x20
148 #define TEXT_LINE2 0x40
149 #define TEXT_NORMAL 0x05
150 #define TEXT_INVERSE 0x25
151 #define STATUS_LENGTH_MAX 28
153 #define FAV_ICON_NONE 0x00
154 #define FAV_ICON_ONHOOK_BLACK 0x20
155 #define FAV_ICON_ONHOOK_WHITE 0x21
156 #define FAV_ICON_SPEAKER_ONHOOK_BLACK 0x22
157 #define FAV_ICON_SPEAKER_ONHOOK_WHITE 0x23
158 #define FAV_ICON_OFFHOOK_BLACK 0x24
159 #define FAV_ICON_OFFHOOK_WHITE 0x25
160 #define FAV_ICON_ONHOLD_BLACK 0x26
161 #define FAV_ICON_ONHOLD_WHITE 0x27
162 #define FAV_ICON_SPEAKER_OFFHOOK_BLACK 0x28
163 #define FAV_ICON_SPEAKER_OFFHOOK_WHITE 0x29
164 #define FAV_ICON_PHONE_BLACK 0x2A
165 #define FAV_ICON_PHONE_WHITE 0x2B
166 #define FAV_ICON_SPEAKER_ONHOLD_BLACK 0x2C
167 #define FAV_ICON_SPEAKER_ONHOLD_WHITE 0x2D
168 #define FAV_ICON_HEADPHONES 0x2E
169 #define FAV_ICON_HEADPHONES_ONHOLD 0x2F
170 #define FAV_ICON_HOME 0x30
171 #define FAV_ICON_CITY 0x31
172 #define FAV_ICON_SHARP 0x32
173 #define FAV_ICON_PAGER 0x33
174 #define FAV_ICON_CALL_CENTER 0x34
175 #define FAV_ICON_FAX 0x35
176 #define FAV_ICON_MAILBOX 0x36
177 #define FAV_ICON_REFLECT 0x37
178 #define FAV_ICON_COMPUTER 0x38
179 #define FAV_ICON_FORWARD 0x39
180 #define FAV_ICON_LOCKED 0x3A
181 #define FAV_ICON_TRASH 0x3B
182 #define FAV_ICON_INBOX 0x3C
183 #define FAV_ICON_OUTBOX 0x3D
184 #define FAV_ICON_MEETING 0x3E
185 #define FAV_ICON_BOX 0x3F
187 #define FAV_BLINK_FAST 0x20
188 #define FAV_BLINK_SLOW 0x40
190 #define FAV_MAX_LENGTH 0x0A
192 static void dummy(char *dummy, ...)
197 /*! \brief Global jitterbuffer configuration - by default, jb is disabled */
198 static struct ast_jb_conf default_jbconf =
202 .resync_threshold = -1,
205 static struct ast_jb_conf global_jbconf;
208 /* #define DUMP_PACKET 1 */
209 /* #define DEBUG_TIMER ast_verbose */
211 #define DEBUG_TIMER dummy
212 /*! Enable verbose output. can also be set with the CLI */
213 static int unistimdebug = 0;
214 static int unistim_port;
215 static enum autoprovision autoprovisioning = AUTOPROVISIONING_NO;
216 static int unistim_keepalive;
217 static int unistimsock = -1;
218 static unsigned int tos = 0;
219 static unsigned int tos_audio = 0;
220 static unsigned int cos = 0;
221 static unsigned int cos_audio = 0;
222 static struct io_context *io;
223 static struct sched_context *sched;
224 static struct sockaddr_in public_ip = { 0, };
225 /*! give the IP address for the last packet received */
226 static struct sockaddr_in addr_from;
227 /*! size of the sockaddr_in (in WSARecvFrom) */
228 static unsigned int size_addr_from = sizeof(addr_from);
229 /*! Receive buffer address */
230 static unsigned char *buff;
231 static int unistim_reloading = 0;
232 AST_MUTEX_DEFINE_STATIC(unistim_reload_lock);
233 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
234 static int usecnt = 0;
235 /* extern char ast_config_AST_LOG_DIR[AST_CONFIG_MAX_PATH]; */
237 /*! This is the thread for the monitor which checks for input on the channels
238 * which are not currently in use. */
239 static pthread_t monitor_thread = AST_PTHREADT_NULL;
241 /*! Protect the monitoring thread, so only one process can kill or start it, and not
242 * when it's doing something critical. */
243 AST_MUTEX_DEFINE_STATIC(monlock);
244 /*! Protect the session list */
245 AST_MUTEX_DEFINE_STATIC(sessionlock);
246 /*! Protect the device list */
247 AST_MUTEX_DEFINE_STATIC(devicelock);
308 struct tone_zone_unistim {
314 static const struct tone_zone_unistim frequency[] = {
354 unsigned short w_year;
355 unsigned short w_month;
356 unsigned short w_day_of_week;
357 unsigned short w_day;
358 unsigned short w_hour;
359 unsigned short w_minute;
360 unsigned short w_second;
361 unsigned short w_milliseconds;
364 struct unistim_subchannel {
366 /*! SUBS_REAL or SUBS_THREEWAY */
367 unsigned int subtype;
368 /*! Asterisk channel used by the subchannel */
369 struct ast_channel *owner;
371 struct unistim_line *parent;
380 * \todo Convert to stringfields
382 struct unistim_line {
386 /*! Like USTM/200\@black */
388 /*! pointer to our current connection, channel... */
389 struct unistim_subchannel *subs[MAX_SUBS];
390 /*! Extension where to start */
391 char exten[AST_MAX_EXTENSION];
392 /*! Context to start in */
393 char context[AST_MAX_EXTENSION];
394 /*! Language for asterisk sounds */
395 char language[MAX_LANGUAGE];
396 /*! CallerID Number */
397 char cid_num[AST_MAX_EXTENSION];
398 /*! Mailbox for MWI */
399 char mailbox[AST_MAX_EXTENSION];
404 /*! MusicOnHold class */
405 char musicclass[MAX_MUSICCLASS];
407 unsigned int callgroup;
409 unsigned int pickupgroup;
410 /*! Account code (for billing) */
411 char accountcode[80];
412 /*! AMA flags (for billing) */
414 /*! Codec supported */
416 struct unistim_line *next;
417 struct unistim_device *parent;
421 * \brief A device containing one or more lines
423 static struct unistim_device {
424 int receiver_state; /*!< state of the receiver (see ReceiverState) */
425 int size_phone_number; /*!< size of the phone number */
426 char phone_number[16]; /*!< the phone number entered by the user */
427 char redial_number[16]; /*!< the last phone number entered by the user */
428 int phone_current; /*!< Number of the current phone */
429 int pos_fav; /*!< Position of the displayed favorites (used for scrolling) */
430 char id[18]; /*!< mac address of the current phone in ascii */
431 char name[DEVICE_NAME_LEN]; /*!< name of the device */
432 int softkeylinepos; /*!< position of the line softkey (default 0) */
433 char softkeylabel[6][11]; /*!< soft key label */
434 char softkeynumber[6][16]; /*!< number dialed when the soft key is pressed */
435 char softkeyicon[6]; /*!< icon number */
436 char softkeydevice[6][16]; /*!< name of the device monitored */
437 struct unistim_device *sp[6]; /*!< pointer to the device monitored by this soft key */
438 char maintext0[25]; /*!< when the phone is idle, display this string on line 0 */
439 char maintext1[25]; /*!< when the phone is idle, display this string on line 1 */
440 char maintext2[25]; /*!< when the phone is idle, display this string on line 2 */
441 char titledefault[13]; /*!< title (text before date/time) */
442 char datetimeformat; /*!< format used for displaying time/date */
443 char contrast; /*!< contrast */
444 char country[3]; /*!< country used for dial tone frequency */
445 struct ind_tone_zone *tz; /*!< Tone zone for res_indications (ring, busy, congestion) */
446 char ringvolume; /*!< Ring volume */
447 char ringstyle; /*!< Ring melody */
448 int rtp_port; /*!< RTP port used by the phone */
449 int rtp_method; /*!< Select the unistim data used to establish a RTP session */
450 int status_method; /*!< Select the unistim packet used for sending status text */
451 char codec_number; /*!< The current codec used to make calls */
452 int missed_call; /*!< Number of call unanswered */
453 int callhistory; /*!< Allowed to record call history */
454 char lst_cid[TEXT_LENGTH_MAX]; /*!< Last callerID received */
455 char lst_cnm[TEXT_LENGTH_MAX]; /*!< Last callername recevied */
456 char call_forward[AST_MAX_EXTENSION]; /*!< Forward number */
457 int output; /*!< Handset, headphone or speaker */
458 int previous_output; /*!< Previous output */
459 int volume; /*!< Default volume */
460 int mute; /*!< Mute mode */
461 int moh; /*!< Music on hold in progress */
462 int nat; /*!< Used by the obscure ast_rtp_setnat */
463 enum autoprov_extn extension; /*!< See ifdef EXTENSION for valid values */
464 char extension_number[11]; /*!< Extension number entered by the user */
465 char to_delete; /*!< Used in reload */
466 time_t start_call_timestamp; /*!< timestamp for the length calculation of the call */
467 struct ast_silence_generator *silence_generator;
468 struct unistim_line *lines;
470 struct unistimsession *session;
471 struct unistim_device *next;
474 static struct unistimsession {
476 struct sockaddr_in sin; /*!< IP address of the phone */
477 struct sockaddr_in sout; /*!< IP address of server */
478 int timeout; /*!< time-out in ticks : resend packet if no ack was received before the timeout occured */
479 unsigned short seq_phone; /*!< sequence number for the next packet (when we receive a request) */
480 unsigned short seq_server; /*!< sequence number for the next packet (when we send a request) */
481 unsigned short last_seq_ack; /*!< sequence number of the last ACK received */
482 unsigned long tick_next_ping; /*!< time for the next ping */
483 int last_buf_available; /*!< number of a free slot */
484 int nb_retransmit; /*!< number of retransmition */
485 int state; /*!< state of the phone (see phone_state) */
486 int size_buff_entry; /*!< size of the buffer used to enter datas */
487 char buff_entry[16]; /*!< Buffer for temporary datas */
488 char macaddr[18]; /*!< mac adress of the phone (not always available) */
489 struct wsabuf wsabufsend[MAX_BUF_NUMBER]; /*!< Size of each paquet stored in the buffer array & pointer to this buffer */
490 unsigned char buf[MAX_BUF_NUMBER][MAX_BUF_SIZE]; /*!< Buffer array used to keep the lastest non-acked paquets */
491 struct unistim_device *device;
492 struct unistimsession *next;
496 * \page Unistim datagram formats
498 * Format of datagrams :
499 * bytes 0 & 1 : ffff for discovery packet, 0000 for everything else
500 * byte 2 : sequence number (high part)
501 * byte 3 : sequence number (low part)
502 * byte 4 : 2 = ask question or send info, 1 = answer or ACK, 0 = retransmit request
503 * byte 5 : direction, 1 = server to phone, 2 = phone to server arguments
506 const static unsigned char packet_rcv_discovery[] =
507 { 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
508 static unsigned char packet_send_discovery_ack[] =
509 { 0x00, 0x00, /*Initial Seq (2 bytes) */ 0x00, 0x00, 0x00, 0x01 };
511 const static unsigned char packet_recv_firm_version[] =
512 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x0a, 0x02 };
513 const static unsigned char packet_recv_pressed_key[] =
514 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x04, 0x00 };
515 const static unsigned char packet_recv_pick_up[] =
516 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x04 };
517 const static unsigned char packet_recv_hangup[] =
518 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x03 };
519 const static unsigned char packet_recv_r2[] = { 0x00, 0x00, 0x00, 0x13, 0x96, 0x03, 0x03 };
521 /*! TransportAdapter */
522 const static unsigned char packet_recv_resume_connection_with_server[] =
523 { 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
524 const static unsigned char packet_recv_mac_addr[] =
525 { 0xff, 0xff, 0xff, 0xff, 0x9a, 0x0d, 0x07, 0x31, 0x38 /*MacAddr */ };
527 const static unsigned char packet_send_date_time3[] =
528 { 0x11, 0x09, 0x02, 0x02, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07,
529 /*Minutes */ 0x08, 0x32
531 const static unsigned char packet_send_date_time[] =
532 { 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07, /*Minutes */
533 0x08, 0x32, 0x17, 0x04, 0x24, 0x07, 0x19,
534 0x04, 0x07, 0x00, 0x19, 0x05, 0x09, 0x3e, 0x0f, 0x16, 0x05, 0x00, 0x80, 0x00, 0x1e,
535 0x05, 0x12, 0x00, 0x78
538 const static unsigned char packet_send_no_ring[] =
539 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00 };
540 const static unsigned char packet_send_s4[] =
541 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff,
542 0x16, 0x05, 0x1c, 0x00, 0x00, 0x17, 0x05,
543 0x0b, 0x00, 0x00, 0x19, 0x04, 0x00, 0x00, 0x19, 0x04, 0x00, 0x08, 0x19, 0x04, 0x00,
544 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
545 0x31, 0x00, 0x00, 0x16, 0x05, 0x04, 0x00, 0x00
547 const static unsigned char packet_send_call[] =
548 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf,
549 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16, 0x0a, 0x38, 0x00, 0x12, 0xca, 0x03,
550 0xc0, 0xc3, 0xc5, 0x16, 0x16, 0x30, 0x00,
551 0x00, /*codec */ 0x12, 0x12, /* frames per packet */ 0x01, 0x5c, 0x00, /*port RTP */
552 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41,
553 /*port RTP */ 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41, /* IP Address */ 0x0a, 0x01,
556 const static unsigned char packet_send_stream_based_tone_off[] =
557 { 0x16, 0x05, 0x1c, 0x00, 0x00 };
559 /* const static unsigned char packet_send_Mute[] = { 0x16, 0x05, 0x04, 0x00, 0x00 };
560 const static unsigned char packet_send_CloseAudioStreamRX[] = { 0x16, 0x05, 0x31, 0x00, 0xff };
561 const static unsigned char packet_send_CloseAudioStreamTX[] = { 0x16, 0x05, 0x31, 0xff, 0x00 };*/
562 const static unsigned char packet_send_stream_based_tone_on[] =
563 { 0x16, 0x06, 0x1b, 0x00, 0x00, 0x05 };
564 const static unsigned char packet_send_stream_based_tone_single_freq[] =
565 { 0x16, 0x06, 0x1d, 0x00, 0x01, 0xb8 };
566 const static unsigned char packet_send_stream_based_tone_dial_freq[] =
567 { 0x16, 0x08, 0x1d, 0x00, 0x01, 0xb8, 0x01, 0x5e };
568 const static unsigned char packet_send_select_output[] =
569 { 0x16, 0x06, 0x32, 0xc0, 0x01, 0x00 };
570 const static unsigned char packet_send_ring[] =
571 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16,
572 0x04, 0x1a, 0x01, 0x16, 0x05, 0x12, 0x13 /* Ring type 10 to 17 */ , 0x18, 0x16, 0x04, 0x18, /* volume 00, 10, 20... */
573 0x20, 0x16, 0x04, 0x10, 0x00
575 const static unsigned char packet_send_end_call[] =
576 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x31, 0x00, 0x00, 0x19, 0x04, 0x00,
577 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
578 0x04, 0x00, 0x00, 0x16, 0x04, 0x37, 0x10
580 const static unsigned char packet_send_s9[] =
581 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x19, 0x04, 0x00, 0x10, 0x16, 0x05, 0x1c, 0x00,
583 const static unsigned char packet_send_rtp_packet_size[] =
584 { 0x16, 0x08, 0x38, 0x00, 0x00, 0xe0, 0x00, 0xa0 };
585 const static unsigned char packet_send_jitter_buffer_conf[] =
586 { 0x16, 0x0e, 0x3a, 0x00, /* jitter */ 0x02, /* high water mark */ 0x04, 0x00, 0x00,
587 /* early packet resync 2 bytes */ 0x3e, 0x80,
588 0x00, 0x00, /* late packet resync 2 bytes */ 0x3e, 0x80
591 /* Duration in ms div 2 (0x20 = 64ms, 0x08 = 16ms)
592 static unsigned char packet_send_StreamBasedToneCad[] =
593 { 0x16, 0x0a, 0x1e, 0x00, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x2b }; */
594 const static unsigned char packet_send_open_audio_stream_rx[] =
595 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
596 0x0e, 0x01, /* Port */ 0x14, 0x50, 0x00,
597 0x00, /* Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
599 const static unsigned char packet_send_open_audio_stream_tx[] =
600 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
601 0x0e, 0x01, /* Local port */ 0x14, 0x50,
602 0x00, 0x00, /* Rmt Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
605 const static unsigned char packet_send_open_audio_stream_rx3[] =
606 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
607 0x06, 0x81, /* RTP Port */ 0x14, 0x50,
608 /* RTCP Port */ 0x14,
609 0x51, /* RTP Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00, /* Dest IP */ 0x0a, 0x93,
612 const static unsigned char packet_send_open_audio_stream_tx3[] =
613 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
614 0x06, 0x81, /* RTP Local port */ 0x14, 0x50,
615 /* RTCP Port */ 0x00, 0x00, /* RTP Rmt Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00,
616 /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
619 const static unsigned char packet_send_arrow[] = { 0x17, 0x04, 0x04, 0x00 };
620 const static unsigned char packet_send_blink_cursor[] = { 0x17, 0x04, 0x10, 0x86 };
621 const static unsigned char packet_send_date_time2[] = { 0x17, 0x04, 0x17, 0x3d, 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */
622 0x06, /*Hour */ 0x07, /*Minutes */ 0x08, 0x32
624 const static unsigned char packet_send_Contrast[] =
625 { 0x17, 0x04, 0x24, /*Contrast */ 0x08 };
626 const static unsigned char packet_send_StartTimer[] =
627 { 0x17, 0x05, 0x0b, 0x05, 0x00, 0x17, 0x08, 0x16, /* Text */ 0x44, 0x75, 0x72, 0xe9,
629 const static unsigned char packet_send_stop_timer[] = { 0x17, 0x05, 0x0b, 0x02, 0x00 };
630 const static unsigned char packet_send_icon[] = { 0x17, 0x05, 0x14, /*pos */ 0x00, /*icon */ 0x25 }; /* display an icon in front of the text zone */
631 const static unsigned char packet_send_S7[] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 };
632 const static unsigned char packet_send_set_pos_cursor[] =
633 { 0x17, 0x06, 0x10, 0x81, 0x04, /*pos */ 0x20 };
635 /*static unsigned char packet_send_MonthLabelsDownload[] =
636 { 0x17, 0x0a, 0x15, Month (3 char) 0x46, 0x65, 0x62, 0x4d, 0xe4, 0x72, 0x20 }; */
637 const static unsigned char packet_send_favorite[] =
638 { 0x17, 0x0f, 0x19, 0x10, /*pos */ 0x01, /*name */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
639 0x20, 0x20, 0x20, 0x20, /*end_name */ 0x19,
640 0x05, 0x0f, /*pos */ 0x01, /*icone */ 0x00
642 const static unsigned char packet_send_title[] =
643 { 0x17, 0x10, 0x19, 0x02, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
644 0x20, 0x20, 0x20, 0x20 /*end_text */ };
645 const static unsigned char packet_send_text[] =
646 { 0x17, 0x1e, 0x1b, 0x04, /*pos */ 0x00, /*inverse */ 0x25, /*text */ 0x20, 0x20,
647 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
648 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
649 /*end_text */ 0x17, 0x04, 0x10, 0x87
651 const static unsigned char packet_send_status[] =
652 { 0x17, 0x20, 0x19, 0x08, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
653 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
654 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 /*end_text */
656 const static unsigned char packet_send_status2[] =
657 { 0x17, 0x0b, 0x19, /* pos [08|28|48|68] */ 0x00, /* text */ 0x20, 0x20, 0x20, 0x20,
658 0x20, 0x20, 0x20 /* end_text */ };
660 const static unsigned char packet_send_led_update[] = { 0x19, 0x04, 0x00, 0x00 };
662 const static unsigned char packet_send_query_basic_manager_04[] = { 0x1a, 0x04, 0x01, 0x04 };
663 const static unsigned char packet_send_query_mac_address[] = { 0x1a, 0x04, 0x01, 0x08 };
664 const static unsigned char packet_send_query_basic_manager_10[] = { 0x1a, 0x04, 0x01, 0x10 };
665 const static unsigned char packet_send_S1[] = { 0x1a, 0x07, 0x07, 0x00, 0x00, 0x00, 0x13 };
667 static unsigned char packet_send_ping[] =
668 { 0x1e, 0x05, 0x12, 0x00, /*Watchdog timer */ 0x78 };
670 #define BUFFSEND unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }
672 const static char tdesc[] = "UNISTIM Channel Driver";
673 const static char type[] = "USTM";
676 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state);
677 static int load_module(void);
678 static int reload(void);
679 static int unload_module(void);
680 static int reload_config(void);
681 static void show_main_page(struct unistimsession *pte);
682 static struct ast_channel *unistim_request(const char *type, int format,
683 void *data, int *cause);
684 static int unistim_call(struct ast_channel *ast, char *dest, int timeout);
685 static int unistim_hangup(struct ast_channel *ast);
686 static int unistim_answer(struct ast_channel *ast);
687 static struct ast_frame *unistim_read(struct ast_channel *ast);
688 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame);
689 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
691 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
692 static int unistim_senddigit_begin(struct ast_channel *ast, char digit);
693 static int unistim_senddigit_end(struct ast_channel *ast, char digit,
694 unsigned int duration);
695 static int unistim_sendtext(struct ast_channel *ast, const char *text);
697 static int write_entry_history(struct unistimsession *pte, FILE * f, char c,
699 static void change_callerid(struct unistimsession *pte, int type, char *callerid);
701 static const struct ast_channel_tech unistim_tech = {
703 .description = tdesc,
704 .capabilities = CAPABILITY,
705 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
706 .requester = unistim_request,
707 .call = unistim_call,
708 .hangup = unistim_hangup,
709 .answer = unistim_answer,
710 .read = unistim_read,
711 .write = unistim_write,
712 .indicate = unistim_indicate,
713 .fixup = unistim_fixup,
714 .send_digit_begin = unistim_senddigit_begin,
715 .send_digit_end = unistim_senddigit_end,
716 .send_text = unistim_sendtext,
717 /* .bridge = ast_rtp_bridge, */
720 static void display_last_error(const char *sz_msg)
726 /* Display the error message */
727 ast_log(LOG_WARNING, "%s %s : (%u) %s\n", ctime(&cur_time), sz_msg, errno,
731 static unsigned int get_tick_count(void)
733 struct timeval tv = ast_tvnow();
735 return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
738 /* Send data to a phone without retransmit nor buffering */
739 static void send_raw_client(int size, unsigned char *data, struct sockaddr_in *addr_to,
740 const struct sockaddr_in *addr_ourip)
743 struct iovec msg_iov;
745 char buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
746 struct cmsghdr *ip_msg = (struct cmsghdr *) buffer;
747 struct in_pktinfo *pki = (struct in_pktinfo *) CMSG_DATA(ip_msg);
749 msg_iov.iov_base = data;
750 msg_iov.iov_len = size;
752 msg.msg_name = addr_to; /* optional address */
753 msg.msg_namelen = sizeof(struct sockaddr_in); /* size of address */
754 msg.msg_iov = &msg_iov; /* scatter/gather array */
755 msg.msg_iovlen = 1; /* # elements in msg_iov */
756 msg.msg_control = ip_msg; /* ancillary data */
757 msg.msg_controllen = sizeof(buffer); /* ancillary data buffer len */
758 msg.msg_flags = 0; /* flags on received message */
760 ip_msg->cmsg_len = CMSG_LEN(sizeof(*pki));
761 ip_msg->cmsg_level = IPPROTO_IP;
762 ip_msg->cmsg_type = IP_PKTINFO;
763 pki->ipi_ifindex = 0; /* Interface index, 0 = use interface specified in routing table */
764 pki->ipi_spec_dst.s_addr = addr_ourip->sin_addr.s_addr; /* Local address */
765 /* pki->ipi_addr = ; Header Destination address - ignored by kernel */
770 char iabuf[INET_ADDRSTRLEN];
771 char iabuf2[INET_ADDRSTRLEN];
772 ast_verbose("\n**> From %s sending %d bytes to %s ***\n",
773 ast_inet_ntoa(addr_ourip->sin_addr), (int) size,
774 ast_inet_ntoa(addr_to->sin_addr));
775 for (tmp = 0; tmp < size; tmp++)
776 ast_verbose("%.2x ", (unsigned char) data[tmp]);
777 ast_verbose("\n******************************************\n");
782 if (sendmsg(unistimsock, &msg, 0) == -1)
783 display_last_error("Error sending datas");
785 if (sendto(unistimsock, data, size, 0, (struct sockaddr *) addr_to, sizeof(*addr_to))
787 display_last_error("Error sending datas");
791 static void send_client(int size, const unsigned char *data, struct unistimsession *pte)
795 unsigned short *sdata = (unsigned short *) data;
797 ast_mutex_lock(&pte->lock);
798 buf_pos = pte->last_buf_available;
800 if (buf_pos >= MAX_BUF_NUMBER) {
801 ast_log(LOG_WARNING, "Error : send queue overflow\n");
802 ast_mutex_unlock(&pte->lock);
805 sdata[1] = ntohs(++(pte->seq_server));
806 pte->wsabufsend[buf_pos].len = size;
807 memcpy(pte->wsabufsend[buf_pos].buf, data, size);
809 tick = get_tick_count();
810 pte->timeout = tick + RETRANSMIT_TIMER;
812 /*#ifdef DUMP_PACKET */
813 if ((unistimdebug) && (option_verbose > 5)) {
814 ast_verbose("Sending datas with seq #0x%.4x Using slot #%d :\n", pte->seq_server,
818 send_raw_client(pte->wsabufsend[buf_pos].len, pte->wsabufsend[buf_pos].buf, &(pte->sin),
820 pte->last_buf_available++;
821 ast_mutex_unlock(&pte->lock);
824 static void send_ping(struct unistimsession *pte)
827 if ((unistimdebug) && (option_verbose > 5))
828 ast_verbose("Sending ping\n");
829 pte->tick_next_ping = get_tick_count() + unistim_keepalive;
830 memcpy(buffsend + SIZE_HEADER, packet_send_ping, sizeof(packet_send_ping));
831 send_client(SIZE_HEADER + sizeof(packet_send_ping), buffsend, pte);
834 static int get_to_address(int fd, struct sockaddr_in *toAddr)
842 struct in_addr address;
845 /* Zero out the structures before we use them */
846 /* This sets several key values to NULL */
847 memset(&msg, 0, sizeof(msg));
848 memset(&ip_msg, 0, sizeof(ip_msg));
850 /* Initialize the message structure */
851 msg.msg_control = &ip_msg;
852 msg.msg_controllen = sizeof(ip_msg);
853 /* Get info about the incoming packet */
854 err = recvmsg(fd, &msg, MSG_PEEK);
856 ast_log(LOG_WARNING, "recvmsg returned an error: %s\n", strerror(errno));
857 memcpy(&toAddr->sin_addr, &ip_msg.address, sizeof(struct in_addr));
860 memcpy(&toAddr, &public_ip, sizeof(&toAddr));
865 /* Allocate memory & initialize structures for a new phone */
866 /* addr_from : ip address of the phone */
867 static struct unistimsession *create_client(const struct sockaddr_in *addr_from)
870 struct unistimsession *s;
872 if (!(s = ast_calloc(1, sizeof(*s))))
875 memcpy(&s->sin, addr_from, sizeof(struct sockaddr_in));
876 get_to_address(unistimsock, &s->sout);
879 ("Creating a new entry for the phone from %s received via server ip %s\n",
880 ast_inet_ntoa(addr_from->sin_addr), ast_inet_ntoa(s->sout.sin_addr));
882 ast_mutex_init(&s->lock);
883 ast_mutex_lock(&sessionlock);
887 s->timeout = get_tick_count() + RETRANSMIT_TIMER;
888 s->seq_phone = (short) 0x0000;
889 s->seq_server = (short) 0x0000;
890 s->last_seq_ack = (short) 0x000;
891 s->last_buf_available = 0;
892 s->nb_retransmit = 0;
893 s->state = STATE_INIT;
894 s->tick_next_ping = get_tick_count() + unistim_keepalive;
895 /* Initialize struct wsabuf */
896 for (tmp = 0; tmp < MAX_BUF_NUMBER; tmp++) {
897 s->wsabufsend[tmp].buf = s->buf[tmp];
899 ast_mutex_unlock(&sessionlock);
903 static void send_end_call(struct unistimsession *pte)
907 ast_verbose("Sending end call\n");
908 memcpy(buffsend + SIZE_HEADER, packet_send_end_call, sizeof(packet_send_end_call));
909 send_client(SIZE_HEADER + sizeof(packet_send_end_call), buffsend, pte);
912 static void set_ping_timer(struct unistimsession *pte)
914 unsigned int tick = 0; /* XXX what is this for, anyways */
916 pte->timeout = pte->tick_next_ping;
917 DEBUG_TIMER("tick = %u next ping at %u tick\n", tick, pte->timeout);
921 /* Checking if our send queue is empty,
922 * if true, setting up a timer for keepalive */
923 static void check_send_queue(struct unistimsession *pte)
925 /* Check if our send queue contained only one element */
926 if (pte->last_buf_available == 1) {
927 if ((unistimdebug) && (option_verbose > 5))
928 ast_verbose("Our single packet was ACKed.\n");
929 pte->last_buf_available--;
933 /* Check if this ACK catch up our latest packet */
934 else if (pte->last_seq_ack + 1 == pte->seq_server + 1) {
935 if ((unistimdebug) && (option_verbose > 5))
936 ast_verbose("Our send queue is completely ACKed.\n");
937 pte->last_buf_available = 0; /* Purge the send queue */
941 if ((unistimdebug) && (option_verbose > 5))
942 ast_verbose("We still have packets in our send queue\n");
946 static void send_start_timer(struct unistimsession *pte)
950 ast_verbose("Sending start timer\n");
951 memcpy(buffsend + SIZE_HEADER, packet_send_StartTimer, sizeof(packet_send_StartTimer));
952 send_client(SIZE_HEADER + sizeof(packet_send_StartTimer), buffsend, pte);
955 static void send_stop_timer(struct unistimsession *pte)
959 ast_verbose("Sending stop timer\n");
960 memcpy(buffsend + SIZE_HEADER, packet_send_stop_timer, sizeof(packet_send_stop_timer));
961 send_client(SIZE_HEADER + sizeof(packet_send_stop_timer), buffsend, pte);
964 static void Sendicon(unsigned char pos, unsigned char status, struct unistimsession *pte)
968 ast_verbose("Sending icon pos %d with status 0x%.2x\n", pos, status);
969 memcpy(buffsend + SIZE_HEADER, packet_send_icon, sizeof(packet_send_icon));
971 buffsend[10] = status;
972 send_client(SIZE_HEADER + sizeof(packet_send_icon), buffsend, pte);
975 static void send_tone(struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
980 ast_verbose("Sending Stream Based Tone Off\n");
981 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_off,
982 sizeof(packet_send_stream_based_tone_off));
983 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_off), buffsend, pte);
986 /* Since most of the world use a continuous tone, it's useless
988 ast_verbose ("Sending Stream Based Tone Cadence Download\n");
989 memcpy (buffsend + SIZE_HEADER, packet_send_StreamBasedToneCad, sizeof (packet_send_StreamBasedToneCad));
990 send_client (SIZE_HEADER + sizeof (packet_send_StreamBasedToneCad), buffsend, pte); */
992 ast_verbose("Sending Stream Based Tone Frequency Component List Download %d %d\n",
996 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_single_freq,
997 sizeof(packet_send_stream_based_tone_single_freq));
998 buffsend[10] = (tone1 & 0xff00) >> 8;
999 buffsend[11] = (tone1 & 0x00ff);
1000 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_single_freq), buffsend,
1004 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dial_freq,
1005 sizeof(packet_send_stream_based_tone_dial_freq));
1006 buffsend[10] = (tone1 & 0xff00) >> 8;
1007 buffsend[11] = (tone1 & 0x00ff);
1008 buffsend[12] = (tone2 & 0xff00) >> 8;
1009 buffsend[13] = (tone2 & 0x00ff);
1010 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_dial_freq), buffsend,
1015 ast_verbose("Sending Stream Based Tone On\n");
1016 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_on,
1017 sizeof(packet_send_stream_based_tone_on));
1018 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_on), buffsend, pte);
1021 /* Positions for favorites
1022 |--------------------|
1028 /* status (icons) : 00 = nothing, 2x/3x = see parser.h, 4x/5x = blink fast, 6x/7x = blink slow */
1030 send_favorite(unsigned char pos, unsigned char status, struct unistimsession *pte,
1037 ast_verbose("Sending favorite pos %d with status 0x%.2x\n", pos, status);
1038 memcpy(buffsend + SIZE_HEADER, packet_send_favorite, sizeof(packet_send_favorite));
1041 buffsend[25] = status;
1043 if (i > FAV_MAX_LENGTH)
1045 memcpy(buffsend + FAV_MAX_LENGTH + 1, text, i);
1046 send_client(SIZE_HEADER + sizeof(packet_send_favorite), buffsend, pte);
1049 static void refresh_all_favorite(struct unistimsession *pte)
1054 ast_verbose("Refreshing all favorite\n");
1055 for (i = 0; i < 6; i++) {
1056 if ((pte->device->softkeyicon[i] <= FAV_ICON_HEADPHONES_ONHOLD) &&
1057 (pte->device->softkeylinepos != i))
1058 send_favorite((unsigned char) i, pte->device->softkeyicon[i] + 1, pte,
1059 pte->device->softkeylabel[i]);
1061 send_favorite((unsigned char) i, pte->device->softkeyicon[i], pte,
1062 pte->device->softkeylabel[i]);
1067 /* Change the status for this phone (pte) and update for each phones where pte is bookmarked
1068 * use FAV_ICON_*_BLACK constant in status parameters */
1069 static void change_favorite_icon(struct unistimsession *pte, unsigned char status)
1071 struct unistim_device *d = devices;
1073 /* Update the current phone */
1074 if (pte->state != STATE_CLEANING)
1075 send_favorite(pte->device->softkeylinepos, status, pte,
1076 pte->device->softkeylabel[pte->device->softkeylinepos]);
1077 /* Notify other phones if we're in their bookmark */
1079 for (i = 0; i < 6; i++) {
1080 if (d->sp[i] == pte->device) { /* It's us ? */
1081 if (d->softkeyicon[i] != status) { /* Avoid resending the same icon */
1082 d->softkeyicon[i] = status;
1084 send_favorite(i, status + 1, d->session, d->softkeylabel[i]);
1092 static int RegisterExtension(const struct unistimsession *pte)
1095 ast_verbose("Trying to register extension '%s' into context '%s' to %s\n",
1096 pte->device->extension_number, pte->device->lines->context,
1097 pte->device->lines->fullname);
1098 return ast_add_extension(pte->device->lines->context, 0,
1099 pte->device->extension_number, 1, NULL, NULL, "Dial",
1100 pte->device->lines->fullname, 0, "Unistim");
1103 static int UnregisterExtension(const struct unistimsession *pte)
1106 ast_verbose("Trying to unregister extension '%s' context '%s'\n",
1107 pte->device->extension_number, pte->device->lines->context);
1108 return ast_context_remove_extension(pte->device->lines->context,
1109 pte->device->extension_number, 1, "Unistim");
1112 /* Free memory allocated for a phone */
1113 static void close_client(struct unistimsession *s)
1115 struct unistim_subchannel *sub;
1116 struct unistimsession *cur, *prev = NULL;
1117 ast_mutex_lock(&sessionlock);
1119 /* Looking for the session in the linked chain */
1126 if (cur) { /* Session found ? */
1127 if (cur->device) { /* This session was registred ? */
1128 s->state = STATE_CLEANING;
1130 ast_verbose("close_client session %p device %p lines %p sub %p\n",
1131 s, s->device, s->device->lines,
1132 s->device->lines->subs[SUB_REAL]);
1133 change_favorite_icon(s, FAV_ICON_NONE);
1134 sub = s->device->lines->subs[SUB_REAL];
1136 if (sub->owner) { /* Call in progress ? */
1138 ast_verbose("Aborting call\n");
1139 ast_queue_hangup(sub->owner);
1142 ast_log(LOG_WARNING, "Freeing a client with no subchannel !\n");
1143 if (!ast_strlen_zero(s->device->extension_number))
1144 UnregisterExtension(s);
1145 cur->device->session = NULL;
1148 ast_verbose("Freeing an unregistered client\n");
1151 prev->next = cur->next;
1153 sessions = cur->next;
1154 ast_mutex_destroy(&s->lock);
1157 ast_log(LOG_WARNING, "Trying to delete non-existant session %p?\n", s);
1158 ast_mutex_unlock(&sessionlock);
1162 /* Return 1 if the session chained link was modified */
1163 static int send_retransmit(struct unistimsession *pte)
1167 ast_mutex_lock(&pte->lock);
1168 if (++pte->nb_retransmit >= NB_MAX_RETRANSMIT) {
1170 ast_verbose("Too many retransmit - freeing client\n");
1171 ast_mutex_unlock(&pte->lock);
1175 pte->timeout = get_tick_count() + RETRANSMIT_TIMER;
1177 for (i = pte->last_buf_available - (pte->seq_server - pte->last_seq_ack);
1178 i < pte->last_buf_available; i++) {
1180 ast_log(LOG_WARNING,
1181 "Asked to retransmit an ACKed slot ! last_buf_available=%d, seq_server = #0x%.4x last_seq_ack = #0x%.4x\n",
1182 pte->last_buf_available, pte->seq_server, pte->last_seq_ack);
1187 unsigned short *sbuf = (unsigned short *) pte->wsabufsend[i].buf;
1190 seq = ntohs(sbuf[1]);
1191 ast_verbose("Retransmit slot #%d (seq=#0x%.4x), last ack was #0x%.4x\n", i,
1192 seq, pte->last_seq_ack);
1194 send_raw_client(pte->wsabufsend[i].len, pte->wsabufsend[i].buf, &pte->sin,
1197 ast_mutex_unlock(&pte->lock);
1201 /* inverse : TEXT_INVERSE : yes, TEXT_NORMAL : no */
1203 send_text(unsigned char pos, unsigned char inverse, struct unistimsession *pte,
1209 ast_verbose("Sending text at pos %d, inverse flag %d\n", pos, inverse);
1210 memcpy(buffsend + SIZE_HEADER, packet_send_text, sizeof(packet_send_text));
1212 buffsend[11] = inverse;
1214 if (i > TEXT_LENGTH_MAX)
1215 i = TEXT_LENGTH_MAX;
1216 memcpy(buffsend + 12, text, i);
1217 send_client(SIZE_HEADER + sizeof(packet_send_text), buffsend, pte);
1220 static void send_text_status(struct unistimsession *pte, const char *text)
1225 ast_verbose("Sending status text\n");
1227 if (pte->device->status_method == 1) { /* For new firmware and i2050 soft phone */
1228 int n = strlen(text);
1229 /* Must send individual button separately */
1231 for (i = 0, j = 0; i < 4; i++, j += 7) {
1232 int pos = 0x08 + (i * 0x20);
1233 memcpy(buffsend + SIZE_HEADER, packet_send_status2,
1234 sizeof(packet_send_status2));
1237 memcpy(buffsend + 10, (j < n) ? (text + j) : " ", 7);
1238 send_client(SIZE_HEADER + sizeof(packet_send_status2), buffsend, pte);
1245 memcpy(buffsend + SIZE_HEADER, packet_send_status, sizeof(packet_send_status));
1247 if (i > STATUS_LENGTH_MAX)
1248 i = STATUS_LENGTH_MAX;
1249 memcpy(buffsend + 10, text, i);
1250 send_client(SIZE_HEADER + sizeof(packet_send_status), buffsend, pte);
1254 /* led values in hexa : 0 = bar off, 1 = bar on, 2 = bar 1s on/1s off, 3 = bar 2.5s on/0.5s off
1255 * 4 = bar 0.6s on/0.3s off, 5 = bar 0.5s on/0.5s off, 6 = bar 2s on/0.5s off
1256 * 7 = bar off, 8 = speaker off, 9 = speaker on, 10 = headphone off, 11 = headphone on
1257 * 18 = mute off, 19 mute on */
1258 static void send_led_update(struct unistimsession *pte, unsigned char led)
1262 ast_verbose("Sending led_update (%x)\n", led);
1263 memcpy(buffsend + SIZE_HEADER, packet_send_led_update, sizeof(packet_send_led_update));
1265 send_client(SIZE_HEADER + sizeof(packet_send_led_update), buffsend, pte);
1268 /* output = OUTPUT_HANDSET, OUTPUT_HEADPHONE or OUTPUT_SPEAKER
1269 * volume = VOLUME_LOW, VOLUME_NORMAL, VOLUME_INSANELY_LOUD
1270 * mute = MUTE_OFF, MUTE_ON */
1272 send_select_output(struct unistimsession *pte, unsigned char output, unsigned char volume,
1277 ast_verbose("Sending select output packet output=%x volume=%x mute=%x\n", output,
1279 memcpy(buffsend + SIZE_HEADER, packet_send_select_output,
1280 sizeof(packet_send_select_output));
1281 buffsend[9] = output;
1282 if (output == OUTPUT_SPEAKER)
1283 volume = VOLUME_LOW_SPEAKER;
1285 volume = VOLUME_LOW;
1286 buffsend[10] = volume;
1287 if (mute == MUTE_ON_DISCRET)
1288 buffsend[11] = MUTE_ON;
1290 buffsend[11] = mute;
1291 send_client(SIZE_HEADER + sizeof(packet_send_select_output), buffsend, pte);
1292 if (mute == MUTE_OFF)
1293 send_led_update(pte, 0x18);
1294 else if (mute == MUTE_ON)
1295 send_led_update(pte, 0x19);
1296 pte->device->mute = mute;
1297 if (output == OUTPUT_HANDSET) {
1298 if (mute == MUTE_ON)
1299 change_favorite_icon(pte, FAV_ICON_ONHOLD_BLACK);
1301 change_favorite_icon(pte, FAV_ICON_OFFHOOK_BLACK);
1302 send_led_update(pte, 0x08);
1303 send_led_update(pte, 0x10);
1304 } else if (output == OUTPUT_HEADPHONE) {
1305 if (mute == MUTE_ON)
1306 change_favorite_icon(pte, FAV_ICON_HEADPHONES_ONHOLD);
1308 change_favorite_icon(pte, FAV_ICON_HEADPHONES);
1309 send_led_update(pte, 0x08);
1310 send_led_update(pte, 0x11);
1311 } else if (output == OUTPUT_SPEAKER) {
1312 send_led_update(pte, 0x10);
1313 send_led_update(pte, 0x09);
1314 if (pte->device->receiver_state == STATE_OFFHOOK) {
1315 if (mute == MUTE_ON)
1316 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1318 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOOK_BLACK);
1320 if (mute == MUTE_ON)
1321 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1323 change_favorite_icon(pte, FAV_ICON_SPEAKER_OFFHOOK_BLACK);
1326 ast_log(LOG_WARNING, "Invalid ouput (%d)\n", output);
1327 if (output != pte->device->output)
1328 pte->device->previous_output = pte->device->output;
1329 pte->device->output = output;
1332 static void send_ring(struct unistimsession *pte, char volume, char style)
1336 ast_verbose("Sending ring packet\n");
1337 memcpy(buffsend + SIZE_HEADER, packet_send_ring, sizeof(packet_send_ring));
1338 buffsend[24] = style + 0x10;
1339 buffsend[29] = volume * 0x10;
1340 send_client(SIZE_HEADER + sizeof(packet_send_ring), buffsend, pte);
1343 static void send_no_ring(struct unistimsession *pte)
1347 ast_verbose("Sending no ring packet\n");
1348 memcpy(buffsend + SIZE_HEADER, packet_send_no_ring, sizeof(packet_send_no_ring));
1349 send_client(SIZE_HEADER + sizeof(packet_send_no_ring), buffsend, pte);
1352 static void send_texttitle(struct unistimsession *pte, const char *text)
1357 ast_verbose("Sending title text\n");
1358 memcpy(buffsend + SIZE_HEADER, packet_send_title, sizeof(packet_send_title));
1362 memcpy(buffsend + 10, text, i);
1363 send_client(SIZE_HEADER + sizeof(packet_send_title), buffsend, pte);
1367 static void send_date_time(struct unistimsession *pte)
1370 struct timeval tv = ast_tvnow();
1371 struct ast_tm atm = { 0, };
1374 ast_verbose("Sending Time & Date\n");
1375 memcpy(buffsend + SIZE_HEADER, packet_send_date_time, sizeof(packet_send_date_time));
1376 ast_localtime(&tv, &atm, NULL);
1377 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1378 buffsend[11] = (unsigned char) atm.tm_mday;
1379 buffsend[12] = (unsigned char) atm.tm_hour;
1380 buffsend[13] = (unsigned char) atm.tm_min;
1381 send_client(SIZE_HEADER + sizeof(packet_send_date_time), buffsend, pte);
1384 static void send_date_time2(struct unistimsession *pte)
1387 struct timeval tv = ast_tvnow();
1388 struct ast_tm atm = { 0, };
1391 ast_verbose("Sending Time & Date #2\n");
1392 memcpy(buffsend + SIZE_HEADER, packet_send_date_time2, sizeof(packet_send_date_time2));
1393 ast_localtime(&tv, &atm, NULL);
1395 buffsend[9] = pte->device->datetimeformat;
1398 buffsend[14] = (unsigned char) atm.tm_mon + 1;
1399 buffsend[15] = (unsigned char) atm.tm_mday;
1400 buffsend[16] = (unsigned char) atm.tm_hour;
1401 buffsend[17] = (unsigned char) atm.tm_min;
1402 send_client(SIZE_HEADER + sizeof(packet_send_date_time2), buffsend, pte);
1405 static void send_date_time3(struct unistimsession *pte)
1408 struct timeval tv = ast_tvnow();
1409 struct ast_tm atm = { 0, };
1412 ast_verbose("Sending Time & Date #3\n");
1413 memcpy(buffsend + SIZE_HEADER, packet_send_date_time3, sizeof(packet_send_date_time3));
1414 ast_localtime(&tv, &atm, NULL);
1415 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1416 buffsend[11] = (unsigned char) atm.tm_mday;
1417 buffsend[12] = (unsigned char) atm.tm_hour;
1418 buffsend[13] = (unsigned char) atm.tm_min;
1419 send_client(SIZE_HEADER + sizeof(packet_send_date_time3), buffsend, pte);
1422 static void send_blink_cursor(struct unistimsession *pte)
1426 ast_verbose("Sending set blink\n");
1427 memcpy(buffsend + SIZE_HEADER, packet_send_blink_cursor, sizeof(packet_send_blink_cursor));
1428 send_client(SIZE_HEADER + sizeof(packet_send_blink_cursor), buffsend, pte);
1432 /* pos : 0xab (a=0/2/4 = line ; b = row) */
1433 static void send_cursor_pos(struct unistimsession *pte, unsigned char pos)
1437 ast_verbose("Sending set cursor position\n");
1438 memcpy(buffsend + SIZE_HEADER, packet_send_set_pos_cursor,
1439 sizeof(packet_send_set_pos_cursor));
1441 send_client(SIZE_HEADER + sizeof(packet_send_set_pos_cursor), buffsend, pte);
1445 static void rcv_resume_connection_with_server(struct unistimsession *pte)
1449 ast_verbose("ResumeConnectionWithServer received\n");
1451 ast_verbose("Sending packet_send_query_mac_address\n");
1452 memcpy(buffsend + SIZE_HEADER, packet_send_query_mac_address,
1453 sizeof(packet_send_query_mac_address));
1454 send_client(SIZE_HEADER + sizeof(packet_send_query_mac_address), buffsend, pte);
1458 static int unistim_register(struct unistimsession *s)
1460 struct unistim_device *d;
1462 ast_mutex_lock(&devicelock);
1465 if (!strcasecmp(s->macaddr, d->id)) {
1466 /* XXX Deal with IP authentication */
1469 d->codec_number = DEFAULT_CODEC;
1472 d->receiver_state = STATE_ONHOOK;
1477 ast_mutex_unlock(&devicelock);
1485 static int alloc_sub(struct unistim_line *l, int x)
1487 struct unistim_subchannel *sub;
1488 if (!(sub = ast_calloc(1, sizeof(*sub))))
1492 ast_verbose(VERBOSE_PREFIX_3
1493 "Allocating UNISTIM subchannel #%d on %s@%s ptr=%p\n", x, l->name,
1494 l->parent->name, sub);
1498 ast_mutex_init(&sub->lock);
1502 static int unalloc_sub(struct unistim_line *p, int x)
1505 ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name,
1510 ast_debug(1, "Released sub %d of channel %s@%s\n", x, p->name,
1512 ast_mutex_destroy(&p->lock);
1513 ast_free(p->subs[x]);
1518 static void rcv_mac_addr(struct unistimsession *pte, const unsigned char *buf)
1525 ast_verbose("Mac Address received : ");
1526 for (tmp = 15; tmp < 15 + SIZE_HEADER; tmp++) {
1527 sprintf(&addrmac[i], "%.2x", (unsigned char) buf[tmp]);
1531 ast_verbose("%s\n", addrmac);
1532 strcpy(pte->macaddr, addrmac);
1533 res = unistim_register(pte);
1535 switch (autoprovisioning) {
1536 case AUTOPROVISIONING_NO:
1537 ast_log(LOG_WARNING, "No entry found for this phone : %s\n", addrmac);
1538 pte->state = STATE_AUTHDENY;
1540 case AUTOPROVISIONING_YES:
1542 struct unistim_device *d, *newd;
1543 struct unistim_line *newl;
1545 ast_verbose("New phone, autoprovisioning on\n");
1546 /* First : locate the [template] section */
1547 ast_mutex_lock(&devicelock);
1550 if (!strcasecmp(d->name, "template")) {
1551 /* Found, cloning this entry */
1552 if (!(newd = ast_malloc(sizeof(*newd)))) {
1553 ast_mutex_unlock(&devicelock);
1557 memcpy(newd, d, sizeof(*newd));
1558 if (!(newl = ast_malloc(sizeof(*newl)))) {
1560 ast_mutex_unlock(&devicelock);
1564 memcpy(newl, d->lines, sizeof(*newl));
1565 if (!alloc_sub(newl, SUB_REAL)) {
1568 ast_mutex_unlock(&devicelock);
1571 /* Ok, now updating some fields */
1572 ast_copy_string(newd->id, addrmac, sizeof(newd->id));
1573 ast_copy_string(newd->name, addrmac, sizeof(newd->name));
1574 if (newd->extension == EXTENSION_NONE)
1575 newd->extension = EXTENSION_ASK;
1577 newd->receiver_state = STATE_ONHOOK;
1578 newd->session = pte;
1579 newd->to_delete = -1;
1582 newl->parent = newd;
1583 strcpy(newl->name, d->lines->name);
1584 snprintf(d->lines->name, sizeof(d->lines->name), "%d",
1585 atoi(d->lines->name) + 1);
1586 snprintf(newl->fullname, sizeof(newl->fullname), "USTM/%s@%s",
1587 newl->name, newd->name);
1588 /* Go to the end of the linked chain */
1598 ast_mutex_unlock(&devicelock);
1600 ast_log(LOG_WARNING, "No entry [template] found in unistim.conf\n");
1601 pte->state = STATE_AUTHDENY;
1605 case AUTOPROVISIONING_TN:
1606 pte->state = STATE_AUTHDENY;
1608 case AUTOPROVISIONING_DB:
1609 ast_log(LOG_WARNING,
1610 "Autoprovisioning with database is not yet functional\n");
1613 ast_log(LOG_WARNING, "Internal error : unknown autoprovisioning value = %d\n",
1617 if (pte->state != STATE_AUTHDENY) {
1618 if (option_verbose > 2)
1619 ast_verbose(VERBOSE_PREFIX_3 "Device '%s' successfuly registered\n",
1621 switch (pte->device->extension) {
1622 case EXTENSION_NONE:
1623 pte->state = STATE_MAINPAGE;
1626 /* Checking if we already have an extension number */
1627 if (ast_strlen_zero(pte->device->extension_number))
1628 pte->state = STATE_EXTENSION;
1630 /* Yes, because of a phone reboot. We don't ask again for the TN */
1631 if (RegisterExtension(pte))
1632 pte->state = STATE_EXTENSION;
1634 pte->state = STATE_MAINPAGE;
1637 case EXTENSION_LINE:
1638 ast_copy_string(pte->device->extension_number, pte->device->lines->name,
1639 sizeof(pte->device->extension_number));
1640 if (RegisterExtension(pte))
1641 pte->state = STATE_EXTENSION;
1643 pte->state = STATE_MAINPAGE;
1646 /* If we are here, it's because of a phone reboot */
1647 pte->state = STATE_MAINPAGE;
1650 ast_log(LOG_WARNING, "Internal error, extension value unknown : %d\n",
1651 pte->device->extension);
1652 pte->state = STATE_AUTHDENY;
1656 if (pte->state == STATE_EXTENSION) {
1657 if (pte->device->extension != EXTENSION_TN)
1658 pte->device->extension = EXTENSION_ASK;
1659 pte->device->extension_number[0] = '\0';
1662 ast_verbose("\nSending S1\n");
1663 memcpy(buffsend + SIZE_HEADER, packet_send_S1, sizeof(packet_send_S1));
1664 send_client(SIZE_HEADER + sizeof(packet_send_S1), buffsend, pte);
1667 ast_verbose("Sending query_basic_manager_04\n");
1668 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_04,
1669 sizeof(packet_send_query_basic_manager_04));
1670 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_04), buffsend, pte);
1673 ast_verbose("Sending query_basic_manager_10\n");
1674 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_10,
1675 sizeof(packet_send_query_basic_manager_10));
1676 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_10), buffsend, pte);
1678 send_date_time(pte);
1682 static int write_entry_history(struct unistimsession *pte, FILE * f, char c, char *line1)
1684 if (fwrite(&c, 1, 1, f) != 1) {
1685 display_last_error("Unable to write history log header.");
1688 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
1689 display_last_error("Unable to write history entry - date.");
1692 if (fwrite(pte->device->lst_cid, TEXT_LENGTH_MAX, 1, f) != 1) {
1693 display_last_error("Unable to write history entry - callerid.");
1696 if (fwrite(pte->device->lst_cnm, TEXT_LENGTH_MAX, 1, f) != 1) {
1697 display_last_error("Unable to write history entry - callername.");
1703 static int write_history(struct unistimsession *pte, char way, char ismissed)
1705 char tmp[AST_CONFIG_MAX_PATH], tmp2[AST_CONFIG_MAX_PATH];
1706 char line1[TEXT_LENGTH_MAX + 1];
1707 char count = 0, *histbuf;
1710 struct timeval tv = ast_tvnow();
1711 struct ast_tm atm = { 0, };
1715 if (!pte->device->callhistory)
1717 if (strchr(pte->device->name, '/') || (pte->device->name[0] == '.')) {
1718 ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n",
1723 snprintf(tmp, sizeof(tmp), "%s/%s", (char *) ast_config_AST_LOG_DIR, USTM_LOG_DIR);
1724 if (ast_mkdir(tmp, 0770)) {
1725 if (errno != EEXIST) {
1726 display_last_error("Unable to create directory for history");
1731 ast_localtime(&tv, &atm, NULL);
1734 strcpy(tmp2, "Miss");
1736 strcpy(tmp2, "Fail");
1738 strcpy(tmp2, "Answ");
1739 snprintf(line1, sizeof(line1), "%04d/%02d/%02d %02d:%02d:%02d %s",
1740 atm.tm_year + 1900, atm.tm_mon + 1, atm.tm_mday, atm.tm_hour,
1741 atm.tm_min, atm.tm_sec, tmp2);
1743 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", (char *) ast_config_AST_LOG_DIR,
1744 USTM_LOG_DIR, pte->device->name, way);
1745 if ((f = fopen(tmp, "r"))) {
1746 struct stat bufstat;
1748 if (stat(tmp, &bufstat)) {
1749 display_last_error("Unable to stat history log.");
1753 size = 1 + (MAX_ENTRY_LOG * TEXT_LENGTH_MAX * 3);
1754 if (bufstat.st_size != size) {
1755 ast_log(LOG_WARNING,
1756 "History file %s has an incorrect size (%d instead of %d). It will be replaced by a new one.",
1757 tmp, (int) bufstat.st_size, size);
1764 /* If we can't open the log file, we create a brand new one */
1769 if ((errno != ENOENT) && (count == 0)) {
1770 display_last_error("Unable to open history log.");
1773 f = fopen(tmp, "w");
1775 display_last_error("Unable to create history log.");
1778 if (write_entry_history(pte, f, c, line1)) {
1782 memset(line1, ' ', TEXT_LENGTH_MAX);
1783 for (i = 3; i < MAX_ENTRY_LOG * 3; i++) {
1784 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
1785 display_last_error("Unable to write history entry - stuffing.");
1791 display_last_error("Unable to close history - creation.");
1794 /* We can open the log file, we create a temporary one, we add our entry and copy the rest */
1795 if (fread(&count, 1, 1, f) != 1) {
1796 display_last_error("Unable to read history header.");
1800 if (count > MAX_ENTRY_LOG) {
1801 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
1802 count, MAX_ENTRY_LOG);
1806 snprintf(tmp2, sizeof(tmp2), "%s/%s/%s-%c.csv.tmp", (char *) ast_config_AST_LOG_DIR,
1807 USTM_LOG_DIR, pte->device->name, way);
1808 if (!(f2 = fopen(tmp2, "w"))) {
1809 display_last_error("Unable to create temporary history log.");
1814 if (++count > MAX_ENTRY_LOG)
1815 count = MAX_ENTRY_LOG;
1817 if (write_entry_history(pte, f2, count, line1)) {
1823 size = (MAX_ENTRY_LOG - 1) * TEXT_LENGTH_MAX * 3;
1824 if (!(histbuf = ast_malloc(size))) {
1830 if (fread(histbuf, size, 1, f) != 1) {
1834 display_last_error("Unable to read previous history entries.");
1837 if (fwrite(histbuf, size, 1, f2) != 1) {
1841 display_last_error("Unable to write previous history entries.");
1846 display_last_error("Unable to close history log.");
1848 display_last_error("Unable to close temporary history log.");
1850 display_last_error("Unable to remove old history log.");
1851 if (rename(tmp2, tmp))
1852 display_last_error("Unable to rename new history log.");
1856 static void cancel_dial(struct unistimsession *pte)
1859 pte->device->missed_call++;
1860 write_history(pte, 'i', 1);
1861 show_main_page(pte);
1865 static void swap_subs(struct unistim_line *p, int a, int b)
1867 /* struct ast_channel *towner; */
1868 struct ast_rtp *rtp;
1872 ast_verbose("Swapping %d and %d\n", a, b);
1874 if ((!p->subs[a]->owner) || (!p->subs[b]->owner)) {
1875 ast_log(LOG_WARNING,
1876 "Attempted to swap subchannels with a null owner : sub #%d=%p sub #%d=%p\n",
1877 a, p->subs[a]->owner, b, p->subs[b]->owner);
1880 rtp = p->subs[a]->rtp;
1881 p->subs[a]->rtp = p->subs[b]->rtp;
1882 p->subs[b]->rtp = rtp;
1884 fds = p->subs[a]->owner->fds[0];
1885 p->subs[a]->owner->fds[0] = p->subs[b]->owner->fds[0];
1886 p->subs[b]->owner->fds[0] = fds;
1888 fds = p->subs[a]->owner->fds[1];
1889 p->subs[a]->owner->fds[1] = p->subs[b]->owner->fds[1];
1890 p->subs[b]->owner->fds[1] = fds;
1893 static int attempt_transfer(struct unistim_subchannel *p1, struct unistim_subchannel *p2)
1897 *chana = NULL, *chanb = NULL, *bridgea = NULL, *bridgeb = NULL, *peera =
1898 NULL, *peerb = NULL, *peerc = NULL, *peerd = NULL;
1900 if (!p1->owner || !p2->owner) {
1901 ast_log(LOG_WARNING, "Transfer attempted without dual ownership?\n");
1906 bridgea = ast_bridged_channel(chana);
1907 bridgeb = ast_bridged_channel(chanb);
1914 } else if (bridgeb) {
1921 if (peera && peerb && peerc && (peerb != peerc)) {
1922 /*ast_quiet_chan(peera);
1923 ast_quiet_chan(peerb);
1924 ast_quiet_chan(peerc);
1925 ast_quiet_chan(peerd); */
1927 if (peera->cdr && peerb->cdr) {
1928 peerb->cdr = ast_cdr_append(peerb->cdr, peera->cdr);
1929 } else if (peera->cdr) {
1930 peerb->cdr = peera->cdr;
1934 if (peerb->cdr && peerc->cdr) {
1935 peerb->cdr = ast_cdr_append(peerb->cdr, peerc->cdr);
1936 } else if (peerc->cdr) {
1937 peerb->cdr = peerc->cdr;
1941 if (ast_channel_masquerade(peerb, peerc)) {
1942 ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name,
1949 "Transfer attempted with no appropriate bridged calls to transfer\n");
1951 ast_softhangup_nolock(chana, AST_SOFTHANGUP_DEV);
1953 ast_softhangup_nolock(chanb, AST_SOFTHANGUP_DEV);
1959 void change_callerid(struct unistimsession *pte, int type, char *callerid)
1965 data = pte->device->lst_cnm;
1967 data = pte->device->lst_cid;
1969 /* This is very nearly strncpy(), except that the remaining buffer
1970 * is padded with ' ', instead of '\0' */
1971 memset(data, ' ', TEXT_LENGTH_MAX);
1972 size = strlen(callerid);
1973 if (size > TEXT_LENGTH_MAX)
1974 size = TEXT_LENGTH_MAX;
1975 memcpy(data, callerid, size);
1978 static void close_call(struct unistimsession *pte)
1980 struct unistim_subchannel *sub;
1981 struct unistim_line *l = pte->device->lines;
1983 sub = pte->device->lines->subs[SUB_REAL];
1984 send_stop_timer(pte);
1986 sub->alreadygone = 1;
1987 if (l->subs[SUB_THREEWAY]) {
1988 l->subs[SUB_THREEWAY]->alreadygone = 1;
1989 if (attempt_transfer(sub, l->subs[SUB_THREEWAY]) < 0)
1990 ast_verbose("attempt_transfer failed.\n");
1992 ast_queue_hangup(sub->owner);
1994 if (l->subs[SUB_THREEWAY]) {
1995 if (l->subs[SUB_THREEWAY]->owner)
1996 ast_queue_hangup(l->subs[SUB_THREEWAY]->owner);
1998 ast_log(LOG_WARNING, "threeway sub without owner\n");
2000 ast_verbose("USTM(%s@%s-%d) channel already destroyed\n", sub->parent->name,
2001 sub->parent->parent->name, sub->subtype);
2003 change_callerid(pte, 0, pte->device->redial_number);
2004 change_callerid(pte, 1, "");
2005 write_history(pte, 'o', pte->device->missed_call);
2006 pte->device->missed_call = 0;
2007 show_main_page(pte);
2011 static void IgnoreCall(struct unistimsession *pte)
2017 static void *unistim_ss(void *data)
2019 struct ast_channel *chan = data;
2020 struct unistim_subchannel *sub = chan->tech_pvt;
2021 struct unistim_line *l = sub->parent;
2022 struct unistimsession *s = l->parent->session;
2025 if (option_verbose > 2)
2026 ast_verbose(VERBOSE_PREFIX_3 "Starting switch on '%s@%s-%d' to %s\n",
2027 l->name, l->parent->name, sub->subtype, s->device->phone_number);
2028 ast_copy_string(chan->exten, s->device->phone_number, sizeof(chan->exten));
2029 ast_copy_string(s->device->redial_number, s->device->phone_number,
2030 sizeof(s->device->redial_number));
2031 ast_setstate(chan, AST_STATE_RING);
2032 res = ast_pbx_run(chan);
2034 ast_log(LOG_WARNING, "PBX exited non-zero\n");
2035 send_tone(s, 1000, 0);;
2040 static void start_rtp(struct unistim_subchannel *sub)
2043 struct sockaddr_in us;
2044 struct sockaddr_in public;
2045 struct sockaddr_in sin;
2047 struct sockaddr_in sout;
2051 ast_log(LOG_WARNING, "start_rtp with a null subchannel !\n");
2055 ast_log(LOG_WARNING, "start_rtp with a null line !\n");
2058 if (!sub->parent->parent) {
2059 ast_log(LOG_WARNING, "start_rtp with a null device !\n");
2062 if (!sub->parent->parent->session) {
2063 ast_log(LOG_WARNING, "start_rtp with a null session !\n");
2066 sout = sub->parent->parent->session->sout;
2068 ast_mutex_lock(&sub->lock);
2069 /* Allocate the RTP */
2071 ast_verbose("Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
2072 sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, sout.sin_addr);
2074 ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
2075 strerror(errno), ast_inet_ntoa(sout.sin_addr));
2076 ast_mutex_unlock(&sub->lock);
2079 if (sub->rtp && sub->owner) {
2080 sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
2081 sub->owner->fds[1] = ast_rtcp_fd(sub->rtp);
2084 ast_rtp_setqos(sub->rtp, tos_audio, cos_audio, "UNISTIM RTP");
2085 ast_rtp_setnat(sub->rtp, sub->parent->parent->nat);
2088 /* Create the RTP connection */
2089 ast_rtp_get_us(sub->rtp, &us);
2090 sin.sin_family = AF_INET;
2091 /* Setting up RTP for our side */
2092 memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
2093 sizeof(sin.sin_addr));
2094 sin.sin_port = htons(sub->parent->parent->rtp_port);
2095 ast_rtp_set_peer(sub->rtp, &sin);
2096 if (!(sub->owner->nativeformats & sub->owner->readformat)) {
2098 fmt = ast_best_codec(sub->owner->nativeformats);
2099 ast_log(LOG_WARNING,
2100 "Our read/writeformat has been changed to something incompatible : %s (%d), using %s (%d) best codec from %d\n",
2101 ast_getformatname(sub->owner->readformat),
2102 sub->owner->readformat, ast_getformatname(fmt), fmt,
2103 sub->owner->nativeformats);
2104 sub->owner->readformat = fmt;
2105 sub->owner->writeformat = fmt;
2107 codec = ast_rtp_lookup_code(sub->rtp, 1, sub->owner->readformat);
2108 /* Setting up RTP of the phone */
2109 if (public_ip.sin_family == 0) /* NAT IP override ? */
2110 memcpy(&public, &us, sizeof(public)); /* No defined, using IP from recvmsg */
2112 memcpy(&public, &public_ip, sizeof(public)); /* override */
2115 ("RTP started : Our IP/port is : %s:%hd with codec %s (%d)\n",
2116 ast_inet_ntoa(us.sin_addr),
2117 htons(us.sin_port), ast_getformatname(sub->owner->readformat),
2118 sub->owner->readformat);
2119 ast_verbose("Starting phone RTP stack. Our public IP is %s\n",
2120 ast_inet_ntoa(public.sin_addr));
2122 if ((sub->owner->readformat == AST_FORMAT_ULAW) ||
2123 (sub->owner->readformat == AST_FORMAT_ALAW)) {
2125 ast_verbose("Sending packet_send_rtp_packet_size for codec %d\n", codec);
2126 memcpy(buffsend + SIZE_HEADER, packet_send_rtp_packet_size,
2127 sizeof(packet_send_rtp_packet_size));
2128 buffsend[10] = codec;
2129 send_client(SIZE_HEADER + sizeof(packet_send_rtp_packet_size), buffsend,
2130 sub->parent->parent->session);
2133 ast_verbose("Sending Jitter Buffer Parameters Configuration\n");
2134 memcpy(buffsend + SIZE_HEADER, packet_send_jitter_buffer_conf,
2135 sizeof(packet_send_jitter_buffer_conf));
2136 send_client(SIZE_HEADER + sizeof(packet_send_jitter_buffer_conf), buffsend,
2137 sub->parent->parent->session);
2138 if (sub->parent->parent->rtp_method != 0) {
2139 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2142 ast_verbose("Sending OpenAudioStreamTX using method #%d\n",
2143 sub->parent->parent->rtp_method);
2144 if (sub->parent->parent->rtp_method == 3)
2145 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx3,
2146 sizeof(packet_send_open_audio_stream_tx3));
2148 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx,
2149 sizeof(packet_send_open_audio_stream_tx));
2150 if (sub->parent->parent->rtp_method != 2) {
2151 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2152 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2153 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2154 buffsend[23] = (rtcpsin_port & 0x00ff);
2155 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2156 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2157 buffsend[24] = (us.sin_port & 0x00ff);
2158 buffsend[27] = (rtcpsin_port & 0x00ff);
2159 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2161 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2162 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2163 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2164 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2165 buffsend[19] = (us.sin_port & 0x00ff);
2166 buffsend[11] = codec;
2168 buffsend[12] = codec;
2169 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_tx), buffsend,
2170 sub->parent->parent->session);
2173 ast_verbose("Sending OpenAudioStreamRX\n");
2174 if (sub->parent->parent->rtp_method == 3)
2175 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx3,
2176 sizeof(packet_send_open_audio_stream_rx3));
2178 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx,
2179 sizeof(packet_send_open_audio_stream_rx));
2180 if (sub->parent->parent->rtp_method != 2) {
2181 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2182 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2183 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2184 buffsend[23] = (rtcpsin_port & 0x00ff);
2185 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2186 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2187 buffsend[24] = (us.sin_port & 0x00ff);
2188 buffsend[27] = (rtcpsin_port & 0x00ff);
2189 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2191 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2192 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2193 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2194 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2195 buffsend[19] = (us.sin_port & 0x00ff);
2196 buffsend[12] = codec;
2198 buffsend[11] = codec;
2199 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_rx), buffsend,
2200 sub->parent->parent->session);
2202 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2205 ast_verbose("Sending packet_send_call default method\n");
2207 memcpy(buffsend + SIZE_HEADER, packet_send_call, sizeof(packet_send_call));
2208 memcpy(buffsend + 53, &public.sin_addr, sizeof(public.sin_addr));
2209 /* Destination port when sending RTP */
2210 buffsend[49] = (us.sin_port & 0x00ff);
2211 buffsend[50] = (us.sin_port & 0xff00) >> 8;
2212 /* Destination port when sending RTCP */
2213 buffsend[52] = (rtcpsin_port & 0x00ff);
2214 buffsend[51] = (rtcpsin_port & 0xff00) >> 8;
2216 buffsend[40] = codec;
2217 buffsend[41] = codec;
2218 if (sub->owner->readformat == AST_FORMAT_ULAW)
2219 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2220 else if (sub->owner->readformat == AST_FORMAT_ALAW)
2221 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2222 else if (sub->owner->readformat == AST_FORMAT_G723_1)
2223 buffsend[42] = 2; /* 1 = 30ms (24 bytes), 2 = 60 ms (48 bytes) */
2224 else if (sub->owner->readformat == AST_FORMAT_G729A)
2225 buffsend[42] = 2; /* 1 = 10ms (10 bytes), 2 = 20ms (20 bytes) */
2227 ast_log(LOG_WARNING, "Unsupported codec %s (%d) !\n",
2228 ast_getformatname(sub->owner->readformat), sub->owner->readformat);
2229 /* Source port for transmit RTP and Destination port for receiving RTP */
2230 buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8;
2231 buffsend[46] = (htons(sin.sin_port) & 0x00ff);
2232 buffsend[47] = (rtcpsin_port & 0xff00) >> 8;
2233 buffsend[48] = (rtcpsin_port & 0x00ff);
2234 send_client(SIZE_HEADER + sizeof(packet_send_call), buffsend,
2235 sub->parent->parent->session);
2237 ast_mutex_unlock(&sub->lock);
2240 static void SendDialTone(struct unistimsession *pte)
2243 /* No country defined ? Using US tone */
2244 if (ast_strlen_zero(pte->device->country)) {
2246 ast_verbose("No country defined, using US tone\n");
2247 send_tone(pte, 350, 440);
2250 if (strlen(pte->device->country) != 2) {
2252 ast_verbose("Country code != 2 char, using US tone\n");
2253 send_tone(pte, 350, 440);
2257 while (frequency[i].freq1) {
2258 if ((frequency[i].country[0] == pte->device->country[0]) &&
2259 (frequency[i].country[1] == pte->device->country[1])) {
2261 ast_verbose("Country code found (%s), freq1=%d freq2=%d\n",
2262 frequency[i].country, frequency[i].freq1, frequency[i].freq2);
2263 send_tone(pte, frequency[i].freq1, frequency[i].freq2);
2269 static void handle_dial_page(struct unistimsession *pte)
2271 pte->state = STATE_DIALPAGE;
2272 if (pte->device->call_forward[0] == -1) {
2273 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
2274 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Enter forward");
2275 send_text_status(pte, "ForwardCancel BackSpcErase");
2276 if (pte->device->call_forward[1] != 0) {
2277 char tmp[TEXT_LENGTH_MAX + 1];
2279 ast_copy_string(pte->device->phone_number, pte->device->call_forward + 1,
2280 sizeof(pte->device->phone_number));
2281 pte->device->size_phone_number = strlen(pte->device->phone_number);
2282 if (pte->device->size_phone_number > 15)
2283 pte->device->size_phone_number = 15;
2284 strcpy(tmp, "Number : ...............");
2285 memcpy(tmp + 9, pte->device->phone_number, pte->device->size_phone_number);
2286 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
2287 send_blink_cursor(pte);
2288 send_cursor_pos(pte,
2289 (unsigned char) (TEXT_LINE2 + 0x09 +
2290 pte->device->size_phone_number));
2291 send_led_update(pte, 0);
2295 if ((pte->device->output == OUTPUT_HANDSET) &&
2296 (pte->device->receiver_state == STATE_ONHOOK))
2297 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2299 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2301 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Enter the number to dial");
2302 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "and press Call");
2303 send_text_status(pte, "Call Redial BackSpcErase");
2305 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
2306 send_blink_cursor(pte);
2307 send_cursor_pos(pte, TEXT_LINE2 + 0x09);
2308 pte->device->size_phone_number = 0;
2309 pte->device->phone_number[0] = 0;
2310 change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
2311 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
2312 pte->device->missed_call = 0;
2313 send_led_update(pte, 0);
2317 /* Step 1 : Music On Hold for peer, Dialing screen for us */
2318 static void TransferCallStep1(struct unistimsession *pte)
2320 struct unistim_subchannel *sub;
2321 struct unistim_line *p = pte->device->lines;
2323 sub = p->subs[SUB_REAL];
2326 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2329 if (p->subs[SUB_THREEWAY]) {
2331 ast_verbose("Transfer canceled, hangup our threeway channel\n");
2332 if (p->subs[SUB_THREEWAY]->owner)
2333 ast_queue_hangup(p->subs[SUB_THREEWAY]->owner);
2335 ast_log(LOG_WARNING, "Canceling a threeway channel without owner\n");
2338 /* Start music on hold if appropriate */
2339 if (pte->device->moh)
2340 ast_log(LOG_WARNING, "Transfer with peer already listening music on hold\n");
2342 if (ast_bridged_channel(p->subs[SUB_REAL]->owner)) {
2343 ast_moh_start(ast_bridged_channel(p->subs[SUB_REAL]->owner),
2344 pte->device->lines->musicclass, NULL);
2345 pte->device->moh = 1;
2347 ast_log(LOG_WARNING, "Unable to find peer subchannel for music on hold\n");
2351 /* Silence our channel */
2352 if (!pte->device->silence_generator) {
2353 pte->device->silence_generator =
2354 ast_channel_start_silence_generator(p->subs[SUB_REAL]->owner);
2355 if (pte->device->silence_generator == NULL)
2356 ast_log(LOG_WARNING, "Unable to start a silence generator.\n");
2357 else if (unistimdebug)
2358 ast_verbose("Starting silence generator\n");
2360 handle_dial_page(pte);
2363 /* From phone to PBX */
2364 static void HandleCallOutgoing(struct unistimsession *s)
2366 struct ast_channel *c;
2367 struct unistim_subchannel *sub;
2369 s->state = STATE_CALL;
2370 sub = s->device->lines->subs[SUB_REAL];
2372 ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
2375 if (!sub->owner) { /* A call is already in progress ? */
2376 c = unistim_new(sub, AST_STATE_DOWN); /* No, starting a new one */
2378 /* Need to start RTP before calling ast_pbx_run */
2381 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
2382 send_text(TEXT_LINE0, TEXT_NORMAL, s, "Calling :");
2383 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
2384 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Dialing...");
2385 send_text_status(s, "Hangup");
2387 if (ast_pthread_create(&t, NULL, unistim_ss, c)) {
2388 display_last_error("Unable to create switch thread");
2389 ast_queue_hangup(c);
2392 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n",
2393 sub->parent->name, s->device->name);
2394 } else { /* We already have a call, so we switch in a threeway call */
2396 if (s->device->moh) {
2397 struct unistim_subchannel *sub;
2398 struct unistim_line *p = s->device->lines;
2399 sub = p->subs[SUB_REAL];
2402 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2405 if (p->subs[SUB_THREEWAY]) {
2406 ast_log(LOG_WARNING,
2407 "Can't transfer while an another transfer is taking place\n");
2410 if (!alloc_sub(p, SUB_THREEWAY)) {
2411 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
2414 /* Stop the silence generator */
2415 if (s->device->silence_generator) {
2417 ast_verbose("Stopping silence generator\n");
2418 ast_channel_stop_silence_generator(sub->owner,
2419 s->device->silence_generator);
2420 s->device->silence_generator = NULL;
2423 /* Make new channel */
2424 c = unistim_new(p->subs[SUB_THREEWAY], AST_STATE_DOWN);
2426 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", p);
2429 /* Swap things around between the three-way and real call */
2430 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2431 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
2432 send_text(TEXT_LINE0, TEXT_NORMAL, s, "Calling (pre-transfer)");
2433 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
2434 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Dialing...");
2435 send_text_status(s, "TransfrCancel");
2437 if (ast_pthread_create(&t, NULL, unistim_ss, p->subs[SUB_THREEWAY]->owner)) {
2438 ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", p);
2444 ("Started three way call on channel %p (%s) subchan %d\n",
2445 p->subs[SUB_THREEWAY]->owner, p->subs[SUB_THREEWAY]->owner->name,
2446 p->subs[SUB_THREEWAY]->subtype);
2448 ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name);
2453 /* From PBX to phone */
2454 static void HandleCallIncoming(struct unistimsession *s)
2456 struct unistim_subchannel *sub;
2457 s->state = STATE_CALL;
2458 s->device->missed_call = 0;
2460 sub = s->device->lines->subs[SUB_REAL];
2462 ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
2464 } else if (unistimdebug)
2465 ast_verbose("Handle Call Incoming for %s@%s\n", sub->parent->name,
2469 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", sub->parent->name,
2471 ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
2472 send_text(TEXT_LINE2, TEXT_NORMAL, s, "is on-line");
2473 send_text_status(s, "Hangup Transf");
2474 send_start_timer(s);
2476 if ((s->device->output == OUTPUT_HANDSET) &&
2477 (s->device->receiver_state == STATE_ONHOOK))
2478 send_select_output(s, OUTPUT_SPEAKER, s->device->volume, MUTE_OFF);
2480 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
2481 s->device->start_call_timestamp = time(0);
2482 write_history(s, 'i', 0);
2486 static int unistim_do_senddigit(struct unistimsession *pte, char digit)
2489 struct ast_frame f = { 0, };
2490 struct unistim_subchannel *sub;
2491 sub = pte->device->lines->subs[SUB_REAL];
2493 ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit\n");
2497 ast_verbose("Send Digit %c\n", digit);
2500 send_tone(pte, 941, 1336);
2503 send_tone(pte, 697, 1209);
2506 send_tone(pte, 697, 1336);
2509 send_tone(pte, 697, 1477);
2512 send_tone(pte, 770, 1209);
2515 send_tone(pte, 770, 1336);
2518 send_tone(pte, 770, 1477);
2521 send_tone(pte, 852, 1209);
2524 send_tone(pte, 852, 1336);
2527 send_tone(pte, 852, 1477);
2530 send_tone(pte, 697, 1633);
2533 send_tone(pte, 770, 1633);
2536 send_tone(pte, 852, 1633);
2539 send_tone(pte, 941, 1633);
2542 send_tone(pte, 941, 1209);
2545 send_tone(pte, 941, 1477);
2548 send_tone(pte, 500, 2000);
2550 usleep(150000); /* XXX Less than perfect, blocking an important thread is not a good idea */
2551 send_tone(pte, 0, 0);
2552 f.frametype = AST_FRAME_DTMF;
2555 ast_queue_frame(sub->owner, &f);
2559 static void key_call(struct unistimsession *pte, char keycode)
2561 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
2562 if (keycode == KEY_SHARP)
2564 else if (keycode == KEY_STAR)
2568 unistim_do_senddigit(pte, keycode);
2577 TransferCallStep1(pte);
2580 if (pte->device->output == OUTPUT_HEADPHONE)
2581 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
2583 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
2586 if (pte->device->output != OUTPUT_SPEAKER)
2587 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2589 send_select_output(pte, pte->device->previous_output, pte->device->volume,
2593 if (!pte->device->moh) {
2594 if (pte->device->mute == MUTE_ON)
2595 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2597 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
2602 struct unistim_subchannel *sub;
2603 struct ast_channel *bridgepeer = NULL;
2604 sub = pte->device->lines->subs[SUB_REAL];
2606 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2609 if ((bridgepeer = ast_bridged_channel(sub->owner))) {
2610 if (pte->device->moh) {
2611 ast_moh_stop(bridgepeer);
2612 pte->device->moh = 0;
2613 send_select_output(pte, pte->device->output, pte->device->volume,
2616 ast_moh_start(bridgepeer, pte->device->lines->musicclass, NULL);
2617 pte->device->moh = 1;
2618 send_select_output(pte, pte->device->output, pte->device->volume,
2622 ast_log(LOG_WARNING,
2623 "Unable to find peer subchannel for music on hold\n");
2630 static void key_ringing(struct unistimsession *pte, char keycode)
2632 if (keycode == KEY_FAV0 + pte->device->softkeylinepos) {
2633 HandleCallIncoming(pte);
2642 HandleCallIncoming(pte);
2648 static void Keyfavorite(struct unistimsession *pte, char keycode)
2652 if ((keycode < KEY_FAV1) && (keycode > KEY_FAV5)) {
2653 ast_log(LOG_WARNING, "It's not a favorite key\n");
2656 if (keycode == KEY_FAV0)
2658 fav = keycode - KEY_FAV0;
2659 if (pte->device->softkeyicon[fav] == 0)
2661 ast_copy_string(pte->device->phone_number, pte->device->softkeynumber[fav],
2662 sizeof(pte->device->phone_number));
2663 HandleCallOutgoing(pte);
2667 static void key_dial_page(struct unistimsession *pte, char keycode)
2669 if (keycode == KEY_FUNC3) {
2670 if (pte->device->size_phone_number <= 1)
2671 keycode = KEY_FUNC4;
2673 pte->device->size_phone_number -= 2;
2674 keycode = pte->device->phone_number[pte->device->size_phone_number] + 0x10;
2677 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
2678 char tmpbuf[] = "Number : ...............";
2681 if (pte->device->size_phone_number >= 15)
2683 if (pte->device->size_phone_number == 0)
2684 send_tone(pte, 0, 0);
2685 while (i < pte->device->size_phone_number) {
2686 tmpbuf[i + 9] = pte->device->phone_number[i];
2689 if (keycode == KEY_SHARP)
2691 else if (keycode == KEY_STAR)
2695 tmpbuf[i + 9] = keycode;
2696 pte->device->phone_number[i] = keycode;
2697 pte->device->size_phone_number++;
2698 pte->device->phone_number[i + 1] = 0;
2699 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
2700 send_blink_cursor(pte);
2701 send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 + 0x0a + i));
2704 if (keycode == KEY_FUNC4) {
2706 pte->device->size_phone_number = 0;
2707 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
2708 send_blink_cursor(pte);
2709 send_cursor_pos(pte, TEXT_LINE2 + 0x09);
2713 if (pte->device->call_forward[0] == -1) {
2714 if (keycode == KEY_FUNC1) {
2715 ast_copy_string(pte->device->call_forward, pte->device->phone_number,
2716 sizeof(pte->device->call_forward));
2717 show_main_page(pte);
2718 } else if ((keycode == KEY_FUNC2) || (keycode == KEY_HANGUP)) {
2719 pte->device->call_forward[0] = '\0';
2720 show_main_page(pte);
2726 if (ast_strlen_zero(pte->device->redial_number))
2728 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
2729 sizeof(pte->device->phone_number));
2731 HandleCallOutgoing(pte);
2734 if (pte->device->lines->subs[SUB_REAL]->owner) {
2735 /* Stop the silence generator */
2736 if (pte->device->silence_generator) {
2738 ast_verbose("Stopping silence generator\n");
2739 ast_channel_stop_silence_generator(pte->device->lines->subs[SUB_REAL]->
2740 owner, pte->device->silence_generator);
2741 pte->device->silence_generator = NULL;
2743 send_tone(pte, 0, 0);
2744 ast_moh_stop(ast_bridged_channel(pte->device->lines->subs[SUB_REAL]->owner));
2745 pte->device->moh = 0;
2746 pte->state = STATE_CALL;
2747 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Dialing canceled,");
2748 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "switching back to");
2749 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "previous call.");
2750 send_text_status(pte, "Hangup Transf");
2752 show_main_page(pte);
2759 Keyfavorite(pte, keycode);
2762 if (pte->device->output == OUTPUT_SPEAKER) {
2763 if (pte->device->receiver_state == STATE_OFFHOOK)
2764 send_select_output(pte, pte->device->previous_output, pte->device->volume,
2767 show_main_page(pte);
2769 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2772 if (pte->device->output == OUTPUT_HEADPHONE) {
2773 if (pte->device->receiver_state == STATE_OFFHOOK)
2774 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
2776 show_main_page(pte);
2778 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
2784 #define SELECTCODEC_START_ENTRY_POS 15
2785 #define SELECTCODEC_MAX_LENGTH 2
2786 #define SELECTCODEC_MSG "Codec number : .."
2787 static void HandleSelectCodec(struct unistimsession *pte)
2789 char buf[30], buf2[5];
2791 pte->state = STATE_SELECTCODEC;
2792 strcpy(buf, "Using codec ");
2793 sprintf(buf2, "%d", pte->device->codec_number);
2795 strcat(buf, " (G711u=0,");
2797 send_text(TEXT_LINE0, TEXT_NORMAL, pte, buf);
2798 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "G723=4,G711a=8,G729A=18)");
2799 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
2800 send_blink_cursor(pte);
2801 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
2802 pte->size_buff_entry = 0;
2803 send_text_status(pte, "Select BackSpcErase Cancel");
2807 static void key_select_codec(struct unistimsession *pte, char keycode)
2809 if (keycode == KEY_FUNC2) {
2810 if (pte->size_buff_entry <= 1)
2811 keycode = KEY_FUNC3;
2813 pte->size_buff_entry -= 2;
2814 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
2817 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
2818 char tmpbuf[] = SELECTCODEC_MSG;
2821 if (pte->size_buff_entry >= SELECTCODEC_MAX_LENGTH)
2824 while (i < pte->size_buff_entry) {
2825 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = pte->buff_entry[i];
2828 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = keycode - 0x10;
2829 pte->buff_entry[i] = keycode - 0x10;
2830 pte->size_buff_entry++;
2831 send_text(TEXT_LINE2, TEXT_INVERSE, pte, tmpbuf);
2832 send_blink_cursor(pte);
2833 send_cursor_pos(pte,
2834 (unsigned char) (TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS + 1 + i));
2840 if (pte->size_buff_entry == 1)
2841 pte->device->codec_number = pte->buff_entry[0] - 48;
2842 else if (pte->size_buff_entry == 2)
2843 pte->device->codec_number =
2844 ((pte->buff_entry[0] - 48) * 10) + (pte->buff_entry[1] - 48);
2845 show_main_page(pte);
2848 pte->size_buff_entry = 0;
2849 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
2850 send_blink_cursor(pte);
2851 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
2855 show_main_page(pte);
2861 #define SELECTEXTENSION_START_ENTRY_POS 0
2862 #define SELECTEXTENSION_MAX_LENGTH 10
2863 #define SELECTEXTENSION_MSG ".........."
2864 static void ShowExtensionPage(struct unistimsession *pte)
2866 pte->state = STATE_EXTENSION;
2868 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Please enter a Terminal");
2869 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Number (TN) :");
2870 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
2871 send_blink_cursor(pte);
2872 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
2873 send_text_status(pte, "Enter BackSpcErase");
2874 pte->size_buff_entry = 0;
2878 static void key_select_extension(struct unistimsession *pte, char keycode)
2880 if (keycode == KEY_FUNC2) {
2881 if (pte->size_buff_entry <= 1)
2882 keycode = KEY_FUNC3;
2884 pte->size_buff_entry -= 2;
2885 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
2888 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
2889 char tmpbuf[] = SELECTEXTENSION_MSG;
2892 if (pte->size_buff_entry >= SELECTEXTENSION_MAX_LENGTH)
2895 while (i < pte->size_buff_entry) {
2896 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = pte->buff_entry[i];
2899 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = keycode - 0x10;
2900 pte->buff_entry[i] = keycode - 0x10;
2901 pte->size_buff_entry++;
2902 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
2903 send_blink_cursor(pte);
2904 send_cursor_pos(pte,
2905 (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS + 1 +
2912 if (pte->size_buff_entry < 1)
2914 if (autoprovisioning == AUTOPROVISIONING_TN) {
2915 struct unistim_device *d;
2917 /* First step : looking for this TN in our device list */
2918 ast_mutex_lock(&devicelock);
2920 pte->buff_entry[pte->size_buff_entry] = '\0';
2922 if (d->id[0] == 'T') { /* It's a TN device ? */
2923 /* It's the TN we're looking for ? */
2924 if (!strcmp((d->id) + 1, pte->buff_entry)) {
2927 d->codec_number = DEFAULT_CODEC;
2930 d->receiver_state = STATE_ONHOOK;
2931 strcpy(d->id, pte->macaddr);
2932 pte->device->extension_number[0] = 'T';
2933 pte->device->extension = EXTENSION_TN;
2934 ast_copy_string((pte->device->extension_number) + 1,
2935 pte->buff_entry, pte->size_buff_entry + 1);
2936 ast_mutex_unlock(&devicelock);
2937 show_main_page(pte);
2938 refresh_all_favorite(pte);
2944 ast_mutex_unlock(&devicelock);
2945 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Invalid Terminal Number.");
2946 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Please try again :");
2947 send_cursor_pos(pte,
2948 (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS +
2949 pte->size_buff_entry));
2950 send_blink_cursor(pte);
2952 ast_copy_string(pte->device->extension_number, pte->buff_entry,
2953 pte->size_buff_entry + 1);
2954 if (RegisterExtension(pte)) {
2955 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Invalid extension.");
2956 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Please try again :");
2957 send_cursor_pos(pte,
2958 (unsigned char) (TEXT_LINE2 +
2959 SELECTEXTENSION_START_ENTRY_POS +
2960 pte->size_buff_entry));
2961 send_blink_cursor(pte);
2963 show_main_page(pte);
2967 pte->size_buff_entry = 0;
2968 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
2969 send_blink_cursor(pte);
2970 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
2976 static int ReformatNumber(char *number)
2978 int pos = 0, i = 0, size = strlen(number);
2980 for (; i < size; i++) {
2981 if ((number[i] >= '0') && (number[i] <= '9')) {
2986 number[pos] = number[i];
2994 static void show_entry_history(struct unistimsession *pte, FILE ** f)
2996 char line[TEXT_LENGTH_MAX + 1], status[STATUS_LENGTH_MAX + 1], func1[10], func2[10],
2999 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
3000 display_last_error("Can't read history date entry");
3004 line[sizeof(line) - 1] = '\0';
3005 send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
3006 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
3007 display_last_error("Can't read callerid entry");
3011 line[sizeof(line) - 1] = '\0';
3012 ast_copy_string(pte->device->lst_cid, line, sizeof(pte->device->lst_cid));
3013 send_text(TEXT_LINE1, TEXT_NORMAL, pte, line);
3014 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
3015 display_last_error("Can't read callername entry");
3019 line[sizeof(line) - 1] = '\0';
3020 send_text(TEXT_LINE2, TEXT_NORMAL, pte, line);
3023 snprintf(line, sizeof(line), "Call %03d/%03d", pte->buff_entry[2],
3024 pte->buff_entry[1]);
3025 send_texttitle(pte, line);
3027 if (pte->buff_entry[2] == 1)
3030 strcpy(func1, "Prvious");
3031 if (pte->buff_entry[2] >= pte->buff_entry[1])
3034 strcpy(func2, "Next ");
3035 if (ReformatNumber(pte->device->lst_cid))
3036 strcpy(func3, "Redial ");
3039 snprintf(status, sizeof(status), "%s%s%sCancel", func1, func2, func3);
3040 send_text_status(pte, status);
3043 static char OpenHistory(struct unistimsession *pte, char way, FILE ** f)
3045 char tmp[AST_CONFIG_MAX_PATH];
3048 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", (char *) ast_config_AST_LOG_DIR,
3049 USTM_LOG_DIR, pte->device->name, way);
3050 *f = fopen(tmp, "r");
3052 display_last_error("Unable to open history file");
3055 if (fread(&count, 1, 1, *f) != 1) {
3056 display_last_error("Unable to read history header - display.");
3060 if (count > MAX_ENTRY_LOG) {
3061 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
3062 count, MAX_ENTRY_LOG);
3069 static void show_history(struct unistimsession *pte, char way)
3076 if (!pte->device->callhistory)
3078 count = OpenHistory(pte, way, &f);
3081 pte->buff_entry[0] = way;
3082 pte->buff_entry[1] = count;
3083 pte->buff_entry[2] = 1;
3084 show_entry_history(pte, &f);
3085 pte->state = STATE_HISTORY;
3088 static void show_main_page(struct unistimsession *pte)
3090 char tmpbuf[TEXT_LENGTH_MAX + 1];
3093 if ((pte->device->extension == EXTENSION_ASK) &&
3094 (ast_strlen_zero(pte->device->extension_number))) {
3095 ShowExtensionPage(pte);
3099 pte->state = STATE_MAINPAGE;
3101 send_tone(pte, 0, 0);
3102 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON_DISCRET);
3103 pte->device->lines->lastmsgssent = 0;
3104 send_favorite(pte->device->softkeylinepos, FAV_ICON_ONHOOK_BLACK, pte,
3105 pte->device->softkeylabel[pte->device->softkeylinepos]);
3106 if (!ast_strlen_zero(pte->device->call_forward)) {
3107 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Call forwarded to :");
3108 send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->call_forward);
3109 Sendicon(TEXT_LINE0, FAV_ICON_REFLECT + FAV_BLINK_SLOW, pte);
3110 send_text_status(pte, "Dial Redial NoForwd");
3112 if ((pte->device->extension == EXTENSION_ASK) ||
3113 (pte->device->extension == EXTENSION_TN))
3114 send_text_status(pte, "Dial Redial ForwardUnregis");
3116 send_text_status(pte, "Dial Redial Forward");
3118 send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->maintext1);
3119 if (pte->device->missed_call == 0)
3120 send_text(TEXT_LINE0, TEXT_NORMAL, pte, pte->device->maintext0);
3122 sprintf(tmpbuf, "%d unanswered call(s)", pte->device->missed_call);
3123 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpbuf);
3124 Sendicon(TEXT_LINE0, FAV_ICON_CALL_CENTER + FAV_BLINK_SLOW, pte);
3127 if (ast_strlen_zero(pte->device->maintext2)) {
3128 strcpy(tmpbuf, "IP : ");
3129 strcat(tmpbuf, ast_inet_ntoa(pte->sin.sin_addr));
3130 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
3132 send_text(TEXT_LINE2, TEXT_NORMAL, pte, pte->device->maintext2);
3133 send_texttitle(pte, pte->device->titledefault);
3134 change_favorite_icon(pte, FAV_ICON_ONHOOK_BLACK);
3137 static void key_main_page(struct unistimsession *pte, char keycode)
3139 if (pte->device->missed_call) {
3140 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
3141 pte->device->missed_call = 0;
3143 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
3144 handle_dial_page(pte);
3145 key_dial_page(pte, keycode);
3150 handle_dial_page(pte);
3153 if (ast_strlen_zero(pte->device->redial_number))
3155 if ((pte->device->output == OUTPUT_HANDSET) &&
3156 (pte->device->receiver_state == STATE_ONHOOK))
3157 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
3159 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
3161 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
3162 sizeof(pte->device->phone_number));
3163 HandleCallOutgoing(pte);
3166 if (!ast_strlen_zero(pte->device->call_forward)) {
3167 /* Cancel call forwarding */
3168 memmove(pte->device->call_forward + 1, pte->device->call_forward,
3169 sizeof(pte->device->call_forward));
3170 pte->device->call_forward[0] = '\0';
3171 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
3172 pte->device->output = OUTPUT_HANDSET; /* Seems to be reseted somewhere */
3173 show_main_page(pte);
3176 pte->device->call_forward[0] = -1;
3177 handle_dial_page(pte);
3180 if (pte->device->extension == EXTENSION_ASK) {
3181 UnregisterExtension(pte);
3182 pte->device->extension_number[0] = '\0';
3183 ShowExtensionPage(pte);
3184 } else if (pte->device->extension == EXTENSION_TN) {
3185 ast_mutex_lock(&devicelock);
3186 strcpy(pte->device->id, pte->device->extension_number);
3187 pte->buff_entry[0] = '\0';
3188 pte->size_buff_entry = 0;
3189 pte->device->session = NULL;
3191 ast_mutex_unlock(&devicelock);
3192 ShowExtensionPage(pte);
3196 handle_dial_page(pte);
3203 if ((pte->device->output == OUTPUT_HANDSET) &&
3204 (pte->device->receiver_state == STATE_ONHOOK))
3205 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
3207 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
3208 Keyfavorite(pte, keycode);
3211 HandleSelectCodec(pte);
3214 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
3215 handle_dial_page(pte);
3218 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
3219 handle_dial_page(pte);
3222 show_history(pte, 'o');
3225 show_history(pte, 'i');
3231 static void key_history(struct unistimsession *pte, char keycode)
3241 if (pte->buff_entry[2] <= 1)
3243 pte->buff_entry[2]--;
3244 count = OpenHistory(pte, pte->buff_entry[0], &f);
3247 offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
3248 if (fseek(f, offset, SEEK_CUR)) {
3249 display_last_error("Unable to seek history entry.");
3253 show_entry_history(pte, &f);
3258 if (pte->buff_entry[2] >= pte->buff_entry[1])
3260 pte->buff_entry[2]++;
3261 count = OpenHistory(pte, pte->buff_entry[0], &f);
3264 offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
3265 if (fseek(f, offset, SEEK_CUR)) {
3266 display_last_error("Unable to seek history entry.");
3270 show_entry_history(pte, &f);
3273 if (!ReformatNumber(pte->device->lst_cid))
3275 ast_copy_string(pte->device->redial_number, pte->device->lst_cid,
3276 sizeof(pte->device->redial_number));
3277 key_main_page(pte, KEY_FUNC2);
3281 show_main_page(pte);
3284 if (pte->buff_entry[0] == 'i')
3285 show_history(pte, 'o');
3287 show_main_page(pte);
3290 if (pte->buff_entry[0] == 'i')
3291 show_main_page(pte);
3293 show_history(pte, 'i');
3299 static void init_phone_step2(struct unistimsession *pte)
3303 ast_verbose("Sending S4\n");
3304 memcpy(buffsend + SIZE_HEADER, packet_send_s4, sizeof(packet_send_s4));
3305 send_client(SIZE_HEADER + sizeof(packet_send_s4), buffsend, pte);
3306 send_date_time2(pte);
3307 send_date_time3(pte);
3309 ast_verbose("Sending S7\n");
3310 memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
3311 send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
3313 ast_verbose("Sending Contrast\n");
3314 memcpy(buffsend + SIZE_HEADER, packet_send_Contrast, sizeof(packet_send_Contrast));
3315 if (pte->device != NULL)
3316 buffsend[9] = pte->device->contrast;
3317 send_client(SIZE_HEADER + sizeof(packet_send_Contrast), buffsend, pte);
3320 ast_verbose("Sending S9\n");
3321 memcpy(buffsend + SIZE_HEADER, packet_send_s9, sizeof(packet_send_s9));
3322 send_client(SIZE_HEADER + sizeof(packet_send_s9), buffsend, pte);
3326 ast_verbose("Sending S7\n");
3327 memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
3328 send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
3329 send_led_update(pte, 0);
3331 if (pte->state < STATE_MAINPAGE) {
3332 if (autoprovisioning == AUTOPROVISIONING_TN) {
3333 ShowExtensionPage(pte);
3339 for (i = 1; i < 6; i++)
3340 send_favorite(i, 0, pte, "");
3341 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Sorry, this phone is not");
3342 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "registred in unistim.cfg");
3343 strcpy(tmp, "MAC = ");
3344 strcat(tmp, pte->macaddr);
3345 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
3346 send_text_status(pte, "");
3347 send_texttitle(pte, "UNISTIM for*");
3351 show_main_page(pte);
3352 refresh_all_favorite(pte);
3354 ast_verbose("Sending arrow\n");
3355 memcpy(buffsend + SIZE_HEADER, packet_send_arrow, sizeof(packet_send_arrow));
3356 send_client(SIZE_HEADER + sizeof(packet_send_arrow), buffsend, pte);
3360 static void process_request(int size, unsigned char *buf, struct unistimsession *pte)
3364 (buf + SIZE_HEADER, packet_recv_resume_connection_with_server,
3365 sizeof(packet_recv_resume_connection_with_server)) == 0) {
3366 rcv_resume_connection_with_server(pte);
3369 if (memcmp(buf + SIZE_HEADER, packet_recv_firm_version, sizeof(packet_recv_firm_version)) ==
3373 ast_verbose("Got the firmware version : '%s'\n", buf + 13);
3374 init_phone_step2(pte);
3377 if (memcmp(buf + SIZE_HEADER, packet_recv_mac_addr, sizeof(packet_recv_mac_addr)) == 0) {
3378 rcv_mac_addr(pte, buf);
3381 if (memcmp(buf + SIZE_HEADER, packet_recv_r2, sizeof(packet_recv_r2)) == 0) {
3383 ast_verbose("R2 received\n");
3387 if (pte->state < STATE_MAINPAGE) {
3389 ast_verbose("Request not authorized in this state\n");
3392 if (!memcmp(buf + SIZE_HEADER, packet_recv_pressed_key, sizeof(packet_recv_pressed_key))) {
3393 char keycode = buf[13];
3396 ast_verbose("Key pressed : keycode = 0x%.2x - current state : %d\n", keycode,
3399 switch (pte->state) {
3402 ast_verbose("No keys allowed in the init state\n");
3404 case STATE_AUTHDENY:
3406 ast_verbose("No keys allowed in authdeny state\n");
3408 case STATE_MAINPAGE:
3409 key_main_page(pte, keycode);
3411 case STATE_DIALPAGE:
3412 key_dial_page(pte, keycode);
3415 key_ringing(pte, keycode);
3418 key_call(pte, keycode);
3420 case STATE_EXTENSION:
3421 key_select_extension(pte, keycode);
3423 case STATE_SELECTCODEC:
3424 key_select_codec(pte, keycode);
3427 key_history(pte, keycode);
3430 ast_log(LOG_WARNING, "Key : Unknown state\n");
3434 if (memcmp(buf + SIZE_HEADER, packet_recv_pick_up, sizeof(packet_recv_pick_up)) == 0) {
3436 ast_verbose("Handset off hook\n");
3437 if (!pte->device) /* We are not yet registred (asking for a TN in AUTOPROVISIONING_TN) */
3439 pte->device->receiver_state = STATE_OFFHOOK;
3440 if (pte->device->output == OUTPUT_HEADPHONE)