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/rtp_engine.h"
67 #include "asterisk/netsock2.h"
68 #include "asterisk/acl.h"
69 #include "asterisk/callerid.h"
70 #include "asterisk/cli.h"
71 #include "asterisk/app.h"
72 #include "asterisk/musiconhold.h"
73 #include "asterisk/causes.h"
74 #include "asterisk/indications.h"
75 #include "asterisk/pickup.h"
76 #include "asterisk/astobj2.h"
77 #include "asterisk/astdb.h"
78 #include "asterisk/features_config.h"
79 #include "asterisk/bridge.h"
80 #include "asterisk/stasis_channels.h"
82 #define DEFAULTCONTEXT "default"
83 #define DEFAULTCALLERID "Unknown"
84 #define DEFAULTCALLERNAME " "
85 #define DEFAULTHEIGHT 3
86 #define USTM_LOG_DIR "unistimHistory"
87 #define USTM_LANG_DIR "unistimLang"
89 /*! Size of the transmit buffer */
90 #define MAX_BUF_SIZE 64
91 /*! Number of slots for the transmit queue */
92 #define MAX_BUF_NUMBER 50
93 /*! Number of digits displayed on screen */
94 #define MAX_SCREEN_NUMBER 15
95 /*! Try x times before removing the phone */
96 #define NB_MAX_RETRANSMIT 8
97 /*! Nb of milliseconds waited when no events are scheduled */
98 #define IDLE_WAIT 1000
99 /*! Wait x milliseconds before resending a packet */
100 #define RETRANSMIT_TIMER 2000
101 /*! How often the mailbox is checked for new messages */
102 #define TIMER_MWI 5000
103 /*! Timeout value for entered number being dialed */
104 #define DEFAULT_INTERDIGIT_TIMER 4000
107 #define DEFAULT_CODEC 0x00
108 #define SIZE_PAGE 4096
109 #define DEVICE_NAME_LEN 16
110 #define AST_CONFIG_MAX_PATH 255
111 #define MAX_ENTRY_LOG 30
115 #define SUB_THREEWAY 2
118 struct ast_format_cap *global_cap;
121 AUTOPROVISIONING_NO = 0,
122 AUTOPROVISIONING_YES,
127 /*! Do not create an extension into the default dialplan */
129 /*! Prompt user for an extension number and register it */
131 /*! Register an extension with the line=> value */
133 /*! Used with AUTOPROVISIONING_TN */
136 #define OUTPUT_HANDSET 0xC0
137 #define OUTPUT_HEADPHONE 0xC1
138 #define OUTPUT_SPEAKER 0xC2
140 #define VOLUME_LOW 0x01
141 #define VOLUME_LOW_SPEAKER 0x03
142 #define VOLUME_NORMAL 0x02
143 #define VOLUME_INSANELY_LOUD 0x07
145 #define MUTE_OFF 0x00
147 #define MUTE_ON_DISCRET 0xCE
149 #define SIZE_HEADER 6
150 #define SIZE_MAC_ADDR 17
151 #define TEXT_LENGTH_MAX 24
152 #define TEXT_LINE0 0x00
153 #define TEXT_LINE1 0x20
154 #define TEXT_LINE2 0x40
155 #define TEXT_NORMAL 0x05
156 #define TEXT_INVERSE 0x25
157 #define STATUS_LENGTH_MAX 28
159 #define FAV_ICON_NONE 0x00
160 #define FAV_ICON_ONHOOK_BLACK 0x20
161 #define FAV_ICON_ONHOOK_WHITE 0x21
162 #define FAV_ICON_SPEAKER_ONHOOK_BLACK 0x22
163 #define FAV_ICON_SPEAKER_ONHOOK_WHITE 0x23
164 #define FAV_ICON_OFFHOOK_BLACK 0x24
165 #define FAV_ICON_OFFHOOK_WHITE 0x25
166 #define FAV_ICON_ONHOLD_BLACK 0x26
167 #define FAV_ICON_ONHOLD_WHITE 0x27
168 #define FAV_ICON_SPEAKER_OFFHOOK_BLACK 0x28
169 #define FAV_ICON_SPEAKER_OFFHOOK_WHITE 0x29
170 #define FAV_ICON_PHONE_BLACK 0x2A
171 #define FAV_ICON_PHONE_WHITE 0x2B
172 #define FAV_ICON_SPEAKER_ONHOLD_BLACK 0x2C
173 #define FAV_ICON_SPEAKER_ONHOLD_WHITE 0x2D
174 #define FAV_ICON_HEADPHONES 0x2E
175 #define FAV_ICON_HEADPHONES_ONHOLD 0x2F
176 #define FAV_ICON_HOME 0x30
177 #define FAV_ICON_CITY 0x31
178 #define FAV_ICON_SHARP 0x32
179 #define FAV_ICON_PAGER 0x33
180 #define FAV_ICON_CALL_CENTER 0x34
181 #define FAV_ICON_FAX 0x35
182 #define FAV_ICON_MAILBOX 0x36
183 #define FAV_ICON_REFLECT 0x37
184 #define FAV_ICON_COMPUTER 0x38
185 #define FAV_ICON_FORWARD 0x39
186 #define FAV_ICON_LOCKED 0x3A
187 #define FAV_ICON_TRASH 0x3B
188 #define FAV_ICON_INBOX 0x3C
189 #define FAV_ICON_OUTBOX 0x3D
190 #define FAV_ICON_MEETING 0x3E
191 #define FAV_ICON_BOX 0x3F
193 #define FAV_BLINK_FAST 0x20
194 #define FAV_BLINK_SLOW 0x40
196 #define FAV_MAX_LENGTH 0x0A
199 #define FAV_LINE_ICON FAV_ICON_ONHOOK_BLACK
201 static void dummy(char *unused, ...)
206 /*! \brief Global jitterbuffer configuration - by default, jb is disabled
207 * \note Values shown here match the defaults shown in unistim.conf.sample */
208 static struct ast_jb_conf default_jbconf =
212 .resync_threshold = 1000,
216 static struct ast_jb_conf global_jbconf;
219 /* #define DUMP_PACKET 1 */
220 /* #define DEBUG_TIMER ast_verbose */
222 #define DEBUG_TIMER dummy
223 /*! Enable verbose output. can also be set with the CLI */
224 static int unistimdebug = 0;
225 static int unistim_port;
226 static enum autoprovision autoprovisioning = AUTOPROVISIONING_NO;
227 static int unistim_keepalive;
228 static int unistimsock = -1;
232 unsigned int tos_audio;
234 unsigned int cos_audio;
235 } qos = { 0, 0, 0, 0 };
237 static struct io_context *io;
238 static struct ast_sched_context *sched;
239 static struct sockaddr_in public_ip = { 0, };
240 static unsigned char *buff; /*! Receive buffer address */
241 static int unistim_reloading = 0;
242 AST_MUTEX_DEFINE_STATIC(unistim_reload_lock);
244 /*! This is the thread for the monitor which checks for input on the channels
245 * which are not currently in use. */
246 static pthread_t monitor_thread = AST_PTHREADT_NULL;
248 /*! Protect the monitoring thread, so only one process can kill or start it, and not
249 * when it's doing something critical. */
250 AST_MUTEX_DEFINE_STATIC(monlock);
251 /*! Protect the session list */
252 AST_MUTEX_DEFINE_STATIC(sessionlock);
253 /*! Protect the device list */
254 AST_MUTEX_DEFINE_STATIC(devicelock);
266 STATE_SELECTLANGUAGE,
326 static const int dtmf_row[] = { 697, 770, 852, 941 };
327 static const float dtmf_col[] = { 1209, 1336, 1477, 1633 };
334 struct unistim_subchannel {
336 unsigned int subtype; /*! SUB_REAL, SUB_RING, SUB_THREEWAY or SUB_ONHOLD */
337 struct ast_channel *owner; /*! Asterisk channel used by the subchannel */
338 struct unistim_line *parent; /*! Unistim line */
339 struct ast_rtp_instance *rtp; /*! RTP handle */
340 int softkey; /*! Softkey assigned */
341 pthread_t ss_thread; /*! unistim_ss thread handle */
345 int moh; /*!< Music on hold in progress */
346 AST_LIST_ENTRY(unistim_subchannel) list;
350 * \todo Convert to stringfields
352 struct unistim_line {
354 char name[80]; /*! Like 200 */
355 char fullname[80]; /*! Like USTM/200\@black */
356 char exten[AST_MAX_EXTENSION]; /*! Extension where to start */
357 char cid_num[AST_MAX_EXTENSION]; /*! CallerID Number */
358 char mailbox[AST_MAX_EXTENSION]; /*! Mailbox for 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 int interdigit_timer; /*!< Interdigit timer for dialing number by timeout */
405 time_t nextdial; /*!< Timer used for dial by timeout */
406 int rtp_port; /*!< RTP port used by the phone */
407 int rtp_method; /*!< Select the unistim data used to establish a RTP session */
408 int status_method; /*!< Select the unistim packet used for sending status text */
409 char codec_number; /*!< The current codec used to make calls */
410 int missed_call; /*!< Number of call unanswered */
411 int callhistory; /*!< Allowed to record call history */
412 int sharp_dial; /*!< Execute Dial on '#' or not */
413 char lst_cid[TEXT_LENGTH_MAX]; /*!< Last callerID received */
414 char lst_cnm[TEXT_LENGTH_MAX]; /*!< Last callername recevied */
415 char call_forward[AST_MAX_EXTENSION]; /*!< Forward number */
416 int output; /*!< Handset, headphone or speaker */
417 int previous_output; /*!< Previous output */
418 int volume; /*!< Default volume */
419 int selected; /*!< softkey selected */
420 int mute; /*!< Mute mode */
421 int lastmsgssent; /*! Used by MWI */
422 time_t nextmsgcheck; /*! Used by MWI */
423 int nat; /*!< Used by the obscure ast_rtp_setnat */
424 enum autoprov_extn extension; /*!< See ifdef EXTENSION for valid values */
425 char extension_number[11]; /*!< Extension number entered by the user */
426 char to_delete; /*!< Used in reload */
427 struct ast_silence_generator *silence_generator;
428 AST_LIST_HEAD(,unistim_subchannel) subs; /*!< pointer to our current connection, channel... */
429 AST_LIST_HEAD(,unistim_line) lines;
431 struct unistimsession *session;
432 struct unistim_device *next;
435 static struct unistimsession {
437 struct sockaddr_in sin; /*!< IP address of the phone */
438 struct sockaddr_in sout; /*!< IP address of server */
439 int timeout; /*!< time-out in ticks : resend packet if no ack was received before the timeout occured */
440 unsigned short seq_phone; /*!< sequence number for the next packet (when we receive a request) */
441 unsigned short seq_server; /*!< sequence number for the next packet (when we send a request) */
442 unsigned short last_seq_ack; /*!< sequence number of the last ACK received */
443 unsigned long tick_next_ping; /*!< time for the next ping */
444 int last_buf_available; /*!< number of a free slot */
445 int nb_retransmit; /*!< number of retransmition */
446 int state; /*!< state of the phone (see phone_state) */
447 int size_buff_entry; /*!< size of the buffer used to enter datas */
448 char buff_entry[16]; /*!< Buffer for temporary datas */
449 char macaddr[18]; /*!< mac adress of the phone (not always available) */
450 char firmware[8]; /*!< firmware of the phone (not always available) */
451 struct wsabuf wsabufsend[MAX_BUF_NUMBER]; /*!< Size of each paquet stored in the buffer array & pointer to this buffer */
452 unsigned char buf[MAX_BUF_NUMBER][MAX_BUF_SIZE]; /*!< Buffer array used to keep the lastest non-acked paquets */
453 struct unistim_device *device;
454 struct unistimsession *next;
457 /*! Store on screen phone menu item (label and handler function) */
458 struct unistim_menu_item {
461 void (*handle_option)(struct unistimsession *);
464 /*! Language item for currently existed translations */
465 struct unistim_languages {
469 struct ao2_container *trans;
473 * \page Unistim datagram formats
475 * Format of datagrams :
476 * bytes 0 & 1 : ffff for discovery packet, 0000 for everything else
477 * byte 2 : sequence number (high part)
478 * byte 3 : sequence number (low part)
479 * byte 4 : 2 = ask question or send info, 1 = answer or ACK, 0 = retransmit request
480 * byte 5 : direction, 1 = server to phone, 2 = phone to server arguments
483 static const unsigned char packet_rcv_discovery[] =
484 { 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
485 static const unsigned char packet_send_discovery_ack[] =
486 { 0x00, 0x00, /*Initial Seq (2 bytes) */ 0x00, 0x00, 0x00, 0x01 };
488 static const unsigned char packet_recv_firm_version[] =
489 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x0a, 0x02 };
490 static const unsigned char packet_recv_it_type[] =
491 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x04, 0x03 };
492 static const unsigned char packet_recv_pressed_key[] =
493 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x04, 0x00 };
494 static const unsigned char packet_recv_pick_up[] =
495 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x04 };
496 static const unsigned char packet_recv_hangup[] =
497 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x03 };
498 static const unsigned char packet_recv_r2[] = { 0x00, 0x00, 0x00, 0x13, 0x96, 0x03, 0x03 };
500 /*! TransportAdapter */
501 static const unsigned char packet_recv_resume_connection_with_server[] =
502 { 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
503 static const unsigned char packet_recv_mac_addr[] =
504 { 0xff, 0xff, 0xff, 0xff, 0x9a, 0x0d, 0x07 /*MacAddr */ };
506 static const unsigned char packet_send_date_time3[] =
507 { 0x11, 0x09, 0x02, 0x02, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07,
508 /*Minutes */ 0x08, 0x32
510 static const unsigned char packet_send_date_time[] =
511 { 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07, /*Minutes */
512 0x08, 0x32, 0x17, 0x04, 0x24, 0x07, 0x19,
513 0x04, 0x07, 0x00, 0x19, 0x05, 0x09, 0x3e, 0x0f, 0x16, 0x05, 0x00, 0x80, 0x00, 0x1e,
514 0x05, 0x12, 0x00, 0x78
517 static const unsigned char packet_send_no_ring[] =
518 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00 };
519 static const unsigned char packet_send_s4[] =
520 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff,
521 0x16, 0x05, 0x1c, 0x00, 0x00, 0x17, 0x05,
522 0x0b, 0x00, 0x00, 0x19, 0x04, 0x00, 0x00, 0x19, 0x04, 0x00, 0x08, 0x19, 0x04, 0x00,
523 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
524 0x31, 0x00, 0x00, 0x16, 0x05, 0x04, 0x00, 0x00
526 static const unsigned char packet_send_call[] =
527 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf,
528 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16, 0x0a, 0x38, 0x00, 0x12, 0xca, 0x03,
529 0xc0, 0xc3, 0xc5, 0x16, 0x16, 0x30, 0x00,
530 0x00, /*codec */ 0x12, 0x12, /* frames per packet */ 0x01, 0x5c, 0x00, /*port RTP */
531 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41,
532 /*port RTP */ 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41, /* IP Address */ 0x0a, 0x01,
535 static const unsigned char packet_send_stream_based_tone_off[] =
536 { 0x16, 0x05, 0x1c, 0x00, 0x00 };
538 /* static const unsigned char packet_send_Mute[] = { 0x16, 0x05, 0x04, 0x00, 0x00 };
539 static const unsigned char packet_send_CloseAudioStreamRX[] = { 0x16, 0x05, 0x31, 0x00, 0xff };
540 static const unsigned char packet_send_CloseAudioStreamTX[] = { 0x16, 0x05, 0x31, 0xff, 0x00 };*/
541 static const unsigned char packet_send_stream_based_tone_on[] =
542 { 0x16, 0x06, 0x1b, 0x00, 0x00, 0x05 };
543 static const unsigned char packet_send_stream_based_tone_single_freq[] =
544 { 0x16, 0x06, 0x1d, 0x00, 0x01, 0xb8 };
545 static const unsigned char packet_send_stream_based_tone_dial_freq[] =
546 { 0x16, 0x08, 0x1d, 0x00, 0x01, 0xb8, 0x01, 0x5e };
547 static const unsigned char packet_send_select_output[] =
548 { 0x16, 0x06, 0x32, 0xc0, 0x01, 0x00 };
549 static const unsigned char packet_send_ring[] =
550 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16,
551 0x04, 0x1a, 0x01, 0x16, 0x05, 0x12, 0x13 /* Ring type 10 to 17 */ , 0x18, 0x16, 0x04, 0x18, /* volume 00, 10, 20... */
552 0x20, 0x16, 0x04, 0x10, 0x00
554 static const unsigned char packet_send_end_call[] =
555 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x31, 0x00, 0x00, 0x19, 0x04, 0x00,
556 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
557 0x04, 0x00, 0x00, 0x16, 0x04, 0x37, 0x10
559 static const unsigned char packet_send_s9[] =
560 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x19, 0x04, 0x00, 0x10, 0x16, 0x05, 0x1c, 0x00,
562 static const unsigned char packet_send_rtp_packet_size[] =
563 { 0x16, 0x08, 0x38, 0x00, 0x00, 0xe0, 0x00, 0xa0 };
564 static const unsigned char packet_send_jitter_buffer_conf[] =
565 { 0x16, 0x0e, 0x3a, 0x00, /* jitter */ 0x02, /* high water mark */ 0x04, 0x00, 0x00,
566 /* early packet resync 2 bytes */ 0x3e, 0x80,
567 0x00, 0x00, /* late packet resync 2 bytes */ 0x3e, 0x80
570 /* Duration in ms div 2 (0x20 = 64ms, 0x08 = 16ms)
571 static unsigned char packet_send_StreamBasedToneCad[] =
572 { 0x16, 0x0a, 0x1e, 0x00, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x2b }; */
573 static const unsigned char packet_send_open_audio_stream_rx[] =
574 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
575 0x0e, 0x01, /* Port */ 0x14, 0x50, 0x00,
576 0x00, /* Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
578 static const unsigned char packet_send_open_audio_stream_tx[] =
579 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
580 0x0e, 0x01, /* Local port */ 0x14, 0x50,
581 0x00, 0x00, /* Rmt Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
584 static const unsigned char packet_send_open_audio_stream_rx3[] =
585 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
586 0x06, 0x81, /* RTP Port */ 0x14, 0x50,
587 /* RTCP Port */ 0x14,
588 0x51, /* RTP Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00, /* Dest IP */ 0x0a, 0x93,
591 static const unsigned char packet_send_open_audio_stream_tx3[] =
592 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
593 0x06, 0x81, /* RTP Local port */ 0x14, 0x50,
594 /* RTCP Port */ 0x00, 0x00, /* RTP Rmt Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00,
595 /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
598 static const unsigned char packet_send_arrow[] = { 0x17, 0x04, 0x04, 0x00 };
599 static const unsigned char packet_send_blink_cursor[] = { 0x17, 0x04, 0x10, 0x86 };
600 static const unsigned char packet_send_date_time2[] = { 0x17, 0x04, 0x17, 0x3d, 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */
601 0x06, /*Hour */ 0x07, /*Minutes */ 0x08, 0x32
603 static const unsigned char packet_send_Contrast[] =
604 { 0x17, 0x04, 0x24, /*Contrast */ 0x08 };
605 static const unsigned char packet_send_start_timer[] =
606 { 0x17, 0x05, 0x0b, /*Timer option*/0x05, /* Timer ID */0x00, 0x17, 0x08, 0x16,
607 /* Text */ 0x44, 0x75, 0x72, 0xe9, 0x65 };
608 static const unsigned char packet_send_stop_timer[] = { 0x17, 0x05, 0x0b, 0x02, 0x00 };
609 static const unsigned char packet_send_icon[] = { 0x17, 0x05, 0x14, /*pos */ 0x00, /*icon */ 0x25 }; /* display an icon in front of the text zone */
610 static const unsigned char packet_send_S7[] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 };
611 static const unsigned char packet_send_set_pos_cursor[] =
612 { 0x17, 0x06, 0x10, 0x81, 0x04, /*pos */ 0x20 };
614 /*static unsigned char packet_send_MonthLabelsDownload[] =
615 { 0x17, 0x0a, 0x15, Month (3 char) 0x46, 0x65, 0x62, 0x4d, 0xe4, 0x72, 0x20 }; */
616 static const unsigned char packet_send_favorite[] =
617 { 0x17, 0x0f, 0x19, 0x10, /*pos */ 0x01, /*name */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
618 0x20, 0x20, 0x20, 0x20, /*end_name */ 0x19,
619 0x05, 0x0f, /*pos */ 0x01, /*icone */ 0x00
621 static const unsigned char packet_send_title[] =
622 { 0x17, 0x10, 0x19, 0x02, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
623 0x20, 0x20, 0x20, 0x20 /*end_text */ };
624 static const unsigned char packet_send_text[] =
625 { 0x17, 0x1e, 0x1b, 0x04, /*pos */ 0x00, /*inverse */ 0x25, /*text */ 0x20, 0x20,
626 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
627 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
628 /*end_text */ 0x17, 0x04, 0x10, 0x87
630 static const unsigned char packet_send_status[] =
631 { 0x17, 0x20, 0x19, 0x08, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
632 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
633 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 /*end_text */
635 static const unsigned char packet_send_status2[] =
636 { 0x17, 0x0b, 0x19, /* pos [08|28|48|68] */ 0x00, /* text */ 0x20, 0x20, 0x20, 0x20,
637 0x20, 0x20, 0x20 /* end_text */ };
639 /* Multiple character set support */
640 /* ISO-8859-1 - Western European) */
641 static const unsigned char packet_send_charset_iso_8859_1[] =
642 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x41, 0x1b, 0x00 };
643 /* ISO-8859-2 - Central European) */
644 static const unsigned char packet_send_charset_iso_8859_2[] =
645 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x42, 0x1b, 0x00 };
646 /* ISO-8859-4 - Baltic) */
647 static const unsigned char packet_send_charset_iso_8859_4[] =
648 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x44, 0x1b, 0x00 };
649 /* ISO 8859-5 - cyrilic */
650 static const unsigned char packet_send_charset_iso_8859_5[] =
651 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x4c, 0x1b, 0x00 };
652 /* Japaneese (ISO-2022-JP ?) */
653 static const unsigned char packet_send_charset_iso_2022_jp[] =
654 { 0x17, 0x08, 0x21, 0x1b, 0x29, 0x49, 0x1b, 0x7e };
656 static const unsigned char packet_send_led_update[] = { 0x19, 0x04, 0x00, 0x00 };
658 static const unsigned char packet_send_query_basic_manager_04[] = { 0x1a, 0x04, 0x01, 0x04 };
659 static const unsigned char packet_send_query_mac_address[] = { 0x1a, 0x04, 0x01, 0x08 };
660 static const unsigned char packet_send_query_basic_manager_10[] = { 0x1a, 0x04, 0x01, 0x10 };
661 static const unsigned char packet_send_S1[] = { 0x1a, 0x07, 0x07, 0x00, 0x00, 0x00, 0x13 };
663 static unsigned char packet_send_ping[] =
664 { 0x1e, 0x05, 0x12, 0x00, /*Watchdog timer */ 0x78 };
666 #define BUFFSEND unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }
668 static const char tdesc[] = "UNISTIM Channel Driver";
669 static const char channel_type[] = "USTM";
672 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state, const char *linkedid);
673 static int load_module(void);
674 static int reload(void);
675 static int unload_module(void);
676 static int reload_config(void);
677 static void unistim_set_owner(struct unistim_subchannel *sub, struct ast_channel *chan);
678 static void show_main_page(struct unistimsession *pte);
679 static struct ast_channel *unistim_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor,
680 const char *dest, int *cause);
681 static int unistim_call(struct ast_channel *ast, const char *dest, int timeout);
682 static int unistim_hangup(struct ast_channel *ast);
683 static int unistim_answer(struct ast_channel *ast);
684 static struct ast_frame *unistim_read(struct ast_channel *ast);
685 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame);
686 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
688 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
689 static int unistim_senddigit_begin(struct ast_channel *ast, char digit);
690 static int unistim_senddigit_end(struct ast_channel *ast, char digit,
691 unsigned int duration);
692 static int unistim_sendtext(struct ast_channel *ast, const char *text);
694 static int write_entry_history(struct unistimsession *pte, FILE * f, char c,
696 static void change_callerid(struct unistimsession *pte, int type, char *callerid);
698 static struct ast_channel_tech unistim_tech = {
699 .type = channel_type,
700 .description = tdesc,
701 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
702 .requester = unistim_request,
703 .call = unistim_call,
704 .hangup = unistim_hangup,
705 .answer = unistim_answer,
706 .read = unistim_read,
707 .write = unistim_write,
708 .indicate = unistim_indicate,
709 .fixup = unistim_fixup,
710 .send_digit_begin = unistim_senddigit_begin,
711 .send_digit_end = unistim_senddigit_end,
712 .send_text = unistim_sendtext,
715 static void send_start_rtp(struct unistim_subchannel *);
717 static void send_callerid_screen(struct unistimsession *, struct unistim_subchannel *);
718 static void key_favorite(struct unistimsession *, char);
720 static void handle_select_codec(struct unistimsession *);
721 static void handle_select_language(struct unistimsession *);
722 static int find_language(const char*);
724 static int unistim_free_sub(struct unistim_subchannel *);
726 static struct unistim_menu_item options_menu[] =
728 {"Change codec", STATE_SELECTCODEC, handle_select_codec},
729 {"Language", STATE_SELECTLANGUAGE, handle_select_language},
733 static struct unistim_languages options_languages[] =
735 {"English", "en", ISO_8859_1, NULL},
736 {"French", "fr", ISO_8859_1, NULL},
737 {"Russian", "ru", ISO_8859_5, NULL},
738 {NULL, NULL, 0, NULL}
741 static char ustm_strcopy[1024];
743 struct ustm_lang_entry {
744 const char *str_orig;
745 const char *str_trans;
748 static int lang_hash_fn(const void *obj, const int flags)
750 const struct ustm_lang_entry *entry = obj;
751 return ast_str_hash(entry->str_orig);
754 static int lang_cmp_fn(void *obj, void *arg, int flags)
756 struct ustm_lang_entry *entry1 = obj;
757 struct ustm_lang_entry *entry2 = arg;
759 return (!strcmp(entry1->str_orig, entry2->str_orig)) ? (CMP_MATCH | CMP_STOP) : 0;
762 static const char *ustmtext(const char *str, struct unistimsession *pte)
764 struct ustm_lang_entry *lang_entry;
765 struct ustm_lang_entry le_search;
766 struct unistim_languages *lang = NULL;
770 lang = &options_languages[find_language(pte->device->language)];
775 /* Check if specified language exists */
777 char tmp[1024], *p, *p_orig = NULL, *p_trans = NULL;
780 if (!(lang->trans = ao2_container_alloc(8, lang_hash_fn, lang_cmp_fn))) {
781 ast_log(LOG_ERROR, "Unable to allocate container for translation!\n");
784 snprintf(tmp, sizeof(tmp), "%s/%s/%s.po", ast_config_AST_VAR_DIR,
785 USTM_LANG_DIR, lang->lang_short);
788 ast_log(LOG_WARNING, "There is no translation file for '%s'\n", lang->lang_short);
791 while (fgets(tmp, sizeof(tmp), f)) {
792 if (!(p = strchr(tmp, '\n'))) {
793 ast_log(LOG_ERROR, "Too long line found in language file - truncated!\n");
797 if (!(p = strchr(tmp, '"'))) {
800 if (tmp == strstr(tmp, "msgid")) {
801 p_orig = ast_strdup(p + 1);
802 p = strchr(p_orig, '"');
803 } else if (tmp == strstr(tmp, "msgstr")) {
804 p_trans = ast_strdup(p + 1);
805 p = strchr(p_trans, '"');
810 if (!p_trans || !p_orig) {
813 if (ast_strlen_zero(p_trans)) {
820 if (!(lang_entry = ao2_alloc(sizeof(*lang_entry), NULL))) {
825 lang_entry->str_trans = p_trans;
826 lang_entry->str_orig = p_orig;
827 ao2_link(lang->trans, lang_entry);
835 le_search.str_orig = str;
836 if ((lang_entry = ao2_find(lang->trans, &le_search, OBJ_POINTER))) {
837 size = strlen(lang_entry->str_trans)+1;
841 memcpy(ustm_strcopy, lang_entry->str_trans, size);
842 ao2_ref(lang_entry, -1);
849 static void display_last_error(const char *sz_msg)
851 /* Display the error message */
852 ast_log(LOG_WARNING, "%s : (%u) %s\n", sz_msg, errno, strerror(errno));
855 static unsigned int get_tick_count(void)
857 struct timeval now = ast_tvnow();
859 return (now.tv_sec * 1000) + (now.tv_usec / 1000);
862 /* Send data to a phone without retransmit nor buffering */
863 static void send_raw_client(int size, const unsigned char *data, struct sockaddr_in *addr_to,
864 const struct sockaddr_in *addr_ourip)
867 struct iovec msg_iov;
869 char buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
870 struct cmsghdr *ip_msg = (struct cmsghdr *) buffer;
871 struct in_pktinfo *pki = (struct in_pktinfo *) CMSG_DATA(ip_msg);
873 /* cast this to a non-const pointer, since the sendmsg() API
874 * does not provide read-only and write-only flavors of the
875 * structures used for its arguments, but in this case we know
876 * the data will not be modified
878 msg_iov.iov_base = (char *) data;
879 msg_iov.iov_len = size;
881 msg.msg_name = addr_to; /* optional address */
882 msg.msg_namelen = sizeof(struct sockaddr_in); /* size of address */
883 msg.msg_iov = &msg_iov; /* scatter/gather array */
884 msg.msg_iovlen = 1; /* # elements in msg_iov */
885 msg.msg_control = ip_msg; /* ancillary data */
886 msg.msg_controllen = sizeof(buffer); /* ancillary data buffer len */
887 msg.msg_flags = 0; /* flags on received message */
889 ip_msg->cmsg_len = CMSG_LEN(sizeof(*pki));
890 ip_msg->cmsg_level = IPPROTO_IP;
891 ip_msg->cmsg_type = IP_PKTINFO;
892 pki->ipi_ifindex = 0; /* Interface index, 0 = use interface specified in routing table */
893 pki->ipi_spec_dst.s_addr = addr_ourip->sin_addr.s_addr; /* Local address */
894 /* pki->ipi_addr = ; Header Destination address - ignored by kernel */
899 ast_verb(0, "\n**> From %s sending %d bytes to %s ***\n",
900 ast_inet_ntoa(addr_ourip->sin_addr), (int) size,
901 ast_inet_ntoa(addr_to->sin_addr));
902 for (tmp = 0; tmp < size; tmp++)
903 ast_verb(0, "%.2x ", (unsigned char) data[tmp]);
904 ast_verb(0, "\n******************************************\n");
909 if (sendmsg(unistimsock, &msg, 0) == -1) {
910 display_last_error("Error sending datas");
913 if (sendto(unistimsock, data, size, 0, (struct sockaddr *) addr_to, sizeof(*addr_to))
915 display_last_error("Error sending datas");
919 static void send_client(int size, const unsigned char *data, struct unistimsession *pte)
923 unsigned short seq = ntohs(++pte->seq_server);
925 ast_mutex_lock(&pte->lock);
926 buf_pos = pte->last_buf_available;
928 if (buf_pos >= MAX_BUF_NUMBER) {
929 ast_log(LOG_WARNING, "Error : send queue overflow\n");
930 ast_mutex_unlock(&pte->lock);
933 memcpy((void *)data + sizeof(unsigned short), (void *)&seq, sizeof(unsigned short));
934 pte->wsabufsend[buf_pos].len = size;
935 memcpy(pte->wsabufsend[buf_pos].buf, data, size);
937 tick = get_tick_count();
938 pte->timeout = tick + RETRANSMIT_TIMER;
940 /*#ifdef DUMP_PACKET */
942 ast_verb(6, "Sending datas with seq #0x%.4x Using slot #%d :\n", pte->seq_server, buf_pos);
945 send_raw_client(pte->wsabufsend[buf_pos].len, pte->wsabufsend[buf_pos].buf, &(pte->sin),
947 pte->last_buf_available++;
948 ast_mutex_unlock(&pte->lock);
951 static void send_ping(struct unistimsession *pte)
955 ast_verb(6, "Sending ping\n");
957 pte->tick_next_ping = get_tick_count() + unistim_keepalive;
958 memcpy(buffsend + SIZE_HEADER, packet_send_ping, sizeof(packet_send_ping));
959 send_client(SIZE_HEADER + sizeof(packet_send_ping), buffsend, pte);
962 static int get_to_address(int fd, struct sockaddr_in *toAddr)
970 struct in_addr address;
973 /* Zero out the structures before we use them */
974 /* This sets several key values to NULL */
975 memset(&msg, 0, sizeof(msg));
976 memset(&ip_msg, 0, sizeof(ip_msg));
978 /* Initialize the message structure */
979 msg.msg_control = &ip_msg;
980 msg.msg_controllen = sizeof(ip_msg);
981 /* Get info about the incoming packet */
982 err = recvmsg(fd, &msg, MSG_PEEK);
984 ast_log(LOG_WARNING, "recvmsg returned an error: %s\n", strerror(errno));
986 memcpy(&toAddr->sin_addr, &ip_msg.address, sizeof(struct in_addr));
989 memcpy(&toAddr, &public_ip, sizeof(&toAddr));
994 /* Allocate memory & initialize structures for a new phone */
995 /* addr_from : ip address of the phone */
996 static struct unistimsession *create_client(const struct sockaddr_in *addr_from)
999 struct unistimsession *s;
1001 if (!(s = ast_calloc(1, sizeof(*s))))
1004 memcpy(&s->sin, addr_from, sizeof(struct sockaddr_in));
1005 get_to_address(unistimsock, &s->sout);
1006 s->sout.sin_family = AF_INET;
1008 ast_verb(0, "Creating a new entry for the phone from %s received via server ip %s\n",
1009 ast_inet_ntoa(addr_from->sin_addr), ast_inet_ntoa(s->sout.sin_addr));
1011 ast_mutex_init(&s->lock);
1012 ast_mutex_lock(&sessionlock);
1016 s->timeout = get_tick_count() + RETRANSMIT_TIMER;
1017 s->state = STATE_INIT;
1018 s->tick_next_ping = get_tick_count() + unistim_keepalive;
1019 /* Initialize struct wsabuf */
1020 for (tmp = 0; tmp < MAX_BUF_NUMBER; tmp++) {
1021 s->wsabufsend[tmp].buf = s->buf[tmp];
1023 ast_mutex_unlock(&sessionlock);
1027 static void send_end_call(struct unistimsession *pte)
1031 ast_verb(0, "Sending end call\n");
1033 memcpy(buffsend + SIZE_HEADER, packet_send_end_call, sizeof(packet_send_end_call));
1034 send_client(SIZE_HEADER + sizeof(packet_send_end_call), buffsend, pte);
1037 static void set_ping_timer(struct unistimsession *pte)
1039 unsigned int tick = 0; /* XXX what is this for, anyways */
1041 pte->timeout = pte->tick_next_ping;
1042 DEBUG_TIMER("tick = %u next ping at %u tick\n", tick, pte->timeout);
1046 /* Checking if our send queue is empty,
1047 * if true, setting up a timer for keepalive */
1048 static void check_send_queue(struct unistimsession *pte)
1050 /* Check if our send queue contained only one element */
1051 if (pte->last_buf_available == 1) {
1053 ast_verb(6, "Our single packet was ACKed.\n");
1055 pte->last_buf_available--;
1056 set_ping_timer(pte);
1059 /* Check if this ACK catch up our latest packet */
1060 else if (pte->last_seq_ack + 1 == pte->seq_server + 1) {
1062 ast_verb(6, "Our send queue is completely ACKed.\n");
1064 pte->last_buf_available = 0; /* Purge the send queue */
1065 set_ping_timer(pte);
1069 ast_verb(6, "We still have packets in our send queue\n");
1074 static void send_start_timer(struct unistimsession *pte)
1078 ast_verb(0, "Sending start timer\n");
1080 memcpy(buffsend + SIZE_HEADER, packet_send_start_timer, sizeof(packet_send_start_timer));
1081 send_client(SIZE_HEADER + sizeof(packet_send_start_timer), buffsend, pte);
1084 static void send_stop_timer(struct unistimsession *pte)
1088 ast_verb(0, "Sending stop timer\n");
1090 memcpy(buffsend + SIZE_HEADER, packet_send_stop_timer, sizeof(packet_send_stop_timer));
1091 send_client(SIZE_HEADER + sizeof(packet_send_stop_timer), buffsend, pte);
1094 static void send_icon(unsigned char pos, unsigned char status, struct unistimsession *pte)
1098 ast_verb(0, "Sending icon pos %d with status 0x%.2x\n", pos, status);
1100 memcpy(buffsend + SIZE_HEADER, packet_send_icon, sizeof(packet_send_icon));
1102 buffsend[10] = status;
1103 send_client(SIZE_HEADER + sizeof(packet_send_icon), buffsend, pte);
1106 static void send_tone(struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
1111 ast_verb(0, "Sending Stream Based Tone Off\n");
1113 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_off,
1114 sizeof(packet_send_stream_based_tone_off));
1115 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_off), buffsend, pte);
1118 /* Since most of the world use a continuous tone, it's useless
1120 ast_verb(0, "Sending Stream Based Tone Cadence Download\n");
1121 memcpy (buffsend + SIZE_HEADER, packet_send_StreamBasedToneCad, sizeof (packet_send_StreamBasedToneCad));
1122 send_client (SIZE_HEADER + sizeof (packet_send_StreamBasedToneCad), buffsend, pte); */
1124 ast_verb(0, "Sending Stream Based Tone Frequency Component List Download %d %d\n", tone1, tone2);
1128 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_single_freq,
1129 sizeof(packet_send_stream_based_tone_single_freq));
1130 buffsend[10] = (tone1 & 0xff00) >> 8;
1131 buffsend[11] = (tone1 & 0x00ff);
1132 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_single_freq), buffsend,
1136 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dial_freq,
1137 sizeof(packet_send_stream_based_tone_dial_freq));
1138 buffsend[10] = (tone1 & 0xff00) >> 8;
1139 buffsend[11] = (tone1 & 0x00ff);
1140 buffsend[12] = (tone2 & 0xff00) >> 8;
1141 buffsend[13] = (tone2 & 0x00ff);
1142 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_dial_freq), buffsend,
1147 ast_verb(0, "Sending Stream Based Tone On\n");
1149 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_on,
1150 sizeof(packet_send_stream_based_tone_on));
1151 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_on), buffsend, pte);
1154 /* Positions for favorites
1155 |--------------------|
1156 | 5 2 | <-- not on screen in i2002
1161 /* status (icons) : 00 = nothing, 2x/3x = see parser.h, 4x/5x = blink fast, 6x/7x = blink slow */
1163 send_favorite(unsigned char pos, unsigned char status, struct unistimsession *pte,
1170 ast_verb(0, "Sending favorite pos %d with status 0x%.2x\n", pos, status);
1172 memcpy(buffsend + SIZE_HEADER, packet_send_favorite, sizeof(packet_send_favorite));
1175 buffsend[25] = status;
1176 i = strlen(ustmtext(text, pte));
1177 if (i > FAV_MAX_LENGTH) {
1180 memcpy(buffsend + FAV_MAX_LENGTH + 1, ustmtext(text, pte), i);
1181 send_client(SIZE_HEADER + sizeof(packet_send_favorite), buffsend, pte);
1184 static void send_favorite_short(unsigned char pos, unsigned char status, struct unistimsession *pte) {
1185 send_favorite(pos, status, pte, pte->device->softkeylabel[pos]);
1189 static void send_favorite_selected(unsigned char status, struct unistimsession *pte) {
1190 if (pte->device->selected != -1) {
1191 send_favorite(pte->device->selected, status, pte, pte->device->softkeylabel[pte->device->selected]);
1196 static int soft_key_visible(struct unistim_device* d, unsigned char num)
1198 if(d->height == 1 && num % 3 == 2) {
1204 static void refresh_all_favorite(struct unistimsession *pte)
1206 unsigned char i = 0;
1208 struct unistim_line *line;
1209 line = AST_LIST_FIRST(&pte->device->lines);
1212 ast_verb(0, "Refreshing all favorite\n");
1214 for (i = 0; i < FAVNUM; i++) {
1215 unsigned char status = pte->device->softkeyicon[i];
1217 if (!soft_key_visible(pte->device, i)) {
1220 if (!strcasecmp(pte->device->softkeylabel[i], "DND") && line) {
1221 if (!ast_db_get("DND", line->name, data, sizeof(data))) {
1222 status = FAV_ICON_SPEAKER_ONHOOK_WHITE;
1226 send_favorite_short(i, status, pte);
1230 static int is_key_favorite(struct unistim_device *d, int fav)
1232 if ((fav < 0) && (fav > 5)) {
1235 if (d->sline[fav]) {
1238 if (d->softkeynumber[fav][0] == '\0') {
1244 static int is_key_line(struct unistim_device *d, int fav)
1246 if ((fav < 0) && (fav > 5)) {
1249 if (!d->sline[fav]) {
1252 if (is_key_favorite(d, fav)) {
1258 static int get_active_softkey(struct unistimsession *pte)
1260 return pte->device->selected;
1263 static int get_avail_softkey(struct unistimsession *pte, const char* name)
1267 if (!is_key_line(pte->device, pte->device->selected)) {
1268 pte->device->selected = -1;
1270 for (i = 0; i < FAVNUM; i++) {
1271 if (pte->device->selected != -1 && pte->device->selected != i) {
1274 if (!soft_key_visible(pte->device, i)) {
1277 if (pte->device->ssub[i]) {
1280 if (is_key_line(pte->device, i)) {
1281 if (name && strcmp(name, pte->device->sline[i]->name)) {
1285 ast_verb(0, "Found softkey %d for device %s\n", i, name);
1294 /* Change the status for this phone (pte) and update for each phones where pte is bookmarked
1295 * use FAV_ICON_*_BLACK constant in status parameters */
1296 static void change_favorite_icon(struct unistimsession *pte, unsigned char status)
1298 struct unistim_device *d = devices;
1300 /* Update the current phone line softkey icon */
1301 if (pte->state != STATE_CLEANING) {
1302 int softkeylinepos = get_active_softkey(pte);
1303 if (softkeylinepos != -1) {
1304 send_favorite_short(softkeylinepos, status, pte);
1307 /* Notify other phones if we're in their bookmark */
1309 for (i = 0; i < FAVNUM; i++) {
1310 if (d->sp[i] == pte->device) { /* It's us ? */
1311 if (d->softkeyicon[i] != status) { /* Avoid resending the same icon */
1312 d->softkeyicon[i] = status;
1314 send_favorite(i, status + 1, d->session, d->softkeylabel[i]);
1323 static int register_extension(const struct unistimsession *pte)
1325 struct unistim_line *line;
1326 line = AST_LIST_FIRST(&pte->device->lines);
1328 ast_verb(0, "Trying to register extension '%s' into context '%s' to %s\n",
1329 pte->device->extension_number, pte->device->context,
1332 return ast_add_extension(pte->device->context, 0,
1333 pte->device->extension_number, 1, NULL, NULL, "Dial",
1334 line->fullname, 0, "Unistim");
1337 static int unregister_extension(const struct unistimsession *pte)
1340 ast_verb(0, "Trying to unregister extension '%s' context '%s'\n",
1341 pte->device->extension_number, pte->device->context);
1343 return ast_context_remove_extension(pte->device->context,
1344 pte->device->extension_number, 1, "Unistim");
1347 /* Free memory allocated for a phone */
1348 static void close_client(struct unistimsession *s)
1350 struct unistim_subchannel *sub = NULL;
1351 struct unistimsession *cur, *prev = NULL;
1352 ast_mutex_lock(&sessionlock);
1354 /* Looking for the session in the linked chain */
1362 if (cur) { /* Session found ? */
1363 if (cur->device) { /* This session was registered ? */
1364 s->state = STATE_CLEANING;
1366 ast_verb(0, "close_client session %p device %p\n", s, s->device);
1368 change_favorite_icon(s, FAV_ICON_NONE);
1369 ast_mutex_lock(&s->device->lock);
1370 AST_LIST_LOCK(&s->device->subs);
1371 AST_LIST_TRAVERSE_SAFE_BEGIN(&s->device->subs, sub, list) {
1375 if (sub->owner) { /* Call in progress ? */
1377 ast_verb(0, "Aborting call\n");
1379 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NETWORK_OUT_OF_ORDER);
1382 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->subtype, sub->parent->name, s->device->name);
1384 AST_LIST_REMOVE_CURRENT(list);
1385 unistim_free_sub(sub);
1388 AST_LIST_TRAVERSE_SAFE_END;
1389 AST_LIST_UNLOCK(&s->device->subs);
1391 if (!ast_strlen_zero(s->device->extension_number)) {
1392 unregister_extension(s);
1394 cur->device->session = NULL;
1395 ast_mutex_unlock(&s->device->lock);
1398 ast_verb(0, "Freeing an unregistered client\n");
1402 prev->next = cur->next;
1404 sessions = cur->next;
1406 ast_mutex_destroy(&s->lock);
1409 ast_log(LOG_WARNING, "Trying to delete non-existent session %p?\n", s);
1411 ast_mutex_unlock(&sessionlock);
1415 /* Return 1 if the session chained link was modified */
1416 static int send_retransmit(struct unistimsession *pte)
1420 ast_mutex_lock(&pte->lock);
1421 if (++pte->nb_retransmit >= NB_MAX_RETRANSMIT) {
1423 ast_verb(0, "Too many retransmit - freeing client\n");
1425 ast_mutex_unlock(&pte->lock);
1429 pte->timeout = get_tick_count() + RETRANSMIT_TIMER;
1431 for (i = pte->last_buf_available - (pte->seq_server - pte->last_seq_ack);
1432 i < pte->last_buf_available; i++) {
1434 ast_log(LOG_WARNING,
1435 "Asked to retransmit an ACKed slot ! last_buf_available=%d, seq_server = #0x%.4x last_seq_ack = #0x%.4x\n",
1436 pte->last_buf_available, pte->seq_server, pte->last_seq_ack);
1441 unsigned short *sbuf = (unsigned short *) pte->wsabufsend[i].buf;
1444 seq = ntohs(sbuf[1]);
1445 ast_verb(0, "Retransmit slot #%d (seq=#0x%.4x), last ack was #0x%.4x\n", i,
1446 seq, pte->last_seq_ack);
1448 send_raw_client(pte->wsabufsend[i].len, pte->wsabufsend[i].buf, &pte->sin,
1451 ast_mutex_unlock(&pte->lock);
1455 /* inverse : TEXT_INVERSE : yes, TEXT_NORMAL : no */
1457 send_text(unsigned char pos, unsigned char inverse, struct unistimsession *pte,
1463 ast_log(LOG_ERROR, "Asked to display NULL text (pos %d, inverse flag %d)\n", pos, inverse);
1466 if (pte->device && pte->device->height == 1 && pos != TEXT_LINE0) {
1470 ast_verb(0, "Sending text at pos %d, inverse flag %d\n", pos, inverse);
1472 memcpy(buffsend + SIZE_HEADER, packet_send_text, sizeof(packet_send_text));
1474 buffsend[11] = inverse;
1476 if (i > TEXT_LENGTH_MAX) {
1477 i = TEXT_LENGTH_MAX;
1479 memcpy(buffsend + 12, text, i);
1480 send_client(SIZE_HEADER + sizeof(packet_send_text), buffsend, pte);
1483 static void send_text_status(struct unistimsession *pte, const char *text)
1488 ast_verb(0, "Sending status text\n");
1491 if (pte->device->status_method == 1) { /* For new firmware and i2050 soft phone */
1492 int n = strlen(text);
1493 /* Must send individual button separately */
1495 for (i = 0, j = 0; i < 4; i++, j += 7) {
1496 int pos = 0x08 + (i * 0x20);
1497 memcpy(buffsend + SIZE_HEADER, packet_send_status2,
1498 sizeof(packet_send_status2));
1501 memcpy(buffsend + 10, (j < n) ? (text + j) : " ", 7);
1502 send_client(SIZE_HEADER + sizeof(packet_send_status2), buffsend, pte);
1509 memcpy(buffsend + SIZE_HEADER, packet_send_status, sizeof(packet_send_status));
1511 if (i > STATUS_LENGTH_MAX) {
1512 i = STATUS_LENGTH_MAX;
1514 memcpy(buffsend + 10, text, i);
1515 send_client(SIZE_HEADER + sizeof(packet_send_status), buffsend, pte);
1519 /* led values in hexa : 0 = bar off, 1 = bar on, 2 = bar 1s on/1s off, 3 = bar 2.5s on/0.5s off
1520 * 4 = bar 0.6s on/0.3s off, 5 = bar 0.5s on/0.5s off, 6 = bar 2s on/0.5s off
1521 * 7 = bar off, 8 = speaker off, 9 = speaker on, 10 = headphone off, 11 = headphone on
1522 * 18 = mute off, 19 mute on */
1523 static void send_led_update(struct unistimsession *pte, unsigned char led)
1527 ast_verb(0, "Sending led_update (%x)\n", led);
1529 memcpy(buffsend + SIZE_HEADER, packet_send_led_update, sizeof(packet_send_led_update));
1531 send_client(SIZE_HEADER + sizeof(packet_send_led_update), buffsend, pte);
1534 /* output = OUTPUT_HANDSET, OUTPUT_HEADPHONE or OUTPUT_SPEAKER
1535 * volume = VOLUME_LOW, VOLUME_NORMAL, VOLUME_INSANELY_LOUD
1536 * mute = MUTE_OFF, MUTE_ON */
1538 send_select_output(struct unistimsession *pte, unsigned char output, unsigned char volume,
1543 ast_verb(0, "Sending select output packet output=%x volume=%x mute=%x\n", output,
1546 memcpy(buffsend + SIZE_HEADER, packet_send_select_output,
1547 sizeof(packet_send_select_output));
1548 buffsend[9] = output;
1549 if (output == OUTPUT_SPEAKER) {
1550 volume = VOLUME_LOW_SPEAKER;
1552 volume = VOLUME_LOW;
1554 buffsend[10] = volume;
1555 if (mute == MUTE_ON_DISCRET) {
1556 buffsend[11] = MUTE_ON;
1558 buffsend[11] = mute;
1560 send_client(SIZE_HEADER + sizeof(packet_send_select_output), buffsend, pte);
1561 if (mute == MUTE_OFF) {
1562 send_led_update(pte, 0x18);
1563 } else if (mute == MUTE_ON) {
1564 send_led_update(pte, 0x19);
1566 pte->device->mute = mute;
1567 if (output == OUTPUT_HANDSET) {
1568 if (mute == MUTE_ON) {
1569 change_favorite_icon(pte, FAV_ICON_ONHOLD_BLACK);
1571 change_favorite_icon(pte, FAV_ICON_OFFHOOK_BLACK);
1573 send_led_update(pte, 0x08);
1574 send_led_update(pte, 0x10);
1575 } else if (output == OUTPUT_HEADPHONE) {
1576 if (mute == MUTE_ON) {
1577 change_favorite_icon(pte, FAV_ICON_HEADPHONES_ONHOLD);
1579 change_favorite_icon(pte, FAV_ICON_HEADPHONES);
1581 send_led_update(pte, 0x08);
1582 send_led_update(pte, 0x11);
1583 } else if (output == OUTPUT_SPEAKER) {
1584 send_led_update(pte, 0x10);
1585 send_led_update(pte, 0x09);
1586 if (pte->device->receiver_state == STATE_OFFHOOK) {
1587 if (mute == MUTE_ON) {
1588 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1590 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOOK_BLACK);
1593 if (mute == MUTE_ON) {
1594 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1596 change_favorite_icon(pte, FAV_ICON_SPEAKER_OFFHOOK_BLACK);
1600 ast_log(LOG_WARNING, "Invalid output (%d)\n", output);
1602 if (output != pte->device->output) {
1603 pte->device->previous_output = pte->device->output;
1605 pte->device->output = output;
1608 static void send_ring(struct unistimsession *pte, char volume, char style)
1612 ast_verb(0, "Sending ring packet\n");
1614 memcpy(buffsend + SIZE_HEADER, packet_send_ring, sizeof(packet_send_ring));
1615 buffsend[24] = style + 0x10;
1616 buffsend[29] = volume * 0x10;
1617 send_client(SIZE_HEADER + sizeof(packet_send_ring), buffsend, pte);
1620 static void send_no_ring(struct unistimsession *pte)
1624 ast_verb(0, "Sending no ring packet\n");
1626 memcpy(buffsend + SIZE_HEADER, packet_send_no_ring, sizeof(packet_send_no_ring));
1627 send_client(SIZE_HEADER + sizeof(packet_send_no_ring), buffsend, pte);
1630 static void send_texttitle(struct unistimsession *pte, const char *text)
1635 ast_verb(0, "Sending title text\n");
1637 memcpy(buffsend + SIZE_HEADER, packet_send_title, sizeof(packet_send_title));
1642 memcpy(buffsend + 10, text, i);
1643 send_client(SIZE_HEADER + sizeof(packet_send_title), buffsend, pte);
1647 static void send_idle_clock(struct unistimsession *pte)
1649 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
1652 static void send_date_time(struct unistimsession *pte)
1655 struct timeval now = ast_tvnow();
1656 struct ast_tm atm = { 0, };
1659 ast_verb(0, "Sending Time & Date\n");
1661 memcpy(buffsend + SIZE_HEADER, packet_send_date_time, sizeof(packet_send_date_time));
1662 ast_localtime(&now, &atm, NULL);
1663 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1664 buffsend[11] = (unsigned char) atm.tm_mday;
1665 buffsend[12] = (unsigned char) atm.tm_hour;
1666 buffsend[13] = (unsigned char) atm.tm_min;
1667 send_client(SIZE_HEADER + sizeof(packet_send_date_time), buffsend, pte);
1670 static void send_date_time2(struct unistimsession *pte)
1673 struct timeval now = ast_tvnow();
1674 struct ast_tm atm = { 0, };
1677 ast_verb(0, "Sending Time & Date #2\n");
1679 memcpy(buffsend + SIZE_HEADER, packet_send_date_time2, sizeof(packet_send_date_time2));
1680 ast_localtime(&now, &atm, NULL);
1682 buffsend[9] = pte->device->datetimeformat;
1686 buffsend[14] = (unsigned char) atm.tm_mon + 1;
1687 buffsend[15] = (unsigned char) atm.tm_mday;
1688 buffsend[16] = (unsigned char) atm.tm_hour;
1689 buffsend[17] = (unsigned char) atm.tm_min;
1690 send_client(SIZE_HEADER + sizeof(packet_send_date_time2), buffsend, pte);
1693 static void send_date_time3(struct unistimsession *pte)
1696 struct timeval now = ast_tvnow();
1697 struct ast_tm atm = { 0, };
1700 ast_verb(0, "Sending Time & Date #3\n");
1702 memcpy(buffsend + SIZE_HEADER, packet_send_date_time3, sizeof(packet_send_date_time3));
1703 ast_localtime(&now, &atm, NULL);
1704 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1705 buffsend[11] = (unsigned char) atm.tm_mday;
1706 buffsend[12] = (unsigned char) atm.tm_hour;
1707 buffsend[13] = (unsigned char) atm.tm_min;
1708 send_client(SIZE_HEADER + sizeof(packet_send_date_time3), buffsend, pte);
1711 static void send_blink_cursor(struct unistimsession *pte)
1715 ast_verb(0, "Sending set blink\n");
1717 memcpy(buffsend + SIZE_HEADER, packet_send_blink_cursor, sizeof(packet_send_blink_cursor));
1718 send_client(SIZE_HEADER + sizeof(packet_send_blink_cursor), buffsend, pte);
1722 /* pos : 0xab (a=0/2/4 = line ; b = row) */
1723 static void send_cursor_pos(struct unistimsession *pte, unsigned char pos)
1727 ast_verb(0, "Sending set cursor position\n");
1729 memcpy(buffsend + SIZE_HEADER, packet_send_set_pos_cursor,
1730 sizeof(packet_send_set_pos_cursor));
1732 send_client(SIZE_HEADER + sizeof(packet_send_set_pos_cursor), buffsend, pte);
1736 static void send_charset_update(struct unistimsession *pte, int charset)
1738 const unsigned char* packet_send_charset;
1742 ast_verb(0, "Sending set default charset\n");
1744 if (charset == LANG_DEFAULT) {
1745 charset = options_languages[find_language(pte->device->language)].encoding;
1749 packet_send_charset = packet_send_charset_iso_8859_2;
1750 packet_size = sizeof(packet_send_charset_iso_8859_2);
1753 packet_send_charset = packet_send_charset_iso_8859_4;
1754 packet_size = sizeof(packet_send_charset_iso_8859_4);
1757 packet_send_charset = packet_send_charset_iso_8859_5;
1758 packet_size = sizeof(packet_send_charset_iso_8859_5);
1761 packet_send_charset = packet_send_charset_iso_2022_jp;
1762 packet_size = sizeof(packet_send_charset_iso_2022_jp);
1766 packet_send_charset = packet_send_charset_iso_8859_1;
1767 packet_size = sizeof(packet_send_charset_iso_8859_1);
1769 memcpy(buffsend + SIZE_HEADER, packet_send_charset, packet_size);
1770 send_client(SIZE_HEADER + packet_size, buffsend, pte);
1774 static void rcv_resume_connection_with_server(struct unistimsession *pte)
1778 ast_verb(0, "ResumeConnectionWithServer received\n");
1779 ast_verb(0, "Sending packet_send_query_mac_address\n");
1781 memcpy(buffsend + SIZE_HEADER, packet_send_query_mac_address,
1782 sizeof(packet_send_query_mac_address));
1783 send_client(SIZE_HEADER + sizeof(packet_send_query_mac_address), buffsend, pte);
1787 static int unistim_register(struct unistimsession *s)
1789 struct unistim_device *d;
1791 ast_mutex_lock(&devicelock);
1794 if (!strcasecmp(s->macaddr, d->id)) {
1795 /* XXX Deal with IP authentication */
1798 d->codec_number = DEFAULT_CODEC;
1800 d->receiver_state = STATE_ONHOOK;
1805 ast_mutex_unlock(&devicelock);
1814 static void unistim_line_copy(struct unistim_line *dst, struct unistim_line *src)
1816 struct ast_format_cap *tmp = src->cap;
1817 memcpy(dst, src, sizeof(*dst)); /* this over writes the cap ptr, so we have to reset it */
1819 ast_format_cap_copy(src->cap, dst->cap);
1822 static struct unistim_line *unistim_line_destroy(struct unistim_line *l)
1827 l->cap = ast_format_cap_destroy(l->cap);
1832 static struct unistim_line *unistim_line_alloc(void)
1834 struct unistim_line *l;
1835 if (!(l = ast_calloc(1, sizeof(*l)))) {
1839 if (!(l->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
1846 static int unistim_free_sub(struct unistim_subchannel *sub) {
1848 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->subtype, sub->parent->name, sub->parent->parent->name);
1850 ast_mutex_destroy(&sub->lock);
1855 static struct unistim_subchannel *unistim_alloc_sub(struct unistim_device *d, int x)
1857 struct unistim_subchannel *sub;
1858 if (!(sub = ast_calloc(1, sizeof(*sub)))) {
1863 ast_verb(3, "Allocating UNISTIM subchannel #%d on %s ptr=%p\n", x, d->name, sub);
1865 sub->ss_thread = AST_PTHREADT_NULL;
1867 AST_LIST_LOCK(&d->subs);
1868 AST_LIST_INSERT_TAIL(&d->subs, sub, list);
1869 AST_LIST_UNLOCK(&d->subs);
1870 ast_mutex_init(&sub->lock);
1874 static int unistim_unalloc_sub(struct unistim_device *d, struct unistim_subchannel *sub)
1876 struct unistim_subchannel *s;
1878 AST_LIST_LOCK(&d->subs);
1879 AST_LIST_TRAVERSE_SAFE_BEGIN(&d->subs, s, list) {
1886 AST_LIST_REMOVE_CURRENT(list);
1887 unistim_free_sub(sub);
1889 AST_LIST_TRAVERSE_SAFE_END;
1890 AST_LIST_UNLOCK(&d->subs);
1894 static const char *subtype_tostr(const int type)
1909 static const char *ptestate_tostr(const int type)
1914 case STATE_AUTHDENY:
1916 case STATE_MAINPAGE:
1918 case STATE_EXTENSION:
1920 case STATE_DIALPAGE:
1926 case STATE_SELECTOPTION:
1927 return "SELECTOPTION";
1928 case STATE_SELECTCODEC:
1929 return "SELECTCODEC";
1930 case STATE_SELECTLANGUAGE:
1931 return "SELECTLANGUAGE";
1932 case STATE_CLEANING:
1940 static void rcv_mac_addr(struct unistimsession *pte, const unsigned char *buf)
1946 for (tmp = 15; tmp < 15 + SIZE_HEADER; tmp++) {
1947 sprintf(&addrmac[i], "%.2x", (unsigned char) buf[tmp]);
1951 ast_verb(0, "MAC Address received: %s\n", addrmac);
1953 strcpy(pte->macaddr, addrmac);
1954 res = unistim_register(pte);
1956 switch (autoprovisioning) {
1957 case AUTOPROVISIONING_NO:
1958 ast_log(LOG_WARNING, "No entry found for this phone : %s\n", addrmac);
1959 pte->state = STATE_AUTHDENY;
1961 case AUTOPROVISIONING_YES:
1963 struct unistim_device *d = NULL, *newd = NULL;
1964 struct unistim_line *newl = NULL, *l = NULL;
1966 ast_verb(0, "New phone, autoprovisioning on\n");
1968 /* First : locate the [template] section */
1969 ast_mutex_lock(&devicelock);
1972 if (strcasecmp(d->name, "template")) {
1976 /* Found, cloning this entry */
1977 if (!(newd = ast_malloc(sizeof(*newd)))) {
1978 ast_mutex_unlock(&devicelock);
1981 memcpy(newd, d, sizeof(*newd));
1982 ast_mutex_init(&newd->lock);
1983 newd->lines.first = NULL;
1984 newd->lines.last = NULL;
1985 AST_LIST_LOCK(&d->lines);
1986 AST_LIST_TRAVERSE(&d->lines, l, list) {
1987 if (!(newl = unistim_line_alloc())) {
1990 unistim_line_copy(l, newl);
1991 newl->parent = newd;
1992 ast_copy_string(newl->name, l->name, sizeof(newl->name));
1993 snprintf(newl->fullname, sizeof(newl->fullname), "USTM/%s@%s",
1994 newl->name, newd->name);
1995 snprintf(l->name, sizeof(l->name), "%d", atoi(l->name) + 1);
1997 AST_LIST_LOCK(&newd->lines);
1998 AST_LIST_INSERT_TAIL(&newd->lines, newl, list);
1999 AST_LIST_UNLOCK(&newd->lines);
2001 AST_LIST_UNLOCK(&d->lines);
2004 ast_mutex_unlock(&devicelock);
2007 /* Ok, now updating some fields */
2008 ast_copy_string(newd->id, addrmac, sizeof(newd->id));
2009 ast_copy_string(newd->name, addrmac, sizeof(newd->name));
2010 if (newd->extension == EXTENSION_NONE) {
2011 newd->extension = EXTENSION_ASK;
2014 newd->receiver_state = STATE_ONHOOK;
2015 newd->session = pte;
2016 newd->language[0] = '\0';
2017 newd->to_delete = -1;
2021 /* Go to the end of the linked chain */
2029 ast_mutex_unlock(&devicelock);
2031 ast_log(LOG_WARNING, "No entry [template] found in unistim.conf\n");
2032 pte->state = STATE_AUTHDENY;
2036 case AUTOPROVISIONING_TN:
2037 pte->state = STATE_AUTHDENY;
2040 ast_log(LOG_WARNING, "Internal error : unknown autoprovisioning value = %d\n",
2044 if (pte->state != STATE_AUTHDENY) {
2045 struct unistim_line *line;
2046 struct unistim_subchannel *sub;
2048 ast_verb(3, "Device '%s' successfuly registered\n", pte->device->name);
2050 AST_LIST_LOCK(&pte->device->subs);
2051 AST_LIST_TRAVERSE_SAFE_BEGIN(&pte->device->subs, sub, list) {
2053 ast_log(LOG_ERROR, "Subchannel lost sice reboot. Hanged channel may apear!\n");
2054 AST_LIST_REMOVE_CURRENT(list);
2058 AST_LIST_TRAVERSE_SAFE_END;
2059 AST_LIST_UNLOCK(&pte->device->subs);
2061 switch (pte->device->extension) {
2062 case EXTENSION_NONE:
2063 pte->state = STATE_MAINPAGE;
2066 /* Checking if we already have an extension number */
2067 if (ast_strlen_zero(pte->device->extension_number)) {
2068 pte->state = STATE_EXTENSION;
2070 /* Yes, because of a phone reboot. We don't ask again for the TN */
2071 if (register_extension(pte)) {
2072 pte->state = STATE_EXTENSION;
2074 pte->state = STATE_MAINPAGE;
2078 case EXTENSION_LINE:
2079 line = AST_LIST_FIRST(&pte->device->lines);
2080 ast_copy_string(pte->device->extension_number, line->name,
2081 sizeof(pte->device->extension_number));
2082 if (register_extension(pte)) {
2083 pte->state = STATE_EXTENSION;
2085 pte->state = STATE_MAINPAGE;
2089 /* If we are here, it's because of a phone reboot */
2090 pte->state = STATE_MAINPAGE;
2093 ast_log(LOG_WARNING, "Internal error, extension value unknown : %d\n",
2094 pte->device->extension);
2095 pte->state = STATE_AUTHDENY;
2099 if (pte->state == STATE_EXTENSION) {
2100 if (pte->device->extension != EXTENSION_TN) {
2101 pte->device->extension = EXTENSION_ASK;
2103 pte->device->extension_number[0] = '\0';
2106 ast_verb(0, "\nSending S1\n");
2108 memcpy(buffsend + SIZE_HEADER, packet_send_S1, sizeof(packet_send_S1));
2109 send_client(SIZE_HEADER + sizeof(packet_send_S1), buffsend, pte);
2112 ast_verb(0, "Sending query_basic_manager_04\n");
2114 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_04,
2115 sizeof(packet_send_query_basic_manager_04));
2116 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_04), buffsend, pte);
2119 ast_verb(0, "Sending query_basic_manager_10\n");
2121 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_10,
2122 sizeof(packet_send_query_basic_manager_10));
2123 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_10), buffsend, pte);
2125 send_date_time(pte);
2129 static int write_entry_history(struct unistimsession *pte, FILE * f, char c, char *line1)
2131 if (fwrite(&c, 1, 1, f) != 1) {
2132 display_last_error("Unable to write history log header.");
2135 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
2136 display_last_error("Unable to write history entry - date.");
2139 if (fwrite(pte->device->lst_cid, TEXT_LENGTH_MAX, 1, f) != 1) {
2140 display_last_error("Unable to write history entry - callerid.");
2143 if (fwrite(pte->device->lst_cnm, TEXT_LENGTH_MAX, 1, f) != 1) {
2144 display_last_error("Unable to write history entry - callername.");
2150 static int write_history(struct unistimsession *pte, char way, char ismissed)
2152 char tmp[AST_CONFIG_MAX_PATH], tmp2[AST_CONFIG_MAX_PATH];
2153 char line1[TEXT_LENGTH_MAX + 1];
2154 char count = 0, *histbuf;
2157 struct timeval now = ast_tvnow();
2158 struct ast_tm atm = { 0, };
2163 if (!pte->device->callhistory) {
2166 if (strchr(pte->device->name, '/') || (pte->device->name[0] == '.')) {
2167 ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n",
2172 snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_LOG_DIR, USTM_LOG_DIR);
2173 if (ast_mkdir(tmp, 0770)) {
2174 ast_log(LOG_WARNING, "Unable to create directory for history\n");
2178 ast_localtime(&now, &atm, NULL);
2181 ast_copy_string(tmp2, ustmtext("Miss", pte), sizeof(tmp2));
2183 ast_copy_string(tmp2, ustmtext("Fail", pte), sizeof(tmp2));
2186 ast_copy_string(tmp2, ustmtext("Answ", pte), sizeof(tmp2));
2188 snprintf(line1, sizeof(line1), "%04d/%02d/%02d %02d:%02d:%02d %s",
2189 atm.tm_year + 1900, atm.tm_mon + 1, atm.tm_mday, atm.tm_hour,
2190 atm.tm_min, atm.tm_sec, tmp2);
2192 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
2193 USTM_LOG_DIR, pte->device->name, way);
2194 if ((f = fopen(tmp, "r"))) {
2195 struct stat bufstat;
2197 if (stat(tmp, &bufstat)) {
2198 display_last_error("Unable to stat history log.");
2202 size = 1 + (MAX_ENTRY_LOG * TEXT_LENGTH_MAX * 3);
2203 if (bufstat.st_size != size) {
2204 ast_log(LOG_WARNING,
2205 "History file %s has an incorrect size (%d instead of %d). It will be replaced by a new one.",
2206 tmp, (int) bufstat.st_size, size);
2213 /* If we can't open the log file, we create a brand new one */
2218 if ((errno != ENOENT) && (count == 0)) {
2219 display_last_error("Unable to open history log.");
2222 f = fopen(tmp, "w");
2224 display_last_error("Unable to create history log.");
2227 if (write_entry_history(pte, f, c, line1)) {
2231 memset(line1, ' ', TEXT_LENGTH_MAX);
2232 for (i = 3; i < MAX_ENTRY_LOG * 3; i++) {
2233 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
2234 display_last_error("Unable to write history entry - stuffing.");
2240 display_last_error("Unable to close history - creation.");
2244 /* We can open the log file, we create a temporary one, we add our entry and copy the rest */
2245 if (fread(&count, 1, 1, f) != 1) {
2246 display_last_error("Unable to read history header.");
2250 if (count > MAX_ENTRY_LOG) {
2251 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
2252 count, MAX_ENTRY_LOG);
2256 snprintf(tmp2, sizeof(tmp2), "%s/%s/%s-%c.csv.tmp", ast_config_AST_LOG_DIR,
2257 USTM_LOG_DIR, pte->device->name, way);
2258 if (!(f2 = fopen(tmp2, "w"))) {
2259 display_last_error("Unable to create temporary history log.");
2264 if (++count > MAX_ENTRY_LOG) {
2265 count = MAX_ENTRY_LOG;
2267 if (write_entry_history(pte, f2, count, line1)) {
2272 size = (MAX_ENTRY_LOG - 1) * TEXT_LENGTH_MAX * 3;
2273 if (!(histbuf = ast_malloc(size))) {
2279 if (fread(histbuf, size, 1, f) != 1) {
2283 display_last_error("Unable to read previous history entries.");
2286 if (fwrite(histbuf, size, 1, f2) != 1) {
2290 display_last_error("Unable to write previous history entries.");
2295 display_last_error("Unable to close history log.");
2298 display_last_error("Unable to close temporary history log.");
2301 display_last_error("Unable to remove old history log.");
2303 if (rename(tmp2, tmp)) {
2304 display_last_error("Unable to rename new history log.");
2309 static int attempt_transfer(struct unistim_subchannel *p1, struct unistim_subchannel *p2)
2311 RAII_VAR(struct ast_channel *, chana, NULL, ast_channel_unref);
2312 RAII_VAR(struct ast_channel *, chanb, NULL, ast_channel_unref);
2314 if (!p1->owner || !p2->owner) {
2315 ast_log(LOG_WARNING, "Transfer attempted without dual ownership?\n");
2318 chana = ast_channel_ref(p1->owner);
2319 chanb = ast_channel_ref(p2->owner);
2321 switch (ast_bridge_transfer_attended(chana, chanb)) {
2322 case AST_BRIDGE_TRANSFER_INVALID:
2323 ast_log(LOG_WARNING, "Transfer failed. Invalid bridge setup\n");
2325 case AST_BRIDGE_TRANSFER_NOT_PERMITTED:
2326 ast_log(LOG_WARNING, "Transfer not permitted\n");
2328 case AST_BRIDGE_TRANSFER_FAIL:
2329 ast_log(LOG_WARNING, "Transfer encountered internal error\n");
2331 case AST_BRIDGE_TRANSFER_SUCCESS:
2335 /* Control only reaches this point if transfer has failed */
2336 ast_softhangup_nolock(chana, AST_SOFTHANGUP_DEV);
2337 ast_softhangup_nolock(chanb, AST_SOFTHANGUP_DEV);
2341 void change_callerid(struct unistimsession *pte, int type, char *callerid)
2347 data = pte->device->lst_cnm;
2349 data = pte->device->lst_cid;
2352 /* This is very nearly strncpy(), except that the remaining buffer
2353 * is padded with ' ', instead of '\0' */
2354 memset(data, ' ', TEXT_LENGTH_MAX);
2355 size = strlen(callerid);
2356 if (size > TEXT_LENGTH_MAX) {
2357 size = TEXT_LENGTH_MAX;
2359 memcpy(data, callerid, size);
2362 static struct unistim_subchannel* get_sub(struct unistim_device *device, int type)
2364 struct unistim_subchannel *sub = NULL;
2366 AST_LIST_LOCK(&device->subs);
2367 AST_LIST_TRAVERSE(&device->subs, sub, list) {
2371 if (sub->subtype == type) {
2375 AST_LIST_UNLOCK(&device->subs);
2380 static void sub_start_silence(struct unistimsession *pte, struct unistim_subchannel *sub)
2382 /* Silence our channel */
2383 if (!pte->device->silence_generator) {
2384 pte->device->silence_generator =
2385 ast_channel_start_silence_generator(sub->owner);
2386 if (pte->device->silence_generator == NULL) {
2387 ast_log(LOG_WARNING, "Unable to start a silence generator.\n");
2388 } else if (unistimdebug) {
2389 ast_verb(0, "Starting silence generator\n");
2395 static void sub_stop_silence(struct unistimsession *pte, struct unistim_subchannel *sub)
2397 /* Stop the silence generator */
2398 if (pte->device->silence_generator) {
2400 ast_verb(0, "Stopping silence generator\n");
2403 ast_channel_stop_silence_generator(sub->owner, pte->device->silence_generator);
2405 ast_log(LOG_WARNING, "Trying to stop silence generator on a null channel!\n");
2407 pte->device->silence_generator = NULL;
2411 static void sub_hold(struct unistimsession *pte, struct unistim_subchannel *sub)
2417 sub->subtype = SUB_ONHOLD;
2418 send_favorite_short(sub->softkey, FAV_ICON_ONHOLD_BLACK + FAV_BLINK_SLOW, pte);
2419 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
2420 send_stop_timer(pte);
2422 ast_queue_hold(sub->owner, NULL);
2428 static void sub_unhold(struct unistimsession *pte, struct unistim_subchannel *sub)
2430 struct unistim_subchannel *sub_real;
2432 sub_real = get_sub(pte->device, SUB_REAL);
2434 sub_hold(pte, sub_real);
2438 sub->subtype = SUB_REAL;
2439 send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, pte);
2440 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2441 send_start_timer(pte);
2443 ast_queue_unhold(sub->owner);
2445 send_start_rtp(sub);
2451 static void close_call(struct unistimsession *pte)
2453 struct unistim_subchannel *sub, *sub_transf;
2455 sub = get_sub(pte->device, SUB_REAL);
2456 sub_transf = get_sub(pte->device, SUB_THREEWAY);
2457 send_stop_timer(pte);
2459 ast_log(LOG_WARNING, "Close call without sub\n");
2462 send_favorite_short(sub->softkey, FAV_LINE_ICON, pte);
2464 sub->alreadygone = 1;
2466 sub_transf->alreadygone = 1;
2467 if (attempt_transfer(sub, sub_transf) < 0) {
2468 ast_verb(0, "attempt_transfer failed.\n");
2471 ast_queue_hangup(sub->owner);
2475 if (sub_transf->owner) {
2476 ast_queue_hangup_with_cause(sub_transf->owner, AST_CAUSE_NORMAL_CLEARING);
2478 ast_log(LOG_WARNING, "threeway sub without owner\n");
2481 ast_verb(0, "USTM(%s@%s-%d) channel already destroyed\n", sub->parent->name,
2482 pte->device->name, sub->softkey);
2485 change_callerid(pte, 0, pte->device->redial_number);
2486 change_callerid(pte, 1, "");
2487 write_history(pte, 'o', pte->device->missed_call);
2488 pte->device->missed_call = 0;
2489 show_main_page(pte);
2493 static void ignore_call(struct unistimsession *pte)
2499 static void discard_call(struct unistimsession *pte)
2501 struct unistim_subchannel* sub;
2502 sub = get_sub(pte->device, SUB_RING);
2507 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NORMAL_CLEARING);
2511 static void *unistim_ss(void *data)
2513 struct ast_channel *chan = data;
2514 struct unistim_subchannel *sub = ast_channel_tech_pvt(chan);
2515 struct unistim_line *l = sub->parent;
2516 struct unistimsession *s = l->parent->session;
2519 ast_verb(3, "Starting switch on '%s@%s-%d' to %s\n", l->name, l->parent->name, sub->softkey, s->device->phone_number);
2520 ast_channel_lock(chan);
2521 ast_channel_exten_set(chan, s->device->phone_number);
2522 ast_setstate(chan, AST_STATE_RING);
2523 ast_channel_unlock(chan);
2524 ast_copy_string(s->device->redial_number, s->device->phone_number,
2525 sizeof(s->device->redial_number));
2526 res = ast_pbx_run(chan);
2528 ast_log(LOG_WARNING, "PBX exited non-zero\n");
2529 send_tone(s, 1000, 0);
2534 static int find_rtp_port(struct unistim_subchannel *s)
2536 struct unistim_subchannel *sub = NULL;
2537 int rtp_start = s->parent->parent->rtp_port;
2538 struct ast_sockaddr us_tmp;
2539 struct sockaddr_in us = { 0, };
2541 AST_LIST_LOCK(&s->parent->parent->subs);
2542 AST_LIST_TRAVERSE(&s->parent->parent->subs, sub, list) {
2547 ast_rtp_instance_get_remote_address(sub->rtp, &us_tmp);
2548 ast_sockaddr_to_sin(&us_tmp, &us);
2549 if (htons(us.sin_port)) {
2550 rtp_start = htons(us.sin_port) + 1;
2555 AST_LIST_UNLOCK(&s->parent->parent->subs);
2559 static void send_start_rtp(struct unistim_subchannel *sub)
2564 struct sockaddr_in public = { 0, };
2565 struct sockaddr_in us = { 0, };
2566 struct sockaddr_in sin = { 0, };
2567 struct ast_sockaddr us_tmp;
2568 struct ast_sockaddr sin_tmp;
2569 struct unistimsession *pte;
2571 ast_rtp_instance_get_local_address(sub->rtp, &us_tmp);
2572 ast_sockaddr_to_sin(&us_tmp, &us);
2573 ast_rtp_instance_get_remote_address(sub->rtp, &sin_tmp);
2574 ast_sockaddr_to_sin(&sin_tmp, &sin);
2576 /* Setting up RTP of the phone */
2577 if (public_ip.sin_family == 0) { /* NAT IP override ? */
2578 memcpy(&public, &us, sizeof(public)); /* No defined, using IP from recvmsg */
2580 memcpy(&public, &public_ip, sizeof(public)); /* override */
2583 ast_verb(0, "RTP started : Our IP/port is : %s:%hd with codec %s\n",
2584 ast_inet_ntoa(us.sin_addr),
2585 htons(us.sin_port), ast_getformatname(ast_channel_readformat(sub->owner)));
2586 ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n",
2587 ast_inet_ntoa(public.sin_addr));
2590 pte = sub->parent->parent->session;
2591 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, ast_channel_readformat(sub->owner), 0);
2592 if ((ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) ||
2593 (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW)) {
2595 ast_verb(0, "Sending packet_send_rtp_packet_size for codec %d\n", codec);
2597 memcpy(buffsend + SIZE_HEADER, packet_send_rtp_packet_size,
2598 sizeof(packet_send_rtp_packet_size));
2599 buffsend[10] = (int) codec & 0xffffffffLL;
2600 send_client(SIZE_HEADER + sizeof(packet_send_rtp_packet_size), buffsend, pte);
2603 ast_verb(0, "Sending Jitter Buffer Parameters Configuration\n");
2605 memcpy(buffsend + SIZE_HEADER, packet_send_jitter_buffer_conf,
2606 sizeof(packet_send_jitter_buffer_conf));
2607 send_client(SIZE_HEADER + sizeof(packet_send_jitter_buffer_conf), buffsend, pte);
2608 if (pte->device->rtp_method != 0) {
2609 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2612 ast_verb(0, "Sending OpenAudioStreamTX using method #%d\n", pte->device->rtp_method);
2614 if (pte->device->rtp_method == 3) {
2615 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx3,
2616 sizeof(packet_send_open_audio_stream_tx3));
2618 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx,
2619 sizeof(packet_send_open_audio_stream_tx));
2621 if (pte->device->rtp_method != 2) {
2622 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2623 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2624 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2625 buffsend[23] = (rtcpsin_port & 0x00ff);
2626 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2627 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2628 buffsend[24] = (us.sin_port & 0x00ff);
2629 buffsend[27] = (rtcpsin_port & 0x00ff);
2630 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2632 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2633 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2634 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2635 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2636 buffsend[19] = (us.sin_port & 0x00ff);
2638 buffsend[11] = codec; /* rx */
2639 buffsend[12] = codec; /* tx */
2640 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_tx), buffsend, pte);
2643 ast_verb(0, "Sending OpenAudioStreamRX\n");
2645 if (pte->device->rtp_method == 3) {
2646 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx3,
2647 sizeof(packet_send_open_audio_stream_rx3));
2649 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx,
2650 sizeof(packet_send_open_audio_stream_rx));
2652 if (pte->device->rtp_method != 2) {
2653 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2654 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2655 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2656 buffsend[23] = (rtcpsin_port & 0x00ff);
2657 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2658 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2659 buffsend[24] = (us.sin_port & 0x00ff);
2660 buffsend[27] = (rtcpsin_port & 0x00ff);
2661 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2663 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2664 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2665 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2666 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2667 buffsend[19] = (us.sin_port & 0x00ff);
2669 buffsend[11] = codec; /* rx */
2670 buffsend[12] = codec; /* tx */
2671 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_rx), buffsend, pte);
2673 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2676 ast_verb(0, "Sending packet_send_call default method\n");
2679 memcpy(buffsend + SIZE_HEADER, packet_send_call, sizeof(packet_send_call));
2680 memcpy(buffsend + 53, &public.sin_addr, sizeof(public.sin_addr));
2681 /* Destination port when sending RTP */
2682 buffsend[49] = (us.sin_port & 0x00ff);
2683 buffsend[50] = (us.sin_port & 0xff00) >> 8;
2684 /* Destination port when sending RTCP */
2685 buffsend[52] = (rtcpsin_port & 0x00ff);
2686 buffsend[51] = (rtcpsin_port & 0xff00) >> 8;
2688 buffsend[40] = codec;
2689 buffsend[41] = codec;
2690 if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) {
2691 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2692 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW) {
2693 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2694 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G723_1) {
2695 buffsend[42] = 2; /* 1 = 30ms (24 bytes), 2 = 60 ms (48 bytes) */
2696 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G729A) {
2697 buffsend[42] = 2; /* 1 = 10ms (10 bytes), 2 = 20ms (20 bytes) */
2699 ast_log(LOG_WARNING, "Unsupported codec %s!\n",
2700 ast_getformatname(ast_channel_readformat(sub->owner)));
2702 /* Source port for transmit RTP and Destination port for receiving RTP */
2703 buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8;
2704 buffsend[46] = (htons(sin.sin_port) & 0x00ff);
2705 buffsend[47] = (rtcpsin_port & 0xff00) >> 8;
2706 buffsend[48] = (rtcpsin_port & 0x00ff);
2707 send_client(SIZE_HEADER + sizeof(packet_send_call), buffsend, pte);
2711 static void start_rtp(struct unistim_subchannel *sub)
2713 struct sockaddr_in sin = { 0, };
2714 struct sockaddr_in sout = { 0, };
2715 struct ast_sockaddr sin_tmp;
2716 struct ast_sockaddr sout_tmp;
2720 ast_log(LOG_WARNING, "start_rtp with a null subchannel !\n");
2724 ast_log(LOG_WARNING, "start_rtp with a null line!\n");
2727 if (!sub->parent->parent) {
2728 ast_log(LOG_WARNING, "start_rtp with a null device!\n");
2731 if (!sub->parent->parent->session) {
2732 ast_log(LOG_WARNING, "start_rtp with a null session!\n");
2736 ast_log(LOG_WARNING, "start_rtp with a null asterisk channel!\n");
2739 sout = sub->parent->parent->session->sout;
2740 ast_mutex_lock(&sub->lock);
2741 /* Allocate the RTP */
2743 ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
2745 ast_sockaddr_from_sin(&sout_tmp, &sout);
2746 sub->rtp = ast_rtp_instance_new("asterisk", sched, &sout_tmp, NULL);
2748 ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
2749 strerror(errno), ast_inet_ntoa(sout.sin_addr));
2750 ast_mutex_unlock(&sub->lock);
2753 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
2754 ast_rtp_instance_set_channel_id(sub->rtp, ast_channel_uniqueid(sub->owner));
2755 ast_channel_internal_fd_set(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
2756 ast_channel_internal_fd_set(sub->owner, 1, ast_rtp_instance_fd(sub->rtp, 1));
2757 ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
2758 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->parent->parent->nat);
2760 /* Create the RTP connection */
2761 sin.sin_family = AF_INET;
2762 /* Setting up RTP for our side */
2763 memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
2764 sizeof(sin.sin_addr));
2766 sin.sin_port = htons(find_rtp_port(sub));
2767 ast_sockaddr_from_sin(&sin_tmp, &sin);
2768 ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
2769 if (!ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), ast_channel_readformat(sub->owner))) {
2770 struct ast_format tmpfmt;
2772 ast_best_codec(ast_channel_nativeformats(sub->owner), &tmpfmt);
2773 ast_log(LOG_WARNING,
2774 "Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n",
2775 ast_getformatname(ast_channel_readformat(sub->owner)),
2776 ast_getformatname(&tmpfmt),
2777 ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(sub->owner)));
2779 ast_format_copy(ast_channel_readformat(sub->owner), &tmpfmt);
2780 ast_format_copy(ast_channel_writeformat(sub->owner), &tmpfmt);
2782 send_start_rtp(sub);
2783 ast_mutex_unlock(&sub->lock);
2786 static void send_dial_tone(struct unistimsession *pte)
2788 struct ast_tone_zone_sound *ts = NULL;
2789 struct ast_tone_zone_part tone_data;
2793 if ((ts = ast_get_indication_tone(pte->device->tz, "dial"))) {
2794 ind = ast_strdupa(ts->data);
2795 s = strsep(&ind, ",");
2796 ast_tone_zone_part_parse(s, &tone_data);
2797 if (tone_data.modulate) {
2798 tone_data.freq2 = 0;
2800 send_tone(pte, tone_data.freq1, tone_data.freq2);
2802 ast_verb(0, "Country code found (%s), freq1=%d freq2=%d\n",
2803 pte->device->tz->country, tone_data.freq1, tone_data.freq2);
2805 ts = ast_tone_zone_sound_unref(ts);
2809 static void show_phone_number(struct unistimsession *pte)
2811 char tmp[TEXT_LENGTH_MAX + 1];
2812 const char *tmp_number = ustmtext("Number:", pte);
2813 int line, tmp_copy, offset = 0, i;
2815 pte->device->phone_number[pte->device->size_phone_number] = '\0';
2816 if (pte->device->size_phone_number > MAX_SCREEN_NUMBER) {
2817 offset = pte->device->size_phone_number - MAX_SCREEN_NUMBER - 1;
2818 if (offset > strlen(tmp_number)) {
2819 offset = strlen(tmp_number);
2821 tmp_copy = strlen(tmp_number) - offset + 1;
2822 if (tmp_copy > sizeof(tmp)) {
2823 tmp_copy = sizeof(tmp);
2825 memcpy(tmp, tmp_number + offset, tmp_copy);
2827 ast_copy_string(tmp, tmp_number, sizeof(tmp));
2830 offset = (pte->device->size_phone_number >= TEXT_LENGTH_MAX) ? (pte->device->size_phone_number - TEXT_LENGTH_MAX +1) : 0;
2831 if (pte->device->size_phone_number) {
2832 memcpy(tmp + strlen(tmp), pte->device->phone_number + offset, pte->device->size_phone_number - offset + 1);
2834 offset = strlen(tmp);
2836 for (i = strlen(tmp); i < TEXT_LENGTH_MAX; i++) {
2841 line = (pte->device->height == 1) ? TEXT_LINE0 : TEXT_LINE2;
2842 send_text(line, TEXT_NORMAL, pte, tmp);
2843 send_blink_cursor(pte);
2844 send_cursor_pos(pte, (unsigned char) (line + offset));
2845 send_led_update(pte, 0);
2848 static void handle_dial_page(struct unistimsession *pte)
2850 pte->state = STATE_DIALPAGE;
2851 if (pte->device->call_forward[0] == -1) {
2852 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
2853 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Enter forward", pte));
2854 send_text_status(pte, ustmtext("Fwd Cancel BackSp Erase", pte));
2855 if (pte->device->call_forward[1] != 0) {
2856 ast_copy_string(pte->device->phone_number, pte->device->call_forward + 1,
2857 sizeof(pte->device->phone_number));
2858 show_phone_number(pte);
2859 send_led_update(pte, 0);
2863 if ((pte->device->output == OUTPUT_HANDSET) &&
2864 (pte->device->receiver_state == STATE_ONHOOK)) {
2865 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2867 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2869 send_dial_tone(pte);
2871 if (pte->device->height > 1) {
2872 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Enter the number to dial", pte));
2873 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("and press Call", pte));
2875 if (ast_strlen_zero(pte->device->redial_number)) {
2876 send_text_status(pte, ustmtext("Call BackSp Erase", pte));
2878 send_text_status(pte, ustmtext("Call Redial BackSp Erase", pte));
2882 pte->device->size_phone_number = 0;
2883 pte->device->phone_number[0] = 0;
2884 show_phone_number(pte);
2885 change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
2886 send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
2887 pte->device->missed_call = 0;
2888 send_led_update(pte, 0);
2889 pte->device->lastmsgssent = -1;
2893 static void swap_subs(struct unistim_subchannel *a, struct unistim_subchannel *b)
2895 struct ast_rtp_instance *rtp;
2899 ast_verb(0, "Swapping %p and %p\n", a, b);
2901 if ((!a->owner) || (!b->owner)) {
2902 ast_log(LOG_WARNING,
2903 "Attempted to swap subchannels with a null owner : sub #%p=%p sub #%p=%p\n",
2904 a, a->owner, b, b->owner);
2911 fds = ast_channel_fd(a->owner, 0);
2912 ast_channel_internal_fd_set(a->owner, 0, ast_channel_fd(b->owner, 0));
2913 ast_channel_internal_fd_set(b->owner, 0, fds);
2915 fds = ast_channel_fd(a->owner, 1);
2916 ast_channel_internal_fd_set(a->owner, 1, ast_channel_fd(b->owner, 1));
2917 ast_channel_internal_fd_set(b->owner, 1, fds);
2920 /* Step 1 : Music On Hold for peer, Dialing screen for us */
2921 static void transfer_call_step1(struct unistimsession *pte)
2923 struct unistim_subchannel *sub /*, *sub_trans */;
2924 struct unistim_device *d = pte->device;
2926 sub = get_sub(d, SUB_REAL);
2927 /* sub_trans = get_sub(d, SUB_THREEWAY); */
2929 if (!sub || !sub->owner) {
2930 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2933 /* Start music on hold if appropriate */
2935 ast_log(LOG_WARNING, "Transfer with peer already listening music on hold\n");
2937 ast_queue_hold(sub->owner, sub->parent->musicclass);
2939 sub->subtype = SUB_THREEWAY;
2941 sub_start_silence(pte, sub);
2942 handle_dial_page(pte);
2945 static void transfer_cancel_step2(struct unistimsession *pte)
2947 struct unistim_subchannel *sub, *sub_trans;
2948 struct unistim_device *d = pte->device;
2950 sub = get_sub(d, SUB_REAL);
2951 sub_trans = get_sub(d, SUB_THREEWAY);
2953 if (!sub || !sub->owner) {
2954 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2959 ast_verb(0, "Transfer canceled, hangup our threeway channel\n");
2962 swap_subs(sub, sub_trans);
2963 ast_queue_unhold(sub_trans->owner);
2965 sub_trans->subtype = SUB_REAL;
2966 sub->subtype = SUB_THREEWAY;
2967 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NORMAL_CLEARING);
2969 ast_log(LOG_WARNING, "Canceling a threeway channel without owner\n");
2975 /* From phone to PBX */
2976 static void handle_call_outgoing(struct unistimsession *s)
2978 struct ast_channel *c;
2979 struct unistim_subchannel *sub;
2982 s->state = STATE_CALL;
2984 sub = get_sub(s->device, SUB_THREEWAY);
2986 /* If sub for threway call created than we use transfer behaviuor */
2987 struct unistim_subchannel *sub_trans = NULL;
2988 struct unistim_device *d = s->device;
2990 sub_trans = get_sub(d, SUB_REAL);
2992 ast_log(LOG_WARNING, "Can't transfer while active subchannel exists!\n");
2996 ast_log(LOG_WARNING, "Unable to find subchannel with music on hold\n");
3000 sub_trans = unistim_alloc_sub(d, SUB_REAL);
3002 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
3005 sub_trans->parent = sub->parent;
3006 sub_stop_silence(s, sub);
3008 /* Make new channel */
3009 c = unistim_new(sub_trans, AST_STATE_DOWN, NULL);
3011 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", sub->parent);
3014 /* Swap things around between the three-way and real call */
3015 swap_subs(sub, sub_trans);
3016 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
3017 if (s->device->height == 1) {
3018 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
3020 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling (pre-transfer)", s));
3021 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
3022 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Dialing...", s));
3024 send_text_status(s, ustmtext("TransfrCancel", s));
3026 if (ast_pthread_create(&sub->ss_thread, NULL, unistim_ss, c)) {
3027 ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", c);
3028 sub->ss_thread = AST_PTHREADT_NULL;
3033 ast_verb(0, "Started three way call on channel %p (%s) subchan %d\n",
3034 sub_trans->owner, ast_channel_name(sub_trans->owner), sub_trans->subtype);
3039 softkey = get_avail_softkey(s, NULL);
3040 if (softkey == -1) {
3041 ast_log(LOG_WARNING, "Have no avail softkey for calling\n");
3044 sub = get_sub(s->device, SUB_REAL);
3045 if (sub) { /* have already call assigned */
3046 sub_hold(s, sub); /* Need to put on hold */
3048 if (!(sub = unistim_alloc_sub(s->device, SUB_REAL))) {
3049 ast_log(LOG_WARNING, "Unable to allocate subchannel!\n");
3052 sub->parent = s->device->sline[softkey];
3053 s->device->ssub[softkey] = sub;
3054 sub->softkey = softkey;
3057 ast_verb(0, "Using softkey %d, line %p\n", sub->softkey, sub->parent);
3059 send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, s);
3060 s->device->selected = -1;
3061 if (!sub->owner) { /* A call is already in progress ? */
3062 RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
3063 const char *pickupexten;
3065 c = unistim_new(sub, AST_STATE_DOWN, NULL); /* No, starting a new one */
3066 if (!sub->rtp) { /* Need to start RTP before calling ast_pbx_run */
3070 ast_channel_lock(c);
3071 pickup_cfg = ast_get_chan_features_pickup_config(c);
3073 ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
3076 pickupexten = ast_strdupa(pickup_cfg->pickupexten);
3078 ast_channel_unlock(c);
3080 if (c && !strcmp(s->device->phone_number, pickupexten)) {
3082 ast_verb(0, "Try to pickup in unistim_new\n");
3084 send_text(TEXT_LINE0, TEXT_NORMAL, s, "");
3085 send_text_status(s, ustmtext(" Transf Hangup", s));
3086 send_start_timer(s);
3087 if (ast_pickup_call(c)) {
3088 ast_log(LOG_NOTICE, "Nothing to pick up\n");
3089 ast_channel_hangupcause_set(c, AST_CAUSE_CALL_REJECTED);
3091 ast_channel_hangupcause_set(c, AST_CAUSE_NORMAL_CLEARING);
3096 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
3097 send_tone(s, 0, 0); /* Dialing empty number should also stop dial tone */
3098 if (s->device->height == 1) {
3099 if (strlen(s->device->phone_number) > 0) {
3100 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
3102 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling...", s));
3105 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling :", s));
3106 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
3107 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Dialing...", s));
3109 send_text_status(s, ustmtext(" Hangup", s));
3112 if (ast_pthread_create(&sub->ss_thread, NULL, unistim_ss, c)) {
3113 ast_log(LOG_WARNING, "Unable to create switch thread\n");
3114 sub->ss_thread = AST_PTHREADT_NULL;
3115 ast_queue_hangup_with_cause(c, AST_CAUSE_SWITCH_CONGESTION);
3118 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n",
3119 sub->parent->name, s->device->name);
3121 ast_debug(1, "Current sub [%s] already has owner\n", ast_channel_name(sub->owner));
3126 /* From PBX to phone */
3127 static void handle_call_incoming(struct unistimsession *s)
3129 struct unistim_subchannel *sub = NULL;
3132 s->state = STATE_CALL;
3133 s->device->missed_call = 0;
3135 sub = get_sub(s->device, SUB_RING); /* Put other SUB_REAL call on hold */
3137 ast_log(LOG_WARNING, "No ringing lines on: %s\n", s->device->name);
3140 /* Change icons for all ringing keys */
3141 for (i = 0; i < FAVNUM; i++) {
3142 if (!s->device->ssub[i]) { /* No sub assigned - skip */
3145 if (s->device->ssub[i]->subtype == SUB_REAL) {
3146 sub_hold(s, s->device->ssub[i]);
3148 if (s->device->ssub[i] != sub) {
3151 if (sub->softkey == i) { /* If softkey assigned at this moment - do not erase */
3154 if (sub->softkey < 0) { /* If softkey not defined - first one used */
3158 send_favorite_short(i, FAV_LINE_ICON, s);
3159 s->device->ssub[i] = NULL;
3161 if (sub->softkey < 0) {
3162 ast_log(LOG_WARNING, "Can not assign softkey for incoming call on: %s\n", s->device->name);
3165 send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, s);
3166 sub->parent = s->device->sline[sub->softkey];
3167 sub->subtype = SUB_REAL;
3169 ast_verb(0, "Handle Call Incoming for %s@%s\n", sub->parent->name,
3173 ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
3175 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("is on-line", s));
3176 send_text_status(s, ustmtext(" Transf Hangup", s));
3177 send_start_timer(s);
3179 if ((s->device->output == OUTPUT_HANDSET) &&
3180 (s->device->receiver_state == STATE_ONHOOK)) {
3181 send_select_output(s, OUTPUT_SPEAKER, s->device->volume, MUTE_OFF);
3183 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
3185 write_history(s, 'i', 0);
3189 static int unistim_do_senddigit(struct unistimsession *pte, char digit)
3191 struct ast_frame f = { .frametype = AST_FRAME_DTMF, .subclass.integer = digit, .src = "unistim" };
3192 struct unistim_subchannel *sub;
3195 sub = get_sub(pte->device, SUB_REAL);
3196 if (!sub || !sub->owner || sub->alreadygone) {
3197 ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit\n");
3201 /* Send DTMF indication _before_ playing sounds */
3202 ast_queue_frame(sub->owner, &f);
3205 ast_verb(0, "Send Digit %c\n", digit);
3207 row = (digit - '1') % 3;
3208 col = (digit - '1' - row) / 3;
3209 if (digit >= '1' && digit <='9') {
3210 send_tone(pte, dtmf_row[row], dtmf_col[col]);
3211 } else if (digit >= 'A' && digit <= 'D') {
3212 send_tone(pte, dtmf_row[digit-'A'], dtmf_col[3]);
3213 } else if (digit == '*') {
3214 send_tone(pte, dtmf_row[3], dtmf_col[0]);
3215 } else if (digit == '0') {
3216 send_tone(pte, dtmf_row[3], dtmf_col[1]);
3217 } else if (digit == '#') {
3218 send_tone(pte, dtmf_row[3], dtmf_col[2]);
3220 send_tone(pte, 500, 2000);
3222 usleep(150000); /* XXX Less than perfect, blocking an important thread is not a good idea */
3223 send_tone(pte, 0, 0);
3227 static void handle_key_fav(struct unistimsession *pte, char keycode)
3229 int keynum = keycode - KEY_FAV0;
3230 struct unistim_subchannel *sub;
3232 sub = get_sub(pte->device, SUB_REAL);
3234 /* Make an action on selected favorite key */
3235 if (!pte->device->ssub[keynum]) { /* Key have no assigned call */
3236 send_favorite_selected(FAV_LINE_ICON, pte);
3237 if (is_key_line(pte->device, keynum)) {
3239 ast_verb(0, "Handle line w/o sub - dialpage\n");
3241 pte->device->selected = keynum;
3242 sub_hold(pte, sub); /* Put active call on hold */
3243 send_stop_timer(pte);
3244 handle_dial_page(pte);
3245 } else if (is_key_favorite(pte->device, keynum)) {
3246 /* Put active call on hold in handle_call_outgoing function, after preparation and
3247 checking if lines available for calling */
3249 ast_verb(0, "Handle favorite w/o sub - dialing\n");
3251 if ((pte->device->output == OUTPUT_HANDSET) &&
3252 (pte->device->receiver_state == STATE_ONHOOK)) {
3253 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
3255 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
3257 key_favorite(pte, keycode);
3260 sub = pte->device->ssub[keynum];
3261 /* Favicon have assigned sub, activate it and put current on hold */
3262 if (sub->subtype == SUB_REAL) {
3264 show_main_page(pte);
3265 } else if (sub->subtype == SUB_RING) {
3266 sub->softkey = keynum;
3267 handle_call_incoming(pte);
3268 } else if (sub->subtype == SUB_ONHOLD) {
3269 if (pte->state == STATE_DIALPAGE){
3270 send_tone(pte, 0, 0);
3272 send_callerid_screen(pte, sub);
3273 sub_unhold(pte, sub);
3274 pte->state = STATE_CALL;
3279 static void key_call(struct unistimsession *pte, char keycode)
3281 struct unistim_subchannel *sub = get_sub(pte->device, SUB_REAL);
3282 struct unistim_subchannel *sub_3way = get_sub(pte->device, SUB_THREEWAY);
3284 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
3285 if (keycode == KEY_SHARP) {
3287 } else if (keycode == KEY_STAR) {
3292 unistim_do_senddigit(pte, keycode);
3297 if (ast_channel_state(sub->owner) == AST_STATE_UP) {
3305 transfer_cancel_step2(pte);
3306 } else if (ast_channel_state(sub->owner) == AST_STATE_UP) {
3307 transfer_call_step1(pte);
3322 handle_key_fav(pte, keycode);
3325 if (pte->device->output == OUTPUT_HEADPHONE) {
3326 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
3328 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
3332 if (pte->device->output != OUTPUT_SPEAKER)
3333 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
3335 send_select_output(pte, pte->device->previous_output, pte->device->volume,
3339 if (!sub || !sub->owner) {
3340 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
3344 if (pte->device->mute == MUTE_ON) {
3345 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
3347 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
3354 if(pte->device->ssub[pte->device->selected]) {
3355 sub_hold(pte, pte->device->ssub[pte->device->selected]);
3365 static void key_ringing(struct unistimsession *pte, char keycode)
3374 handle_key_fav(pte, keycode);
3384 pte->device->output = OUTPUT_SPEAKER;
3385 handle_call_incoming(pte);
3388 pte->device->output = OUTPUT_HEADPHONE;
3389 handle_call_incoming(pte);
3392 handle_call_incoming(pte);
3398 static void key_favorite(struct unistimsession *pte, char keycode)
3400 int fav = keycode - KEY_FAV0;
3401 if (!is_key_favorite(pte->device, fav)) {
3402 ast_log(LOG_WARNING, "It's not a favorite key\n");
3405 ast_copy_string(pte->device->phone_number, pte->device->softkeynumber[fav],
3406 sizeof(pte->device->phone_number));
3407 handle_call_outgoing(pte);
3411 static void key_dial_page(struct unistimsession *pte, char keycode)
3413 struct unistim_subchannel *sub = get_sub(pte->device, SUB_THREEWAY);
3415 pte->device->nextdial = 0;
3416 if (keycode == KEY_FUNC3) {
3417 if (pte->device->size_phone_number <= 1) {
3418 keycode = KEY_FUNC4;
3420 pte->device->size_phone_number -= 2;
3421 keycode = pte->device->phone_number[pte->device->size_phone_number] + 0x10;
3424 if (keycode == KEY_SHARP && pte->device->sharp_dial == 1) {
3425 keycode = KEY_FUNC1;
3427 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
3428 int i = pte->device->size_phone_number;
3430 if (pte->device->size_phone_number == 0) {
3431 send_tone(pte, 0, 0);
3433 if (keycode == KEY_SHARP) {
3435 } else if (keycode == KEY_STAR) {
3440 pte->device->phone_number[i] = keycode;
3441 pte->device->size_phone_number++;
3442 pte->device->phone_number[i + 1] = 0;
3443 show_phone_number(pte);
3445 if (ast_exists_extension(NULL, pte->device->context, pte->device->phone_number, 1, NULL) &&
3446 !ast_matchmore_extension(NULL, pte->device->context, pte->device->phone_number, 1, NULL)) {
3447 keycode = KEY_FUNC1;
3449 if (pte->device->interdigit_timer) {
3450 pte->device->nextdial = get_tick_count() + pte->device->interdigit_timer;
3454 if (keycode == KEY_FUNC4) {
3455 pte->device->size_phone_number = 0;
3456 show_phone_number(pte);
3460 if (pte->device->call_forward[0] == -1) {
3461 if (keycode == KEY_FUNC1) {
3462 ast_copy_string(pte->device->call_forward, pte->device->phone_number,
3463 sizeof(pte->device->call_forward));
3464 show_main_page(pte);
3465 } else if ((keycode == KEY_FUNC2) || (keycode == KEY_HANGUP)) {
3466 pte->device->call_forward[0] = '\0';
3467 send_led_update(pte, 0x08);
3468 send_led_update(pte, 0x10);
3469 show_main_page(pte);
3475 if (ast_strlen_zero(pte->device->redial_number)) {
3478 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
3479 sizeof(pte->device->phone_number));
3481 handle_call_outgoing(pte);
3484 if (sub && sub->owner) {
3485 sub_stop_silence(pte, sub);
3486 send_tone(pte, 0, 0);
3487 ast_queue_unhold(sub->owner);
3489 sub->subtype = SUB_REAL;
3490 pte->state = STATE_CALL;
3492 send_text_status(pte, ustmtext(" Transf Hangup", pte));
3493 send_callerid_screen(pte, sub);
3495 send_led_update(pte, 0x08);
3496 send_led_update(pte, 0x10);
3497 show_main_page(pte);
3506 send_favorite_selected(FAV_LINE_ICON, pte);
3507 pte->device->selected = -1;
3508 handle_key_fav(pte, keycode);
3511 if (pte->device->output == OUTPUT_SPEAKER) {
3512 if (pte->device->receiver_state == STATE_OFFHOOK) {
3513 send_select_output(pte, pte->device->previous_output, pte->device->volume,
3516 show_main_page(pte);
3519 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
3523 if (pte->device->output == OUTPUT_HEADPHONE) {
3524 if (pte->device->receiver_state == STATE_OFFHOOK) {
3525 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);