2 * Asterisk -- An open source telephony toolkit.
4 * UNISTIM channel driver for asterisk
6 * Copyright (C) 2005 - 2007, Cedric Hans
8 * Cedric Hans <cedric.hans@mlkj.net>
10 * Asterisk 1.4 patch by Peter Be
12 * See http://www.asterisk.org for more information about
13 * the Asterisk project. Please do not directly contact
14 * any of the maintainers of this project for assistance;
15 * the project provides a web site, mailing lists and IRC
16 * channels for your use.
18 * This program is free software, distributed under the terms of
19 * the GNU General Public License Version 2. See the LICENSE file
20 * at the top of the source tree.
26 * \brief chan_unistim channel driver for Asterisk
27 * \author Cedric Hans <cedric.hans@mlkj.net>
29 * Unistim (Unified Networks IP Stimulus) channel driver
30 * for Nortel i2002, i2004 and i2050
32 * \ingroup channel_drivers
36 <support_level>extended</support_level>
41 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
46 #if defined(__CYGWIN__)
48 * cygwin headers are partly inconsistent. struct iovec is defined in sys/uio.h
49 * which is not included by default by sys/socket.h - in_pktinfo is defined in
50 * w32api/ws2tcpip.h but this probably has compatibility problems with sys/socket.h
51 * So for the time being we simply disable HAVE_PKTINFO when building under cygwin.
52 * This should be done in some common header, but for now this is the only file
53 * using iovec and in_pktinfo so it suffices to apply the fix here.
58 #endif /* __CYGWIN__ */
60 #include "asterisk/paths.h" /* ast_config_AST_LOG_DIR used in (too ?) many places */
61 #include "asterisk/network.h"
62 #include "asterisk/channel.h"
63 #include "asterisk/config.h"
64 #include "asterisk/module.h"
65 #include "asterisk/pbx.h"
66 #include "asterisk/event.h"
67 #include "asterisk/rtp_engine.h"
68 #include "asterisk/netsock.h"
69 #include "asterisk/acl.h"
70 #include "asterisk/callerid.h"
71 #include "asterisk/cli.h"
72 #include "asterisk/app.h"
73 #include "asterisk/musiconhold.h"
74 #include "asterisk/causes.h"
75 #include "asterisk/indications.h"
77 /*! Beware, G729 and G723 are not supported by asterisk, except with the proper licence */
79 #define DEFAULTCONTEXT "default"
80 #define DEFAULTCALLERID "Unknown"
81 #define DEFAULTCALLERNAME " "
82 #define DEFAULTHEIGHT 3
83 #define USTM_LOG_DIR "unistimHistory"
85 /*! Size of the transmit buffer */
86 #define MAX_BUF_SIZE 64
87 /*! Number of slots for the transmit queue */
88 #define MAX_BUF_NUMBER 50
89 /*! Try x times before removing the phone */
90 #define NB_MAX_RETRANSMIT 8
91 /*! Nb of milliseconds waited when no events are scheduled */
92 #define IDLE_WAIT 1000
93 /*! Wait x milliseconds before resending a packet */
94 #define RETRANSMIT_TIMER 2000
95 /*! How often the mailbox is checked for new messages */
96 #define TIMER_MWI 10000
98 #define DEFAULT_CODEC 0x00
99 #define SIZE_PAGE 4096
100 #define DEVICE_NAME_LEN 16
101 #define AST_CONFIG_MAX_PATH 255
102 #define MAX_ENTRY_LOG 30
105 #define SUB_THREEWAY 1
108 struct ast_format_cap *global_cap;
111 AUTOPROVISIONING_NO = 0,
112 AUTOPROVISIONING_YES,
118 /*! Do not create an extension into the default dialplan */
120 /*! Prompt user for an extension number and register it */
122 /*! Register an extension with the line=> value */
124 /*! Used with AUTOPROVISIONING_TN */
127 #define OUTPUT_HANDSET 0xC0
128 #define OUTPUT_HEADPHONE 0xC1
129 #define OUTPUT_SPEAKER 0xC2
131 #define VOLUME_LOW 0x01
132 #define VOLUME_LOW_SPEAKER 0x03
133 #define VOLUME_NORMAL 0x02
134 #define VOLUME_INSANELY_LOUD 0x07
136 #define MUTE_OFF 0x00
138 #define MUTE_ON_DISCRET 0xCE
140 #define SIZE_HEADER 6
141 #define SIZE_MAC_ADDR 17
142 #define TEXT_LENGTH_MAX 24
143 #define TEXT_LINE0 0x00
144 #define TEXT_LINE1 0x20
145 #define TEXT_LINE2 0x40
146 #define TEXT_NORMAL 0x05
147 #define TEXT_INVERSE 0x25
148 #define STATUS_LENGTH_MAX 28
150 #define FAV_ICON_NONE 0x00
151 #define FAV_ICON_ONHOOK_BLACK 0x20
152 #define FAV_ICON_ONHOOK_WHITE 0x21
153 #define FAV_ICON_SPEAKER_ONHOOK_BLACK 0x22
154 #define FAV_ICON_SPEAKER_ONHOOK_WHITE 0x23
155 #define FAV_ICON_OFFHOOK_BLACK 0x24
156 #define FAV_ICON_OFFHOOK_WHITE 0x25
157 #define FAV_ICON_ONHOLD_BLACK 0x26
158 #define FAV_ICON_ONHOLD_WHITE 0x27
159 #define FAV_ICON_SPEAKER_OFFHOOK_BLACK 0x28
160 #define FAV_ICON_SPEAKER_OFFHOOK_WHITE 0x29
161 #define FAV_ICON_PHONE_BLACK 0x2A
162 #define FAV_ICON_PHONE_WHITE 0x2B
163 #define FAV_ICON_SPEAKER_ONHOLD_BLACK 0x2C
164 #define FAV_ICON_SPEAKER_ONHOLD_WHITE 0x2D
165 #define FAV_ICON_HEADPHONES 0x2E
166 #define FAV_ICON_HEADPHONES_ONHOLD 0x2F
167 #define FAV_ICON_HOME 0x30
168 #define FAV_ICON_CITY 0x31
169 #define FAV_ICON_SHARP 0x32
170 #define FAV_ICON_PAGER 0x33
171 #define FAV_ICON_CALL_CENTER 0x34
172 #define FAV_ICON_FAX 0x35
173 #define FAV_ICON_MAILBOX 0x36
174 #define FAV_ICON_REFLECT 0x37
175 #define FAV_ICON_COMPUTER 0x38
176 #define FAV_ICON_FORWARD 0x39
177 #define FAV_ICON_LOCKED 0x3A
178 #define FAV_ICON_TRASH 0x3B
179 #define FAV_ICON_INBOX 0x3C
180 #define FAV_ICON_OUTBOX 0x3D
181 #define FAV_ICON_MEETING 0x3E
182 #define FAV_ICON_BOX 0x3F
184 #define FAV_BLINK_FAST 0x20
185 #define FAV_BLINK_SLOW 0x40
187 #define FAV_MAX_LENGTH 0x0A
189 static void dummy(char *unused, ...)
194 /*! \brief Global jitterbuffer configuration - by default, jb is disabled
195 * \note Values shown here match the defaults shown in unistim.conf.sample */
196 static struct ast_jb_conf default_jbconf =
200 .resync_threshold = 1000,
204 static struct ast_jb_conf global_jbconf;
207 /* #define DUMP_PACKET 1 */
208 /* #define DEBUG_TIMER ast_verbose */
210 #define DEBUG_TIMER dummy
211 /*! Enable verbose output. can also be set with the CLI */
212 static int unistimdebug = 0;
213 static int unistim_port;
214 static enum autoprovision autoprovisioning = AUTOPROVISIONING_NO;
215 static int unistim_keepalive;
216 static int unistimsock = -1;
220 unsigned int tos_audio;
222 unsigned int cos_audio;
223 } qos = { 0, 0, 0, 0 };
225 static struct io_context *io;
226 static struct ast_sched_context *sched;
227 static struct sockaddr_in public_ip = { 0, };
228 /*! give the IP address for the last packet received */
229 static struct sockaddr_in address_from;
230 /*! size of the sockaddr_in (in WSARecvFrom) */
231 static unsigned int size_addr_from = sizeof(address_from);
232 /*! Receive buffer address */
233 static unsigned char *buff;
234 static int unistim_reloading = 0;
235 AST_MUTEX_DEFINE_STATIC(unistim_reload_lock);
236 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
237 static int usecnt = 0;
238 /* extern char ast_config_AST_LOG_DIR[AST_CONFIG_MAX_PATH]; */
240 /*! This is the thread for the monitor which checks for input on the channels
241 * which are not currently in use. */
242 static pthread_t monitor_thread = AST_PTHREADT_NULL;
244 /*! Protect the monitoring thread, so only one process can kill or start it, and not
245 * when it's doing something critical. */
246 AST_MUTEX_DEFINE_STATIC(monlock);
247 /*! Protect the session list */
248 AST_MUTEX_DEFINE_STATIC(sessionlock);
249 /*! Protect the device list */
250 AST_MUTEX_DEFINE_STATIC(devicelock);
311 struct tone_zone_unistim {
317 static const struct tone_zone_unistim frequency[] = {
357 unsigned short w_year;
358 unsigned short w_month;
359 unsigned short w_day_of_week;
360 unsigned short w_day;
361 unsigned short w_hour;
362 unsigned short w_minute;
363 unsigned short w_second;
364 unsigned short w_milliseconds;
367 struct unistim_subchannel {
369 /*! SUBS_REAL or SUBS_THREEWAY */
370 unsigned int subtype;
371 /*! Asterisk channel used by the subchannel */
372 struct ast_channel *owner;
374 struct unistim_line *parent;
376 struct ast_rtp_instance *rtp;
383 * \todo Convert to stringfields
385 struct unistim_line {
389 /*! Like USTM/200\@black */
391 /*! pointer to our current connection, channel... */
392 struct unistim_subchannel *subs[MAX_SUBS];
393 /*! Extension where to start */
394 char exten[AST_MAX_EXTENSION];
395 /*! Context to start in */
396 char context[AST_MAX_EXTENSION];
397 /*! Language for asterisk sounds */
398 char language[MAX_LANGUAGE];
399 /*! CallerID Number */
400 char cid_num[AST_MAX_EXTENSION];
401 /*! Mailbox for MWI */
402 char mailbox[AST_MAX_EXTENSION];
407 /*! MusicOnHold class */
408 char musicclass[MAX_MUSICCLASS];
410 unsigned int callgroup;
412 unsigned int pickupgroup;
413 /*! Account code (for billing) */
414 char accountcode[80];
415 /*! AMA flags (for billing) */
417 /*! Codec supported */
418 struct ast_format_cap *cap;
420 char parkinglot[AST_MAX_CONTEXT];
421 struct unistim_line *next;
422 struct unistim_device *parent;
426 * \brief A device containing one or more lines
428 static struct unistim_device {
429 int receiver_state; /*!< state of the receiver (see ReceiverState) */
430 int size_phone_number; /*!< size of the phone number */
431 char phone_number[16]; /*!< the phone number entered by the user */
432 char redial_number[16]; /*!< the last phone number entered by the user */
433 int phone_current; /*!< Number of the current phone */
434 int pos_fav; /*!< Position of the displayed favorites (used for scrolling) */
435 char id[18]; /*!< mac address of the current phone in ascii */
436 char name[DEVICE_NAME_LEN]; /*!< name of the device */
437 int softkeylinepos; /*!< position of the line softkey (default 0) */
438 char softkeylabel[6][11]; /*!< soft key label */
439 char softkeynumber[6][16]; /*!< number dialed when the soft key is pressed */
440 char softkeyicon[6]; /*!< icon number */
441 char softkeydevice[6][16]; /*!< name of the device monitored */
442 struct unistim_device *sp[6]; /*!< pointer to the device monitored by this soft key */
443 int height; /*!< The number of lines the phone can display */
444 char maintext0[25]; /*!< when the phone is idle, display this string on line 0 */
445 char maintext1[25]; /*!< when the phone is idle, display this string on line 1 */
446 char maintext2[25]; /*!< when the phone is idle, display this string on line 2 */
447 char titledefault[13]; /*!< title (text before date/time) */
448 char datetimeformat; /*!< format used for displaying time/date */
449 char contrast; /*!< contrast */
450 char country[3]; /*!< country used for dial tone frequency */
451 struct ast_tone_zone *tz; /*!< Tone zone for res_indications (ring, busy, congestion) */
452 char ringvolume; /*!< Ring volume */
453 char ringstyle; /*!< Ring melody */
454 int rtp_port; /*!< RTP port used by the phone */
455 int rtp_method; /*!< Select the unistim data used to establish a RTP session */
456 int status_method; /*!< Select the unistim packet used for sending status text */
457 char codec_number; /*!< The current codec used to make calls */
458 int missed_call; /*!< Number of call unanswered */
459 int callhistory; /*!< Allowed to record call history */
460 char lst_cid[TEXT_LENGTH_MAX]; /*!< Last callerID received */
461 char lst_cnm[TEXT_LENGTH_MAX]; /*!< Last callername recevied */
462 char call_forward[AST_MAX_EXTENSION]; /*!< Forward number */
463 int output; /*!< Handset, headphone or speaker */
464 int previous_output; /*!< Previous output */
465 int volume; /*!< Default volume */
466 int mute; /*!< Mute mode */
467 int moh; /*!< Music on hold in progress */
468 int nat; /*!< Used by the obscure ast_rtp_setnat */
469 enum autoprov_extn extension; /*!< See ifdef EXTENSION for valid values */
470 char extension_number[11]; /*!< Extension number entered by the user */
471 char to_delete; /*!< Used in reload */
472 time_t start_call_timestamp; /*!< timestamp for the length calculation of the call */
473 struct ast_silence_generator *silence_generator;
474 struct unistim_line *lines;
476 struct unistimsession *session;
477 struct unistim_device *next;
480 static struct unistimsession {
482 struct sockaddr_in sin; /*!< IP address of the phone */
483 struct sockaddr_in sout; /*!< IP address of server */
484 int timeout; /*!< time-out in ticks : resend packet if no ack was received before the timeout occured */
485 unsigned short seq_phone; /*!< sequence number for the next packet (when we receive a request) */
486 unsigned short seq_server; /*!< sequence number for the next packet (when we send a request) */
487 unsigned short last_seq_ack; /*!< sequence number of the last ACK received */
488 unsigned long tick_next_ping; /*!< time for the next ping */
489 int last_buf_available; /*!< number of a free slot */
490 int nb_retransmit; /*!< number of retransmition */
491 int state; /*!< state of the phone (see phone_state) */
492 int size_buff_entry; /*!< size of the buffer used to enter datas */
493 char buff_entry[16]; /*!< Buffer for temporary datas */
494 char macaddr[18]; /*!< mac adress of the phone (not always available) */
495 struct wsabuf wsabufsend[MAX_BUF_NUMBER]; /*!< Size of each paquet stored in the buffer array & pointer to this buffer */
496 unsigned char buf[MAX_BUF_NUMBER][MAX_BUF_SIZE]; /*!< Buffer array used to keep the lastest non-acked paquets */
497 struct unistim_device *device;
498 struct unistimsession *next;
502 * \page Unistim datagram formats
504 * Format of datagrams :
505 * bytes 0 & 1 : ffff for discovery packet, 0000 for everything else
506 * byte 2 : sequence number (high part)
507 * byte 3 : sequence number (low part)
508 * byte 4 : 2 = ask question or send info, 1 = answer or ACK, 0 = retransmit request
509 * byte 5 : direction, 1 = server to phone, 2 = phone to server arguments
512 static const unsigned char packet_rcv_discovery[] =
513 { 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
514 static const unsigned char packet_send_discovery_ack[] =
515 { 0x00, 0x00, /*Initial Seq (2 bytes) */ 0x00, 0x00, 0x00, 0x01 };
517 static const unsigned char packet_recv_firm_version[] =
518 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x0a, 0x02 };
519 static const unsigned char packet_recv_pressed_key[] =
520 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x04, 0x00 };
521 static const unsigned char packet_recv_pick_up[] =
522 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x04 };
523 static const unsigned char packet_recv_hangup[] =
524 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x03 };
525 static const unsigned char packet_recv_r2[] = { 0x00, 0x00, 0x00, 0x13, 0x96, 0x03, 0x03 };
527 /*! TransportAdapter */
528 static const unsigned char packet_recv_resume_connection_with_server[] =
529 { 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
530 static const unsigned char packet_recv_mac_addr[] =
531 { 0xff, 0xff, 0xff, 0xff, 0x9a, 0x0d, 0x07 /*MacAddr */ };
533 static const unsigned char packet_send_date_time3[] =
534 { 0x11, 0x09, 0x02, 0x02, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07,
535 /*Minutes */ 0x08, 0x32
537 static const unsigned char packet_send_date_time[] =
538 { 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07, /*Minutes */
539 0x08, 0x32, 0x17, 0x04, 0x24, 0x07, 0x19,
540 0x04, 0x07, 0x00, 0x19, 0x05, 0x09, 0x3e, 0x0f, 0x16, 0x05, 0x00, 0x80, 0x00, 0x1e,
541 0x05, 0x12, 0x00, 0x78
544 static const unsigned char packet_send_no_ring[] =
545 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00 };
546 static const unsigned char packet_send_s4[] =
547 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff,
548 0x16, 0x05, 0x1c, 0x00, 0x00, 0x17, 0x05,
549 0x0b, 0x00, 0x00, 0x19, 0x04, 0x00, 0x00, 0x19, 0x04, 0x00, 0x08, 0x19, 0x04, 0x00,
550 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
551 0x31, 0x00, 0x00, 0x16, 0x05, 0x04, 0x00, 0x00
553 static const unsigned char packet_send_call[] =
554 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf,
555 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16, 0x0a, 0x38, 0x00, 0x12, 0xca, 0x03,
556 0xc0, 0xc3, 0xc5, 0x16, 0x16, 0x30, 0x00,
557 0x00, /*codec */ 0x12, 0x12, /* frames per packet */ 0x01, 0x5c, 0x00, /*port RTP */
558 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41,
559 /*port RTP */ 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41, /* IP Address */ 0x0a, 0x01,
562 static const unsigned char packet_send_stream_based_tone_off[] =
563 { 0x16, 0x05, 0x1c, 0x00, 0x00 };
565 /* static const unsigned char packet_send_Mute[] = { 0x16, 0x05, 0x04, 0x00, 0x00 };
566 static const unsigned char packet_send_CloseAudioStreamRX[] = { 0x16, 0x05, 0x31, 0x00, 0xff };
567 static const unsigned char packet_send_CloseAudioStreamTX[] = { 0x16, 0x05, 0x31, 0xff, 0x00 };*/
568 static const unsigned char packet_send_stream_based_tone_on[] =
569 { 0x16, 0x06, 0x1b, 0x00, 0x00, 0x05 };
570 static const unsigned char packet_send_stream_based_tone_single_freq[] =
571 { 0x16, 0x06, 0x1d, 0x00, 0x01, 0xb8 };
572 static const unsigned char packet_send_stream_based_tone_dial_freq[] =
573 { 0x16, 0x08, 0x1d, 0x00, 0x01, 0xb8, 0x01, 0x5e };
574 static const unsigned char packet_send_select_output[] =
575 { 0x16, 0x06, 0x32, 0xc0, 0x01, 0x00 };
576 static const unsigned char packet_send_ring[] =
577 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16,
578 0x04, 0x1a, 0x01, 0x16, 0x05, 0x12, 0x13 /* Ring type 10 to 17 */ , 0x18, 0x16, 0x04, 0x18, /* volume 00, 10, 20... */
579 0x20, 0x16, 0x04, 0x10, 0x00
581 static const unsigned char packet_send_end_call[] =
582 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x31, 0x00, 0x00, 0x19, 0x04, 0x00,
583 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
584 0x04, 0x00, 0x00, 0x16, 0x04, 0x37, 0x10
586 static const unsigned char packet_send_s9[] =
587 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x19, 0x04, 0x00, 0x10, 0x16, 0x05, 0x1c, 0x00,
589 static const unsigned char packet_send_rtp_packet_size[] =
590 { 0x16, 0x08, 0x38, 0x00, 0x00, 0xe0, 0x00, 0xa0 };
591 static const unsigned char packet_send_jitter_buffer_conf[] =
592 { 0x16, 0x0e, 0x3a, 0x00, /* jitter */ 0x02, /* high water mark */ 0x04, 0x00, 0x00,
593 /* early packet resync 2 bytes */ 0x3e, 0x80,
594 0x00, 0x00, /* late packet resync 2 bytes */ 0x3e, 0x80
597 /* Duration in ms div 2 (0x20 = 64ms, 0x08 = 16ms)
598 static unsigned char packet_send_StreamBasedToneCad[] =
599 { 0x16, 0x0a, 0x1e, 0x00, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x2b }; */
600 static const unsigned char packet_send_open_audio_stream_rx[] =
601 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
602 0x0e, 0x01, /* Port */ 0x14, 0x50, 0x00,
603 0x00, /* Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
605 static const unsigned char packet_send_open_audio_stream_tx[] =
606 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
607 0x0e, 0x01, /* Local port */ 0x14, 0x50,
608 0x00, 0x00, /* Rmt Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
611 static const unsigned char packet_send_open_audio_stream_rx3[] =
612 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
613 0x06, 0x81, /* RTP Port */ 0x14, 0x50,
614 /* RTCP Port */ 0x14,
615 0x51, /* RTP Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00, /* Dest IP */ 0x0a, 0x93,
618 static const unsigned char packet_send_open_audio_stream_tx3[] =
619 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
620 0x06, 0x81, /* RTP Local port */ 0x14, 0x50,
621 /* RTCP Port */ 0x00, 0x00, /* RTP Rmt Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00,
622 /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
625 static const unsigned char packet_send_arrow[] = { 0x17, 0x04, 0x04, 0x00 };
626 static const unsigned char packet_send_blink_cursor[] = { 0x17, 0x04, 0x10, 0x86 };
627 static const unsigned char packet_send_date_time2[] = { 0x17, 0x04, 0x17, 0x3d, 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */
628 0x06, /*Hour */ 0x07, /*Minutes */ 0x08, 0x32
630 static const unsigned char packet_send_Contrast[] =
631 { 0x17, 0x04, 0x24, /*Contrast */ 0x08 };
632 static const unsigned char packet_send_StartTimer[] =
633 { 0x17, 0x05, 0x0b, 0x05, 0x00, 0x17, 0x08, 0x16, /* Text */ 0x44, 0x75, 0x72, 0xe9,
635 static const unsigned char packet_send_stop_timer[] = { 0x17, 0x05, 0x0b, 0x02, 0x00 };
636 static const unsigned char packet_send_icon[] = { 0x17, 0x05, 0x14, /*pos */ 0x00, /*icon */ 0x25 }; /* display an icon in front of the text zone */
637 static const unsigned char packet_send_S7[] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 };
638 static const unsigned char packet_send_set_pos_cursor[] =
639 { 0x17, 0x06, 0x10, 0x81, 0x04, /*pos */ 0x20 };
641 /*static unsigned char packet_send_MonthLabelsDownload[] =
642 { 0x17, 0x0a, 0x15, Month (3 char) 0x46, 0x65, 0x62, 0x4d, 0xe4, 0x72, 0x20 }; */
643 static const unsigned char packet_send_favorite[] =
644 { 0x17, 0x0f, 0x19, 0x10, /*pos */ 0x01, /*name */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
645 0x20, 0x20, 0x20, 0x20, /*end_name */ 0x19,
646 0x05, 0x0f, /*pos */ 0x01, /*icone */ 0x00
648 static const unsigned char packet_send_title[] =
649 { 0x17, 0x10, 0x19, 0x02, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
650 0x20, 0x20, 0x20, 0x20 /*end_text */ };
651 static const unsigned char packet_send_text[] =
652 { 0x17, 0x1e, 0x1b, 0x04, /*pos */ 0x00, /*inverse */ 0x25, /*text */ 0x20, 0x20,
653 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
654 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
655 /*end_text */ 0x17, 0x04, 0x10, 0x87
657 static const unsigned char packet_send_status[] =
658 { 0x17, 0x20, 0x19, 0x08, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
659 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
660 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 /*end_text */
662 static const unsigned char packet_send_status2[] =
663 { 0x17, 0x0b, 0x19, /* pos [08|28|48|68] */ 0x00, /* text */ 0x20, 0x20, 0x20, 0x20,
664 0x20, 0x20, 0x20 /* end_text */ };
666 static const unsigned char packet_send_led_update[] = { 0x19, 0x04, 0x00, 0x00 };
668 static const unsigned char packet_send_query_basic_manager_04[] = { 0x1a, 0x04, 0x01, 0x04 };
669 static const unsigned char packet_send_query_mac_address[] = { 0x1a, 0x04, 0x01, 0x08 };
670 static const unsigned char packet_send_query_basic_manager_10[] = { 0x1a, 0x04, 0x01, 0x10 };
671 static const unsigned char packet_send_S1[] = { 0x1a, 0x07, 0x07, 0x00, 0x00, 0x00, 0x13 };
673 static unsigned char packet_send_ping[] =
674 { 0x1e, 0x05, 0x12, 0x00, /*Watchdog timer */ 0x78 };
676 #define BUFFSEND unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }
678 static const char tdesc[] = "UNISTIM Channel Driver";
679 static const char channel_type[] = "USTM";
682 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state, const char *linkedid);
683 static int load_module(void);
684 static int reload(void);
685 static int unload_module(void);
686 static int reload_config(void);
687 static void show_main_page(struct unistimsession *pte);
688 static struct ast_channel *unistim_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor,
689 void *data, int *cause);
690 static int unistim_call(struct ast_channel *ast, char *dest, int timeout);
691 static int unistim_hangup(struct ast_channel *ast);
692 static int unistim_answer(struct ast_channel *ast);
693 static struct ast_frame *unistim_read(struct ast_channel *ast);
694 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame);
695 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
697 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
698 static int unistim_senddigit_begin(struct ast_channel *ast, char digit);
699 static int unistim_senddigit_end(struct ast_channel *ast, char digit,
700 unsigned int duration);
701 static int unistim_sendtext(struct ast_channel *ast, const char *text);
703 static int write_entry_history(struct unistimsession *pte, FILE * f, char c,
705 static void change_callerid(struct unistimsession *pte, int type, char *callerid);
707 static struct ast_channel_tech unistim_tech = {
708 .type = channel_type,
709 .description = tdesc,
710 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
711 .requester = unistim_request,
712 .call = unistim_call,
713 .hangup = unistim_hangup,
714 .answer = unistim_answer,
715 .read = unistim_read,
716 .write = unistim_write,
717 .indicate = unistim_indicate,
718 .fixup = unistim_fixup,
719 .send_digit_begin = unistim_senddigit_begin,
720 .send_digit_end = unistim_senddigit_end,
721 .send_text = unistim_sendtext,
722 .bridge = ast_rtp_instance_bridge,
725 static void display_last_error(const char *sz_msg)
731 /* Display the error message */
732 ast_log(LOG_WARNING, "%s %s : (%u) %s\n", ctime(&cur_time), sz_msg, errno,
736 static unsigned int get_tick_count(void)
738 struct timeval now = ast_tvnow();
740 return (now.tv_sec * 1000) + (now.tv_usec / 1000);
743 /* Send data to a phone without retransmit nor buffering */
744 static void send_raw_client(int size, const unsigned char *data, struct sockaddr_in *addr_to,
745 const struct sockaddr_in *addr_ourip)
748 struct iovec msg_iov;
750 char buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
751 struct cmsghdr *ip_msg = (struct cmsghdr *) buffer;
752 struct in_pktinfo *pki = (struct in_pktinfo *) CMSG_DATA(ip_msg);
754 /* cast this to a non-const pointer, since the sendmsg() API
755 * does not provide read-only and write-only flavors of the
756 * structures used for its arguments, but in this case we know
757 * the data will not be modified
759 msg_iov.iov_base = (char *) data;
760 msg_iov.iov_len = size;
762 msg.msg_name = addr_to; /* optional address */
763 msg.msg_namelen = sizeof(struct sockaddr_in); /* size of address */
764 msg.msg_iov = &msg_iov; /* scatter/gather array */
765 msg.msg_iovlen = 1; /* # elements in msg_iov */
766 msg.msg_control = ip_msg; /* ancillary data */
767 msg.msg_controllen = sizeof(buffer); /* ancillary data buffer len */
768 msg.msg_flags = 0; /* flags on received message */
770 ip_msg->cmsg_len = CMSG_LEN(sizeof(*pki));
771 ip_msg->cmsg_level = IPPROTO_IP;
772 ip_msg->cmsg_type = IP_PKTINFO;
773 pki->ipi_ifindex = 0; /* Interface index, 0 = use interface specified in routing table */
774 pki->ipi_spec_dst.s_addr = addr_ourip->sin_addr.s_addr; /* Local address */
775 /* pki->ipi_addr = ; Header Destination address - ignored by kernel */
780 char iabuf[INET_ADDRSTRLEN];
781 char iabuf2[INET_ADDRSTRLEN];
782 ast_verb(0, "\n**> From %s sending %d bytes to %s ***\n",
783 ast_inet_ntoa(addr_ourip->sin_addr), (int) size,
784 ast_inet_ntoa(addr_to->sin_addr));
785 for (tmp = 0; tmp < size; tmp++)
786 ast_verb(0, "%.2x ", (unsigned char) data[tmp]);
787 ast_verb(0, "\n******************************************\n");
792 if (sendmsg(unistimsock, &msg, 0) == -1)
793 display_last_error("Error sending datas");
795 if (sendto(unistimsock, data, size, 0, (struct sockaddr *) addr_to, sizeof(*addr_to))
797 display_last_error("Error sending datas");
801 static void send_client(int size, const unsigned char *data, struct unistimsession *pte)
805 unsigned short seq = ntohs(++pte->seq_server);
807 ast_mutex_lock(&pte->lock);
808 buf_pos = pte->last_buf_available;
810 if (buf_pos >= MAX_BUF_NUMBER) {
811 ast_log(LOG_WARNING, "Error : send queue overflow\n");
812 ast_mutex_unlock(&pte->lock);
815 memcpy((void *)data + sizeof(unsigned short), (void *)&seq, sizeof(unsigned short));
816 pte->wsabufsend[buf_pos].len = size;
817 memcpy(pte->wsabufsend[buf_pos].buf, data, size);
819 tick = get_tick_count();
820 pte->timeout = tick + RETRANSMIT_TIMER;
822 /*#ifdef DUMP_PACKET */
824 ast_verb(6, "Sending datas with seq #0x%.4x Using slot #%d :\n", pte->seq_server, buf_pos);
826 send_raw_client(pte->wsabufsend[buf_pos].len, pte->wsabufsend[buf_pos].buf, &(pte->sin),
828 pte->last_buf_available++;
829 ast_mutex_unlock(&pte->lock);
832 static void send_ping(struct unistimsession *pte)
836 ast_verb(6, "Sending ping\n");
837 pte->tick_next_ping = get_tick_count() + unistim_keepalive;
838 memcpy(buffsend + SIZE_HEADER, packet_send_ping, sizeof(packet_send_ping));
839 send_client(SIZE_HEADER + sizeof(packet_send_ping), buffsend, pte);
842 static int get_to_address(int fd, struct sockaddr_in *toAddr)
850 struct in_addr address;
853 /* Zero out the structures before we use them */
854 /* This sets several key values to NULL */
855 memset(&msg, 0, sizeof(msg));
856 memset(&ip_msg, 0, sizeof(ip_msg));
858 /* Initialize the message structure */
859 msg.msg_control = &ip_msg;
860 msg.msg_controllen = sizeof(ip_msg);
861 /* Get info about the incoming packet */
862 err = recvmsg(fd, &msg, MSG_PEEK);
864 ast_log(LOG_WARNING, "recvmsg returned an error: %s\n", strerror(errno));
865 memcpy(&toAddr->sin_addr, &ip_msg.address, sizeof(struct in_addr));
868 memcpy(&toAddr, &public_ip, sizeof(&toAddr));
873 /* Allocate memory & initialize structures for a new phone */
874 /* addr_from : ip address of the phone */
875 static struct unistimsession *create_client(const struct sockaddr_in *addr_from)
878 struct unistimsession *s;
880 if (!(s = ast_calloc(1, sizeof(*s))))
883 memcpy(&s->sin, addr_from, sizeof(struct sockaddr_in));
884 get_to_address(unistimsock, &s->sout);
886 ast_verb(0, "Creating a new entry for the phone from %s received via server ip %s\n",
887 ast_inet_ntoa(addr_from->sin_addr), ast_inet_ntoa(s->sout.sin_addr));
889 ast_mutex_init(&s->lock);
890 ast_mutex_lock(&sessionlock);
894 s->timeout = get_tick_count() + RETRANSMIT_TIMER;
895 s->seq_phone = (short) 0x0000;
896 s->seq_server = (short) 0x0000;
897 s->last_seq_ack = (short) 0x000;
898 s->last_buf_available = 0;
899 s->nb_retransmit = 0;
900 s->state = STATE_INIT;
901 s->tick_next_ping = get_tick_count() + unistim_keepalive;
902 /* Initialize struct wsabuf */
903 for (tmp = 0; tmp < MAX_BUF_NUMBER; tmp++) {
904 s->wsabufsend[tmp].buf = s->buf[tmp];
906 ast_mutex_unlock(&sessionlock);
910 static void send_end_call(struct unistimsession *pte)
914 ast_verb(0, "Sending end call\n");
915 memcpy(buffsend + SIZE_HEADER, packet_send_end_call, sizeof(packet_send_end_call));
916 send_client(SIZE_HEADER + sizeof(packet_send_end_call), buffsend, pte);
919 static void set_ping_timer(struct unistimsession *pte)
921 unsigned int tick = 0; /* XXX what is this for, anyways */
923 pte->timeout = pte->tick_next_ping;
924 DEBUG_TIMER("tick = %u next ping at %u tick\n", tick, pte->timeout);
928 /* Checking if our send queue is empty,
929 * if true, setting up a timer for keepalive */
930 static void check_send_queue(struct unistimsession *pte)
932 /* Check if our send queue contained only one element */
933 if (pte->last_buf_available == 1) {
935 ast_verb(6, "Our single packet was ACKed.\n");
936 pte->last_buf_available--;
940 /* Check if this ACK catch up our latest packet */
941 else if (pte->last_seq_ack + 1 == pte->seq_server + 1) {
943 ast_verb(6, "Our send queue is completely ACKed.\n");
944 pte->last_buf_available = 0; /* Purge the send queue */
949 ast_verb(6, "We still have packets in our send queue\n");
953 static void send_start_timer(struct unistimsession *pte)
957 ast_verb(0, "Sending start timer\n");
958 memcpy(buffsend + SIZE_HEADER, packet_send_StartTimer, sizeof(packet_send_StartTimer));
959 send_client(SIZE_HEADER + sizeof(packet_send_StartTimer), buffsend, pte);
962 static void send_stop_timer(struct unistimsession *pte)
966 ast_verb(0, "Sending stop timer\n");
967 memcpy(buffsend + SIZE_HEADER, packet_send_stop_timer, sizeof(packet_send_stop_timer));
968 send_client(SIZE_HEADER + sizeof(packet_send_stop_timer), buffsend, pte);
971 static void Sendicon(unsigned char pos, unsigned char status, struct unistimsession *pte)
975 ast_verb(0, "Sending icon pos %d with status 0x%.2x\n", pos, status);
976 memcpy(buffsend + SIZE_HEADER, packet_send_icon, sizeof(packet_send_icon));
978 buffsend[10] = status;
979 send_client(SIZE_HEADER + sizeof(packet_send_icon), buffsend, pte);
982 static void send_tone(struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
987 ast_verb(0, "Sending Stream Based Tone Off\n");
988 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_off,
989 sizeof(packet_send_stream_based_tone_off));
990 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_off), buffsend, pte);
993 /* Since most of the world use a continuous tone, it's useless
995 ast_verb(0, "Sending Stream Based Tone Cadence Download\n");
996 memcpy (buffsend + SIZE_HEADER, packet_send_StreamBasedToneCad, sizeof (packet_send_StreamBasedToneCad));
997 send_client (SIZE_HEADER + sizeof (packet_send_StreamBasedToneCad), buffsend, pte); */
999 ast_verb(0, "Sending Stream Based Tone Frequency Component List Download %d %d\n", tone1, tone2);
1002 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_single_freq,
1003 sizeof(packet_send_stream_based_tone_single_freq));
1004 buffsend[10] = (tone1 & 0xff00) >> 8;
1005 buffsend[11] = (tone1 & 0x00ff);
1006 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_single_freq), buffsend,
1010 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dial_freq,
1011 sizeof(packet_send_stream_based_tone_dial_freq));
1012 buffsend[10] = (tone1 & 0xff00) >> 8;
1013 buffsend[11] = (tone1 & 0x00ff);
1014 buffsend[12] = (tone2 & 0xff00) >> 8;
1015 buffsend[13] = (tone2 & 0x00ff);
1016 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_dial_freq), buffsend,
1021 ast_verb(0, "Sending Stream Based Tone On\n");
1022 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_on,
1023 sizeof(packet_send_stream_based_tone_on));
1024 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_on), buffsend, pte);
1027 /* Positions for favorites
1028 |--------------------|
1034 /* status (icons) : 00 = nothing, 2x/3x = see parser.h, 4x/5x = blink fast, 6x/7x = blink slow */
1036 send_favorite(unsigned char pos, unsigned char status, struct unistimsession *pte,
1043 ast_verb(0, "Sending favorite pos %d with status 0x%.2x\n", pos, status);
1044 memcpy(buffsend + SIZE_HEADER, packet_send_favorite, sizeof(packet_send_favorite));
1047 buffsend[25] = status;
1049 if (i > FAV_MAX_LENGTH)
1051 memcpy(buffsend + FAV_MAX_LENGTH + 1, text, i);
1052 send_client(SIZE_HEADER + sizeof(packet_send_favorite), buffsend, pte);
1055 static void refresh_all_favorite(struct unistimsession *pte)
1060 ast_verb(0, "Refreshing all favorite\n");
1061 for (i = 0; i < 6; i++) {
1062 if ((pte->device->softkeyicon[i] <= FAV_ICON_HEADPHONES_ONHOLD) &&
1063 (pte->device->softkeylinepos != i))
1064 send_favorite((unsigned char) i, pte->device->softkeyicon[i] + 1, pte,
1065 pte->device->softkeylabel[i]);
1067 send_favorite((unsigned char) i, pte->device->softkeyicon[i], pte,
1068 pte->device->softkeylabel[i]);
1073 /* Change the status for this phone (pte) and update for each phones where pte is bookmarked
1074 * use FAV_ICON_*_BLACK constant in status parameters */
1075 static void change_favorite_icon(struct unistimsession *pte, unsigned char status)
1077 struct unistim_device *d = devices;
1079 /* Update the current phone */
1080 if (pte->state != STATE_CLEANING)
1081 send_favorite(pte->device->softkeylinepos, status, pte,
1082 pte->device->softkeylabel[pte->device->softkeylinepos]);
1083 /* Notify other phones if we're in their bookmark */
1085 for (i = 0; i < 6; i++) {
1086 if (d->sp[i] == pte->device) { /* It's us ? */
1087 if (d->softkeyicon[i] != status) { /* Avoid resending the same icon */
1088 d->softkeyicon[i] = status;
1090 send_favorite(i, status + 1, d->session, d->softkeylabel[i]);
1098 static int RegisterExtension(const struct unistimsession *pte)
1101 ast_verb(0, "Trying to register extension '%s' into context '%s' to %s\n",
1102 pte->device->extension_number, pte->device->lines->context,
1103 pte->device->lines->fullname);
1104 return ast_add_extension(pte->device->lines->context, 0,
1105 pte->device->extension_number, 1, NULL, NULL, "Dial",
1106 pte->device->lines->fullname, 0, "Unistim");
1109 static int UnregisterExtension(const struct unistimsession *pte)
1112 ast_verb(0, "Trying to unregister extension '%s' context '%s'\n",
1113 pte->device->extension_number, pte->device->lines->context);
1114 return ast_context_remove_extension(pte->device->lines->context,
1115 pte->device->extension_number, 1, "Unistim");
1118 /* Free memory allocated for a phone */
1119 static void close_client(struct unistimsession *s)
1121 struct unistim_subchannel *sub;
1122 struct unistimsession *cur, *prev = NULL;
1123 ast_mutex_lock(&sessionlock);
1125 /* Looking for the session in the linked chain */
1132 if (cur) { /* Session found ? */
1133 if (cur->device) { /* This session was registered ? */
1134 s->state = STATE_CLEANING;
1136 ast_verb(0, "close_client session %p device %p lines %p sub %p\n",
1137 s, s->device, s->device->lines,
1138 s->device->lines->subs[SUB_REAL]);
1139 change_favorite_icon(s, FAV_ICON_NONE);
1140 sub = s->device->lines->subs[SUB_REAL];
1142 if (sub->owner) { /* Call in progress ? */
1144 ast_verb(0, "Aborting call\n");
1145 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NETWORK_OUT_OF_ORDER);
1148 ast_log(LOG_WARNING, "Freeing a client with no subchannel !\n");
1149 if (!ast_strlen_zero(s->device->extension_number))
1150 UnregisterExtension(s);
1151 cur->device->session = NULL;
1154 ast_verb(0, "Freeing an unregistered client\n");
1157 prev->next = cur->next;
1159 sessions = cur->next;
1160 ast_mutex_destroy(&s->lock);
1163 ast_log(LOG_WARNING, "Trying to delete non-existent session %p?\n", s);
1164 ast_mutex_unlock(&sessionlock);
1168 /* Return 1 if the session chained link was modified */
1169 static int send_retransmit(struct unistimsession *pte)
1173 ast_mutex_lock(&pte->lock);
1174 if (++pte->nb_retransmit >= NB_MAX_RETRANSMIT) {
1176 ast_verb(0, "Too many retransmit - freeing client\n");
1177 ast_mutex_unlock(&pte->lock);
1181 pte->timeout = get_tick_count() + RETRANSMIT_TIMER;
1183 for (i = pte->last_buf_available - (pte->seq_server - pte->last_seq_ack);
1184 i < pte->last_buf_available; i++) {
1186 ast_log(LOG_WARNING,
1187 "Asked to retransmit an ACKed slot ! last_buf_available=%d, seq_server = #0x%.4x last_seq_ack = #0x%.4x\n",
1188 pte->last_buf_available, pte->seq_server, pte->last_seq_ack);
1193 unsigned short *sbuf = (unsigned short *) pte->wsabufsend[i].buf;
1196 seq = ntohs(sbuf[1]);
1197 ast_verb(0, "Retransmit slot #%d (seq=#0x%.4x), last ack was #0x%.4x\n", i,
1198 seq, pte->last_seq_ack);
1200 send_raw_client(pte->wsabufsend[i].len, pte->wsabufsend[i].buf, &pte->sin,
1203 ast_mutex_unlock(&pte->lock);
1207 /* inverse : TEXT_INVERSE : yes, TEXT_NORMAL : no */
1209 send_text(unsigned char pos, unsigned char inverse, struct unistimsession *pte,
1215 ast_verb(0, "Sending text at pos %d, inverse flag %d\n", pos, inverse);
1216 memcpy(buffsend + SIZE_HEADER, packet_send_text, sizeof(packet_send_text));
1218 buffsend[11] = inverse;
1220 if (i > TEXT_LENGTH_MAX)
1221 i = TEXT_LENGTH_MAX;
1222 memcpy(buffsend + 12, text, i);
1223 send_client(SIZE_HEADER + sizeof(packet_send_text), buffsend, pte);
1226 static void send_text_status(struct unistimsession *pte, const char *text)
1231 ast_verb(0, "Sending status text\n");
1233 if (pte->device->status_method == 1) { /* For new firmware and i2050 soft phone */
1234 int n = strlen(text);
1235 /* Must send individual button separately */
1237 for (i = 0, j = 0; i < 4; i++, j += 7) {
1238 int pos = 0x08 + (i * 0x20);
1239 memcpy(buffsend + SIZE_HEADER, packet_send_status2,
1240 sizeof(packet_send_status2));
1243 memcpy(buffsend + 10, (j < n) ? (text + j) : " ", 7);
1244 send_client(SIZE_HEADER + sizeof(packet_send_status2), buffsend, pte);
1251 memcpy(buffsend + SIZE_HEADER, packet_send_status, sizeof(packet_send_status));
1253 if (i > STATUS_LENGTH_MAX)
1254 i = STATUS_LENGTH_MAX;
1255 memcpy(buffsend + 10, text, i);
1256 send_client(SIZE_HEADER + sizeof(packet_send_status), buffsend, pte);
1260 /* led values in hexa : 0 = bar off, 1 = bar on, 2 = bar 1s on/1s off, 3 = bar 2.5s on/0.5s off
1261 * 4 = bar 0.6s on/0.3s off, 5 = bar 0.5s on/0.5s off, 6 = bar 2s on/0.5s off
1262 * 7 = bar off, 8 = speaker off, 9 = speaker on, 10 = headphone off, 11 = headphone on
1263 * 18 = mute off, 19 mute on */
1264 static void send_led_update(struct unistimsession *pte, unsigned char led)
1268 ast_verb(0, "Sending led_update (%x)\n", led);
1269 memcpy(buffsend + SIZE_HEADER, packet_send_led_update, sizeof(packet_send_led_update));
1271 send_client(SIZE_HEADER + sizeof(packet_send_led_update), buffsend, pte);
1274 /* output = OUTPUT_HANDSET, OUTPUT_HEADPHONE or OUTPUT_SPEAKER
1275 * volume = VOLUME_LOW, VOLUME_NORMAL, VOLUME_INSANELY_LOUD
1276 * mute = MUTE_OFF, MUTE_ON */
1278 send_select_output(struct unistimsession *pte, unsigned char output, unsigned char volume,
1283 ast_verb(0, "Sending select output packet output=%x volume=%x mute=%x\n", output,
1285 memcpy(buffsend + SIZE_HEADER, packet_send_select_output,
1286 sizeof(packet_send_select_output));
1287 buffsend[9] = output;
1288 if (output == OUTPUT_SPEAKER)
1289 volume = VOLUME_LOW_SPEAKER;
1291 volume = VOLUME_LOW;
1292 buffsend[10] = volume;
1293 if (mute == MUTE_ON_DISCRET)
1294 buffsend[11] = MUTE_ON;
1296 buffsend[11] = mute;
1297 send_client(SIZE_HEADER + sizeof(packet_send_select_output), buffsend, pte);
1298 if (mute == MUTE_OFF)
1299 send_led_update(pte, 0x18);
1300 else if (mute == MUTE_ON)
1301 send_led_update(pte, 0x19);
1302 pte->device->mute = mute;
1303 if (output == OUTPUT_HANDSET) {
1304 if (mute == MUTE_ON)
1305 change_favorite_icon(pte, FAV_ICON_ONHOLD_BLACK);
1307 change_favorite_icon(pte, FAV_ICON_OFFHOOK_BLACK);
1308 send_led_update(pte, 0x08);
1309 send_led_update(pte, 0x10);
1310 } else if (output == OUTPUT_HEADPHONE) {
1311 if (mute == MUTE_ON)
1312 change_favorite_icon(pte, FAV_ICON_HEADPHONES_ONHOLD);
1314 change_favorite_icon(pte, FAV_ICON_HEADPHONES);
1315 send_led_update(pte, 0x08);
1316 send_led_update(pte, 0x11);
1317 } else if (output == OUTPUT_SPEAKER) {
1318 send_led_update(pte, 0x10);
1319 send_led_update(pte, 0x09);
1320 if (pte->device->receiver_state == STATE_OFFHOOK) {
1321 if (mute == MUTE_ON)
1322 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1324 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOOK_BLACK);
1326 if (mute == MUTE_ON)
1327 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1329 change_favorite_icon(pte, FAV_ICON_SPEAKER_OFFHOOK_BLACK);
1332 ast_log(LOG_WARNING, "Invalid output (%d)\n", output);
1333 if (output != pte->device->output)
1334 pte->device->previous_output = pte->device->output;
1335 pte->device->output = output;
1338 static void send_ring(struct unistimsession *pte, char volume, char style)
1342 ast_verb(0, "Sending ring packet\n");
1343 memcpy(buffsend + SIZE_HEADER, packet_send_ring, sizeof(packet_send_ring));
1344 buffsend[24] = style + 0x10;
1345 buffsend[29] = volume * 0x10;
1346 send_client(SIZE_HEADER + sizeof(packet_send_ring), buffsend, pte);
1349 static void send_no_ring(struct unistimsession *pte)
1353 ast_verb(0, "Sending no ring packet\n");
1354 memcpy(buffsend + SIZE_HEADER, packet_send_no_ring, sizeof(packet_send_no_ring));
1355 send_client(SIZE_HEADER + sizeof(packet_send_no_ring), buffsend, pte);
1358 static void send_texttitle(struct unistimsession *pte, const char *text)
1363 ast_verb(0, "Sending title text\n");
1364 memcpy(buffsend + SIZE_HEADER, packet_send_title, sizeof(packet_send_title));
1368 memcpy(buffsend + 10, text, i);
1369 send_client(SIZE_HEADER + sizeof(packet_send_title), buffsend, pte);
1373 static void send_date_time(struct unistimsession *pte)
1376 struct timeval now = ast_tvnow();
1377 struct ast_tm atm = { 0, };
1380 ast_verb(0, "Sending Time & Date\n");
1381 memcpy(buffsend + SIZE_HEADER, packet_send_date_time, sizeof(packet_send_date_time));
1382 ast_localtime(&now, &atm, NULL);
1383 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1384 buffsend[11] = (unsigned char) atm.tm_mday;
1385 buffsend[12] = (unsigned char) atm.tm_hour;
1386 buffsend[13] = (unsigned char) atm.tm_min;
1387 send_client(SIZE_HEADER + sizeof(packet_send_date_time), buffsend, pte);
1390 static void send_date_time2(struct unistimsession *pte)
1393 struct timeval now = ast_tvnow();
1394 struct ast_tm atm = { 0, };
1397 ast_verb(0, "Sending Time & Date #2\n");
1398 memcpy(buffsend + SIZE_HEADER, packet_send_date_time2, sizeof(packet_send_date_time2));
1399 ast_localtime(&now, &atm, NULL);
1401 buffsend[9] = pte->device->datetimeformat;
1404 buffsend[14] = (unsigned char) atm.tm_mon + 1;
1405 buffsend[15] = (unsigned char) atm.tm_mday;
1406 buffsend[16] = (unsigned char) atm.tm_hour;
1407 buffsend[17] = (unsigned char) atm.tm_min;
1408 send_client(SIZE_HEADER + sizeof(packet_send_date_time2), buffsend, pte);
1411 static void send_date_time3(struct unistimsession *pte)
1414 struct timeval now = ast_tvnow();
1415 struct ast_tm atm = { 0, };
1418 ast_verb(0, "Sending Time & Date #3\n");
1419 memcpy(buffsend + SIZE_HEADER, packet_send_date_time3, sizeof(packet_send_date_time3));
1420 ast_localtime(&now, &atm, NULL);
1421 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1422 buffsend[11] = (unsigned char) atm.tm_mday;
1423 buffsend[12] = (unsigned char) atm.tm_hour;
1424 buffsend[13] = (unsigned char) atm.tm_min;
1425 send_client(SIZE_HEADER + sizeof(packet_send_date_time3), buffsend, pte);
1428 static void send_blink_cursor(struct unistimsession *pte)
1432 ast_verb(0, "Sending set blink\n");
1433 memcpy(buffsend + SIZE_HEADER, packet_send_blink_cursor, sizeof(packet_send_blink_cursor));
1434 send_client(SIZE_HEADER + sizeof(packet_send_blink_cursor), buffsend, pte);
1438 /* pos : 0xab (a=0/2/4 = line ; b = row) */
1439 static void send_cursor_pos(struct unistimsession *pte, unsigned char pos)
1443 ast_verb(0, "Sending set cursor position\n");
1444 memcpy(buffsend + SIZE_HEADER, packet_send_set_pos_cursor,
1445 sizeof(packet_send_set_pos_cursor));
1447 send_client(SIZE_HEADER + sizeof(packet_send_set_pos_cursor), buffsend, pte);
1451 static void rcv_resume_connection_with_server(struct unistimsession *pte)
1455 ast_verb(0, "ResumeConnectionWithServer received\n");
1456 ast_verb(0, "Sending packet_send_query_mac_address\n");
1458 memcpy(buffsend + SIZE_HEADER, packet_send_query_mac_address,
1459 sizeof(packet_send_query_mac_address));
1460 send_client(SIZE_HEADER + sizeof(packet_send_query_mac_address), buffsend, pte);
1464 static int unistim_register(struct unistimsession *s)
1466 struct unistim_device *d;
1468 ast_mutex_lock(&devicelock);
1471 if (!strcasecmp(s->macaddr, d->id)) {
1472 /* XXX Deal with IP authentication */
1475 d->codec_number = DEFAULT_CODEC;
1478 d->receiver_state = STATE_ONHOOK;
1483 ast_mutex_unlock(&devicelock);
1491 static void unistim_line_copy(struct unistim_line *dst, struct unistim_line *src)
1493 struct ast_format_cap *tmp = src->cap;
1494 memcpy(dst, src, sizeof(*dst)); /* this over writes the cap ptr, so we have to reset it */
1496 ast_format_cap_copy(src->cap, dst->cap);
1499 static struct unistim_line *unistim_line_destroy(struct unistim_line *l)
1504 l->cap = ast_format_cap_destroy(l->cap);
1509 static struct unistim_line *unistim_line_alloc(void)
1511 struct unistim_line *l;
1512 if (!(l = ast_calloc(1, sizeof(*l)))) {
1516 if (!(l->cap = ast_format_cap_alloc_nolock())) {
1523 static int alloc_sub(struct unistim_line *l, int x)
1525 struct unistim_subchannel *sub;
1526 if (!(sub = ast_calloc(1, sizeof(*sub))))
1530 ast_verb(3, "Allocating UNISTIM subchannel #%d on %s@%s ptr=%p\n", x, l->name, l->parent->name, sub);
1534 ast_mutex_init(&sub->lock);
1538 static int unalloc_sub(struct unistim_line *p, int x)
1541 ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name,
1546 ast_debug(1, "Released sub %d of channel %s@%s\n", x, p->name,
1548 ast_mutex_destroy(&p->lock);
1549 ast_free(p->subs[x]);
1554 static void rcv_mac_addr(struct unistimsession *pte, const unsigned char *buf)
1561 ast_verb(0, "Mac Address received : ");
1562 for (tmp = 15; tmp < 15 + SIZE_HEADER; tmp++) {
1563 sprintf(&addrmac[i], "%.2x", (unsigned char) buf[tmp]);
1567 ast_verb(0, "%s\n", addrmac);
1568 strcpy(pte->macaddr, addrmac);
1569 res = unistim_register(pte);
1571 switch (autoprovisioning) {
1572 case AUTOPROVISIONING_NO:
1573 ast_log(LOG_WARNING, "No entry found for this phone : %s\n", addrmac);
1574 pte->state = STATE_AUTHDENY;
1576 case AUTOPROVISIONING_YES:
1578 struct unistim_device *d, *newd;
1579 struct unistim_line *newl;
1581 ast_verb(0, "New phone, autoprovisioning on\n");
1582 /* First : locate the [template] section */
1583 ast_mutex_lock(&devicelock);
1586 if (!strcasecmp(d->name, "template")) {
1587 /* Found, cloning this entry */
1588 if (!(newd = ast_malloc(sizeof(*newd)))) {
1589 ast_mutex_unlock(&devicelock);
1593 memcpy(newd, d, sizeof(*newd));
1594 if (!(newl = unistim_line_alloc())) {
1596 ast_mutex_unlock(&devicelock);
1600 unistim_line_copy(d->lines, newl);
1601 if (!alloc_sub(newl, SUB_REAL)) {
1603 unistim_line_destroy(newl);
1604 ast_mutex_unlock(&devicelock);
1607 /* Ok, now updating some fields */
1608 ast_copy_string(newd->id, addrmac, sizeof(newd->id));
1609 ast_copy_string(newd->name, addrmac, sizeof(newd->name));
1610 if (newd->extension == EXTENSION_NONE)
1611 newd->extension = EXTENSION_ASK;
1613 newd->receiver_state = STATE_ONHOOK;
1614 newd->session = pte;
1615 newd->to_delete = -1;
1618 newl->parent = newd;
1619 strcpy(newl->name, d->lines->name);
1620 snprintf(d->lines->name, sizeof(d->lines->name), "%d",
1621 atoi(d->lines->name) + 1);
1622 snprintf(newl->fullname, sizeof(newl->fullname), "USTM/%s@%s",
1623 newl->name, newd->name);
1624 /* Go to the end of the linked chain */
1634 ast_mutex_unlock(&devicelock);
1636 ast_log(LOG_WARNING, "No entry [template] found in unistim.conf\n");
1637 pte->state = STATE_AUTHDENY;
1641 case AUTOPROVISIONING_TN:
1642 pte->state = STATE_AUTHDENY;
1644 case AUTOPROVISIONING_DB:
1645 ast_log(LOG_WARNING,
1646 "Autoprovisioning with database is not yet functional\n");
1649 ast_log(LOG_WARNING, "Internal error : unknown autoprovisioning value = %d\n",
1653 if (pte->state != STATE_AUTHDENY) {
1654 ast_verb(3, "Device '%s' successfuly registered\n", pte->device->name);
1655 switch (pte->device->extension) {
1656 case EXTENSION_NONE:
1657 pte->state = STATE_MAINPAGE;
1660 /* Checking if we already have an extension number */
1661 if (ast_strlen_zero(pte->device->extension_number))
1662 pte->state = STATE_EXTENSION;
1664 /* Yes, because of a phone reboot. We don't ask again for the TN */
1665 if (RegisterExtension(pte))
1666 pte->state = STATE_EXTENSION;
1668 pte->state = STATE_MAINPAGE;
1671 case EXTENSION_LINE:
1672 ast_copy_string(pte->device->extension_number, pte->device->lines->name,
1673 sizeof(pte->device->extension_number));
1674 if (RegisterExtension(pte))
1675 pte->state = STATE_EXTENSION;
1677 pte->state = STATE_MAINPAGE;
1680 /* If we are here, it's because of a phone reboot */
1681 pte->state = STATE_MAINPAGE;
1684 ast_log(LOG_WARNING, "Internal error, extension value unknown : %d\n",
1685 pte->device->extension);
1686 pte->state = STATE_AUTHDENY;
1690 if (pte->state == STATE_EXTENSION) {
1691 if (pte->device->extension != EXTENSION_TN)
1692 pte->device->extension = EXTENSION_ASK;
1693 pte->device->extension_number[0] = '\0';
1696 ast_verb(0, "\nSending S1\n");
1697 memcpy(buffsend + SIZE_HEADER, packet_send_S1, sizeof(packet_send_S1));
1698 send_client(SIZE_HEADER + sizeof(packet_send_S1), buffsend, pte);
1701 ast_verb(0, "Sending query_basic_manager_04\n");
1702 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_04,
1703 sizeof(packet_send_query_basic_manager_04));
1704 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_04), buffsend, pte);
1707 ast_verb(0, "Sending query_basic_manager_10\n");
1708 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_10,
1709 sizeof(packet_send_query_basic_manager_10));
1710 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_10), buffsend, pte);
1712 send_date_time(pte);
1716 static int write_entry_history(struct unistimsession *pte, FILE * f, char c, char *line1)
1718 if (fwrite(&c, 1, 1, f) != 1) {
1719 display_last_error("Unable to write history log header.");
1722 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
1723 display_last_error("Unable to write history entry - date.");
1726 if (fwrite(pte->device->lst_cid, TEXT_LENGTH_MAX, 1, f) != 1) {
1727 display_last_error("Unable to write history entry - callerid.");
1730 if (fwrite(pte->device->lst_cnm, TEXT_LENGTH_MAX, 1, f) != 1) {
1731 display_last_error("Unable to write history entry - callername.");
1737 static int write_history(struct unistimsession *pte, char way, char ismissed)
1739 char tmp[AST_CONFIG_MAX_PATH], tmp2[AST_CONFIG_MAX_PATH];
1740 char line1[TEXT_LENGTH_MAX + 1];
1741 char count = 0, *histbuf;
1744 struct timeval now = ast_tvnow();
1745 struct ast_tm atm = { 0, };
1749 if (!pte->device->callhistory)
1751 if (strchr(pte->device->name, '/') || (pte->device->name[0] == '.')) {
1752 ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n",
1757 snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_LOG_DIR, USTM_LOG_DIR);
1758 if (ast_mkdir(tmp, 0770)) {
1759 if (errno != EEXIST) {
1760 display_last_error("Unable to create directory for history");
1765 ast_localtime(&now, &atm, NULL);
1768 strcpy(tmp2, "Miss");
1770 strcpy(tmp2, "Fail");
1772 strcpy(tmp2, "Answ");
1773 snprintf(line1, sizeof(line1), "%04d/%02d/%02d %02d:%02d:%02d %s",
1774 atm.tm_year + 1900, atm.tm_mon + 1, atm.tm_mday, atm.tm_hour,
1775 atm.tm_min, atm.tm_sec, tmp2);
1777 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
1778 USTM_LOG_DIR, pte->device->name, way);
1779 if ((f = fopen(tmp, "r"))) {
1780 struct stat bufstat;
1782 if (stat(tmp, &bufstat)) {
1783 display_last_error("Unable to stat history log.");
1787 size = 1 + (MAX_ENTRY_LOG * TEXT_LENGTH_MAX * 3);
1788 if (bufstat.st_size != size) {
1789 ast_log(LOG_WARNING,
1790 "History file %s has an incorrect size (%d instead of %d). It will be replaced by a new one.",
1791 tmp, (int) bufstat.st_size, size);
1798 /* If we can't open the log file, we create a brand new one */
1803 if ((errno != ENOENT) && (count == 0)) {
1804 display_last_error("Unable to open history log.");
1807 f = fopen(tmp, "w");
1809 display_last_error("Unable to create history log.");
1812 if (write_entry_history(pte, f, c, line1)) {
1816 memset(line1, ' ', TEXT_LENGTH_MAX);
1817 for (i = 3; i < MAX_ENTRY_LOG * 3; i++) {
1818 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
1819 display_last_error("Unable to write history entry - stuffing.");
1825 display_last_error("Unable to close history - creation.");
1828 /* We can open the log file, we create a temporary one, we add our entry and copy the rest */
1829 if (fread(&count, 1, 1, f) != 1) {
1830 display_last_error("Unable to read history header.");
1834 if (count > MAX_ENTRY_LOG) {
1835 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
1836 count, MAX_ENTRY_LOG);
1840 snprintf(tmp2, sizeof(tmp2), "%s/%s/%s-%c.csv.tmp", ast_config_AST_LOG_DIR,
1841 USTM_LOG_DIR, pte->device->name, way);
1842 if (!(f2 = fopen(tmp2, "w"))) {
1843 display_last_error("Unable to create temporary history log.");
1848 if (++count > MAX_ENTRY_LOG)
1849 count = MAX_ENTRY_LOG;
1851 if (write_entry_history(pte, f2, count, line1)) {
1857 size = (MAX_ENTRY_LOG - 1) * TEXT_LENGTH_MAX * 3;
1858 if (!(histbuf = ast_malloc(size))) {
1864 if (fread(histbuf, size, 1, f) != 1) {
1868 display_last_error("Unable to read previous history entries.");
1871 if (fwrite(histbuf, size, 1, f2) != 1) {
1875 display_last_error("Unable to write previous history entries.");
1880 display_last_error("Unable to close history log.");
1882 display_last_error("Unable to close temporary history log.");
1884 display_last_error("Unable to remove old history log.");
1885 if (rename(tmp2, tmp))
1886 display_last_error("Unable to rename new history log.");
1890 static void cancel_dial(struct unistimsession *pte)
1893 pte->device->missed_call++;
1894 write_history(pte, 'i', 1);
1895 show_main_page(pte);
1899 static void swap_subs(struct unistim_line *p, int a, int b)
1901 /* struct ast_channel *towner; */
1902 struct ast_rtp_instance *rtp;
1906 ast_verb(0, "Swapping %d and %d\n", a, b);
1908 if ((!p->subs[a]->owner) || (!p->subs[b]->owner)) {
1909 ast_log(LOG_WARNING,
1910 "Attempted to swap subchannels with a null owner : sub #%d=%p sub #%d=%p\n",
1911 a, p->subs[a]->owner, b, p->subs[b]->owner);
1914 rtp = p->subs[a]->rtp;
1915 p->subs[a]->rtp = p->subs[b]->rtp;
1916 p->subs[b]->rtp = rtp;
1918 fds = p->subs[a]->owner->fds[0];
1919 p->subs[a]->owner->fds[0] = p->subs[b]->owner->fds[0];
1920 p->subs[b]->owner->fds[0] = fds;
1922 fds = p->subs[a]->owner->fds[1];
1923 p->subs[a]->owner->fds[1] = p->subs[b]->owner->fds[1];
1924 p->subs[b]->owner->fds[1] = fds;
1927 static int attempt_transfer(struct unistim_subchannel *p1, struct unistim_subchannel *p2)
1931 *chana = NULL, *chanb = NULL, *bridgea = NULL, *bridgeb = NULL, *peera =
1932 NULL, *peerb = NULL, *peerc = NULL;
1934 if (!p1->owner || !p2->owner) {
1935 ast_log(LOG_WARNING, "Transfer attempted without dual ownership?\n");
1940 bridgea = ast_bridged_channel(chana);
1941 bridgeb = ast_bridged_channel(chanb);
1947 } else if (bridgeb) {
1953 if (peera && peerb && peerc && (peerb != peerc)) {
1954 /*ast_quiet_chan(peera);
1955 ast_quiet_chan(peerb);
1956 ast_quiet_chan(peerc);
1957 ast_quiet_chan(peerd); */
1959 if (peera->cdr && peerb->cdr) {
1960 peerb->cdr = ast_cdr_append(peerb->cdr, peera->cdr);
1961 } else if (peera->cdr) {
1962 peerb->cdr = peera->cdr;
1966 if (peerb->cdr && peerc->cdr) {
1967 peerb->cdr = ast_cdr_append(peerb->cdr, peerc->cdr);
1968 } else if (peerc->cdr) {
1969 peerb->cdr = peerc->cdr;
1973 if (ast_channel_masquerade(peerb, peerc)) {
1974 ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name,
1981 "Transfer attempted with no appropriate bridged calls to transfer\n");
1983 ast_softhangup_nolock(chana, AST_SOFTHANGUP_DEV);
1985 ast_softhangup_nolock(chanb, AST_SOFTHANGUP_DEV);
1991 void change_callerid(struct unistimsession *pte, int type, char *callerid)
1997 data = pte->device->lst_cnm;
1999 data = pte->device->lst_cid;
2001 /* This is very nearly strncpy(), except that the remaining buffer
2002 * is padded with ' ', instead of '\0' */
2003 memset(data, ' ', TEXT_LENGTH_MAX);
2004 size = strlen(callerid);
2005 if (size > TEXT_LENGTH_MAX)
2006 size = TEXT_LENGTH_MAX;
2007 memcpy(data, callerid, size);
2010 static void close_call(struct unistimsession *pte)
2012 struct unistim_subchannel *sub;
2013 struct unistim_line *l = pte->device->lines;
2015 sub = pte->device->lines->subs[SUB_REAL];
2016 send_stop_timer(pte);
2018 sub->alreadygone = 1;
2019 if (l->subs[SUB_THREEWAY]) {
2020 l->subs[SUB_THREEWAY]->alreadygone = 1;
2021 if (attempt_transfer(sub, l->subs[SUB_THREEWAY]) < 0)
2022 ast_verb(0, "attempt_transfer failed.\n");
2024 ast_queue_hangup(sub->owner);
2026 if (l->subs[SUB_THREEWAY]) {
2027 if (l->subs[SUB_THREEWAY]->owner)
2028 ast_queue_hangup_with_cause(l->subs[SUB_THREEWAY]->owner, AST_CAUSE_NORMAL_CLEARING);
2030 ast_log(LOG_WARNING, "threeway sub without owner\n");
2032 ast_verb(0, "USTM(%s@%s-%d) channel already destroyed\n", sub->parent->name,
2033 sub->parent->parent->name, sub->subtype);
2035 change_callerid(pte, 0, pte->device->redial_number);
2036 change_callerid(pte, 1, "");
2037 write_history(pte, 'o', pte->device->missed_call);
2038 pte->device->missed_call = 0;
2039 show_main_page(pte);
2043 static void IgnoreCall(struct unistimsession *pte)
2049 static void *unistim_ss(void *data)
2051 struct ast_channel *chan = data;
2052 struct unistim_subchannel *sub = chan->tech_pvt;
2053 struct unistim_line *l = sub->parent;
2054 struct unistimsession *s = l->parent->session;
2057 ast_verb(3, "Starting switch on '%s@%s-%d' to %s\n", l->name, l->parent->name, sub->subtype, s->device->phone_number);
2058 ast_copy_string(chan->exten, s->device->phone_number, sizeof(chan->exten));
2059 ast_copy_string(s->device->redial_number, s->device->phone_number,
2060 sizeof(s->device->redial_number));
2061 ast_setstate(chan, AST_STATE_RING);
2062 res = ast_pbx_run(chan);
2064 ast_log(LOG_WARNING, "PBX exited non-zero\n");
2065 send_tone(s, 1000, 0);;
2070 static void start_rtp(struct unistim_subchannel *sub)
2073 struct sockaddr_in us = { 0, };
2074 struct sockaddr_in public = { 0, };
2075 struct sockaddr_in sin = { 0, };
2077 struct sockaddr_in sout = { 0, };
2078 struct ast_sockaddr us_tmp;
2079 struct ast_sockaddr sin_tmp;
2080 struct ast_sockaddr sout_tmp;
2084 ast_log(LOG_WARNING, "start_rtp with a null subchannel !\n");
2088 ast_log(LOG_WARNING, "start_rtp with a null line !\n");
2091 if (!sub->parent->parent) {
2092 ast_log(LOG_WARNING, "start_rtp with a null device !\n");
2095 if (!sub->parent->parent->session) {
2096 ast_log(LOG_WARNING, "start_rtp with a null session !\n");
2099 sout = sub->parent->parent->session->sout;
2101 ast_mutex_lock(&sub->lock);
2102 /* Allocate the RTP */
2104 ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
2105 ast_sockaddr_from_sin(&sout_tmp, &sout);
2106 sub->rtp = ast_rtp_instance_new("asterisk", sched, &sout_tmp, NULL);
2108 ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
2109 strerror(errno), ast_inet_ntoa(sout.sin_addr));
2110 ast_mutex_unlock(&sub->lock);
2113 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
2115 sub->owner->fds[0] = ast_rtp_instance_fd(sub->rtp, 0);
2116 sub->owner->fds[1] = ast_rtp_instance_fd(sub->rtp, 1);
2118 ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
2119 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->parent->parent->nat);
2121 /* Create the RTP connection */
2122 ast_rtp_instance_get_local_address(sub->rtp, &us_tmp);
2123 ast_sockaddr_to_sin(&us_tmp, &us);
2124 sin.sin_family = AF_INET;
2125 /* Setting up RTP for our side */
2126 memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
2127 sizeof(sin.sin_addr));
2128 sin.sin_port = htons(sub->parent->parent->rtp_port);
2129 ast_sockaddr_from_sin(&sin_tmp, &sin);
2130 ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
2131 if (!(ast_format_cap_iscompatible(sub->owner->nativeformats, &sub->owner->readformat))) {
2132 struct ast_format tmpfmt;
2134 ast_best_codec(sub->owner->nativeformats, &tmpfmt);
2135 ast_log(LOG_WARNING,
2136 "Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n",
2137 ast_getformatname(&sub->owner->readformat),
2138 ast_getformatname(&tmpfmt),
2139 ast_getformatname_multiple(tmp, sizeof(tmp), sub->owner->nativeformats));
2140 ast_format_copy(&sub->owner->readformat, &tmpfmt);
2141 ast_format_copy(&sub->owner->writeformat, &tmpfmt);
2143 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, &sub->owner->readformat, 0);
2144 /* Setting up RTP of the phone */
2145 if (public_ip.sin_family == 0) /* NAT IP override ? */
2146 memcpy(&public, &us, sizeof(public)); /* No defined, using IP from recvmsg */
2148 memcpy(&public, &public_ip, sizeof(public)); /* override */
2150 ast_verb(0, "RTP started : Our IP/port is : %s:%hd with codec %s\n",
2151 ast_inet_ntoa(us.sin_addr),
2152 htons(us.sin_port), ast_getformatname(&sub->owner->readformat));
2153 ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n",
2154 ast_inet_ntoa(public.sin_addr));
2156 if ((sub->owner->readformat.id == AST_FORMAT_ULAW) ||
2157 (sub->owner->readformat.id == AST_FORMAT_ALAW)) {
2159 ast_verb(0, "Sending packet_send_rtp_packet_size for codec %d\n", codec);
2160 memcpy(buffsend + SIZE_HEADER, packet_send_rtp_packet_size,
2161 sizeof(packet_send_rtp_packet_size));
2162 buffsend[10] = (int) codec & 0xffffffffLL;
2163 send_client(SIZE_HEADER + sizeof(packet_send_rtp_packet_size), buffsend,
2164 sub->parent->parent->session);
2167 ast_verb(0, "Sending Jitter Buffer Parameters Configuration\n");
2168 memcpy(buffsend + SIZE_HEADER, packet_send_jitter_buffer_conf,
2169 sizeof(packet_send_jitter_buffer_conf));
2170 send_client(SIZE_HEADER + sizeof(packet_send_jitter_buffer_conf), buffsend,
2171 sub->parent->parent->session);
2172 if (sub->parent->parent->rtp_method != 0) {
2173 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2176 ast_verb(0, "Sending OpenAudioStreamTX using method #%d\n",
2177 sub->parent->parent->rtp_method);
2178 if (sub->parent->parent->rtp_method == 3)
2179 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx3,
2180 sizeof(packet_send_open_audio_stream_tx3));
2182 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx,
2183 sizeof(packet_send_open_audio_stream_tx));
2184 if (sub->parent->parent->rtp_method != 2) {
2185 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2186 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2187 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2188 buffsend[23] = (rtcpsin_port & 0x00ff);
2189 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2190 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2191 buffsend[24] = (us.sin_port & 0x00ff);
2192 buffsend[27] = (rtcpsin_port & 0x00ff);
2193 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2195 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2196 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2197 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2198 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2199 buffsend[19] = (us.sin_port & 0x00ff);
2200 buffsend[11] = codec;
2202 buffsend[12] = codec;
2203 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_tx), buffsend,
2204 sub->parent->parent->session);
2207 ast_verb(0, "Sending OpenAudioStreamRX\n");
2208 if (sub->parent->parent->rtp_method == 3)
2209 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx3,
2210 sizeof(packet_send_open_audio_stream_rx3));
2212 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx,
2213 sizeof(packet_send_open_audio_stream_rx));
2214 if (sub->parent->parent->rtp_method != 2) {
2215 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2216 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2217 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2218 buffsend[23] = (rtcpsin_port & 0x00ff);
2219 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2220 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2221 buffsend[24] = (us.sin_port & 0x00ff);
2222 buffsend[27] = (rtcpsin_port & 0x00ff);
2223 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2225 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2226 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2227 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2228 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2229 buffsend[19] = (us.sin_port & 0x00ff);
2230 buffsend[12] = codec;
2232 buffsend[11] = codec;
2233 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_rx), buffsend,
2234 sub->parent->parent->session);
2236 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2239 ast_verb(0, "Sending packet_send_call default method\n");
2241 memcpy(buffsend + SIZE_HEADER, packet_send_call, sizeof(packet_send_call));
2242 memcpy(buffsend + 53, &public.sin_addr, sizeof(public.sin_addr));
2243 /* Destination port when sending RTP */
2244 buffsend[49] = (us.sin_port & 0x00ff);
2245 buffsend[50] = (us.sin_port & 0xff00) >> 8;
2246 /* Destination port when sending RTCP */
2247 buffsend[52] = (rtcpsin_port & 0x00ff);
2248 buffsend[51] = (rtcpsin_port & 0xff00) >> 8;
2250 buffsend[40] = codec;
2251 buffsend[41] = codec;
2252 if (sub->owner->readformat.id == AST_FORMAT_ULAW)
2253 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2254 else if (sub->owner->readformat.id == AST_FORMAT_ALAW)
2255 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2256 else if (sub->owner->readformat.id == AST_FORMAT_G723_1)
2257 buffsend[42] = 2; /* 1 = 30ms (24 bytes), 2 = 60 ms (48 bytes) */
2258 else if (sub->owner->readformat.id == AST_FORMAT_G729A)
2259 buffsend[42] = 2; /* 1 = 10ms (10 bytes), 2 = 20ms (20 bytes) */
2261 ast_log(LOG_WARNING, "Unsupported codec %s!\n",
2262 ast_getformatname(&sub->owner->readformat));
2263 /* Source port for transmit RTP and Destination port for receiving RTP */
2264 buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8;
2265 buffsend[46] = (htons(sin.sin_port) & 0x00ff);
2266 buffsend[47] = (rtcpsin_port & 0xff00) >> 8;
2267 buffsend[48] = (rtcpsin_port & 0x00ff);
2268 send_client(SIZE_HEADER + sizeof(packet_send_call), buffsend,
2269 sub->parent->parent->session);
2271 ast_mutex_unlock(&sub->lock);
2274 static void SendDialTone(struct unistimsession *pte)
2277 /* No country defined ? Using US tone */
2278 if (ast_strlen_zero(pte->device->country)) {
2280 ast_verb(0, "No country defined, using US tone\n");
2281 send_tone(pte, 350, 440);
2284 if (strlen(pte->device->country) != 2) {
2286 ast_verb(0, "Country code != 2 char, using US tone\n");
2287 send_tone(pte, 350, 440);
2291 while (frequency[i].freq1) {
2292 if ((frequency[i].country[0] == pte->device->country[0]) &&
2293 (frequency[i].country[1] == pte->device->country[1])) {
2295 ast_verb(0, "Country code found (%s), freq1=%d freq2=%d\n",
2296 frequency[i].country, frequency[i].freq1, frequency[i].freq2);
2297 send_tone(pte, frequency[i].freq1, frequency[i].freq2);
2303 static void handle_dial_page(struct unistimsession *pte)
2305 pte->state = STATE_DIALPAGE;
2306 if (pte->device->call_forward[0] == -1) {
2307 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
2308 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Enter forward");
2309 send_text_status(pte, "ForwardCancel BackSpcErase");
2310 if (pte->device->call_forward[1] != 0) {
2311 char tmp[TEXT_LENGTH_MAX + 1];
2313 ast_copy_string(pte->device->phone_number, pte->device->call_forward + 1,
2314 sizeof(pte->device->phone_number));
2315 pte->device->size_phone_number = strlen(pte->device->phone_number);
2316 if (pte->device->size_phone_number > 15)
2317 pte->device->size_phone_number = 15;
2318 strcpy(tmp, "Number : ...............");
2319 memcpy(tmp + 9, pte->device->phone_number, pte->device->size_phone_number);
2321 if (pte->device->height == 1) {
2322 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmp);
2323 send_blink_cursor(pte);
2324 send_cursor_pos(pte,
2325 (unsigned char) (TEXT_LINE0 + 0x09 +
2326 pte->device->size_phone_number));
2328 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
2329 send_blink_cursor(pte);
2330 send_cursor_pos(pte,
2331 (unsigned char) (TEXT_LINE2 + 0x09 +
2332 pte->device->size_phone_number));
2335 send_led_update(pte, 0);
2339 if ((pte->device->output == OUTPUT_HANDSET) &&
2340 (pte->device->receiver_state == STATE_ONHOOK))
2341 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2343 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2346 if (pte->device->height > 1) {
2347 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Enter the number to dial");
2348 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "and press Call");
2350 send_text_status(pte, "Call Redial BackSpcErase");
2353 if (pte->device->height == 1) {
2354 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Number : ...............");
2355 send_blink_cursor(pte);
2356 send_cursor_pos(pte, TEXT_LINE0 + 0x09);
2358 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
2359 send_blink_cursor(pte);
2360 send_cursor_pos(pte, TEXT_LINE2 + 0x09);
2362 pte->device->size_phone_number = 0;
2363 pte->device->phone_number[0] = 0;
2364 change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
2365 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
2366 pte->device->missed_call = 0;
2367 send_led_update(pte, 0);
2371 /* Step 1 : Music On Hold for peer, Dialing screen for us */
2372 static void TransferCallStep1(struct unistimsession *pte)
2374 struct unistim_subchannel *sub;
2375 struct unistim_line *p = pte->device->lines;
2377 sub = p->subs[SUB_REAL];
2380 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2383 if (p->subs[SUB_THREEWAY]) {
2385 ast_verb(0, "Transfer canceled, hangup our threeway channel\n");
2386 if (p->subs[SUB_THREEWAY]->owner)
2387 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY]->owner, AST_CAUSE_NORMAL_CLEARING);
2389 ast_log(LOG_WARNING, "Canceling a threeway channel without owner\n");
2392 /* Start music on hold if appropriate */
2393 if (pte->device->moh)
2394 ast_log(LOG_WARNING, "Transfer with peer already listening music on hold\n");
2396 if (ast_bridged_channel(p->subs[SUB_REAL]->owner)) {
2397 ast_moh_start(ast_bridged_channel(p->subs[SUB_REAL]->owner),
2398 pte->device->lines->musicclass, NULL);
2399 pte->device->moh = 1;
2401 ast_log(LOG_WARNING, "Unable to find peer subchannel for music on hold\n");
2405 /* Silence our channel */
2406 if (!pte->device->silence_generator) {
2407 pte->device->silence_generator =
2408 ast_channel_start_silence_generator(p->subs[SUB_REAL]->owner);
2409 if (pte->device->silence_generator == NULL)
2410 ast_log(LOG_WARNING, "Unable to start a silence generator.\n");
2411 else if (unistimdebug)
2412 ast_verb(0, "Starting silence generator\n");
2414 handle_dial_page(pte);
2417 /* From phone to PBX */
2418 static void HandleCallOutgoing(struct unistimsession *s)
2420 struct ast_channel *c;
2421 struct unistim_subchannel *sub;
2423 s->state = STATE_CALL;
2424 sub = s->device->lines->subs[SUB_REAL];
2426 ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
2429 if (!sub->owner) { /* A call is already in progress ? */
2430 c = unistim_new(sub, AST_STATE_DOWN, NULL); /* No, starting a new one */
2432 /* Need to start RTP before calling ast_pbx_run */
2435 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
2437 if (s->device->height == 1) {
2438 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
2440 send_text(TEXT_LINE0, TEXT_NORMAL, s, "Calling :");
2441 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
2442 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Dialing...");
2444 send_text_status(s, "Hangup");
2447 if (ast_pthread_create(&t, NULL, unistim_ss, c)) {
2448 display_last_error("Unable to create switch thread");
2449 ast_queue_hangup_with_cause(c, AST_CAUSE_SWITCH_CONGESTION);
2452 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n",
2453 sub->parent->name, s->device->name);
2454 } else { /* We already have a call, so we switch in a threeway call */
2456 if (s->device->moh) {
2457 struct unistim_subchannel *subchannel;
2458 struct unistim_line *p = s->device->lines;
2459 subchannel = p->subs[SUB_REAL];
2461 if (!subchannel->owner) {
2462 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2465 if (p->subs[SUB_THREEWAY]) {
2466 ast_log(LOG_WARNING,
2467 "Can't transfer while an another transfer is taking place\n");
2470 if (!alloc_sub(p, SUB_THREEWAY)) {
2471 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
2474 /* Stop the silence generator */
2475 if (s->device->silence_generator) {
2477 ast_verb(0, "Stopping silence generator\n");
2478 ast_channel_stop_silence_generator(subchannel->owner,
2479 s->device->silence_generator);
2480 s->device->silence_generator = NULL;
2483 /* Make new channel */
2484 c = unistim_new(p->subs[SUB_THREEWAY], AST_STATE_DOWN, NULL);
2486 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", p);
2489 /* Swap things around between the three-way and real call */
2490 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2491 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
2493 if (s->device->height == 1) {
2494 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
2496 send_text(TEXT_LINE0, TEXT_NORMAL, s, "Calling (pre-transfer)");
2497 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
2498 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Dialing...");
2500 send_text_status(s, "TransfrCancel");
2502 if (ast_pthread_create(&t, NULL, unistim_ss, p->subs[SUB_THREEWAY]->owner)) {
2503 ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", p);
2508 ast_verb(0, "Started three way call on channel %p (%s) subchan %d\n",
2509 p->subs[SUB_THREEWAY]->owner, p->subs[SUB_THREEWAY]->owner->name,
2510 p->subs[SUB_THREEWAY]->subtype);
2512 ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name);
2517 /* From PBX to phone */
2518 static void HandleCallIncoming(struct unistimsession *s)
2520 struct unistim_subchannel *sub;
2521 s->state = STATE_CALL;
2522 s->device->missed_call = 0;
2524 sub = s->device->lines->subs[SUB_REAL];
2526 ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
2528 } else if (unistimdebug)
2529 ast_verb(0, "Handle Call Incoming for %s@%s\n", sub->parent->name,
2533 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", sub->parent->name,
2535 ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
2536 send_text(TEXT_LINE2, TEXT_NORMAL, s, "is on-line");
2537 send_text_status(s, "Hangup Transf");
2538 send_start_timer(s);
2540 if ((s->device->output == OUTPUT_HANDSET) &&
2541 (s->device->receiver_state == STATE_ONHOOK))
2542 send_select_output(s, OUTPUT_SPEAKER, s->device->volume, MUTE_OFF);
2544 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
2545 s->device->start_call_timestamp = time(0);
2546 write_history(s, 'i', 0);
2550 static int unistim_do_senddigit(struct unistimsession *pte, char digit)
2552 struct ast_frame f = { .frametype = AST_FRAME_DTMF, .subclass.integer = digit, .src = "unistim" };
2553 struct unistim_subchannel *sub;
2554 sub = pte->device->lines->subs[SUB_REAL];
2555 if (!sub->owner || sub->alreadygone) {
2556 ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit\n");
2560 /* Send DTMF indication _before_ playing sounds */
2561 ast_queue_frame(sub->owner, &f);
2564 ast_verb(0, "Send Digit %c\n", digit);
2567 send_tone(pte, 941, 1336);
2570 send_tone(pte, 697, 1209);
2573 send_tone(pte, 697, 1336);
2576 send_tone(pte, 697, 1477);
2579 send_tone(pte, 770, 1209);
2582 send_tone(pte, 770, 1336);
2585 send_tone(pte, 770, 1477);
2588 send_tone(pte, 852, 1209);
2591 send_tone(pte, 852, 1336);
2594 send_tone(pte, 852, 1477);
2597 send_tone(pte, 697, 1633);
2600 send_tone(pte, 770, 1633);
2603 send_tone(pte, 852, 1633);
2606 send_tone(pte, 941, 1633);
2609 send_tone(pte, 941, 1209);
2612 send_tone(pte, 941, 1477);
2615 send_tone(pte, 500, 2000);
2617 usleep(150000); /* XXX Less than perfect, blocking an important thread is not a good idea */
2618 send_tone(pte, 0, 0);
2622 static void key_call(struct unistimsession *pte, char keycode)
2624 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
2625 if (keycode == KEY_SHARP)
2627 else if (keycode == KEY_STAR)
2631 unistim_do_senddigit(pte, keycode);
2640 TransferCallStep1(pte);
2643 if (pte->device->output == OUTPUT_HEADPHONE)
2644 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
2646 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
2649 if (pte->device->output != OUTPUT_SPEAKER)
2650 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2652 send_select_output(pte, pte->device->previous_output, pte->device->volume,
2656 if (!pte->device->moh) {
2657 if (pte->device->mute == MUTE_ON)
2658 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2660 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
2665 struct unistim_subchannel *sub;
2666 struct ast_channel *bridgepeer = NULL;
2667 sub = pte->device->lines->subs[SUB_REAL];
2669 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2672 if ((bridgepeer = ast_bridged_channel(sub->owner))) {
2673 if (pte->device->moh) {
2674 ast_moh_stop(bridgepeer);
2675 pte->device->moh = 0;
2676 send_select_output(pte, pte->device->output, pte->device->volume,
2679 ast_moh_start(bridgepeer, pte->device->lines->musicclass, NULL);
2680 pte->device->moh = 1;
2681 send_select_output(pte, pte->device->output, pte->device->volume,
2685 ast_log(LOG_WARNING,
2686 "Unable to find peer subchannel for music on hold\n");
2693 static void key_ringing(struct unistimsession *pte, char keycode)
2695 if (keycode == KEY_FAV0 + pte->device->softkeylinepos) {
2696 HandleCallIncoming(pte);
2705 HandleCallIncoming(pte);
2711 static void Keyfavorite(struct unistimsession *pte, char keycode)
2715 if ((keycode < KEY_FAV1) && (keycode > KEY_FAV5)) {
2716 ast_log(LOG_WARNING, "It's not a favorite key\n");
2719 if (keycode == KEY_FAV0)
2721 fav = keycode - KEY_FAV0;
2722 if (pte->device->softkeyicon[fav] == 0)
2724 ast_copy_string(pte->device->phone_number, pte->device->softkeynumber[fav],
2725 sizeof(pte->device->phone_number));
2726 HandleCallOutgoing(pte);
2730 static void key_dial_page(struct unistimsession *pte, char keycode)
2732 if (keycode == KEY_FUNC3) {
2733 if (pte->device->size_phone_number <= 1)
2734 keycode = KEY_FUNC4;
2736 pte->device->size_phone_number -= 2;
2737 keycode = pte->device->phone_number[pte->device->size_phone_number] + 0x10;
2740 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
2741 char tmpbuf[] = "Number : ...............";
2744 if (pte->device->size_phone_number >= 15)
2746 if (pte->device->size_phone_number == 0)
2747 send_tone(pte, 0, 0);
2748 while (i < pte->device->size_phone_number) {
2749 tmpbuf[i + 9] = pte->device->phone_number[i];
2752 if (keycode == KEY_SHARP)
2754 else if (keycode == KEY_STAR)
2758 tmpbuf[i + 9] = keycode;
2759 pte->device->phone_number[i] = keycode;
2760 pte->device->size_phone_number++;
2761 pte->device->phone_number[i + 1] = 0;
2762 if (pte->device->height == 1) {
2763 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpbuf);
2765 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
2767 send_blink_cursor(pte);
2768 send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 + 0x0a + i));
2771 if (keycode == KEY_FUNC4) {
2773 pte->device->size_phone_number = 0;
2774 if (pte->device->height == 1) {
2775 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Number : ...............");
2776 send_blink_cursor(pte);
2777 send_cursor_pos(pte, TEXT_LINE0 + 0x09);
2779 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
2780 send_blink_cursor(pte);
2781 send_cursor_pos(pte, TEXT_LINE2 + 0x09);
2786 if (pte->device->call_forward[0] == -1) {
2787 if (keycode == KEY_FUNC1) {
2788 ast_copy_string(pte->device->call_forward, pte->device->phone_number,
2789 sizeof(pte->device->call_forward));
2790 show_main_page(pte);
2791 } else if ((keycode == KEY_FUNC2) || (keycode == KEY_HANGUP)) {
2792 pte->device->call_forward[0] = '\0';
2793 show_main_page(pte);
2799 if (ast_strlen_zero(pte->device->redial_number))
2801 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
2802 sizeof(pte->device->phone_number));
2804 HandleCallOutgoing(pte);
2807 if (pte->device->lines->subs[SUB_REAL]->owner) {
2808 /* Stop the silence generator */
2809 if (pte->device->silence_generator) {
2811 ast_verb(0, "Stopping silence generator\n");
2812 ast_channel_stop_silence_generator(pte->device->lines->subs[SUB_REAL]->
2813 owner, pte->device->silence_generator);
2814 pte->device->silence_generator = NULL;
2816 send_tone(pte, 0, 0);
2817 ast_moh_stop(ast_bridged_channel(pte->device->lines->subs[SUB_REAL]->owner));
2818 pte->device->moh = 0;
2819 pte->state = STATE_CALL;
2821 if (pte->device->height == 1) {
2822 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Dial Cancel,back to priv. call.");
2824 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Dialing canceled,");
2825 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "switching back to");
2826 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "previous call.");
2828 send_text_status(pte, "Hangup Transf");
2830 show_main_page(pte);
2837 Keyfavorite(pte, keycode);
2840 if (pte->device->output == OUTPUT_SPEAKER) {
2841 if (pte->device->receiver_state == STATE_OFFHOOK)
2842 send_select_output(pte, pte->device->previous_output, pte->device->volume,
2845 show_main_page(pte);
2847 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2850 if (pte->device->output == OUTPUT_HEADPHONE) {
2851 if (pte->device->receiver_state == STATE_OFFHOOK)
2852 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
2854 show_main_page(pte);
2856 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
2862 #define SELECTCODEC_START_ENTRY_POS 15
2863 #define SELECTCODEC_MAX_LENGTH 2
2864 #define SELECTCODEC_MSG "Codec number : .."
2865 static void HandleSelectCodec(struct unistimsession *pte)
2867 char buf[30], buf2[5];
2869 pte->state = STATE_SELECTCODEC;
2870 strcpy(buf, "Using codec ");
2871 sprintf(buf2, "%d", pte->device->codec_number);
2873 strcat(buf, " (G711u=0,");
2875 send_text(TEXT_LINE0, TEXT_NORMAL, pte, buf);
2876 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "G723=4,G711a=8,G729A=18)");
2877 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
2878 send_blink_cursor(pte);
2879 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
2880 pte->size_buff_entry = 0;
2881 send_text_status(pte, "Select BackSpcErase Cancel");
2885 static void key_select_codec(struct unistimsession *pte, char keycode)
2887 if (keycode == KEY_FUNC2) {
2888 if (pte->size_buff_entry <= 1)
2889 keycode = KEY_FUNC3;
2891 pte->size_buff_entry -= 2;
2892 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
2895 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
2896 char tmpbuf[] = SELECTCODEC_MSG;
2899 if (pte->size_buff_entry >= SELECTCODEC_MAX_LENGTH)
2902 while (i < pte->size_buff_entry) {
2903 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = pte->buff_entry[i];
2906 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = keycode - 0x10;
2907 pte->buff_entry[i] = keycode - 0x10;
2908 pte->size_buff_entry++;
2909 send_text(TEXT_LINE2, TEXT_INVERSE, pte, tmpbuf);
2910 send_blink_cursor(pte);
2911 send_cursor_pos(pte,
2912 (unsigned char) (TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS + 1 + i));
2918 if (pte->size_buff_entry == 1)
2919 pte->device->codec_number = pte->buff_entry[0] - 48;
2920 else if (pte->size_buff_entry == 2)
2921 pte->device->codec_number =
2922 ((pte->buff_entry[0] - 48) * 10) + (pte->buff_entry[1] - 48);
2923 show_main_page(pte);
2926 pte->size_buff_entry = 0;
2927 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
2928 send_blink_cursor(pte);
2929 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
2933 show_main_page(pte);
2939 #define SELECTEXTENSION_START_ENTRY_POS 0
2940 #define SELECTEXTENSION_MAX_LENGTH 10
2941 #define SELECTEXTENSION_MSG ".........."
2942 static void ShowExtensionPage(struct unistimsession *pte)
2944 pte->state = STATE_EXTENSION;
2946 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Please enter a Terminal");
2947 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Number (TN) :");
2948 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
2949 send_blink_cursor(pte);
2950 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
2951 send_text_status(pte, "Enter BackSpcErase");
2952 pte->size_buff_entry = 0;
2956 static void key_select_extension(struct unistimsession *pte, char keycode)
2958 if (keycode == KEY_FUNC2) {
2959 if (pte->size_buff_entry <= 1)
2960 keycode = KEY_FUNC3;
2962 pte->size_buff_entry -= 2;
2963 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
2966 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
2967 char tmpbuf[] = SELECTEXTENSION_MSG;
2970 if (pte->size_buff_entry >= SELECTEXTENSION_MAX_LENGTH)
2973 while (i < pte->size_buff_entry) {
2974 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = pte->buff_entry[i];
2977 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = keycode - 0x10;
2978 pte->buff_entry[i] = keycode - 0x10;
2979 pte->size_buff_entry++;
2980 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
2981 send_blink_cursor(pte);
2982 send_cursor_pos(pte,
2983 (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS + 1 +
2990 if (pte->size_buff_entry < 1)
2992 if (autoprovisioning == AUTOPROVISIONING_TN) {
2993 struct unistim_device *d;
2995 /* First step : looking for this TN in our device list */
2996 ast_mutex_lock(&devicelock);
2998 pte->buff_entry[pte->size_buff_entry] = '\0';
3000 if (d->id[0] == 'T') { /* It's a TN device ? */
3001 /* It's the TN we're looking for ? */
3002 if (!strcmp((d->id) + 1, pte->buff_entry)) {
3005 d->codec_number = DEFAULT_CODEC;
3008 d->receiver_state = STATE_ONHOOK;
3009 strcpy(d->id, pte->macaddr);
3010 pte->device->extension_number[0] = 'T';