2 * Asterisk -- An open source telephony toolkit.
4 * UNISTIM channel driver for asterisk
6 * Copyright (C) 2005 - 2007, Cedric Hans
8 * Cedric Hans <cedric.hans@mlkj.net>
10 * Asterisk 1.4 patch by Peter Be
12 * See http://www.asterisk.org for more information about
13 * the Asterisk project. Please do not directly contact
14 * any of the maintainers of this project for assistance;
15 * the project provides a web site, mailing lists and IRC
16 * channels for your use.
18 * This program is free software, distributed under the terms of
19 * the GNU General Public License Version 2. See the LICENSE file
20 * at the top of the source tree.
26 * \brief chan_unistim channel driver for Asterisk
27 * \author Cedric Hans <cedric.hans@mlkj.net>
29 * Unistim (Unified Networks IP Stimulus) channel driver
30 * for Nortel i2002, i2004 and i2050
32 * \ingroup channel_drivers
36 <support_level>extended</support_level>
41 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
46 #if defined(__CYGWIN__)
48 * cygwin headers are partly inconsistent. struct iovec is defined in sys/uio.h
49 * which is not included by default by sys/socket.h - in_pktinfo is defined in
50 * w32api/ws2tcpip.h but this probably has compatibility problems with sys/socket.h
51 * So for the time being we simply disable HAVE_PKTINFO when building under cygwin.
52 * This should be done in some common header, but for now this is the only file
53 * using iovec and in_pktinfo so it suffices to apply the fix here.
58 #endif /* __CYGWIN__ */
60 #include "asterisk/paths.h" /* ast_config_AST_LOG_DIR used in (too ?) many places */
61 #include "asterisk/network.h"
62 #include "asterisk/channel.h"
63 #include "asterisk/config.h"
64 #include "asterisk/module.h"
65 #include "asterisk/pbx.h"
66 #include "asterisk/event.h"
67 #include "asterisk/rtp_engine.h"
68 #include "asterisk/netsock2.h"
69 #include "asterisk/acl.h"
70 #include "asterisk/callerid.h"
71 #include "asterisk/cli.h"
72 #include "asterisk/app.h"
73 #include "asterisk/musiconhold.h"
74 #include "asterisk/causes.h"
75 #include "asterisk/indications.h"
76 #include "asterisk/features.h"
77 #include "asterisk/astobj2.h"
78 #include "asterisk/astdb.h"
79 #include "asterisk/features_config.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 show_main_page(struct unistimsession *pte);
678 static struct ast_channel *unistim_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor,
679 const char *dest, int *cause);
680 static int unistim_call(struct ast_channel *ast, const char *dest, int timeout);
681 static int unistim_hangup(struct ast_channel *ast);
682 static int unistim_answer(struct ast_channel *ast);
683 static struct ast_frame *unistim_read(struct ast_channel *ast);
684 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame);
685 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
687 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
688 static int unistim_senddigit_begin(struct ast_channel *ast, char digit);
689 static int unistim_senddigit_end(struct ast_channel *ast, char digit,
690 unsigned int duration);
691 static int unistim_sendtext(struct ast_channel *ast, const char *text);
693 static int write_entry_history(struct unistimsession *pte, FILE * f, char c,
695 static void change_callerid(struct unistimsession *pte, int type, char *callerid);
697 static struct ast_channel_tech unistim_tech = {
698 .type = channel_type,
699 .description = tdesc,
700 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
701 .requester = unistim_request,
702 .call = unistim_call,
703 .hangup = unistim_hangup,
704 .answer = unistim_answer,
705 .read = unistim_read,
706 .write = unistim_write,
707 .indicate = unistim_indicate,
708 .fixup = unistim_fixup,
709 .send_digit_begin = unistim_senddigit_begin,
710 .send_digit_end = unistim_senddigit_end,
711 .send_text = unistim_sendtext,
714 static void send_start_rtp(struct unistim_subchannel *);
716 static void send_callerid_screen(struct unistimsession *, struct unistim_subchannel *);
717 static void key_favorite(struct unistimsession *, char);
719 static void handle_select_codec(struct unistimsession *);
720 static void handle_select_language(struct unistimsession *);
721 static int find_language(const char*);
723 static int unistim_free_sub(struct unistim_subchannel *);
725 static struct unistim_menu_item options_menu[] =
727 {"Change codec", STATE_SELECTCODEC, handle_select_codec},
728 {"Language", STATE_SELECTLANGUAGE, handle_select_language},
732 static struct unistim_languages options_languages[] =
734 {"English", "en", ISO_8859_1, NULL},
735 {"French", "fr", ISO_8859_1, NULL},
736 {"Russian", "ru", ISO_8859_5, NULL},
737 {NULL, NULL, 0, NULL}
740 static char ustm_strcopy[1024];
742 struct ustm_lang_entry {
743 const char *str_orig;
744 const char *str_trans;
747 static int lang_hash_fn(const void *obj, const int flags)
749 const struct ustm_lang_entry *entry = obj;
750 return ast_str_hash(entry->str_orig);
753 static int lang_cmp_fn(void *obj, void *arg, int flags)
755 struct ustm_lang_entry *entry1 = obj;
756 struct ustm_lang_entry *entry2 = arg;
758 return (!strcmp(entry1->str_orig, entry2->str_orig)) ? (CMP_MATCH | CMP_STOP) : 0;
761 static const char *ustmtext(const char *str, struct unistimsession *pte)
763 struct ustm_lang_entry *lang_entry;
764 struct ustm_lang_entry le_search;
765 struct unistim_languages *lang = NULL;
769 lang = &options_languages[find_language(pte->device->language)];
774 /* Check if specified language exists */
776 char tmp[1024], *p, *p_orig = NULL, *p_trans = NULL;
779 if (!(lang->trans = ao2_container_alloc(8, lang_hash_fn, lang_cmp_fn))) {
780 ast_log(LOG_ERROR, "Unable to allocate container for translation!\n");
783 snprintf(tmp, sizeof(tmp), "%s/%s/%s.po", ast_config_AST_VAR_DIR,
784 USTM_LANG_DIR, lang->lang_short);
787 ast_log(LOG_WARNING, "There is no translation file for '%s'\n", lang->lang_short);
790 while (fgets(tmp, sizeof(tmp), f)) {
791 if (!(p = strchr(tmp, '\n'))) {
792 ast_log(LOG_ERROR, "Too long line found in language file - truncated!\n");
796 if (!(p = strchr(tmp, '"'))) {
799 if (tmp == strstr(tmp, "msgid")) {
800 p_orig = ast_strdup(p + 1);
801 p = strchr(p_orig, '"');
802 } else if (tmp == strstr(tmp, "msgstr")) {
803 p_trans = ast_strdup(p + 1);
804 p = strchr(p_trans, '"');
809 if (!p_trans || !p_orig) {
812 if (ast_strlen_zero(p_trans)) {
819 if (!(lang_entry = ao2_alloc(sizeof(*lang_entry), NULL))) {
824 lang_entry->str_trans = p_trans;
825 lang_entry->str_orig = p_orig;
826 ao2_link(lang->trans, lang_entry);
834 le_search.str_orig = str;
835 if ((lang_entry = ao2_find(lang->trans, &le_search, OBJ_POINTER))) {
836 size = strlen(lang_entry->str_trans)+1;
840 memcpy(ustm_strcopy, lang_entry->str_trans, size);
841 ao2_ref(lang_entry, -1);
848 static void display_last_error(const char *sz_msg)
850 /* Display the error message */
851 ast_log(LOG_WARNING, "%s : (%u) %s\n", sz_msg, errno, strerror(errno));
854 static unsigned int get_tick_count(void)
856 struct timeval now = ast_tvnow();
858 return (now.tv_sec * 1000) + (now.tv_usec / 1000);
861 /* Send data to a phone without retransmit nor buffering */
862 static void send_raw_client(int size, const unsigned char *data, struct sockaddr_in *addr_to,
863 const struct sockaddr_in *addr_ourip)
866 struct iovec msg_iov;
868 char buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
869 struct cmsghdr *ip_msg = (struct cmsghdr *) buffer;
870 struct in_pktinfo *pki = (struct in_pktinfo *) CMSG_DATA(ip_msg);
872 /* cast this to a non-const pointer, since the sendmsg() API
873 * does not provide read-only and write-only flavors of the
874 * structures used for its arguments, but in this case we know
875 * the data will not be modified
877 msg_iov.iov_base = (char *) data;
878 msg_iov.iov_len = size;
880 msg.msg_name = addr_to; /* optional address */
881 msg.msg_namelen = sizeof(struct sockaddr_in); /* size of address */
882 msg.msg_iov = &msg_iov; /* scatter/gather array */
883 msg.msg_iovlen = 1; /* # elements in msg_iov */
884 msg.msg_control = ip_msg; /* ancillary data */
885 msg.msg_controllen = sizeof(buffer); /* ancillary data buffer len */
886 msg.msg_flags = 0; /* flags on received message */
888 ip_msg->cmsg_len = CMSG_LEN(sizeof(*pki));
889 ip_msg->cmsg_level = IPPROTO_IP;
890 ip_msg->cmsg_type = IP_PKTINFO;
891 pki->ipi_ifindex = 0; /* Interface index, 0 = use interface specified in routing table */
892 pki->ipi_spec_dst.s_addr = addr_ourip->sin_addr.s_addr; /* Local address */
893 /* pki->ipi_addr = ; Header Destination address - ignored by kernel */
898 ast_verb(0, "\n**> From %s sending %d bytes to %s ***\n",
899 ast_inet_ntoa(addr_ourip->sin_addr), (int) size,
900 ast_inet_ntoa(addr_to->sin_addr));
901 for (tmp = 0; tmp < size; tmp++)
902 ast_verb(0, "%.2x ", (unsigned char) data[tmp]);
903 ast_verb(0, "\n******************************************\n");
908 if (sendmsg(unistimsock, &msg, 0) == -1) {
909 display_last_error("Error sending datas");
912 if (sendto(unistimsock, data, size, 0, (struct sockaddr *) addr_to, sizeof(*addr_to))
914 display_last_error("Error sending datas");
918 static void send_client(int size, const unsigned char *data, struct unistimsession *pte)
922 unsigned short seq = ntohs(++pte->seq_server);
924 ast_mutex_lock(&pte->lock);
925 buf_pos = pte->last_buf_available;
927 if (buf_pos >= MAX_BUF_NUMBER) {
928 ast_log(LOG_WARNING, "Error : send queue overflow\n");
929 ast_mutex_unlock(&pte->lock);
932 memcpy((void *)data + sizeof(unsigned short), (void *)&seq, sizeof(unsigned short));
933 pte->wsabufsend[buf_pos].len = size;
934 memcpy(pte->wsabufsend[buf_pos].buf, data, size);
936 tick = get_tick_count();
937 pte->timeout = tick + RETRANSMIT_TIMER;
939 /*#ifdef DUMP_PACKET */
941 ast_verb(6, "Sending datas with seq #0x%.4x Using slot #%d :\n", pte->seq_server, buf_pos);
944 send_raw_client(pte->wsabufsend[buf_pos].len, pte->wsabufsend[buf_pos].buf, &(pte->sin),
946 pte->last_buf_available++;
947 ast_mutex_unlock(&pte->lock);
950 static void send_ping(struct unistimsession *pte)
954 ast_verb(6, "Sending ping\n");
956 pte->tick_next_ping = get_tick_count() + unistim_keepalive;
957 memcpy(buffsend + SIZE_HEADER, packet_send_ping, sizeof(packet_send_ping));
958 send_client(SIZE_HEADER + sizeof(packet_send_ping), buffsend, pte);
961 static int get_to_address(int fd, struct sockaddr_in *toAddr)
969 struct in_addr address;
972 /* Zero out the structures before we use them */
973 /* This sets several key values to NULL */
974 memset(&msg, 0, sizeof(msg));
975 memset(&ip_msg, 0, sizeof(ip_msg));
977 /* Initialize the message structure */
978 msg.msg_control = &ip_msg;
979 msg.msg_controllen = sizeof(ip_msg);
980 /* Get info about the incoming packet */
981 err = recvmsg(fd, &msg, MSG_PEEK);
983 ast_log(LOG_WARNING, "recvmsg returned an error: %s\n", strerror(errno));
985 memcpy(&toAddr->sin_addr, &ip_msg.address, sizeof(struct in_addr));
988 memcpy(&toAddr, &public_ip, sizeof(&toAddr));
993 /* Allocate memory & initialize structures for a new phone */
994 /* addr_from : ip address of the phone */
995 static struct unistimsession *create_client(const struct sockaddr_in *addr_from)
998 struct unistimsession *s;
1000 if (!(s = ast_calloc(1, sizeof(*s))))
1003 memcpy(&s->sin, addr_from, sizeof(struct sockaddr_in));
1004 get_to_address(unistimsock, &s->sout);
1005 s->sout.sin_family = AF_INET;
1007 ast_verb(0, "Creating a new entry for the phone from %s received via server ip %s\n",
1008 ast_inet_ntoa(addr_from->sin_addr), ast_inet_ntoa(s->sout.sin_addr));
1010 ast_mutex_init(&s->lock);
1011 ast_mutex_lock(&sessionlock);
1015 s->timeout = get_tick_count() + RETRANSMIT_TIMER;
1016 s->state = STATE_INIT;
1017 s->tick_next_ping = get_tick_count() + unistim_keepalive;
1018 /* Initialize struct wsabuf */
1019 for (tmp = 0; tmp < MAX_BUF_NUMBER; tmp++) {
1020 s->wsabufsend[tmp].buf = s->buf[tmp];
1022 ast_mutex_unlock(&sessionlock);
1026 static void send_end_call(struct unistimsession *pte)
1030 ast_verb(0, "Sending end call\n");
1032 memcpy(buffsend + SIZE_HEADER, packet_send_end_call, sizeof(packet_send_end_call));
1033 send_client(SIZE_HEADER + sizeof(packet_send_end_call), buffsend, pte);
1036 static void set_ping_timer(struct unistimsession *pte)
1038 unsigned int tick = 0; /* XXX what is this for, anyways */
1040 pte->timeout = pte->tick_next_ping;
1041 DEBUG_TIMER("tick = %u next ping at %u tick\n", tick, pte->timeout);
1045 /* Checking if our send queue is empty,
1046 * if true, setting up a timer for keepalive */
1047 static void check_send_queue(struct unistimsession *pte)
1049 /* Check if our send queue contained only one element */
1050 if (pte->last_buf_available == 1) {
1052 ast_verb(6, "Our single packet was ACKed.\n");
1054 pte->last_buf_available--;
1055 set_ping_timer(pte);
1058 /* Check if this ACK catch up our latest packet */
1059 else if (pte->last_seq_ack + 1 == pte->seq_server + 1) {
1061 ast_verb(6, "Our send queue is completely ACKed.\n");
1063 pte->last_buf_available = 0; /* Purge the send queue */
1064 set_ping_timer(pte);
1068 ast_verb(6, "We still have packets in our send queue\n");
1073 static void send_start_timer(struct unistimsession *pte)
1077 ast_verb(0, "Sending start timer\n");
1079 memcpy(buffsend + SIZE_HEADER, packet_send_start_timer, sizeof(packet_send_start_timer));
1080 send_client(SIZE_HEADER + sizeof(packet_send_start_timer), buffsend, pte);
1083 static void send_stop_timer(struct unistimsession *pte)
1087 ast_verb(0, "Sending stop timer\n");
1089 memcpy(buffsend + SIZE_HEADER, packet_send_stop_timer, sizeof(packet_send_stop_timer));
1090 send_client(SIZE_HEADER + sizeof(packet_send_stop_timer), buffsend, pte);
1093 static void send_icon(unsigned char pos, unsigned char status, struct unistimsession *pte)
1097 ast_verb(0, "Sending icon pos %d with status 0x%.2x\n", pos, status);
1099 memcpy(buffsend + SIZE_HEADER, packet_send_icon, sizeof(packet_send_icon));
1101 buffsend[10] = status;
1102 send_client(SIZE_HEADER + sizeof(packet_send_icon), buffsend, pte);
1105 static void send_tone(struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
1110 ast_verb(0, "Sending Stream Based Tone Off\n");
1112 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_off,
1113 sizeof(packet_send_stream_based_tone_off));
1114 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_off), buffsend, pte);
1117 /* Since most of the world use a continuous tone, it's useless
1119 ast_verb(0, "Sending Stream Based Tone Cadence Download\n");
1120 memcpy (buffsend + SIZE_HEADER, packet_send_StreamBasedToneCad, sizeof (packet_send_StreamBasedToneCad));
1121 send_client (SIZE_HEADER + sizeof (packet_send_StreamBasedToneCad), buffsend, pte); */
1123 ast_verb(0, "Sending Stream Based Tone Frequency Component List Download %d %d\n", tone1, tone2);
1127 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_single_freq,
1128 sizeof(packet_send_stream_based_tone_single_freq));
1129 buffsend[10] = (tone1 & 0xff00) >> 8;
1130 buffsend[11] = (tone1 & 0x00ff);
1131 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_single_freq), buffsend,
1135 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dial_freq,
1136 sizeof(packet_send_stream_based_tone_dial_freq));
1137 buffsend[10] = (tone1 & 0xff00) >> 8;
1138 buffsend[11] = (tone1 & 0x00ff);
1139 buffsend[12] = (tone2 & 0xff00) >> 8;
1140 buffsend[13] = (tone2 & 0x00ff);
1141 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_dial_freq), buffsend,
1146 ast_verb(0, "Sending Stream Based Tone On\n");
1148 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_on,
1149 sizeof(packet_send_stream_based_tone_on));
1150 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_on), buffsend, pte);
1153 /* Positions for favorites
1154 |--------------------|
1155 | 5 2 | <-- not on screen in i2002
1160 /* status (icons) : 00 = nothing, 2x/3x = see parser.h, 4x/5x = blink fast, 6x/7x = blink slow */
1162 send_favorite(unsigned char pos, unsigned char status, struct unistimsession *pte,
1169 ast_verb(0, "Sending favorite pos %d with status 0x%.2x\n", pos, status);
1171 memcpy(buffsend + SIZE_HEADER, packet_send_favorite, sizeof(packet_send_favorite));
1174 buffsend[25] = status;
1175 i = strlen(ustmtext(text, pte));
1176 if (i > FAV_MAX_LENGTH) {
1179 memcpy(buffsend + FAV_MAX_LENGTH + 1, ustmtext(text, pte), i);
1180 send_client(SIZE_HEADER + sizeof(packet_send_favorite), buffsend, pte);
1183 static void send_favorite_short(unsigned char pos, unsigned char status, struct unistimsession *pte) {
1184 send_favorite(pos, status, pte, pte->device->softkeylabel[pos]);
1188 static void send_favorite_selected(unsigned char status, struct unistimsession *pte) {
1189 if (pte->device->selected != -1) {
1190 send_favorite(pte->device->selected, status, pte, pte->device->softkeylabel[pte->device->selected]);
1195 static int soft_key_visible(struct unistim_device* d, unsigned char num)
1197 if(d->height == 1 && num % 3 == 2) {
1203 static void refresh_all_favorite(struct unistimsession *pte)
1205 unsigned char i = 0;
1207 struct unistim_line *line;
1208 line = AST_LIST_FIRST(&pte->device->lines);
1211 ast_verb(0, "Refreshing all favorite\n");
1213 for (i = 0; i < FAVNUM; i++) {
1214 unsigned char status = pte->device->softkeyicon[i];
1216 if (!soft_key_visible(pte->device, i)) {
1219 if (!strcasecmp(pte->device->softkeylabel[i], "DND") && line) {
1220 if (!ast_db_get("DND", line->name, data, sizeof(data))) {
1221 status = FAV_ICON_SPEAKER_ONHOOK_WHITE;
1225 send_favorite_short(i, status, pte);
1229 static int is_key_favorite(struct unistim_device *d, int fav)
1231 if ((fav < 0) && (fav > 5)) {
1234 if (d->sline[fav]) {
1237 if (d->softkeynumber[fav][0] == '\0') {
1243 static int is_key_line(struct unistim_device *d, int fav)
1245 if ((fav < 0) && (fav > 5)) {
1248 if (!d->sline[fav]) {
1251 if (is_key_favorite(d, fav)) {
1257 static int get_active_softkey(struct unistimsession *pte)
1259 return pte->device->selected;
1262 static int get_avail_softkey(struct unistimsession *pte, const char* name)
1266 if (!is_key_line(pte->device, pte->device->selected)) {
1267 pte->device->selected = -1;
1269 for (i = 0; i < FAVNUM; i++) {
1270 if (pte->device->selected != -1 && pte->device->selected != i) {
1273 if (!soft_key_visible(pte->device, i)) {
1276 if (pte->device->ssub[i]) {
1279 if (is_key_line(pte->device, i)) {
1280 if (name && strcmp(name, pte->device->sline[i]->name)) {
1284 ast_verb(0, "Found softkey %d for device %s\n", i, name);
1293 /* Change the status for this phone (pte) and update for each phones where pte is bookmarked
1294 * use FAV_ICON_*_BLACK constant in status parameters */
1295 static void change_favorite_icon(struct unistimsession *pte, unsigned char status)
1297 struct unistim_device *d = devices;
1299 /* Update the current phone line softkey icon */
1300 if (pte->state != STATE_CLEANING) {
1301 int softkeylinepos = get_active_softkey(pte);
1302 if (softkeylinepos != -1) {
1303 send_favorite_short(softkeylinepos, status, pte);
1306 /* Notify other phones if we're in their bookmark */
1308 for (i = 0; i < FAVNUM; i++) {
1309 if (d->sp[i] == pte->device) { /* It's us ? */
1310 if (d->softkeyicon[i] != status) { /* Avoid resending the same icon */
1311 d->softkeyicon[i] = status;
1313 send_favorite(i, status + 1, d->session, d->softkeylabel[i]);
1322 static int register_extension(const struct unistimsession *pte)
1324 struct unistim_line *line;
1325 line = AST_LIST_FIRST(&pte->device->lines);
1327 ast_verb(0, "Trying to register extension '%s' into context '%s' to %s\n",
1328 pte->device->extension_number, pte->device->context,
1331 return ast_add_extension(pte->device->context, 0,
1332 pte->device->extension_number, 1, NULL, NULL, "Dial",
1333 line->fullname, 0, "Unistim");
1336 static int unregister_extension(const struct unistimsession *pte)
1339 ast_verb(0, "Trying to unregister extension '%s' context '%s'\n",
1340 pte->device->extension_number, pte->device->context);
1342 return ast_context_remove_extension(pte->device->context,
1343 pte->device->extension_number, 1, "Unistim");
1346 /* Free memory allocated for a phone */
1347 static void close_client(struct unistimsession *s)
1349 struct unistim_subchannel *sub = NULL;
1350 struct unistimsession *cur, *prev = NULL;
1351 ast_mutex_lock(&sessionlock);
1353 /* Looking for the session in the linked chain */
1361 if (cur) { /* Session found ? */
1362 if (cur->device) { /* This session was registered ? */
1363 s->state = STATE_CLEANING;
1365 ast_verb(0, "close_client session %p device %p\n", s, s->device);
1367 change_favorite_icon(s, FAV_ICON_NONE);
1368 ast_mutex_lock(&s->device->lock);
1369 AST_LIST_LOCK(&s->device->subs);
1370 AST_LIST_TRAVERSE_SAFE_BEGIN(&s->device->subs, sub, list) {
1374 if (sub->owner) { /* Call in progress ? */
1376 ast_verb(0, "Aborting call\n");
1378 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NETWORK_OUT_OF_ORDER);
1381 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->subtype, sub->parent->name, s->device->name);
1383 AST_LIST_REMOVE_CURRENT(list);
1384 unistim_free_sub(sub);
1387 AST_LIST_TRAVERSE_SAFE_END;
1388 AST_LIST_UNLOCK(&s->device->subs);
1390 if (!ast_strlen_zero(s->device->extension_number)) {
1391 unregister_extension(s);
1393 cur->device->session = NULL;
1394 ast_mutex_unlock(&s->device->lock);
1397 ast_verb(0, "Freeing an unregistered client\n");
1401 prev->next = cur->next;
1403 sessions = cur->next;
1405 ast_mutex_destroy(&s->lock);
1408 ast_log(LOG_WARNING, "Trying to delete non-existent session %p?\n", s);
1410 ast_mutex_unlock(&sessionlock);
1414 /* Return 1 if the session chained link was modified */
1415 static int send_retransmit(struct unistimsession *pte)
1419 ast_mutex_lock(&pte->lock);
1420 if (++pte->nb_retransmit >= NB_MAX_RETRANSMIT) {
1422 ast_verb(0, "Too many retransmit - freeing client\n");
1424 ast_mutex_unlock(&pte->lock);
1428 pte->timeout = get_tick_count() + RETRANSMIT_TIMER;
1430 for (i = pte->last_buf_available - (pte->seq_server - pte->last_seq_ack);
1431 i < pte->last_buf_available; i++) {
1433 ast_log(LOG_WARNING,
1434 "Asked to retransmit an ACKed slot ! last_buf_available=%d, seq_server = #0x%.4x last_seq_ack = #0x%.4x\n",
1435 pte->last_buf_available, pte->seq_server, pte->last_seq_ack);
1440 unsigned short *sbuf = (unsigned short *) pte->wsabufsend[i].buf;
1443 seq = ntohs(sbuf[1]);
1444 ast_verb(0, "Retransmit slot #%d (seq=#0x%.4x), last ack was #0x%.4x\n", i,
1445 seq, pte->last_seq_ack);
1447 send_raw_client(pte->wsabufsend[i].len, pte->wsabufsend[i].buf, &pte->sin,
1450 ast_mutex_unlock(&pte->lock);
1454 /* inverse : TEXT_INVERSE : yes, TEXT_NORMAL : no */
1456 send_text(unsigned char pos, unsigned char inverse, struct unistimsession *pte,
1462 ast_log(LOG_ERROR, "Asked to display NULL text (pos %d, inverse flag %d)\n", pos, inverse);
1465 if (pte->device && pte->device->height == 1 && pos != TEXT_LINE0) {
1469 ast_verb(0, "Sending text at pos %d, inverse flag %d\n", pos, inverse);
1471 memcpy(buffsend + SIZE_HEADER, packet_send_text, sizeof(packet_send_text));
1473 buffsend[11] = inverse;
1475 if (i > TEXT_LENGTH_MAX) {
1476 i = TEXT_LENGTH_MAX;
1478 memcpy(buffsend + 12, text, i);
1479 send_client(SIZE_HEADER + sizeof(packet_send_text), buffsend, pte);
1482 static void send_text_status(struct unistimsession *pte, const char *text)
1487 ast_verb(0, "Sending status text\n");
1490 if (pte->device->status_method == 1) { /* For new firmware and i2050 soft phone */
1491 int n = strlen(text);
1492 /* Must send individual button separately */
1494 for (i = 0, j = 0; i < 4; i++, j += 7) {
1495 int pos = 0x08 + (i * 0x20);
1496 memcpy(buffsend + SIZE_HEADER, packet_send_status2,
1497 sizeof(packet_send_status2));
1500 memcpy(buffsend + 10, (j < n) ? (text + j) : " ", 7);
1501 send_client(SIZE_HEADER + sizeof(packet_send_status2), buffsend, pte);
1508 memcpy(buffsend + SIZE_HEADER, packet_send_status, sizeof(packet_send_status));
1510 if (i > STATUS_LENGTH_MAX) {
1511 i = STATUS_LENGTH_MAX;
1513 memcpy(buffsend + 10, text, i);
1514 send_client(SIZE_HEADER + sizeof(packet_send_status), buffsend, pte);
1518 /* led values in hexa : 0 = bar off, 1 = bar on, 2 = bar 1s on/1s off, 3 = bar 2.5s on/0.5s off
1519 * 4 = bar 0.6s on/0.3s off, 5 = bar 0.5s on/0.5s off, 6 = bar 2s on/0.5s off
1520 * 7 = bar off, 8 = speaker off, 9 = speaker on, 10 = headphone off, 11 = headphone on
1521 * 18 = mute off, 19 mute on */
1522 static void send_led_update(struct unistimsession *pte, unsigned char led)
1526 ast_verb(0, "Sending led_update (%x)\n", led);
1528 memcpy(buffsend + SIZE_HEADER, packet_send_led_update, sizeof(packet_send_led_update));
1530 send_client(SIZE_HEADER + sizeof(packet_send_led_update), buffsend, pte);
1533 /* output = OUTPUT_HANDSET, OUTPUT_HEADPHONE or OUTPUT_SPEAKER
1534 * volume = VOLUME_LOW, VOLUME_NORMAL, VOLUME_INSANELY_LOUD
1535 * mute = MUTE_OFF, MUTE_ON */
1537 send_select_output(struct unistimsession *pte, unsigned char output, unsigned char volume,
1542 ast_verb(0, "Sending select output packet output=%x volume=%x mute=%x\n", output,
1545 memcpy(buffsend + SIZE_HEADER, packet_send_select_output,
1546 sizeof(packet_send_select_output));
1547 buffsend[9] = output;
1548 if (output == OUTPUT_SPEAKER) {
1549 volume = VOLUME_LOW_SPEAKER;
1551 volume = VOLUME_LOW;
1553 buffsend[10] = volume;
1554 if (mute == MUTE_ON_DISCRET) {
1555 buffsend[11] = MUTE_ON;
1557 buffsend[11] = mute;
1559 send_client(SIZE_HEADER + sizeof(packet_send_select_output), buffsend, pte);
1560 if (mute == MUTE_OFF) {
1561 send_led_update(pte, 0x18);
1562 } else if (mute == MUTE_ON) {
1563 send_led_update(pte, 0x19);
1565 pte->device->mute = mute;
1566 if (output == OUTPUT_HANDSET) {
1567 if (mute == MUTE_ON) {
1568 change_favorite_icon(pte, FAV_ICON_ONHOLD_BLACK);
1570 change_favorite_icon(pte, FAV_ICON_OFFHOOK_BLACK);
1572 send_led_update(pte, 0x08);
1573 send_led_update(pte, 0x10);
1574 } else if (output == OUTPUT_HEADPHONE) {
1575 if (mute == MUTE_ON) {
1576 change_favorite_icon(pte, FAV_ICON_HEADPHONES_ONHOLD);
1578 change_favorite_icon(pte, FAV_ICON_HEADPHONES);
1580 send_led_update(pte, 0x08);
1581 send_led_update(pte, 0x11);
1582 } else if (output == OUTPUT_SPEAKER) {
1583 send_led_update(pte, 0x10);
1584 send_led_update(pte, 0x09);
1585 if (pte->device->receiver_state == STATE_OFFHOOK) {
1586 if (mute == MUTE_ON) {
1587 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1589 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOOK_BLACK);
1592 if (mute == MUTE_ON) {
1593 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1595 change_favorite_icon(pte, FAV_ICON_SPEAKER_OFFHOOK_BLACK);
1599 ast_log(LOG_WARNING, "Invalid output (%d)\n", output);
1601 if (output != pte->device->output) {
1602 pte->device->previous_output = pte->device->output;
1604 pte->device->output = output;
1607 static void send_ring(struct unistimsession *pte, char volume, char style)
1611 ast_verb(0, "Sending ring packet\n");
1613 memcpy(buffsend + SIZE_HEADER, packet_send_ring, sizeof(packet_send_ring));
1614 buffsend[24] = style + 0x10;
1615 buffsend[29] = volume * 0x10;
1616 send_client(SIZE_HEADER + sizeof(packet_send_ring), buffsend, pte);
1619 static void send_no_ring(struct unistimsession *pte)
1623 ast_verb(0, "Sending no ring packet\n");
1625 memcpy(buffsend + SIZE_HEADER, packet_send_no_ring, sizeof(packet_send_no_ring));
1626 send_client(SIZE_HEADER + sizeof(packet_send_no_ring), buffsend, pte);
1629 static void send_texttitle(struct unistimsession *pte, const char *text)
1634 ast_verb(0, "Sending title text\n");
1636 memcpy(buffsend + SIZE_HEADER, packet_send_title, sizeof(packet_send_title));
1641 memcpy(buffsend + 10, text, i);
1642 send_client(SIZE_HEADER + sizeof(packet_send_title), buffsend, pte);
1646 static void send_idle_clock(struct unistimsession *pte)
1648 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
1651 static void send_date_time(struct unistimsession *pte)
1654 struct timeval now = ast_tvnow();
1655 struct ast_tm atm = { 0, };
1658 ast_verb(0, "Sending Time & Date\n");
1660 memcpy(buffsend + SIZE_HEADER, packet_send_date_time, sizeof(packet_send_date_time));
1661 ast_localtime(&now, &atm, NULL);
1662 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1663 buffsend[11] = (unsigned char) atm.tm_mday;
1664 buffsend[12] = (unsigned char) atm.tm_hour;
1665 buffsend[13] = (unsigned char) atm.tm_min;
1666 send_client(SIZE_HEADER + sizeof(packet_send_date_time), buffsend, pte);
1669 static void send_date_time2(struct unistimsession *pte)
1672 struct timeval now = ast_tvnow();
1673 struct ast_tm atm = { 0, };
1676 ast_verb(0, "Sending Time & Date #2\n");
1678 memcpy(buffsend + SIZE_HEADER, packet_send_date_time2, sizeof(packet_send_date_time2));
1679 ast_localtime(&now, &atm, NULL);
1681 buffsend[9] = pte->device->datetimeformat;
1685 buffsend[14] = (unsigned char) atm.tm_mon + 1;
1686 buffsend[15] = (unsigned char) atm.tm_mday;
1687 buffsend[16] = (unsigned char) atm.tm_hour;
1688 buffsend[17] = (unsigned char) atm.tm_min;
1689 send_client(SIZE_HEADER + sizeof(packet_send_date_time2), buffsend, pte);
1692 static void send_date_time3(struct unistimsession *pte)
1695 struct timeval now = ast_tvnow();
1696 struct ast_tm atm = { 0, };
1699 ast_verb(0, "Sending Time & Date #3\n");
1701 memcpy(buffsend + SIZE_HEADER, packet_send_date_time3, sizeof(packet_send_date_time3));
1702 ast_localtime(&now, &atm, NULL);
1703 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1704 buffsend[11] = (unsigned char) atm.tm_mday;
1705 buffsend[12] = (unsigned char) atm.tm_hour;
1706 buffsend[13] = (unsigned char) atm.tm_min;
1707 send_client(SIZE_HEADER + sizeof(packet_send_date_time3), buffsend, pte);
1710 static void send_blink_cursor(struct unistimsession *pte)
1714 ast_verb(0, "Sending set blink\n");
1716 memcpy(buffsend + SIZE_HEADER, packet_send_blink_cursor, sizeof(packet_send_blink_cursor));
1717 send_client(SIZE_HEADER + sizeof(packet_send_blink_cursor), buffsend, pte);
1721 /* pos : 0xab (a=0/2/4 = line ; b = row) */
1722 static void send_cursor_pos(struct unistimsession *pte, unsigned char pos)
1726 ast_verb(0, "Sending set cursor position\n");
1728 memcpy(buffsend + SIZE_HEADER, packet_send_set_pos_cursor,
1729 sizeof(packet_send_set_pos_cursor));
1731 send_client(SIZE_HEADER + sizeof(packet_send_set_pos_cursor), buffsend, pte);
1735 static void send_charset_update(struct unistimsession *pte, int charset)
1737 const unsigned char* packet_send_charset;
1741 ast_verb(0, "Sending set default charset\n");
1743 if (charset == LANG_DEFAULT) {
1744 charset = options_languages[find_language(pte->device->language)].encoding;
1748 packet_send_charset = packet_send_charset_iso_8859_2;
1749 packet_size = sizeof(packet_send_charset_iso_8859_2);
1752 packet_send_charset = packet_send_charset_iso_8859_4;
1753 packet_size = sizeof(packet_send_charset_iso_8859_4);
1756 packet_send_charset = packet_send_charset_iso_8859_5;
1757 packet_size = sizeof(packet_send_charset_iso_8859_5);
1760 packet_send_charset = packet_send_charset_iso_2022_jp;
1761 packet_size = sizeof(packet_send_charset_iso_2022_jp);
1765 packet_send_charset = packet_send_charset_iso_8859_1;
1766 packet_size = sizeof(packet_send_charset_iso_8859_1);
1768 memcpy(buffsend + SIZE_HEADER, packet_send_charset, packet_size);
1769 send_client(SIZE_HEADER + packet_size, buffsend, pte);
1773 static void rcv_resume_connection_with_server(struct unistimsession *pte)
1777 ast_verb(0, "ResumeConnectionWithServer received\n");
1778 ast_verb(0, "Sending packet_send_query_mac_address\n");
1780 memcpy(buffsend + SIZE_HEADER, packet_send_query_mac_address,
1781 sizeof(packet_send_query_mac_address));
1782 send_client(SIZE_HEADER + sizeof(packet_send_query_mac_address), buffsend, pte);
1786 static int unistim_register(struct unistimsession *s)
1788 struct unistim_device *d;
1790 ast_mutex_lock(&devicelock);
1793 if (!strcasecmp(s->macaddr, d->id)) {
1794 /* XXX Deal with IP authentication */
1797 d->codec_number = DEFAULT_CODEC;
1799 d->receiver_state = STATE_ONHOOK;
1804 ast_mutex_unlock(&devicelock);
1813 static void unistim_line_copy(struct unistim_line *dst, struct unistim_line *src)
1815 struct ast_format_cap *tmp = src->cap;
1816 memcpy(dst, src, sizeof(*dst)); /* this over writes the cap ptr, so we have to reset it */
1818 ast_format_cap_copy(src->cap, dst->cap);
1821 static struct unistim_line *unistim_line_destroy(struct unistim_line *l)
1826 l->cap = ast_format_cap_destroy(l->cap);
1831 static struct unistim_line *unistim_line_alloc(void)
1833 struct unistim_line *l;
1834 if (!(l = ast_calloc(1, sizeof(*l)))) {
1838 if (!(l->cap = ast_format_cap_alloc_nolock())) {
1845 static int unistim_free_sub(struct unistim_subchannel *sub) {
1847 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->subtype, sub->parent->name, sub->parent->parent->name);
1849 ast_mutex_destroy(&sub->lock);
1854 static struct unistim_subchannel *unistim_alloc_sub(struct unistim_device *d, int x)
1856 struct unistim_subchannel *sub;
1857 if (!(sub = ast_calloc(1, sizeof(*sub)))) {
1862 ast_verb(3, "Allocating UNISTIM subchannel #%d on %s ptr=%p\n", x, d->name, sub);
1864 sub->ss_thread = AST_PTHREADT_NULL;
1866 AST_LIST_LOCK(&d->subs);
1867 AST_LIST_INSERT_TAIL(&d->subs, sub, list);
1868 AST_LIST_UNLOCK(&d->subs);
1869 ast_mutex_init(&sub->lock);
1873 static int unistim_unalloc_sub(struct unistim_device *d, struct unistim_subchannel *sub)
1875 struct unistim_subchannel *s;
1877 AST_LIST_LOCK(&d->subs);
1878 AST_LIST_TRAVERSE_SAFE_BEGIN(&d->subs, s, list) {
1885 AST_LIST_REMOVE_CURRENT(list);
1886 unistim_free_sub(sub);
1888 AST_LIST_TRAVERSE_SAFE_END;
1889 AST_LIST_UNLOCK(&d->subs);
1893 static const char *subtype_tostr(const int type)
1908 static const char *ptestate_tostr(const int type)
1913 case STATE_AUTHDENY:
1915 case STATE_MAINPAGE:
1917 case STATE_EXTENSION:
1919 case STATE_DIALPAGE:
1925 case STATE_SELECTOPTION:
1926 return "SELECTOPTION";
1927 case STATE_SELECTCODEC:
1928 return "SELECTCODEC";
1929 case STATE_SELECTLANGUAGE:
1930 return "SELECTLANGUAGE";
1931 case STATE_CLEANING:
1939 static void rcv_mac_addr(struct unistimsession *pte, const unsigned char *buf)
1945 for (tmp = 15; tmp < 15 + SIZE_HEADER; tmp++) {
1946 sprintf(&addrmac[i], "%.2x", (unsigned char) buf[tmp]);
1950 ast_verb(0, "MAC Address received: %s\n", addrmac);
1952 strcpy(pte->macaddr, addrmac);
1953 res = unistim_register(pte);
1955 switch (autoprovisioning) {
1956 case AUTOPROVISIONING_NO:
1957 ast_log(LOG_WARNING, "No entry found for this phone : %s\n", addrmac);
1958 pte->state = STATE_AUTHDENY;
1960 case AUTOPROVISIONING_YES:
1962 struct unistim_device *d = NULL, *newd = NULL;
1963 struct unistim_line *newl = NULL, *l = NULL;
1965 ast_verb(0, "New phone, autoprovisioning on\n");
1967 /* First : locate the [template] section */
1968 ast_mutex_lock(&devicelock);
1971 if (strcasecmp(d->name, "template")) {
1975 /* Found, cloning this entry */
1976 if (!(newd = ast_malloc(sizeof(*newd)))) {
1977 ast_mutex_unlock(&devicelock);
1980 memcpy(newd, d, sizeof(*newd));
1981 ast_mutex_init(&newd->lock);
1982 newd->lines.first = NULL;
1983 newd->lines.last = NULL;
1984 AST_LIST_LOCK(&d->lines);
1985 AST_LIST_TRAVERSE(&d->lines, l, list) {
1986 if (!(newl = unistim_line_alloc())) {
1989 unistim_line_copy(l, newl);
1990 newl->parent = newd;
1991 ast_copy_string(newl->name, l->name, sizeof(newl->name));
1992 snprintf(newl->fullname, sizeof(newl->fullname), "USTM/%s@%s",
1993 newl->name, newd->name);
1994 snprintf(l->name, sizeof(l->name), "%d", atoi(l->name) + 1);
1996 AST_LIST_LOCK(&newd->lines);
1997 AST_LIST_INSERT_TAIL(&newd->lines, newl, list);
1998 AST_LIST_UNLOCK(&newd->lines);
2000 AST_LIST_UNLOCK(&d->lines);
2003 ast_mutex_unlock(&devicelock);
2006 /* Ok, now updating some fields */
2007 ast_copy_string(newd->id, addrmac, sizeof(newd->id));
2008 ast_copy_string(newd->name, addrmac, sizeof(newd->name));
2009 if (newd->extension == EXTENSION_NONE) {
2010 newd->extension = EXTENSION_ASK;
2013 newd->receiver_state = STATE_ONHOOK;
2014 newd->session = pte;
2015 newd->language[0] = '\0';
2016 newd->to_delete = -1;
2020 /* Go to the end of the linked chain */
2028 ast_mutex_unlock(&devicelock);
2030 ast_log(LOG_WARNING, "No entry [template] found in unistim.conf\n");
2031 pte->state = STATE_AUTHDENY;
2035 case AUTOPROVISIONING_TN:
2036 pte->state = STATE_AUTHDENY;
2039 ast_log(LOG_WARNING, "Internal error : unknown autoprovisioning value = %d\n",
2043 if (pte->state != STATE_AUTHDENY) {
2044 struct unistim_line *line;
2045 struct unistim_subchannel *sub;
2047 ast_verb(3, "Device '%s' successfuly registered\n", pte->device->name);
2049 AST_LIST_LOCK(&pte->device->subs);
2050 AST_LIST_TRAVERSE_SAFE_BEGIN(&pte->device->subs, sub, list) {
2052 ast_log(LOG_ERROR, "Subchannel lost sice reboot. Hanged channel may apear!\n");
2053 AST_LIST_REMOVE_CURRENT(list);
2057 AST_LIST_TRAVERSE_SAFE_END;
2058 AST_LIST_UNLOCK(&pte->device->subs);
2060 switch (pte->device->extension) {
2061 case EXTENSION_NONE:
2062 pte->state = STATE_MAINPAGE;
2065 /* Checking if we already have an extension number */
2066 if (ast_strlen_zero(pte->device->extension_number)) {
2067 pte->state = STATE_EXTENSION;
2069 /* Yes, because of a phone reboot. We don't ask again for the TN */
2070 if (register_extension(pte)) {
2071 pte->state = STATE_EXTENSION;
2073 pte->state = STATE_MAINPAGE;
2077 case EXTENSION_LINE:
2078 line = AST_LIST_FIRST(&pte->device->lines);
2079 ast_copy_string(pte->device->extension_number, line->name,
2080 sizeof(pte->device->extension_number));
2081 if (register_extension(pte)) {
2082 pte->state = STATE_EXTENSION;
2084 pte->state = STATE_MAINPAGE;
2088 /* If we are here, it's because of a phone reboot */
2089 pte->state = STATE_MAINPAGE;
2092 ast_log(LOG_WARNING, "Internal error, extension value unknown : %d\n",
2093 pte->device->extension);
2094 pte->state = STATE_AUTHDENY;
2098 if (pte->state == STATE_EXTENSION) {
2099 if (pte->device->extension != EXTENSION_TN) {
2100 pte->device->extension = EXTENSION_ASK;
2102 pte->device->extension_number[0] = '\0';
2105 ast_verb(0, "\nSending S1\n");
2107 memcpy(buffsend + SIZE_HEADER, packet_send_S1, sizeof(packet_send_S1));
2108 send_client(SIZE_HEADER + sizeof(packet_send_S1), buffsend, pte);
2111 ast_verb(0, "Sending query_basic_manager_04\n");
2113 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_04,
2114 sizeof(packet_send_query_basic_manager_04));
2115 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_04), buffsend, pte);
2118 ast_verb(0, "Sending query_basic_manager_10\n");
2120 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_10,
2121 sizeof(packet_send_query_basic_manager_10));
2122 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_10), buffsend, pte);
2124 send_date_time(pte);
2128 static int write_entry_history(struct unistimsession *pte, FILE * f, char c, char *line1)
2130 if (fwrite(&c, 1, 1, f) != 1) {
2131 display_last_error("Unable to write history log header.");
2134 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
2135 display_last_error("Unable to write history entry - date.");
2138 if (fwrite(pte->device->lst_cid, TEXT_LENGTH_MAX, 1, f) != 1) {
2139 display_last_error("Unable to write history entry - callerid.");
2142 if (fwrite(pte->device->lst_cnm, TEXT_LENGTH_MAX, 1, f) != 1) {
2143 display_last_error("Unable to write history entry - callername.");
2149 static int write_history(struct unistimsession *pte, char way, char ismissed)
2151 char tmp[AST_CONFIG_MAX_PATH], tmp2[AST_CONFIG_MAX_PATH];
2152 char line1[TEXT_LENGTH_MAX + 1];
2153 char count = 0, *histbuf;
2156 struct timeval now = ast_tvnow();
2157 struct ast_tm atm = { 0, };
2162 if (!pte->device->callhistory) {
2165 if (strchr(pte->device->name, '/') || (pte->device->name[0] == '.')) {
2166 ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n",
2171 snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_LOG_DIR, USTM_LOG_DIR);
2172 if (ast_mkdir(tmp, 0770)) {
2173 ast_log(LOG_WARNING, "Unable to create directory for history\n");
2177 ast_localtime(&now, &atm, NULL);
2180 ast_copy_string(tmp2, ustmtext("Miss", pte), sizeof(tmp2));
2182 ast_copy_string(tmp2, ustmtext("Fail", pte), sizeof(tmp2));
2185 ast_copy_string(tmp2, ustmtext("Answ", pte), sizeof(tmp2));
2187 snprintf(line1, sizeof(line1), "%04d/%02d/%02d %02d:%02d:%02d %s",
2188 atm.tm_year + 1900, atm.tm_mon + 1, atm.tm_mday, atm.tm_hour,
2189 atm.tm_min, atm.tm_sec, tmp2);
2191 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
2192 USTM_LOG_DIR, pte->device->name, way);
2193 if ((f = fopen(tmp, "r"))) {
2194 struct stat bufstat;
2196 if (stat(tmp, &bufstat)) {
2197 display_last_error("Unable to stat history log.");
2201 size = 1 + (MAX_ENTRY_LOG * TEXT_LENGTH_MAX * 3);
2202 if (bufstat.st_size != size) {
2203 ast_log(LOG_WARNING,
2204 "History file %s has an incorrect size (%d instead of %d). It will be replaced by a new one.",
2205 tmp, (int) bufstat.st_size, size);
2212 /* If we can't open the log file, we create a brand new one */
2217 if ((errno != ENOENT) && (count == 0)) {
2218 display_last_error("Unable to open history log.");
2221 f = fopen(tmp, "w");
2223 display_last_error("Unable to create history log.");
2226 if (write_entry_history(pte, f, c, line1)) {
2230 memset(line1, ' ', TEXT_LENGTH_MAX);
2231 for (i = 3; i < MAX_ENTRY_LOG * 3; i++) {
2232 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
2233 display_last_error("Unable to write history entry - stuffing.");
2239 display_last_error("Unable to close history - creation.");
2243 /* We can open the log file, we create a temporary one, we add our entry and copy the rest */
2244 if (fread(&count, 1, 1, f) != 1) {
2245 display_last_error("Unable to read history header.");
2249 if (count > MAX_ENTRY_LOG) {
2250 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
2251 count, MAX_ENTRY_LOG);
2255 snprintf(tmp2, sizeof(tmp2), "%s/%s/%s-%c.csv.tmp", ast_config_AST_LOG_DIR,
2256 USTM_LOG_DIR, pte->device->name, way);
2257 if (!(f2 = fopen(tmp2, "w"))) {
2258 display_last_error("Unable to create temporary history log.");
2263 if (++count > MAX_ENTRY_LOG) {
2264 count = MAX_ENTRY_LOG;
2266 if (write_entry_history(pte, f2, count, line1)) {
2271 size = (MAX_ENTRY_LOG - 1) * TEXT_LENGTH_MAX * 3;
2272 if (!(histbuf = ast_malloc(size))) {
2278 if (fread(histbuf, size, 1, f) != 1) {
2282 display_last_error("Unable to read previous history entries.");
2285 if (fwrite(histbuf, size, 1, f2) != 1) {
2289 display_last_error("Unable to write previous history entries.");
2294 display_last_error("Unable to close history log.");
2297 display_last_error("Unable to close temporary history log.");
2300 display_last_error("Unable to remove old history log.");
2302 if (rename(tmp2, tmp)) {
2303 display_last_error("Unable to rename new history log.");
2308 static void unistim_quiet_chan(struct ast_channel *chan)
2310 if (chan && ast_channel_state(chan) == AST_STATE_UP) {
2311 if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_MOH)) {
2313 } else if (ast_channel_generatordata(chan)) {
2314 ast_deactivate_generator(chan);
2319 static int attempt_transfer(struct unistim_subchannel *p1, struct unistim_subchannel *p2)
2323 *chana = NULL, *chanb = NULL, *bridgea = NULL, *bridgeb = NULL, *peera =
2324 NULL, *peerb = NULL, *peerc = NULL, *peerd = NULL;
2326 if (!p1->owner || !p2->owner) {
2327 ast_log(LOG_WARNING, "Transfer attempted without dual ownership?\n");
2332 bridgea = ast_bridged_channel(chana);
2333 bridgeb = ast_bridged_channel(chanb);
2340 } else if (bridgeb) {
2347 if (peera && peerb && peerc && (peerb != peerc)) {
2348 unistim_quiet_chan(peera);
2349 unistim_quiet_chan(peerb);
2350 unistim_quiet_chan(peerc);
2352 unistim_quiet_chan(peerd);
2355 ast_log(LOG_NOTICE, "UNISTIM transfer: trying to masquerade %s into %s\n", ast_channel_name(peerc), ast_channel_name(peerb));
2356 if (ast_channel_masquerade(peerb, peerc)) {
2357 ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", ast_channel_name(peerb),
2358 ast_channel_name(peerc));
2364 "Transfer attempted with no appropriate bridged calls to transfer\n");
2366 ast_softhangup_nolock(chana, AST_SOFTHANGUP_DEV);
2369 ast_softhangup_nolock(chanb, AST_SOFTHANGUP_DEV);
2376 void change_callerid(struct unistimsession *pte, int type, char *callerid)
2382 data = pte->device->lst_cnm;
2384 data = pte->device->lst_cid;
2387 /* This is very nearly strncpy(), except that the remaining buffer
2388 * is padded with ' ', instead of '\0' */
2389 memset(data, ' ', TEXT_LENGTH_MAX);
2390 size = strlen(callerid);
2391 if (size > TEXT_LENGTH_MAX) {
2392 size = TEXT_LENGTH_MAX;
2394 memcpy(data, callerid, size);
2397 static struct unistim_subchannel* get_sub(struct unistim_device *device, int type)
2399 struct unistim_subchannel *sub = NULL;
2401 AST_LIST_LOCK(&device->subs);
2402 AST_LIST_TRAVERSE(&device->subs, sub, list) {
2406 if (sub->subtype == type) {
2410 AST_LIST_UNLOCK(&device->subs);
2415 static void sub_start_silence(struct unistimsession *pte, struct unistim_subchannel *sub)
2417 /* Silence our channel */
2418 if (!pte->device->silence_generator) {
2419 pte->device->silence_generator =
2420 ast_channel_start_silence_generator(sub->owner);
2421 if (pte->device->silence_generator == NULL) {
2422 ast_log(LOG_WARNING, "Unable to start a silence generator.\n");
2423 } else if (unistimdebug) {
2424 ast_verb(0, "Starting silence generator\n");
2430 static void sub_stop_silence(struct unistimsession *pte, struct unistim_subchannel *sub)
2432 /* Stop the silence generator */
2433 if (pte->device->silence_generator) {
2435 ast_verb(0, "Stopping silence generator\n");
2438 ast_channel_stop_silence_generator(sub->owner, pte->device->silence_generator);
2440 ast_log(LOG_WARNING, "Trying to stop silence generator on a null channel!\n");
2442 pte->device->silence_generator = NULL;
2446 static void sub_hold(struct unistimsession *pte, struct unistim_subchannel *sub)
2452 sub->subtype = SUB_ONHOLD;
2453 send_favorite_short(sub->softkey, FAV_ICON_ONHOLD_BLACK + FAV_BLINK_SLOW, pte);
2454 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
2455 send_stop_timer(pte);
2457 ast_queue_hold(sub->owner, NULL);
2463 static void sub_unhold(struct unistimsession *pte, struct unistim_subchannel *sub)
2465 struct unistim_subchannel *sub_real;
2467 sub_real = get_sub(pte->device, SUB_REAL);
2469 sub_hold(pte, sub_real);
2473 sub->subtype = SUB_REAL;
2474 send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, pte);
2475 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2476 send_start_timer(pte);
2478 ast_queue_unhold(sub->owner);
2480 send_start_rtp(sub);
2486 static void close_call(struct unistimsession *pte)
2488 struct unistim_subchannel *sub, *sub_transf;
2490 sub = get_sub(pte->device, SUB_REAL);
2491 sub_transf = get_sub(pte->device, SUB_THREEWAY);
2492 send_stop_timer(pte);
2494 ast_log(LOG_WARNING, "Close call without sub\n");
2497 send_favorite_short(sub->softkey, FAV_LINE_ICON, pte);
2499 sub->alreadygone = 1;
2501 sub_transf->alreadygone = 1;
2502 if (attempt_transfer(sub, sub_transf) < 0) {
2503 ast_verb(0, "attempt_transfer failed.\n");
2506 ast_queue_hangup(sub->owner);
2510 if (sub_transf->owner) {
2511 ast_queue_hangup_with_cause(sub_transf->owner, AST_CAUSE_NORMAL_CLEARING);
2513 ast_log(LOG_WARNING, "threeway sub without owner\n");
2516 ast_verb(0, "USTM(%s@%s-%d) channel already destroyed\n", sub->parent->name,
2517 pte->device->name, sub->softkey);
2520 change_callerid(pte, 0, pte->device->redial_number);
2521 change_callerid(pte, 1, "");
2522 write_history(pte, 'o', pte->device->missed_call);
2523 pte->device->missed_call = 0;
2524 show_main_page(pte);
2528 static void ignore_call(struct unistimsession *pte)
2534 static void discard_call(struct unistimsession *pte)
2536 struct unistim_subchannel* sub;
2537 sub = get_sub(pte->device, SUB_RING);
2542 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NORMAL_CLEARING);
2546 static void *unistim_ss(void *data)
2548 struct ast_channel *chan = data;
2549 struct unistim_subchannel *sub = ast_channel_tech_pvt(chan);
2550 struct unistim_line *l = sub->parent;
2551 struct unistimsession *s = l->parent->session;
2554 ast_verb(3, "Starting switch on '%s@%s-%d' to %s\n", l->name, l->parent->name, sub->softkey, s->device->phone_number);
2555 ast_channel_exten_set(chan, s->device->phone_number);
2556 ast_copy_string(s->device->redial_number, s->device->phone_number,
2557 sizeof(s->device->redial_number));
2558 ast_setstate(chan, AST_STATE_RING);
2559 res = ast_pbx_run(chan);
2561 ast_log(LOG_WARNING, "PBX exited non-zero\n");
2562 send_tone(s, 1000, 0);
2567 static int find_rtp_port(struct unistim_subchannel *s)
2569 struct unistim_subchannel *sub = NULL;
2570 int rtp_start = s->parent->parent->rtp_port;
2571 struct ast_sockaddr us_tmp;
2572 struct sockaddr_in us = { 0, };
2574 AST_LIST_LOCK(&s->parent->parent->subs);
2575 AST_LIST_TRAVERSE(&s->parent->parent->subs, sub, list) {
2580 ast_rtp_instance_get_remote_address(sub->rtp, &us_tmp);
2581 ast_sockaddr_to_sin(&us_tmp, &us);
2582 if (htons(us.sin_port)) {
2583 rtp_start = htons(us.sin_port) + 1;
2588 AST_LIST_UNLOCK(&s->parent->parent->subs);
2592 static void send_start_rtp(struct unistim_subchannel *sub)
2597 struct sockaddr_in public = { 0, };
2598 struct sockaddr_in us = { 0, };
2599 struct sockaddr_in sin = { 0, };
2600 struct ast_sockaddr us_tmp;
2601 struct ast_sockaddr sin_tmp;
2602 struct unistimsession *pte;
2604 ast_rtp_instance_get_local_address(sub->rtp, &us_tmp);
2605 ast_sockaddr_to_sin(&us_tmp, &us);
2606 ast_rtp_instance_get_remote_address(sub->rtp, &sin_tmp);
2607 ast_sockaddr_to_sin(&sin_tmp, &sin);
2609 /* Setting up RTP of the phone */
2610 if (public_ip.sin_family == 0) { /* NAT IP override ? */
2611 memcpy(&public, &us, sizeof(public)); /* No defined, using IP from recvmsg */
2613 memcpy(&public, &public_ip, sizeof(public)); /* override */
2616 ast_verb(0, "RTP started : Our IP/port is : %s:%hd with codec %s\n",
2617 ast_inet_ntoa(us.sin_addr),
2618 htons(us.sin_port), ast_getformatname(ast_channel_readformat(sub->owner)));
2619 ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n",
2620 ast_inet_ntoa(public.sin_addr));
2623 pte = sub->parent->parent->session;
2624 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, ast_channel_readformat(sub->owner), 0);
2625 if ((ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) ||
2626 (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW)) {
2628 ast_verb(0, "Sending packet_send_rtp_packet_size for codec %d\n", codec);
2630 memcpy(buffsend + SIZE_HEADER, packet_send_rtp_packet_size,
2631 sizeof(packet_send_rtp_packet_size));
2632 buffsend[10] = (int) codec & 0xffffffffLL;
2633 send_client(SIZE_HEADER + sizeof(packet_send_rtp_packet_size), buffsend, pte);
2636 ast_verb(0, "Sending Jitter Buffer Parameters Configuration\n");
2638 memcpy(buffsend + SIZE_HEADER, packet_send_jitter_buffer_conf,
2639 sizeof(packet_send_jitter_buffer_conf));
2640 send_client(SIZE_HEADER + sizeof(packet_send_jitter_buffer_conf), buffsend, pte);
2641 if (pte->device->rtp_method != 0) {
2642 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2645 ast_verb(0, "Sending OpenAudioStreamTX using method #%d\n", pte->device->rtp_method);
2647 if (pte->device->rtp_method == 3) {
2648 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx3,
2649 sizeof(packet_send_open_audio_stream_tx3));
2651 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx,
2652 sizeof(packet_send_open_audio_stream_tx));
2654 if (pte->device->rtp_method != 2) {
2655 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2656 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2657 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2658 buffsend[23] = (rtcpsin_port & 0x00ff);
2659 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2660 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2661 buffsend[24] = (us.sin_port & 0x00ff);
2662 buffsend[27] = (rtcpsin_port & 0x00ff);
2663 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2665 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2666 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2667 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2668 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2669 buffsend[19] = (us.sin_port & 0x00ff);
2671 buffsend[11] = codec; /* rx */
2672 buffsend[12] = codec; /* tx */
2673 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_tx), buffsend, pte);
2676 ast_verb(0, "Sending OpenAudioStreamRX\n");
2678 if (pte->device->rtp_method == 3) {
2679 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx3,
2680 sizeof(packet_send_open_audio_stream_rx3));
2682 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx,
2683 sizeof(packet_send_open_audio_stream_rx));
2685 if (pte->device->rtp_method != 2) {
2686 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2687 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2688 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2689 buffsend[23] = (rtcpsin_port & 0x00ff);
2690 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2691 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2692 buffsend[24] = (us.sin_port & 0x00ff);
2693 buffsend[27] = (rtcpsin_port & 0x00ff);
2694 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2696 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2697 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2698 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2699 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2700 buffsend[19] = (us.sin_port & 0x00ff);
2702 buffsend[11] = codec; /* rx */
2703 buffsend[12] = codec; /* tx */
2704 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_rx), buffsend, pte);
2706 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2709 ast_verb(0, "Sending packet_send_call default method\n");
2712 memcpy(buffsend + SIZE_HEADER, packet_send_call, sizeof(packet_send_call));
2713 memcpy(buffsend + 53, &public.sin_addr, sizeof(public.sin_addr));
2714 /* Destination port when sending RTP */
2715 buffsend[49] = (us.sin_port & 0x00ff);
2716 buffsend[50] = (us.sin_port & 0xff00) >> 8;
2717 /* Destination port when sending RTCP */
2718 buffsend[52] = (rtcpsin_port & 0x00ff);
2719 buffsend[51] = (rtcpsin_port & 0xff00) >> 8;
2721 buffsend[40] = codec;
2722 buffsend[41] = codec;
2723 if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) {
2724 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2725 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW) {
2726 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2727 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G723_1) {
2728 buffsend[42] = 2; /* 1 = 30ms (24 bytes), 2 = 60 ms (48 bytes) */
2729 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G729A) {
2730 buffsend[42] = 2; /* 1 = 10ms (10 bytes), 2 = 20ms (20 bytes) */
2732 ast_log(LOG_WARNING, "Unsupported codec %s!\n",
2733 ast_getformatname(ast_channel_readformat(sub->owner)));
2735 /* Source port for transmit RTP and Destination port for receiving RTP */
2736 buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8;
2737 buffsend[46] = (htons(sin.sin_port) & 0x00ff);
2738 buffsend[47] = (rtcpsin_port & 0xff00) >> 8;
2739 buffsend[48] = (rtcpsin_port & 0x00ff);
2740 send_client(SIZE_HEADER + sizeof(packet_send_call), buffsend, pte);
2744 static void start_rtp(struct unistim_subchannel *sub)
2746 struct sockaddr_in sin = { 0, };
2747 struct sockaddr_in sout = { 0, };
2748 struct ast_sockaddr sin_tmp;
2749 struct ast_sockaddr sout_tmp;
2753 ast_log(LOG_WARNING, "start_rtp with a null subchannel !\n");
2757 ast_log(LOG_WARNING, "start_rtp with a null line!\n");
2760 if (!sub->parent->parent) {
2761 ast_log(LOG_WARNING, "start_rtp with a null device!\n");
2764 if (!sub->parent->parent->session) {
2765 ast_log(LOG_WARNING, "start_rtp with a null session!\n");
2769 ast_log(LOG_WARNING, "start_rtp with a null asterisk channel!\n");
2772 sout = sub->parent->parent->session->sout;
2773 ast_mutex_lock(&sub->lock);
2774 /* Allocate the RTP */
2776 ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
2778 ast_sockaddr_from_sin(&sout_tmp, &sout);
2779 sub->rtp = ast_rtp_instance_new("asterisk", sched, &sout_tmp, NULL);
2781 ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
2782 strerror(errno), ast_inet_ntoa(sout.sin_addr));
2783 ast_mutex_unlock(&sub->lock);
2786 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
2787 ast_channel_internal_fd_set(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
2788 ast_channel_internal_fd_set(sub->owner, 1, ast_rtp_instance_fd(sub->rtp, 1));
2789 ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
2790 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->parent->parent->nat);
2792 /* Create the RTP connection */
2793 sin.sin_family = AF_INET;
2794 /* Setting up RTP for our side */
2795 memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
2796 sizeof(sin.sin_addr));
2798 sin.sin_port = htons(find_rtp_port(sub));
2799 ast_sockaddr_from_sin(&sin_tmp, &sin);
2800 ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
2801 if (!ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), ast_channel_readformat(sub->owner))) {
2802 struct ast_format tmpfmt;
2804 ast_best_codec(ast_channel_nativeformats(sub->owner), &tmpfmt);
2805 ast_log(LOG_WARNING,
2806 "Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n",
2807 ast_getformatname(ast_channel_readformat(sub->owner)),
2808 ast_getformatname(&tmpfmt),
2809 ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(sub->owner)));
2811 ast_format_copy(ast_channel_readformat(sub->owner), &tmpfmt);
2812 ast_format_copy(ast_channel_writeformat(sub->owner), &tmpfmt);
2814 send_start_rtp(sub);
2815 ast_mutex_unlock(&sub->lock);
2818 static void send_dial_tone(struct unistimsession *pte)
2820 struct ast_tone_zone_sound *ts = NULL;
2821 struct ast_tone_zone_part tone_data;
2825 if ((ts = ast_get_indication_tone(pte->device->tz, "dial"))) {
2826 ind = ast_strdupa(ts->data);
2827 s = strsep(&ind, ",");
2828 ast_tone_zone_part_parse(s, &tone_data);
2829 if (tone_data.modulate) {
2830 tone_data.freq2 = 0;
2832 send_tone(pte, tone_data.freq1, tone_data.freq2);
2834 ast_verb(0, "Country code found (%s), freq1=%d freq2=%d\n",
2835 pte->device->tz->country, tone_data.freq1, tone_data.freq2);
2837 ts = ast_tone_zone_sound_unref(ts);
2841 static void show_phone_number(struct unistimsession *pte)
2843 char tmp[TEXT_LENGTH_MAX + 1];
2844 const char *tmp_number = ustmtext("Number:", pte);
2845 int line, tmp_copy, offset = 0, i;
2847 pte->device->phone_number[pte->device->size_phone_number] = '\0';
2848 if (pte->device->size_phone_number > MAX_SCREEN_NUMBER) {
2849 offset = pte->device->size_phone_number - MAX_SCREEN_NUMBER - 1;
2850 if (offset > strlen(tmp_number)) {
2851 offset = strlen(tmp_number);
2853 tmp_copy = strlen(tmp_number) - offset + 1;
2854 if (tmp_copy > sizeof(tmp)) {
2855 tmp_copy = sizeof(tmp);
2857 memcpy(tmp, tmp_number + offset, tmp_copy);
2859 ast_copy_string(tmp, tmp_number, sizeof(tmp));
2862 offset = (pte->device->size_phone_number >= TEXT_LENGTH_MAX) ? (pte->device->size_phone_number - TEXT_LENGTH_MAX +1) : 0;
2863 if (pte->device->size_phone_number) {
2864 memcpy(tmp + strlen(tmp), pte->device->phone_number + offset, pte->device->size_phone_number - offset + 1);
2866 offset = strlen(tmp);
2868 for (i = strlen(tmp); i < TEXT_LENGTH_MAX; i++) {
2873 line = (pte->device->height == 1) ? TEXT_LINE0 : TEXT_LINE2;
2874 send_text(line, TEXT_NORMAL, pte, tmp);
2875 send_blink_cursor(pte);
2876 send_cursor_pos(pte, (unsigned char) (line + offset));
2877 send_led_update(pte, 0);
2880 static void handle_dial_page(struct unistimsession *pte)
2882 pte->state = STATE_DIALPAGE;
2883 if (pte->device->call_forward[0] == -1) {
2884 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
2885 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Enter forward", pte));
2886 send_text_status(pte, ustmtext("Fwd Cancel BackSp Erase", pte));
2887 if (pte->device->call_forward[1] != 0) {
2888 ast_copy_string(pte->device->phone_number, pte->device->call_forward + 1,
2889 sizeof(pte->device->phone_number));
2890 show_phone_number(pte);
2891 send_led_update(pte, 0);
2895 if ((pte->device->output == OUTPUT_HANDSET) &&
2896 (pte->device->receiver_state == STATE_ONHOOK)) {
2897 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2899 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2901 send_dial_tone(pte);
2903 if (pte->device->height > 1) {
2904 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Enter the number to dial", pte));
2905 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("and press Call", pte));
2907 send_text_status(pte, ustmtext("Call Redial BackSp Erase", pte));
2910 pte->device->size_phone_number = 0;
2911 pte->device->phone_number[0] = 0;
2912 show_phone_number(pte);
2913 change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
2914 send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
2915 pte->device->missed_call = 0;
2916 send_led_update(pte, 0);
2917 pte->device->lastmsgssent = -1;
2921 static void swap_subs(struct unistim_subchannel *a, struct unistim_subchannel *b)
2923 struct ast_rtp_instance *rtp;
2927 ast_verb(0, "Swapping %p and %p\n", a, b);
2929 if ((!a->owner) || (!b->owner)) {
2930 ast_log(LOG_WARNING,
2931 "Attempted to swap subchannels with a null owner : sub #%p=%p sub #%p=%p\n",
2932 a, a->owner, b, b->owner);
2939 fds = ast_channel_fd(a->owner, 0);
2940 ast_channel_internal_fd_set(a->owner, 0, ast_channel_fd(b->owner, 0));
2941 ast_channel_internal_fd_set(b->owner, 0, fds);
2943 fds = ast_channel_fd(a->owner, 1);
2944 ast_channel_internal_fd_set(a->owner, 1, ast_channel_fd(b->owner, 1));
2945 ast_channel_internal_fd_set(b->owner, 1, fds);
2948 /* Step 1 : Music On Hold for peer, Dialing screen for us */
2949 static void transfer_call_step1(struct unistimsession *pte)
2951 struct unistim_subchannel *sub /*, *sub_trans */;
2952 struct unistim_device *d = pte->device;
2954 sub = get_sub(d, SUB_REAL);
2955 /* sub_trans = get_sub(d, SUB_THREEWAY); */
2957 if (!sub || !sub->owner) {
2958 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2961 /* Start music on hold if appropriate */
2963 ast_log(LOG_WARNING, "Transfer with peer already listening music on hold\n");
2965 ast_queue_hold(sub->owner, sub->parent->musicclass);
2967 sub->subtype = SUB_THREEWAY;
2969 sub_start_silence(pte, sub);
2970 handle_dial_page(pte);
2973 static void transfer_cancel_step2(struct unistimsession *pte)
2975 struct unistim_subchannel *sub, *sub_trans;
2976 struct unistim_device *d = pte->device;
2978 sub = get_sub(d, SUB_REAL);
2979 sub_trans = get_sub(d, SUB_THREEWAY);
2981 if (!sub || !sub->owner) {
2982 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2987 ast_verb(0, "Transfer canceled, hangup our threeway channel\n");
2990 swap_subs(sub, sub_trans);
2991 ast_queue_unhold(sub_trans->owner);
2993 sub_trans->subtype = SUB_REAL;
2994 sub->subtype = SUB_THREEWAY;
2995 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NORMAL_CLEARING);
2997 ast_log(LOG_WARNING, "Canceling a threeway channel without owner\n");
3003 /* From phone to PBX */
3004 static void handle_call_outgoing(struct unistimsession *s)
3006 struct ast_channel *c;
3007 struct unistim_subchannel *sub;
3010 s->state = STATE_CALL;
3012 sub = get_sub(s->device, SUB_THREEWAY);
3014 /* If sub for threway call created than we use transfer behaviuor */
3015 struct unistim_subchannel *sub_trans = NULL;
3016 struct unistim_device *d = s->device;
3018 sub_trans = get_sub(d, SUB_REAL);
3020 ast_log(LOG_WARNING, "Can't transfer while active subchannel exists!\n");
3024 ast_log(LOG_WARNING, "Unable to find subchannel with music on hold\n");
3028 sub_trans = unistim_alloc_sub(d, SUB_REAL);
3030 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
3033 sub_trans->parent = sub->parent;
3034 sub_stop_silence(s, sub);
3036 /* Make new channel */
3037 c = unistim_new(sub_trans, AST_STATE_DOWN, NULL);
3039 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", sub->parent);
3042 /* Swap things around between the three-way and real call */
3043 swap_subs(sub, sub_trans);
3044 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
3045 if (s->device->height == 1) {
3046 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
3048 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling (pre-transfer)", s));
3049 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
3050 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Dialing...", s));
3052 send_text_status(s, ustmtext("TransfrCancel", s));
3054 if (ast_pthread_create(&sub->ss_thread, NULL, unistim_ss, c)) {
3055 ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", c);
3056 sub->ss_thread = AST_PTHREADT_NULL;
3061 ast_verb(0, "Started three way call on channel %p (%s) subchan %d\n",
3062 sub_trans->owner, ast_channel_name(sub_trans->owner), sub_trans->subtype);
3067 softkey = get_avail_softkey(s, NULL);
3068 if (softkey == -1) {
3069 ast_log(LOG_WARNING, "Have no avail softkey for calling\n");
3072 sub = get_sub(s->device, SUB_REAL);
3073 if (sub) { /* have already call assigned */
3074 sub_hold(s, sub); /* Need to put on hold */
3076 if (!(sub = unistim_alloc_sub(s->device, SUB_REAL))) {
3077 ast_log(LOG_WARNING, "Unable to allocate subchannel!\n");
3080 sub->parent = s->device->sline[softkey];
3081 s->device->ssub[softkey] = sub;
3082 sub->softkey = softkey;
3085 ast_verb(0, "Using softkey %d, line %p\n", sub->softkey, sub->parent);
3087 send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, s);
3088 s->device->selected = -1;
3089 if (!sub->owner) { /* A call is already in progress ? */
3090 RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
3091 const char *pickupexten;
3093 c = unistim_new(sub, AST_STATE_DOWN, NULL); /* No, starting a new one */
3094 if (!sub->rtp) { /* Need to start RTP before calling ast_pbx_run */
3098 ast_channel_lock(c);
3099 pickup_cfg = ast_get_chan_features_pickup_config(c);
3101 ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
3104 pickupexten = ast_strdupa(pickup_cfg->pickupexten);
3106 ast_channel_unlock(c);
3108 if (c && !strcmp(s->device->phone_number, pickupexten)) {
3110 ast_verb(0, "Try to pickup in unistim_new\n");
3112 send_text(TEXT_LINE0, TEXT_NORMAL, s, "");
3113 send_text_status(s, ustmtext(" Transf Hangup", s));
3114 send_start_timer(s);
3115 if (ast_pickup_call(c)) {
3116 ast_log(LOG_NOTICE, "Nothing to pick up\n");
3117 ast_channel_hangupcause_set(c, AST_CAUSE_CALL_REJECTED);
3119 ast_channel_hangupcause_set(c, AST_CAUSE_NORMAL_CLEARING);
3124 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
3125 send_tone(s, 0, 0); /* Dialing empty number should also stop dial tone */
3126 if (s->device->height == 1) {
3127 if (strlen(s->device->phone_number) > 0) {
3128 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
3130 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling...", s));
3133 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling :", s));
3134 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
3135 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Dialing...", s));
3137 send_text_status(s, ustmtext(" Hangup", s));
3140 if (ast_pthread_create(&sub->ss_thread, NULL, unistim_ss, c)) {
3141 ast_log(LOG_WARNING, "Unable to create switch thread\n");
3142 sub->ss_thread = AST_PTHREADT_NULL;
3143 ast_queue_hangup_with_cause(c, AST_CAUSE_SWITCH_CONGESTION);
3146 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n",
3147 sub->parent->name, s->device->name);
3149 ast_debug(1, "Current sub [%s] already has owner\n", ast_channel_name(sub->owner));
3154 /* From PBX to phone */
3155 static void handle_call_incoming(struct unistimsession *s)
3157 struct unistim_subchannel *sub = NULL;
3160 s->state = STATE_CALL;
3161 s->device->missed_call = 0;
3163 sub = get_sub(s->device, SUB_RING); /* Put other SUB_REAL call on hold */
3165 ast_log(LOG_WARNING, "No ringing lines on: %s\n", s->device->name);
3168 /* Change icons for all ringing keys */
3169 for (i = 0; i < FAVNUM; i++) {
3170 if (!s->device->ssub[i]) { /* No sub assigned - skip */
3173 if (s->device->ssub[i]->subtype == SUB_REAL) {
3174 sub_hold(s, s->device->ssub[i]);
3176 if (s->device->ssub[i] != sub) {
3179 if (sub->softkey == i) { /* If softkey assigned at this moment - do not erase */
3182 if (sub->softkey < 0) { /* If softkey not defined - first one used */
3186 send_favorite_short(i, FAV_LINE_ICON, s);
3187 s->device->ssub[i] = NULL;
3189 if (sub->softkey < 0) {
3190 ast_log(LOG_WARNING, "Can not assign softkey for incoming call on: %s\n", s->device->name);
3193 send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, s);
3194 sub->parent = s->device->sline[sub->softkey];
3195 sub->subtype = SUB_REAL;
3197 ast_verb(0, "Handle Call Incoming for %s@%s\n", sub->parent->name,
3201 ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
3203 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("is on-line", s));
3204 send_text_status(s, ustmtext(" Transf Hangup", s));
3205 send_start_timer(s);
3207 if ((s->device->output == OUTPUT_HANDSET) &&
3208 (s->device->receiver_state == STATE_ONHOOK)) {
3209 send_select_output(s, OUTPUT_SPEAKER, s->device->volume, MUTE_OFF);
3211 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
3213 write_history(s, 'i', 0);
3217 static int unistim_do_senddigit(struct unistimsession *pte, char digit)
3219 struct ast_frame f = { .frametype = AST_FRAME_DTMF, .subclass.integer = digit, .src = "unistim" };
3220 struct unistim_subchannel *sub;
3223 sub = get_sub(pte->device, SUB_REAL);
3224 if (!sub || !sub->owner || sub->alreadygone) {
3225 ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit\n");
3229 /* Send DTMF indication _before_ playing sounds */
3230 ast_queue_frame(sub->owner, &f);
3233 ast_verb(0, "Send Digit %c\n", digit);
3235 row = (digit - '1') % 3;
3236 col = (digit - '1' - row) / 3;
3237 if (digit >= '1' && digit <='9') {
3238 send_tone(pte, dtmf_row[row], dtmf_col[col]);
3239 } else if (digit >= 'A' && digit <= 'D') {
3240 send_tone(pte, dtmf_row[digit-'A'], dtmf_col[3]);
3241 } else if (digit == '*') {
3242 send_tone(pte, dtmf_row[3], dtmf_col[0]);
3243 } else if (digit == '0') {
3244 send_tone(pte, dtmf_row[3], dtmf_col[1]);
3245 } else if (digit == '#') {
3246 send_tone(pte, dtmf_row[3], dtmf_col[2]);
3248 send_tone(pte, 500, 2000);
3250 usleep(150000); /* XXX Less than perfect, blocking an important thread is not a good idea */
3251 send_tone(pte, 0, 0);
3255 static void handle_key_fav(struct unistimsession *pte, char keycode)
3257 int keynum = keycode - KEY_FAV0;
3258 struct unistim_subchannel *sub;
3260 sub = get_sub(pte->device, SUB_REAL);
3262 /* Make an action on selected favorite key */
3263 if (!pte->device->ssub[keynum]) { /* Key have no assigned call */
3264 send_favorite_selected(FAV_LINE_ICON, pte);
3265 if (is_key_line(pte->device, keynum)) {
3267 ast_verb(0, "Handle line w/o sub - dialpage\n");
3269 pte->device->selected = keynum;
3270 sub_hold(pte, sub); /* Put active call on hold */
3271 send_stop_timer(pte);
3272 handle_dial_page(pte);
3273 } else if (is_key_favorite(pte->device, keynum)) {
3274 /* Put active call on hold in handle_call_outgoing function, after preparation and
3275 checking if lines available for calling */
3277 ast_verb(0, "Handle favorite w/o sub - dialing\n");
3279 if ((pte->device->output == OUTPUT_HANDSET) &&
3280 (pte->device->receiver_state == STATE_ONHOOK)) {
3281 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
3283 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
3285 key_favorite(pte, keycode);
3288 sub = pte->device->ssub[keynum];
3289 /* Favicon have assigned sub, activate it and put current on hold */
3290 if (sub->subtype == SUB_REAL) {
3292 show_main_page(pte);
3293 } else if (sub->subtype == SUB_RING) {
3294 sub->softkey = keynum;
3295 handle_call_incoming(pte);
3296 } else if (sub->subtype == SUB_ONHOLD) {
3297 if (pte->state == STATE_DIALPAGE){
3298 send_tone(pte, 0, 0);
3300 send_callerid_screen(pte, sub);
3301 sub_unhold(pte, sub);
3302 pte->state = STATE_CALL;
3307 static void key_call(struct unistimsession *pte, char keycode)
3309 struct unistim_subchannel *sub = get_sub(pte->device, SUB_REAL);
3310 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
3311 if (keycode == KEY_SHARP) {
3313 } else if (keycode == KEY_STAR) {
3318 unistim_do_senddigit(pte, keycode);
3323 if (ast_channel_state(sub->owner) == AST_STATE_UP) {
3324 if (get_sub(pte->device, SUB_THREEWAY)) {
3330 if (ast_channel_state(sub->owner) == AST_STATE_UP) {
3331 if (get_sub(pte->device, SUB_THREEWAY)) {
3332 transfer_cancel_step2(pte);
3334 transfer_call_step1(pte);
3340 if (!get_sub(pte->device, SUB_THREEWAY)) {
3350 handle_key_fav(pte, keycode);
3353 if (pte->device->output == OUTPUT_HEADPHONE) {
3354 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
3356 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
3360 if (pte->device->output != OUTPUT_SPEAKER)
3361 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
3363 send_select_output(pte, pte->device->previous_output, pte->device->volume,
3367 if (!sub || !sub->owner) {
3368 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
3372 if (pte->device->mute == MUTE_ON) {
3373 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
3375 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
3382 if(pte->device->ssub[pte->device->selected]) {
3383 sub_hold(pte, pte->device->ssub[pte->device->selected]);
3393 static void key_ringing(struct unistimsession *pte, char keycode)
3402 handle_key_fav(pte, keycode);
3412 pte->device->output = OUTPUT_SPEAKER;
3413 handle_call_incoming(pte);
3416 pte->device->output = OUTPUT_HEADPHONE;
3417 handle_call_incoming(pte);
3420 handle_call_incoming(pte);
3426 static void key_favorite(struct unistimsession *pte, char keycode)
3428 int fav = keycode - KEY_FAV0;
3429 if (!is_key_favorite(pte->device, fav)) {
3430 ast_log(LOG_WARNING, "It's not a favorite key\n");
3433 ast_copy_string(pte->device->phone_number, pte->device->softkeynumber[fav],
3434 sizeof(pte->device->phone_number));
3435 handle_call_outgoing(pte);
3439 static void key_dial_page(struct unistimsession *pte, char keycode)
3441 struct unistim_subchannel *sub = get_sub(pte->device, SUB_THREEWAY);
3443 pte->device->nextdial = 0;
3444 if (keycode == KEY_FUNC3) {
3445 if (pte->device->size_phone_number <= 1) {
3446 keycode = KEY_FUNC4;
3448 pte->device->size_phone_number -= 2;
3449 keycode = pte->device->phone_number[pte->device->size_phone_number] + 0x10;
3452 if (keycode == KEY_SHARP && pte->device->sharp_dial == 1) {
3453 keycode = KEY_FUNC1;
3455 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
3456 int i = pte->device->size_phone_number;
3458 if (pte->device->size_phone_number == 0) {
3459 send_tone(pte, 0, 0);
3461 if (keycode == KEY_SHARP) {
3463 } else if (keycode == KEY_STAR) {
3468 pte->device->phone_number[i] = keycode;
3469 pte->device->size_phone_number++;
3470 pte->device->phone_number[i + 1] = 0;
3471 show_phone_number(pte);
3473 if (ast_exists_extension(NULL, pte->device->context, pte->device->phone_number, 1, NULL) &&
3474 !ast_matchmore_extension(NULL, pte->device->context, pte->device->phone_number, 1, NULL)) {
3475 keycode = KEY_FUNC1;
3477 if (pte->device->interdigit_timer) {
3478 pte->device->nextdial = get_tick_count() + pte->device->interdigit_timer;
3482 if (keycode == KEY_FUNC4) {
3483 pte->device->size_phone_number = 0;
3484 show_phone_number(pte);
3488 if (pte->device->call_forward[0] == -1) {
3489 if (keycode == KEY_FUNC1) {
3490 ast_copy_string(pte->device->call_forward, pte->device->phone_number,
3491 sizeof(pte->device->call_forward));
3492 show_main_page(pte);
3493 } else if ((keycode == KEY_FUNC2) || (keycode == KEY_HANGUP)) {
3494 pte->device->call_forward[0] = '\0';
3495 send_led_update(pte, 0x08);
3496 send_led_update(pte, 0x10);
3497 show_main_page(pte);
3503 if (ast_strlen_zero(pte->device->redial_number)) {
3506 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
3507 sizeof(pte->device->phone_number));
3509 handle_call_outgoing(pte);
3512 if (sub && sub->owner) {
3513 sub_stop_silence(pte, sub);
3514 send_tone(pte, 0, 0);
3515 ast_queue_unhold(sub->owner);
3517 sub->subtype = SUB_REAL;
3518 pte->state = STATE_CALL;
3520 send_text_status(pte, ustmtext(" Transf Hangup", pte));
3521 send_callerid_screen(pte, sub);
3523 send_led_update(pte, 0x08);
3524 send_led_update(pte, 0x10);
3525 show_main_page(pte);