2 * Asterisk -- An open source telephony toolkit.
4 * UNISTIM channel driver for asterisk
6 * Copyright (C) 2005 - 2007, Cedric Hans
8 * Cedric Hans <cedric.hans@mlkj.net>
10 * Asterisk 1.4 patch by Peter Be
12 * See http://www.asterisk.org for more information about
13 * the Asterisk project. Please do not directly contact
14 * any of the maintainers of this project for assistance;
15 * the project provides a web site, mailing lists and IRC
16 * channels for your use.
18 * This program is free software, distributed under the terms of
19 * the GNU General Public License Version 2. See the LICENSE file
20 * at the top of the source tree.
26 * \brief chan_unistim channel driver for Asterisk
27 * \author Cedric Hans <cedric.hans@mlkj.net>
29 * Unistim (Unified Networks IP Stimulus) channel driver
30 * for Nortel i2002, i2004 and i2050
32 * \ingroup channel_drivers
36 <support_level>extended</support_level>
41 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
46 #if defined(__CYGWIN__)
48 * cygwin headers are partly inconsistent. struct iovec is defined in sys/uio.h
49 * which is not included by default by sys/socket.h - in_pktinfo is defined in
50 * w32api/ws2tcpip.h but this probably has compatibility problems with sys/socket.h
51 * So for the time being we simply disable HAVE_PKTINFO when building under cygwin.
52 * This should be done in some common header, but for now this is the only file
53 * using iovec and in_pktinfo so it suffices to apply the fix here.
58 #endif /* __CYGWIN__ */
60 #include "asterisk/paths.h" /* ast_config_AST_LOG_DIR used in (too ?) many places */
61 #include "asterisk/network.h"
62 #include "asterisk/channel.h"
63 #include "asterisk/config.h"
64 #include "asterisk/module.h"
65 #include "asterisk/pbx.h"
66 #include "asterisk/event.h"
67 #include "asterisk/rtp_engine.h"
68 #include "asterisk/netsock.h"
69 #include "asterisk/acl.h"
70 #include "asterisk/callerid.h"
71 #include "asterisk/cli.h"
72 #include "asterisk/app.h"
73 #include "asterisk/musiconhold.h"
74 #include "asterisk/causes.h"
75 #include "asterisk/indications.h"
77 /*! Beware, G729 and G723 are not supported by asterisk, except with the proper licence */
79 #define DEFAULTCONTEXT "default"
80 #define DEFAULTCALLERID "Unknown"
81 #define DEFAULTCALLERNAME " "
82 #define DEFAULTHEIGHT 3
83 #define USTM_LOG_DIR "unistimHistory"
85 /*! Size of the transmit buffer */
86 #define MAX_BUF_SIZE 64
87 /*! Number of slots for the transmit queue */
88 #define MAX_BUF_NUMBER 50
89 /*! Try x times before removing the phone */
90 #define NB_MAX_RETRANSMIT 8
91 /*! Nb of milliseconds waited when no events are scheduled */
92 #define IDLE_WAIT 1000
93 /*! Wait x milliseconds before resending a packet */
94 #define RETRANSMIT_TIMER 2000
95 /*! How often the mailbox is checked for new messages */
96 #define TIMER_MWI 10000
98 #define DEFAULT_CODEC 0x00
99 #define SIZE_PAGE 4096
100 #define DEVICE_NAME_LEN 16
101 #define AST_CONFIG_MAX_PATH 255
102 #define MAX_ENTRY_LOG 30
105 #define SUB_THREEWAY 1
108 struct ast_format_cap *global_cap;
111 AUTOPROVISIONING_NO = 0,
112 AUTOPROVISIONING_YES,
118 /*! Do not create an extension into the default dialplan */
120 /*! Prompt user for an extension number and register it */
122 /*! Register an extension with the line=> value */
124 /*! Used with AUTOPROVISIONING_TN */
127 #define OUTPUT_HANDSET 0xC0
128 #define OUTPUT_HEADPHONE 0xC1
129 #define OUTPUT_SPEAKER 0xC2
131 #define VOLUME_LOW 0x01
132 #define VOLUME_LOW_SPEAKER 0x03
133 #define VOLUME_NORMAL 0x02
134 #define VOLUME_INSANELY_LOUD 0x07
136 #define MUTE_OFF 0x00
138 #define MUTE_ON_DISCRET 0xCE
140 #define SIZE_HEADER 6
141 #define SIZE_MAC_ADDR 17
142 #define TEXT_LENGTH_MAX 24
143 #define TEXT_LINE0 0x00
144 #define TEXT_LINE1 0x20
145 #define TEXT_LINE2 0x40
146 #define TEXT_NORMAL 0x05
147 #define TEXT_INVERSE 0x25
148 #define STATUS_LENGTH_MAX 28
150 #define FAV_ICON_NONE 0x00
151 #define FAV_ICON_ONHOOK_BLACK 0x20
152 #define FAV_ICON_ONHOOK_WHITE 0x21
153 #define FAV_ICON_SPEAKER_ONHOOK_BLACK 0x22
154 #define FAV_ICON_SPEAKER_ONHOOK_WHITE 0x23
155 #define FAV_ICON_OFFHOOK_BLACK 0x24
156 #define FAV_ICON_OFFHOOK_WHITE 0x25
157 #define FAV_ICON_ONHOLD_BLACK 0x26
158 #define FAV_ICON_ONHOLD_WHITE 0x27
159 #define FAV_ICON_SPEAKER_OFFHOOK_BLACK 0x28
160 #define FAV_ICON_SPEAKER_OFFHOOK_WHITE 0x29
161 #define FAV_ICON_PHONE_BLACK 0x2A
162 #define FAV_ICON_PHONE_WHITE 0x2B
163 #define FAV_ICON_SPEAKER_ONHOLD_BLACK 0x2C
164 #define FAV_ICON_SPEAKER_ONHOLD_WHITE 0x2D
165 #define FAV_ICON_HEADPHONES 0x2E
166 #define FAV_ICON_HEADPHONES_ONHOLD 0x2F
167 #define FAV_ICON_HOME 0x30
168 #define FAV_ICON_CITY 0x31
169 #define FAV_ICON_SHARP 0x32
170 #define FAV_ICON_PAGER 0x33
171 #define FAV_ICON_CALL_CENTER 0x34
172 #define FAV_ICON_FAX 0x35
173 #define FAV_ICON_MAILBOX 0x36
174 #define FAV_ICON_REFLECT 0x37
175 #define FAV_ICON_COMPUTER 0x38
176 #define FAV_ICON_FORWARD 0x39
177 #define FAV_ICON_LOCKED 0x3A
178 #define FAV_ICON_TRASH 0x3B
179 #define FAV_ICON_INBOX 0x3C
180 #define FAV_ICON_OUTBOX 0x3D
181 #define FAV_ICON_MEETING 0x3E
182 #define FAV_ICON_BOX 0x3F
184 #define FAV_BLINK_FAST 0x20
185 #define FAV_BLINK_SLOW 0x40
187 #define FAV_MAX_LENGTH 0x0A
189 static void dummy(char *unused, ...)
194 /*! \brief Global jitterbuffer configuration - by default, jb is disabled
195 * \note Values shown here match the defaults shown in unistim.conf.sample */
196 static struct ast_jb_conf default_jbconf =
200 .resync_threshold = 1000,
204 static struct ast_jb_conf global_jbconf;
207 /* #define DUMP_PACKET 1 */
208 /* #define DEBUG_TIMER ast_verbose */
210 #define DEBUG_TIMER dummy
211 /*! Enable verbose output. can also be set with the CLI */
212 static int unistimdebug = 0;
213 static int unistim_port;
214 static enum autoprovision autoprovisioning = AUTOPROVISIONING_NO;
215 static int unistim_keepalive;
216 static int unistimsock = -1;
220 unsigned int tos_audio;
222 unsigned int cos_audio;
223 } qos = { 0, 0, 0, 0 };
225 static struct io_context *io;
226 static struct ast_sched_context *sched;
227 static struct sockaddr_in public_ip = { 0, };
228 /*! give the IP address for the last packet received */
229 static struct sockaddr_in address_from;
230 /*! size of the sockaddr_in (in WSARecvFrom) */
231 static unsigned int size_addr_from = sizeof(address_from);
232 /*! Receive buffer address */
233 static unsigned char *buff;
234 static int unistim_reloading = 0;
235 AST_MUTEX_DEFINE_STATIC(unistim_reload_lock);
236 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
237 static int usecnt = 0;
238 /* extern char ast_config_AST_LOG_DIR[AST_CONFIG_MAX_PATH]; */
240 /*! This is the thread for the monitor which checks for input on the channels
241 * which are not currently in use. */
242 static pthread_t monitor_thread = AST_PTHREADT_NULL;
244 /*! Protect the monitoring thread, so only one process can kill or start it, and not
245 * when it's doing something critical. */
246 AST_MUTEX_DEFINE_STATIC(monlock);
247 /*! Protect the session list */
248 AST_MUTEX_DEFINE_STATIC(sessionlock);
249 /*! Protect the device list */
250 AST_MUTEX_DEFINE_STATIC(devicelock);
311 struct tone_zone_unistim {
317 static const struct tone_zone_unistim frequency[] = {
357 unsigned short w_year;
358 unsigned short w_month;
359 unsigned short w_day_of_week;
360 unsigned short w_day;
361 unsigned short w_hour;
362 unsigned short w_minute;
363 unsigned short w_second;
364 unsigned short w_milliseconds;
367 struct unistim_subchannel {
369 /*! SUBS_REAL or SUBS_THREEWAY */
370 unsigned int subtype;
371 /*! Asterisk channel used by the subchannel */
372 struct ast_channel *owner;
374 struct unistim_line *parent;
376 struct ast_rtp_instance *rtp;
383 * \todo Convert to stringfields
385 struct unistim_line {
389 /*! Like USTM/200\@black */
391 /*! pointer to our current connection, channel... */
392 struct unistim_subchannel *subs[MAX_SUBS];
393 /*! Extension where to start */
394 char exten[AST_MAX_EXTENSION];
395 /*! Context to start in */
396 char context[AST_MAX_EXTENSION];
397 /*! Language for asterisk sounds */
398 char language[MAX_LANGUAGE];
399 /*! CallerID Number */
400 char cid_num[AST_MAX_EXTENSION];
401 /*! Mailbox for MWI */
402 char mailbox[AST_MAX_EXTENSION];
407 /*! MusicOnHold class */
408 char musicclass[MAX_MUSICCLASS];
410 unsigned int callgroup;
412 unsigned int pickupgroup;
413 /*! Account code (for billing) */
414 char accountcode[80];
415 /*! AMA flags (for billing) */
417 /*! Codec supported */
418 struct ast_format_cap *cap;
420 char parkinglot[AST_MAX_CONTEXT];
421 struct unistim_line *next;
422 struct unistim_device *parent;
426 * \brief A device containing one or more lines
428 static struct unistim_device {
429 int receiver_state; /*!< state of the receiver (see ReceiverState) */
430 int size_phone_number; /*!< size of the phone number */
431 char phone_number[16]; /*!< the phone number entered by the user */
432 char redial_number[16]; /*!< the last phone number entered by the user */
433 int phone_current; /*!< Number of the current phone */
434 int pos_fav; /*!< Position of the displayed favorites (used for scrolling) */
435 char id[18]; /*!< mac address of the current phone in ascii */
436 char name[DEVICE_NAME_LEN]; /*!< name of the device */
437 int softkeylinepos; /*!< position of the line softkey (default 0) */
438 char softkeylabel[6][11]; /*!< soft key label */
439 char softkeynumber[6][16]; /*!< number dialed when the soft key is pressed */
440 char softkeyicon[6]; /*!< icon number */
441 char softkeydevice[6][16]; /*!< name of the device monitored */
442 struct unistim_device *sp[6]; /*!< pointer to the device monitored by this soft key */
443 int height; /*!< The number of lines the phone can display */
444 char maintext0[25]; /*!< when the phone is idle, display this string on line 0 */
445 char maintext1[25]; /*!< when the phone is idle, display this string on line 1 */
446 char maintext2[25]; /*!< when the phone is idle, display this string on line 2 */
447 char titledefault[13]; /*!< title (text before date/time) */
448 char datetimeformat; /*!< format used for displaying time/date */
449 char contrast; /*!< contrast */
450 char country[3]; /*!< country used for dial tone frequency */
451 struct ast_tone_zone *tz; /*!< Tone zone for res_indications (ring, busy, congestion) */
452 char ringvolume; /*!< Ring volume */
453 char ringstyle; /*!< Ring melody */
454 int rtp_port; /*!< RTP port used by the phone */
455 int rtp_method; /*!< Select the unistim data used to establish a RTP session */
456 int status_method; /*!< Select the unistim packet used for sending status text */
457 char codec_number; /*!< The current codec used to make calls */
458 int missed_call; /*!< Number of call unanswered */
459 int callhistory; /*!< Allowed to record call history */
460 char lst_cid[TEXT_LENGTH_MAX]; /*!< Last callerID received */
461 char lst_cnm[TEXT_LENGTH_MAX]; /*!< Last callername recevied */
462 char call_forward[AST_MAX_EXTENSION]; /*!< Forward number */
463 int output; /*!< Handset, headphone or speaker */
464 int previous_output; /*!< Previous output */
465 int volume; /*!< Default volume */
466 int mute; /*!< Mute mode */
467 int moh; /*!< Music on hold in progress */
468 int nat; /*!< Used by the obscure ast_rtp_setnat */
469 enum autoprov_extn extension; /*!< See ifdef EXTENSION for valid values */
470 char extension_number[11]; /*!< Extension number entered by the user */
471 char to_delete; /*!< Used in reload */
472 time_t start_call_timestamp; /*!< timestamp for the length calculation of the call */
473 struct ast_silence_generator *silence_generator;
474 struct unistim_line *lines;
476 struct unistimsession *session;
477 struct unistim_device *next;
480 static struct unistimsession {
482 struct sockaddr_in sin; /*!< IP address of the phone */
483 struct sockaddr_in sout; /*!< IP address of server */
484 int timeout; /*!< time-out in ticks : resend packet if no ack was received before the timeout occured */
485 unsigned short seq_phone; /*!< sequence number for the next packet (when we receive a request) */
486 unsigned short seq_server; /*!< sequence number for the next packet (when we send a request) */
487 unsigned short last_seq_ack; /*!< sequence number of the last ACK received */
488 unsigned long tick_next_ping; /*!< time for the next ping */
489 int last_buf_available; /*!< number of a free slot */
490 int nb_retransmit; /*!< number of retransmition */
491 int state; /*!< state of the phone (see phone_state) */
492 int size_buff_entry; /*!< size of the buffer used to enter datas */
493 char buff_entry[16]; /*!< Buffer for temporary datas */
494 char macaddr[18]; /*!< mac adress of the phone (not always available) */
495 struct wsabuf wsabufsend[MAX_BUF_NUMBER]; /*!< Size of each paquet stored in the buffer array & pointer to this buffer */
496 unsigned char buf[MAX_BUF_NUMBER][MAX_BUF_SIZE]; /*!< Buffer array used to keep the lastest non-acked paquets */
497 struct unistim_device *device;
498 struct unistimsession *next;
502 * \page Unistim datagram formats
504 * Format of datagrams :
505 * bytes 0 & 1 : ffff for discovery packet, 0000 for everything else
506 * byte 2 : sequence number (high part)
507 * byte 3 : sequence number (low part)
508 * byte 4 : 2 = ask question or send info, 1 = answer or ACK, 0 = retransmit request
509 * byte 5 : direction, 1 = server to phone, 2 = phone to server arguments
512 static const unsigned char packet_rcv_discovery[] =
513 { 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
514 static const unsigned char packet_send_discovery_ack[] =
515 { 0x00, 0x00, /*Initial Seq (2 bytes) */ 0x00, 0x00, 0x00, 0x01 };
517 static const unsigned char packet_recv_firm_version[] =
518 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x0a, 0x02 };
519 static const unsigned char packet_recv_pressed_key[] =
520 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x04, 0x00 };
521 static const unsigned char packet_recv_pick_up[] =
522 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x04 };
523 static const unsigned char packet_recv_hangup[] =
524 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x03 };
525 static const unsigned char packet_recv_r2[] = { 0x00, 0x00, 0x00, 0x13, 0x96, 0x03, 0x03 };
527 /*! TransportAdapter */
528 static const unsigned char packet_recv_resume_connection_with_server[] =
529 { 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
530 static const unsigned char packet_recv_mac_addr[] =
531 { 0xff, 0xff, 0xff, 0xff, 0x9a, 0x0d, 0x07 /*MacAddr */ };
533 static const unsigned char packet_send_date_time3[] =
534 { 0x11, 0x09, 0x02, 0x02, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07,
535 /*Minutes */ 0x08, 0x32
537 static const unsigned char packet_send_date_time[] =
538 { 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07, /*Minutes */
539 0x08, 0x32, 0x17, 0x04, 0x24, 0x07, 0x19,
540 0x04, 0x07, 0x00, 0x19, 0x05, 0x09, 0x3e, 0x0f, 0x16, 0x05, 0x00, 0x80, 0x00, 0x1e,
541 0x05, 0x12, 0x00, 0x78
544 static const unsigned char packet_send_no_ring[] =
545 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00 };
546 static const unsigned char packet_send_s4[] =
547 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff,
548 0x16, 0x05, 0x1c, 0x00, 0x00, 0x17, 0x05,
549 0x0b, 0x00, 0x00, 0x19, 0x04, 0x00, 0x00, 0x19, 0x04, 0x00, 0x08, 0x19, 0x04, 0x00,
550 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
551 0x31, 0x00, 0x00, 0x16, 0x05, 0x04, 0x00, 0x00
553 static const unsigned char packet_send_call[] =
554 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf,
555 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16, 0x0a, 0x38, 0x00, 0x12, 0xca, 0x03,
556 0xc0, 0xc3, 0xc5, 0x16, 0x16, 0x30, 0x00,
557 0x00, /*codec */ 0x12, 0x12, /* frames per packet */ 0x01, 0x5c, 0x00, /*port RTP */
558 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41,
559 /*port RTP */ 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41, /* IP Address */ 0x0a, 0x01,
562 static const unsigned char packet_send_stream_based_tone_off[] =
563 { 0x16, 0x05, 0x1c, 0x00, 0x00 };
565 /* static const unsigned char packet_send_Mute[] = { 0x16, 0x05, 0x04, 0x00, 0x00 };
566 static const unsigned char packet_send_CloseAudioStreamRX[] = { 0x16, 0x05, 0x31, 0x00, 0xff };
567 static const unsigned char packet_send_CloseAudioStreamTX[] = { 0x16, 0x05, 0x31, 0xff, 0x00 };*/
568 static const unsigned char packet_send_stream_based_tone_on[] =
569 { 0x16, 0x06, 0x1b, 0x00, 0x00, 0x05 };
570 static const unsigned char packet_send_stream_based_tone_single_freq[] =
571 { 0x16, 0x06, 0x1d, 0x00, 0x01, 0xb8 };
572 static const unsigned char packet_send_stream_based_tone_dial_freq[] =
573 { 0x16, 0x08, 0x1d, 0x00, 0x01, 0xb8, 0x01, 0x5e };
574 static const unsigned char packet_send_select_output[] =
575 { 0x16, 0x06, 0x32, 0xc0, 0x01, 0x00 };
576 static const unsigned char packet_send_ring[] =
577 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16,
578 0x04, 0x1a, 0x01, 0x16, 0x05, 0x12, 0x13 /* Ring type 10 to 17 */ , 0x18, 0x16, 0x04, 0x18, /* volume 00, 10, 20... */
579 0x20, 0x16, 0x04, 0x10, 0x00
581 static const unsigned char packet_send_end_call[] =
582 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x31, 0x00, 0x00, 0x19, 0x04, 0x00,
583 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
584 0x04, 0x00, 0x00, 0x16, 0x04, 0x37, 0x10
586 static const unsigned char packet_send_s9[] =
587 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x19, 0x04, 0x00, 0x10, 0x16, 0x05, 0x1c, 0x00,
589 static const unsigned char packet_send_rtp_packet_size[] =
590 { 0x16, 0x08, 0x38, 0x00, 0x00, 0xe0, 0x00, 0xa0 };
591 static const unsigned char packet_send_jitter_buffer_conf[] =
592 { 0x16, 0x0e, 0x3a, 0x00, /* jitter */ 0x02, /* high water mark */ 0x04, 0x00, 0x00,
593 /* early packet resync 2 bytes */ 0x3e, 0x80,
594 0x00, 0x00, /* late packet resync 2 bytes */ 0x3e, 0x80
597 /* Duration in ms div 2 (0x20 = 64ms, 0x08 = 16ms)
598 static unsigned char packet_send_StreamBasedToneCad[] =
599 { 0x16, 0x0a, 0x1e, 0x00, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x2b }; */
600 static const unsigned char packet_send_open_audio_stream_rx[] =
601 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
602 0x0e, 0x01, /* Port */ 0x14, 0x50, 0x00,
603 0x00, /* Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
605 static const unsigned char packet_send_open_audio_stream_tx[] =
606 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
607 0x0e, 0x01, /* Local port */ 0x14, 0x50,
608 0x00, 0x00, /* Rmt Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
611 static const unsigned char packet_send_open_audio_stream_rx3[] =
612 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
613 0x06, 0x81, /* RTP Port */ 0x14, 0x50,
614 /* RTCP Port */ 0x14,
615 0x51, /* RTP Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00, /* Dest IP */ 0x0a, 0x93,
618 static const unsigned char packet_send_open_audio_stream_tx3[] =
619 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
620 0x06, 0x81, /* RTP Local port */ 0x14, 0x50,
621 /* RTCP Port */ 0x00, 0x00, /* RTP Rmt Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00,
622 /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
625 static const unsigned char packet_send_arrow[] = { 0x17, 0x04, 0x04, 0x00 };
626 static const unsigned char packet_send_blink_cursor[] = { 0x17, 0x04, 0x10, 0x86 };
627 static const unsigned char packet_send_date_time2[] = { 0x17, 0x04, 0x17, 0x3d, 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */
628 0x06, /*Hour */ 0x07, /*Minutes */ 0x08, 0x32
630 static const unsigned char packet_send_Contrast[] =
631 { 0x17, 0x04, 0x24, /*Contrast */ 0x08 };
632 static const unsigned char packet_send_StartTimer[] =
633 { 0x17, 0x05, 0x0b, 0x05, 0x00, 0x17, 0x08, 0x16, /* Text */ 0x44, 0x75, 0x72, 0xe9,
635 static const unsigned char packet_send_stop_timer[] = { 0x17, 0x05, 0x0b, 0x02, 0x00 };
636 static const unsigned char packet_send_icon[] = { 0x17, 0x05, 0x14, /*pos */ 0x00, /*icon */ 0x25 }; /* display an icon in front of the text zone */
637 static const unsigned char packet_send_S7[] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 };
638 static const unsigned char packet_send_set_pos_cursor[] =
639 { 0x17, 0x06, 0x10, 0x81, 0x04, /*pos */ 0x20 };
641 /*static unsigned char packet_send_MonthLabelsDownload[] =
642 { 0x17, 0x0a, 0x15, Month (3 char) 0x46, 0x65, 0x62, 0x4d, 0xe4, 0x72, 0x20 }; */
643 static const unsigned char packet_send_favorite[] =
644 { 0x17, 0x0f, 0x19, 0x10, /*pos */ 0x01, /*name */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
645 0x20, 0x20, 0x20, 0x20, /*end_name */ 0x19,
646 0x05, 0x0f, /*pos */ 0x01, /*icone */ 0x00
648 static const unsigned char packet_send_title[] =
649 { 0x17, 0x10, 0x19, 0x02, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
650 0x20, 0x20, 0x20, 0x20 /*end_text */ };
651 static const unsigned char packet_send_text[] =
652 { 0x17, 0x1e, 0x1b, 0x04, /*pos */ 0x00, /*inverse */ 0x25, /*text */ 0x20, 0x20,
653 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
654 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
655 /*end_text */ 0x17, 0x04, 0x10, 0x87
657 static const unsigned char packet_send_status[] =
658 { 0x17, 0x20, 0x19, 0x08, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
659 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
660 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 /*end_text */
662 static const unsigned char packet_send_status2[] =
663 { 0x17, 0x0b, 0x19, /* pos [08|28|48|68] */ 0x00, /* text */ 0x20, 0x20, 0x20, 0x20,
664 0x20, 0x20, 0x20 /* end_text */ };
666 static const unsigned char packet_send_led_update[] = { 0x19, 0x04, 0x00, 0x00 };
668 static const unsigned char packet_send_query_basic_manager_04[] = { 0x1a, 0x04, 0x01, 0x04 };
669 static const unsigned char packet_send_query_mac_address[] = { 0x1a, 0x04, 0x01, 0x08 };
670 static const unsigned char packet_send_query_basic_manager_10[] = { 0x1a, 0x04, 0x01, 0x10 };
671 static const unsigned char packet_send_S1[] = { 0x1a, 0x07, 0x07, 0x00, 0x00, 0x00, 0x13 };
673 static unsigned char packet_send_ping[] =
674 { 0x1e, 0x05, 0x12, 0x00, /*Watchdog timer */ 0x78 };
676 #define BUFFSEND unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }
678 static const char tdesc[] = "UNISTIM Channel Driver";
679 static const char channel_type[] = "USTM";
682 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state, const char *linkedid);
683 static int load_module(void);
684 static int reload(void);
685 static int unload_module(void);
686 static int reload_config(void);
687 static void show_main_page(struct unistimsession *pte);
688 static struct ast_channel *unistim_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor,
689 void *data, int *cause);
690 static int unistim_call(struct ast_channel *ast, char *dest, int timeout);
691 static int unistim_hangup(struct ast_channel *ast);
692 static int unistim_answer(struct ast_channel *ast);
693 static struct ast_frame *unistim_read(struct ast_channel *ast);
694 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame);
695 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
697 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
698 static int unistim_senddigit_begin(struct ast_channel *ast, char digit);
699 static int unistim_senddigit_end(struct ast_channel *ast, char digit,
700 unsigned int duration);
701 static int unistim_sendtext(struct ast_channel *ast, const char *text);
703 static int write_entry_history(struct unistimsession *pte, FILE * f, char c,
705 static void change_callerid(struct unistimsession *pte, int type, char *callerid);
707 static struct ast_channel_tech unistim_tech = {
708 .type = channel_type,
709 .description = tdesc,
710 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
711 .requester = unistim_request,
712 .call = unistim_call,
713 .hangup = unistim_hangup,
714 .answer = unistim_answer,
715 .read = unistim_read,
716 .write = unistim_write,
717 .indicate = unistim_indicate,
718 .fixup = unistim_fixup,
719 .send_digit_begin = unistim_senddigit_begin,
720 .send_digit_end = unistim_senddigit_end,
721 .send_text = unistim_sendtext,
722 .bridge = ast_rtp_instance_bridge,
725 static void display_last_error(const char *sz_msg)
731 /* Display the error message */
732 ast_log(LOG_WARNING, "%s %s : (%u) %s\n", ctime(&cur_time), sz_msg, errno,
736 static unsigned int get_tick_count(void)
738 struct timeval now = ast_tvnow();
740 return (now.tv_sec * 1000) + (now.tv_usec / 1000);
743 /* Send data to a phone without retransmit nor buffering */
744 static void send_raw_client(int size, const unsigned char *data, struct sockaddr_in *addr_to,
745 const struct sockaddr_in *addr_ourip)
748 struct iovec msg_iov;
750 char buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
751 struct cmsghdr *ip_msg = (struct cmsghdr *) buffer;
752 struct in_pktinfo *pki = (struct in_pktinfo *) CMSG_DATA(ip_msg);
754 /* cast this to a non-const pointer, since the sendmsg() API
755 * does not provide read-only and write-only flavors of the
756 * structures used for its arguments, but in this case we know
757 * the data will not be modified
759 msg_iov.iov_base = (char *) data;
760 msg_iov.iov_len = size;
762 msg.msg_name = addr_to; /* optional address */
763 msg.msg_namelen = sizeof(struct sockaddr_in); /* size of address */
764 msg.msg_iov = &msg_iov; /* scatter/gather array */
765 msg.msg_iovlen = 1; /* # elements in msg_iov */
766 msg.msg_control = ip_msg; /* ancillary data */
767 msg.msg_controllen = sizeof(buffer); /* ancillary data buffer len */
768 msg.msg_flags = 0; /* flags on received message */
770 ip_msg->cmsg_len = CMSG_LEN(sizeof(*pki));
771 ip_msg->cmsg_level = IPPROTO_IP;
772 ip_msg->cmsg_type = IP_PKTINFO;
773 pki->ipi_ifindex = 0; /* Interface index, 0 = use interface specified in routing table */
774 pki->ipi_spec_dst.s_addr = addr_ourip->sin_addr.s_addr; /* Local address */
775 /* pki->ipi_addr = ; Header Destination address - ignored by kernel */
780 char iabuf[INET_ADDRSTRLEN];
781 char iabuf2[INET_ADDRSTRLEN];
782 ast_verb(0, "\n**> From %s sending %d bytes to %s ***\n",
783 ast_inet_ntoa(addr_ourip->sin_addr), (int) size,
784 ast_inet_ntoa(addr_to->sin_addr));
785 for (tmp = 0; tmp < size; tmp++)
786 ast_verb(0, "%.2x ", (unsigned char) data[tmp]);
787 ast_verb(0, "\n******************************************\n");
792 if (sendmsg(unistimsock, &msg, 0) == -1)
793 display_last_error("Error sending datas");
795 if (sendto(unistimsock, data, size, 0, (struct sockaddr *) addr_to, sizeof(*addr_to))
797 display_last_error("Error sending datas");
801 static void send_client(int size, const unsigned char *data, struct unistimsession *pte)
805 unsigned short seq = ntohs(++pte->seq_server);
807 ast_mutex_lock(&pte->lock);
808 buf_pos = pte->last_buf_available;
810 if (buf_pos >= MAX_BUF_NUMBER) {
811 ast_log(LOG_WARNING, "Error : send queue overflow\n");
812 ast_mutex_unlock(&pte->lock);
815 memcpy((void *)data + sizeof(unsigned short), (void *)&seq, sizeof(unsigned short));
816 pte->wsabufsend[buf_pos].len = size;
817 memcpy(pte->wsabufsend[buf_pos].buf, data, size);
819 tick = get_tick_count();
820 pte->timeout = tick + RETRANSMIT_TIMER;
822 /*#ifdef DUMP_PACKET */
824 ast_verb(6, "Sending datas with seq #0x%.4x Using slot #%d :\n", pte->seq_server, buf_pos);
826 send_raw_client(pte->wsabufsend[buf_pos].len, pte->wsabufsend[buf_pos].buf, &(pte->sin),
828 pte->last_buf_available++;
829 ast_mutex_unlock(&pte->lock);
832 static void send_ping(struct unistimsession *pte)
836 ast_verb(6, "Sending ping\n");
837 pte->tick_next_ping = get_tick_count() + unistim_keepalive;
838 memcpy(buffsend + SIZE_HEADER, packet_send_ping, sizeof(packet_send_ping));
839 send_client(SIZE_HEADER + sizeof(packet_send_ping), buffsend, pte);
842 static int get_to_address(int fd, struct sockaddr_in *toAddr)
850 struct in_addr address;
853 /* Zero out the structures before we use them */
854 /* This sets several key values to NULL */
855 memset(&msg, 0, sizeof(msg));
856 memset(&ip_msg, 0, sizeof(ip_msg));
858 /* Initialize the message structure */
859 msg.msg_control = &ip_msg;
860 msg.msg_controllen = sizeof(ip_msg);
861 /* Get info about the incoming packet */
862 err = recvmsg(fd, &msg, MSG_PEEK);
864 ast_log(LOG_WARNING, "recvmsg returned an error: %s\n", strerror(errno));
865 memcpy(&toAddr->sin_addr, &ip_msg.address, sizeof(struct in_addr));
868 memcpy(&toAddr, &public_ip, sizeof(&toAddr));
873 /* Allocate memory & initialize structures for a new phone */
874 /* addr_from : ip address of the phone */
875 static struct unistimsession *create_client(const struct sockaddr_in *addr_from)
878 struct unistimsession *s;
880 if (!(s = ast_calloc(1, sizeof(*s))))
883 memcpy(&s->sin, addr_from, sizeof(struct sockaddr_in));
884 get_to_address(unistimsock, &s->sout);
885 sout.sin_family = AF_INET;
887 ast_verb(0, "Creating a new entry for the phone from %s received via server ip %s\n",
888 ast_inet_ntoa(addr_from->sin_addr), ast_inet_ntoa(s->sout.sin_addr));
890 ast_mutex_init(&s->lock);
891 ast_mutex_lock(&sessionlock);
895 s->timeout = get_tick_count() + RETRANSMIT_TIMER;
896 s->seq_phone = (short) 0x0000;
897 s->seq_server = (short) 0x0000;
898 s->last_seq_ack = (short) 0x000;
899 s->last_buf_available = 0;
900 s->nb_retransmit = 0;
901 s->state = STATE_INIT;
902 s->tick_next_ping = get_tick_count() + unistim_keepalive;
903 /* Initialize struct wsabuf */
904 for (tmp = 0; tmp < MAX_BUF_NUMBER; tmp++) {
905 s->wsabufsend[tmp].buf = s->buf[tmp];
907 ast_mutex_unlock(&sessionlock);
911 static void send_end_call(struct unistimsession *pte)
915 ast_verb(0, "Sending end call\n");
916 memcpy(buffsend + SIZE_HEADER, packet_send_end_call, sizeof(packet_send_end_call));
917 send_client(SIZE_HEADER + sizeof(packet_send_end_call), buffsend, pte);
920 static void set_ping_timer(struct unistimsession *pte)
922 unsigned int tick = 0; /* XXX what is this for, anyways */
924 pte->timeout = pte->tick_next_ping;
925 DEBUG_TIMER("tick = %u next ping at %u tick\n", tick, pte->timeout);
929 /* Checking if our send queue is empty,
930 * if true, setting up a timer for keepalive */
931 static void check_send_queue(struct unistimsession *pte)
933 /* Check if our send queue contained only one element */
934 if (pte->last_buf_available == 1) {
936 ast_verb(6, "Our single packet was ACKed.\n");
937 pte->last_buf_available--;
941 /* Check if this ACK catch up our latest packet */
942 else if (pte->last_seq_ack + 1 == pte->seq_server + 1) {
944 ast_verb(6, "Our send queue is completely ACKed.\n");
945 pte->last_buf_available = 0; /* Purge the send queue */
950 ast_verb(6, "We still have packets in our send queue\n");
954 static void send_start_timer(struct unistimsession *pte)
958 ast_verb(0, "Sending start timer\n");
959 memcpy(buffsend + SIZE_HEADER, packet_send_StartTimer, sizeof(packet_send_StartTimer));
960 send_client(SIZE_HEADER + sizeof(packet_send_StartTimer), buffsend, pte);
963 static void send_stop_timer(struct unistimsession *pte)
967 ast_verb(0, "Sending stop timer\n");
968 memcpy(buffsend + SIZE_HEADER, packet_send_stop_timer, sizeof(packet_send_stop_timer));
969 send_client(SIZE_HEADER + sizeof(packet_send_stop_timer), buffsend, pte);
972 static void Sendicon(unsigned char pos, unsigned char status, struct unistimsession *pte)
976 ast_verb(0, "Sending icon pos %d with status 0x%.2x\n", pos, status);
977 memcpy(buffsend + SIZE_HEADER, packet_send_icon, sizeof(packet_send_icon));
979 buffsend[10] = status;
980 send_client(SIZE_HEADER + sizeof(packet_send_icon), buffsend, pte);
983 static void send_tone(struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
988 ast_verb(0, "Sending Stream Based Tone Off\n");
989 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_off,
990 sizeof(packet_send_stream_based_tone_off));
991 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_off), buffsend, pte);
994 /* Since most of the world use a continuous tone, it's useless
996 ast_verb(0, "Sending Stream Based Tone Cadence Download\n");
997 memcpy (buffsend + SIZE_HEADER, packet_send_StreamBasedToneCad, sizeof (packet_send_StreamBasedToneCad));
998 send_client (SIZE_HEADER + sizeof (packet_send_StreamBasedToneCad), buffsend, pte); */
1000 ast_verb(0, "Sending Stream Based Tone Frequency Component List Download %d %d\n", tone1, tone2);
1003 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_single_freq,
1004 sizeof(packet_send_stream_based_tone_single_freq));
1005 buffsend[10] = (tone1 & 0xff00) >> 8;
1006 buffsend[11] = (tone1 & 0x00ff);
1007 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_single_freq), buffsend,
1011 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dial_freq,
1012 sizeof(packet_send_stream_based_tone_dial_freq));
1013 buffsend[10] = (tone1 & 0xff00) >> 8;
1014 buffsend[11] = (tone1 & 0x00ff);
1015 buffsend[12] = (tone2 & 0xff00) >> 8;
1016 buffsend[13] = (tone2 & 0x00ff);
1017 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_dial_freq), buffsend,
1022 ast_verb(0, "Sending Stream Based Tone On\n");
1023 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_on,
1024 sizeof(packet_send_stream_based_tone_on));
1025 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_on), buffsend, pte);
1028 /* Positions for favorites
1029 |--------------------|
1035 /* status (icons) : 00 = nothing, 2x/3x = see parser.h, 4x/5x = blink fast, 6x/7x = blink slow */
1037 send_favorite(unsigned char pos, unsigned char status, struct unistimsession *pte,
1044 ast_verb(0, "Sending favorite pos %d with status 0x%.2x\n", pos, status);
1045 memcpy(buffsend + SIZE_HEADER, packet_send_favorite, sizeof(packet_send_favorite));
1048 buffsend[25] = status;
1050 if (i > FAV_MAX_LENGTH)
1052 memcpy(buffsend + FAV_MAX_LENGTH + 1, text, i);
1053 send_client(SIZE_HEADER + sizeof(packet_send_favorite), buffsend, pte);
1056 static void refresh_all_favorite(struct unistimsession *pte)
1061 ast_verb(0, "Refreshing all favorite\n");
1062 for (i = 0; i < 6; i++) {
1063 if ((pte->device->softkeyicon[i] <= FAV_ICON_HEADPHONES_ONHOLD) &&
1064 (pte->device->softkeylinepos != i))
1065 send_favorite((unsigned char) i, pte->device->softkeyicon[i] + 1, pte,
1066 pte->device->softkeylabel[i]);
1068 send_favorite((unsigned char) i, pte->device->softkeyicon[i], pte,
1069 pte->device->softkeylabel[i]);
1074 /* Change the status for this phone (pte) and update for each phones where pte is bookmarked
1075 * use FAV_ICON_*_BLACK constant in status parameters */
1076 static void change_favorite_icon(struct unistimsession *pte, unsigned char status)
1078 struct unistim_device *d = devices;
1080 /* Update the current phone */
1081 if (pte->state != STATE_CLEANING)
1082 send_favorite(pte->device->softkeylinepos, status, pte,
1083 pte->device->softkeylabel[pte->device->softkeylinepos]);
1084 /* Notify other phones if we're in their bookmark */
1086 for (i = 0; i < 6; i++) {
1087 if (d->sp[i] == pte->device) { /* It's us ? */
1088 if (d->softkeyicon[i] != status) { /* Avoid resending the same icon */
1089 d->softkeyicon[i] = status;
1091 send_favorite(i, status + 1, d->session, d->softkeylabel[i]);
1099 static int RegisterExtension(const struct unistimsession *pte)
1102 ast_verb(0, "Trying to register extension '%s' into context '%s' to %s\n",
1103 pte->device->extension_number, pte->device->lines->context,
1104 pte->device->lines->fullname);
1105 return ast_add_extension(pte->device->lines->context, 0,
1106 pte->device->extension_number, 1, NULL, NULL, "Dial",
1107 pte->device->lines->fullname, 0, "Unistim");
1110 static int UnregisterExtension(const struct unistimsession *pte)
1113 ast_verb(0, "Trying to unregister extension '%s' context '%s'\n",
1114 pte->device->extension_number, pte->device->lines->context);
1115 return ast_context_remove_extension(pte->device->lines->context,
1116 pte->device->extension_number, 1, "Unistim");
1119 /* Free memory allocated for a phone */
1120 static void close_client(struct unistimsession *s)
1122 struct unistim_subchannel *sub;
1123 struct unistimsession *cur, *prev = NULL;
1124 ast_mutex_lock(&sessionlock);
1126 /* Looking for the session in the linked chain */
1133 if (cur) { /* Session found ? */
1134 if (cur->device) { /* This session was registered ? */
1135 s->state = STATE_CLEANING;
1137 ast_verb(0, "close_client session %p device %p lines %p sub %p\n",
1138 s, s->device, s->device->lines,
1139 s->device->lines->subs[SUB_REAL]);
1140 change_favorite_icon(s, FAV_ICON_NONE);
1141 sub = s->device->lines->subs[SUB_REAL];
1143 if (sub->owner) { /* Call in progress ? */
1145 ast_verb(0, "Aborting call\n");
1146 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NETWORK_OUT_OF_ORDER);
1149 ast_log(LOG_WARNING, "Freeing a client with no subchannel !\n");
1150 if (!ast_strlen_zero(s->device->extension_number))
1151 UnregisterExtension(s);
1152 cur->device->session = NULL;
1155 ast_verb(0, "Freeing an unregistered client\n");
1158 prev->next = cur->next;
1160 sessions = cur->next;
1161 ast_mutex_destroy(&s->lock);
1164 ast_log(LOG_WARNING, "Trying to delete non-existent session %p?\n", s);
1165 ast_mutex_unlock(&sessionlock);
1169 /* Return 1 if the session chained link was modified */
1170 static int send_retransmit(struct unistimsession *pte)
1174 ast_mutex_lock(&pte->lock);
1175 if (++pte->nb_retransmit >= NB_MAX_RETRANSMIT) {
1177 ast_verb(0, "Too many retransmit - freeing client\n");
1178 ast_mutex_unlock(&pte->lock);
1182 pte->timeout = get_tick_count() + RETRANSMIT_TIMER;
1184 for (i = pte->last_buf_available - (pte->seq_server - pte->last_seq_ack);
1185 i < pte->last_buf_available; i++) {
1187 ast_log(LOG_WARNING,
1188 "Asked to retransmit an ACKed slot ! last_buf_available=%d, seq_server = #0x%.4x last_seq_ack = #0x%.4x\n",
1189 pte->last_buf_available, pte->seq_server, pte->last_seq_ack);
1194 unsigned short *sbuf = (unsigned short *) pte->wsabufsend[i].buf;
1197 seq = ntohs(sbuf[1]);
1198 ast_verb(0, "Retransmit slot #%d (seq=#0x%.4x), last ack was #0x%.4x\n", i,
1199 seq, pte->last_seq_ack);
1201 send_raw_client(pte->wsabufsend[i].len, pte->wsabufsend[i].buf, &pte->sin,
1204 ast_mutex_unlock(&pte->lock);
1208 /* inverse : TEXT_INVERSE : yes, TEXT_NORMAL : no */
1210 send_text(unsigned char pos, unsigned char inverse, struct unistimsession *pte,
1216 ast_verb(0, "Sending text at pos %d, inverse flag %d\n", pos, inverse);
1217 memcpy(buffsend + SIZE_HEADER, packet_send_text, sizeof(packet_send_text));
1219 buffsend[11] = inverse;
1221 if (i > TEXT_LENGTH_MAX)
1222 i = TEXT_LENGTH_MAX;
1223 memcpy(buffsend + 12, text, i);
1224 send_client(SIZE_HEADER + sizeof(packet_send_text), buffsend, pte);
1227 static void send_text_status(struct unistimsession *pte, const char *text)
1232 ast_verb(0, "Sending status text\n");
1234 if (pte->device->status_method == 1) { /* For new firmware and i2050 soft phone */
1235 int n = strlen(text);
1236 /* Must send individual button separately */
1238 for (i = 0, j = 0; i < 4; i++, j += 7) {
1239 int pos = 0x08 + (i * 0x20);
1240 memcpy(buffsend + SIZE_HEADER, packet_send_status2,
1241 sizeof(packet_send_status2));
1244 memcpy(buffsend + 10, (j < n) ? (text + j) : " ", 7);
1245 send_client(SIZE_HEADER + sizeof(packet_send_status2), buffsend, pte);
1252 memcpy(buffsend + SIZE_HEADER, packet_send_status, sizeof(packet_send_status));
1254 if (i > STATUS_LENGTH_MAX)
1255 i = STATUS_LENGTH_MAX;
1256 memcpy(buffsend + 10, text, i);
1257 send_client(SIZE_HEADER + sizeof(packet_send_status), buffsend, pte);
1261 /* led values in hexa : 0 = bar off, 1 = bar on, 2 = bar 1s on/1s off, 3 = bar 2.5s on/0.5s off
1262 * 4 = bar 0.6s on/0.3s off, 5 = bar 0.5s on/0.5s off, 6 = bar 2s on/0.5s off
1263 * 7 = bar off, 8 = speaker off, 9 = speaker on, 10 = headphone off, 11 = headphone on
1264 * 18 = mute off, 19 mute on */
1265 static void send_led_update(struct unistimsession *pte, unsigned char led)
1269 ast_verb(0, "Sending led_update (%x)\n", led);
1270 memcpy(buffsend + SIZE_HEADER, packet_send_led_update, sizeof(packet_send_led_update));
1272 send_client(SIZE_HEADER + sizeof(packet_send_led_update), buffsend, pte);
1275 /* output = OUTPUT_HANDSET, OUTPUT_HEADPHONE or OUTPUT_SPEAKER
1276 * volume = VOLUME_LOW, VOLUME_NORMAL, VOLUME_INSANELY_LOUD
1277 * mute = MUTE_OFF, MUTE_ON */
1279 send_select_output(struct unistimsession *pte, unsigned char output, unsigned char volume,
1284 ast_verb(0, "Sending select output packet output=%x volume=%x mute=%x\n", output,
1286 memcpy(buffsend + SIZE_HEADER, packet_send_select_output,
1287 sizeof(packet_send_select_output));
1288 buffsend[9] = output;
1289 if (output == OUTPUT_SPEAKER)
1290 volume = VOLUME_LOW_SPEAKER;
1292 volume = VOLUME_LOW;
1293 buffsend[10] = volume;
1294 if (mute == MUTE_ON_DISCRET)
1295 buffsend[11] = MUTE_ON;
1297 buffsend[11] = mute;
1298 send_client(SIZE_HEADER + sizeof(packet_send_select_output), buffsend, pte);
1299 if (mute == MUTE_OFF)
1300 send_led_update(pte, 0x18);
1301 else if (mute == MUTE_ON)
1302 send_led_update(pte, 0x19);
1303 pte->device->mute = mute;
1304 if (output == OUTPUT_HANDSET) {
1305 if (mute == MUTE_ON)
1306 change_favorite_icon(pte, FAV_ICON_ONHOLD_BLACK);
1308 change_favorite_icon(pte, FAV_ICON_OFFHOOK_BLACK);
1309 send_led_update(pte, 0x08);
1310 send_led_update(pte, 0x10);
1311 } else if (output == OUTPUT_HEADPHONE) {
1312 if (mute == MUTE_ON)
1313 change_favorite_icon(pte, FAV_ICON_HEADPHONES_ONHOLD);
1315 change_favorite_icon(pte, FAV_ICON_HEADPHONES);
1316 send_led_update(pte, 0x08);
1317 send_led_update(pte, 0x11);
1318 } else if (output == OUTPUT_SPEAKER) {
1319 send_led_update(pte, 0x10);
1320 send_led_update(pte, 0x09);
1321 if (pte->device->receiver_state == STATE_OFFHOOK) {
1322 if (mute == MUTE_ON)
1323 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1325 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOOK_BLACK);
1327 if (mute == MUTE_ON)
1328 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1330 change_favorite_icon(pte, FAV_ICON_SPEAKER_OFFHOOK_BLACK);
1333 ast_log(LOG_WARNING, "Invalid output (%d)\n", output);
1334 if (output != pte->device->output)
1335 pte->device->previous_output = pte->device->output;
1336 pte->device->output = output;
1339 static void send_ring(struct unistimsession *pte, char volume, char style)
1343 ast_verb(0, "Sending ring packet\n");
1344 memcpy(buffsend + SIZE_HEADER, packet_send_ring, sizeof(packet_send_ring));
1345 buffsend[24] = style + 0x10;
1346 buffsend[29] = volume * 0x10;
1347 send_client(SIZE_HEADER + sizeof(packet_send_ring), buffsend, pte);
1350 static void send_no_ring(struct unistimsession *pte)
1354 ast_verb(0, "Sending no ring packet\n");
1355 memcpy(buffsend + SIZE_HEADER, packet_send_no_ring, sizeof(packet_send_no_ring));
1356 send_client(SIZE_HEADER + sizeof(packet_send_no_ring), buffsend, pte);
1359 static void send_texttitle(struct unistimsession *pte, const char *text)
1364 ast_verb(0, "Sending title text\n");
1365 memcpy(buffsend + SIZE_HEADER, packet_send_title, sizeof(packet_send_title));
1369 memcpy(buffsend + 10, text, i);
1370 send_client(SIZE_HEADER + sizeof(packet_send_title), buffsend, pte);
1374 static void send_date_time(struct unistimsession *pte)
1377 struct timeval now = ast_tvnow();
1378 struct ast_tm atm = { 0, };
1381 ast_verb(0, "Sending Time & Date\n");
1382 memcpy(buffsend + SIZE_HEADER, packet_send_date_time, sizeof(packet_send_date_time));
1383 ast_localtime(&now, &atm, NULL);
1384 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1385 buffsend[11] = (unsigned char) atm.tm_mday;
1386 buffsend[12] = (unsigned char) atm.tm_hour;
1387 buffsend[13] = (unsigned char) atm.tm_min;
1388 send_client(SIZE_HEADER + sizeof(packet_send_date_time), buffsend, pte);
1391 static void send_date_time2(struct unistimsession *pte)
1394 struct timeval now = ast_tvnow();
1395 struct ast_tm atm = { 0, };
1398 ast_verb(0, "Sending Time & Date #2\n");
1399 memcpy(buffsend + SIZE_HEADER, packet_send_date_time2, sizeof(packet_send_date_time2));
1400 ast_localtime(&now, &atm, NULL);
1402 buffsend[9] = pte->device->datetimeformat;
1405 buffsend[14] = (unsigned char) atm.tm_mon + 1;
1406 buffsend[15] = (unsigned char) atm.tm_mday;
1407 buffsend[16] = (unsigned char) atm.tm_hour;
1408 buffsend[17] = (unsigned char) atm.tm_min;
1409 send_client(SIZE_HEADER + sizeof(packet_send_date_time2), buffsend, pte);
1412 static void send_date_time3(struct unistimsession *pte)
1415 struct timeval now = ast_tvnow();
1416 struct ast_tm atm = { 0, };
1419 ast_verb(0, "Sending Time & Date #3\n");
1420 memcpy(buffsend + SIZE_HEADER, packet_send_date_time3, sizeof(packet_send_date_time3));
1421 ast_localtime(&now, &atm, NULL);
1422 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1423 buffsend[11] = (unsigned char) atm.tm_mday;
1424 buffsend[12] = (unsigned char) atm.tm_hour;
1425 buffsend[13] = (unsigned char) atm.tm_min;
1426 send_client(SIZE_HEADER + sizeof(packet_send_date_time3), buffsend, pte);
1429 static void send_blink_cursor(struct unistimsession *pte)
1433 ast_verb(0, "Sending set blink\n");
1434 memcpy(buffsend + SIZE_HEADER, packet_send_blink_cursor, sizeof(packet_send_blink_cursor));
1435 send_client(SIZE_HEADER + sizeof(packet_send_blink_cursor), buffsend, pte);
1439 /* pos : 0xab (a=0/2/4 = line ; b = row) */
1440 static void send_cursor_pos(struct unistimsession *pte, unsigned char pos)
1444 ast_verb(0, "Sending set cursor position\n");
1445 memcpy(buffsend + SIZE_HEADER, packet_send_set_pos_cursor,
1446 sizeof(packet_send_set_pos_cursor));
1448 send_client(SIZE_HEADER + sizeof(packet_send_set_pos_cursor), buffsend, pte);
1452 static void rcv_resume_connection_with_server(struct unistimsession *pte)
1456 ast_verb(0, "ResumeConnectionWithServer received\n");
1457 ast_verb(0, "Sending packet_send_query_mac_address\n");
1459 memcpy(buffsend + SIZE_HEADER, packet_send_query_mac_address,
1460 sizeof(packet_send_query_mac_address));
1461 send_client(SIZE_HEADER + sizeof(packet_send_query_mac_address), buffsend, pte);
1465 static int unistim_register(struct unistimsession *s)
1467 struct unistim_device *d;
1469 ast_mutex_lock(&devicelock);
1472 if (!strcasecmp(s->macaddr, d->id)) {
1473 /* XXX Deal with IP authentication */
1476 d->codec_number = DEFAULT_CODEC;
1479 d->receiver_state = STATE_ONHOOK;
1484 ast_mutex_unlock(&devicelock);
1492 static void unistim_line_copy(struct unistim_line *dst, struct unistim_line *src)
1494 struct ast_format_cap *tmp = src->cap;
1495 memcpy(dst, src, sizeof(*dst)); /* this over writes the cap ptr, so we have to reset it */
1497 ast_format_cap_copy(src->cap, dst->cap);
1500 static struct unistim_line *unistim_line_destroy(struct unistim_line *l)
1505 l->cap = ast_format_cap_destroy(l->cap);
1510 static struct unistim_line *unistim_line_alloc(void)
1512 struct unistim_line *l;
1513 if (!(l = ast_calloc(1, sizeof(*l)))) {
1517 if (!(l->cap = ast_format_cap_alloc_nolock())) {
1524 static int alloc_sub(struct unistim_line *l, int x)
1526 struct unistim_subchannel *sub;
1527 if (!(sub = ast_calloc(1, sizeof(*sub))))
1531 ast_verb(3, "Allocating UNISTIM subchannel #%d on %s@%s ptr=%p\n", x, l->name, l->parent->name, sub);
1535 ast_mutex_init(&sub->lock);
1539 static int unalloc_sub(struct unistim_line *p, int x)
1542 ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name,
1547 ast_debug(1, "Released sub %d of channel %s@%s\n", x, p->name,
1549 ast_mutex_destroy(&p->lock);
1550 ast_free(p->subs[x]);
1555 static void rcv_mac_addr(struct unistimsession *pte, const unsigned char *buf)
1562 ast_verb(0, "Mac Address received : ");
1563 for (tmp = 15; tmp < 15 + SIZE_HEADER; tmp++) {
1564 sprintf(&addrmac[i], "%.2x", (unsigned char) buf[tmp]);
1568 ast_verb(0, "%s\n", addrmac);
1569 strcpy(pte->macaddr, addrmac);
1570 res = unistim_register(pte);
1572 switch (autoprovisioning) {
1573 case AUTOPROVISIONING_NO:
1574 ast_log(LOG_WARNING, "No entry found for this phone : %s\n", addrmac);
1575 pte->state = STATE_AUTHDENY;
1577 case AUTOPROVISIONING_YES:
1579 struct unistim_device *d, *newd;
1580 struct unistim_line *newl;
1582 ast_verb(0, "New phone, autoprovisioning on\n");
1583 /* First : locate the [template] section */
1584 ast_mutex_lock(&devicelock);
1587 if (!strcasecmp(d->name, "template")) {
1588 /* Found, cloning this entry */
1589 if (!(newd = ast_malloc(sizeof(*newd)))) {
1590 ast_mutex_unlock(&devicelock);
1594 memcpy(newd, d, sizeof(*newd));
1595 if (!(newl = unistim_line_alloc())) {
1597 ast_mutex_unlock(&devicelock);
1601 unistim_line_copy(d->lines, newl);
1602 if (!alloc_sub(newl, SUB_REAL)) {
1604 unistim_line_destroy(newl);
1605 ast_mutex_unlock(&devicelock);
1608 /* Ok, now updating some fields */
1609 ast_copy_string(newd->id, addrmac, sizeof(newd->id));
1610 ast_copy_string(newd->name, addrmac, sizeof(newd->name));
1611 if (newd->extension == EXTENSION_NONE)
1612 newd->extension = EXTENSION_ASK;
1614 newd->receiver_state = STATE_ONHOOK;
1615 newd->session = pte;
1616 newd->to_delete = -1;
1619 newl->parent = newd;
1620 strcpy(newl->name, d->lines->name);
1621 snprintf(d->lines->name, sizeof(d->lines->name), "%d",
1622 atoi(d->lines->name) + 1);
1623 snprintf(newl->fullname, sizeof(newl->fullname), "USTM/%s@%s",
1624 newl->name, newd->name);
1625 /* Go to the end of the linked chain */
1635 ast_mutex_unlock(&devicelock);
1637 ast_log(LOG_WARNING, "No entry [template] found in unistim.conf\n");
1638 pte->state = STATE_AUTHDENY;
1642 case AUTOPROVISIONING_TN:
1643 pte->state = STATE_AUTHDENY;
1645 case AUTOPROVISIONING_DB:
1646 ast_log(LOG_WARNING,
1647 "Autoprovisioning with database is not yet functional\n");
1650 ast_log(LOG_WARNING, "Internal error : unknown autoprovisioning value = %d\n",
1654 if (pte->state != STATE_AUTHDENY) {
1655 ast_verb(3, "Device '%s' successfuly registered\n", pte->device->name);
1656 switch (pte->device->extension) {
1657 case EXTENSION_NONE:
1658 pte->state = STATE_MAINPAGE;
1661 /* Checking if we already have an extension number */
1662 if (ast_strlen_zero(pte->device->extension_number))
1663 pte->state = STATE_EXTENSION;
1665 /* Yes, because of a phone reboot. We don't ask again for the TN */
1666 if (RegisterExtension(pte))
1667 pte->state = STATE_EXTENSION;
1669 pte->state = STATE_MAINPAGE;
1672 case EXTENSION_LINE:
1673 ast_copy_string(pte->device->extension_number, pte->device->lines->name,
1674 sizeof(pte->device->extension_number));
1675 if (RegisterExtension(pte))
1676 pte->state = STATE_EXTENSION;
1678 pte->state = STATE_MAINPAGE;
1681 /* If we are here, it's because of a phone reboot */
1682 pte->state = STATE_MAINPAGE;
1685 ast_log(LOG_WARNING, "Internal error, extension value unknown : %d\n",
1686 pte->device->extension);
1687 pte->state = STATE_AUTHDENY;
1691 if (pte->state == STATE_EXTENSION) {
1692 if (pte->device->extension != EXTENSION_TN)
1693 pte->device->extension = EXTENSION_ASK;
1694 pte->device->extension_number[0] = '\0';
1697 ast_verb(0, "\nSending S1\n");
1698 memcpy(buffsend + SIZE_HEADER, packet_send_S1, sizeof(packet_send_S1));
1699 send_client(SIZE_HEADER + sizeof(packet_send_S1), buffsend, pte);
1702 ast_verb(0, "Sending query_basic_manager_04\n");
1703 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_04,
1704 sizeof(packet_send_query_basic_manager_04));
1705 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_04), buffsend, pte);
1708 ast_verb(0, "Sending query_basic_manager_10\n");
1709 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_10,
1710 sizeof(packet_send_query_basic_manager_10));
1711 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_10), buffsend, pte);
1713 send_date_time(pte);
1717 static int write_entry_history(struct unistimsession *pte, FILE * f, char c, char *line1)
1719 if (fwrite(&c, 1, 1, f) != 1) {
1720 display_last_error("Unable to write history log header.");
1723 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
1724 display_last_error("Unable to write history entry - date.");
1727 if (fwrite(pte->device->lst_cid, TEXT_LENGTH_MAX, 1, f) != 1) {
1728 display_last_error("Unable to write history entry - callerid.");
1731 if (fwrite(pte->device->lst_cnm, TEXT_LENGTH_MAX, 1, f) != 1) {
1732 display_last_error("Unable to write history entry - callername.");
1738 static int write_history(struct unistimsession *pte, char way, char ismissed)
1740 char tmp[AST_CONFIG_MAX_PATH], tmp2[AST_CONFIG_MAX_PATH];
1741 char line1[TEXT_LENGTH_MAX + 1];
1742 char count = 0, *histbuf;
1745 struct timeval now = ast_tvnow();
1746 struct ast_tm atm = { 0, };
1750 if (!pte->device->callhistory)
1752 if (strchr(pte->device->name, '/') || (pte->device->name[0] == '.')) {
1753 ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n",
1758 snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_LOG_DIR, USTM_LOG_DIR);
1759 if (ast_mkdir(tmp, 0770)) {
1760 if (errno != EEXIST) {
1761 display_last_error("Unable to create directory for history");
1766 ast_localtime(&now, &atm, NULL);
1769 strcpy(tmp2, "Miss");
1771 strcpy(tmp2, "Fail");
1773 strcpy(tmp2, "Answ");
1774 snprintf(line1, sizeof(line1), "%04d/%02d/%02d %02d:%02d:%02d %s",
1775 atm.tm_year + 1900, atm.tm_mon + 1, atm.tm_mday, atm.tm_hour,
1776 atm.tm_min, atm.tm_sec, tmp2);
1778 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
1779 USTM_LOG_DIR, pte->device->name, way);
1780 if ((f = fopen(tmp, "r"))) {
1781 struct stat bufstat;
1783 if (stat(tmp, &bufstat)) {
1784 display_last_error("Unable to stat history log.");
1788 size = 1 + (MAX_ENTRY_LOG * TEXT_LENGTH_MAX * 3);
1789 if (bufstat.st_size != size) {
1790 ast_log(LOG_WARNING,
1791 "History file %s has an incorrect size (%d instead of %d). It will be replaced by a new one.",
1792 tmp, (int) bufstat.st_size, size);
1799 /* If we can't open the log file, we create a brand new one */
1804 if ((errno != ENOENT) && (count == 0)) {
1805 display_last_error("Unable to open history log.");
1808 f = fopen(tmp, "w");
1810 display_last_error("Unable to create history log.");
1813 if (write_entry_history(pte, f, c, line1)) {
1817 memset(line1, ' ', TEXT_LENGTH_MAX);
1818 for (i = 3; i < MAX_ENTRY_LOG * 3; i++) {
1819 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
1820 display_last_error("Unable to write history entry - stuffing.");
1826 display_last_error("Unable to close history - creation.");
1829 /* We can open the log file, we create a temporary one, we add our entry and copy the rest */
1830 if (fread(&count, 1, 1, f) != 1) {
1831 display_last_error("Unable to read history header.");
1835 if (count > MAX_ENTRY_LOG) {
1836 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
1837 count, MAX_ENTRY_LOG);
1841 snprintf(tmp2, sizeof(tmp2), "%s/%s/%s-%c.csv.tmp", ast_config_AST_LOG_DIR,
1842 USTM_LOG_DIR, pte->device->name, way);
1843 if (!(f2 = fopen(tmp2, "w"))) {
1844 display_last_error("Unable to create temporary history log.");
1849 if (++count > MAX_ENTRY_LOG)
1850 count = MAX_ENTRY_LOG;
1852 if (write_entry_history(pte, f2, count, line1)) {
1858 size = (MAX_ENTRY_LOG - 1) * TEXT_LENGTH_MAX * 3;
1859 if (!(histbuf = ast_malloc(size))) {
1865 if (fread(histbuf, size, 1, f) != 1) {
1869 display_last_error("Unable to read previous history entries.");
1872 if (fwrite(histbuf, size, 1, f2) != 1) {
1876 display_last_error("Unable to write previous history entries.");
1881 display_last_error("Unable to close history log.");
1883 display_last_error("Unable to close temporary history log.");
1885 display_last_error("Unable to remove old history log.");
1886 if (rename(tmp2, tmp))
1887 display_last_error("Unable to rename new history log.");
1891 static void cancel_dial(struct unistimsession *pte)
1894 pte->device->missed_call++;
1895 write_history(pte, 'i', 1);
1896 show_main_page(pte);
1900 static void swap_subs(struct unistim_line *p, int a, int b)
1902 /* struct ast_channel *towner; */
1903 struct ast_rtp_instance *rtp;
1907 ast_verb(0, "Swapping %d and %d\n", a, b);
1909 if ((!p->subs[a]->owner) || (!p->subs[b]->owner)) {
1910 ast_log(LOG_WARNING,
1911 "Attempted to swap subchannels with a null owner : sub #%d=%p sub #%d=%p\n",
1912 a, p->subs[a]->owner, b, p->subs[b]->owner);
1915 rtp = p->subs[a]->rtp;
1916 p->subs[a]->rtp = p->subs[b]->rtp;
1917 p->subs[b]->rtp = rtp;
1919 fds = p->subs[a]->owner->fds[0];
1920 p->subs[a]->owner->fds[0] = p->subs[b]->owner->fds[0];
1921 p->subs[b]->owner->fds[0] = fds;
1923 fds = p->subs[a]->owner->fds[1];
1924 p->subs[a]->owner->fds[1] = p->subs[b]->owner->fds[1];
1925 p->subs[b]->owner->fds[1] = fds;
1928 static int attempt_transfer(struct unistim_subchannel *p1, struct unistim_subchannel *p2)
1932 *chana = NULL, *chanb = NULL, *bridgea = NULL, *bridgeb = NULL, *peera =
1933 NULL, *peerb = NULL, *peerc = NULL;
1935 if (!p1->owner || !p2->owner) {
1936 ast_log(LOG_WARNING, "Transfer attempted without dual ownership?\n");
1941 bridgea = ast_bridged_channel(chana);
1942 bridgeb = ast_bridged_channel(chanb);
1948 } else if (bridgeb) {
1954 if (peera && peerb && peerc && (peerb != peerc)) {
1955 /*ast_quiet_chan(peera);
1956 ast_quiet_chan(peerb);
1957 ast_quiet_chan(peerc);
1958 ast_quiet_chan(peerd); */
1960 if (peera->cdr && peerb->cdr) {
1961 peerb->cdr = ast_cdr_append(peerb->cdr, peera->cdr);
1962 } else if (peera->cdr) {
1963 peerb->cdr = peera->cdr;
1967 if (peerb->cdr && peerc->cdr) {
1968 peerb->cdr = ast_cdr_append(peerb->cdr, peerc->cdr);
1969 } else if (peerc->cdr) {
1970 peerb->cdr = peerc->cdr;
1974 if (ast_channel_masquerade(peerb, peerc)) {
1975 ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name,
1982 "Transfer attempted with no appropriate bridged calls to transfer\n");
1984 ast_softhangup_nolock(chana, AST_SOFTHANGUP_DEV);
1986 ast_softhangup_nolock(chanb, AST_SOFTHANGUP_DEV);
1992 void change_callerid(struct unistimsession *pte, int type, char *callerid)
1998 data = pte->device->lst_cnm;
2000 data = pte->device->lst_cid;
2002 /* This is very nearly strncpy(), except that the remaining buffer
2003 * is padded with ' ', instead of '\0' */
2004 memset(data, ' ', TEXT_LENGTH_MAX);
2005 size = strlen(callerid);
2006 if (size > TEXT_LENGTH_MAX)
2007 size = TEXT_LENGTH_MAX;
2008 memcpy(data, callerid, size);
2011 static void close_call(struct unistimsession *pte)
2013 struct unistim_subchannel *sub;
2014 struct unistim_line *l = pte->device->lines;
2016 sub = pte->device->lines->subs[SUB_REAL];
2017 send_stop_timer(pte);
2019 sub->alreadygone = 1;
2020 if (l->subs[SUB_THREEWAY]) {
2021 l->subs[SUB_THREEWAY]->alreadygone = 1;
2022 if (attempt_transfer(sub, l->subs[SUB_THREEWAY]) < 0)
2023 ast_verb(0, "attempt_transfer failed.\n");
2025 ast_queue_hangup(sub->owner);
2027 if (l->subs[SUB_THREEWAY]) {
2028 if (l->subs[SUB_THREEWAY]->owner)
2029 ast_queue_hangup_with_cause(l->subs[SUB_THREEWAY]->owner, AST_CAUSE_NORMAL_CLEARING);
2031 ast_log(LOG_WARNING, "threeway sub without owner\n");
2033 ast_verb(0, "USTM(%s@%s-%d) channel already destroyed\n", sub->parent->name,
2034 sub->parent->parent->name, sub->subtype);
2036 change_callerid(pte, 0, pte->device->redial_number);
2037 change_callerid(pte, 1, "");
2038 write_history(pte, 'o', pte->device->missed_call);
2039 pte->device->missed_call = 0;
2040 show_main_page(pte);
2044 static void IgnoreCall(struct unistimsession *pte)
2050 static void *unistim_ss(void *data)
2052 struct ast_channel *chan = data;
2053 struct unistim_subchannel *sub = chan->tech_pvt;
2054 struct unistim_line *l = sub->parent;
2055 struct unistimsession *s = l->parent->session;
2058 ast_verb(3, "Starting switch on '%s@%s-%d' to %s\n", l->name, l->parent->name, sub->subtype, s->device->phone_number);
2059 ast_copy_string(chan->exten, s->device->phone_number, sizeof(chan->exten));
2060 ast_copy_string(s->device->redial_number, s->device->phone_number,
2061 sizeof(s->device->redial_number));
2062 ast_setstate(chan, AST_STATE_RING);
2063 res = ast_pbx_run(chan);
2065 ast_log(LOG_WARNING, "PBX exited non-zero\n");
2066 send_tone(s, 1000, 0);;
2071 static void start_rtp(struct unistim_subchannel *sub)
2074 struct sockaddr_in us = { 0, };
2075 struct sockaddr_in public = { 0, };
2076 struct sockaddr_in sin = { 0, };
2078 struct sockaddr_in sout = { 0, };
2079 struct ast_sockaddr us_tmp;
2080 struct ast_sockaddr sin_tmp;
2081 struct ast_sockaddr sout_tmp;
2085 ast_log(LOG_WARNING, "start_rtp with a null subchannel !\n");
2089 ast_log(LOG_WARNING, "start_rtp with a null line !\n");
2092 if (!sub->parent->parent) {
2093 ast_log(LOG_WARNING, "start_rtp with a null device !\n");
2096 if (!sub->parent->parent->session) {
2097 ast_log(LOG_WARNING, "start_rtp with a null session !\n");
2100 sout = sub->parent->parent->session->sout;
2102 ast_mutex_lock(&sub->lock);
2103 /* Allocate the RTP */
2105 ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
2106 ast_sockaddr_from_sin(&sout_tmp, &sout);
2107 sub->rtp = ast_rtp_instance_new("asterisk", sched, &sout_tmp, NULL);
2109 ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
2110 strerror(errno), ast_inet_ntoa(sout.sin_addr));
2111 ast_mutex_unlock(&sub->lock);
2114 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
2116 sub->owner->fds[0] = ast_rtp_instance_fd(sub->rtp, 0);
2117 sub->owner->fds[1] = ast_rtp_instance_fd(sub->rtp, 1);
2119 ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
2120 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->parent->parent->nat);
2122 /* Create the RTP connection */
2123 ast_rtp_instance_get_local_address(sub->rtp, &us_tmp);
2124 ast_sockaddr_to_sin(&us_tmp, &us);
2125 sin.sin_family = AF_INET;
2126 /* Setting up RTP for our side */
2127 memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
2128 sizeof(sin.sin_addr));
2129 sin.sin_port = htons(sub->parent->parent->rtp_port);
2130 ast_sockaddr_from_sin(&sin_tmp, &sin);
2131 ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
2132 if (!(ast_format_cap_iscompatible(sub->owner->nativeformats, &sub->owner->readformat))) {
2133 struct ast_format tmpfmt;
2135 ast_best_codec(sub->owner->nativeformats, &tmpfmt);
2136 ast_log(LOG_WARNING,
2137 "Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n",
2138 ast_getformatname(&sub->owner->readformat),
2139 ast_getformatname(&tmpfmt),
2140 ast_getformatname_multiple(tmp, sizeof(tmp), sub->owner->nativeformats));
2141 ast_format_copy(&sub->owner->readformat, &tmpfmt);
2142 ast_format_copy(&sub->owner->writeformat, &tmpfmt);
2144 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, &sub->owner->readformat, 0);
2145 /* Setting up RTP of the phone */
2146 if (public_ip.sin_family == 0) /* NAT IP override ? */
2147 memcpy(&public, &us, sizeof(public)); /* No defined, using IP from recvmsg */
2149 memcpy(&public, &public_ip, sizeof(public)); /* override */
2151 ast_verb(0, "RTP started : Our IP/port is : %s:%hd with codec %s\n",
2152 ast_inet_ntoa(us.sin_addr),
2153 htons(us.sin_port), ast_getformatname(&sub->owner->readformat));
2154 ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n",
2155 ast_inet_ntoa(public.sin_addr));
2157 if ((sub->owner->readformat.id == AST_FORMAT_ULAW) ||
2158 (sub->owner->readformat.id == AST_FORMAT_ALAW)) {
2160 ast_verb(0, "Sending packet_send_rtp_packet_size for codec %d\n", codec);
2161 memcpy(buffsend + SIZE_HEADER, packet_send_rtp_packet_size,
2162 sizeof(packet_send_rtp_packet_size));
2163 buffsend[10] = (int) codec & 0xffffffffLL;
2164 send_client(SIZE_HEADER + sizeof(packet_send_rtp_packet_size), buffsend,
2165 sub->parent->parent->session);
2168 ast_verb(0, "Sending Jitter Buffer Parameters Configuration\n");
2169 memcpy(buffsend + SIZE_HEADER, packet_send_jitter_buffer_conf,
2170 sizeof(packet_send_jitter_buffer_conf));
2171 send_client(SIZE_HEADER + sizeof(packet_send_jitter_buffer_conf), buffsend,
2172 sub->parent->parent->session);
2173 if (sub->parent->parent->rtp_method != 0) {
2174 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2177 ast_verb(0, "Sending OpenAudioStreamTX using method #%d\n",
2178 sub->parent->parent->rtp_method);
2179 if (sub->parent->parent->rtp_method == 3)
2180 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx3,
2181 sizeof(packet_send_open_audio_stream_tx3));
2183 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx,
2184 sizeof(packet_send_open_audio_stream_tx));
2185 if (sub->parent->parent->rtp_method != 2) {
2186 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2187 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2188 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2189 buffsend[23] = (rtcpsin_port & 0x00ff);
2190 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2191 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2192 buffsend[24] = (us.sin_port & 0x00ff);
2193 buffsend[27] = (rtcpsin_port & 0x00ff);
2194 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2196 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2197 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2198 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2199 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2200 buffsend[19] = (us.sin_port & 0x00ff);
2201 buffsend[11] = codec;
2203 buffsend[12] = codec;
2204 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_tx), buffsend,
2205 sub->parent->parent->session);
2208 ast_verb(0, "Sending OpenAudioStreamRX\n");
2209 if (sub->parent->parent->rtp_method == 3)
2210 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx3,
2211 sizeof(packet_send_open_audio_stream_rx3));
2213 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx,
2214 sizeof(packet_send_open_audio_stream_rx));
2215 if (sub->parent->parent->rtp_method != 2) {
2216 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2217 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2218 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2219 buffsend[23] = (rtcpsin_port & 0x00ff);
2220 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2221 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2222 buffsend[24] = (us.sin_port & 0x00ff);
2223 buffsend[27] = (rtcpsin_port & 0x00ff);
2224 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2226 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2227 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2228 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2229 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2230 buffsend[19] = (us.sin_port & 0x00ff);
2231 buffsend[12] = codec;
2233 buffsend[11] = codec;
2234 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_rx), buffsend,
2235 sub->parent->parent->session);
2237 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2240 ast_verb(0, "Sending packet_send_call default method\n");
2242 memcpy(buffsend + SIZE_HEADER, packet_send_call, sizeof(packet_send_call));
2243 memcpy(buffsend + 53, &public.sin_addr, sizeof(public.sin_addr));
2244 /* Destination port when sending RTP */
2245 buffsend[49] = (us.sin_port & 0x00ff);
2246 buffsend[50] = (us.sin_port & 0xff00) >> 8;
2247 /* Destination port when sending RTCP */
2248 buffsend[52] = (rtcpsin_port & 0x00ff);
2249 buffsend[51] = (rtcpsin_port & 0xff00) >> 8;
2251 buffsend[40] = codec;
2252 buffsend[41] = codec;
2253 if (sub->owner->readformat.id == AST_FORMAT_ULAW)
2254 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2255 else if (sub->owner->readformat.id == AST_FORMAT_ALAW)
2256 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2257 else if (sub->owner->readformat.id == AST_FORMAT_G723_1)
2258 buffsend[42] = 2; /* 1 = 30ms (24 bytes), 2 = 60 ms (48 bytes) */
2259 else if (sub->owner->readformat.id == AST_FORMAT_G729A)
2260 buffsend[42] = 2; /* 1 = 10ms (10 bytes), 2 = 20ms (20 bytes) */
2262 ast_log(LOG_WARNING, "Unsupported codec %s!\n",
2263 ast_getformatname(&sub->owner->readformat));
2264 /* Source port for transmit RTP and Destination port for receiving RTP */
2265 buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8;
2266 buffsend[46] = (htons(sin.sin_port) & 0x00ff);
2267 buffsend[47] = (rtcpsin_port & 0xff00) >> 8;
2268 buffsend[48] = (rtcpsin_port & 0x00ff);
2269 send_client(SIZE_HEADER + sizeof(packet_send_call), buffsend,
2270 sub->parent->parent->session);
2272 ast_mutex_unlock(&sub->lock);
2275 static void SendDialTone(struct unistimsession *pte)
2278 /* No country defined ? Using US tone */
2279 if (ast_strlen_zero(pte->device->country)) {
2281 ast_verb(0, "No country defined, using US tone\n");
2282 send_tone(pte, 350, 440);
2285 if (strlen(pte->device->country) != 2) {
2287 ast_verb(0, "Country code != 2 char, using US tone\n");
2288 send_tone(pte, 350, 440);
2292 while (frequency[i].freq1) {
2293 if ((frequency[i].country[0] == pte->device->country[0]) &&
2294 (frequency[i].country[1] == pte->device->country[1])) {
2296 ast_verb(0, "Country code found (%s), freq1=%d freq2=%d\n",
2297 frequency[i].country, frequency[i].freq1, frequency[i].freq2);
2298 send_tone(pte, frequency[i].freq1, frequency[i].freq2);
2304 static void handle_dial_page(struct unistimsession *pte)
2306 pte->state = STATE_DIALPAGE;
2307 if (pte->device->call_forward[0] == -1) {
2308 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
2309 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Enter forward");
2310 send_text_status(pte, "ForwardCancel BackSpcErase");
2311 if (pte->device->call_forward[1] != 0) {
2312 char tmp[TEXT_LENGTH_MAX + 1];
2314 ast_copy_string(pte->device->phone_number, pte->device->call_forward + 1,
2315 sizeof(pte->device->phone_number));
2316 pte->device->size_phone_number = strlen(pte->device->phone_number);
2317 if (pte->device->size_phone_number > 15)
2318 pte->device->size_phone_number = 15;
2319 strcpy(tmp, "Number : ...............");
2320 memcpy(tmp + 9, pte->device->phone_number, pte->device->size_phone_number);
2322 if (pte->device->height == 1) {
2323 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmp);
2324 send_blink_cursor(pte);
2325 send_cursor_pos(pte,
2326 (unsigned char) (TEXT_LINE0 + 0x09 +
2327 pte->device->size_phone_number));
2329 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
2330 send_blink_cursor(pte);
2331 send_cursor_pos(pte,
2332 (unsigned char) (TEXT_LINE2 + 0x09 +
2333 pte->device->size_phone_number));
2336 send_led_update(pte, 0);
2340 if ((pte->device->output == OUTPUT_HANDSET) &&
2341 (pte->device->receiver_state == STATE_ONHOOK))
2342 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2344 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2347 if (pte->device->height > 1) {
2348 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Enter the number to dial");
2349 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "and press Call");
2351 send_text_status(pte, "Call Redial BackSpcErase");
2354 if (pte->device->height == 1) {
2355 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Number : ...............");
2356 send_blink_cursor(pte);
2357 send_cursor_pos(pte, TEXT_LINE0 + 0x09);
2359 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
2360 send_blink_cursor(pte);
2361 send_cursor_pos(pte, TEXT_LINE2 + 0x09);
2363 pte->device->size_phone_number = 0;
2364 pte->device->phone_number[0] = 0;
2365 change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
2366 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
2367 pte->device->missed_call = 0;
2368 send_led_update(pte, 0);
2372 /* Step 1 : Music On Hold for peer, Dialing screen for us */
2373 static void TransferCallStep1(struct unistimsession *pte)
2375 struct unistim_subchannel *sub;
2376 struct unistim_line *p = pte->device->lines;
2378 sub = p->subs[SUB_REAL];
2381 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2384 if (p->subs[SUB_THREEWAY]) {
2386 ast_verb(0, "Transfer canceled, hangup our threeway channel\n");
2387 if (p->subs[SUB_THREEWAY]->owner)
2388 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY]->owner, AST_CAUSE_NORMAL_CLEARING);
2390 ast_log(LOG_WARNING, "Canceling a threeway channel without owner\n");
2393 /* Start music on hold if appropriate */
2394 if (pte->device->moh)
2395 ast_log(LOG_WARNING, "Transfer with peer already listening music on hold\n");
2397 if (ast_bridged_channel(p->subs[SUB_REAL]->owner)) {
2398 ast_moh_start(ast_bridged_channel(p->subs[SUB_REAL]->owner),
2399 pte->device->lines->musicclass, NULL);
2400 pte->device->moh = 1;
2402 ast_log(LOG_WARNING, "Unable to find peer subchannel for music on hold\n");
2406 /* Silence our channel */
2407 if (!pte->device->silence_generator) {
2408 pte->device->silence_generator =
2409 ast_channel_start_silence_generator(p->subs[SUB_REAL]->owner);
2410 if (pte->device->silence_generator == NULL)
2411 ast_log(LOG_WARNING, "Unable to start a silence generator.\n");
2412 else if (unistimdebug)
2413 ast_verb(0, "Starting silence generator\n");
2415 handle_dial_page(pte);
2418 /* From phone to PBX */
2419 static void HandleCallOutgoing(struct unistimsession *s)
2421 struct ast_channel *c;
2422 struct unistim_subchannel *sub;
2424 s->state = STATE_CALL;
2425 sub = s->device->lines->subs[SUB_REAL];
2427 ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
2430 if (!sub->owner) { /* A call is already in progress ? */
2431 c = unistim_new(sub, AST_STATE_DOWN, NULL); /* No, starting a new one */
2433 /* Need to start RTP before calling ast_pbx_run */
2436 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
2438 if (s->device->height == 1) {
2439 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
2441 send_text(TEXT_LINE0, TEXT_NORMAL, s, "Calling :");
2442 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
2443 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Dialing...");
2445 send_text_status(s, "Hangup");
2448 if (ast_pthread_create(&t, NULL, unistim_ss, c)) {
2449 display_last_error("Unable to create switch thread");
2450 ast_queue_hangup_with_cause(c, AST_CAUSE_SWITCH_CONGESTION);
2453 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n",
2454 sub->parent->name, s->device->name);
2455 } else { /* We already have a call, so we switch in a threeway call */
2457 if (s->device->moh) {
2458 struct unistim_subchannel *subchannel;
2459 struct unistim_line *p = s->device->lines;
2460 subchannel = p->subs[SUB_REAL];
2462 if (!subchannel->owner) {
2463 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2466 if (p->subs[SUB_THREEWAY]) {
2467 ast_log(LOG_WARNING,
2468 "Can't transfer while an another transfer is taking place\n");
2471 if (!alloc_sub(p, SUB_THREEWAY)) {
2472 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
2475 /* Stop the silence generator */
2476 if (s->device->silence_generator) {
2478 ast_verb(0, "Stopping silence generator\n");
2479 ast_channel_stop_silence_generator(subchannel->owner,
2480 s->device->silence_generator);
2481 s->device->silence_generator = NULL;
2484 /* Make new channel */
2485 c = unistim_new(p->subs[SUB_THREEWAY], AST_STATE_DOWN, NULL);
2487 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", p);
2490 /* Swap things around between the three-way and real call */
2491 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2492 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
2494 if (s->device->height == 1) {
2495 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
2497 send_text(TEXT_LINE0, TEXT_NORMAL, s, "Calling (pre-transfer)");
2498 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
2499 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Dialing...");
2501 send_text_status(s, "TransfrCancel");
2503 if (ast_pthread_create(&t, NULL, unistim_ss, p->subs[SUB_THREEWAY]->owner)) {
2504 ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", p);
2509 ast_verb(0, "Started three way call on channel %p (%s) subchan %d\n",
2510 p->subs[SUB_THREEWAY]->owner, p->subs[SUB_THREEWAY]->owner->name,
2511 p->subs[SUB_THREEWAY]->subtype);
2513 ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name);
2518 /* From PBX to phone */
2519 static void HandleCallIncoming(struct unistimsession *s)
2521 struct unistim_subchannel *sub;
2522 s->state = STATE_CALL;
2523 s->device->missed_call = 0;
2525 sub = s->device->lines->subs[SUB_REAL];
2527 ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
2529 } else if (unistimdebug)
2530 ast_verb(0, "Handle Call Incoming for %s@%s\n", sub->parent->name,
2534 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", sub->parent->name,
2536 ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
2537 send_text(TEXT_LINE2, TEXT_NORMAL, s, "is on-line");
2538 send_text_status(s, "Hangup Transf");
2539 send_start_timer(s);
2541 if ((s->device->output == OUTPUT_HANDSET) &&
2542 (s->device->receiver_state == STATE_ONHOOK))
2543 send_select_output(s, OUTPUT_SPEAKER, s->device->volume, MUTE_OFF);
2545 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
2546 s->device->start_call_timestamp = time(0);
2547 write_history(s, 'i', 0);
2551 static int unistim_do_senddigit(struct unistimsession *pte, char digit)
2553 struct ast_frame f = { .frametype = AST_FRAME_DTMF, .subclass.integer = digit, .src = "unistim" };
2554 struct unistim_subchannel *sub;
2555 sub = pte->device->lines->subs[SUB_REAL];
2556 if (!sub->owner || sub->alreadygone) {
2557 ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit\n");
2561 /* Send DTMF indication _before_ playing sounds */
2562 ast_queue_frame(sub->owner, &f);
2565 ast_verb(0, "Send Digit %c\n", digit);
2568 send_tone(pte, 941, 1336);
2571 send_tone(pte, 697, 1209);
2574 send_tone(pte, 697, 1336);
2577 send_tone(pte, 697, 1477);
2580 send_tone(pte, 770, 1209);
2583 send_tone(pte, 770, 1336);
2586 send_tone(pte, 770, 1477);
2589 send_tone(pte, 852, 1209);
2592 send_tone(pte, 852, 1336);
2595 send_tone(pte, 852, 1477);
2598 send_tone(pte, 697, 1633);
2601 send_tone(pte, 770, 1633);
2604 send_tone(pte, 852, 1633);
2607 send_tone(pte, 941, 1633);
2610 send_tone(pte, 941, 1209);
2613 send_tone(pte, 941, 1477);
2616 send_tone(pte, 500, 2000);
2618 usleep(150000); /* XXX Less than perfect, blocking an important thread is not a good idea */
2619 send_tone(pte, 0, 0);
2623 static void key_call(struct unistimsession *pte, char keycode)
2625 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
2626 if (keycode == KEY_SHARP)
2628 else if (keycode == KEY_STAR)
2632 unistim_do_senddigit(pte, keycode);
2641 TransferCallStep1(pte);
2644 if (pte->device->output == OUTPUT_HEADPHONE)
2645 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
2647 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
2650 if (pte->device->output != OUTPUT_SPEAKER)
2651 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2653 send_select_output(pte, pte->device->previous_output, pte->device->volume,
2657 if (!pte->device->moh) {
2658 if (pte->device->mute == MUTE_ON)
2659 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2661 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
2666 struct unistim_subchannel *sub;
2667 struct ast_channel *bridgepeer = NULL;
2668 sub = pte->device->lines->subs[SUB_REAL];
2670 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2673 if ((bridgepeer = ast_bridged_channel(sub->owner))) {
2674 if (pte->device->moh) {
2675 ast_moh_stop(bridgepeer);
2676 pte->device->moh = 0;
2677 send_select_output(pte, pte->device->output, pte->device->volume,
2680 ast_moh_start(bridgepeer, pte->device->lines->musicclass, NULL);
2681 pte->device->moh = 1;
2682 send_select_output(pte, pte->device->output, pte->device->volume,
2686 ast_log(LOG_WARNING,
2687 "Unable to find peer subchannel for music on hold\n");
2694 static void key_ringing(struct unistimsession *pte, char keycode)
2696 if (keycode == KEY_FAV0 + pte->device->softkeylinepos) {
2697 HandleCallIncoming(pte);
2706 HandleCallIncoming(pte);
2712 static void Keyfavorite(struct unistimsession *pte, char keycode)
2716 if ((keycode < KEY_FAV1) && (keycode > KEY_FAV5)) {
2717 ast_log(LOG_WARNING, "It's not a favorite key\n");
2720 if (keycode == KEY_FAV0)
2722 fav = keycode - KEY_FAV0;
2723 if (pte->device->softkeyicon[fav] == 0)
2725 ast_copy_string(pte->device->phone_number, pte->device->softkeynumber[fav],
2726 sizeof(pte->device->phone_number));
2727 HandleCallOutgoing(pte);
2731 static void key_dial_page(struct unistimsession *pte, char keycode)
2733 if (keycode == KEY_FUNC3) {
2734 if (pte->device->size_phone_number <= 1)
2735 keycode = KEY_FUNC4;
2737 pte->device->size_phone_number -= 2;
2738 keycode = pte->device->phone_number[pte->device->size_phone_number] + 0x10;
2741 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
2742 char tmpbuf[] = "Number : ...............";
2745 if (pte->device->size_phone_number >= 15)
2747 if (pte->device->size_phone_number == 0)
2748 send_tone(pte, 0, 0);
2749 while (i < pte->device->size_phone_number) {
2750 tmpbuf[i + 9] = pte->device->phone_number[i];
2753 if (keycode == KEY_SHARP)
2755 else if (keycode == KEY_STAR)
2759 tmpbuf[i + 9] = keycode;
2760 pte->device->phone_number[i] = keycode;
2761 pte->device->size_phone_number++;
2762 pte->device->phone_number[i + 1] = 0;
2763 if (pte->device->height == 1) {
2764 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpbuf);
2766 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
2768 send_blink_cursor(pte);
2769 send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 + 0x0a + i));
2772 if (keycode == KEY_FUNC4) {
2774 pte->device->size_phone_number = 0;
2775 if (pte->device->height == 1) {
2776 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Number : ...............");
2777 send_blink_cursor(pte);
2778 send_cursor_pos(pte, TEXT_LINE0 + 0x09);
2780 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
2781 send_blink_cursor(pte);
2782 send_cursor_pos(pte, TEXT_LINE2 + 0x09);
2787 if (pte->device->call_forward[0] == -1) {
2788 if (keycode == KEY_FUNC1) {
2789 ast_copy_string(pte->device->call_forward, pte->device->phone_number,
2790 sizeof(pte->device->call_forward));
2791 show_main_page(pte);
2792 } else if ((keycode == KEY_FUNC2) || (keycode == KEY_HANGUP)) {
2793 pte->device->call_forward[0] = '\0';
2794 show_main_page(pte);
2800 if (ast_strlen_zero(pte->device->redial_number))
2802 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
2803 sizeof(pte->device->phone_number));
2805 HandleCallOutgoing(pte);
2808 if (pte->device->lines->subs[SUB_REAL]->owner) {
2809 /* Stop the silence generator */
2810 if (pte->device->silence_generator) {
2812 ast_verb(0, "Stopping silence generator\n");
2813 ast_channel_stop_silence_generator(pte->device->lines->subs[SUB_REAL]->
2814 owner, pte->device->silence_generator);
2815 pte->device->silence_generator = NULL;
2817 send_tone(pte, 0, 0);
2818 ast_moh_stop(ast_bridged_channel(pte->device->lines->subs[SUB_REAL]->owner));
2819 pte->device->moh = 0;
2820 pte->state = STATE_CALL;
2822 if (pte->device->height == 1) {
2823 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Dial Cancel,back to priv. call.");
2825 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Dialing canceled,");
2826 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "switching back to");
2827 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "previous call.");
2829 send_text_status(pte, "Hangup Transf");
2831 show_main_page(pte);
2838 Keyfavorite(pte, keycode);
2841 if (pte->device->output == OUTPUT_SPEAKER) {
2842 if (pte->device->receiver_state == STATE_OFFHOOK)
2843 send_select_output(pte, pte->device->previous_output, pte->device->volume,
2846 show_main_page(pte);
2848 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2851 if (pte->device->output == OUTPUT_HEADPHONE) {
2852 if (pte->device->receiver_state == STATE_OFFHOOK)
2853 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
2855 show_main_page(pte);
2857 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
2863 #define SELECTCODEC_START_ENTRY_POS 15
2864 #define SELECTCODEC_MAX_LENGTH 2
2865 #define SELECTCODEC_MSG "Codec number : .."
2866 static void HandleSelectCodec(struct unistimsession *pte)
2868 char buf[30], buf2[5];
2870 pte->state = STATE_SELECTCODEC;
2871 strcpy(buf, "Using codec ");
2872 sprintf(buf2, "%d", pte->device->codec_number);
2874 strcat(buf, " (G711u=0,");
2876 send_text(TEXT_LINE0, TEXT_NORMAL, pte, buf);
2877 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "G723=4,G711a=8,G729A=18)");
2878 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
2879 send_blink_cursor(pte);
2880 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
2881 pte->size_buff_entry = 0;
2882 send_text_status(pte, "Select BackSpcErase Cancel");
2886 static void key_select_codec(struct unistimsession *pte, char keycode)
2888 if (keycode == KEY_FUNC2) {
2889 if (pte->size_buff_entry <= 1)
2890 keycode = KEY_FUNC3;
2892 pte->size_buff_entry -= 2;
2893 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
2896 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
2897 char tmpbuf[] = SELECTCODEC_MSG;
2900 if (pte->size_buff_entry >= SELECTCODEC_MAX_LENGTH)
2903 while (i < pte->size_buff_entry) {
2904 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = pte->buff_entry[i];
2907 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = keycode - 0x10;
2908 pte->buff_entry[i] = keycode - 0x10;
2909 pte->size_buff_entry++;
2910 send_text(TEXT_LINE2, TEXT_INVERSE, pte, tmpbuf);
2911 send_blink_cursor(pte);
2912 send_cursor_pos(pte,
2913 (unsigned char) (TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS + 1 + i));
2919 if (pte->size_buff_entry == 1)
2920 pte->device->codec_number = pte->buff_entry[0] - 48;
2921 else if (pte->size_buff_entry == 2)
2922 pte->device->codec_number =
2923 ((pte->buff_entry[0] - 48) * 10) + (pte->buff_entry[1] - 48);
2924 show_main_page(pte);
2927 pte->size_buff_entry = 0;
2928 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
2929 send_blink_cursor(pte);
2930 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
2934 show_main_page(pte);
2940 #define SELECTEXTENSION_START_ENTRY_POS 0
2941 #define SELECTEXTENSION_MAX_LENGTH 10
2942 #define SELECTEXTENSION_MSG ".........."
2943 static void ShowExtensionPage(struct unistimsession *pte)
2945 pte->state = STATE_EXTENSION;
2947 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Please enter a Terminal");
2948 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Number (TN) :");
2949 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
2950 send_blink_cursor(pte);
2951 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
2952 send_text_status(pte, "Enter BackSpcErase");
2953 pte->size_buff_entry = 0;
2957 static void key_select_extension(struct unistimsession *pte, char keycode)
2959 if (keycode == KEY_FUNC2) {
2960 if (pte->size_buff_entry <= 1)
2961 keycode = KEY_FUNC3;
2963 pte->size_buff_entry -= 2;
2964 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
2967 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
2968 char tmpbuf[] = SELECTEXTENSION_MSG;
2971 if (pte->size_buff_entry >= SELECTEXTENSION_MAX_LENGTH)
2974 while (i < pte->size_buff_entry) {
2975 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = pte->buff_entry[i];
2978 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = keycode - 0x10;
2979 pte->buff_entry[i] = keycode - 0x10;
2980 pte->size_buff_entry++;
2981 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
2982 send_blink_cursor(pte);
2983 send_cursor_pos(pte,
2984 (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS + 1 +
2991 if (pte->size_buff_entry < 1)
2993 if (autoprovisioning == AUTOPROVISIONING_TN) {
2994 struct unistim_device *d;
2996 /* First step : looking for this TN in our device list */
2997 ast_mutex_lock(&devicelock);
2999 pte->buff_entry[pte->size_buff_entry] = '\0';
3001 if (d->id[0] == 'T') { /* It's a TN device ? */
3002 /* It's the TN we're looking for ? */
3003 if (!strcmp((d->id) + 1, pte->buff_entry)) {
3006 d->codec_number = DEFAULT_CODEC;
3009 d->receiver_state = STATE_ONHOOK;
3010 strcpy(d->id, pte->macaddr);
3011 pte->device->extension_number[0] = 'T';
3012 pte->device->extension = EXTENSION_TN;
3013 ast_copy_string((pte->device->extension_number) + 1,
3014 pte->buff_entry, pte->size_buff_entry + 1);
3015 ast_mutex_unlock(&devicelock);
3016 show_main_page(pte);
3017 refresh_all_favorite(pte);
3023 ast_mutex_unlock(&devicelock);
3024 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Invalid Terminal Number.");
3025 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Please try again :");
3026 send_cursor_pos(pte,
3027 (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS +
3028 pte->size_buff_entry));
3029 send_blink_cursor(pte);
3031 ast_copy_string(pte->device->extension_number, pte->buff_entry,
3032 pte->size_buff_entry + 1);
3033 if (RegisterExtension(pte)) {
3034 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Invalid extension.");
3035 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Please try again :");
3036 send_cursor_pos(pte,
3037 (unsigned char) (TEXT_LINE2 +
3038 SELECTEXTENSION_START_ENTRY_POS +
3039 pte->size_buff_entry));
3040 send_blink_cursor(pte);
3042 show_main_page(pte);
3046 pte->size_buff_entry = 0;
3047 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
3048 send_blink_cursor(pte);
3049 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
3055 static int ReformatNumber(char *number)
3057 int pos = 0, i = 0, size = strlen(number);
3059 for (; i < size; i++) {
3060 if ((number[i] >= '0') && (number[i] <= '9')) {
3065 number[pos] = number[i];
3073 static void show_entry_history(struct unistimsession *pte, FILE ** f)
3075 char line[TEXT_LENGTH_MAX + 1], status[STATUS_LENGTH_MAX + 1], func1[10], func2[10],
3078 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
3079 display_last_error("Can't read history date entry");
3083 line[sizeof(line) - 1] = '\0';
3084 send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
3085 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
3086 display_last_error("Can't read callerid entry");
3090 line[sizeof(line) - 1] = '\0';
3091 ast_copy_string(pte->device->lst_cid, line, sizeof(pte->device->lst_cid));
3092 send_text(TEXT_LINE1, TEXT_NORMAL, pte, line);
3093 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
3094 display_last_error("Can't read callername entry");
3098 line[sizeof(line) - 1] = '\0';
3099 send_text(TEXT_LINE2, TEXT_NORMAL, pte, line);
3102 snprintf(line, sizeof(line), "Call %03d/%03d", pte->buff_entry[2],
3103 pte->buff_entry[1]);
3104 send_texttitle(pte, line);
3106 if (pte->buff_entry[2] == 1)
3109 strcpy(func1, "Prvious");
3110 if (pte->buff_entry[2] >= pte->buff_entry[1])
3113 strcpy(func2, "Next ");
3114 if (ReformatNumber(pte->device->lst_cid))
3115 strcpy(func3, "Redial ");
3118 snprintf(status, sizeof(status), "%s%s%sCancel", func1, func2, func3);
3119 send_text_status(pte, status);
3122 static char OpenHistory(struct unistimsession *pte, char way, FILE ** f)
3124 char tmp[AST_CONFIG_MAX_PATH];
3127 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
3128 USTM_LOG_DIR, pte->device->name, way);
3129 *f = fopen(tmp, "r");
3131 display_last_error("Unable to open history file");
3134 if (fread(&count, 1, 1, *f) != 1) {
3135 display_last_error("Unable to read history header - display.");
3139 if (count > MAX_ENTRY_LOG) {
3140 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
3141 count, MAX_ENTRY_LOG);
3148 static void show_history(struct unistimsession *pte, char way)
3155 if (!pte->device->callhistory)
3157 count = OpenHistory(pte, way, &f);
3160 pte->buff_entry[0] = way;
3161 pte->buff_entry[1] = count;
3162 pte->buff_entry[2] = 1;
3163 show_entry_history(pte, &f);
3164 pte->state = STATE_HISTORY;
3167 static void show_main_page(struct unistimsession *pte)
3169 char tmpbuf[TEXT_LENGTH_MAX + 1];
3172 if ((pte->device->extension == EXTENSION_ASK) &&
3173 (ast_strlen_zero(pte->device->extension_number))) {
3174 ShowExtensionPage(pte);
3178 pte->state = STATE_MAINPAGE;
3180 send_tone(pte, 0, 0);
3181 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON_DISCRET);
3182 pte->device->lines->lastmsgssent = 0;
3183 send_favorite(pte->device->softkeylinepos, FAV_ICON_ONHOOK_BLACK, pte,
3184 pte->device->softkeylabel[pte->device->softkeylinepos]);
3185 if (!ast_strlen_zero(pte->device->call_forward)) {
3186 if (pte->device->height == 1) {
3187 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Forwarding ON");
3189 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Call forwarded to :");
3190 send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->call_forward);
3192 Sendicon(TEXT_LINE0, FAV_ICON_REFLECT + FAV_BLINK_SLOW, pte);
3193 send_text_status(pte, "Dial Redial NoForwd");
3195 if ((pte->device->extension == EXTENSION_ASK) ||
3196 (pte->device->extension == EXTENSION_TN))
3197 send_text_status(pte, "Dial Redial ForwardUnregis");
3199 send_text_status(pte, "Dial Redial Forward");
3201 send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->maintext1);
3202 if (pte->device->missed_call == 0)
3203 send_text(TEXT_LINE0, TEXT_NORMAL, pte, pte->device->maintext0);
3205 sprintf(tmpbuf, "%d unanswered call(s)", pte->device->missed_call);
3206 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpbuf);
3207 Sendicon(TEXT_LINE0, FAV_ICON_CALL_CENTER + FAV_BLINK_SLOW, pte);
3210 if (ast_strlen_zero(pte->device->maintext2)) {
3211 strcpy(tmpbuf, "IP : ");
3212 strcat(tmpbuf, ast_inet_ntoa(pte->sin.sin_addr));
3213 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
3215 send_text(TEXT_LINE2, TEXT_NORMAL, pte, pte->device->maintext2);
3216 send_texttitle(pte, pte->device->titledefault);
3217 change_favorite_icon(pte, FAV_ICON_ONHOOK_BLACK);
3220 static void key_main_page(struct unistimsession *pte, char keycode)
3222 if (pte->device->missed_call) {
3223 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
3224 pte->device->missed_call = 0;
3226 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
3227 handle_dial_page(pte);
3228 key_dial_page(pte, keycode);
3233 handle_dial_page(pte);
3236 if (ast_strlen_zero(pte->device->redial_number))
3238 if ((pte->device->output == OUTPUT_HANDSET) &&
3239 (pte->device->receiver_state == STATE_ONHOOK))
3240 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
3242 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
3244 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
3245 sizeof(pte->device->phone_number));
3246 HandleCallOutgoing(pte);
3249 if (!ast_strlen_zero(pte->device->call_forward)) {
3250 /* Cancel call forwarding */
3251 memmove(pte->device->call_forward + 1, pte->device->call_forward,
3252 sizeof(pte->device->call_forward));
3253 pte->device->call_forward[0] = '\0';
3254 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
3255 pte->device->output = OUTPUT_HANDSET; /* Seems to be reseted somewhere */
3256 show_main_page(pte);
3259 pte->device->call_forward[0] = -1;
3260 handle_dial_page(pte);
3263 if (pte->device->extension == EXTENSION_ASK) {
3264 UnregisterExtension(pte);
3265 pte->device->extension_number[0] = '\0';
3266 ShowExtensionPage(pte);
3267 } else if (pte->device->extension == EXTENSION_TN) {
3268 ast_mutex_lock(&devicelock);
3269 strcpy(pte->device->id, pte->device->extension_number);
3270 pte->buff_entry[0] = '\0';
3271 pte->size_buff_entry = 0;
3272 pte->device->session = NULL;
3274 ast_mutex_unlock(&devicelock);
3275 ShowExtensionPage(pte);
3279 handle_dial_page(pte);
3286 if ((pte->device->output == OUTPUT_HANDSET) &&
3287 (pte->device->receiver_state == STATE_ONHOOK))
3288 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
3290 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
3291 Keyfavorite(pte, keycode);
3294 HandleSelectCodec(pte);
3297 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
3298 handle_dial_page(pte);
3301 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
3302 handle_dial_page(pte);
3305 show_history(pte, 'o');
3308 show_history(pte, 'i');
3314 static void key_history(struct unistimsession *pte, char keycode)
3324 if (pte->buff_entry[2] <= 1)
3326 pte->buff_entry[2]--;
3327 count = OpenHistory(pte, pte->buff_entry[0], &f);
3330 offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
3331 if (fseek(f, offset, SEEK_CUR)) {
3332 display_last_error("Unable to seek history entry.");
3336 show_entry_history(pte, &f);
3341 if (pte->buff_entry[2] >= pte->buff_entry[1])
3343 pte->buff_entry[2]++;
3344 count = OpenHistory(pte, pte->buff_entry[0], &f);
3347 offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
3348 if (fseek(f, offset, SEEK_CUR)) {
3349 display_last_error("Unable to seek history entry.");
3353 show_entry_history(pte, &f);
3356 if (!ReformatNumber(pte->device->lst_cid))
3358 ast_copy_string(pte->device->redial_number, pte->device->lst_cid,
3359 sizeof(pte->device->redial_number));
3360 key_main_page(pte, KEY_FUNC2);
3364 show_main_page(pte);
3367 if (pte->buff_entry[0] == 'i')
3368 show_history(pte, 'o');
3370 show_main_page(pte);
3373 if (pte->buff_entry[0] == 'i')
3374 show_main_page(pte);
3376 show_history(pte, 'i');
3382 static void init_phone_step2(struct unistimsession *pte)
3386 ast_verb(0, "Sending S4\n");
3387 memcpy(buffsend + SIZE_HEADER, packet_send_s4, sizeof(packet_send_s4));
3388 send_client(SIZE_HEADER + sizeof(packet_send_s4), buffsend, pte);
3389 send_date_time2(pte);
3390 send_date_time3(pte);
3392 ast_verb(0, "Sending S7\n");
3393 memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
3394 send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
3396 ast_verb(0, "Sending Contrast\n");
3397 memcpy(buffsend + SIZE_HEADER, packet_send_Contrast, sizeof(packet_send_Contrast));
3398 if (pte->device != NULL)
3399 buffsend[9] = pte->device->contrast;
3400 send_client(SIZE_HEADER + sizeof(packet_send_Contrast), buffsend, pte);
3403 ast_verb(0, "Sending S9\n");
3404 memcpy(buffsend + SIZE_HEADER, packet_send_s9, sizeof(packet_send_s9));
3405 send_client(SIZE_HEADER + sizeof(packet_send_s9), buffsend, pte);
3409 ast_verb(0, "Sending S7\n");
3410 memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
3411 send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
3412 send_led_update(pte, 0);
3414 if (pte->state < STATE_MAINPAGE) {
3415 if (autoprovisioning == AUTOPROVISIONING_TN) {
3416 ShowExtensionPage(pte);
3422 for (i = 1; i < 6; i++)
3423 send_favorite(i, 0, pte, "");
3424 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Sorry, this phone is not");
3425 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "registered in unistim.cfg");
3426 strcpy(tmp, "MAC = ");
3427 strcat(tmp, pte->macaddr);
3428 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
3429 send_text_status(pte, "");
3430 send_texttitle(pte, "UNISTIM for*");
3434 show_main_page(pte);
3435 refresh_all_favorite(pte);
3437 ast_verb(0, "Sending arrow\n");
3438 memcpy(buffsend + SIZE_HEADER, packet_send_arrow, sizeof(packet_send_arrow));
3439 send_client(SIZE_HEADER + sizeof(packet_send_arrow), buffsend, pte);