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/netsock2.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"
76 #include "asterisk/features.h"
77 #include "asterisk/astobj2.h"
78 #include "asterisk/astdb.h"
81 #define DEFAULTCONTEXT "default"
82 #define DEFAULTCALLERID "Unknown"
83 #define DEFAULTCALLERNAME " "
84 #define DEFAULTHEIGHT 3
85 #define USTM_LOG_DIR "unistimHistory"
86 #define USTM_LANG_DIR "unistimLang"
88 /*! Size of the transmit buffer */
89 #define MAX_BUF_SIZE 64
90 /*! Number of slots for the transmit queue */
91 #define MAX_BUF_NUMBER 50
92 /*! Number of digits displayed on screen */
93 #define MAX_SCREEN_NUMBER 15
94 /*! Try x times before removing the phone */
95 #define NB_MAX_RETRANSMIT 8
96 /*! Nb of milliseconds waited when no events are scheduled */
97 #define IDLE_WAIT 1000
98 /*! Wait x milliseconds before resending a packet */
99 #define RETRANSMIT_TIMER 2000
100 /*! How often the mailbox is checked for new messages */
101 #define TIMER_MWI 5000
102 /*! How often the mailbox is checked for new messages */
103 #define TIMER_DIAL 4000
105 #define DEFAULT_CODEC 0x00
106 #define SIZE_PAGE 4096
107 #define DEVICE_NAME_LEN 16
108 #define AST_CONFIG_MAX_PATH 255
109 #define MAX_ENTRY_LOG 30
113 #define SUB_THREEWAY 2
116 struct ast_format_cap *global_cap;
119 AUTOPROVISIONING_NO = 0,
120 AUTOPROVISIONING_YES,
125 /*! Do not create an extension into the default dialplan */
127 /*! Prompt user for an extension number and register it */
129 /*! Register an extension with the line=> value */
131 /*! Used with AUTOPROVISIONING_TN */
134 #define OUTPUT_HANDSET 0xC0
135 #define OUTPUT_HEADPHONE 0xC1
136 #define OUTPUT_SPEAKER 0xC2
138 #define VOLUME_LOW 0x01
139 #define VOLUME_LOW_SPEAKER 0x03
140 #define VOLUME_NORMAL 0x02
141 #define VOLUME_INSANELY_LOUD 0x07
143 #define MUTE_OFF 0x00
145 #define MUTE_ON_DISCRET 0xCE
147 #define SIZE_HEADER 6
148 #define SIZE_MAC_ADDR 17
149 #define TEXT_LENGTH_MAX 24
150 #define TEXT_LINE0 0x00
151 #define TEXT_LINE1 0x20
152 #define TEXT_LINE2 0x40
153 #define TEXT_NORMAL 0x05
154 #define TEXT_INVERSE 0x25
155 #define STATUS_LENGTH_MAX 28
157 #define FAV_ICON_NONE 0x00
158 #define FAV_ICON_ONHOOK_BLACK 0x20
159 #define FAV_ICON_ONHOOK_WHITE 0x21
160 #define FAV_ICON_SPEAKER_ONHOOK_BLACK 0x22
161 #define FAV_ICON_SPEAKER_ONHOOK_WHITE 0x23
162 #define FAV_ICON_OFFHOOK_BLACK 0x24
163 #define FAV_ICON_OFFHOOK_WHITE 0x25
164 #define FAV_ICON_ONHOLD_BLACK 0x26
165 #define FAV_ICON_ONHOLD_WHITE 0x27
166 #define FAV_ICON_SPEAKER_OFFHOOK_BLACK 0x28
167 #define FAV_ICON_SPEAKER_OFFHOOK_WHITE 0x29
168 #define FAV_ICON_PHONE_BLACK 0x2A
169 #define FAV_ICON_PHONE_WHITE 0x2B
170 #define FAV_ICON_SPEAKER_ONHOLD_BLACK 0x2C
171 #define FAV_ICON_SPEAKER_ONHOLD_WHITE 0x2D
172 #define FAV_ICON_HEADPHONES 0x2E
173 #define FAV_ICON_HEADPHONES_ONHOLD 0x2F
174 #define FAV_ICON_HOME 0x30
175 #define FAV_ICON_CITY 0x31
176 #define FAV_ICON_SHARP 0x32
177 #define FAV_ICON_PAGER 0x33
178 #define FAV_ICON_CALL_CENTER 0x34
179 #define FAV_ICON_FAX 0x35
180 #define FAV_ICON_MAILBOX 0x36
181 #define FAV_ICON_REFLECT 0x37
182 #define FAV_ICON_COMPUTER 0x38
183 #define FAV_ICON_FORWARD 0x39
184 #define FAV_ICON_LOCKED 0x3A
185 #define FAV_ICON_TRASH 0x3B
186 #define FAV_ICON_INBOX 0x3C
187 #define FAV_ICON_OUTBOX 0x3D
188 #define FAV_ICON_MEETING 0x3E
189 #define FAV_ICON_BOX 0x3F
191 #define FAV_BLINK_FAST 0x20
192 #define FAV_BLINK_SLOW 0x40
194 #define FAV_MAX_LENGTH 0x0A
197 #define FAV_LINE_ICON FAV_ICON_ONHOOK_BLACK
199 static void dummy(char *unused, ...)
204 /*! \brief Global jitterbuffer configuration - by default, jb is disabled
205 * \note Values shown here match the defaults shown in unistim.conf.sample */
206 static struct ast_jb_conf default_jbconf =
210 .resync_threshold = 1000,
214 static struct ast_jb_conf global_jbconf;
217 /* #define DUMP_PACKET 1 */
218 /* #define DEBUG_TIMER ast_verbose */
220 #define DEBUG_TIMER dummy
221 /*! Enable verbose output. can also be set with the CLI */
222 static int unistimdebug = 0;
223 static int unistim_port;
224 static enum autoprovision autoprovisioning = AUTOPROVISIONING_NO;
225 static int unistim_keepalive;
226 static int unistimsock = -1;
230 unsigned int tos_audio;
232 unsigned int cos_audio;
233 } qos = { 0, 0, 0, 0 };
235 static struct io_context *io;
236 static struct ast_sched_context *sched;
237 static struct sockaddr_in public_ip = { 0, };
238 static unsigned char *buff; /*! Receive buffer address */
239 static int unistim_reloading = 0;
240 AST_MUTEX_DEFINE_STATIC(unistim_reload_lock);
242 /*! This is the thread for the monitor which checks for input on the channels
243 * which are not currently in use. */
244 static pthread_t monitor_thread = AST_PTHREADT_NULL;
246 /*! Protect the monitoring thread, so only one process can kill or start it, and not
247 * when it's doing something critical. */
248 AST_MUTEX_DEFINE_STATIC(monlock);
249 /*! Protect the session list */
250 AST_MUTEX_DEFINE_STATIC(sessionlock);
251 /*! Protect the device list */
252 AST_MUTEX_DEFINE_STATIC(devicelock);
264 STATE_SELECTLANGUAGE,
324 static const int dtmf_row[] = { 697, 770, 852, 941 };
325 static const float dtmf_col[] = { 1209, 1336, 1477, 1633 };
332 struct unistim_subchannel {
334 unsigned int subtype; /*! SUB_REAL, SUB_RING, SUB_THREEWAY or SUB_ONHOLD */
335 struct ast_channel *owner; /*! Asterisk channel used by the subchannel */
336 struct unistim_line *parent; /*! Unistim line */
337 struct ast_rtp_instance *rtp; /*! RTP handle */
338 int softkey; /*! Softkey assigned */
339 pthread_t ss_thread; /*! unistim_ss thread handle */
343 int moh; /*!< Music on hold in progress */
344 AST_LIST_ENTRY(unistim_subchannel) list;
348 * \todo Convert to stringfields
350 struct unistim_line {
352 char name[80]; /*! Like 200 */
353 char fullname[80]; /*! Like USTM/200\@black */
354 char exten[AST_MAX_EXTENSION]; /*! Extension where to start */
355 char cid_num[AST_MAX_EXTENSION]; /*! CallerID Number */
356 char mailbox[AST_MAX_EXTENSION]; /*! Mailbox for MWI */
357 int lastmsgssent; /*! Used by MWI */
358 time_t nextmsgcheck; /*! Used by MWI */
359 char musicclass[MAX_MUSICCLASS]; /*! MusicOnHold class */
360 ast_group_t callgroup; /*! Call group */
361 ast_group_t pickupgroup; /*! Pickup group */
362 char accountcode[AST_MAX_ACCOUNT_CODE]; /*! Account code (for billing) */
363 int amaflags; /*! AMA flags (for billing) */
364 struct ast_format_cap *cap; /*! Codec supported */
365 char parkinglot[AST_MAX_CONTEXT]; /*! Parkinglot */
366 struct unistim_line *next;
367 struct unistim_device *parent;
368 AST_LIST_ENTRY(unistim_line) list;
372 * \brief A device containing one or more lines
374 static struct unistim_device {
376 int receiver_state; /*!< state of the receiver (see ReceiverState) */
377 int size_phone_number; /*!< size of the phone number */
378 char context[AST_MAX_EXTENSION]; /*!< Context to start in */
379 char phone_number[AST_MAX_EXTENSION]; /*!< the phone number entered by the user */
380 char redial_number[AST_MAX_EXTENSION]; /*!< the last phone number entered by the user */
381 char id[18]; /*!< mac address of the current phone in ascii */
382 char name[DEVICE_NAME_LEN]; /*!< name of the device */
383 char softkeylabel[FAVNUM][11]; /*!< soft key label */
384 char softkeynumber[FAVNUM][AST_MAX_EXTENSION]; /*!< number dialed when the soft key is pressed */
385 char softkeyicon[FAVNUM]; /*!< icon number */
386 char softkeydevice[FAVNUM][16]; /*!< name of the device monitored */
387 struct unistim_subchannel *ssub[FAVNUM];
388 struct unistim_line *sline[FAVNUM];
389 struct unistim_device *sp[FAVNUM]; /*!< pointer to the device monitored by this soft key */
390 char language[MAX_LANGUAGE]; /*!< Language for asterisk sounds */
391 int height; /*!< The number of lines the phone can display */
392 char maintext0[25]; /*!< when the phone is idle, display this string on line 0 */
393 char maintext1[25]; /*!< when the phone is idle, display this string on line 1 */
394 char maintext2[25]; /*!< when the phone is idle, display this string on line 2 */
395 char titledefault[13]; /*!< title (text before date/time) */
396 char datetimeformat; /*!< format used for displaying time/date */
397 char contrast; /*!< contrast */
398 char country[3]; /*!< country used for dial tone frequency */
399 struct ast_tone_zone *tz; /*!< Tone zone for res_indications (ring, busy, congestion) */
400 char ringvolume; /*!< Ring volume */
401 char ringstyle; /*!< Ring melody */
402 char cwvolume; /*!< Ring volume on call waiting */
403 char cwstyle; /*!< Ring melody on call waiting */
404 time_t nextdial; /*!< Timer used for dial by timeout */
405 int rtp_port; /*!< RTP port used by the phone */
406 int rtp_method; /*!< Select the unistim data used to establish a RTP session */
407 int status_method; /*!< Select the unistim packet used for sending status text */
408 char codec_number; /*!< The current codec used to make calls */
409 int missed_call; /*!< Number of call unanswered */
410 int callhistory; /*!< Allowed to record call history */
411 int sharp_dial; /*!< Execute Dial on '#' or not */
412 char lst_cid[TEXT_LENGTH_MAX]; /*!< Last callerID received */
413 char lst_cnm[TEXT_LENGTH_MAX]; /*!< Last callername recevied */
414 char call_forward[AST_MAX_EXTENSION]; /*!< Forward number */
415 int output; /*!< Handset, headphone or speaker */
416 int previous_output; /*!< Previous output */
417 int volume; /*!< Default volume */
418 int selected; /*!< softkey selected */
419 int mute; /*!< Mute mode */
420 int nat; /*!< Used by the obscure ast_rtp_setnat */
421 enum autoprov_extn extension; /*!< See ifdef EXTENSION for valid values */
422 char extension_number[11]; /*!< Extension number entered by the user */
423 char to_delete; /*!< Used in reload */
424 struct ast_silence_generator *silence_generator;
425 AST_LIST_HEAD(,unistim_subchannel) subs; /*!< pointer to our current connection, channel... */
426 AST_LIST_HEAD(,unistim_line) lines;
428 struct unistimsession *session;
429 struct unistim_device *next;
432 static struct unistimsession {
434 struct sockaddr_in sin; /*!< IP address of the phone */
435 struct sockaddr_in sout; /*!< IP address of server */
436 int timeout; /*!< time-out in ticks : resend packet if no ack was received before the timeout occured */
437 unsigned short seq_phone; /*!< sequence number for the next packet (when we receive a request) */
438 unsigned short seq_server; /*!< sequence number for the next packet (when we send a request) */
439 unsigned short last_seq_ack; /*!< sequence number of the last ACK received */
440 unsigned long tick_next_ping; /*!< time for the next ping */
441 int last_buf_available; /*!< number of a free slot */
442 int nb_retransmit; /*!< number of retransmition */
443 int state; /*!< state of the phone (see phone_state) */
444 int size_buff_entry; /*!< size of the buffer used to enter datas */
445 char buff_entry[16]; /*!< Buffer for temporary datas */
446 char macaddr[18]; /*!< mac adress of the phone (not always available) */
447 struct wsabuf wsabufsend[MAX_BUF_NUMBER]; /*!< Size of each paquet stored in the buffer array & pointer to this buffer */
448 unsigned char buf[MAX_BUF_NUMBER][MAX_BUF_SIZE]; /*!< Buffer array used to keep the lastest non-acked paquets */
449 struct unistim_device *device;
450 struct unistimsession *next;
453 /*! Store on screen phone menu item (label and handler function) */
454 struct unistim_menu_item {
457 void (*handle_option)(struct unistimsession *);
460 /*! Language item for currently existed translations */
461 struct unistim_languages {
465 struct ao2_container *trans;
469 * \page Unistim datagram formats
471 * Format of datagrams :
472 * bytes 0 & 1 : ffff for discovery packet, 0000 for everything else
473 * byte 2 : sequence number (high part)
474 * byte 3 : sequence number (low part)
475 * byte 4 : 2 = ask question or send info, 1 = answer or ACK, 0 = retransmit request
476 * byte 5 : direction, 1 = server to phone, 2 = phone to server arguments
479 static const unsigned char packet_rcv_discovery[] =
480 { 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
481 static const unsigned char packet_send_discovery_ack[] =
482 { 0x00, 0x00, /*Initial Seq (2 bytes) */ 0x00, 0x00, 0x00, 0x01 };
484 static const unsigned char packet_recv_firm_version[] =
485 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x0a, 0x02 };
486 static const unsigned char packet_recv_it_type[] =
487 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x04, 0x03 };
488 static const unsigned char packet_recv_pressed_key[] =
489 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x04, 0x00 };
490 static const unsigned char packet_recv_pick_up[] =
491 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x04 };
492 static const unsigned char packet_recv_hangup[] =
493 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x03 };
494 static const unsigned char packet_recv_r2[] = { 0x00, 0x00, 0x00, 0x13, 0x96, 0x03, 0x03 };
496 /*! TransportAdapter */
497 static const unsigned char packet_recv_resume_connection_with_server[] =
498 { 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
499 static const unsigned char packet_recv_mac_addr[] =
500 { 0xff, 0xff, 0xff, 0xff, 0x9a, 0x0d, 0x07 /*MacAddr */ };
502 static const unsigned char packet_send_date_time3[] =
503 { 0x11, 0x09, 0x02, 0x02, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07,
504 /*Minutes */ 0x08, 0x32
506 static const unsigned char packet_send_date_time[] =
507 { 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07, /*Minutes */
508 0x08, 0x32, 0x17, 0x04, 0x24, 0x07, 0x19,
509 0x04, 0x07, 0x00, 0x19, 0x05, 0x09, 0x3e, 0x0f, 0x16, 0x05, 0x00, 0x80, 0x00, 0x1e,
510 0x05, 0x12, 0x00, 0x78
513 static const unsigned char packet_send_no_ring[] =
514 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00 };
515 static const unsigned char packet_send_s4[] =
516 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff,
517 0x16, 0x05, 0x1c, 0x00, 0x00, 0x17, 0x05,
518 0x0b, 0x00, 0x00, 0x19, 0x04, 0x00, 0x00, 0x19, 0x04, 0x00, 0x08, 0x19, 0x04, 0x00,
519 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
520 0x31, 0x00, 0x00, 0x16, 0x05, 0x04, 0x00, 0x00
522 static const unsigned char packet_send_call[] =
523 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf,
524 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16, 0x0a, 0x38, 0x00, 0x12, 0xca, 0x03,
525 0xc0, 0xc3, 0xc5, 0x16, 0x16, 0x30, 0x00,
526 0x00, /*codec */ 0x12, 0x12, /* frames per packet */ 0x01, 0x5c, 0x00, /*port RTP */
527 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41,
528 /*port RTP */ 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41, /* IP Address */ 0x0a, 0x01,
531 static const unsigned char packet_send_stream_based_tone_off[] =
532 { 0x16, 0x05, 0x1c, 0x00, 0x00 };
534 /* static const unsigned char packet_send_Mute[] = { 0x16, 0x05, 0x04, 0x00, 0x00 };
535 static const unsigned char packet_send_CloseAudioStreamRX[] = { 0x16, 0x05, 0x31, 0x00, 0xff };
536 static const unsigned char packet_send_CloseAudioStreamTX[] = { 0x16, 0x05, 0x31, 0xff, 0x00 };*/
537 static const unsigned char packet_send_stream_based_tone_on[] =
538 { 0x16, 0x06, 0x1b, 0x00, 0x00, 0x05 };
539 static const unsigned char packet_send_stream_based_tone_single_freq[] =
540 { 0x16, 0x06, 0x1d, 0x00, 0x01, 0xb8 };
541 static const unsigned char packet_send_stream_based_tone_dial_freq[] =
542 { 0x16, 0x08, 0x1d, 0x00, 0x01, 0xb8, 0x01, 0x5e };
543 static const unsigned char packet_send_select_output[] =
544 { 0x16, 0x06, 0x32, 0xc0, 0x01, 0x00 };
545 static const unsigned char packet_send_ring[] =
546 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16,
547 0x04, 0x1a, 0x01, 0x16, 0x05, 0x12, 0x13 /* Ring type 10 to 17 */ , 0x18, 0x16, 0x04, 0x18, /* volume 00, 10, 20... */
548 0x20, 0x16, 0x04, 0x10, 0x00
550 static const unsigned char packet_send_end_call[] =
551 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x31, 0x00, 0x00, 0x19, 0x04, 0x00,
552 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
553 0x04, 0x00, 0x00, 0x16, 0x04, 0x37, 0x10
555 static const unsigned char packet_send_s9[] =
556 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x19, 0x04, 0x00, 0x10, 0x16, 0x05, 0x1c, 0x00,
558 static const unsigned char packet_send_rtp_packet_size[] =
559 { 0x16, 0x08, 0x38, 0x00, 0x00, 0xe0, 0x00, 0xa0 };
560 static const unsigned char packet_send_jitter_buffer_conf[] =
561 { 0x16, 0x0e, 0x3a, 0x00, /* jitter */ 0x02, /* high water mark */ 0x04, 0x00, 0x00,
562 /* early packet resync 2 bytes */ 0x3e, 0x80,
563 0x00, 0x00, /* late packet resync 2 bytes */ 0x3e, 0x80
566 /* Duration in ms div 2 (0x20 = 64ms, 0x08 = 16ms)
567 static unsigned char packet_send_StreamBasedToneCad[] =
568 { 0x16, 0x0a, 0x1e, 0x00, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x2b }; */
569 static const unsigned char packet_send_open_audio_stream_rx[] =
570 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
571 0x0e, 0x01, /* Port */ 0x14, 0x50, 0x00,
572 0x00, /* Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
574 static const unsigned char packet_send_open_audio_stream_tx[] =
575 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
576 0x0e, 0x01, /* Local port */ 0x14, 0x50,
577 0x00, 0x00, /* Rmt Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
580 static const unsigned char packet_send_open_audio_stream_rx3[] =
581 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
582 0x06, 0x81, /* RTP Port */ 0x14, 0x50,
583 /* RTCP Port */ 0x14,
584 0x51, /* RTP Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00, /* Dest IP */ 0x0a, 0x93,
587 static const unsigned char packet_send_open_audio_stream_tx3[] =
588 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
589 0x06, 0x81, /* RTP Local port */ 0x14, 0x50,
590 /* RTCP Port */ 0x00, 0x00, /* RTP Rmt Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00,
591 /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
594 static const unsigned char packet_send_arrow[] = { 0x17, 0x04, 0x04, 0x00 };
595 static const unsigned char packet_send_blink_cursor[] = { 0x17, 0x04, 0x10, 0x86 };
596 static const unsigned char packet_send_date_time2[] = { 0x17, 0x04, 0x17, 0x3d, 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */
597 0x06, /*Hour */ 0x07, /*Minutes */ 0x08, 0x32
599 static const unsigned char packet_send_Contrast[] =
600 { 0x17, 0x04, 0x24, /*Contrast */ 0x08 };
601 static const unsigned char packet_send_start_timer[] =
602 { 0x17, 0x05, 0x0b, /*Timer option*/0x05, /* Timer ID */0x00, 0x17, 0x08, 0x16,
603 /* Text */ 0x44, 0x75, 0x72, 0xe9, 0x65 };
604 static const unsigned char packet_send_stop_timer[] = { 0x17, 0x05, 0x0b, 0x02, 0x00 };
605 static const unsigned char packet_send_icon[] = { 0x17, 0x05, 0x14, /*pos */ 0x00, /*icon */ 0x25 }; /* display an icon in front of the text zone */
606 static const unsigned char packet_send_S7[] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 };
607 static const unsigned char packet_send_set_pos_cursor[] =
608 { 0x17, 0x06, 0x10, 0x81, 0x04, /*pos */ 0x20 };
610 /*static unsigned char packet_send_MonthLabelsDownload[] =
611 { 0x17, 0x0a, 0x15, Month (3 char) 0x46, 0x65, 0x62, 0x4d, 0xe4, 0x72, 0x20 }; */
612 static const unsigned char packet_send_favorite[] =
613 { 0x17, 0x0f, 0x19, 0x10, /*pos */ 0x01, /*name */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
614 0x20, 0x20, 0x20, 0x20, /*end_name */ 0x19,
615 0x05, 0x0f, /*pos */ 0x01, /*icone */ 0x00
617 static const unsigned char packet_send_title[] =
618 { 0x17, 0x10, 0x19, 0x02, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
619 0x20, 0x20, 0x20, 0x20 /*end_text */ };
620 static const unsigned char packet_send_text[] =
621 { 0x17, 0x1e, 0x1b, 0x04, /*pos */ 0x00, /*inverse */ 0x25, /*text */ 0x20, 0x20,
622 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
623 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
624 /*end_text */ 0x17, 0x04, 0x10, 0x87
626 static const unsigned char packet_send_status[] =
627 { 0x17, 0x20, 0x19, 0x08, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
628 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
629 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 /*end_text */
631 static const unsigned char packet_send_status2[] =
632 { 0x17, 0x0b, 0x19, /* pos [08|28|48|68] */ 0x00, /* text */ 0x20, 0x20, 0x20, 0x20,
633 0x20, 0x20, 0x20 /* end_text */ };
635 /* Multiple character set support */
636 /* ISO-8859-1 - Western European) */
637 static const unsigned char packet_send_charset_iso_8859_1[] =
638 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x41, 0x1b, 0x00 };
639 /* ISO-8859-2 - Central European) */
640 static const unsigned char packet_send_charset_iso_8859_2[] =
641 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x42, 0x1b, 0x00 };
642 /* ISO-8859-4 - Baltic) */
643 static const unsigned char packet_send_charset_iso_8859_4[] =
644 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x44, 0x1b, 0x00 };
645 /* ISO 8859-5 - cyrilic */
646 static const unsigned char packet_send_charset_iso_8859_5[] =
647 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x4c, 0x1b, 0x00 };
648 /* Japaneese (ISO-2022-JP ?) */
649 static const unsigned char packet_send_charset_iso_2022_jp[] =
650 { 0x17, 0x08, 0x21, 0x1b, 0x29, 0x49, 0x1b, 0x7e };
652 static const unsigned char packet_send_led_update[] = { 0x19, 0x04, 0x00, 0x00 };
654 static const unsigned char packet_send_query_basic_manager_04[] = { 0x1a, 0x04, 0x01, 0x04 };
655 static const unsigned char packet_send_query_mac_address[] = { 0x1a, 0x04, 0x01, 0x08 };
656 static const unsigned char packet_send_query_basic_manager_10[] = { 0x1a, 0x04, 0x01, 0x10 };
657 static const unsigned char packet_send_S1[] = { 0x1a, 0x07, 0x07, 0x00, 0x00, 0x00, 0x13 };
659 static unsigned char packet_send_ping[] =
660 { 0x1e, 0x05, 0x12, 0x00, /*Watchdog timer */ 0x78 };
662 #define BUFFSEND unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }
664 static const char tdesc[] = "UNISTIM Channel Driver";
665 static const char channel_type[] = "USTM";
668 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state, const char *linkedid);
669 static int load_module(void);
670 static int reload(void);
671 static int unload_module(void);
672 static int reload_config(void);
673 static void show_main_page(struct unistimsession *pte);
674 static struct ast_channel *unistim_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor,
675 const char *dest, int *cause);
676 static int unistim_call(struct ast_channel *ast, const char *dest, int timeout);
677 static int unistim_hangup(struct ast_channel *ast);
678 static int unistim_answer(struct ast_channel *ast);
679 static struct ast_frame *unistim_read(struct ast_channel *ast);
680 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame);
681 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
683 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
684 static int unistim_senddigit_begin(struct ast_channel *ast, char digit);
685 static int unistim_senddigit_end(struct ast_channel *ast, char digit,
686 unsigned int duration);
687 static int unistim_sendtext(struct ast_channel *ast, const char *text);
689 static int write_entry_history(struct unistimsession *pte, FILE * f, char c,
691 static void change_callerid(struct unistimsession *pte, int type, char *callerid);
693 static struct ast_channel_tech unistim_tech = {
694 .type = channel_type,
695 .description = tdesc,
696 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
697 .requester = unistim_request,
698 .call = unistim_call,
699 .hangup = unistim_hangup,
700 .answer = unistim_answer,
701 .read = unistim_read,
702 .write = unistim_write,
703 .indicate = unistim_indicate,
704 .fixup = unistim_fixup,
705 .send_digit_begin = unistim_senddigit_begin,
706 .send_digit_end = unistim_senddigit_end,
707 .send_text = unistim_sendtext,
708 .bridge = ast_rtp_instance_bridge,
711 static void send_start_rtp(struct unistim_subchannel *);
713 static void send_callerid_screen(struct unistimsession *, struct unistim_subchannel *);
714 static void key_favorite(struct unistimsession *, char);
716 static void handle_select_codec(struct unistimsession *);
717 static void handle_select_language(struct unistimsession *);
718 static int find_language(const char*);
720 static int unistim_free_sub(struct unistim_subchannel *);
722 static struct unistim_menu_item options_menu[] =
724 {"Change codec", STATE_SELECTCODEC, handle_select_codec},
725 {"Language", STATE_SELECTLANGUAGE, handle_select_language},
729 static struct unistim_languages options_languages[] =
731 {"English", "en", ISO_8859_1, NULL},
732 {"Russian", "ru", ISO_8859_5, NULL},
733 {NULL, NULL, 0, NULL}
736 static char ustm_strcopy[1024];
738 struct ustm_lang_entry {
739 const char *str_orig;
740 const char *str_trans;
743 static int lang_hash_fn(const void *obj, const int flags)
745 const struct ustm_lang_entry *entry = obj;
746 return ast_str_hash(entry->str_orig);
749 static int lang_cmp_fn(void *obj, void *arg, int flags)
751 struct ustm_lang_entry *entry1 = obj;
752 struct ustm_lang_entry *entry2 = arg;
754 return (!strcmp(entry1->str_orig, entry2->str_orig)) ? (CMP_MATCH | CMP_STOP) : 0;
757 static const char *ustmtext(const char *str, struct unistimsession *pte)
759 struct ustm_lang_entry *lang_entry;
760 struct ustm_lang_entry le_search;
761 struct unistim_languages *lang = NULL;
765 lang = &options_languages[find_language(pte->device->language)];
770 /* Check if specified language exists */
772 char tmp[1024], *p, *p_orig = NULL, *p_trans = NULL;
775 if (!(lang->trans = ao2_container_alloc(8, lang_hash_fn, lang_cmp_fn))) {
776 ast_log(LOG_ERROR, "Unable to allocate container for translation!\n");
779 snprintf(tmp, sizeof(tmp), "%s/%s/%s.po", ast_config_AST_VAR_DIR,
780 USTM_LANG_DIR, lang->lang_short);
783 ast_log(LOG_ERROR, "There is no translation file for '%s'\n", pte->device->language);
786 while (fgets(tmp, sizeof(tmp), f)) {
787 if (!(p = strchr(tmp, '\n'))) {
788 ast_log(LOG_ERROR, "Too long line found in language file - truncated!\n");
792 if (!(p = strchr(tmp, '"'))) {
795 if (tmp == strstr(tmp, "msgid")) {
796 p_orig = ast_strdup(p + 1);
797 p = strchr(p_orig, '"');
798 } else if (tmp == strstr(tmp, "msgstr")) {
799 p_trans = ast_strdup(p + 1);
800 p = strchr(p_trans, '"');
805 if (!p_trans || !p_orig) {
808 if (ast_strlen_zero(p_trans)) {
815 if (!(lang_entry = ao2_alloc(sizeof(*lang_entry), NULL))) {
820 lang_entry->str_trans = p_trans;
821 lang_entry->str_orig = p_orig;
822 ao2_link(lang->trans, lang_entry);
830 le_search.str_orig = str;
831 if ((lang_entry = ao2_find(lang->trans, &le_search, OBJ_POINTER))) {
832 size = strlen(lang_entry->str_trans)+1;
836 memcpy(ustm_strcopy, lang_entry->str_trans, size);
837 ao2_ref(lang_entry, -1);
844 static void display_last_error(const char *sz_msg)
846 /* Display the error message */
847 ast_log(LOG_WARNING, "%s : (%u) %s\n", sz_msg, errno, strerror(errno));
850 static unsigned int get_tick_count(void)
852 struct timeval now = ast_tvnow();
854 return (now.tv_sec * 1000) + (now.tv_usec / 1000);
857 /* Send data to a phone without retransmit nor buffering */
858 static void send_raw_client(int size, const unsigned char *data, struct sockaddr_in *addr_to,
859 const struct sockaddr_in *addr_ourip)
862 struct iovec msg_iov;
864 char buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
865 struct cmsghdr *ip_msg = (struct cmsghdr *) buffer;
866 struct in_pktinfo *pki = (struct in_pktinfo *) CMSG_DATA(ip_msg);
868 /* cast this to a non-const pointer, since the sendmsg() API
869 * does not provide read-only and write-only flavors of the
870 * structures used for its arguments, but in this case we know
871 * the data will not be modified
873 msg_iov.iov_base = (char *) data;
874 msg_iov.iov_len = size;
876 msg.msg_name = addr_to; /* optional address */
877 msg.msg_namelen = sizeof(struct sockaddr_in); /* size of address */
878 msg.msg_iov = &msg_iov; /* scatter/gather array */
879 msg.msg_iovlen = 1; /* # elements in msg_iov */
880 msg.msg_control = ip_msg; /* ancillary data */
881 msg.msg_controllen = sizeof(buffer); /* ancillary data buffer len */
882 msg.msg_flags = 0; /* flags on received message */
884 ip_msg->cmsg_len = CMSG_LEN(sizeof(*pki));
885 ip_msg->cmsg_level = IPPROTO_IP;
886 ip_msg->cmsg_type = IP_PKTINFO;
887 pki->ipi_ifindex = 0; /* Interface index, 0 = use interface specified in routing table */
888 pki->ipi_spec_dst.s_addr = addr_ourip->sin_addr.s_addr; /* Local address */
889 /* pki->ipi_addr = ; Header Destination address - ignored by kernel */
894 char iabuf[INET_ADDRSTRLEN];
895 char iabuf2[INET_ADDRSTRLEN];
896 ast_verb(0, "\n**> From %s sending %d bytes to %s ***\n",
897 ast_inet_ntoa(addr_ourip->sin_addr), (int) size,
898 ast_inet_ntoa(addr_to->sin_addr));
899 for (tmp = 0; tmp < size; tmp++)
900 ast_verb(0, "%.2x ", (unsigned char) data[tmp]);
901 ast_verb(0, "\n******************************************\n");
906 if (sendmsg(unistimsock, &msg, 0) == -1) {
907 display_last_error("Error sending datas");
910 if (sendto(unistimsock, data, size, 0, (struct sockaddr *) addr_to, sizeof(*addr_to))
912 display_last_error("Error sending datas");
916 static void send_client(int size, const unsigned char *data, struct unistimsession *pte)
920 unsigned short seq = ntohs(++pte->seq_server);
922 ast_mutex_lock(&pte->lock);
923 buf_pos = pte->last_buf_available;
925 if (buf_pos >= MAX_BUF_NUMBER) {
926 ast_log(LOG_WARNING, "Error : send queue overflow\n");
927 ast_mutex_unlock(&pte->lock);
930 memcpy((void *)data + sizeof(unsigned short), (void *)&seq, sizeof(unsigned short));
931 pte->wsabufsend[buf_pos].len = size;
932 memcpy(pte->wsabufsend[buf_pos].buf, data, size);
934 tick = get_tick_count();
935 pte->timeout = tick + RETRANSMIT_TIMER;
937 /*#ifdef DUMP_PACKET */
939 ast_verb(6, "Sending datas with seq #0x%.4x Using slot #%d :\n", pte->seq_server, buf_pos);
942 send_raw_client(pte->wsabufsend[buf_pos].len, pte->wsabufsend[buf_pos].buf, &(pte->sin),
944 pte->last_buf_available++;
945 ast_mutex_unlock(&pte->lock);
948 static void send_ping(struct unistimsession *pte)
952 ast_verb(6, "Sending ping\n");
954 pte->tick_next_ping = get_tick_count() + unistim_keepalive;
955 memcpy(buffsend + SIZE_HEADER, packet_send_ping, sizeof(packet_send_ping));
956 send_client(SIZE_HEADER + sizeof(packet_send_ping), buffsend, pte);
959 static int get_to_address(int fd, struct sockaddr_in *toAddr)
967 struct in_addr address;
970 /* Zero out the structures before we use them */
971 /* This sets several key values to NULL */
972 memset(&msg, 0, sizeof(msg));
973 memset(&ip_msg, 0, sizeof(ip_msg));
975 /* Initialize the message structure */
976 msg.msg_control = &ip_msg;
977 msg.msg_controllen = sizeof(ip_msg);
978 /* Get info about the incoming packet */
979 err = recvmsg(fd, &msg, MSG_PEEK);
981 ast_log(LOG_WARNING, "recvmsg returned an error: %s\n", strerror(errno));
983 memcpy(&toAddr->sin_addr, &ip_msg.address, sizeof(struct in_addr));
986 memcpy(&toAddr, &public_ip, sizeof(&toAddr));
991 /* Allocate memory & initialize structures for a new phone */
992 /* addr_from : ip address of the phone */
993 static struct unistimsession *create_client(const struct sockaddr_in *addr_from)
996 struct unistimsession *s;
998 if (!(s = ast_calloc(1, sizeof(*s))))
1001 memcpy(&s->sin, addr_from, sizeof(struct sockaddr_in));
1002 get_to_address(unistimsock, &s->sout);
1003 s->sout.sin_family = AF_INET;
1005 ast_verb(0, "Creating a new entry for the phone from %s received via server ip %s\n",
1006 ast_inet_ntoa(addr_from->sin_addr), ast_inet_ntoa(s->sout.sin_addr));
1008 ast_mutex_init(&s->lock);
1009 ast_mutex_lock(&sessionlock);
1013 s->timeout = get_tick_count() + RETRANSMIT_TIMER;
1014 s->state = STATE_INIT;
1015 s->tick_next_ping = get_tick_count() + unistim_keepalive;
1016 /* Initialize struct wsabuf */
1017 for (tmp = 0; tmp < MAX_BUF_NUMBER; tmp++) {
1018 s->wsabufsend[tmp].buf = s->buf[tmp];
1020 ast_mutex_unlock(&sessionlock);
1024 static void send_end_call(struct unistimsession *pte)
1028 ast_verb(0, "Sending end call\n");
1030 memcpy(buffsend + SIZE_HEADER, packet_send_end_call, sizeof(packet_send_end_call));
1031 send_client(SIZE_HEADER + sizeof(packet_send_end_call), buffsend, pte);
1034 static void set_ping_timer(struct unistimsession *pte)
1036 unsigned int tick = 0; /* XXX what is this for, anyways */
1038 pte->timeout = pte->tick_next_ping;
1039 DEBUG_TIMER("tick = %u next ping at %u tick\n", tick, pte->timeout);
1043 /* Checking if our send queue is empty,
1044 * if true, setting up a timer for keepalive */
1045 static void check_send_queue(struct unistimsession *pte)
1047 /* Check if our send queue contained only one element */
1048 if (pte->last_buf_available == 1) {
1050 ast_verb(6, "Our single packet was ACKed.\n");
1052 pte->last_buf_available--;
1053 set_ping_timer(pte);
1056 /* Check if this ACK catch up our latest packet */
1057 else if (pte->last_seq_ack + 1 == pte->seq_server + 1) {
1059 ast_verb(6, "Our send queue is completely ACKed.\n");
1061 pte->last_buf_available = 0; /* Purge the send queue */
1062 set_ping_timer(pte);
1066 ast_verb(6, "We still have packets in our send queue\n");
1071 static void send_start_timer(struct unistimsession *pte)
1075 ast_verb(0, "Sending start timer\n");
1077 memcpy(buffsend + SIZE_HEADER, packet_send_start_timer, sizeof(packet_send_start_timer));
1078 send_client(SIZE_HEADER + sizeof(packet_send_start_timer), buffsend, pte);
1081 static void send_stop_timer(struct unistimsession *pte)
1085 ast_verb(0, "Sending stop timer\n");
1087 memcpy(buffsend + SIZE_HEADER, packet_send_stop_timer, sizeof(packet_send_stop_timer));
1088 send_client(SIZE_HEADER + sizeof(packet_send_stop_timer), buffsend, pte);
1091 static void send_icon(unsigned char pos, unsigned char status, struct unistimsession *pte)
1095 ast_verb(0, "Sending icon pos %d with status 0x%.2x\n", pos, status);
1097 memcpy(buffsend + SIZE_HEADER, packet_send_icon, sizeof(packet_send_icon));
1099 buffsend[10] = status;
1100 send_client(SIZE_HEADER + sizeof(packet_send_icon), buffsend, pte);
1103 static void send_tone(struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
1108 ast_verb(0, "Sending Stream Based Tone Off\n");
1110 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_off,
1111 sizeof(packet_send_stream_based_tone_off));
1112 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_off), buffsend, pte);
1115 /* Since most of the world use a continuous tone, it's useless
1117 ast_verb(0, "Sending Stream Based Tone Cadence Download\n");
1118 memcpy (buffsend + SIZE_HEADER, packet_send_StreamBasedToneCad, sizeof (packet_send_StreamBasedToneCad));
1119 send_client (SIZE_HEADER + sizeof (packet_send_StreamBasedToneCad), buffsend, pte); */
1121 ast_verb(0, "Sending Stream Based Tone Frequency Component List Download %d %d\n", tone1, tone2);
1125 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_single_freq,
1126 sizeof(packet_send_stream_based_tone_single_freq));
1127 buffsend[10] = (tone1 & 0xff00) >> 8;
1128 buffsend[11] = (tone1 & 0x00ff);
1129 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_single_freq), buffsend,
1133 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dial_freq,
1134 sizeof(packet_send_stream_based_tone_dial_freq));
1135 buffsend[10] = (tone1 & 0xff00) >> 8;
1136 buffsend[11] = (tone1 & 0x00ff);
1137 buffsend[12] = (tone2 & 0xff00) >> 8;
1138 buffsend[13] = (tone2 & 0x00ff);
1139 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_dial_freq), buffsend,
1144 ast_verb(0, "Sending Stream Based Tone On\n");
1146 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_on,
1147 sizeof(packet_send_stream_based_tone_on));
1148 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_on), buffsend, pte);
1151 /* Positions for favorites
1152 |--------------------|
1153 | 5 2 | <-- not on screen in i2002
1158 /* status (icons) : 00 = nothing, 2x/3x = see parser.h, 4x/5x = blink fast, 6x/7x = blink slow */
1160 send_favorite(unsigned char pos, unsigned char status, struct unistimsession *pte,
1167 ast_verb(0, "Sending favorite pos %d with status 0x%.2x\n", pos, status);
1169 memcpy(buffsend + SIZE_HEADER, packet_send_favorite, sizeof(packet_send_favorite));
1172 buffsend[25] = status;
1173 i = strlen(ustmtext(text, pte));
1174 if (i > FAV_MAX_LENGTH) {
1177 memcpy(buffsend + FAV_MAX_LENGTH + 1, ustmtext(text, pte), i);
1178 send_client(SIZE_HEADER + sizeof(packet_send_favorite), buffsend, pte);
1181 static void send_favorite_short(unsigned char pos, unsigned char status, struct unistimsession *pte) {
1182 send_favorite(pos, status, pte, pte->device->softkeylabel[pos]);
1186 static void send_favorite_selected(unsigned char status, struct unistimsession *pte) {
1187 if (pte->device->selected != -1) {
1188 send_favorite(pte->device->selected, status, pte, pte->device->softkeylabel[pte->device->selected]);
1193 static int soft_key_visible(struct unistim_device* d, unsigned char num)
1195 if(d->height == 1 && num % 3 == 2) {
1201 static void refresh_all_favorite(struct unistimsession *pte)
1203 unsigned char i = 0;
1205 struct unistim_line *line;
1206 line = AST_LIST_FIRST(&pte->device->lines);
1209 ast_verb(0, "Refreshing all favorite\n");
1211 for (i = 0; i < FAVNUM; i++) {
1212 unsigned char status = pte->device->softkeyicon[i];
1214 if (!soft_key_visible(pte->device, i)) {
1217 if (!strcasecmp(pte->device->softkeylabel[i], "DND") && line) {
1218 if (!ast_db_get("DND", line->name, data, sizeof(data))) {
1219 status = FAV_ICON_SPEAKER_ONHOOK_WHITE;
1223 send_favorite_short(i, status, pte);
1227 static int is_key_favorite(struct unistim_device *d, int fav)
1229 if ((fav < 0) && (fav > 5)) {
1232 if (d->sline[fav]) {
1235 if (d->softkeynumber[fav][0] == '\0') {
1241 static int is_key_line(struct unistim_device *d, int fav)
1243 if ((fav < 0) && (fav > 5)) {
1246 if (!d->sline[fav]) {
1249 if (is_key_favorite(d, fav)) {
1255 static int get_active_softkey(struct unistimsession *pte)
1257 return pte->device->selected;
1260 static int get_avail_softkey(struct unistimsession *pte, const char* name)
1264 if (!is_key_line(pte->device, pte->device->selected)) {
1265 pte->device->selected = -1;
1267 for (i = 0; i < FAVNUM; i++) {
1268 if (pte->device->selected != -1 && pte->device->selected != i) {
1271 if (!soft_key_visible(pte->device, i)) {
1274 if (pte->device->ssub[i]) {
1277 if (is_key_line(pte->device, i)) {
1278 if (name && strcmp(name, pte->device->sline[i]->name)) {
1282 ast_verb(0, "Found softkey %d for device %s\n", i, name);
1291 /* Change the status for this phone (pte) and update for each phones where pte is bookmarked
1292 * use FAV_ICON_*_BLACK constant in status parameters */
1293 static void change_favorite_icon(struct unistimsession *pte, unsigned char status)
1295 struct unistim_device *d = devices;
1297 /* Update the current phone line softkey icon */
1298 if (pte->state != STATE_CLEANING) {
1299 int softkeylinepos = get_active_softkey(pte);
1300 if (softkeylinepos != -1) {
1301 send_favorite_short(softkeylinepos, status, pte);
1304 /* Notify other phones if we're in their bookmark */
1306 for (i = 0; i < FAVNUM; i++) {
1307 if (d->sp[i] == pte->device) { /* It's us ? */
1308 if (d->softkeyicon[i] != status) { /* Avoid resending the same icon */
1309 d->softkeyicon[i] = status;
1311 send_favorite(i, status + 1, d->session, d->softkeylabel[i]);
1320 static int register_extension(const struct unistimsession *pte)
1322 struct unistim_line *line;
1323 line = AST_LIST_FIRST(&pte->device->lines);
1325 ast_verb(0, "Trying to register extension '%s' into context '%s' to %s\n",
1326 pte->device->extension_number, pte->device->context,
1329 return ast_add_extension(pte->device->context, 0,
1330 pte->device->extension_number, 1, NULL, NULL, "Dial",
1331 line->fullname, 0, "Unistim");
1334 static int unregister_extension(const struct unistimsession *pte)
1337 ast_verb(0, "Trying to unregister extension '%s' context '%s'\n",
1338 pte->device->extension_number, pte->device->context);
1340 return ast_context_remove_extension(pte->device->context,
1341 pte->device->extension_number, 1, "Unistim");
1344 /* Free memory allocated for a phone */
1345 static void close_client(struct unistimsession *s)
1347 struct unistim_subchannel *sub = NULL;
1348 struct unistimsession *cur, *prev = NULL;
1349 ast_mutex_lock(&sessionlock);
1351 /* Looking for the session in the linked chain */
1359 if (cur) { /* Session found ? */
1360 if (cur->device) { /* This session was registered ? */
1361 s->state = STATE_CLEANING;
1363 ast_verb(0, "close_client session %p device %p\n", s, s->device);
1365 change_favorite_icon(s, FAV_ICON_NONE);
1366 ast_mutex_lock(&s->device->lock);
1367 AST_LIST_LOCK(&s->device->subs);
1368 AST_LIST_TRAVERSE_SAFE_BEGIN(&s->device->subs, sub, list) {
1372 if (sub->owner) { /* Call in progress ? */
1374 ast_verb(0, "Aborting call\n");
1376 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NETWORK_OUT_OF_ORDER);
1379 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->subtype, sub->parent->name, s->device->name);
1381 AST_LIST_REMOVE_CURRENT(list);
1382 unistim_free_sub(sub);
1385 AST_LIST_TRAVERSE_SAFE_END;
1386 AST_LIST_UNLOCK(&s->device->subs);
1388 if (!ast_strlen_zero(s->device->extension_number)) {
1389 unregister_extension(s);
1391 cur->device->session = NULL;
1392 ast_mutex_unlock(&s->device->lock);
1395 ast_verb(0, "Freeing an unregistered client\n");
1399 prev->next = cur->next;
1401 sessions = cur->next;
1403 ast_mutex_destroy(&s->lock);
1406 ast_log(LOG_WARNING, "Trying to delete non-existent session %p?\n", s);
1408 ast_mutex_unlock(&sessionlock);
1412 /* Return 1 if the session chained link was modified */
1413 static int send_retransmit(struct unistimsession *pte)
1417 ast_mutex_lock(&pte->lock);
1418 if (++pte->nb_retransmit >= NB_MAX_RETRANSMIT) {
1420 ast_verb(0, "Too many retransmit - freeing client\n");
1422 ast_mutex_unlock(&pte->lock);
1426 pte->timeout = get_tick_count() + RETRANSMIT_TIMER;
1428 for (i = pte->last_buf_available - (pte->seq_server - pte->last_seq_ack);
1429 i < pte->last_buf_available; i++) {
1431 ast_log(LOG_WARNING,
1432 "Asked to retransmit an ACKed slot ! last_buf_available=%d, seq_server = #0x%.4x last_seq_ack = #0x%.4x\n",
1433 pte->last_buf_available, pte->seq_server, pte->last_seq_ack);
1438 unsigned short *sbuf = (unsigned short *) pte->wsabufsend[i].buf;
1441 seq = ntohs(sbuf[1]);
1442 ast_verb(0, "Retransmit slot #%d (seq=#0x%.4x), last ack was #0x%.4x\n", i,
1443 seq, pte->last_seq_ack);
1445 send_raw_client(pte->wsabufsend[i].len, pte->wsabufsend[i].buf, &pte->sin,
1448 ast_mutex_unlock(&pte->lock);
1452 /* inverse : TEXT_INVERSE : yes, TEXT_NORMAL : no */
1454 send_text(unsigned char pos, unsigned char inverse, struct unistimsession *pte,
1460 ast_log(LOG_ERROR, "Asked to display NULL text (pos %d, inverse flag %d)\n", pos, inverse);
1463 if (pte->device && pte->device->height == 1 && pos != TEXT_LINE0) {
1467 ast_verb(0, "Sending text at pos %d, inverse flag %d\n", pos, inverse);
1469 memcpy(buffsend + SIZE_HEADER, packet_send_text, sizeof(packet_send_text));
1471 buffsend[11] = inverse;
1473 if (i > TEXT_LENGTH_MAX) {
1474 i = TEXT_LENGTH_MAX;
1476 memcpy(buffsend + 12, text, i);
1477 send_client(SIZE_HEADER + sizeof(packet_send_text), buffsend, pte);
1480 static void send_text_status(struct unistimsession *pte, const char *text)
1485 ast_verb(0, "Sending status text\n");
1488 if (pte->device->status_method == 1) { /* For new firmware and i2050 soft phone */
1489 int n = strlen(text);
1490 /* Must send individual button separately */
1492 for (i = 0, j = 0; i < 4; i++, j += 7) {
1493 int pos = 0x08 + (i * 0x20);
1494 memcpy(buffsend + SIZE_HEADER, packet_send_status2,
1495 sizeof(packet_send_status2));
1498 memcpy(buffsend + 10, (j < n) ? (text + j) : " ", 7);
1499 send_client(SIZE_HEADER + sizeof(packet_send_status2), buffsend, pte);
1506 memcpy(buffsend + SIZE_HEADER, packet_send_status, sizeof(packet_send_status));
1508 if (i > STATUS_LENGTH_MAX) {
1509 i = STATUS_LENGTH_MAX;
1511 memcpy(buffsend + 10, text, i);
1512 send_client(SIZE_HEADER + sizeof(packet_send_status), buffsend, pte);
1516 /* led values in hexa : 0 = bar off, 1 = bar on, 2 = bar 1s on/1s off, 3 = bar 2.5s on/0.5s off
1517 * 4 = bar 0.6s on/0.3s off, 5 = bar 0.5s on/0.5s off, 6 = bar 2s on/0.5s off
1518 * 7 = bar off, 8 = speaker off, 9 = speaker on, 10 = headphone off, 11 = headphone on
1519 * 18 = mute off, 19 mute on */
1520 static void send_led_update(struct unistimsession *pte, unsigned char led)
1524 ast_verb(0, "Sending led_update (%x)\n", led);
1526 memcpy(buffsend + SIZE_HEADER, packet_send_led_update, sizeof(packet_send_led_update));
1528 send_client(SIZE_HEADER + sizeof(packet_send_led_update), buffsend, pte);
1531 /* output = OUTPUT_HANDSET, OUTPUT_HEADPHONE or OUTPUT_SPEAKER
1532 * volume = VOLUME_LOW, VOLUME_NORMAL, VOLUME_INSANELY_LOUD
1533 * mute = MUTE_OFF, MUTE_ON */
1535 send_select_output(struct unistimsession *pte, unsigned char output, unsigned char volume,
1540 ast_verb(0, "Sending select output packet output=%x volume=%x mute=%x\n", output,
1543 memcpy(buffsend + SIZE_HEADER, packet_send_select_output,
1544 sizeof(packet_send_select_output));
1545 buffsend[9] = output;
1546 if (output == OUTPUT_SPEAKER) {
1547 volume = VOLUME_LOW_SPEAKER;
1549 volume = VOLUME_LOW;
1551 buffsend[10] = volume;
1552 if (mute == MUTE_ON_DISCRET) {
1553 buffsend[11] = MUTE_ON;
1555 buffsend[11] = mute;
1557 send_client(SIZE_HEADER + sizeof(packet_send_select_output), buffsend, pte);
1558 if (mute == MUTE_OFF) {
1559 send_led_update(pte, 0x18);
1560 } else if (mute == MUTE_ON) {
1561 send_led_update(pte, 0x19);
1563 pte->device->mute = mute;
1564 if (output == OUTPUT_HANDSET) {
1565 if (mute == MUTE_ON) {
1566 change_favorite_icon(pte, FAV_ICON_ONHOLD_BLACK);
1568 change_favorite_icon(pte, FAV_ICON_OFFHOOK_BLACK);
1570 send_led_update(pte, 0x08);
1571 send_led_update(pte, 0x10);
1572 } else if (output == OUTPUT_HEADPHONE) {
1573 if (mute == MUTE_ON) {
1574 change_favorite_icon(pte, FAV_ICON_HEADPHONES_ONHOLD);
1576 change_favorite_icon(pte, FAV_ICON_HEADPHONES);
1578 send_led_update(pte, 0x08);
1579 send_led_update(pte, 0x11);
1580 } else if (output == OUTPUT_SPEAKER) {
1581 send_led_update(pte, 0x10);
1582 send_led_update(pte, 0x09);
1583 if (pte->device->receiver_state == STATE_OFFHOOK) {
1584 if (mute == MUTE_ON) {
1585 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1587 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOOK_BLACK);
1590 if (mute == MUTE_ON) {
1591 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1593 change_favorite_icon(pte, FAV_ICON_SPEAKER_OFFHOOK_BLACK);
1597 ast_log(LOG_WARNING, "Invalid output (%d)\n", output);
1599 if (output != pte->device->output) {
1600 pte->device->previous_output = pte->device->output;
1602 pte->device->output = output;
1605 static void send_ring(struct unistimsession *pte, char volume, char style)
1609 ast_verb(0, "Sending ring packet\n");
1611 memcpy(buffsend + SIZE_HEADER, packet_send_ring, sizeof(packet_send_ring));
1612 buffsend[24] = style + 0x10;
1613 buffsend[29] = volume * 0x10;
1614 send_client(SIZE_HEADER + sizeof(packet_send_ring), buffsend, pte);
1617 static void send_no_ring(struct unistimsession *pte)
1621 ast_verb(0, "Sending no ring packet\n");
1623 memcpy(buffsend + SIZE_HEADER, packet_send_no_ring, sizeof(packet_send_no_ring));
1624 send_client(SIZE_HEADER + sizeof(packet_send_no_ring), buffsend, pte);
1627 static void send_texttitle(struct unistimsession *pte, const char *text)
1632 ast_verb(0, "Sending title text\n");
1634 memcpy(buffsend + SIZE_HEADER, packet_send_title, sizeof(packet_send_title));
1639 memcpy(buffsend + 10, text, i);
1640 send_client(SIZE_HEADER + sizeof(packet_send_title), buffsend, pte);
1644 static void send_idle_clock(struct unistimsession *pte)
1646 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
1649 static void send_date_time(struct unistimsession *pte)
1652 struct timeval now = ast_tvnow();
1653 struct ast_tm atm = { 0, };
1656 ast_verb(0, "Sending Time & Date\n");
1658 memcpy(buffsend + SIZE_HEADER, packet_send_date_time, sizeof(packet_send_date_time));
1659 ast_localtime(&now, &atm, NULL);
1660 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1661 buffsend[11] = (unsigned char) atm.tm_mday;
1662 buffsend[12] = (unsigned char) atm.tm_hour;
1663 buffsend[13] = (unsigned char) atm.tm_min;
1664 send_client(SIZE_HEADER + sizeof(packet_send_date_time), buffsend, pte);
1667 static void send_date_time2(struct unistimsession *pte)
1670 struct timeval now = ast_tvnow();
1671 struct ast_tm atm = { 0, };
1674 ast_verb(0, "Sending Time & Date #2\n");
1676 memcpy(buffsend + SIZE_HEADER, packet_send_date_time2, sizeof(packet_send_date_time2));
1677 ast_localtime(&now, &atm, NULL);
1679 buffsend[9] = pte->device->datetimeformat;
1683 buffsend[14] = (unsigned char) atm.tm_mon + 1;
1684 buffsend[15] = (unsigned char) atm.tm_mday;
1685 buffsend[16] = (unsigned char) atm.tm_hour;
1686 buffsend[17] = (unsigned char) atm.tm_min;
1687 send_client(SIZE_HEADER + sizeof(packet_send_date_time2), buffsend, pte);
1690 static void send_date_time3(struct unistimsession *pte)
1693 struct timeval now = ast_tvnow();
1694 struct ast_tm atm = { 0, };
1697 ast_verb(0, "Sending Time & Date #3\n");
1699 memcpy(buffsend + SIZE_HEADER, packet_send_date_time3, sizeof(packet_send_date_time3));
1700 ast_localtime(&now, &atm, NULL);
1701 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1702 buffsend[11] = (unsigned char) atm.tm_mday;
1703 buffsend[12] = (unsigned char) atm.tm_hour;
1704 buffsend[13] = (unsigned char) atm.tm_min;
1705 send_client(SIZE_HEADER + sizeof(packet_send_date_time3), buffsend, pte);
1708 static void send_blink_cursor(struct unistimsession *pte)
1712 ast_verb(0, "Sending set blink\n");
1714 memcpy(buffsend + SIZE_HEADER, packet_send_blink_cursor, sizeof(packet_send_blink_cursor));
1715 send_client(SIZE_HEADER + sizeof(packet_send_blink_cursor), buffsend, pte);
1719 /* pos : 0xab (a=0/2/4 = line ; b = row) */
1720 static void send_cursor_pos(struct unistimsession *pte, unsigned char pos)
1724 ast_verb(0, "Sending set cursor position\n");
1726 memcpy(buffsend + SIZE_HEADER, packet_send_set_pos_cursor,
1727 sizeof(packet_send_set_pos_cursor));
1729 send_client(SIZE_HEADER + sizeof(packet_send_set_pos_cursor), buffsend, pte);
1733 static void send_charset_update(struct unistimsession *pte, int charset)
1735 const unsigned char* packet_send_charset;
1739 ast_verb(0, "Sending set default charset\n");
1741 if (charset == LANG_DEFAULT) {
1742 charset = options_languages[find_language(pte->device->language)].encoding;
1746 packet_send_charset = packet_send_charset_iso_8859_2;
1747 packet_size = sizeof(packet_send_charset_iso_8859_2);
1750 packet_send_charset = packet_send_charset_iso_8859_4;
1751 packet_size = sizeof(packet_send_charset_iso_8859_4);
1754 packet_send_charset = packet_send_charset_iso_8859_5;
1755 packet_size = sizeof(packet_send_charset_iso_8859_5);
1758 packet_send_charset = packet_send_charset_iso_2022_jp;
1759 packet_size = sizeof(packet_send_charset_iso_2022_jp);
1763 packet_send_charset = packet_send_charset_iso_8859_1;
1764 packet_size = sizeof(packet_send_charset_iso_8859_1);
1766 memcpy(buffsend + SIZE_HEADER, packet_send_charset, packet_size);
1767 send_client(SIZE_HEADER + packet_size, buffsend, pte);
1771 static void rcv_resume_connection_with_server(struct unistimsession *pte)
1775 ast_verb(0, "ResumeConnectionWithServer received\n");
1776 ast_verb(0, "Sending packet_send_query_mac_address\n");
1778 memcpy(buffsend + SIZE_HEADER, packet_send_query_mac_address,
1779 sizeof(packet_send_query_mac_address));
1780 send_client(SIZE_HEADER + sizeof(packet_send_query_mac_address), buffsend, pte);
1784 static int unistim_register(struct unistimsession *s)
1786 struct unistim_device *d;
1788 ast_mutex_lock(&devicelock);
1791 if (!strcasecmp(s->macaddr, d->id)) {
1792 /* XXX Deal with IP authentication */
1795 d->codec_number = DEFAULT_CODEC;
1797 d->receiver_state = STATE_ONHOOK;
1802 ast_mutex_unlock(&devicelock);
1811 static void unistim_line_copy(struct unistim_line *dst, struct unistim_line *src)
1813 struct ast_format_cap *tmp = src->cap;
1814 memcpy(dst, src, sizeof(*dst)); /* this over writes the cap ptr, so we have to reset it */
1816 ast_format_cap_copy(src->cap, dst->cap);
1819 static struct unistim_line *unistim_line_destroy(struct unistim_line *l)
1824 l->cap = ast_format_cap_destroy(l->cap);
1829 static struct unistim_line *unistim_line_alloc(void)
1831 struct unistim_line *l;
1832 if (!(l = ast_calloc(1, sizeof(*l)))) {
1836 if (!(l->cap = ast_format_cap_alloc_nolock())) {
1843 static int unistim_free_sub(struct unistim_subchannel *sub) {
1845 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->subtype, sub->parent->name, sub->parent->parent->name);
1847 ast_mutex_destroy(&sub->lock);
1852 static struct unistim_subchannel *unistim_alloc_sub(struct unistim_device *d, int x)
1854 struct unistim_subchannel *sub;
1855 if (!(sub = ast_calloc(1, sizeof(*sub)))) {
1860 ast_verb(3, "Allocating UNISTIM subchannel #%d on %s ptr=%p\n", x, d->name, sub);
1862 sub->ss_thread = AST_PTHREADT_NULL;
1864 AST_LIST_LOCK(&d->subs);
1865 AST_LIST_INSERT_TAIL(&d->subs, sub, list);
1866 AST_LIST_UNLOCK(&d->subs);
1867 ast_mutex_init(&sub->lock);
1871 static int unistim_unalloc_sub(struct unistim_device *d, struct unistim_subchannel *sub)
1873 struct unistim_subchannel *s;
1875 AST_LIST_LOCK(&d->subs);
1876 AST_LIST_TRAVERSE_SAFE_BEGIN(&d->subs, s, list) {
1883 AST_LIST_REMOVE_CURRENT(list);
1884 unistim_free_sub(sub);
1886 AST_LIST_TRAVERSE_SAFE_END;
1887 AST_LIST_UNLOCK(&d->subs);
1891 static const char *subtype_tostr(const int type)
1906 static const char *ptestate_tostr(const int type)
1911 case STATE_AUTHDENY:
1913 case STATE_MAINPAGE:
1915 case STATE_EXTENSION:
1917 case STATE_DIALPAGE:
1923 case STATE_SELECTOPTION:
1924 return "SELECTOPTION";
1925 case STATE_SELECTCODEC:
1926 return "SELECTCODEC";
1927 case STATE_SELECTLANGUAGE:
1928 return "SELECTLANGUAGE";
1929 case STATE_CLEANING:
1937 static void rcv_mac_addr(struct unistimsession *pte, const unsigned char *buf)
1943 for (tmp = 15; tmp < 15 + SIZE_HEADER; tmp++) {
1944 sprintf(&addrmac[i], "%.2x", (unsigned char) buf[tmp]);
1948 ast_verb(0, "MAC Address received: %s\n", addrmac);
1950 strcpy(pte->macaddr, addrmac);
1951 res = unistim_register(pte);
1953 switch (autoprovisioning) {
1954 case AUTOPROVISIONING_NO:
1955 ast_log(LOG_WARNING, "No entry found for this phone : %s\n", addrmac);
1956 pte->state = STATE_AUTHDENY;
1958 case AUTOPROVISIONING_YES:
1960 struct unistim_device *d = NULL, *newd = NULL;
1961 struct unistim_line *newl = NULL, *l = NULL;
1963 ast_verb(0, "New phone, autoprovisioning on\n");
1965 /* First : locate the [template] section */
1966 ast_mutex_lock(&devicelock);
1969 if (strcasecmp(d->name, "template")) {
1973 /* Found, cloning this entry */
1974 if (!(newd = ast_malloc(sizeof(*newd)))) {
1975 ast_mutex_unlock(&devicelock);
1978 memcpy(newd, d, sizeof(*newd));
1979 ast_mutex_init(&newd->lock);
1980 newd->lines.first = NULL;
1981 newd->lines.last = NULL;
1982 AST_LIST_LOCK(&d->lines);
1983 AST_LIST_TRAVERSE(&d->lines, l, list) {
1984 if (!(newl = unistim_line_alloc())) {
1987 unistim_line_copy(l, newl);
1988 newl->parent = newd;
1989 ast_copy_string(newl->name, l->name, sizeof(newl->name));
1990 snprintf(newl->fullname, sizeof(newl->fullname), "USTM/%s@%s",
1991 newl->name, newd->name);
1992 snprintf(l->name, sizeof(l->name), "%d", atoi(l->name) + 1);
1994 AST_LIST_LOCK(&newd->lines);
1995 AST_LIST_INSERT_TAIL(&newd->lines, newl, list);
1996 AST_LIST_UNLOCK(&newd->lines);
1998 AST_LIST_UNLOCK(&d->lines);
2001 ast_mutex_unlock(&devicelock);
2004 /* Ok, now updating some fields */
2005 ast_copy_string(newd->id, addrmac, sizeof(newd->id));
2006 ast_copy_string(newd->name, addrmac, sizeof(newd->name));
2007 if (newd->extension == EXTENSION_NONE) {
2008 newd->extension = EXTENSION_ASK;
2011 newd->receiver_state = STATE_ONHOOK;
2012 newd->session = pte;
2013 newd->language[0] = '\0';
2014 newd->to_delete = -1;
2018 /* Go to the end of the linked chain */
2026 ast_mutex_unlock(&devicelock);
2028 ast_log(LOG_WARNING, "No entry [template] found in unistim.conf\n");
2029 pte->state = STATE_AUTHDENY;
2033 case AUTOPROVISIONING_TN:
2034 pte->state = STATE_AUTHDENY;
2037 ast_log(LOG_WARNING, "Internal error : unknown autoprovisioning value = %d\n",
2041 if (pte->state != STATE_AUTHDENY) {
2042 struct unistim_line *line;
2043 struct unistim_subchannel *sub;
2045 ast_verb(3, "Device '%s' successfuly registered\n", pte->device->name);
2047 AST_LIST_LOCK(&pte->device->subs);
2048 AST_LIST_TRAVERSE_SAFE_BEGIN(&pte->device->subs, sub, list) {
2050 ast_log(LOG_ERROR, "Subchannel lost sice reboot. Hanged channel may apear!\n");
2051 AST_LIST_REMOVE_CURRENT(list);
2055 AST_LIST_TRAVERSE_SAFE_END;
2056 AST_LIST_UNLOCK(&pte->device->subs);
2058 switch (pte->device->extension) {
2059 case EXTENSION_NONE:
2060 pte->state = STATE_MAINPAGE;
2063 /* Checking if we already have an extension number */
2064 if (ast_strlen_zero(pte->device->extension_number)) {
2065 pte->state = STATE_EXTENSION;
2067 /* Yes, because of a phone reboot. We don't ask again for the TN */
2068 if (register_extension(pte)) {
2069 pte->state = STATE_EXTENSION;
2071 pte->state = STATE_MAINPAGE;
2075 case EXTENSION_LINE:
2076 line = AST_LIST_FIRST(&pte->device->lines);
2077 ast_copy_string(pte->device->extension_number, line->name,
2078 sizeof(pte->device->extension_number));
2079 if (register_extension(pte)) {
2080 pte->state = STATE_EXTENSION;
2082 pte->state = STATE_MAINPAGE;
2086 /* If we are here, it's because of a phone reboot */
2087 pte->state = STATE_MAINPAGE;
2090 ast_log(LOG_WARNING, "Internal error, extension value unknown : %d\n",
2091 pte->device->extension);
2092 pte->state = STATE_AUTHDENY;
2096 if (pte->state == STATE_EXTENSION) {
2097 if (pte->device->extension != EXTENSION_TN) {
2098 pte->device->extension = EXTENSION_ASK;
2100 pte->device->extension_number[0] = '\0';
2103 ast_verb(0, "\nSending S1\n");
2105 memcpy(buffsend + SIZE_HEADER, packet_send_S1, sizeof(packet_send_S1));
2106 send_client(SIZE_HEADER + sizeof(packet_send_S1), buffsend, pte);
2109 ast_verb(0, "Sending query_basic_manager_04\n");
2111 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_04,
2112 sizeof(packet_send_query_basic_manager_04));
2113 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_04), buffsend, pte);
2116 ast_verb(0, "Sending query_basic_manager_10\n");
2118 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_10,
2119 sizeof(packet_send_query_basic_manager_10));
2120 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_10), buffsend, pte);
2122 send_date_time(pte);
2126 static int write_entry_history(struct unistimsession *pte, FILE * f, char c, char *line1)
2128 if (fwrite(&c, 1, 1, f) != 1) {
2129 display_last_error("Unable to write history log header.");
2132 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
2133 display_last_error("Unable to write history entry - date.");
2136 if (fwrite(pte->device->lst_cid, TEXT_LENGTH_MAX, 1, f) != 1) {
2137 display_last_error("Unable to write history entry - callerid.");
2140 if (fwrite(pte->device->lst_cnm, TEXT_LENGTH_MAX, 1, f) != 1) {
2141 display_last_error("Unable to write history entry - callername.");
2147 static int write_history(struct unistimsession *pte, char way, char ismissed)
2149 char tmp[AST_CONFIG_MAX_PATH], tmp2[AST_CONFIG_MAX_PATH];
2150 char line1[TEXT_LENGTH_MAX + 1];
2151 char count = 0, *histbuf;
2154 struct timeval now = ast_tvnow();
2155 struct ast_tm atm = { 0, };
2160 if (!pte->device->callhistory) {
2163 if (strchr(pte->device->name, '/') || (pte->device->name[0] == '.')) {
2164 ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n",
2169 snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_LOG_DIR, USTM_LOG_DIR);
2170 if (ast_mkdir(tmp, 0770)) {
2171 ast_log(LOG_WARNING, "Unable to create directory for history");
2175 ast_localtime(&now, &atm, NULL);
2178 ast_copy_string(tmp2, ustmtext("Miss", pte), sizeof(tmp2));
2180 ast_copy_string(tmp2, ustmtext("Fail", pte), sizeof(tmp2));
2183 ast_copy_string(tmp2, ustmtext("Answ", pte), sizeof(tmp2));
2185 snprintf(line1, sizeof(line1), "%04d/%02d/%02d %02d:%02d:%02d %s",
2186 atm.tm_year + 1900, atm.tm_mon + 1, atm.tm_mday, atm.tm_hour,
2187 atm.tm_min, atm.tm_sec, tmp2);
2189 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
2190 USTM_LOG_DIR, pte->device->name, way);
2191 if ((f = fopen(tmp, "r"))) {
2192 struct stat bufstat;
2194 if (stat(tmp, &bufstat)) {
2195 display_last_error("Unable to stat history log.");
2199 size = 1 + (MAX_ENTRY_LOG * TEXT_LENGTH_MAX * 3);
2200 if (bufstat.st_size != size) {
2201 ast_log(LOG_WARNING,
2202 "History file %s has an incorrect size (%d instead of %d). It will be replaced by a new one.",
2203 tmp, (int) bufstat.st_size, size);
2210 /* If we can't open the log file, we create a brand new one */
2215 if ((errno != ENOENT) && (count == 0)) {
2216 display_last_error("Unable to open history log.");
2219 f = fopen(tmp, "w");
2221 display_last_error("Unable to create history log.");
2224 if (write_entry_history(pte, f, c, line1)) {
2228 memset(line1, ' ', TEXT_LENGTH_MAX);
2229 for (i = 3; i < MAX_ENTRY_LOG * 3; i++) {
2230 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
2231 display_last_error("Unable to write history entry - stuffing.");
2237 display_last_error("Unable to close history - creation.");
2241 /* We can open the log file, we create a temporary one, we add our entry and copy the rest */
2242 if (fread(&count, 1, 1, f) != 1) {
2243 display_last_error("Unable to read history header.");
2247 if (count > MAX_ENTRY_LOG) {
2248 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
2249 count, MAX_ENTRY_LOG);
2253 snprintf(tmp2, sizeof(tmp2), "%s/%s/%s-%c.csv.tmp", ast_config_AST_LOG_DIR,
2254 USTM_LOG_DIR, pte->device->name, way);
2255 if (!(f2 = fopen(tmp2, "w"))) {
2256 display_last_error("Unable to create temporary history log.");
2261 if (++count > MAX_ENTRY_LOG) {
2262 count = MAX_ENTRY_LOG;
2264 if (write_entry_history(pte, f2, count, line1)) {
2269 size = (MAX_ENTRY_LOG - 1) * TEXT_LENGTH_MAX * 3;
2270 if (!(histbuf = ast_malloc(size))) {
2276 if (fread(histbuf, size, 1, f) != 1) {
2280 display_last_error("Unable to read previous history entries.");
2283 if (fwrite(histbuf, size, 1, f2) != 1) {
2287 display_last_error("Unable to write previous history entries.");
2292 display_last_error("Unable to close history log.");
2295 display_last_error("Unable to close temporary history log.");
2298 display_last_error("Unable to remove old history log.");
2300 if (rename(tmp2, tmp)) {
2301 display_last_error("Unable to rename new history log.");
2306 static void unistim_quiet_chan(struct ast_channel *chan)
2308 if (chan && ast_channel_state(chan) == AST_STATE_UP) {
2309 if (ast_test_flag(chan, AST_FLAG_MOH)) {
2311 } else if (ast_channel_generatordata(chan)) {
2312 ast_deactivate_generator(chan);
2317 static int attempt_transfer(struct unistim_subchannel *p1, struct unistim_subchannel *p2)
2321 *chana = NULL, *chanb = NULL, *bridgea = NULL, *bridgeb = NULL, *peera =
2322 NULL, *peerb = NULL, *peerc = NULL, *peerd = NULL;
2324 if (!p1->owner || !p2->owner) {
2325 ast_log(LOG_WARNING, "Transfer attempted without dual ownership?\n");
2330 bridgea = ast_bridged_channel(chana);
2331 bridgeb = ast_bridged_channel(chanb);
2338 } else if (bridgeb) {
2345 if (peera && peerb && peerc && (peerb != peerc)) {
2346 unistim_quiet_chan(peera);
2347 unistim_quiet_chan(peerb);
2348 unistim_quiet_chan(peerc);
2350 unistim_quiet_chan(peerd);
2353 if (ast_channel_cdr(peera) && ast_channel_cdr(peerb)) {
2354 ast_channel_cdr_set(peerb, ast_cdr_append(ast_channel_cdr(peerb), ast_channel_cdr(peera)));
2355 } else if (ast_channel_cdr(peera)) {
2356 ast_channel_cdr_set(peerb, ast_channel_cdr(peera));
2358 ast_channel_cdr_set(peera, NULL);
2360 if (ast_channel_cdr(peerb) && ast_channel_cdr(peerc)) {
2361 ast_channel_cdr_set(peerb, ast_cdr_append(ast_channel_cdr(peerb), ast_channel_cdr(peerc)));
2362 } else if (ast_channel_cdr(peerc)) {
2363 ast_channel_cdr_set(peerb, ast_channel_cdr(peerc));
2365 ast_channel_cdr_set(peerc, NULL);
2367 ast_log(LOG_NOTICE, "UNISTIM transfer: trying to masquerade %s into %s\n", ast_channel_name(peerc), ast_channel_name(peerb));
2368 if (ast_channel_masquerade(peerb, peerc)) {
2369 ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", ast_channel_name(peerb),
2370 ast_channel_name(peerc));
2376 "Transfer attempted with no appropriate bridged calls to transfer\n");
2378 ast_softhangup_nolock(chana, AST_SOFTHANGUP_DEV);
2381 ast_softhangup_nolock(chanb, AST_SOFTHANGUP_DEV);
2388 void change_callerid(struct unistimsession *pte, int type, char *callerid)
2394 data = pte->device->lst_cnm;
2396 data = pte->device->lst_cid;
2399 /* This is very nearly strncpy(), except that the remaining buffer
2400 * is padded with ' ', instead of '\0' */
2401 memset(data, ' ', TEXT_LENGTH_MAX);
2402 size = strlen(callerid);
2403 if (size > TEXT_LENGTH_MAX) {
2404 size = TEXT_LENGTH_MAX;
2406 memcpy(data, callerid, size);
2409 static struct unistim_subchannel* get_sub(struct unistim_device *device, int type)
2411 struct unistim_subchannel *sub = NULL;
2413 AST_LIST_LOCK(&device->subs);
2414 AST_LIST_TRAVERSE(&device->subs, sub, list) {
2418 if (sub->subtype == type) {
2422 AST_LIST_UNLOCK(&device->subs);
2427 static void sub_start_silence(struct unistimsession *pte, struct unistim_subchannel *sub)
2429 /* Silence our channel */
2430 if (!pte->device->silence_generator) {
2431 pte->device->silence_generator =
2432 ast_channel_start_silence_generator(sub->owner);
2433 if (pte->device->silence_generator == NULL) {
2434 ast_log(LOG_WARNING, "Unable to start a silence generator.\n");
2435 } else if (unistimdebug) {
2436 ast_verb(0, "Starting silence generator\n");
2442 static void sub_stop_silence(struct unistimsession *pte, struct unistim_subchannel *sub)
2444 /* Stop the silence generator */
2445 if (pte->device->silence_generator) {
2447 ast_verb(0, "Stopping silence generator\n");
2450 ast_channel_stop_silence_generator(sub->owner, pte->device->silence_generator);
2452 ast_log(LOG_WARNING, "Trying to stop silence generator on a null channel!\n");
2454 pte->device->silence_generator = NULL;
2458 static void sub_hold(struct unistimsession *pte, struct unistim_subchannel *sub)
2464 sub->subtype = SUB_ONHOLD;
2465 send_favorite_short(sub->softkey, FAV_ICON_ONHOLD_BLACK + FAV_BLINK_SLOW, pte);
2466 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
2467 send_stop_timer(pte);
2469 ast_queue_control_data(sub->owner, AST_CONTROL_HOLD, NULL, 0);
2475 static void sub_unhold(struct unistimsession *pte, struct unistim_subchannel *sub)
2477 struct unistim_subchannel *sub_real;
2479 sub_real = get_sub(pte->device, SUB_REAL);
2481 sub_hold(pte, sub_real);
2485 sub->subtype = SUB_REAL;
2486 send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, pte);
2487 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2488 send_start_timer(pte);
2490 ast_queue_control_data(sub->owner, AST_CONTROL_UNHOLD, NULL, 0);
2492 send_start_rtp(sub);
2498 static void close_call(struct unistimsession *pte)
2500 struct unistim_subchannel *sub, *sub_transf;
2502 sub = get_sub(pte->device, SUB_REAL);
2503 sub_transf = get_sub(pte->device, SUB_THREEWAY);
2504 send_stop_timer(pte);
2506 ast_log(LOG_WARNING, "Close call without sub\n");
2509 send_favorite_short(sub->softkey, FAV_LINE_ICON, pte);
2511 sub->alreadygone = 1;
2513 sub_transf->alreadygone = 1;
2514 if (attempt_transfer(sub, sub_transf) < 0) {
2515 ast_verb(0, "attempt_transfer failed.\n");
2518 ast_queue_hangup(sub->owner);
2522 if (sub_transf->owner) {
2523 ast_queue_hangup_with_cause(sub_transf->owner, AST_CAUSE_NORMAL_CLEARING);
2525 ast_log(LOG_WARNING, "threeway sub without owner\n");
2528 ast_verb(0, "USTM(%s@%s-%d) channel already destroyed\n", sub->parent->name,
2529 pte->device->name, sub->softkey);
2532 change_callerid(pte, 0, pte->device->redial_number);
2533 change_callerid(pte, 1, "");
2534 write_history(pte, 'o', pte->device->missed_call);
2535 pte->device->missed_call = 0;
2536 show_main_page(pte);
2540 static void ignore_call(struct unistimsession *pte)
2546 static void discard_call(struct unistimsession *pte)
2548 struct unistim_subchannel* sub;
2549 sub = get_sub(pte->device, SUB_RING);
2554 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NORMAL_CLEARING);
2558 static void *unistim_ss(void *data)
2560 struct ast_channel *chan = data;
2561 struct unistim_subchannel *sub = ast_channel_tech_pvt(chan);
2562 struct unistim_line *l = sub->parent;
2563 struct unistimsession *s = l->parent->session;
2566 ast_verb(3, "Starting switch on '%s@%s-%d' to %s\n", l->name, l->parent->name, sub->softkey, s->device->phone_number);
2567 ast_channel_exten_set(chan, s->device->phone_number);
2568 ast_copy_string(s->device->redial_number, s->device->phone_number,
2569 sizeof(s->device->redial_number));
2570 ast_setstate(chan, AST_STATE_RING);
2571 res = ast_pbx_run(chan);
2573 ast_log(LOG_WARNING, "PBX exited non-zero\n");
2574 send_tone(s, 1000, 0);
2579 static int find_rtp_port(struct unistim_subchannel *s)
2581 struct unistim_subchannel *sub = NULL;
2582 int rtp_start = s->parent->parent->rtp_port;
2583 struct ast_sockaddr us_tmp;
2584 struct sockaddr_in us = { 0, };
2586 AST_LIST_LOCK(&s->parent->parent->subs);
2587 AST_LIST_TRAVERSE(&s->parent->parent->subs, sub, list) {
2592 ast_rtp_instance_get_remote_address(sub->rtp, &us_tmp);
2593 ast_sockaddr_to_sin(&us_tmp, &us);
2594 if (htons(us.sin_port)) {
2595 rtp_start = htons(us.sin_port) + 1;
2600 AST_LIST_UNLOCK(&s->parent->parent->subs);
2604 static void send_start_rtp(struct unistim_subchannel *sub)
2609 struct sockaddr_in public = { 0, };
2610 struct sockaddr_in us = { 0, };
2611 struct sockaddr_in sin = { 0, };
2612 struct ast_sockaddr us_tmp;
2613 struct ast_sockaddr sin_tmp;
2614 struct unistimsession *pte;
2616 ast_rtp_instance_get_local_address(sub->rtp, &us_tmp);
2617 ast_sockaddr_to_sin(&us_tmp, &us);
2618 ast_rtp_instance_get_remote_address(sub->rtp, &sin_tmp);
2619 ast_sockaddr_to_sin(&sin_tmp, &sin);
2621 /* Setting up RTP of the phone */
2622 if (public_ip.sin_family == 0) { /* NAT IP override ? */
2623 memcpy(&public, &us, sizeof(public)); /* No defined, using IP from recvmsg */
2625 memcpy(&public, &public_ip, sizeof(public)); /* override */
2628 ast_verb(0, "RTP started : Our IP/port is : %s:%hd with codec %s\n",
2629 ast_inet_ntoa(us.sin_addr),
2630 htons(us.sin_port), ast_getformatname(ast_channel_readformat(sub->owner)));
2631 ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n",
2632 ast_inet_ntoa(public.sin_addr));
2635 pte = sub->parent->parent->session;
2636 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, ast_channel_readformat(sub->owner), 0);
2637 if ((ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) ||
2638 (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW)) {
2640 ast_verb(0, "Sending packet_send_rtp_packet_size for codec %d\n", codec);
2642 memcpy(buffsend + SIZE_HEADER, packet_send_rtp_packet_size,
2643 sizeof(packet_send_rtp_packet_size));
2644 buffsend[10] = (int) codec & 0xffffffffLL;
2645 send_client(SIZE_HEADER + sizeof(packet_send_rtp_packet_size), buffsend, pte);
2648 ast_verb(0, "Sending Jitter Buffer Parameters Configuration\n");
2650 memcpy(buffsend + SIZE_HEADER, packet_send_jitter_buffer_conf,
2651 sizeof(packet_send_jitter_buffer_conf));
2652 send_client(SIZE_HEADER + sizeof(packet_send_jitter_buffer_conf), buffsend, pte);
2653 if (pte->device->rtp_method != 0) {
2654 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2657 ast_verb(0, "Sending OpenAudioStreamTX using method #%d\n", pte->device->rtp_method);
2659 if (pte->device->rtp_method == 3) {
2660 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx3,
2661 sizeof(packet_send_open_audio_stream_tx3));
2663 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx,
2664 sizeof(packet_send_open_audio_stream_tx));
2666 if (pte->device->rtp_method != 2) {
2667 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2668 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2669 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2670 buffsend[23] = (rtcpsin_port & 0x00ff);
2671 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2672 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2673 buffsend[24] = (us.sin_port & 0x00ff);
2674 buffsend[27] = (rtcpsin_port & 0x00ff);
2675 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2677 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2678 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2679 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2680 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2681 buffsend[19] = (us.sin_port & 0x00ff);
2682 buffsend[11] = codec;
2684 buffsend[12] = codec;
2685 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_tx), buffsend, pte);
2688 ast_verb(0, "Sending OpenAudioStreamRX\n");
2690 if (pte->device->rtp_method == 3) {
2691 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx3,
2692 sizeof(packet_send_open_audio_stream_rx3));
2694 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx,
2695 sizeof(packet_send_open_audio_stream_rx));
2697 if (pte->device->rtp_method != 2) {
2698 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2699 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2700 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2701 buffsend[23] = (rtcpsin_port & 0x00ff);
2702 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2703 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2704 buffsend[24] = (us.sin_port & 0x00ff);
2705 buffsend[27] = (rtcpsin_port & 0x00ff);
2706 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2708 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2709 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2710 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2711 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2712 buffsend[19] = (us.sin_port & 0x00ff);
2713 buffsend[12] = codec;
2715 buffsend[11] = codec;
2716 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_rx), buffsend, pte);
2718 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2721 ast_verb(0, "Sending packet_send_call default method\n");
2724 memcpy(buffsend + SIZE_HEADER, packet_send_call, sizeof(packet_send_call));
2725 memcpy(buffsend + 53, &public.sin_addr, sizeof(public.sin_addr));
2726 /* Destination port when sending RTP */
2727 buffsend[49] = (us.sin_port & 0x00ff);
2728 buffsend[50] = (us.sin_port & 0xff00) >> 8;
2729 /* Destination port when sending RTCP */
2730 buffsend[52] = (rtcpsin_port & 0x00ff);
2731 buffsend[51] = (rtcpsin_port & 0xff00) >> 8;
2733 buffsend[40] = codec;
2734 buffsend[41] = codec;
2735 if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) {
2736 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2737 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW) {
2738 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2739 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G723_1) {
2740 buffsend[42] = 2; /* 1 = 30ms (24 bytes), 2 = 60 ms (48 bytes) */
2741 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G729A) {
2742 buffsend[42] = 2; /* 1 = 10ms (10 bytes), 2 = 20ms (20 bytes) */
2744 ast_log(LOG_WARNING, "Unsupported codec %s!\n",
2745 ast_getformatname(ast_channel_readformat(sub->owner)));
2747 /* Source port for transmit RTP and Destination port for receiving RTP */
2748 buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8;
2749 buffsend[46] = (htons(sin.sin_port) & 0x00ff);
2750 buffsend[47] = (rtcpsin_port & 0xff00) >> 8;
2751 buffsend[48] = (rtcpsin_port & 0x00ff);
2752 send_client(SIZE_HEADER + sizeof(packet_send_call), buffsend, pte);
2756 static void start_rtp(struct unistim_subchannel *sub)
2758 struct sockaddr_in sin = { 0, };
2759 struct sockaddr_in sout = { 0, };
2760 struct ast_sockaddr sin_tmp;
2761 struct ast_sockaddr sout_tmp;
2765 ast_log(LOG_WARNING, "start_rtp with a null subchannel !\n");
2769 ast_log(LOG_WARNING, "start_rtp with a null line!\n");
2772 if (!sub->parent->parent) {
2773 ast_log(LOG_WARNING, "start_rtp with a null device!\n");
2776 if (!sub->parent->parent->session) {
2777 ast_log(LOG_WARNING, "start_rtp with a null session!\n");
2781 ast_log(LOG_WARNING, "start_rtp with a null asterisk channel!\n");
2784 sout = sub->parent->parent->session->sout;
2785 ast_mutex_lock(&sub->lock);
2786 /* Allocate the RTP */
2788 ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
2790 ast_sockaddr_from_sin(&sout_tmp, &sout);
2791 sub->rtp = ast_rtp_instance_new("asterisk", sched, &sout_tmp, NULL);
2793 ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
2794 strerror(errno), ast_inet_ntoa(sout.sin_addr));
2795 ast_mutex_unlock(&sub->lock);
2798 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
2799 ast_channel_internal_fd_set(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
2800 ast_channel_internal_fd_set(sub->owner, 1, ast_rtp_instance_fd(sub->rtp, 1));
2801 ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
2802 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->parent->parent->nat);
2804 /* Create the RTP connection */
2805 sin.sin_family = AF_INET;
2806 /* Setting up RTP for our side */
2807 memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
2808 sizeof(sin.sin_addr));
2810 sin.sin_port = htons(find_rtp_port(sub));
2811 ast_sockaddr_from_sin(&sin_tmp, &sin);
2812 ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
2813 if (!ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), ast_channel_readformat(sub->owner))) {
2814 struct ast_format tmpfmt;
2816 ast_best_codec(ast_channel_nativeformats(sub->owner), &tmpfmt);
2817 ast_log(LOG_WARNING,
2818 "Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n",
2819 ast_getformatname(ast_channel_readformat(sub->owner)),
2820 ast_getformatname(&tmpfmt),
2821 ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(sub->owner)));
2823 ast_format_copy(ast_channel_readformat(sub->owner), &tmpfmt);
2824 ast_format_copy(ast_channel_writeformat(sub->owner), &tmpfmt);
2826 send_start_rtp(sub);
2827 ast_mutex_unlock(&sub->lock);
2830 static void send_dial_tone(struct unistimsession *pte)
2832 struct ast_tone_zone_sound *ts = NULL;
2833 struct ast_tone_zone_part tone_data;
2837 if ((ts = ast_get_indication_tone(pte->device->tz, "dial"))) {
2838 ind = ast_strdupa(ts->data);
2839 s = strsep(&ind, ",");
2840 ast_tone_zone_part_parse(s, &tone_data);
2841 if (tone_data.modulate) {
2842 tone_data.freq2 = 0;
2844 send_tone(pte, tone_data.freq1, tone_data.freq2);
2846 ast_verb(0, "Country code found (%s), freq1=%d freq2=%d\n",
2847 pte->device->tz->country, tone_data.freq1, tone_data.freq2);
2849 ts = ast_tone_zone_sound_unref(ts);
2853 static void show_phone_number(struct unistimsession *pte)
2855 char tmp[TEXT_LENGTH_MAX + 1];
2856 const char *tmp_number = ustmtext("Number:", pte);
2857 int line, tmp_copy, offset = 0, i;
2859 pte->device->phone_number[pte->device->size_phone_number] = '\0';
2860 if (pte->device->size_phone_number > MAX_SCREEN_NUMBER) {
2861 offset = pte->device->size_phone_number - MAX_SCREEN_NUMBER - 1;
2862 if (offset > strlen(tmp_number)) {
2863 offset = strlen(tmp_number);
2865 tmp_copy = strlen(tmp_number) - offset + 1;
2866 if (tmp_copy > sizeof(tmp)) {
2867 tmp_copy = sizeof(tmp);
2869 memcpy(tmp, tmp_number + offset, tmp_copy);
2871 ast_copy_string(tmp, tmp_number, sizeof(tmp));
2874 offset = (pte->device->size_phone_number >= TEXT_LENGTH_MAX) ? (pte->device->size_phone_number - TEXT_LENGTH_MAX +1) : 0;
2875 if (pte->device->size_phone_number) {
2876 memcpy(tmp + strlen(tmp), pte->device->phone_number + offset, pte->device->size_phone_number - offset + 1);
2878 offset = strlen(tmp);
2880 for (i = strlen(tmp); i < TEXT_LENGTH_MAX; i++) {
2885 line = (pte->device->height == 1) ? TEXT_LINE0 : TEXT_LINE2;
2886 send_text(line, TEXT_NORMAL, pte, tmp);
2887 send_blink_cursor(pte);
2888 send_cursor_pos(pte, (unsigned char) (line + offset));
2889 send_led_update(pte, 0);
2892 static void handle_dial_page(struct unistimsession *pte)
2894 pte->state = STATE_DIALPAGE;
2895 if (pte->device->call_forward[0] == -1) {
2896 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
2897 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Enter forward", pte));
2898 send_text_status(pte, ustmtext("Fwd Cancel BackSp Erase", pte));
2899 if (pte->device->call_forward[1] != 0) {
2900 ast_copy_string(pte->device->phone_number, pte->device->call_forward + 1,
2901 sizeof(pte->device->phone_number));
2902 show_phone_number(pte);
2903 send_led_update(pte, 0);
2907 if ((pte->device->output == OUTPUT_HANDSET) &&
2908 (pte->device->receiver_state == STATE_ONHOOK)) {
2909 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2911 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2913 send_dial_tone(pte);
2915 if (pte->device->height > 1) {
2916 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Enter the number to dial", pte));
2917 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("and press Call", pte));
2919 send_text_status(pte, ustmtext("Call Redial BackSp Erase", pte));
2922 pte->device->size_phone_number = 0;
2923 pte->device->phone_number[0] = 0;
2924 show_phone_number(pte);
2925 change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
2926 send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
2927 pte->device->missed_call = 0;
2928 send_led_update(pte, 0);
2932 static void swap_subs(struct unistim_subchannel *a, struct unistim_subchannel *b)
2934 struct ast_rtp_instance *rtp;
2938 ast_verb(0, "Swapping %p and %p\n", a, b);
2940 if ((!a->owner) || (!b->owner)) {
2941 ast_log(LOG_WARNING,
2942 "Attempted to swap subchannels with a null owner : sub #%p=%p sub #%p=%p\n",
2943 a, a->owner, b, b->owner);
2950 fds = ast_channel_fd(a->owner, 0);
2951 ast_channel_internal_fd_set(a->owner, 0, ast_channel_fd(b->owner, 0));
2952 ast_channel_internal_fd_set(b->owner, 0, fds);
2954 fds = ast_channel_fd(a->owner, 1);
2955 ast_channel_internal_fd_set(a->owner, 1, ast_channel_fd(b->owner, 1));
2956 ast_channel_internal_fd_set(b->owner, 1, fds);
2959 /* Step 1 : Music On Hold for peer, Dialing screen for us */
2960 static void transfer_call_step1(struct unistimsession *pte)
2962 struct unistim_subchannel *sub, *sub_trans;
2963 struct unistim_device *d = pte->device;
2965 sub = get_sub(d, SUB_REAL);
2966 sub_trans = get_sub(d, SUB_THREEWAY);
2968 if (!sub || !sub->owner) {
2969 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2972 /* Start music on hold if appropriate */
2974 ast_log(LOG_WARNING, "Transfer with peer already listening music on hold\n");
2976 if (ast_bridged_channel(sub->owner)) {
2977 ast_moh_start(ast_bridged_channel(sub->owner),
2978 sub->parent->musicclass, NULL);
2980 sub->subtype = SUB_THREEWAY;
2982 ast_log(LOG_WARNING, "Unable to find peer subchannel for music on hold\n");
2986 sub_start_silence(pte, sub);
2987 handle_dial_page(pte);
2990 static void transfer_cancel_step2(struct unistimsession *pte)
2992 struct unistim_subchannel *sub, *sub_trans;
2993 struct unistim_device *d = pte->device;
2995 sub = get_sub(d, SUB_REAL);
2996 sub_trans = get_sub(d, SUB_THREEWAY);
2998 if (!sub || !sub->owner) {
2999 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
3004 ast_verb(0, "Transfer canceled, hangup our threeway channel\n");
3007 swap_subs(sub, sub_trans);
3008 ast_moh_stop(ast_bridged_channel(sub_trans->owner));
3010 sub_trans->subtype = SUB_REAL;
3011 sub->subtype = SUB_THREEWAY;
3012 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NORMAL_CLEARING);
3014 ast_log(LOG_WARNING, "Canceling a threeway channel without owner\n");
3020 /* From phone to PBX */
3021 static void handle_call_outgoing(struct unistimsession *s)
3023 struct ast_channel *c;
3024 struct unistim_subchannel *sub;
3027 s->state = STATE_CALL;
3029 sub = get_sub(s->device, SUB_THREEWAY);
3031 /* If sub for threway call created than we use transfer behaviuor */
3032 struct unistim_subchannel *sub_trans = NULL;
3033 struct unistim_device *d = s->device;
3035 sub_trans = get_sub(d, SUB_REAL);
3037 ast_log(LOG_WARNING, "Can't transfer while active subchannel exists!\n");
3041 ast_log(LOG_WARNING, "Unable to find subchannel with music on hold\n");
3045 sub_trans = unistim_alloc_sub(d, SUB_REAL);
3047 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
3050 sub_trans->parent = sub->parent;
3051 sub_stop_silence(s, sub);
3053 /* Make new channel */
3054 c = unistim_new(sub_trans, AST_STATE_DOWN, NULL);
3056 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", sub->parent);
3059 /* Swap things around between the three-way and real call */
3060 swap_subs(sub, sub_trans);
3061 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
3062 if (s->device->height == 1) {
3063 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
3065 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling (pre-transfer)", s));
3066 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
3067 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Dialing...", s));
3069 send_text_status(s, ustmtext("TransfrCancel", s));
3071 if (ast_pthread_create(&sub->ss_thread, NULL, unistim_ss, c)) {
3072 ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", c);
3073 sub->ss_thread = AST_PTHREADT_NULL;
3078 ast_verb(0, "Started three way call on channel %p (%s) subchan %d\n",
3079 sub_trans->owner, ast_channel_name(sub_trans->owner), sub_trans->subtype);
3084 softkey = get_avail_softkey(s, NULL);
3085 if (softkey == -1) {
3086 ast_log(LOG_WARNING, "Have no avail softkey for calling\n");
3089 sub = get_sub(s->device, SUB_REAL);
3090 if (sub) { /* have already call assigned */
3091 sub_hold(s, sub); /* Need to put on hold */
3093 if (!(sub = unistim_alloc_sub(s->device, SUB_REAL))) {
3094 ast_log(LOG_WARNING, "Unable to allocate subchannel!\n");