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$")
42 #if defined(__CYGWIN__)
44 * cygwin headers are partly inconsistent. struct iovec is defined in sys/uio.h
45 * which is not included by default by sys/socket.h - in_pktinfo is defined in
46 * w32api/ws2tcpip.h but this probably has compatibility problems with sys/socket.h
47 * So for the time being we simply disable HAVE_PKTINFO when building under cygwin.
48 * This should be done in some common header, but for now this is the only file
49 * using iovec and in_pktinfo so it suffices to apply the fix here.
54 #endif /* __CYGWIN__ */
56 #include "asterisk/paths.h" /* ast_config_AST_LOG_DIR used in (too ?) many places */
57 #include "asterisk/network.h"
58 #include "asterisk/channel.h"
59 #include "asterisk/config.h"
60 #include "asterisk/module.h"
61 #include "asterisk/pbx.h"
62 #include "asterisk/event.h"
63 #include "asterisk/rtp_engine.h"
64 #include "asterisk/netsock.h"
65 #include "asterisk/acl.h"
66 #include "asterisk/callerid.h"
67 #include "asterisk/cli.h"
68 #include "asterisk/app.h"
69 #include "asterisk/musiconhold.h"
70 #include "asterisk/causes.h"
71 #include "asterisk/indications.h"
73 /*! Beware, G729 and G723 are not supported by asterisk, except with the proper licence */
74 #define CAPABILITY AST_FORMAT_ALAW | AST_FORMAT_ULAW /* | AST_FORMAT_G729A | AST_FORMAT_G723_1 */
76 #define DEFAULTCONTEXT "default"
77 #define DEFAULTCALLERID "Unknown"
78 #define DEFAULTCALLERNAME " "
79 #define USTM_LOG_DIR "unistimHistory"
81 /*! Size of the transmit buffer */
82 #define MAX_BUF_SIZE 64
83 /*! Number of slots for the transmit queue */
84 #define MAX_BUF_NUMBER 50
85 /*! Try x times before removing the phone */
86 #define NB_MAX_RETRANSMIT 8
87 /*! Nb of milliseconds waited when no events are scheduled */
88 #define IDLE_WAIT 1000
89 /*! Wait x milliseconds before resending a packet */
90 #define RETRANSMIT_TIMER 2000
91 /*! How often the mailbox is checked for new messages */
92 #define TIMER_MWI 10000
94 #define DEFAULT_CODEC 0x00
95 #define SIZE_PAGE 4096
96 #define DEVICE_NAME_LEN 16
97 #define AST_CONFIG_MAX_PATH 255
98 #define MAX_ENTRY_LOG 30
101 #define SUB_THREEWAY 1
105 AUTOPROVISIONING_NO = 0,
106 AUTOPROVISIONING_YES,
112 /*! Do not create an extension into the default dialplan */
114 /*! Prompt user for an extension number and register it */
116 /*! Register an extension with the line=> value */
118 /*! Used with AUTOPROVISIONING_TN */
121 #define OUTPUT_HANDSET 0xC0
122 #define OUTPUT_HEADPHONE 0xC1
123 #define OUTPUT_SPEAKER 0xC2
125 #define VOLUME_LOW 0x01
126 #define VOLUME_LOW_SPEAKER 0x03
127 #define VOLUME_NORMAL 0x02
128 #define VOLUME_INSANELY_LOUD 0x07
130 #define MUTE_OFF 0x00
132 #define MUTE_ON_DISCRET 0xCE
134 #define SIZE_HEADER 6
135 #define SIZE_MAC_ADDR 17
136 #define TEXT_LENGTH_MAX 24
137 #define TEXT_LINE0 0x00
138 #define TEXT_LINE1 0x20
139 #define TEXT_LINE2 0x40
140 #define TEXT_NORMAL 0x05
141 #define TEXT_INVERSE 0x25
142 #define STATUS_LENGTH_MAX 28
144 #define FAV_ICON_NONE 0x00
145 #define FAV_ICON_ONHOOK_BLACK 0x20
146 #define FAV_ICON_ONHOOK_WHITE 0x21
147 #define FAV_ICON_SPEAKER_ONHOOK_BLACK 0x22
148 #define FAV_ICON_SPEAKER_ONHOOK_WHITE 0x23
149 #define FAV_ICON_OFFHOOK_BLACK 0x24
150 #define FAV_ICON_OFFHOOK_WHITE 0x25
151 #define FAV_ICON_ONHOLD_BLACK 0x26
152 #define FAV_ICON_ONHOLD_WHITE 0x27
153 #define FAV_ICON_SPEAKER_OFFHOOK_BLACK 0x28
154 #define FAV_ICON_SPEAKER_OFFHOOK_WHITE 0x29
155 #define FAV_ICON_PHONE_BLACK 0x2A
156 #define FAV_ICON_PHONE_WHITE 0x2B
157 #define FAV_ICON_SPEAKER_ONHOLD_BLACK 0x2C
158 #define FAV_ICON_SPEAKER_ONHOLD_WHITE 0x2D
159 #define FAV_ICON_HEADPHONES 0x2E
160 #define FAV_ICON_HEADPHONES_ONHOLD 0x2F
161 #define FAV_ICON_HOME 0x30
162 #define FAV_ICON_CITY 0x31
163 #define FAV_ICON_SHARP 0x32
164 #define FAV_ICON_PAGER 0x33
165 #define FAV_ICON_CALL_CENTER 0x34
166 #define FAV_ICON_FAX 0x35
167 #define FAV_ICON_MAILBOX 0x36
168 #define FAV_ICON_REFLECT 0x37
169 #define FAV_ICON_COMPUTER 0x38
170 #define FAV_ICON_FORWARD 0x39
171 #define FAV_ICON_LOCKED 0x3A
172 #define FAV_ICON_TRASH 0x3B
173 #define FAV_ICON_INBOX 0x3C
174 #define FAV_ICON_OUTBOX 0x3D
175 #define FAV_ICON_MEETING 0x3E
176 #define FAV_ICON_BOX 0x3F
178 #define FAV_BLINK_FAST 0x20
179 #define FAV_BLINK_SLOW 0x40
181 #define FAV_MAX_LENGTH 0x0A
183 static void dummy(char *unused, ...)
188 /*! \brief Global jitterbuffer configuration - by default, jb is disabled */
189 static struct ast_jb_conf default_jbconf =
193 .resync_threshold = -1,
196 static struct ast_jb_conf global_jbconf;
199 /* #define DUMP_PACKET 1 */
200 /* #define DEBUG_TIMER ast_verbose */
202 #define DEBUG_TIMER dummy
203 /*! Enable verbose output. can also be set with the CLI */
204 static int unistimdebug = 0;
205 static int unistim_port;
206 static enum autoprovision autoprovisioning = AUTOPROVISIONING_NO;
207 static int unistim_keepalive;
208 static int unistimsock = -1;
212 unsigned int tos_audio;
214 unsigned int cos_audio;
215 } qos = { 0, 0, 0, 0 };
217 static struct io_context *io;
218 static struct sched_context *sched;
219 static struct sockaddr_in public_ip = { 0, };
220 /*! give the IP address for the last packet received */
221 static struct sockaddr_in address_from;
222 /*! size of the sockaddr_in (in WSARecvFrom) */
223 static unsigned int size_addr_from = sizeof(address_from);
224 /*! Receive buffer address */
225 static unsigned char *buff;
226 static int unistim_reloading = 0;
227 AST_MUTEX_DEFINE_STATIC(unistim_reload_lock);
228 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
229 static int usecnt = 0;
230 /* extern char ast_config_AST_LOG_DIR[AST_CONFIG_MAX_PATH]; */
232 /*! This is the thread for the monitor which checks for input on the channels
233 * which are not currently in use. */
234 static pthread_t monitor_thread = AST_PTHREADT_NULL;
236 /*! Protect the monitoring thread, so only one process can kill or start it, and not
237 * when it's doing something critical. */
238 AST_MUTEX_DEFINE_STATIC(monlock);
239 /*! Protect the session list */
240 AST_MUTEX_DEFINE_STATIC(sessionlock);
241 /*! Protect the device list */
242 AST_MUTEX_DEFINE_STATIC(devicelock);
303 struct tone_zone_unistim {
309 static const struct tone_zone_unistim frequency[] = {
349 unsigned short w_year;
350 unsigned short w_month;
351 unsigned short w_day_of_week;
352 unsigned short w_day;
353 unsigned short w_hour;
354 unsigned short w_minute;
355 unsigned short w_second;
356 unsigned short w_milliseconds;
359 struct unistim_subchannel {
361 /*! SUBS_REAL or SUBS_THREEWAY */
362 unsigned int subtype;
363 /*! Asterisk channel used by the subchannel */
364 struct ast_channel *owner;
366 struct unistim_line *parent;
368 struct ast_rtp_instance *rtp;
375 * \todo Convert to stringfields
377 struct unistim_line {
381 /*! Like USTM/200\@black */
383 /*! pointer to our current connection, channel... */
384 struct unistim_subchannel *subs[MAX_SUBS];
385 /*! Extension where to start */
386 char exten[AST_MAX_EXTENSION];
387 /*! Context to start in */
388 char context[AST_MAX_EXTENSION];
389 /*! Language for asterisk sounds */
390 char language[MAX_LANGUAGE];
391 /*! CallerID Number */
392 char cid_num[AST_MAX_EXTENSION];
393 /*! Mailbox for MWI */
394 char mailbox[AST_MAX_EXTENSION];
399 /*! MusicOnHold class */
400 char musicclass[MAX_MUSICCLASS];
402 unsigned int callgroup;
404 unsigned int pickupgroup;
405 /*! Account code (for billing) */
406 char accountcode[80];
407 /*! AMA flags (for billing) */
409 /*! Codec supported */
412 char parkinglot[AST_MAX_CONTEXT];
413 struct unistim_line *next;
414 struct unistim_device *parent;
418 * \brief A device containing one or more lines
420 static struct unistim_device {
421 int receiver_state; /*!< state of the receiver (see ReceiverState) */
422 int size_phone_number; /*!< size of the phone number */
423 char phone_number[16]; /*!< the phone number entered by the user */
424 char redial_number[16]; /*!< the last phone number entered by the user */
425 int phone_current; /*!< Number of the current phone */
426 int pos_fav; /*!< Position of the displayed favorites (used for scrolling) */
427 char id[18]; /*!< mac address of the current phone in ascii */
428 char name[DEVICE_NAME_LEN]; /*!< name of the device */
429 int softkeylinepos; /*!< position of the line softkey (default 0) */
430 char softkeylabel[6][11]; /*!< soft key label */
431 char softkeynumber[6][16]; /*!< number dialed when the soft key is pressed */
432 char softkeyicon[6]; /*!< icon number */
433 char softkeydevice[6][16]; /*!< name of the device monitored */
434 struct unistim_device *sp[6]; /*!< pointer to the device monitored by this soft key */
435 char maintext0[25]; /*!< when the phone is idle, display this string on line 0 */
436 char maintext1[25]; /*!< when the phone is idle, display this string on line 1 */
437 char maintext2[25]; /*!< when the phone is idle, display this string on line 2 */
438 char titledefault[13]; /*!< title (text before date/time) */
439 char datetimeformat; /*!< format used for displaying time/date */
440 char contrast; /*!< contrast */
441 char country[3]; /*!< country used for dial tone frequency */
442 struct ast_tone_zone *tz; /*!< Tone zone for res_indications (ring, busy, congestion) */
443 char ringvolume; /*!< Ring volume */
444 char ringstyle; /*!< Ring melody */
445 int rtp_port; /*!< RTP port used by the phone */
446 int rtp_method; /*!< Select the unistim data used to establish a RTP session */
447 int status_method; /*!< Select the unistim packet used for sending status text */
448 char codec_number; /*!< The current codec used to make calls */
449 int missed_call; /*!< Number of call unanswered */
450 int callhistory; /*!< Allowed to record call history */
451 char lst_cid[TEXT_LENGTH_MAX]; /*!< Last callerID received */
452 char lst_cnm[TEXT_LENGTH_MAX]; /*!< Last callername recevied */
453 char call_forward[AST_MAX_EXTENSION]; /*!< Forward number */
454 int output; /*!< Handset, headphone or speaker */
455 int previous_output; /*!< Previous output */
456 int volume; /*!< Default volume */
457 int mute; /*!< Mute mode */
458 int moh; /*!< Music on hold in progress */
459 int nat; /*!< Used by the obscure ast_rtp_setnat */
460 enum autoprov_extn extension; /*!< See ifdef EXTENSION for valid values */
461 char extension_number[11]; /*!< Extension number entered by the user */
462 char to_delete; /*!< Used in reload */
463 time_t start_call_timestamp; /*!< timestamp for the length calculation of the call */
464 struct ast_silence_generator *silence_generator;
465 struct unistim_line *lines;
467 struct unistimsession *session;
468 struct unistim_device *next;
471 static struct unistimsession {
473 struct sockaddr_in sin; /*!< IP address of the phone */
474 struct sockaddr_in sout; /*!< IP address of server */
475 int timeout; /*!< time-out in ticks : resend packet if no ack was received before the timeout occured */
476 unsigned short seq_phone; /*!< sequence number for the next packet (when we receive a request) */
477 unsigned short seq_server; /*!< sequence number for the next packet (when we send a request) */
478 unsigned short last_seq_ack; /*!< sequence number of the last ACK received */
479 unsigned long tick_next_ping; /*!< time for the next ping */
480 int last_buf_available; /*!< number of a free slot */
481 int nb_retransmit; /*!< number of retransmition */
482 int state; /*!< state of the phone (see phone_state) */
483 int size_buff_entry; /*!< size of the buffer used to enter datas */
484 char buff_entry[16]; /*!< Buffer for temporary datas */
485 char macaddr[18]; /*!< mac adress of the phone (not always available) */
486 struct wsabuf wsabufsend[MAX_BUF_NUMBER]; /*!< Size of each paquet stored in the buffer array & pointer to this buffer */
487 unsigned char buf[MAX_BUF_NUMBER][MAX_BUF_SIZE]; /*!< Buffer array used to keep the lastest non-acked paquets */
488 struct unistim_device *device;
489 struct unistimsession *next;
493 * \page Unistim datagram formats
495 * Format of datagrams :
496 * bytes 0 & 1 : ffff for discovery packet, 0000 for everything else
497 * byte 2 : sequence number (high part)
498 * byte 3 : sequence number (low part)
499 * byte 4 : 2 = ask question or send info, 1 = answer or ACK, 0 = retransmit request
500 * byte 5 : direction, 1 = server to phone, 2 = phone to server arguments
503 static const unsigned char packet_rcv_discovery[] =
504 { 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
505 static unsigned char packet_send_discovery_ack[] =
506 { 0x00, 0x00, /*Initial Seq (2 bytes) */ 0x00, 0x00, 0x00, 0x01 };
508 static const unsigned char packet_recv_firm_version[] =
509 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x0a, 0x02 };
510 static const unsigned char packet_recv_pressed_key[] =
511 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x04, 0x00 };
512 static const unsigned char packet_recv_pick_up[] =
513 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x04 };
514 static const unsigned char packet_recv_hangup[] =
515 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x03 };
516 static const unsigned char packet_recv_r2[] = { 0x00, 0x00, 0x00, 0x13, 0x96, 0x03, 0x03 };
518 /*! TransportAdapter */
519 static const unsigned char packet_recv_resume_connection_with_server[] =
520 { 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
521 static const unsigned char packet_recv_mac_addr[] =
522 { 0xff, 0xff, 0xff, 0xff, 0x9a, 0x0d, 0x07 /*MacAddr */ };
524 static const unsigned char packet_send_date_time3[] =
525 { 0x11, 0x09, 0x02, 0x02, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07,
526 /*Minutes */ 0x08, 0x32
528 static const unsigned char packet_send_date_time[] =
529 { 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07, /*Minutes */
530 0x08, 0x32, 0x17, 0x04, 0x24, 0x07, 0x19,
531 0x04, 0x07, 0x00, 0x19, 0x05, 0x09, 0x3e, 0x0f, 0x16, 0x05, 0x00, 0x80, 0x00, 0x1e,
532 0x05, 0x12, 0x00, 0x78
535 static const unsigned char packet_send_no_ring[] =
536 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00 };
537 static const unsigned char packet_send_s4[] =
538 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff,
539 0x16, 0x05, 0x1c, 0x00, 0x00, 0x17, 0x05,
540 0x0b, 0x00, 0x00, 0x19, 0x04, 0x00, 0x00, 0x19, 0x04, 0x00, 0x08, 0x19, 0x04, 0x00,
541 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
542 0x31, 0x00, 0x00, 0x16, 0x05, 0x04, 0x00, 0x00
544 static const unsigned char packet_send_call[] =
545 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf,
546 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16, 0x0a, 0x38, 0x00, 0x12, 0xca, 0x03,
547 0xc0, 0xc3, 0xc5, 0x16, 0x16, 0x30, 0x00,
548 0x00, /*codec */ 0x12, 0x12, /* frames per packet */ 0x01, 0x5c, 0x00, /*port RTP */
549 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41,
550 /*port RTP */ 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41, /* IP Address */ 0x0a, 0x01,
553 static const unsigned char packet_send_stream_based_tone_off[] =
554 { 0x16, 0x05, 0x1c, 0x00, 0x00 };
556 /* static const unsigned char packet_send_Mute[] = { 0x16, 0x05, 0x04, 0x00, 0x00 };
557 static const unsigned char packet_send_CloseAudioStreamRX[] = { 0x16, 0x05, 0x31, 0x00, 0xff };
558 static const unsigned char packet_send_CloseAudioStreamTX[] = { 0x16, 0x05, 0x31, 0xff, 0x00 };*/
559 static const unsigned char packet_send_stream_based_tone_on[] =
560 { 0x16, 0x06, 0x1b, 0x00, 0x00, 0x05 };
561 static const unsigned char packet_send_stream_based_tone_single_freq[] =
562 { 0x16, 0x06, 0x1d, 0x00, 0x01, 0xb8 };
563 static const unsigned char packet_send_stream_based_tone_dial_freq[] =
564 { 0x16, 0x08, 0x1d, 0x00, 0x01, 0xb8, 0x01, 0x5e };
565 static const unsigned char packet_send_select_output[] =
566 { 0x16, 0x06, 0x32, 0xc0, 0x01, 0x00 };
567 static const unsigned char packet_send_ring[] =
568 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16,
569 0x04, 0x1a, 0x01, 0x16, 0x05, 0x12, 0x13 /* Ring type 10 to 17 */ , 0x18, 0x16, 0x04, 0x18, /* volume 00, 10, 20... */
570 0x20, 0x16, 0x04, 0x10, 0x00
572 static const unsigned char packet_send_end_call[] =
573 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x31, 0x00, 0x00, 0x19, 0x04, 0x00,
574 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
575 0x04, 0x00, 0x00, 0x16, 0x04, 0x37, 0x10
577 static const unsigned char packet_send_s9[] =
578 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x19, 0x04, 0x00, 0x10, 0x16, 0x05, 0x1c, 0x00,
580 static const unsigned char packet_send_rtp_packet_size[] =
581 { 0x16, 0x08, 0x38, 0x00, 0x00, 0xe0, 0x00, 0xa0 };
582 static const unsigned char packet_send_jitter_buffer_conf[] =
583 { 0x16, 0x0e, 0x3a, 0x00, /* jitter */ 0x02, /* high water mark */ 0x04, 0x00, 0x00,
584 /* early packet resync 2 bytes */ 0x3e, 0x80,
585 0x00, 0x00, /* late packet resync 2 bytes */ 0x3e, 0x80
588 /* Duration in ms div 2 (0x20 = 64ms, 0x08 = 16ms)
589 static unsigned char packet_send_StreamBasedToneCad[] =
590 { 0x16, 0x0a, 0x1e, 0x00, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x2b }; */
591 static const unsigned char packet_send_open_audio_stream_rx[] =
592 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
593 0x0e, 0x01, /* Port */ 0x14, 0x50, 0x00,
594 0x00, /* Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
596 static const unsigned char packet_send_open_audio_stream_tx[] =
597 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
598 0x0e, 0x01, /* Local port */ 0x14, 0x50,
599 0x00, 0x00, /* Rmt Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
602 static const unsigned char packet_send_open_audio_stream_rx3[] =
603 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
604 0x06, 0x81, /* RTP Port */ 0x14, 0x50,
605 /* RTCP Port */ 0x14,
606 0x51, /* RTP Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00, /* Dest IP */ 0x0a, 0x93,
609 static const unsigned char packet_send_open_audio_stream_tx3[] =
610 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
611 0x06, 0x81, /* RTP Local port */ 0x14, 0x50,
612 /* RTCP Port */ 0x00, 0x00, /* RTP Rmt Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00,
613 /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
616 static const unsigned char packet_send_arrow[] = { 0x17, 0x04, 0x04, 0x00 };
617 static const unsigned char packet_send_blink_cursor[] = { 0x17, 0x04, 0x10, 0x86 };
618 static const unsigned char packet_send_date_time2[] = { 0x17, 0x04, 0x17, 0x3d, 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */
619 0x06, /*Hour */ 0x07, /*Minutes */ 0x08, 0x32
621 static const unsigned char packet_send_Contrast[] =
622 { 0x17, 0x04, 0x24, /*Contrast */ 0x08 };
623 static const unsigned char packet_send_StartTimer[] =
624 { 0x17, 0x05, 0x0b, 0x05, 0x00, 0x17, 0x08, 0x16, /* Text */ 0x44, 0x75, 0x72, 0xe9,
626 static const unsigned char packet_send_stop_timer[] = { 0x17, 0x05, 0x0b, 0x02, 0x00 };
627 static const unsigned char packet_send_icon[] = { 0x17, 0x05, 0x14, /*pos */ 0x00, /*icon */ 0x25 }; /* display an icon in front of the text zone */
628 static const unsigned char packet_send_S7[] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 };
629 static const unsigned char packet_send_set_pos_cursor[] =
630 { 0x17, 0x06, 0x10, 0x81, 0x04, /*pos */ 0x20 };
632 /*static unsigned char packet_send_MonthLabelsDownload[] =
633 { 0x17, 0x0a, 0x15, Month (3 char) 0x46, 0x65, 0x62, 0x4d, 0xe4, 0x72, 0x20 }; */
634 static const unsigned char packet_send_favorite[] =
635 { 0x17, 0x0f, 0x19, 0x10, /*pos */ 0x01, /*name */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
636 0x20, 0x20, 0x20, 0x20, /*end_name */ 0x19,
637 0x05, 0x0f, /*pos */ 0x01, /*icone */ 0x00
639 static const unsigned char packet_send_title[] =
640 { 0x17, 0x10, 0x19, 0x02, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
641 0x20, 0x20, 0x20, 0x20 /*end_text */ };
642 static const unsigned char packet_send_text[] =
643 { 0x17, 0x1e, 0x1b, 0x04, /*pos */ 0x00, /*inverse */ 0x25, /*text */ 0x20, 0x20,
644 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
645 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
646 /*end_text */ 0x17, 0x04, 0x10, 0x87
648 static const unsigned char packet_send_status[] =
649 { 0x17, 0x20, 0x19, 0x08, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
650 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
651 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 /*end_text */
653 static const unsigned char packet_send_status2[] =
654 { 0x17, 0x0b, 0x19, /* pos [08|28|48|68] */ 0x00, /* text */ 0x20, 0x20, 0x20, 0x20,
655 0x20, 0x20, 0x20 /* end_text */ };
657 static const unsigned char packet_send_led_update[] = { 0x19, 0x04, 0x00, 0x00 };
659 static const unsigned char packet_send_query_basic_manager_04[] = { 0x1a, 0x04, 0x01, 0x04 };
660 static const unsigned char packet_send_query_mac_address[] = { 0x1a, 0x04, 0x01, 0x08 };
661 static const unsigned char packet_send_query_basic_manager_10[] = { 0x1a, 0x04, 0x01, 0x10 };
662 static const unsigned char packet_send_S1[] = { 0x1a, 0x07, 0x07, 0x00, 0x00, 0x00, 0x13 };
664 static unsigned char packet_send_ping[] =
665 { 0x1e, 0x05, 0x12, 0x00, /*Watchdog timer */ 0x78 };
667 #define BUFFSEND unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }
669 static const char tdesc[] = "UNISTIM Channel Driver";
670 static const char channel_type[] = "USTM";
673 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state);
674 static int load_module(void);
675 static int reload(void);
676 static int unload_module(void);
677 static int reload_config(void);
678 static void show_main_page(struct unistimsession *pte);
679 static struct ast_channel *unistim_request(const char *type, int format,
680 void *data, int *cause);
681 static int unistim_call(struct ast_channel *ast, char *dest, int timeout);
682 static int unistim_hangup(struct ast_channel *ast);
683 static int unistim_answer(struct ast_channel *ast);
684 static struct ast_frame *unistim_read(struct ast_channel *ast);
685 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame);
686 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
688 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
689 static int unistim_senddigit_begin(struct ast_channel *ast, char digit);
690 static int unistim_senddigit_end(struct ast_channel *ast, char digit,
691 unsigned int duration);
692 static int unistim_sendtext(struct ast_channel *ast, const char *text);
694 static int write_entry_history(struct unistimsession *pte, FILE * f, char c,
696 static void change_callerid(struct unistimsession *pte, int type, char *callerid);
698 static const struct ast_channel_tech unistim_tech = {
699 .type = channel_type,
700 .description = tdesc,
701 .capabilities = CAPABILITY,
702 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
703 .requester = unistim_request,
704 .call = unistim_call,
705 .hangup = unistim_hangup,
706 .answer = unistim_answer,
707 .read = unistim_read,
708 .write = unistim_write,
709 .indicate = unistim_indicate,
710 .fixup = unistim_fixup,
711 .send_digit_begin = unistim_senddigit_begin,
712 .send_digit_end = unistim_senddigit_end,
713 .send_text = unistim_sendtext,
714 .bridge = ast_rtp_instance_bridge,
717 static void display_last_error(const char *sz_msg)
723 /* Display the error message */
724 ast_log(LOG_WARNING, "%s %s : (%u) %s\n", ctime(&cur_time), sz_msg, errno,
728 static unsigned int get_tick_count(void)
730 struct timeval now = ast_tvnow();
732 return (now.tv_sec * 1000) + (now.tv_usec / 1000);
735 /* Send data to a phone without retransmit nor buffering */
736 static void send_raw_client(int size, unsigned char *data, struct sockaddr_in *addr_to,
737 const struct sockaddr_in *addr_ourip)
740 struct iovec msg_iov;
742 char buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
743 struct cmsghdr *ip_msg = (struct cmsghdr *) buffer;
744 struct in_pktinfo *pki = (struct in_pktinfo *) CMSG_DATA(ip_msg);
746 msg_iov.iov_base = data;
747 msg_iov.iov_len = size;
749 msg.msg_name = addr_to; /* optional address */
750 msg.msg_namelen = sizeof(struct sockaddr_in); /* size of address */
751 msg.msg_iov = &msg_iov; /* scatter/gather array */
752 msg.msg_iovlen = 1; /* # elements in msg_iov */
753 msg.msg_control = ip_msg; /* ancillary data */
754 msg.msg_controllen = sizeof(buffer); /* ancillary data buffer len */
755 msg.msg_flags = 0; /* flags on received message */
757 ip_msg->cmsg_len = CMSG_LEN(sizeof(*pki));
758 ip_msg->cmsg_level = IPPROTO_IP;
759 ip_msg->cmsg_type = IP_PKTINFO;
760 pki->ipi_ifindex = 0; /* Interface index, 0 = use interface specified in routing table */
761 pki->ipi_spec_dst.s_addr = addr_ourip->sin_addr.s_addr; /* Local address */
762 /* pki->ipi_addr = ; Header Destination address - ignored by kernel */
767 char iabuf[INET_ADDRSTRLEN];
768 char iabuf2[INET_ADDRSTRLEN];
769 ast_verb(0, "\n**> From %s sending %d bytes to %s ***\n",
770 ast_inet_ntoa(addr_ourip->sin_addr), (int) size,
771 ast_inet_ntoa(addr_to->sin_addr));
772 for (tmp = 0; tmp < size; tmp++)
773 ast_verb(0, "%.2x ", (unsigned char) data[tmp]);
774 ast_verb(0, "\n******************************************\n");
779 if (sendmsg(unistimsock, &msg, 0) == -1)
780 display_last_error("Error sending datas");
782 if (sendto(unistimsock, data, size, 0, (struct sockaddr *) addr_to, sizeof(*addr_to))
784 display_last_error("Error sending datas");
788 static void send_client(int size, const unsigned char *data, struct unistimsession *pte)
792 unsigned short *sdata = (unsigned short *) data;
794 ast_mutex_lock(&pte->lock);
795 buf_pos = pte->last_buf_available;
797 if (buf_pos >= MAX_BUF_NUMBER) {
798 ast_log(LOG_WARNING, "Error : send queue overflow\n");
799 ast_mutex_unlock(&pte->lock);
802 sdata[1] = ntohs(++(pte->seq_server));
803 pte->wsabufsend[buf_pos].len = size;
804 memcpy(pte->wsabufsend[buf_pos].buf, data, size);
806 tick = get_tick_count();
807 pte->timeout = tick + RETRANSMIT_TIMER;
809 /*#ifdef DUMP_PACKET */
811 ast_verb(6, "Sending datas with seq #0x%.4x Using slot #%d :\n", pte->seq_server, buf_pos);
813 send_raw_client(pte->wsabufsend[buf_pos].len, pte->wsabufsend[buf_pos].buf, &(pte->sin),
815 pte->last_buf_available++;
816 ast_mutex_unlock(&pte->lock);
819 static void send_ping(struct unistimsession *pte)
823 ast_verb(6, "Sending ping\n");
824 pte->tick_next_ping = get_tick_count() + unistim_keepalive;
825 memcpy(buffsend + SIZE_HEADER, packet_send_ping, sizeof(packet_send_ping));
826 send_client(SIZE_HEADER + sizeof(packet_send_ping), buffsend, pte);
829 static int get_to_address(int fd, struct sockaddr_in *toAddr)
837 struct in_addr address;
840 /* Zero out the structures before we use them */
841 /* This sets several key values to NULL */
842 memset(&msg, 0, sizeof(msg));
843 memset(&ip_msg, 0, sizeof(ip_msg));
845 /* Initialize the message structure */
846 msg.msg_control = &ip_msg;
847 msg.msg_controllen = sizeof(ip_msg);
848 /* Get info about the incoming packet */
849 err = recvmsg(fd, &msg, MSG_PEEK);
851 ast_log(LOG_WARNING, "recvmsg returned an error: %s\n", strerror(errno));
852 memcpy(&toAddr->sin_addr, &ip_msg.address, sizeof(struct in_addr));
855 memcpy(&toAddr, &public_ip, sizeof(&toAddr));
860 /* Allocate memory & initialize structures for a new phone */
861 /* addr_from : ip address of the phone */
862 static struct unistimsession *create_client(const struct sockaddr_in *addr_from)
865 struct unistimsession *s;
867 if (!(s = ast_calloc(1, sizeof(*s))))
870 memcpy(&s->sin, addr_from, sizeof(struct sockaddr_in));
871 get_to_address(unistimsock, &s->sout);
873 ast_verb(0, "Creating a new entry for the phone from %s received via server ip %s\n",
874 ast_inet_ntoa(addr_from->sin_addr), ast_inet_ntoa(s->sout.sin_addr));
876 ast_mutex_init(&s->lock);
877 ast_mutex_lock(&sessionlock);
881 s->timeout = get_tick_count() + RETRANSMIT_TIMER;
882 s->seq_phone = (short) 0x0000;
883 s->seq_server = (short) 0x0000;
884 s->last_seq_ack = (short) 0x000;
885 s->last_buf_available = 0;
886 s->nb_retransmit = 0;
887 s->state = STATE_INIT;
888 s->tick_next_ping = get_tick_count() + unistim_keepalive;
889 /* Initialize struct wsabuf */
890 for (tmp = 0; tmp < MAX_BUF_NUMBER; tmp++) {
891 s->wsabufsend[tmp].buf = s->buf[tmp];
893 ast_mutex_unlock(&sessionlock);
897 static void send_end_call(struct unistimsession *pte)
901 ast_verb(0, "Sending end call\n");
902 memcpy(buffsend + SIZE_HEADER, packet_send_end_call, sizeof(packet_send_end_call));
903 send_client(SIZE_HEADER + sizeof(packet_send_end_call), buffsend, pte);
906 static void set_ping_timer(struct unistimsession *pte)
908 unsigned int tick = 0; /* XXX what is this for, anyways */
910 pte->timeout = pte->tick_next_ping;
911 DEBUG_TIMER("tick = %u next ping at %u tick\n", tick, pte->timeout);
915 /* Checking if our send queue is empty,
916 * if true, setting up a timer for keepalive */
917 static void check_send_queue(struct unistimsession *pte)
919 /* Check if our send queue contained only one element */
920 if (pte->last_buf_available == 1) {
922 ast_verb(6, "Our single packet was ACKed.\n");
923 pte->last_buf_available--;
927 /* Check if this ACK catch up our latest packet */
928 else if (pte->last_seq_ack + 1 == pte->seq_server + 1) {
930 ast_verb(6, "Our send queue is completely ACKed.\n");
931 pte->last_buf_available = 0; /* Purge the send queue */
936 ast_verb(6, "We still have packets in our send queue\n");
940 static void send_start_timer(struct unistimsession *pte)
944 ast_verb(0, "Sending start timer\n");
945 memcpy(buffsend + SIZE_HEADER, packet_send_StartTimer, sizeof(packet_send_StartTimer));
946 send_client(SIZE_HEADER + sizeof(packet_send_StartTimer), buffsend, pte);
949 static void send_stop_timer(struct unistimsession *pte)
953 ast_verb(0, "Sending stop timer\n");
954 memcpy(buffsend + SIZE_HEADER, packet_send_stop_timer, sizeof(packet_send_stop_timer));
955 send_client(SIZE_HEADER + sizeof(packet_send_stop_timer), buffsend, pte);
958 static void Sendicon(unsigned char pos, unsigned char status, struct unistimsession *pte)
962 ast_verb(0, "Sending icon pos %d with status 0x%.2x\n", pos, status);
963 memcpy(buffsend + SIZE_HEADER, packet_send_icon, sizeof(packet_send_icon));
965 buffsend[10] = status;
966 send_client(SIZE_HEADER + sizeof(packet_send_icon), buffsend, pte);
969 static void send_tone(struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
974 ast_verb(0, "Sending Stream Based Tone Off\n");
975 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_off,
976 sizeof(packet_send_stream_based_tone_off));
977 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_off), buffsend, pte);
980 /* Since most of the world use a continuous tone, it's useless
982 ast_verb(0, "Sending Stream Based Tone Cadence Download\n");
983 memcpy (buffsend + SIZE_HEADER, packet_send_StreamBasedToneCad, sizeof (packet_send_StreamBasedToneCad));
984 send_client (SIZE_HEADER + sizeof (packet_send_StreamBasedToneCad), buffsend, pte); */
986 ast_verb(0, "Sending Stream Based Tone Frequency Component List Download %d %d\n", tone1, tone2);
989 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_single_freq,
990 sizeof(packet_send_stream_based_tone_single_freq));
991 buffsend[10] = (tone1 & 0xff00) >> 8;
992 buffsend[11] = (tone1 & 0x00ff);
993 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_single_freq), buffsend,
997 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dial_freq,
998 sizeof(packet_send_stream_based_tone_dial_freq));
999 buffsend[10] = (tone1 & 0xff00) >> 8;
1000 buffsend[11] = (tone1 & 0x00ff);
1001 buffsend[12] = (tone2 & 0xff00) >> 8;
1002 buffsend[13] = (tone2 & 0x00ff);
1003 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_dial_freq), buffsend,
1008 ast_verb(0, "Sending Stream Based Tone On\n");
1009 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_on,
1010 sizeof(packet_send_stream_based_tone_on));
1011 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_on), buffsend, pte);
1014 /* Positions for favorites
1015 |--------------------|
1021 /* status (icons) : 00 = nothing, 2x/3x = see parser.h, 4x/5x = blink fast, 6x/7x = blink slow */
1023 send_favorite(unsigned char pos, unsigned char status, struct unistimsession *pte,
1030 ast_verb(0, "Sending favorite pos %d with status 0x%.2x\n", pos, status);
1031 memcpy(buffsend + SIZE_HEADER, packet_send_favorite, sizeof(packet_send_favorite));
1034 buffsend[25] = status;
1036 if (i > FAV_MAX_LENGTH)
1038 memcpy(buffsend + FAV_MAX_LENGTH + 1, text, i);
1039 send_client(SIZE_HEADER + sizeof(packet_send_favorite), buffsend, pte);
1042 static void refresh_all_favorite(struct unistimsession *pte)
1047 ast_verb(0, "Refreshing all favorite\n");
1048 for (i = 0; i < 6; i++) {
1049 if ((pte->device->softkeyicon[i] <= FAV_ICON_HEADPHONES_ONHOLD) &&
1050 (pte->device->softkeylinepos != i))
1051 send_favorite((unsigned char) i, pte->device->softkeyicon[i] + 1, pte,
1052 pte->device->softkeylabel[i]);
1054 send_favorite((unsigned char) i, pte->device->softkeyicon[i], pte,
1055 pte->device->softkeylabel[i]);
1060 /* Change the status for this phone (pte) and update for each phones where pte is bookmarked
1061 * use FAV_ICON_*_BLACK constant in status parameters */
1062 static void change_favorite_icon(struct unistimsession *pte, unsigned char status)
1064 struct unistim_device *d = devices;
1066 /* Update the current phone */
1067 if (pte->state != STATE_CLEANING)
1068 send_favorite(pte->device->softkeylinepos, status, pte,
1069 pte->device->softkeylabel[pte->device->softkeylinepos]);
1070 /* Notify other phones if we're in their bookmark */
1072 for (i = 0; i < 6; i++) {
1073 if (d->sp[i] == pte->device) { /* It's us ? */
1074 if (d->softkeyicon[i] != status) { /* Avoid resending the same icon */
1075 d->softkeyicon[i] = status;
1077 send_favorite(i, status + 1, d->session, d->softkeylabel[i]);
1085 static int RegisterExtension(const struct unistimsession *pte)
1088 ast_verb(0, "Trying to register extension '%s' into context '%s' to %s\n",
1089 pte->device->extension_number, pte->device->lines->context,
1090 pte->device->lines->fullname);
1091 return ast_add_extension(pte->device->lines->context, 0,
1092 pte->device->extension_number, 1, NULL, NULL, "Dial",
1093 pte->device->lines->fullname, 0, "Unistim");
1096 static int UnregisterExtension(const struct unistimsession *pte)
1099 ast_verb(0, "Trying to unregister extension '%s' context '%s'\n",
1100 pte->device->extension_number, pte->device->lines->context);
1101 return ast_context_remove_extension(pte->device->lines->context,
1102 pte->device->extension_number, 1, "Unistim");
1105 /* Free memory allocated for a phone */
1106 static void close_client(struct unistimsession *s)
1108 struct unistim_subchannel *sub;
1109 struct unistimsession *cur, *prev = NULL;
1110 ast_mutex_lock(&sessionlock);
1112 /* Looking for the session in the linked chain */
1119 if (cur) { /* Session found ? */
1120 if (cur->device) { /* This session was registered ? */
1121 s->state = STATE_CLEANING;
1123 ast_verb(0, "close_client session %p device %p lines %p sub %p\n",
1124 s, s->device, s->device->lines,
1125 s->device->lines->subs[SUB_REAL]);
1126 change_favorite_icon(s, FAV_ICON_NONE);
1127 sub = s->device->lines->subs[SUB_REAL];
1129 if (sub->owner) { /* Call in progress ? */
1131 ast_verb(0, "Aborting call\n");
1132 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NETWORK_OUT_OF_ORDER);
1135 ast_log(LOG_WARNING, "Freeing a client with no subchannel !\n");
1136 if (!ast_strlen_zero(s->device->extension_number))
1137 UnregisterExtension(s);
1138 cur->device->session = NULL;
1141 ast_verb(0, "Freeing an unregistered client\n");
1144 prev->next = cur->next;
1146 sessions = cur->next;
1147 ast_mutex_destroy(&s->lock);
1150 ast_log(LOG_WARNING, "Trying to delete non-existent session %p?\n", s);
1151 ast_mutex_unlock(&sessionlock);
1155 /* Return 1 if the session chained link was modified */
1156 static int send_retransmit(struct unistimsession *pte)
1160 ast_mutex_lock(&pte->lock);
1161 if (++pte->nb_retransmit >= NB_MAX_RETRANSMIT) {
1163 ast_verb(0, "Too many retransmit - freeing client\n");
1164 ast_mutex_unlock(&pte->lock);
1168 pte->timeout = get_tick_count() + RETRANSMIT_TIMER;
1170 for (i = pte->last_buf_available - (pte->seq_server - pte->last_seq_ack);
1171 i < pte->last_buf_available; i++) {
1173 ast_log(LOG_WARNING,
1174 "Asked to retransmit an ACKed slot ! last_buf_available=%d, seq_server = #0x%.4x last_seq_ack = #0x%.4x\n",
1175 pte->last_buf_available, pte->seq_server, pte->last_seq_ack);
1180 unsigned short *sbuf = (unsigned short *) pte->wsabufsend[i].buf;
1183 seq = ntohs(sbuf[1]);
1184 ast_verb(0, "Retransmit slot #%d (seq=#0x%.4x), last ack was #0x%.4x\n", i,
1185 seq, pte->last_seq_ack);
1187 send_raw_client(pte->wsabufsend[i].len, pte->wsabufsend[i].buf, &pte->sin,
1190 ast_mutex_unlock(&pte->lock);
1194 /* inverse : TEXT_INVERSE : yes, TEXT_NORMAL : no */
1196 send_text(unsigned char pos, unsigned char inverse, struct unistimsession *pte,
1202 ast_verb(0, "Sending text at pos %d, inverse flag %d\n", pos, inverse);
1203 memcpy(buffsend + SIZE_HEADER, packet_send_text, sizeof(packet_send_text));
1205 buffsend[11] = inverse;
1207 if (i > TEXT_LENGTH_MAX)
1208 i = TEXT_LENGTH_MAX;
1209 memcpy(buffsend + 12, text, i);
1210 send_client(SIZE_HEADER + sizeof(packet_send_text), buffsend, pte);
1213 static void send_text_status(struct unistimsession *pte, const char *text)
1218 ast_verb(0, "Sending status text\n");
1220 if (pte->device->status_method == 1) { /* For new firmware and i2050 soft phone */
1221 int n = strlen(text);
1222 /* Must send individual button separately */
1224 for (i = 0, j = 0; i < 4; i++, j += 7) {
1225 int pos = 0x08 + (i * 0x20);
1226 memcpy(buffsend + SIZE_HEADER, packet_send_status2,
1227 sizeof(packet_send_status2));
1230 memcpy(buffsend + 10, (j < n) ? (text + j) : " ", 7);
1231 send_client(SIZE_HEADER + sizeof(packet_send_status2), buffsend, pte);
1238 memcpy(buffsend + SIZE_HEADER, packet_send_status, sizeof(packet_send_status));
1240 if (i > STATUS_LENGTH_MAX)
1241 i = STATUS_LENGTH_MAX;
1242 memcpy(buffsend + 10, text, i);
1243 send_client(SIZE_HEADER + sizeof(packet_send_status), buffsend, pte);
1247 /* led values in hexa : 0 = bar off, 1 = bar on, 2 = bar 1s on/1s off, 3 = bar 2.5s on/0.5s off
1248 * 4 = bar 0.6s on/0.3s off, 5 = bar 0.5s on/0.5s off, 6 = bar 2s on/0.5s off
1249 * 7 = bar off, 8 = speaker off, 9 = speaker on, 10 = headphone off, 11 = headphone on
1250 * 18 = mute off, 19 mute on */
1251 static void send_led_update(struct unistimsession *pte, unsigned char led)
1255 ast_verb(0, "Sending led_update (%x)\n", led);
1256 memcpy(buffsend + SIZE_HEADER, packet_send_led_update, sizeof(packet_send_led_update));
1258 send_client(SIZE_HEADER + sizeof(packet_send_led_update), buffsend, pte);
1261 /* output = OUTPUT_HANDSET, OUTPUT_HEADPHONE or OUTPUT_SPEAKER
1262 * volume = VOLUME_LOW, VOLUME_NORMAL, VOLUME_INSANELY_LOUD
1263 * mute = MUTE_OFF, MUTE_ON */
1265 send_select_output(struct unistimsession *pte, unsigned char output, unsigned char volume,
1270 ast_verb(0, "Sending select output packet output=%x volume=%x mute=%x\n", output,
1272 memcpy(buffsend + SIZE_HEADER, packet_send_select_output,
1273 sizeof(packet_send_select_output));
1274 buffsend[9] = output;
1275 if (output == OUTPUT_SPEAKER)
1276 volume = VOLUME_LOW_SPEAKER;
1278 volume = VOLUME_LOW;
1279 buffsend[10] = volume;
1280 if (mute == MUTE_ON_DISCRET)
1281 buffsend[11] = MUTE_ON;
1283 buffsend[11] = mute;
1284 send_client(SIZE_HEADER + sizeof(packet_send_select_output), buffsend, pte);
1285 if (mute == MUTE_OFF)
1286 send_led_update(pte, 0x18);
1287 else if (mute == MUTE_ON)
1288 send_led_update(pte, 0x19);
1289 pte->device->mute = mute;
1290 if (output == OUTPUT_HANDSET) {
1291 if (mute == MUTE_ON)
1292 change_favorite_icon(pte, FAV_ICON_ONHOLD_BLACK);
1294 change_favorite_icon(pte, FAV_ICON_OFFHOOK_BLACK);
1295 send_led_update(pte, 0x08);
1296 send_led_update(pte, 0x10);
1297 } else if (output == OUTPUT_HEADPHONE) {
1298 if (mute == MUTE_ON)
1299 change_favorite_icon(pte, FAV_ICON_HEADPHONES_ONHOLD);
1301 change_favorite_icon(pte, FAV_ICON_HEADPHONES);
1302 send_led_update(pte, 0x08);
1303 send_led_update(pte, 0x11);
1304 } else if (output == OUTPUT_SPEAKER) {
1305 send_led_update(pte, 0x10);
1306 send_led_update(pte, 0x09);
1307 if (pte->device->receiver_state == STATE_OFFHOOK) {
1308 if (mute == MUTE_ON)
1309 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1311 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOOK_BLACK);
1313 if (mute == MUTE_ON)
1314 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1316 change_favorite_icon(pte, FAV_ICON_SPEAKER_OFFHOOK_BLACK);
1319 ast_log(LOG_WARNING, "Invalid ouput (%d)\n", output);
1320 if (output != pte->device->output)
1321 pte->device->previous_output = pte->device->output;
1322 pte->device->output = output;
1325 static void send_ring(struct unistimsession *pte, char volume, char style)
1329 ast_verb(0, "Sending ring packet\n");
1330 memcpy(buffsend + SIZE_HEADER, packet_send_ring, sizeof(packet_send_ring));
1331 buffsend[24] = style + 0x10;
1332 buffsend[29] = volume * 0x10;
1333 send_client(SIZE_HEADER + sizeof(packet_send_ring), buffsend, pte);
1336 static void send_no_ring(struct unistimsession *pte)
1340 ast_verb(0, "Sending no ring packet\n");
1341 memcpy(buffsend + SIZE_HEADER, packet_send_no_ring, sizeof(packet_send_no_ring));
1342 send_client(SIZE_HEADER + sizeof(packet_send_no_ring), buffsend, pte);
1345 static void send_texttitle(struct unistimsession *pte, const char *text)
1350 ast_verb(0, "Sending title text\n");
1351 memcpy(buffsend + SIZE_HEADER, packet_send_title, sizeof(packet_send_title));
1355 memcpy(buffsend + 10, text, i);
1356 send_client(SIZE_HEADER + sizeof(packet_send_title), buffsend, pte);
1360 static void send_date_time(struct unistimsession *pte)
1363 struct timeval now = ast_tvnow();
1364 struct ast_tm atm = { 0, };
1367 ast_verb(0, "Sending Time & Date\n");
1368 memcpy(buffsend + SIZE_HEADER, packet_send_date_time, sizeof(packet_send_date_time));
1369 ast_localtime(&now, &atm, NULL);
1370 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1371 buffsend[11] = (unsigned char) atm.tm_mday;
1372 buffsend[12] = (unsigned char) atm.tm_hour;
1373 buffsend[13] = (unsigned char) atm.tm_min;
1374 send_client(SIZE_HEADER + sizeof(packet_send_date_time), buffsend, pte);
1377 static void send_date_time2(struct unistimsession *pte)
1380 struct timeval now = ast_tvnow();
1381 struct ast_tm atm = { 0, };
1384 ast_verb(0, "Sending Time & Date #2\n");
1385 memcpy(buffsend + SIZE_HEADER, packet_send_date_time2, sizeof(packet_send_date_time2));
1386 ast_localtime(&now, &atm, NULL);
1388 buffsend[9] = pte->device->datetimeformat;
1391 buffsend[14] = (unsigned char) atm.tm_mon + 1;
1392 buffsend[15] = (unsigned char) atm.tm_mday;
1393 buffsend[16] = (unsigned char) atm.tm_hour;
1394 buffsend[17] = (unsigned char) atm.tm_min;
1395 send_client(SIZE_HEADER + sizeof(packet_send_date_time2), buffsend, pte);
1398 static void send_date_time3(struct unistimsession *pte)
1401 struct timeval now = ast_tvnow();
1402 struct ast_tm atm = { 0, };
1405 ast_verb(0, "Sending Time & Date #3\n");
1406 memcpy(buffsend + SIZE_HEADER, packet_send_date_time3, sizeof(packet_send_date_time3));
1407 ast_localtime(&now, &atm, NULL);
1408 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1409 buffsend[11] = (unsigned char) atm.tm_mday;
1410 buffsend[12] = (unsigned char) atm.tm_hour;
1411 buffsend[13] = (unsigned char) atm.tm_min;
1412 send_client(SIZE_HEADER + sizeof(packet_send_date_time3), buffsend, pte);
1415 static void send_blink_cursor(struct unistimsession *pte)
1419 ast_verb(0, "Sending set blink\n");
1420 memcpy(buffsend + SIZE_HEADER, packet_send_blink_cursor, sizeof(packet_send_blink_cursor));
1421 send_client(SIZE_HEADER + sizeof(packet_send_blink_cursor), buffsend, pte);
1425 /* pos : 0xab (a=0/2/4 = line ; b = row) */
1426 static void send_cursor_pos(struct unistimsession *pte, unsigned char pos)
1430 ast_verb(0, "Sending set cursor position\n");
1431 memcpy(buffsend + SIZE_HEADER, packet_send_set_pos_cursor,
1432 sizeof(packet_send_set_pos_cursor));
1434 send_client(SIZE_HEADER + sizeof(packet_send_set_pos_cursor), buffsend, pte);
1438 static void rcv_resume_connection_with_server(struct unistimsession *pte)
1442 ast_verb(0, "ResumeConnectionWithServer received\n");
1443 ast_verb(0, "Sending packet_send_query_mac_address\n");
1445 memcpy(buffsend + SIZE_HEADER, packet_send_query_mac_address,
1446 sizeof(packet_send_query_mac_address));
1447 send_client(SIZE_HEADER + sizeof(packet_send_query_mac_address), buffsend, pte);
1451 static int unistim_register(struct unistimsession *s)
1453 struct unistim_device *d;
1455 ast_mutex_lock(&devicelock);
1458 if (!strcasecmp(s->macaddr, d->id)) {
1459 /* XXX Deal with IP authentication */
1462 d->codec_number = DEFAULT_CODEC;
1465 d->receiver_state = STATE_ONHOOK;
1470 ast_mutex_unlock(&devicelock);
1478 static int alloc_sub(struct unistim_line *l, int x)
1480 struct unistim_subchannel *sub;
1481 if (!(sub = ast_calloc(1, sizeof(*sub))))
1485 ast_verb(3, "Allocating UNISTIM subchannel #%d on %s@%s ptr=%p\n", x, l->name, l->parent->name, sub);
1489 ast_mutex_init(&sub->lock);
1493 static int unalloc_sub(struct unistim_line *p, int x)
1496 ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name,
1501 ast_debug(1, "Released sub %d of channel %s@%s\n", x, p->name,
1503 ast_mutex_destroy(&p->lock);
1504 ast_free(p->subs[x]);
1509 static void rcv_mac_addr(struct unistimsession *pte, const unsigned char *buf)
1516 ast_verb(0, "Mac Address received : ");
1517 for (tmp = 15; tmp < 15 + SIZE_HEADER; tmp++) {
1518 sprintf(&addrmac[i], "%.2x", (unsigned char) buf[tmp]);
1522 ast_verb(0, "%s\n", addrmac);
1523 strcpy(pte->macaddr, addrmac);
1524 res = unistim_register(pte);
1526 switch (autoprovisioning) {
1527 case AUTOPROVISIONING_NO:
1528 ast_log(LOG_WARNING, "No entry found for this phone : %s\n", addrmac);
1529 pte->state = STATE_AUTHDENY;
1531 case AUTOPROVISIONING_YES:
1533 struct unistim_device *d, *newd;
1534 struct unistim_line *newl;
1536 ast_verb(0, "New phone, autoprovisioning on\n");
1537 /* First : locate the [template] section */
1538 ast_mutex_lock(&devicelock);
1541 if (!strcasecmp(d->name, "template")) {
1542 /* Found, cloning this entry */
1543 if (!(newd = ast_malloc(sizeof(*newd)))) {
1544 ast_mutex_unlock(&devicelock);
1548 memcpy(newd, d, sizeof(*newd));
1549 if (!(newl = ast_malloc(sizeof(*newl)))) {
1551 ast_mutex_unlock(&devicelock);
1555 memcpy(newl, d->lines, sizeof(*newl));
1556 if (!alloc_sub(newl, SUB_REAL)) {
1559 ast_mutex_unlock(&devicelock);
1562 /* Ok, now updating some fields */
1563 ast_copy_string(newd->id, addrmac, sizeof(newd->id));
1564 ast_copy_string(newd->name, addrmac, sizeof(newd->name));
1565 if (newd->extension == EXTENSION_NONE)
1566 newd->extension = EXTENSION_ASK;
1568 newd->receiver_state = STATE_ONHOOK;
1569 newd->session = pte;
1570 newd->to_delete = -1;
1573 newl->parent = newd;
1574 strcpy(newl->name, d->lines->name);
1575 snprintf(d->lines->name, sizeof(d->lines->name), "%d",
1576 atoi(d->lines->name) + 1);
1577 snprintf(newl->fullname, sizeof(newl->fullname), "USTM/%s@%s",
1578 newl->name, newd->name);
1579 /* Go to the end of the linked chain */
1589 ast_mutex_unlock(&devicelock);
1591 ast_log(LOG_WARNING, "No entry [template] found in unistim.conf\n");
1592 pte->state = STATE_AUTHDENY;
1596 case AUTOPROVISIONING_TN:
1597 pte->state = STATE_AUTHDENY;
1599 case AUTOPROVISIONING_DB:
1600 ast_log(LOG_WARNING,
1601 "Autoprovisioning with database is not yet functional\n");
1604 ast_log(LOG_WARNING, "Internal error : unknown autoprovisioning value = %d\n",
1608 if (pte->state != STATE_AUTHDENY) {
1609 ast_verb(3, "Device '%s' successfuly registered\n", pte->device->name);
1610 switch (pte->device->extension) {
1611 case EXTENSION_NONE:
1612 pte->state = STATE_MAINPAGE;
1615 /* Checking if we already have an extension number */
1616 if (ast_strlen_zero(pte->device->extension_number))
1617 pte->state = STATE_EXTENSION;
1619 /* Yes, because of a phone reboot. We don't ask again for the TN */
1620 if (RegisterExtension(pte))
1621 pte->state = STATE_EXTENSION;
1623 pte->state = STATE_MAINPAGE;
1626 case EXTENSION_LINE:
1627 ast_copy_string(pte->device->extension_number, pte->device->lines->name,
1628 sizeof(pte->device->extension_number));
1629 if (RegisterExtension(pte))
1630 pte->state = STATE_EXTENSION;
1632 pte->state = STATE_MAINPAGE;
1635 /* If we are here, it's because of a phone reboot */
1636 pte->state = STATE_MAINPAGE;
1639 ast_log(LOG_WARNING, "Internal error, extension value unknown : %d\n",
1640 pte->device->extension);
1641 pte->state = STATE_AUTHDENY;
1645 if (pte->state == STATE_EXTENSION) {
1646 if (pte->device->extension != EXTENSION_TN)
1647 pte->device->extension = EXTENSION_ASK;
1648 pte->device->extension_number[0] = '\0';
1651 ast_verb(0, "\nSending S1\n");
1652 memcpy(buffsend + SIZE_HEADER, packet_send_S1, sizeof(packet_send_S1));
1653 send_client(SIZE_HEADER + sizeof(packet_send_S1), buffsend, pte);
1656 ast_verb(0, "Sending query_basic_manager_04\n");
1657 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_04,
1658 sizeof(packet_send_query_basic_manager_04));
1659 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_04), buffsend, pte);
1662 ast_verb(0, "Sending query_basic_manager_10\n");
1663 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_10,
1664 sizeof(packet_send_query_basic_manager_10));
1665 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_10), buffsend, pte);
1667 send_date_time(pte);
1671 static int write_entry_history(struct unistimsession *pte, FILE * f, char c, char *line1)
1673 if (fwrite(&c, 1, 1, f) != 1) {
1674 display_last_error("Unable to write history log header.");
1677 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
1678 display_last_error("Unable to write history entry - date.");
1681 if (fwrite(pte->device->lst_cid, TEXT_LENGTH_MAX, 1, f) != 1) {
1682 display_last_error("Unable to write history entry - callerid.");
1685 if (fwrite(pte->device->lst_cnm, TEXT_LENGTH_MAX, 1, f) != 1) {
1686 display_last_error("Unable to write history entry - callername.");
1692 static int write_history(struct unistimsession *pte, char way, char ismissed)
1694 char tmp[AST_CONFIG_MAX_PATH], tmp2[AST_CONFIG_MAX_PATH];
1695 char line1[TEXT_LENGTH_MAX + 1];
1696 char count = 0, *histbuf;
1699 struct timeval now = ast_tvnow();
1700 struct ast_tm atm = { 0, };
1704 if (!pte->device->callhistory)
1706 if (strchr(pte->device->name, '/') || (pte->device->name[0] == '.')) {
1707 ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n",
1712 snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_LOG_DIR, USTM_LOG_DIR);
1713 if (ast_mkdir(tmp, 0770)) {
1714 if (errno != EEXIST) {
1715 display_last_error("Unable to create directory for history");
1720 ast_localtime(&now, &atm, NULL);
1723 strcpy(tmp2, "Miss");
1725 strcpy(tmp2, "Fail");
1727 strcpy(tmp2, "Answ");
1728 snprintf(line1, sizeof(line1), "%04d/%02d/%02d %02d:%02d:%02d %s",
1729 atm.tm_year + 1900, atm.tm_mon + 1, atm.tm_mday, atm.tm_hour,
1730 atm.tm_min, atm.tm_sec, tmp2);
1732 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
1733 USTM_LOG_DIR, pte->device->name, way);
1734 if ((f = fopen(tmp, "r"))) {
1735 struct stat bufstat;
1737 if (stat(tmp, &bufstat)) {
1738 display_last_error("Unable to stat history log.");
1742 size = 1 + (MAX_ENTRY_LOG * TEXT_LENGTH_MAX * 3);
1743 if (bufstat.st_size != size) {
1744 ast_log(LOG_WARNING,
1745 "History file %s has an incorrect size (%d instead of %d). It will be replaced by a new one.",
1746 tmp, (int) bufstat.st_size, size);
1753 /* If we can't open the log file, we create a brand new one */
1758 if ((errno != ENOENT) && (count == 0)) {
1759 display_last_error("Unable to open history log.");
1762 f = fopen(tmp, "w");
1764 display_last_error("Unable to create history log.");
1767 if (write_entry_history(pte, f, c, line1)) {
1771 memset(line1, ' ', TEXT_LENGTH_MAX);
1772 for (i = 3; i < MAX_ENTRY_LOG * 3; i++) {
1773 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
1774 display_last_error("Unable to write history entry - stuffing.");
1780 display_last_error("Unable to close history - creation.");
1783 /* We can open the log file, we create a temporary one, we add our entry and copy the rest */
1784 if (fread(&count, 1, 1, f) != 1) {
1785 display_last_error("Unable to read history header.");
1789 if (count > MAX_ENTRY_LOG) {
1790 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
1791 count, MAX_ENTRY_LOG);
1795 snprintf(tmp2, sizeof(tmp2), "%s/%s/%s-%c.csv.tmp", ast_config_AST_LOG_DIR,
1796 USTM_LOG_DIR, pte->device->name, way);
1797 if (!(f2 = fopen(tmp2, "w"))) {
1798 display_last_error("Unable to create temporary history log.");
1803 if (++count > MAX_ENTRY_LOG)
1804 count = MAX_ENTRY_LOG;
1806 if (write_entry_history(pte, f2, count, line1)) {
1812 size = (MAX_ENTRY_LOG - 1) * TEXT_LENGTH_MAX * 3;
1813 if (!(histbuf = ast_malloc(size))) {
1819 if (fread(histbuf, size, 1, f) != 1) {
1823 display_last_error("Unable to read previous history entries.");
1826 if (fwrite(histbuf, size, 1, f2) != 1) {
1830 display_last_error("Unable to write previous history entries.");
1835 display_last_error("Unable to close history log.");
1837 display_last_error("Unable to close temporary history log.");
1839 display_last_error("Unable to remove old history log.");
1840 if (rename(tmp2, tmp))
1841 display_last_error("Unable to rename new history log.");
1845 static void cancel_dial(struct unistimsession *pte)
1848 pte->device->missed_call++;
1849 write_history(pte, 'i', 1);
1850 show_main_page(pte);
1854 static void swap_subs(struct unistim_line *p, int a, int b)
1856 /* struct ast_channel *towner; */
1857 struct ast_rtp_instance *rtp;
1861 ast_verb(0, "Swapping %d and %d\n", a, b);
1863 if ((!p->subs[a]->owner) || (!p->subs[b]->owner)) {
1864 ast_log(LOG_WARNING,
1865 "Attempted to swap subchannels with a null owner : sub #%d=%p sub #%d=%p\n",
1866 a, p->subs[a]->owner, b, p->subs[b]->owner);
1869 rtp = p->subs[a]->rtp;
1870 p->subs[a]->rtp = p->subs[b]->rtp;
1871 p->subs[b]->rtp = rtp;
1873 fds = p->subs[a]->owner->fds[0];
1874 p->subs[a]->owner->fds[0] = p->subs[b]->owner->fds[0];
1875 p->subs[b]->owner->fds[0] = fds;
1877 fds = p->subs[a]->owner->fds[1];
1878 p->subs[a]->owner->fds[1] = p->subs[b]->owner->fds[1];
1879 p->subs[b]->owner->fds[1] = fds;
1882 static int attempt_transfer(struct unistim_subchannel *p1, struct unistim_subchannel *p2)
1886 *chana = NULL, *chanb = NULL, *bridgea = NULL, *bridgeb = NULL, *peera =
1887 NULL, *peerb = NULL, *peerc = NULL, *peerd = NULL;
1889 if (!p1->owner || !p2->owner) {
1890 ast_log(LOG_WARNING, "Transfer attempted without dual ownership?\n");
1895 bridgea = ast_bridged_channel(chana);
1896 bridgeb = ast_bridged_channel(chanb);
1903 } else if (bridgeb) {
1910 if (peera && peerb && peerc && (peerb != peerc)) {
1911 /*ast_quiet_chan(peera);
1912 ast_quiet_chan(peerb);
1913 ast_quiet_chan(peerc);
1914 ast_quiet_chan(peerd); */
1916 if (peera->cdr && peerb->cdr) {
1917 peerb->cdr = ast_cdr_append(peerb->cdr, peera->cdr);
1918 } else if (peera->cdr) {
1919 peerb->cdr = peera->cdr;
1923 if (peerb->cdr && peerc->cdr) {
1924 peerb->cdr = ast_cdr_append(peerb->cdr, peerc->cdr);
1925 } else if (peerc->cdr) {
1926 peerb->cdr = peerc->cdr;
1930 if (ast_channel_masquerade(peerb, peerc)) {
1931 ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name,
1938 "Transfer attempted with no appropriate bridged calls to transfer\n");
1940 ast_softhangup_nolock(chana, AST_SOFTHANGUP_DEV);
1942 ast_softhangup_nolock(chanb, AST_SOFTHANGUP_DEV);
1948 void change_callerid(struct unistimsession *pte, int type, char *callerid)
1954 data = pte->device->lst_cnm;
1956 data = pte->device->lst_cid;
1958 /* This is very nearly strncpy(), except that the remaining buffer
1959 * is padded with ' ', instead of '\0' */
1960 memset(data, ' ', TEXT_LENGTH_MAX);
1961 size = strlen(callerid);
1962 if (size > TEXT_LENGTH_MAX)
1963 size = TEXT_LENGTH_MAX;
1964 memcpy(data, callerid, size);
1967 static void close_call(struct unistimsession *pte)
1969 struct unistim_subchannel *sub;
1970 struct unistim_line *l = pte->device->lines;
1972 sub = pte->device->lines->subs[SUB_REAL];
1973 send_stop_timer(pte);
1975 sub->alreadygone = 1;
1976 if (l->subs[SUB_THREEWAY]) {
1977 l->subs[SUB_THREEWAY]->alreadygone = 1;
1978 if (attempt_transfer(sub, l->subs[SUB_THREEWAY]) < 0)
1979 ast_verb(0, "attempt_transfer failed.\n");
1981 ast_queue_hangup(sub->owner);
1983 if (l->subs[SUB_THREEWAY]) {
1984 if (l->subs[SUB_THREEWAY]->owner)
1985 ast_queue_hangup_with_cause(l->subs[SUB_THREEWAY]->owner, AST_CAUSE_NORMAL_CLEARING);
1987 ast_log(LOG_WARNING, "threeway sub without owner\n");
1989 ast_verb(0, "USTM(%s@%s-%d) channel already destroyed\n", sub->parent->name,
1990 sub->parent->parent->name, sub->subtype);
1992 change_callerid(pte, 0, pte->device->redial_number);
1993 change_callerid(pte, 1, "");
1994 write_history(pte, 'o', pte->device->missed_call);
1995 pte->device->missed_call = 0;
1996 show_main_page(pte);
2000 static void IgnoreCall(struct unistimsession *pte)
2006 static void *unistim_ss(void *data)
2008 struct ast_channel *chan = data;
2009 struct unistim_subchannel *sub = chan->tech_pvt;
2010 struct unistim_line *l = sub->parent;
2011 struct unistimsession *s = l->parent->session;
2014 ast_verb(3, "Starting switch on '%s@%s-%d' to %s\n", l->name, l->parent->name, sub->subtype, s->device->phone_number);
2015 ast_copy_string(chan->exten, s->device->phone_number, sizeof(chan->exten));
2016 ast_copy_string(s->device->redial_number, s->device->phone_number,
2017 sizeof(s->device->redial_number));
2018 ast_setstate(chan, AST_STATE_RING);
2019 res = ast_pbx_run(chan);
2021 ast_log(LOG_WARNING, "PBX exited non-zero\n");
2022 send_tone(s, 1000, 0);;
2027 static void start_rtp(struct unistim_subchannel *sub)
2030 struct sockaddr_in us = { 0, };
2031 struct sockaddr_in public = { 0, };
2032 struct sockaddr_in sin = { 0, };
2034 struct sockaddr_in sout = { 0, };
2038 ast_log(LOG_WARNING, "start_rtp with a null subchannel !\n");
2042 ast_log(LOG_WARNING, "start_rtp with a null line !\n");
2045 if (!sub->parent->parent) {
2046 ast_log(LOG_WARNING, "start_rtp with a null device !\n");
2049 if (!sub->parent->parent->session) {
2050 ast_log(LOG_WARNING, "start_rtp with a null session !\n");
2053 sout = sub->parent->parent->session->sout;
2055 ast_mutex_lock(&sub->lock);
2056 /* Allocate the RTP */
2058 ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
2059 sub->rtp = ast_rtp_instance_new(NULL, sched, &sout, NULL);
2061 ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
2062 strerror(errno), ast_inet_ntoa(sout.sin_addr));
2063 ast_mutex_unlock(&sub->lock);
2066 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
2068 sub->owner->fds[0] = ast_rtp_instance_fd(sub->rtp, 0);
2069 sub->owner->fds[1] = ast_rtp_instance_fd(sub->rtp, 1);
2071 ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
2072 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->parent->parent->nat);
2074 /* Create the RTP connection */
2075 ast_rtp_instance_get_local_address(sub->rtp, &us);
2076 sin.sin_family = AF_INET;
2077 /* Setting up RTP for our side */
2078 memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
2079 sizeof(sin.sin_addr));
2080 sin.sin_port = htons(sub->parent->parent->rtp_port);
2081 ast_rtp_instance_set_remote_address(sub->rtp, &sin);
2082 if (!(sub->owner->nativeformats & sub->owner->readformat)) {
2084 fmt = ast_best_codec(sub->owner->nativeformats);
2085 ast_log(LOG_WARNING,
2086 "Our read/writeformat has been changed to something incompatible : %s (%d), using %s (%d) best codec from %d\n",
2087 ast_getformatname(sub->owner->readformat),
2088 sub->owner->readformat, ast_getformatname(fmt), fmt,
2089 sub->owner->nativeformats);
2090 sub->owner->readformat = fmt;
2091 sub->owner->writeformat = fmt;
2093 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, sub->owner->readformat);
2094 /* Setting up RTP of the phone */
2095 if (public_ip.sin_family == 0) /* NAT IP override ? */
2096 memcpy(&public, &us, sizeof(public)); /* No defined, using IP from recvmsg */
2098 memcpy(&public, &public_ip, sizeof(public)); /* override */
2100 ast_verb(0, "RTP started : Our IP/port is : %s:%hd with codec %s (%d)\n",
2101 ast_inet_ntoa(us.sin_addr),
2102 htons(us.sin_port), ast_getformatname(sub->owner->readformat),
2103 sub->owner->readformat);
2104 ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n",
2105 ast_inet_ntoa(public.sin_addr));
2107 if ((sub->owner->readformat == AST_FORMAT_ULAW) ||
2108 (sub->owner->readformat == AST_FORMAT_ALAW)) {
2110 ast_verb(0, "Sending packet_send_rtp_packet_size for codec %d\n", codec);
2111 memcpy(buffsend + SIZE_HEADER, packet_send_rtp_packet_size,
2112 sizeof(packet_send_rtp_packet_size));
2113 buffsend[10] = codec;
2114 send_client(SIZE_HEADER + sizeof(packet_send_rtp_packet_size), buffsend,
2115 sub->parent->parent->session);
2118 ast_verb(0, "Sending Jitter Buffer Parameters Configuration\n");
2119 memcpy(buffsend + SIZE_HEADER, packet_send_jitter_buffer_conf,
2120 sizeof(packet_send_jitter_buffer_conf));
2121 send_client(SIZE_HEADER + sizeof(packet_send_jitter_buffer_conf), buffsend,
2122 sub->parent->parent->session);
2123 if (sub->parent->parent->rtp_method != 0) {
2124 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2127 ast_verb(0, "Sending OpenAudioStreamTX using method #%d\n",
2128 sub->parent->parent->rtp_method);
2129 if (sub->parent->parent->rtp_method == 3)
2130 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx3,
2131 sizeof(packet_send_open_audio_stream_tx3));
2133 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx,
2134 sizeof(packet_send_open_audio_stream_tx));
2135 if (sub->parent->parent->rtp_method != 2) {
2136 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2137 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2138 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2139 buffsend[23] = (rtcpsin_port & 0x00ff);
2140 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2141 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2142 buffsend[24] = (us.sin_port & 0x00ff);
2143 buffsend[27] = (rtcpsin_port & 0x00ff);
2144 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2146 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2147 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2148 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2149 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2150 buffsend[19] = (us.sin_port & 0x00ff);
2151 buffsend[11] = codec;
2153 buffsend[12] = codec;
2154 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_tx), buffsend,
2155 sub->parent->parent->session);
2158 ast_verb(0, "Sending OpenAudioStreamRX\n");
2159 if (sub->parent->parent->rtp_method == 3)
2160 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx3,
2161 sizeof(packet_send_open_audio_stream_rx3));
2163 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx,
2164 sizeof(packet_send_open_audio_stream_rx));
2165 if (sub->parent->parent->rtp_method != 2) {
2166 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2167 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2168 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2169 buffsend[23] = (rtcpsin_port & 0x00ff);
2170 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2171 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2172 buffsend[24] = (us.sin_port & 0x00ff);
2173 buffsend[27] = (rtcpsin_port & 0x00ff);
2174 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2176 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2177 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2178 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2179 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2180 buffsend[19] = (us.sin_port & 0x00ff);
2181 buffsend[12] = codec;
2183 buffsend[11] = codec;
2184 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_rx), buffsend,
2185 sub->parent->parent->session);
2187 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2190 ast_verb(0, "Sending packet_send_call default method\n");
2192 memcpy(buffsend + SIZE_HEADER, packet_send_call, sizeof(packet_send_call));
2193 memcpy(buffsend + 53, &public.sin_addr, sizeof(public.sin_addr));
2194 /* Destination port when sending RTP */
2195 buffsend[49] = (us.sin_port & 0x00ff);
2196 buffsend[50] = (us.sin_port & 0xff00) >> 8;
2197 /* Destination port when sending RTCP */
2198 buffsend[52] = (rtcpsin_port & 0x00ff);
2199 buffsend[51] = (rtcpsin_port & 0xff00) >> 8;
2201 buffsend[40] = codec;
2202 buffsend[41] = codec;
2203 if (sub->owner->readformat == AST_FORMAT_ULAW)
2204 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2205 else if (sub->owner->readformat == AST_FORMAT_ALAW)
2206 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2207 else if (sub->owner->readformat == AST_FORMAT_G723_1)
2208 buffsend[42] = 2; /* 1 = 30ms (24 bytes), 2 = 60 ms (48 bytes) */
2209 else if (sub->owner->readformat == AST_FORMAT_G729A)
2210 buffsend[42] = 2; /* 1 = 10ms (10 bytes), 2 = 20ms (20 bytes) */
2212 ast_log(LOG_WARNING, "Unsupported codec %s (%d) !\n",
2213 ast_getformatname(sub->owner->readformat), sub->owner->readformat);
2214 /* Source port for transmit RTP and Destination port for receiving RTP */
2215 buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8;
2216 buffsend[46] = (htons(sin.sin_port) & 0x00ff);
2217 buffsend[47] = (rtcpsin_port & 0xff00) >> 8;
2218 buffsend[48] = (rtcpsin_port & 0x00ff);
2219 send_client(SIZE_HEADER + sizeof(packet_send_call), buffsend,
2220 sub->parent->parent->session);
2222 ast_mutex_unlock(&sub->lock);
2225 static void SendDialTone(struct unistimsession *pte)
2228 /* No country defined ? Using US tone */
2229 if (ast_strlen_zero(pte->device->country)) {
2231 ast_verb(0, "No country defined, using US tone\n");
2232 send_tone(pte, 350, 440);
2235 if (strlen(pte->device->country) != 2) {
2237 ast_verb(0, "Country code != 2 char, using US tone\n");
2238 send_tone(pte, 350, 440);
2242 while (frequency[i].freq1) {
2243 if ((frequency[i].country[0] == pte->device->country[0]) &&
2244 (frequency[i].country[1] == pte->device->country[1])) {
2246 ast_verb(0, "Country code found (%s), freq1=%d freq2=%d\n",
2247 frequency[i].country, frequency[i].freq1, frequency[i].freq2);
2248 send_tone(pte, frequency[i].freq1, frequency[i].freq2);
2254 static void handle_dial_page(struct unistimsession *pte)
2256 pte->state = STATE_DIALPAGE;
2257 if (pte->device->call_forward[0] == -1) {
2258 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
2259 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Enter forward");
2260 send_text_status(pte, "ForwardCancel BackSpcErase");
2261 if (pte->device->call_forward[1] != 0) {
2262 char tmp[TEXT_LENGTH_MAX + 1];
2264 ast_copy_string(pte->device->phone_number, pte->device->call_forward + 1,
2265 sizeof(pte->device->phone_number));
2266 pte->device->size_phone_number = strlen(pte->device->phone_number);
2267 if (pte->device->size_phone_number > 15)
2268 pte->device->size_phone_number = 15;
2269 strcpy(tmp, "Number : ...............");
2270 memcpy(tmp + 9, pte->device->phone_number, pte->device->size_phone_number);
2271 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
2272 send_blink_cursor(pte);
2273 send_cursor_pos(pte,
2274 (unsigned char) (TEXT_LINE2 + 0x09 +
2275 pte->device->size_phone_number));
2276 send_led_update(pte, 0);
2280 if ((pte->device->output == OUTPUT_HANDSET) &&
2281 (pte->device->receiver_state == STATE_ONHOOK))
2282 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2284 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2286 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Enter the number to dial");
2287 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "and press Call");
2288 send_text_status(pte, "Call Redial BackSpcErase");
2290 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
2291 send_blink_cursor(pte);
2292 send_cursor_pos(pte, TEXT_LINE2 + 0x09);
2293 pte->device->size_phone_number = 0;
2294 pte->device->phone_number[0] = 0;
2295 change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
2296 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
2297 pte->device->missed_call = 0;
2298 send_led_update(pte, 0);
2302 /* Step 1 : Music On Hold for peer, Dialing screen for us */
2303 static void TransferCallStep1(struct unistimsession *pte)
2305 struct unistim_subchannel *sub;
2306 struct unistim_line *p = pte->device->lines;
2308 sub = p->subs[SUB_REAL];
2311 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2314 if (p->subs[SUB_THREEWAY]) {
2316 ast_verb(0, "Transfer canceled, hangup our threeway channel\n");
2317 if (p->subs[SUB_THREEWAY]->owner)
2318 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY]->owner, AST_CAUSE_NORMAL_CLEARING);
2320 ast_log(LOG_WARNING, "Canceling a threeway channel without owner\n");
2323 /* Start music on hold if appropriate */
2324 if (pte->device->moh)
2325 ast_log(LOG_WARNING, "Transfer with peer already listening music on hold\n");
2327 if (ast_bridged_channel(p->subs[SUB_REAL]->owner)) {
2328 ast_moh_start(ast_bridged_channel(p->subs[SUB_REAL]->owner),
2329 pte->device->lines->musicclass, NULL);
2330 pte->device->moh = 1;
2332 ast_log(LOG_WARNING, "Unable to find peer subchannel for music on hold\n");
2336 /* Silence our channel */
2337 if (!pte->device->silence_generator) {
2338 pte->device->silence_generator =
2339 ast_channel_start_silence_generator(p->subs[SUB_REAL]->owner);
2340 if (pte->device->silence_generator == NULL)
2341 ast_log(LOG_WARNING, "Unable to start a silence generator.\n");
2342 else if (unistimdebug)
2343 ast_verb(0, "Starting silence generator\n");
2345 handle_dial_page(pte);
2348 /* From phone to PBX */
2349 static void HandleCallOutgoing(struct unistimsession *s)
2351 struct ast_channel *c;
2352 struct unistim_subchannel *sub;
2354 s->state = STATE_CALL;
2355 sub = s->device->lines->subs[SUB_REAL];
2357 ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
2360 if (!sub->owner) { /* A call is already in progress ? */
2361 c = unistim_new(sub, AST_STATE_DOWN); /* No, starting a new one */
2363 /* Need to start RTP before calling ast_pbx_run */
2366 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
2367 send_text(TEXT_LINE0, TEXT_NORMAL, s, "Calling :");
2368 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
2369 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Dialing...");
2370 send_text_status(s, "Hangup");
2372 if (ast_pthread_create(&t, NULL, unistim_ss, c)) {
2373 display_last_error("Unable to create switch thread");
2374 ast_queue_hangup_with_cause(c, AST_CAUSE_SWITCH_CONGESTION);
2377 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n",
2378 sub->parent->name, s->device->name);
2379 } else { /* We already have a call, so we switch in a threeway call */
2381 if (s->device->moh) {
2382 struct unistim_subchannel *subchannel;
2383 struct unistim_line *p = s->device->lines;
2384 subchannel = p->subs[SUB_REAL];
2386 if (!subchannel->owner) {
2387 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2390 if (p->subs[SUB_THREEWAY]) {
2391 ast_log(LOG_WARNING,
2392 "Can't transfer while an another transfer is taking place\n");
2395 if (!alloc_sub(p, SUB_THREEWAY)) {
2396 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
2399 /* Stop the silence generator */
2400 if (s->device->silence_generator) {
2402 ast_verb(0, "Stopping silence generator\n");
2403 ast_channel_stop_silence_generator(subchannel->owner,
2404 s->device->silence_generator);
2405 s->device->silence_generator = NULL;
2408 /* Make new channel */
2409 c = unistim_new(p->subs[SUB_THREEWAY], AST_STATE_DOWN);
2411 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", p);
2414 /* Swap things around between the three-way and real call */
2415 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2416 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
2417 send_text(TEXT_LINE0, TEXT_NORMAL, s, "Calling (pre-transfer)");
2418 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
2419 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Dialing...");
2420 send_text_status(s, "TransfrCancel");
2422 if (ast_pthread_create(&t, NULL, unistim_ss, p->subs[SUB_THREEWAY]->owner)) {
2423 ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", p);
2428 ast_verb(0, "Started three way call on channel %p (%s) subchan %d\n",
2429 p->subs[SUB_THREEWAY]->owner, p->subs[SUB_THREEWAY]->owner->name,
2430 p->subs[SUB_THREEWAY]->subtype);
2432 ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name);
2437 /* From PBX to phone */
2438 static void HandleCallIncoming(struct unistimsession *s)
2440 struct unistim_subchannel *sub;
2441 s->state = STATE_CALL;
2442 s->device->missed_call = 0;
2444 sub = s->device->lines->subs[SUB_REAL];
2446 ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
2448 } else if (unistimdebug)
2449 ast_verb(0, "Handle Call Incoming for %s@%s\n", sub->parent->name,
2453 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", sub->parent->name,
2455 ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
2456 send_text(TEXT_LINE2, TEXT_NORMAL, s, "is on-line");
2457 send_text_status(s, "Hangup Transf");
2458 send_start_timer(s);
2460 if ((s->device->output == OUTPUT_HANDSET) &&
2461 (s->device->receiver_state == STATE_ONHOOK))
2462 send_select_output(s, OUTPUT_SPEAKER, s->device->volume, MUTE_OFF);
2464 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
2465 s->device->start_call_timestamp = time(0);
2466 write_history(s, 'i', 0);
2470 static int unistim_do_senddigit(struct unistimsession *pte, char digit)
2473 struct ast_frame f = { 0, };
2474 struct unistim_subchannel *sub;
2475 sub = pte->device->lines->subs[SUB_REAL];
2477 ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit\n");
2481 ast_verb(0, "Send Digit %c\n", digit);
2484 send_tone(pte, 941, 1336);
2487 send_tone(pte, 697, 1209);
2490 send_tone(pte, 697, 1336);
2493 send_tone(pte, 697, 1477);
2496 send_tone(pte, 770, 1209);
2499 send_tone(pte, 770, 1336);
2502 send_tone(pte, 770, 1477);
2505 send_tone(pte, 852, 1209);
2508 send_tone(pte, 852, 1336);
2511 send_tone(pte, 852, 1477);
2514 send_tone(pte, 697, 1633);
2517 send_tone(pte, 770, 1633);
2520 send_tone(pte, 852, 1633);
2523 send_tone(pte, 941, 1633);
2526 send_tone(pte, 941, 1209);
2529 send_tone(pte, 941, 1477);
2532 send_tone(pte, 500, 2000);
2534 usleep(150000); /* XXX Less than perfect, blocking an important thread is not a good idea */
2535 send_tone(pte, 0, 0);
2536 f.frametype = AST_FRAME_DTMF;
2539 ast_queue_frame(sub->owner, &f);
2543 static void key_call(struct unistimsession *pte, char keycode)
2545 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
2546 if (keycode == KEY_SHARP)
2548 else if (keycode == KEY_STAR)
2552 unistim_do_senddigit(pte, keycode);
2561 TransferCallStep1(pte);
2564 if (pte->device->output == OUTPUT_HEADPHONE)
2565 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
2567 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
2570 if (pte->device->output != OUTPUT_SPEAKER)
2571 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2573 send_select_output(pte, pte->device->previous_output, pte->device->volume,
2577 if (!pte->device->moh) {
2578 if (pte->device->mute == MUTE_ON)
2579 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2581 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
2586 struct unistim_subchannel *sub;
2587 struct ast_channel *bridgepeer = NULL;
2588 sub = pte->device->lines->subs[SUB_REAL];
2590 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2593 if ((bridgepeer = ast_bridged_channel(sub->owner))) {
2594 if (pte->device->moh) {
2595 ast_moh_stop(bridgepeer);
2596 pte->device->moh = 0;
2597 send_select_output(pte, pte->device->output, pte->device->volume,
2600 ast_moh_start(bridgepeer, pte->device->lines->musicclass, NULL);
2601 pte->device->moh = 1;
2602 send_select_output(pte, pte->device->output, pte->device->volume,
2606 ast_log(LOG_WARNING,
2607 "Unable to find peer subchannel for music on hold\n");
2614 static void key_ringing(struct unistimsession *pte, char keycode)
2616 if (keycode == KEY_FAV0 + pte->device->softkeylinepos) {
2617 HandleCallIncoming(pte);
2626 HandleCallIncoming(pte);
2632 static void Keyfavorite(struct unistimsession *pte, char keycode)
2636 if ((keycode < KEY_FAV1) && (keycode > KEY_FAV5)) {
2637 ast_log(LOG_WARNING, "It's not a favorite key\n");
2640 if (keycode == KEY_FAV0)
2642 fav = keycode - KEY_FAV0;
2643 if (pte->device->softkeyicon[fav] == 0)
2645 ast_copy_string(pte->device->phone_number, pte->device->softkeynumber[fav],
2646 sizeof(pte->device->phone_number));
2647 HandleCallOutgoing(pte);
2651 static void key_dial_page(struct unistimsession *pte, char keycode)
2653 if (keycode == KEY_FUNC3) {
2654 if (pte->device->size_phone_number <= 1)
2655 keycode = KEY_FUNC4;
2657 pte->device->size_phone_number -= 2;
2658 keycode = pte->device->phone_number[pte->device->size_phone_number] + 0x10;
2661 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
2662 char tmpbuf[] = "Number : ...............";
2665 if (pte->device->size_phone_number >= 15)
2667 if (pte->device->size_phone_number == 0)
2668 send_tone(pte, 0, 0);
2669 while (i < pte->device->size_phone_number) {
2670 tmpbuf[i + 9] = pte->device->phone_number[i];
2673 if (keycode == KEY_SHARP)
2675 else if (keycode == KEY_STAR)
2679 tmpbuf[i + 9] = keycode;
2680 pte->device->phone_number[i] = keycode;
2681 pte->device->size_phone_number++;
2682 pte->device->phone_number[i + 1] = 0;
2683 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
2684 send_blink_cursor(pte);
2685 send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 + 0x0a + i));
2688 if (keycode == KEY_FUNC4) {
2690 pte->device->size_phone_number = 0;
2691 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
2692 send_blink_cursor(pte);
2693 send_cursor_pos(pte, TEXT_LINE2 + 0x09);
2697 if (pte->device->call_forward[0] == -1) {
2698 if (keycode == KEY_FUNC1) {
2699 ast_copy_string(pte->device->call_forward, pte->device->phone_number,
2700 sizeof(pte->device->call_forward));
2701 show_main_page(pte);
2702 } else if ((keycode == KEY_FUNC2) || (keycode == KEY_HANGUP)) {
2703 pte->device->call_forward[0] = '\0';
2704 show_main_page(pte);
2710 if (ast_strlen_zero(pte->device->redial_number))
2712 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
2713 sizeof(pte->device->phone_number));
2715 HandleCallOutgoing(pte);
2718 if (pte->device->lines->subs[SUB_REAL]->owner) {
2719 /* Stop the silence generator */
2720 if (pte->device->silence_generator) {
2722 ast_verb(0, "Stopping silence generator\n");
2723 ast_channel_stop_silence_generator(pte->device->lines->subs[SUB_REAL]->
2724 owner, pte->device->silence_generator);
2725 pte->device->silence_generator = NULL;
2727 send_tone(pte, 0, 0);
2728 ast_moh_stop(ast_bridged_channel(pte->device->lines->subs[SUB_REAL]->owner));
2729 pte->device->moh = 0;
2730 pte->state = STATE_CALL;
2731 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Dialing canceled,");
2732 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "switching back to");
2733 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "previous call.");
2734 send_text_status(pte, "Hangup Transf");
2736 show_main_page(pte);
2743 Keyfavorite(pte, keycode);
2746 if (pte->device->output == OUTPUT_SPEAKER) {
2747 if (pte->device->receiver_state == STATE_OFFHOOK)
2748 send_select_output(pte, pte->device->previous_output, pte->device->volume,
2751 show_main_page(pte);
2753 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2756 if (pte->device->output == OUTPUT_HEADPHONE) {
2757 if (pte->device->receiver_state == STATE_OFFHOOK)
2758 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
2760 show_main_page(pte);
2762 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
2768 #define SELECTCODEC_START_ENTRY_POS 15
2769 #define SELECTCODEC_MAX_LENGTH 2
2770 #define SELECTCODEC_MSG "Codec number : .."
2771 static void HandleSelectCodec(struct unistimsession *pte)
2773 char buf[30], buf2[5];
2775 pte->state = STATE_SELECTCODEC;
2776 strcpy(buf, "Using codec ");
2777 sprintf(buf2, "%d", pte->device->codec_number);
2779 strcat(buf, " (G711u=0,");
2781 send_text(TEXT_LINE0, TEXT_NORMAL, pte, buf);
2782 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "G723=4,G711a=8,G729A=18)");
2783 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
2784 send_blink_cursor(pte);
2785 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
2786 pte->size_buff_entry = 0;
2787 send_text_status(pte, "Select BackSpcErase Cancel");
2791 static void key_select_codec(struct unistimsession *pte, char keycode)
2793 if (keycode == KEY_FUNC2) {
2794 if (pte->size_buff_entry <= 1)
2795 keycode = KEY_FUNC3;
2797 pte->size_buff_entry -= 2;
2798 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
2801 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
2802 char tmpbuf[] = SELECTCODEC_MSG;
2805 if (pte->size_buff_entry >= SELECTCODEC_MAX_LENGTH)
2808 while (i < pte->size_buff_entry) {
2809 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = pte->buff_entry[i];
2812 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = keycode - 0x10;
2813 pte->buff_entry[i] = keycode - 0x10;
2814 pte->size_buff_entry++;
2815 send_text(TEXT_LINE2, TEXT_INVERSE, pte, tmpbuf);
2816 send_blink_cursor(pte);
2817 send_cursor_pos(pte,
2818 (unsigned char) (TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS + 1 + i));
2824 if (pte->size_buff_entry == 1)
2825 pte->device->codec_number = pte->buff_entry[0] - 48;
2826 else if (pte->size_buff_entry == 2)
2827 pte->device->codec_number =
2828 ((pte->buff_entry[0] - 48) * 10) + (pte->buff_entry[1] - 48);
2829 show_main_page(pte);
2832 pte->size_buff_entry = 0;
2833 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
2834 send_blink_cursor(pte);
2835 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
2839 show_main_page(pte);
2845 #define SELECTEXTENSION_START_ENTRY_POS 0
2846 #define SELECTEXTENSION_MAX_LENGTH 10
2847 #define SELECTEXTENSION_MSG ".........."
2848 static void ShowExtensionPage(struct unistimsession *pte)
2850 pte->state = STATE_EXTENSION;
2852 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Please enter a Terminal");
2853 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Number (TN) :");
2854 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
2855 send_blink_cursor(pte);
2856 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
2857 send_text_status(pte, "Enter BackSpcErase");
2858 pte->size_buff_entry = 0;
2862 static void key_select_extension(struct unistimsession *pte, char keycode)
2864 if (keycode == KEY_FUNC2) {
2865 if (pte->size_buff_entry <= 1)
2866 keycode = KEY_FUNC3;
2868 pte->size_buff_entry -= 2;
2869 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
2872 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
2873 char tmpbuf[] = SELECTEXTENSION_MSG;
2876 if (pte->size_buff_entry >= SELECTEXTENSION_MAX_LENGTH)
2879 while (i < pte->size_buff_entry) {
2880 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = pte->buff_entry[i];
2883 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = keycode - 0x10;
2884 pte->buff_entry[i] = keycode - 0x10;
2885 pte->size_buff_entry++;
2886 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
2887 send_blink_cursor(pte);
2888 send_cursor_pos(pte,
2889 (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS + 1 +
2896 if (pte->size_buff_entry < 1)
2898 if (autoprovisioning == AUTOPROVISIONING_TN) {
2899 struct unistim_device *d;
2901 /* First step : looking for this TN in our device list */
2902 ast_mutex_lock(&devicelock);
2904 pte->buff_entry[pte->size_buff_entry] = '\0';
2906 if (d->id[0] == 'T') { /* It's a TN device ? */
2907 /* It's the TN we're looking for ? */
2908 if (!strcmp((d->id) + 1, pte->buff_entry)) {
2911 d->codec_number = DEFAULT_CODEC;
2914 d->receiver_state = STATE_ONHOOK;
2915 strcpy(d->id, pte->macaddr);
2916 pte->device->extension_number[0] = 'T';
2917 pte->device->extension = EXTENSION_TN;
2918 ast_copy_string((pte->device->extension_number) + 1,
2919 pte->buff_entry, pte->size_buff_entry + 1);
2920 ast_mutex_unlock(&devicelock);
2921 show_main_page(pte);
2922 refresh_all_favorite(pte);
2928 ast_mutex_unlock(&devicelock);
2929 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Invalid Terminal Number.");
2930 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Please try again :");
2931 send_cursor_pos(pte,
2932 (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS +
2933 pte->size_buff_entry));
2934 send_blink_cursor(pte);
2936 ast_copy_string(pte->device->extension_number, pte->buff_entry,
2937 pte->size_buff_entry + 1);
2938 if (RegisterExtension(pte)) {
2939 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Invalid extension.");
2940 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Please try again :");
2941 send_cursor_pos(pte,
2942 (unsigned char) (TEXT_LINE2 +
2943 SELECTEXTENSION_START_ENTRY_POS +
2944 pte->size_buff_entry));
2945 send_blink_cursor(pte);
2947 show_main_page(pte);
2951 pte->size_buff_entry = 0;
2952 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
2953 send_blink_cursor(pte);
2954 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
2960 static int ReformatNumber(char *number)
2962 int pos = 0, i = 0, size = strlen(number);
2964 for (; i < size; i++) {
2965 if ((number[i] >= '0') && (number[i] <= '9')) {
2970 number[pos] = number[i];
2978 static void show_entry_history(struct unistimsession *pte, FILE ** f)
2980 char line[TEXT_LENGTH_MAX + 1], status[STATUS_LENGTH_MAX + 1], func1[10], func2[10],
2983 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
2984 display_last_error("Can't read history date entry");
2988 line[sizeof(line) - 1] = '\0';
2989 send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
2990 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
2991 display_last_error("Can't read callerid entry");
2995 line[sizeof(line) - 1] = '\0';
2996 ast_copy_string(pte->device->lst_cid, line, sizeof(pte->device->lst_cid));
2997 send_text(TEXT_LINE1, TEXT_NORMAL, pte, line);
2998 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
2999 display_last_error("Can't read callername entry");
3003 line[sizeof(line) - 1] = '\0';
3004 send_text(TEXT_LINE2, TEXT_NORMAL, pte, line);
3007 snprintf(line, sizeof(line), "Call %03d/%03d", pte->buff_entry[2],
3008 pte->buff_entry[1]);
3009 send_texttitle(pte, line);
3011 if (pte->buff_entry[2] == 1)
3014 strcpy(func1, "Prvious");
3015 if (pte->buff_entry[2] >= pte->buff_entry[1])
3018 strcpy(func2, "Next ");
3019 if (ReformatNumber(pte->device->lst_cid))
3020 strcpy(func3, "Redial ");
3023 snprintf(status, sizeof(status), "%s%s%sCancel", func1, func2, func3);
3024 send_text_status(pte, status);
3027 static char OpenHistory(struct unistimsession *pte, char way, FILE ** f)
3029 char tmp[AST_CONFIG_MAX_PATH];
3032 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
3033 USTM_LOG_DIR, pte->device->name, way);
3034 *f = fopen(tmp, "r");
3036 display_last_error("Unable to open history file");
3039 if (fread(&count, 1, 1, *f) != 1) {
3040 display_last_error("Unable to read history header - display.");
3044 if (count > MAX_ENTRY_LOG) {
3045 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
3046 count, MAX_ENTRY_LOG);
3053 static void show_history(struct unistimsession *pte, char way)
3060 if (!pte->device->callhistory)
3062 count = OpenHistory(pte, way, &f);
3065 pte->buff_entry[0] = way;
3066 pte->buff_entry[1] = count;
3067 pte->buff_entry[2] = 1;
3068 show_entry_history(pte, &f);
3069 pte->state = STATE_HISTORY;
3072 static void show_main_page(struct unistimsession *pte)
3074 char tmpbuf[TEXT_LENGTH_MAX + 1];
3077 if ((pte->device->extension == EXTENSION_ASK) &&
3078 (ast_strlen_zero(pte->device->extension_number))) {
3079 ShowExtensionPage(pte);
3083 pte->state = STATE_MAINPAGE;
3085 send_tone(pte, 0, 0);
3086 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON_DISCRET);
3087 pte->device->lines->lastmsgssent = 0;
3088 send_favorite(pte->device->softkeylinepos, FAV_ICON_ONHOOK_BLACK, pte,
3089 pte->device->softkeylabel[pte->device->softkeylinepos]);
3090 if (!ast_strlen_zero(pte->device->call_forward)) {
3091 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Call forwarded to :");
3092 send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->call_forward);
3093 Sendicon(TEXT_LINE0, FAV_ICON_REFLECT + FAV_BLINK_SLOW, pte);
3094 send_text_status(pte, "Dial Redial NoForwd");
3096 if ((pte->device->extension == EXTENSION_ASK) ||
3097 (pte->device->extension == EXTENSION_TN))
3098 send_text_status(pte, "Dial Redial ForwardUnregis");
3100 send_text_status(pte, "Dial Redial Forward");
3102 send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->maintext1);
3103 if (pte->device->missed_call == 0)
3104 send_text(TEXT_LINE0, TEXT_NORMAL, pte, pte->device->maintext0);
3106 sprintf(tmpbuf, "%d unanswered call(s)", pte->device->missed_call);
3107 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpbuf);
3108 Sendicon(TEXT_LINE0, FAV_ICON_CALL_CENTER + FAV_BLINK_SLOW, pte);
3111 if (ast_strlen_zero(pte->device->maintext2)) {
3112 strcpy(tmpbuf, "IP : ");
3113 strcat(tmpbuf, ast_inet_ntoa(pte->sin.sin_addr));
3114 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
3116 send_text(TEXT_LINE2, TEXT_NORMAL, pte, pte->device->maintext2);
3117 send_texttitle(pte, pte->device->titledefault);
3118 change_favorite_icon(pte, FAV_ICON_ONHOOK_BLACK);
3121 static void key_main_page(struct unistimsession *pte, char keycode)
3123 if (pte->device->missed_call) {
3124 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
3125 pte->device->missed_call = 0;
3127 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
3128 handle_dial_page(pte);
3129 key_dial_page(pte, keycode);
3134 handle_dial_page(pte);
3137 if (ast_strlen_zero(pte->device->redial_number))
3139 if ((pte->device->output == OUTPUT_HANDSET) &&
3140 (pte->device->receiver_state == STATE_ONHOOK))
3141 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
3143 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
3145 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
3146 sizeof(pte->device->phone_number));
3147 HandleCallOutgoing(pte);
3150 if (!ast_strlen_zero(pte->device->call_forward)) {
3151 /* Cancel call forwarding */
3152 memmove(pte->device->call_forward + 1, pte->device->call_forward,
3153 sizeof(pte->device->call_forward));
3154 pte->device->call_forward[0] = '\0';
3155 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
3156 pte->device->output = OUTPUT_HANDSET; /* Seems to be reseted somewhere */
3157 show_main_page(pte);
3160 pte->device->call_forward[0] = -1;
3161 handle_dial_page(pte);
3164 if (pte->device->extension == EXTENSION_ASK) {
3165 UnregisterExtension(pte);
3166 pte->device->extension_number[0] = '\0';
3167 ShowExtensionPage(pte);
3168 } else if (pte->device->extension == EXTENSION_TN) {
3169 ast_mutex_lock(&devicelock);
3170 strcpy(pte->device->id, pte->device->extension_number);
3171 pte->buff_entry[0] = '\0';
3172 pte->size_buff_entry = 0;
3173 pte->device->session = NULL;
3175 ast_mutex_unlock(&devicelock);
3176 ShowExtensionPage(pte);
3180 handle_dial_page(pte);
3187 if ((pte->device->output == OUTPUT_HANDSET) &&
3188 (pte->device->receiver_state == STATE_ONHOOK))
3189 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
3191 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
3192 Keyfavorite(pte, keycode);
3195 HandleSelectCodec(pte);
3198 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
3199 handle_dial_page(pte);
3202 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
3203 handle_dial_page(pte);
3206 show_history(pte, 'o');
3209 show_history(pte, 'i');
3215 static void key_history(struct unistimsession *pte, char keycode)
3225 if (pte->buff_entry[2] <= 1)
3227 pte->buff_entry[2]--;
3228 count = OpenHistory(pte, pte->buff_entry[0], &f);
3231 offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
3232 if (fseek(f, offset, SEEK_CUR)) {
3233 display_last_error("Unable to seek history entry.");
3237 show_entry_history(pte, &f);
3242 if (pte->buff_entry[2] >= pte->buff_entry[1])
3244 pte->buff_entry[2]++;
3245 count = OpenHistory(pte, pte->buff_entry[0], &f);
3248 offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
3249 if (fseek(f, offset, SEEK_CUR)) {
3250 display_last_error("Unable to seek history entry.");
3254 show_entry_history(pte, &f);
3257 if (!ReformatNumber(pte->device->lst_cid))
3259 ast_copy_string(pte->device->redial_number, pte->device->lst_cid,
3260 sizeof(pte->device->redial_number));
3261 key_main_page(pte, KEY_FUNC2);
3265 show_main_page(pte);
3268 if (pte->buff_entry[0] == 'i')
3269 show_history(pte, 'o');
3271 show_main_page(pte);
3274 if (pte->buff_entry[0] == 'i')
3275 show_main_page(pte);
3277 show_history(pte, 'i');
3283 static void init_phone_step2(struct unistimsession *pte)
3287 ast_verb(0, "Sending S4\n");
3288 memcpy(buffsend + SIZE_HEADER, packet_send_s4, sizeof(packet_send_s4));
3289 send_client(SIZE_HEADER + sizeof(packet_send_s4), buffsend, pte);
3290 send_date_time2(pte);
3291 send_date_time3(pte);
3293 ast_verb(0, "Sending S7\n");
3294 memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
3295 send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
3297 ast_verb(0, "Sending Contrast\n");
3298 memcpy(buffsend + SIZE_HEADER, packet_send_Contrast, sizeof(packet_send_Contrast));
3299 if (pte->device != NULL)
3300 buffsend[9] = pte->device->contrast;
3301 send_client(SIZE_HEADER + sizeof(packet_send_Contrast), buffsend, pte);
3304 ast_verb(0, "Sending S9\n");
3305 memcpy(buffsend + SIZE_HEADER, packet_send_s9, sizeof(packet_send_s9));
3306 send_client(SIZE_HEADER + sizeof(packet_send_s9), buffsend, pte);
3310 ast_verb(0, "Sending S7\n");
3311 memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
3312 send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
3313 send_led_update(pte, 0);
3315 if (pte->state < STATE_MAINPAGE) {
3316 if (autoprovisioning == AUTOPROVISIONING_TN) {
3317 ShowExtensionPage(pte);
3323 for (i = 1; i < 6; i++)
3324 send_favorite(i, 0, pte, "");
3325 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Sorry, this phone is not");
3326 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "registered in unistim.cfg");
3327 strcpy(tmp, "MAC = ");
3328 strcat(tmp, pte->macaddr);
3329 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
3330 send_text_status(pte, "");
3331 send_texttitle(pte, "UNISTIM for*");
3335 show_main_page(pte);
3336 refresh_all_favorite(pte);
3338 ast_verb(0, "Sending arrow\n");
3339 memcpy(buffsend + SIZE_HEADER, packet_send_arrow, sizeof(packet_send_arrow));
3340 send_client(SIZE_HEADER + sizeof(packet_send_arrow), buffsend, pte);
3344 static void process_request(int size, unsigned char *buf, struct unistimsession *pte)
3348 (buf + SIZE_HEADER, packet_recv_resume_connection_with_server,
3349 sizeof(packet_recv_resume_connection_with_server)) == 0) {
3350 rcv_resume_connection_with_server(pte);
3353 if (memcmp(buf + SIZE_HEADER, packet_recv_firm_version, sizeof(packet_recv_firm_version)) ==
3357 ast_verb(0, "Got the firmware version : '%s'\n", buf + 13);
3358 init_phone_step2(pte);
3361 if (memcmp(buf + SIZE_HEADER, packet_recv_mac_addr, sizeof(packet_recv_mac_addr)) == 0) {
3362 rcv_mac_addr(pte, buf);
3365 if (memcmp(buf + SIZE_HEADER, packet_recv_r2, sizeof(packet_recv_r2)) == 0) {
3367 ast_verb(0, "R2 received\n");
3371 if (pte->state < STATE_MAINPAGE) {
3373 ast_verb(0, "Request not authorized in this state\n");
3376 if (!memcmp(buf + SIZE_HEADER, packet_recv_pressed_key, sizeof(packet_recv_pressed_key))) {
3377 char keycode = buf[13];
3380 ast_verb(0, "Key pressed : keycode = 0x%.2x - current state : %d\n", keycode,
3383 switch (pte->state) {
3386 ast_verb(0, "No keys allowed in the init state\n");
3388 case STATE_AUTHDENY:
3390 ast_verb(0, "No keys allowed in authdeny state\n");
3392 case STATE_MAINPAGE:
3393 key_main_page(pte, keycode);
3395 case STATE_DIALPAGE:
3396 key_dial_page(pte, keycode);
3399 key_ringing(pte, keycode);
3402 key_call(pte, keycode);
3404 case STATE_EXTENSION:
3405 key_select_extension(pte, keycode);
3407 case STATE_SELECTCODEC:
3408 key_select_codec(pte, keycode);
3411 key_history(pte, keycode);
3414 ast_log(LOG_WARNING, "Key : Unknown state\n");
3418 if (memcmp(buf + SIZE_HEADER, packet_recv_pick_up, sizeof(packet_recv_pick_up)) == 0) {
3420 ast_verb(0, "Handset off hook\n");
3421 if (!pte->device) /* We are not yet registered (asking for a TN in AUTOPROVISIONING_TN) */
3423 pte->device->receiver_state = STATE_OFFHOOK;
3424 if (pte->device->output == OUTPUT_HEADPHONE)
3425 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
3427 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
3428 if (pte->state == STATE_RINGING)
3429 HandleCallIncoming(pte);
3430 else if ((pte->state == STATE_DIALPAGE) || (pte->state == STATE_CALL))
3431 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
3432 else if (pte->state == STATE_EXTENSION) /* We must have a TN before calling */
3435 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
3436 handle_dial_page(pte);