chan_unistim.c File Reference

chan_unistim channel driver for Asterisk More...

#include "asterisk.h"
#include <sys/stat.h>
#include <signal.h>
#include "asterisk/paths.h"
#include "asterisk/network.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/netsock2.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/causes.h"
#include "asterisk/indications.h"
#include "asterisk/pickup.h"
#include "asterisk/astobj2.h"
#include "asterisk/astdb.h"
#include "asterisk/features_config.h"
#include "asterisk/bridge.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/format_cache.h"

Include dependency graph for chan_unistim.c:

Go to the source code of this file.

Data Structures

struct  unistim_device
 A device containing one or more lines. More...
struct  unistim_languages
struct  unistim_line
struct  unistim_menu_item
struct  unistim_subchannel
struct  unistimsession
struct  ustm_lang_entry
struct  wsabuf

Defines

#define AST_CONFIG_MAX_PATH   255
#define BUFFSEND   unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }
#define DEBUG_TIMER   dummy
#define DEFAULT_CODEC   0x00
#define DEFAULT_INTERDIGIT_TIMER   4000
#define DEFAULTCALLERID   "Unknown"
#define DEFAULTCALLERNAME   " "
#define DEFAULTCONTEXT   "default"
#define DEFAULTHEIGHT   3
#define DEVICE_NAME_LEN   16
#define EXPNUM   24
#define FAV_BLINK_FAST   0x20
#define FAV_BLINK_SLOW   0x40
#define FAV_ICON_BOX   0x3F
#define FAV_ICON_CALL_CENTER   0x34
#define FAV_ICON_CITY   0x31
#define FAV_ICON_COMPUTER   0x38
#define FAV_ICON_FAX   0x35
#define FAV_ICON_FORWARD   0x39
#define FAV_ICON_HEADPHONES   0x2E
#define FAV_ICON_HEADPHONES_ONHOLD   0x2F
#define FAV_ICON_HOME   0x30
#define FAV_ICON_INBOX   0x3C
#define FAV_ICON_LOCKED   0x3A
#define FAV_ICON_MAILBOX   0x36
#define FAV_ICON_MEETING   0x3E
#define FAV_ICON_NONE   0x00
#define FAV_ICON_OFFHOOK_BLACK   0x24
#define FAV_ICON_OFFHOOK_WHITE   0x25
#define FAV_ICON_ONHOLD_BLACK   0x26
#define FAV_ICON_ONHOLD_WHITE   0x27
#define FAV_ICON_ONHOOK_BLACK   0x20
#define FAV_ICON_ONHOOK_WHITE   0x21
#define FAV_ICON_OUTBOX   0x3D
#define FAV_ICON_PAGER   0x33
#define FAV_ICON_PHONE_BLACK   0x2A
#define FAV_ICON_PHONE_WHITE   0x2B
#define FAV_ICON_REFLECT   0x37
#define FAV_ICON_SHARP   0x32
#define FAV_ICON_SPEAKER_OFFHOOK_BLACK   0x28
#define FAV_ICON_SPEAKER_OFFHOOK_WHITE   0x29
#define FAV_ICON_SPEAKER_ONHOLD_BLACK   0x2C
#define FAV_ICON_SPEAKER_ONHOLD_WHITE   0x2D
#define FAV_ICON_SPEAKER_ONHOOK_BLACK   0x22
#define FAV_ICON_SPEAKER_ONHOOK_WHITE   0x23
#define FAV_ICON_TRASH   0x3B
#define FAV_LINE_ICON   FAV_ICON_ONHOOK_BLACK
#define FAV_MAX_LENGTH   0x0A
#define FAVNUM   6
#define IDLE_WAIT   1000
#define LED_BAR_OFF   0x00
#define LED_BAR_ON   0x01
#define LED_BAR_P2   0x02
#define LED_BAR_P3   0x03
#define LED_BAR_P4   0x04
#define LED_BAR_P5   0x05
#define LED_BAR_P6   0x06
#define LED_BAR_P7   0x07
#define LED_HEADPHONE_OFF   0x010
#define LED_HEADPHONE_ON   0x011
#define LED_MUTE_OFF   0x018
#define LED_MUTE_ON   0x019
#define LED_SPEAKER_OFF   0x08
#define LED_SPEAKER_ON   0x09
#define MAX_BUF_NUMBER   150
#define MAX_BUF_SIZE   64
#define MAX_ENTRY_LOG   30
#define MAX_SCREEN_NUMBER   15
#define MONTH_LABEL_SIZE   3
#define MUTE_OFF   0x00
#define MUTE_ON   0xFF
#define MUTE_ON_DISCRET   0xCE
#define NB_MAX_RETRANSMIT   8
#define OUTPUT_HANDSET   0xC0
#define OUTPUT_HEADPHONE   0xC1
#define OUTPUT_SPEAKER   0xC2
#define RETRANSMIT_TIMER   2000
#define SELECTCODEC_MAX_LENGTH   2
#define SELECTCODEC_MSG   "Codec number : .."
#define SELECTCODEC_START_ENTRY_POS   15
#define SELECTEXTENSION_MAX_LENGTH   10
#define SELECTEXTENSION_MSG   ".........."
#define SELECTEXTENSION_START_ENTRY_POS   0
#define SIZE_HEADER   6
#define SIZE_MAC_ADDR   17
#define SIZE_PAGE   4096
#define STATUS_LENGTH_MAX   28
#define SUB_ONHOLD   3
#define SUB_REAL   0
#define SUB_RING   1
#define SUB_THREEWAY   2
#define TEXT_INVERSE   0x25
#define TEXT_LENGTH_MAX   24
#define TEXT_LINE0   0x00
#define TEXT_LINE1   0x20
#define TEXT_LINE2   0x40
#define TEXT_NORMAL   0x05
#define TIMER_MWI   5000
#define USTM_LANG_DIR   "unistimLang"
#define USTM_LOG_DIR   "unistimHistory"
#define VOLUME_INSANELY_LOUD   0x07
#define VOLUME_LOW   0x01
#define VOLUME_LOW_SPEAKER   0x03
#define VOLUME_NORMAL   0x02

Enumerations

enum  autoprov_extn { EXTENSION_NONE = 0, EXTENSION_ASK, EXTENSION_LINE, EXTENSION_TN }
enum  autoprovision { AUTOPROVISIONING_NO = 0, AUTOPROVISIONING_YES, AUTOPROVISIONING_TN }
enum  charset {
  LANG_DEFAULT, ISO_8859_1, ISO_8859_2, ISO_8859_4,
  ISO_8859_5, ISO_2022_JP
}
enum  handset_state { STATE_ONHOOK, STATE_OFFHOOK }
enum  phone_key {
  KEY_0 = 0x40, KEY_1 = 0x41, KEY_2 = 0x42, KEY_3 = 0x43,
  KEY_4 = 0x44, KEY_5 = 0x45, KEY_6 = 0x46, KEY_7 = 0x47,
  KEY_8 = 0x48, KEY_9 = 0x49, KEY_STAR = 0x4a, KEY_SHARP = 0x4b,
  KEY_UP = 0x4c, KEY_DOWN = 0x4d, KEY_RIGHT = 0x4e, KEY_LEFT = 0x4f,
  KEY_QUIT = 0x50, KEY_COPY = 0x51, KEY_FUNC1 = 0x54, KEY_FUNC2 = 0x55,
  KEY_FUNC3 = 0x56, KEY_FUNC4 = 0x57, KEY_ONHOLD = 0x5b, KEY_HANGUP = 0x5c,
  KEY_MUTE = 0x5d, KEY_HEADPHN = 0x5e, KEY_LOUDSPK = 0x5f, KEY_FAV0 = 0x60,
  KEY_FAV1 = 0x61, KEY_FAV2 = 0x62, KEY_FAV3 = 0x63, KEY_FAV4 = 0x64,
  KEY_FAV5 = 0x65, KEY_COMPUTR = 0x7b, KEY_CONF = 0x7c, KEY_SNDHIST = 0x7d,
  KEY_RCVHIST = 0x7e, KEY_INDEX = 0x7f
}
enum  phone_state {
  STATE_INIT, STATE_AUTHDENY, STATE_MAINPAGE, STATE_EXTENSION,
  STATE_DIALPAGE, STATE_RINGING, STATE_CALL, STATE_SELECTOPTION,
  STATE_SELECTCODEC, STATE_SELECTLANGUAGE, STATE_CLEANING, STATE_HISTORY
}

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int attempt_transfer (struct unistim_subchannel *p1, struct unistim_subchannel *p2)
static struct unistim_devicebuild_device (const char *cat, const struct ast_variable *v)
static void change_callerid (struct unistimsession *pte, int type, char *callerid)
static void change_favorite_icon (struct unistimsession *pte, unsigned char status)
static struct unistimsessionchannel_to_session (struct ast_channel *ast)
static void check_send_queue (struct unistimsession *pte)
static void close_call (struct unistimsession *pte)
static void close_client (struct unistimsession *s)
static char * control2str (int ind)
static struct unistimsessioncreate_client (const struct sockaddr_in *addr_from)
static void discard_call (struct unistimsession *pte)
static void display_last_error (const char *sz_msg)
static void * do_monitor (void *data)
static void dummy (char *unused,...)
static int find_language (const char *)
static struct unistim_linefind_line_by_number (struct unistim_device *d, const char *val)
static int find_rtp_port (struct unistim_subchannel *s)
static struct unistim_subchannelfind_subchannel_by_name (const char *dest)
static void finish_bookmark (void)
static int get_active_softkey (struct unistimsession *pte)
static int get_avail_softkey (struct unistimsession *pte, const char *name)
static struct unistim_subchannelget_sub (struct unistim_device *device, int type)
static unsigned int get_tick_count (void)
static int get_to_address (int fd, struct sockaddr_in *toAddr)
static void handle_call_incoming (struct unistimsession *s)
static void handle_call_outgoing (struct unistimsession *s)
static void handle_dial_page (struct unistimsession *pte)
static void handle_key_fav (struct unistimsession *pte, char keycode)
static void handle_select_codec (struct unistimsession *)
static void handle_select_language (struct unistimsession *)
static void handle_select_option (struct unistimsession *pte)
static void ignore_call (struct unistimsession *pte)
static void in_band_indication (struct ast_channel *ast, const struct ast_tone_zone *tz, const char *indication)
static void init_phone_step2 (struct unistimsession *pte)
static int is_key_favorite (struct unistim_device *d, int fav)
static int is_key_line (struct unistim_device *d, int fav)
static void key_call (struct unistimsession *pte, char keycode)
static void key_dial_page (struct unistimsession *pte, char keycode)
static void key_favorite (struct unistimsession *, char)
static void key_history (struct unistimsession *pte, char keycode)
static void key_main_page (struct unistimsession *pte, char keycode)
static void key_ringing (struct unistimsession *pte, char keycode)
static void key_select_codec (struct unistimsession *pte, char keycode)
static void key_select_extension (struct unistimsession *pte, char keycode)
static void key_select_language (struct unistimsession *pte, char keycode)
static void key_select_option (struct unistimsession *pte, char keycode)
static int lang_cmp_fn (void *obj, void *arg, int flags)
static int lang_hash_fn (const void *obj, const int flags)
static int load_module (void)
static void microphone_mute_toggle (struct unistimsession *pte)
static char open_history (struct unistimsession *pte, char way, FILE **f)
static int parse_bookmark (const char *text, struct unistim_device *d)
static void parsing (int size, unsigned char *buf, struct unistimsession *pte, struct sockaddr_in *addr_from)
static void process_request (int size, unsigned char *buf, struct unistimsession *pte)
static const char * ptestate_tostr (const int type)
static void rcv_mac_addr (struct unistimsession *pte, const unsigned char *buf)
static void rcv_resume_connection_with_server (struct unistimsession *pte)
static void refresh_all_favorite (struct unistimsession *pte)
static int register_extension (const struct unistimsession *pte)
static int reload (void)
static int reload_config (void)
static int restart_monitor (void)
static void send_blink_cursor (struct unistimsession *pte)
static void send_callerid_screen (struct unistimsession *, struct unistim_subchannel *)
static void send_charset_update (struct unistimsession *pte, int charset)
static void send_client (int size, const unsigned char *data, struct unistimsession *pte)
static void send_cursor_pos (struct unistimsession *pte, unsigned char pos)
static void send_date_time (struct unistimsession *pte)
static void send_date_time2 (struct unistimsession *pte)
static void send_date_time3 (struct unistimsession *pte)
static void send_dial_tone (struct unistimsession *pte)
static void send_end_call (struct unistimsession *pte)
static void send_expansion_icon (unsigned char pos, unsigned char status, struct unistimsession *pte)
static void send_expansion_next (struct unistimsession *pte)
static void send_expansion_short (unsigned char pos, unsigned char status, struct unistimsession *pte)
static void send_expansion_text (unsigned char pos, struct unistimsession *pte, const char *text)
static void send_favorite (unsigned char pos, unsigned char status, struct unistimsession *pte, const char *text)
static void send_favorite_selected (unsigned char status, struct unistimsession *pte)
static void send_favorite_short (unsigned char pos, unsigned char status, struct unistimsession *pte)
static void send_icon (unsigned char pos, unsigned char status, struct unistimsession *pte)
static void send_idle_clock (struct unistimsession *pte)
static void send_led_update (struct unistimsession *pte, unsigned char led)
static void send_month_labels (struct unistimsession *pte, int month)
static void send_mute (struct unistimsession *pte, unsigned char mute)
static void send_no_ring (struct unistimsession *pte)
static void send_ping (struct unistimsession *pte)
static void send_raw_client (int size, const unsigned char *data, struct sockaddr_in *addr_to, const struct sockaddr_in *addr_ourip)
static int send_retransmit (struct unistimsession *pte)
static void send_ring (struct unistimsession *pte, char volume, char style)
static void send_select_output (struct unistimsession *pte, unsigned char output, unsigned char volume, unsigned char mute)
static void send_start_rtp (struct unistim_subchannel *)
static void send_start_timer (struct unistimsession *pte)
static void send_stop_timer (struct unistimsession *pte)
static void send_text (unsigned char pos, unsigned char inverse, struct unistimsession *pte, const char *text)
static void send_text_status (struct unistimsession *pte, const char *text)
static void send_texttitle (struct unistimsession *pte, const char *text)
static void send_tone (struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
static void set_ping_timer (struct unistimsession *pte)
static void show_entry_history (struct unistimsession *pte, FILE **f)
static void show_extension_page (struct unistimsession *pte)
static void show_history (struct unistimsession *pte, char way)
static void show_main_page (struct unistimsession *pte)
static void show_phone_number (struct unistimsession *pte)
static int soft_key_visible (struct unistim_device *d, unsigned char num)
static void start_rtp (struct unistim_subchannel *sub)
static void sub_hold (struct unistimsession *pte, struct unistim_subchannel *sub)
static void sub_start_silence (struct unistimsession *pte, struct unistim_subchannel *sub)
static void sub_stop_silence (struct unistimsession *pte, struct unistim_subchannel *sub)
static void sub_unhold (struct unistimsession *pte, struct unistim_subchannel *sub)
static const char * subtype_tostr (const int type)
static void swap_subs (struct unistim_subchannel *a, struct unistim_subchannel *b)
static void transfer_call_step1 (struct unistimsession *pte)
static void transfer_cancel_step2 (struct unistimsession *pte)
static struct unistim_subchannelunistim_alloc_sub (struct unistim_device *d, int x)
static int unistim_answer (struct ast_channel *ast)
static int unistim_call (struct ast_channel *ast, const char *dest, int timeout)
static char * unistim_do_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int unistim_do_senddigit (struct unistimsession *pte, char digit)
static int unistim_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static int unistim_free_sub (struct unistim_subchannel *)
static enum ast_rtp_glue_result unistim_get_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance)
static int unistim_hangup (struct ast_channel *ast)
static int unistim_hangup_clean (struct ast_channel *ast, struct unistim_subchannel *sub)
static int unistim_indicate (struct ast_channel *ast, int ind, const void *data, size_t datalen)
static struct unistim_lineunistim_line_alloc (void)
static void unistim_line_copy (struct unistim_line *dst, struct unistim_line *src)
static struct unistim_lineunistim_line_destroy (struct unistim_line *l)
static struct ast_channelunistim_new (struct unistim_subchannel *sub, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
static struct ast_frameunistim_read (struct ast_channel *ast)
static int unistim_register (struct unistimsession *s)
static char * unistim_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 --- unistim_reload: Force reload of module from cli --- Runs in the asterisk main thread, so don't do anything useful but setting a flag and waiting for do_monitor to do the job in our thread
static struct ast_channelunistim_request (const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *dest, int *cause)
static struct ast_frameunistim_rtp_read (const struct ast_channel *ast, const struct unistim_subchannel *sub)
static int unistim_send_mwi_to_peer (struct unistim_line *peer, unsigned int tick)
static int unistim_senddigit_begin (struct ast_channel *ast, char digit)
static int unistim_senddigit_end (struct ast_channel *ast, char digit, unsigned int duration)
static int unistim_sendtext (struct ast_channel *ast, const char *text)
static void unistim_set_owner (struct unistim_subchannel *sub, struct ast_channel *chan)
static int unistim_set_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *codecs, int nat_active)
static char * unistim_show_devices (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * unistim_show_info (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * unistim_sp (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void * unistim_ss (void *data)
static int unistim_unalloc_sub (struct unistim_device *d, struct unistim_subchannel *sub)
static int unistim_write (struct ast_channel *ast, struct ast_frame *frame)
static int unistimsock_read (int *id, int fd, short events, void *ignore)
static int unload_module (void)
static void unquote (char *out, const char *src, int maxlen)
static int unregister_extension (const struct unistimsession *pte)
static const char * ustmtext (const char *str, struct unistimsession *pte)
static int write_entry_history (struct unistimsession *pte, FILE *f, char c, char *line1)
static int write_history (struct unistimsession *pte, char way, char ismissed)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "UNISTIM Protocol (USTM)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, }
static struct ast_module_infoast_module_info = &__mod_info
static enum autoprovision autoprovisioning = AUTOPROVISIONING_NO
static unsigned char * buff
static const char channel_type [] = "USTM"
static struct ast_jb_conf default_jbconf
 Global jitterbuffer configuration - by default, jb is disabled.
static ast_mutex_t devicelock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
static struct unistim_devicedevices
 A device containing one or more lines.
static const float dtmf_col [] = { 1209, 1336, 1477, 1633 }
static const int dtmf_row [] = { 697, 770, 852, 941 }
struct ast_format_capglobal_cap
static struct ast_jb_conf global_jbconf
static struct io_contextio
static pthread_t monitor_thread = AST_PTHREADT_NULL
static ast_mutex_t monlock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
static unsigned char monthlabels []
static struct unistim_languages options_languages []
static struct unistim_menu_item options_menu []
static const unsigned char packet_rcv_discovery []
static const unsigned char packet_recv_expansion_pressed_key []
static const unsigned char packet_recv_firm_version []
static const unsigned char packet_recv_hangup []
static const unsigned char packet_recv_it_type []
static const unsigned char packet_recv_mac_addr []
static const unsigned char packet_recv_pick_up []
static const unsigned char packet_recv_pressed_key []
static const unsigned char packet_recv_r2 [] = { 0x00, 0x00, 0x00, 0x13, 0x96, 0x03, 0x03 }
static const unsigned char packet_recv_resume_connection_with_server []
static const unsigned char packet_send_arrow [] = { 0x17, 0x04, 0x04, 0x00 }
static const unsigned char packet_send_blink_cursor [] = { 0x17, 0x04, 0x10, 0x86 }
static const unsigned char packet_send_call []
static const unsigned char packet_send_charset_iso_2022_jp []
static const unsigned char packet_send_charset_iso_8859_1 []
static const unsigned char packet_send_charset_iso_8859_2 []
static const unsigned char packet_send_charset_iso_8859_4 []
static const unsigned char packet_send_charset_iso_8859_5 []
static const unsigned char packet_send_CloseAudioStreamRX [] = { 0x16, 0x05, 0x31, 0x00, 0xff }
static const unsigned char packet_send_CloseAudioStreamTX [] = { 0x16, 0x05, 0x31, 0xff, 0x00 }
static const unsigned char packet_send_Contrast []
static const unsigned char packet_send_date_time []
static const unsigned char packet_send_date_time2 []
static const unsigned char packet_send_date_time3 []
static const unsigned char packet_send_discovery_ack []
static const unsigned char packet_send_end_call []
static const unsigned char packet_send_expansion_icon [] = { 0x09, 0x06, 0x59, 0x05, 0x47, 0x20 }
static const unsigned char packet_send_expansion_next [] = { 0x09, 0x03, 0x17 }
static const unsigned char packet_send_expansion_text []
static const unsigned char packet_send_favorite []
static const unsigned char packet_send_icon [] = { 0x17, 0x05, 0x14, 0x00, 0x25 }
static const unsigned char packet_send_jitter_buffer_conf []
static const unsigned char packet_send_led_update [] = { 0x19, 0x04, 0x00, 0x00 }
static unsigned char packet_send_monthlabels_download []
static const unsigned char packet_send_mute [] = { 0x16, 0x05, 0x04, 0x00, 0x00 }
static const unsigned char packet_send_no_ring []
static const unsigned char packet_send_open_audio_stream_rx []
static const unsigned char packet_send_open_audio_stream_rx3 []
static const unsigned char packet_send_open_audio_stream_tx []
static const unsigned char packet_send_open_audio_stream_tx3 []
static unsigned char packet_send_ping []
static const unsigned char packet_send_query_basic_manager_04 [] = { 0x1a, 0x04, 0x01, 0x04 }
static const unsigned char packet_send_query_basic_manager_10 [] = { 0x1a, 0x04, 0x01, 0x10 }
static const unsigned char packet_send_query_mac_address [] = { 0x1a, 0x04, 0x01, 0x08 }
static const unsigned char packet_send_ring []
static const unsigned char packet_send_rtp_packet_size []
static const unsigned char packet_send_S1 [] = { 0x1a, 0x07, 0x07, 0x00, 0x00, 0x00, 0x13 }
static const unsigned char packet_send_s4 []
static const unsigned char packet_send_S7 [] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 }
static const unsigned char packet_send_s9 []
static const unsigned char packet_send_select_output []
static const unsigned char packet_send_set_pos_cursor []
static const unsigned char packet_send_start_timer []
static const unsigned char packet_send_status []
static const unsigned char packet_send_status2 []
static const unsigned char packet_send_stop_timer [] = { 0x17, 0x05, 0x0b, 0x02, 0x00 }
static const unsigned char packet_send_stream_based_tone_dial_freq []
static const unsigned char packet_send_stream_based_tone_off []
static const unsigned char packet_send_stream_based_tone_on []
static const unsigned char packet_send_stream_based_tone_single_freq []
static const unsigned char packet_send_text []
static const unsigned char packet_send_title []
static struct sockaddr_in public_ip = { 0, }
struct {
   unsigned int   cos
   unsigned int   cos_audio
   unsigned int   tos
   unsigned int   tos_audio
qos
static struct ast_sched_contextsched
static ast_mutex_t sessionlock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
static struct unistimsessionsessions
static const char tdesc [] = "UNISTIM Channel Driver"
static struct ast_cli_entry unistim_cli []
static int unistim_keepalive
static int unistim_port
static ast_mutex_t unistim_reload_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
static int unistim_reloading = 0
static struct ast_rtp_glue unistim_rtp_glue
static struct ast_channel_tech unistim_tech
static int unistimdebug = 0
static int unistimsock = -1
static char ustm_strcopy [1024]


Detailed Description

chan_unistim channel driver for Asterisk

Author:
Cedric Hans <cedric.hans@mlkj.net>
Unistim (Unified Networks IP Stimulus) channel driver for Nortel i2002, i2004 and i2050

Definition in file chan_unistim.c.


Define Documentation

#define AST_CONFIG_MAX_PATH   255

Definition at line 113 of file chan_unistim.c.

Referenced by open_history(), and write_history().

#define BUFFSEND   unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }

#define DEBUG_TIMER   dummy

Definition at line 241 of file chan_unistim.c.

Referenced by do_monitor(), and set_ping_timer().

#define DEFAULT_CODEC   0x00

Not used

Definition at line 110 of file chan_unistim.c.

Referenced by key_select_extension(), and unistim_register().

#define DEFAULT_INTERDIGIT_TIMER   4000

Timeout value for entered number being dialed

Definition at line 107 of file chan_unistim.c.

Referenced by build_device().

#define DEFAULTCALLERID   "Unknown"

Definition at line 84 of file chan_unistim.c.

Referenced by send_callerid_screen().

#define DEFAULTCALLERNAME   " "

Definition at line 85 of file chan_unistim.c.

Referenced by send_callerid_screen().

#define DEFAULTCONTEXT   "default"

Definition at line 83 of file chan_unistim.c.

Referenced by build_device().

#define DEFAULTHEIGHT   3

Definition at line 86 of file chan_unistim.c.

Referenced by build_device().

#define DEVICE_NAME_LEN   16

Definition at line 112 of file chan_unistim.c.

#define EXPNUM   24

Definition at line 217 of file chan_unistim.c.

Referenced by refresh_all_favorite().

#define FAV_BLINK_FAST   0x20

Definition at line 211 of file chan_unistim.c.

Referenced by unistim_call().

#define FAV_BLINK_SLOW   0x40

Definition at line 212 of file chan_unistim.c.

Referenced by show_main_page(), and sub_hold().

#define FAV_ICON_BOX   0x3F

Definition at line 209 of file chan_unistim.c.

#define FAV_ICON_CALL_CENTER   0x34

Definition at line 198 of file chan_unistim.c.

Referenced by show_main_page().

#define FAV_ICON_CITY   0x31

Definition at line 195 of file chan_unistim.c.

#define FAV_ICON_COMPUTER   0x38

Definition at line 202 of file chan_unistim.c.

#define FAV_ICON_FAX   0x35

Definition at line 199 of file chan_unistim.c.

#define FAV_ICON_FORWARD   0x39

Definition at line 203 of file chan_unistim.c.

#define FAV_ICON_HEADPHONES   0x2E

Definition at line 192 of file chan_unistim.c.

Referenced by send_select_output().

#define FAV_ICON_HEADPHONES_ONHOLD   0x2F

Definition at line 193 of file chan_unistim.c.

Referenced by send_select_output().

#define FAV_ICON_HOME   0x30

Definition at line 194 of file chan_unistim.c.

#define FAV_ICON_INBOX   0x3C

Definition at line 206 of file chan_unistim.c.

#define FAV_ICON_LOCKED   0x3A

Definition at line 204 of file chan_unistim.c.

#define FAV_ICON_MAILBOX   0x36

Definition at line 200 of file chan_unistim.c.

#define FAV_ICON_MEETING   0x3E

Definition at line 208 of file chan_unistim.c.

#define FAV_ICON_NONE   0x00

#define FAV_ICON_OFFHOOK_BLACK   0x24

#define FAV_ICON_OFFHOOK_WHITE   0x25

Definition at line 183 of file chan_unistim.c.

#define FAV_ICON_ONHOLD_BLACK   0x26

Definition at line 184 of file chan_unistim.c.

Referenced by send_select_output(), and sub_hold().

#define FAV_ICON_ONHOLD_WHITE   0x27

Definition at line 185 of file chan_unistim.c.

#define FAV_ICON_ONHOOK_BLACK   0x20

Definition at line 178 of file chan_unistim.c.

#define FAV_ICON_ONHOOK_WHITE   0x21

Definition at line 179 of file chan_unistim.c.

#define FAV_ICON_OUTBOX   0x3D

Definition at line 207 of file chan_unistim.c.

#define FAV_ICON_PAGER   0x33

Definition at line 197 of file chan_unistim.c.

#define FAV_ICON_PHONE_BLACK   0x2A

Definition at line 188 of file chan_unistim.c.

Referenced by handle_dial_page().

#define FAV_ICON_PHONE_WHITE   0x2B

Definition at line 189 of file chan_unistim.c.

#define FAV_ICON_REFLECT   0x37

Definition at line 201 of file chan_unistim.c.

Referenced by show_main_page().

#define FAV_ICON_SHARP   0x32

Definition at line 196 of file chan_unistim.c.

Referenced by parse_bookmark().

#define FAV_ICON_SPEAKER_OFFHOOK_BLACK   0x28

Definition at line 186 of file chan_unistim.c.

Referenced by send_select_output().

#define FAV_ICON_SPEAKER_OFFHOOK_WHITE   0x29

Definition at line 187 of file chan_unistim.c.

#define FAV_ICON_SPEAKER_ONHOLD_BLACK   0x2C

Definition at line 190 of file chan_unistim.c.

Referenced by send_select_output().

#define FAV_ICON_SPEAKER_ONHOLD_WHITE   0x2D

Definition at line 191 of file chan_unistim.c.

#define FAV_ICON_SPEAKER_ONHOOK_BLACK   0x22

Definition at line 180 of file chan_unistim.c.

Referenced by send_select_output(), and unistim_call().

#define FAV_ICON_SPEAKER_ONHOOK_WHITE   0x23

Definition at line 181 of file chan_unistim.c.

Referenced by refresh_all_favorite().

#define FAV_ICON_TRASH   0x3B

Definition at line 205 of file chan_unistim.c.

#define FAV_LINE_ICON   FAV_ICON_ONHOOK_BLACK

#define FAV_MAX_LENGTH   0x0A

Definition at line 214 of file chan_unistim.c.

Referenced by send_favorite().

#define FAVNUM   6

#define IDLE_WAIT   1000

Nb of milliseconds waited when no events are scheduled

Definition at line 101 of file chan_unistim.c.

Referenced by do_monitor().

#define LED_BAR_OFF   0x00

#define LED_BAR_ON   0x01

Definition at line 153 of file chan_unistim.c.

Referenced by unistim_send_mwi_to_peer().

#define LED_BAR_P2   0x02

Definition at line 154 of file chan_unistim.c.

#define LED_BAR_P3   0x03

Definition at line 155 of file chan_unistim.c.

#define LED_BAR_P4   0x04

Definition at line 156 of file chan_unistim.c.

#define LED_BAR_P5   0x05

Definition at line 157 of file chan_unistim.c.

#define LED_BAR_P6   0x06

Definition at line 158 of file chan_unistim.c.

#define LED_BAR_P7   0x07

Definition at line 159 of file chan_unistim.c.

#define LED_HEADPHONE_OFF   0x010

Definition at line 162 of file chan_unistim.c.

Referenced by key_dial_page(), send_select_output(), and show_main_page().

#define LED_HEADPHONE_ON   0x011

Definition at line 163 of file chan_unistim.c.

Referenced by send_select_output().

#define LED_MUTE_OFF   0x018

Definition at line 164 of file chan_unistim.c.

Referenced by microphone_mute_toggle().

#define LED_MUTE_ON   0x019

Definition at line 165 of file chan_unistim.c.

Referenced by microphone_mute_toggle().

#define LED_SPEAKER_OFF   0x08

Definition at line 160 of file chan_unistim.c.

Referenced by key_dial_page(), send_select_output(), and show_main_page().

#define LED_SPEAKER_ON   0x09

Definition at line 161 of file chan_unistim.c.

Referenced by send_select_output().

#define MAX_BUF_NUMBER   150

Number of slots for the transmit queue

Definition at line 93 of file chan_unistim.c.

Referenced by create_client(), and send_client().

#define MAX_BUF_SIZE   64

Size of the transmit buffer

Definition at line 91 of file chan_unistim.c.

#define MAX_ENTRY_LOG   30

Definition at line 114 of file chan_unistim.c.

Referenced by open_history(), and write_history().

#define MAX_SCREEN_NUMBER   15

Number of digits displayed on screen

Definition at line 95 of file chan_unistim.c.

Referenced by show_phone_number().

#define MONTH_LABEL_SIZE   3

Length of month label size

Definition at line 97 of file chan_unistim.c.

Referenced by send_month_labels().

#define MUTE_OFF   0x00

#define MUTE_ON   0xFF

Definition at line 149 of file chan_unistim.c.

Referenced by microphone_mute_toggle(), send_select_output(), and sub_hold().

#define MUTE_ON_DISCRET   0xCE

Definition at line 150 of file chan_unistim.c.

Referenced by send_select_output(), and show_main_page().

#define NB_MAX_RETRANSMIT   8

Try x times before removing the phone

Definition at line 99 of file chan_unistim.c.

Referenced by reload_config(), and send_retransmit().

#define OUTPUT_HANDSET   0xC0

#define OUTPUT_HEADPHONE   0xC1

#define OUTPUT_SPEAKER   0xC2

#define RETRANSMIT_TIMER   2000

Wait x milliseconds before resending a packet

Definition at line 103 of file chan_unistim.c.

Referenced by create_client(), reload_config(), send_client(), and send_retransmit().

#define SELECTCODEC_MAX_LENGTH   2

Definition at line 3695 of file chan_unistim.c.

Referenced by key_select_codec().

#define SELECTCODEC_MSG   "Codec number : .."

Definition at line 3696 of file chan_unistim.c.

Referenced by handle_select_codec(), and key_select_codec().

#define SELECTCODEC_START_ENTRY_POS   15

Definition at line 3694 of file chan_unistim.c.

Referenced by handle_select_codec(), and key_select_codec().

#define SELECTEXTENSION_MAX_LENGTH   10

Definition at line 3839 of file chan_unistim.c.

Referenced by key_select_extension().

#define SELECTEXTENSION_MSG   ".........."

Definition at line 3840 of file chan_unistim.c.

Referenced by key_select_extension(), and show_extension_page().

#define SELECTEXTENSION_START_ENTRY_POS   0

Definition at line 3838 of file chan_unistim.c.

Referenced by key_select_extension(), and show_extension_page().

#define SIZE_HEADER   6

#define SIZE_MAC_ADDR   17

Definition at line 168 of file chan_unistim.c.

#define SIZE_PAGE   4096

Definition at line 111 of file chan_unistim.c.

Referenced by load_module(), and unistimsock_read().

#define STATUS_LENGTH_MAX   28

Definition at line 175 of file chan_unistim.c.

Referenced by send_text_status(), and show_entry_history().

#define SUB_ONHOLD   3

Definition at line 119 of file chan_unistim.c.

Referenced by find_subchannel_by_name(), handle_key_fav(), sub_hold(), and subtype_tostr().

#define SUB_REAL   0

Definition at line 116 of file chan_unistim.c.

#define SUB_RING   1

#define SUB_THREEWAY   2

Definition at line 118 of file chan_unistim.c.

#define TEXT_INVERSE   0x25

Definition at line 174 of file chan_unistim.c.

Referenced by handle_select_codec(), and key_select_codec().

#define TEXT_LENGTH_MAX   24

#define TEXT_LINE0   0x00

#define TEXT_LINE1   0x20

#define TEXT_LINE2   0x40

#define TEXT_NORMAL   0x05

#define TIMER_MWI   5000

How often the mailbox is checked for new messages

Definition at line 105 of file chan_unistim.c.

Referenced by unistim_send_mwi_to_peer().

#define USTM_LANG_DIR   "unistimLang"

Definition at line 88 of file chan_unistim.c.

Referenced by ustmtext().

#define USTM_LOG_DIR   "unistimHistory"

Definition at line 87 of file chan_unistim.c.

Referenced by open_history(), and write_history().

#define VOLUME_INSANELY_LOUD   0x07

Definition at line 146 of file chan_unistim.c.

#define VOLUME_LOW   0x01

Definition at line 143 of file chan_unistim.c.

Referenced by build_device(), and send_select_output().

#define VOLUME_LOW_SPEAKER   0x03

Definition at line 144 of file chan_unistim.c.

Referenced by send_select_output().

#define VOLUME_NORMAL   0x02

Definition at line 145 of file chan_unistim.c.


Enumeration Type Documentation

Enumerator:
EXTENSION_NONE  Do not create an extension into the default dialplan
EXTENSION_ASK  Prompt user for an extension number and register it
EXTENSION_LINE  Register an extension with the line=> value
EXTENSION_TN  Used with AUTOPROVISIONING_TN

Definition at line 129 of file chan_unistim.c.

00129                    {
00130    /*! Do not create an extension into the default dialplan */
00131    EXTENSION_NONE = 0,
00132    /*! Prompt user for an extension number and register it */
00133    EXTENSION_ASK,
00134    /*! Register an extension with the line=> value */
00135    EXTENSION_LINE,
00136    /*! Used with AUTOPROVISIONING_TN */
00137    EXTENSION_TN
00138 };

Enumerator:
AUTOPROVISIONING_NO 
AUTOPROVISIONING_YES 
AUTOPROVISIONING_TN 

Definition at line 123 of file chan_unistim.c.

00123                    {
00124    AUTOPROVISIONING_NO = 0,
00125    AUTOPROVISIONING_YES,
00126    AUTOPROVISIONING_TN
00127 };

enum charset

Enumerator:
LANG_DEFAULT 
ISO_8859_1 
ISO_8859_2 
ISO_8859_4 
ISO_8859_5 
ISO_2022_JP 

Definition at line 336 of file chan_unistim.c.

00336              {
00337    LANG_DEFAULT,
00338    ISO_8859_1,
00339    ISO_8859_2,
00340    ISO_8859_4,
00341    ISO_8859_5,
00342    ISO_2022_JP,
00343 };

Enumerator:
STATE_ONHOOK 
STATE_OFFHOOK 

Definition at line 290 of file chan_unistim.c.

00290                    {
00291    STATE_ONHOOK,
00292    STATE_OFFHOOK,
00293 };

enum phone_key

Enumerator:
KEY_0 
KEY_1 
KEY_2 
KEY_3 
KEY_4 
KEY_5 
KEY_6 
KEY_7 
KEY_8 
KEY_9 
KEY_STAR 
KEY_SHARP 
KEY_UP 
KEY_DOWN 
KEY_RIGHT 
KEY_LEFT 
KEY_QUIT 
KEY_COPY 
KEY_FUNC1 
KEY_FUNC2 
KEY_FUNC3 
KEY_FUNC4 
KEY_ONHOLD 
KEY_HANGUP 
KEY_MUTE 
KEY_HEADPHN 
KEY_LOUDSPK 
KEY_FAV0 
KEY_FAV1 
KEY_FAV2 
KEY_FAV3 
KEY_FAV4 
KEY_FAV5 
KEY_COMPUTR 
KEY_CONF 
KEY_SNDHIST 
KEY_RCVHIST 
KEY_INDEX 

Definition at line 295 of file chan_unistim.c.

00295                {
00296    KEY_0 = 0x40,
00297    KEY_1 = 0x41,
00298    KEY_2 = 0x42,
00299    KEY_3 = 0x43,
00300    KEY_4 = 0x44,
00301    KEY_5 = 0x45,
00302    KEY_6 = 0x46,
00303    KEY_7 = 0x47,
00304    KEY_8 = 0x48,
00305    KEY_9 = 0x49,
00306    KEY_STAR = 0x4a,
00307    KEY_SHARP = 0x4b,
00308    KEY_UP = 0x4c,
00309    KEY_DOWN = 0x4d,
00310    KEY_RIGHT = 0x4e,
00311    KEY_LEFT = 0x4f,
00312    KEY_QUIT = 0x50,
00313    KEY_COPY = 0x51,
00314    KEY_FUNC1 = 0x54,
00315    KEY_FUNC2 = 0x55,
00316    KEY_FUNC3 = 0x56,
00317    KEY_FUNC4 = 0x57,
00318    KEY_ONHOLD = 0x5b,
00319    KEY_HANGUP = 0x5c,
00320    KEY_MUTE = 0x5d,
00321    KEY_HEADPHN = 0x5e,
00322    KEY_LOUDSPK = 0x5f,
00323    KEY_FAV0 = 0x60,
00324    KEY_FAV1 = 0x61,
00325    KEY_FAV2 = 0x62,
00326    KEY_FAV3 = 0x63,
00327    KEY_FAV4 = 0x64,
00328    KEY_FAV5 = 0x65,
00329    KEY_COMPUTR = 0x7b,
00330    KEY_CONF = 0x7c,
00331    KEY_SNDHIST = 0x7d,
00332    KEY_RCVHIST = 0x7e,
00333    KEY_INDEX = 0x7f
00334 };

Enumerator:
STATE_INIT 
STATE_AUTHDENY 
STATE_MAINPAGE 
STATE_EXTENSION 
STATE_DIALPAGE 
STATE_RINGING 
STATE_CALL 
STATE_SELECTOPTION 
STATE_SELECTCODEC 
STATE_SELECTLANGUAGE 
STATE_CLEANING 
STATE_HISTORY 

Definition at line 275 of file chan_unistim.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 7176 of file chan_unistim.c.

static void __unreg_module ( void   )  [static]

Definition at line 7176 of file chan_unistim.c.

static int attempt_transfer ( struct unistim_subchannel p1,
struct unistim_subchannel p2 
) [static]

Definition at line 2427 of file chan_unistim.c.

References ast_bridge_transfer_attended(), AST_BRIDGE_TRANSFER_FAIL, AST_BRIDGE_TRANSFER_INVALID, AST_BRIDGE_TRANSFER_NOT_PERMITTED, AST_BRIDGE_TRANSFER_SUCCESS, ast_channel_ref, ast_channel_unref, ast_log, AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), LOG_WARNING, NULL, unistim_subchannel::owner, and RAII_VAR.

02428 {
02429    RAII_VAR(struct ast_channel *, chana, NULL, ast_channel_unref);
02430    RAII_VAR(struct ast_channel *, chanb, NULL, ast_channel_unref);
02431 
02432    if (!p1->owner || !p2->owner) {
02433       ast_log(LOG_WARNING, "Transfer attempted without dual ownership?\n");
02434       return -1;
02435    }
02436    chana = ast_channel_ref(p1->owner);
02437    chanb = ast_channel_ref(p2->owner);
02438 
02439    switch (ast_bridge_transfer_attended(chana, chanb)) {
02440    case AST_BRIDGE_TRANSFER_INVALID:
02441       ast_log(LOG_WARNING, "Transfer failed. Invalid bridge setup\n");
02442       break;
02443    case AST_BRIDGE_TRANSFER_NOT_PERMITTED:
02444       ast_log(LOG_WARNING, "Transfer not permitted\n");
02445       break;
02446    case AST_BRIDGE_TRANSFER_FAIL:
02447       ast_log(LOG_WARNING, "Transfer encountered internal error\n");
02448       break;
02449    case AST_BRIDGE_TRANSFER_SUCCESS:
02450       return 0;
02451    }
02452 
02453    /* Control only reaches this point if transfer has failed */
02454    ast_softhangup_nolock(chana, AST_SOFTHANGUP_DEV);
02455    ast_softhangup_nolock(chanb, AST_SOFTHANGUP_DEV);
02456    return -1;
02457 }

static struct unistim_device* build_device ( const char *  cat,
const struct ast_variable v 
) [static, read]

Definition at line 6398 of file chan_unistim.c.

References ast_append_ha(), ast_calloc, ast_channel_string2amaflag(), ast_copy_string(), ast_format_cap_append_from_cap(), ast_free, ast_get_group(), ast_get_indication_zone(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_localtime(), ast_log, AST_MAX_EXTENSION, AST_MEDIA_TYPE_UNKNOWN, ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero, ast_tone_zone_unref(), ast_true(), ast_tvnow(), ast_verb, AUTOPROVISIONING_TN, unistim_device::callhistory, unistim_line::cap, unistim_device::context, unistim_device::contrast, unistim_device::country, unistim_device::cwstyle, unistim_device::cwvolume, d, dateformat, unistim_device::datetimeformat, DEFAULT_INTERDIGIT_TIMER, DEFAULTCONTEXT, DEFAULTHEIGHT, devicelock, unistim_device::dtmfduration, unistim_device::extension, EXTENSION_ASK, EXTENSION_LINE, EXTENSION_NONE, unistim_device::extension_number, EXTENSION_TN, FAV_ICON_NONE, FAV_LINE_ICON, find_line_by_number(), unistim_line::fullname, unistim_device::ha, unistim_device::hasexp, unistim_device::height, unistim_device::id, unistim_device::interdigit_timer, unistim_device::language, len(), ast_variable::lineno, unistim_device::lines, unistim_line::lock, unistim_device::lock, LOG_ERROR, LOG_WARNING, unistim_line::mailbox, unistim_device::maintext0, unistim_device::maintext1, unistim_device::maintext2, unistim_device::microphone, MUTE_OFF, unistim_line::name, ast_variable::name, unistim_device::name, unistim_device::nat, ast_variable::next, unistim_device::next, NULL, unistim_device::output, OUTPUT_HANDSET, unistim_line::parent, parse_bookmark(), unistim_device::previous_output, unistim_device::ringstyle, unistim_device::ringvolume, unistim_device::rtp_method, unistim_device::rtp_port, unistim_device::selected, unistim_device::sharp_dial, unistim_device::sline, unistim_device::softkeydevice, unistim_device::softkeyicon, unistim_device::softkeylabel, unistim_device::softkeynumber, unistim_device::sp, unistim_device::ssub, unistim_device::status_method, unistim_device::titledefault, ast_tm::tm_zone, unistim_device::to_delete, unistim_device::tz, unistim_line_alloc(), unistim_line_destroy(), unquote(), ast_variable::value, unistim_device::volume, and VOLUME_LOW.

06399 {
06400    struct unistim_device *d;
06401    struct unistim_line *l = NULL, *lt = NULL;
06402    int create = 1;
06403    int nbsoftkey, dateformat, timeformat, callhistory, sharpdial, linecnt;
06404    char linelabel[AST_MAX_EXTENSION];
06405    char ringvolume, ringstyle, cwvolume, cwstyle;
06406 
06407    /* First, we need to know if we already have this name in our list */
06408    /* Get a lock for the device chained list */
06409    ast_mutex_lock(&devicelock);
06410    d = devices;
06411    while (d) {
06412       if (!strcmp(d->name, cat)) {
06413          /* Yep, we alreay have this one */
06414          if (unistimsock < 0) {
06415             /* It's a dupe */
06416             ast_log(LOG_WARNING, "Duplicate entry found (%s), ignoring.\n", cat);
06417             ast_mutex_unlock(&devicelock);
06418             return NULL;
06419          }
06420          /* we're reloading right now */
06421          create = 0;
06422          break;
06423       }
06424       d = d->next;
06425    }
06426    ast_mutex_unlock(&devicelock);
06427    if (!(lt = ast_calloc(1, sizeof(*lt)))) {
06428       return NULL;
06429    }
06430    if (create) {
06431       if (!(d = ast_calloc(1, sizeof(*d)))) {
06432          return NULL;
06433       }
06434       ast_mutex_init(&d->lock);
06435       ast_copy_string(d->name, cat, sizeof(d->name));
06436       
06437       ast_copy_string(d->context, DEFAULTCONTEXT, sizeof(d->context));
06438       d->contrast = -1;
06439       d->output = OUTPUT_HANDSET;
06440       d->previous_output = OUTPUT_HANDSET;
06441       d->volume = VOLUME_LOW;
06442       d->microphone = MUTE_OFF;
06443       d->height = DEFAULTHEIGHT;
06444       d->selected = -1;
06445       d->interdigit_timer = DEFAULT_INTERDIGIT_TIMER;
06446    } else {
06447       /* Delete existing line information */
06448       AST_LIST_LOCK(&d->lines);
06449       AST_LIST_TRAVERSE_SAFE_BEGIN(&d->lines, l, list){
06450          AST_LIST_REMOVE_CURRENT(list);
06451          unistim_line_destroy(l);
06452       }
06453       AST_LIST_TRAVERSE_SAFE_END
06454       AST_LIST_UNLOCK(&d->lines);
06455 
06456       /* reset bookmarks */
06457       memset(d->softkeylabel, 0, sizeof(d->softkeylabel));
06458       memset(d->softkeynumber, 0, sizeof(d->softkeynumber));
06459       memset(d->softkeyicon, 0, sizeof(d->softkeyicon));
06460       memset(d->softkeydevice, 0, sizeof(d->softkeydevice));
06461       memset(d->ssub, 0, sizeof(d->ssub));
06462       memset(d->sline, 0, sizeof(d->sline));
06463       memset(d->sp, 0, sizeof(d->sp));
06464    }
06465    linelabel[0] = '\0';
06466    dateformat = 1;
06467    timeformat = 1;
06468    ringvolume = 2;
06469    cwvolume = 1;
06470    callhistory = 1;
06471    sharpdial = 0;
06472    ringstyle = 3;
06473    cwstyle = 2;
06474    nbsoftkey = 0;
06475    linecnt = 0;
06476    d->dtmfduration = 0;
06477    while (v) {
06478       if (!strcasecmp(v->name, "rtp_port")) {
06479          d->rtp_port = atoi(v->value);
06480       } else if (!strcasecmp(v->name, "rtp_method")) {
06481          d->rtp_method = atoi(v->value);
06482       } else if (!strcasecmp(v->name, "status_method")) {
06483          d->status_method = atoi(v->value);
06484       } else if (!strcasecmp(v->name, "device")) {
06485          ast_copy_string(d->id, v->value, sizeof(d->id));
06486       } else if (!strcasecmp(v->name, "tn")) {
06487          ast_copy_string(d->extension_number, v->value, sizeof(d->extension_number));
06488       } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) {
06489          d->ha = ast_append_ha(v->name, v->value, d->ha, NULL);
06490       } else if (!strcasecmp(v->name, "context")) {
06491          ast_copy_string(d->context, v->value, sizeof(d->context));
06492       } else if (!strcasecmp(v->name, "maintext0")) {
06493          unquote(d->maintext0, v->value, sizeof(d->maintext0) - 1);
06494       } else if (!strcasecmp(v->name, "maintext1")) {
06495          unquote(d->maintext1, v->value, sizeof(d->maintext1) - 1);
06496       } else if (!strcasecmp(v->name, "maintext2")) {
06497          unquote(d->maintext2, v->value, sizeof(d->maintext2) - 1);
06498       } else if (!strcasecmp(v->name, "titledefault")) {
06499          unquote(d->titledefault, v->value, sizeof(d->titledefault) - 1);
06500       } else if (!strcasecmp(v->name, "dateformat")) {
06501          dateformat = atoi(v->value);
06502       } else if (!strcasecmp(v->name, "timeformat")) {
06503          timeformat = atoi(v->value);
06504       } else if (!strcasecmp(v->name, "contrast")) {
06505          d->contrast = atoi(v->value);
06506          if ((d->contrast < 0) || (d->contrast > 15)) {
06507             ast_log(LOG_WARNING, "contrast must be beetween 0 and 15\n");
06508             d->contrast = 8;
06509          }
06510       } else if (!strcasecmp(v->name, "nat")) {
06511          d->nat = ast_true(v->value);
06512       } else if (!strcasecmp(v->name, "hasexp")) {
06513          d->hasexp = ast_true(v->value);
06514       } else if (!strcasecmp(v->name, "ringvolume")) {
06515          ringvolume = atoi(v->value);
06516       } else if (!strcasecmp(v->name, "ringstyle")) {
06517          ringstyle = atoi(v->value);
06518       } else if (!strcasecmp(v->name, "cwvolume")) {
06519          cwvolume = atoi(v->value);
06520       } else if (!strcasecmp(v->name, "cwstyle")) {
06521          cwstyle = atoi(v->value);
06522       } else if (!strcasecmp(v->name, "callhistory")) {
06523          callhistory = atoi(v->value);
06524       } else if (!strcasecmp(v->name, "sharpdial")) {
06525          sharpdial = ast_true(v->value) ? 1 : 0;
06526       } else if (!strcasecmp(v->name, "interdigit_timer")) {
06527          d->interdigit_timer = atoi(v->value);
06528       } else if (!strcasecmp(v->name, "dtmf_duration")) {
06529          d->dtmfduration = atoi(v->value);
06530          if (d->dtmfduration > 150) {
06531             d->dtmfduration = 150;
06532          }
06533       } else if (!strcasecmp(v->name, "callerid")) {
06534          if (!strcasecmp(v->value, "asreceived")) {
06535             lt->cid_num[0] = '\0';
06536          } else {
06537             ast_copy_string(lt->cid_num, v->value, sizeof(lt->cid_num));
06538          }
06539       } else if (!strcasecmp(v->name, "language")) {
06540          ast_copy_string(d->language, v->value, sizeof(d->language));
06541       } else if (!strcasecmp(v->name, "country")) {
06542          ast_copy_string(d->country, v->value, sizeof(d->country));
06543       } else if (!strcasecmp(v->name, "accountcode")) {
06544          ast_copy_string(lt->accountcode, v->value, sizeof(lt->accountcode));
06545       } else if (!strcasecmp(v->name, "amaflags")) {
06546          int y;
06547          y = ast_channel_string2amaflag(v->value);
06548          if (y < 0) {
06549             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value,
06550                   v->lineno);
06551          } else {
06552             lt->amaflags = y;
06553          }
06554       } else if (!strcasecmp(v->name, "musiconhold")) {
06555          ast_copy_string(lt->musicclass, v->value, sizeof(lt->musicclass));
06556       } else if (!strcasecmp(v->name, "callgroup")) {
06557          lt->callgroup = ast_get_group(v->value);
06558       } else if (!strcasecmp(v->name, "pickupgroup")) {
06559          lt->pickupgroup = ast_get_group(v->value);
06560       } else if (!strcasecmp(v->name, "mailbox")) {
06561          ast_copy_string(lt->mailbox, v->value, sizeof(lt->mailbox));
06562       } else if (!strcasecmp(v->name, "parkinglot")) {
06563          ast_copy_string(lt->parkinglot, v->value, sizeof(lt->parkinglot));
06564       } else if (!strcasecmp(v->name, "linelabel")) {
06565          unquote(linelabel, v->value, sizeof(linelabel) - 1);
06566       } else if (!strcasecmp(v->name, "extension")) {
06567          if (!strcasecmp(v->value, "none")) {
06568             d->extension = EXTENSION_NONE;
06569          } else if (!strcasecmp(v->value, "ask")) {
06570             d->extension = EXTENSION_ASK;
06571          } else if (!strcasecmp(v->value, "line")) {
06572             d->extension = EXTENSION_LINE;
06573          } else {
06574             ast_log(LOG_WARNING, "Unknown extension option.\n");
06575          }
06576       } else if (!strcasecmp(v->name, "bookmark")) {
06577          if (nbsoftkey > 5) {
06578             ast_log(LOG_WARNING,
06579                   "More than 6 softkeys defined. Ignoring new entries.\n");
06580          } else {
06581             if (parse_bookmark(v->value, d)) {
06582                nbsoftkey++;
06583             }
06584          }
06585       } else if (!strcasecmp(v->name, "line")) {
06586          int len = strlen(linelabel);
06587          int create_line = 0;
06588 
06589          l = find_line_by_number(d, v->value);
06590          if (!l) { /* If line still not exists */
06591             if (!(l = unistim_line_alloc())) {
06592                ast_free(d);
06593                ast_free(lt);
06594                return NULL;
06595             }
06596             lt->cap = l->cap;
06597             memcpy(l, lt, sizeof(*l));
06598             ast_mutex_init(&l->lock);
06599             create_line = 1;
06600          }
06601          d->to_delete = 0;
06602 
06603          /* Set softkey info for new line*/
06604          d->sline[nbsoftkey] = l;
06605          d->softkeyicon[nbsoftkey] = FAV_LINE_ICON;
06606          if (!len) {       /* label is undefined ? */
06607             ast_copy_string(d->softkeylabel[nbsoftkey], v->value, sizeof(d->softkeylabel[nbsoftkey]));
06608          } else {
06609             int softkeylinepos = 0;
06610             if ((len > 2) && (linelabel[1] == '@')) {
06611                softkeylinepos = linelabel[0];
06612                if ((softkeylinepos >= '0') && (softkeylinepos <= '5')) {
06613                   softkeylinepos -= '0';
06614                   d->softkeyicon[nbsoftkey] = FAV_ICON_NONE;
06615                } else {
06616                   ast_log(LOG_WARNING,
06617                         "Invalid position for linelabel : must be between 0 and 5\n");
06618                }
06619                ast_copy_string(d->softkeylabel[softkeylinepos], linelabel + 2,
06620                            sizeof(d->softkeylabel[softkeylinepos]));
06621                d->softkeyicon[softkeylinepos] = FAV_LINE_ICON;
06622             } else {
06623                ast_copy_string(d->softkeylabel[nbsoftkey], linelabel,
06624                            sizeof(d->softkeylabel[nbsoftkey]));
06625             }
06626          }
06627          nbsoftkey++;
06628 
06629          if (create_line) {
06630             ast_copy_string(l->name, v->value, sizeof(l->name));
06631             snprintf(l->fullname, sizeof(l->fullname), "USTM/%s@%s", l->name, d->name);
06632             if (!ast_strlen_zero(l->mailbox)) {
06633                if (unistimdebug) {
06634                   ast_verb(3, "Setting mailbox '%s' on %s@%s\n", l->mailbox, d->name, l->name);
06635                }
06636             }
06637             ast_format_cap_append_from_cap(l->cap, global_cap, AST_MEDIA_TYPE_UNKNOWN);
06638             l->parent = d;
06639             linecnt++;
06640             AST_LIST_LOCK(&d->lines);
06641             AST_LIST_INSERT_TAIL(&d->lines, l, list);
06642             AST_LIST_UNLOCK(&d->lines);
06643          }
06644       } else if (!strcasecmp(v->name, "height")) {
06645          /* Allow the user to lower the expected display lines on the phone
06646           * For example the Nortel i2001 and i2002 only have one ! */
06647          d->height = atoi(v->value);
06648       } else
06649          ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name,
06650                v->lineno);
06651       v = v->next;
06652    }
06653    ast_free(lt);
06654    if (linecnt == 0) {
06655       ast_log(LOG_ERROR, "An Unistim device must have at least one line!\n");
06656       ast_free(d);
06657       return NULL;
06658    }
06659    d->ringvolume = ringvolume;
06660    d->ringstyle = ringstyle;
06661    d->cwvolume = cwvolume;
06662    d->cwstyle = cwstyle;
06663    d->callhistory = callhistory;
06664    d->sharp_dial = sharpdial;
06665    d->tz = ast_get_indication_zone(d->country);
06666    if ((d->tz == NULL) && !ast_strlen_zero(d->country)) {
06667       ast_log(LOG_WARNING, "Country '%s' was not found in indications.conf\n",
06668             d->country);
06669    }
06670    d->datetimeformat = 48 + (dateformat * 4);
06671    d->datetimeformat += timeformat;
06672    if ((autoprovisioning == AUTOPROVISIONING_TN) &&
06673       (!ast_strlen_zero(d->extension_number))) {
06674       d->extension = EXTENSION_TN;
06675       if (!ast_strlen_zero(d->id)) {
06676          ast_log(LOG_WARNING,
06677                "tn= and device= can't be used together. Ignoring device= entry\n");
06678       }
06679       d->id[0] = 'T';       /* magic : this is a tn entry */
06680       ast_copy_string((d->id) + 1, d->extension_number, sizeof(d->id) - 1);
06681       d->extension_number[0] = '\0';
06682    } else if (ast_strlen_zero(d->id)) {
06683       if (strcmp(d->name, "template")) {
06684          ast_log(LOG_ERROR, "You must specify the mac address with device=\n");
06685          if (d->tz) {
06686             d->tz = ast_tone_zone_unref(d->tz);
06687          }
06688          ast_free(d);
06689          return NULL;
06690       } else {
06691          strcpy(d->id, "000000000000");
06692       }
06693    }
06694    if (!d->rtp_port) {
06695       d->rtp_port = 10000;
06696    }
06697    if (d->contrast == -1) {
06698       d->contrast = 8;
06699    }
06700    if (ast_strlen_zero(d->maintext1)) {
06701       strcpy(d->maintext1, d->name);
06702    }
06703    if (ast_strlen_zero(d->titledefault)) {
06704       struct ast_tm tm = { 0, };
06705       struct timeval cur_time = ast_tvnow();
06706 
06707       if ((ast_localtime(&cur_time, &tm, 0)) == 0 || ast_strlen_zero(tm.tm_zone)) {
06708          ast_log(LOG_WARNING, "Error in ast_localtime()\n");
06709          ast_copy_string(d->titledefault, "UNISTIM for*", 12);
06710       } else {
06711          if (strlen(tm.tm_zone) < 4) {
06712             strcpy(d->titledefault, "TimeZone ");
06713             strcat(d->titledefault, tm.tm_zone);
06714          } else if (strlen(tm.tm_zone) < 9) {
06715             strcpy(d->titledefault, "TZ ");
06716             strcat(d->titledefault, tm.tm_zone);
06717          } else {
06718             ast_copy_string(d->titledefault, tm.tm_zone, 12);
06719          }
06720       }
06721    }
06722    /* Update the chained link if it's a new device */
06723    if (create) {
06724       ast_mutex_lock(&devicelock);
06725       d->next = devices;
06726       devices = d;
06727       ast_mutex_unlock(&devicelock);
06728       ast_verb(3, "Added device '%s'\n", d->name);
06729    } else {
06730       ast_verb(3, "Device '%s' reloaded\n", d->name);
06731    }
06732    return d;
06733 }

void change_callerid ( struct unistimsession pte,
int  type,
char *  callerid 
) [static]

Definition at line 2459 of file chan_unistim.c.

References unistimsession::device, unistim_device::lst_cid, unistim_device::lst_cnm, and TEXT_LENGTH_MAX.

Referenced by close_call(), and send_callerid_screen().

02460 {
02461    char *data;
02462    int size;
02463 
02464    if (type) {
02465       data = pte->device->lst_cnm;
02466    } else {
02467       data = pte->device->lst_cid;
02468    }
02469 
02470    /* This is very nearly strncpy(), except that the remaining buffer
02471     * is padded with ' ', instead of '\0' */
02472    memset(data, ' ', TEXT_LENGTH_MAX);
02473    size = strlen(callerid);
02474    if (size > TEXT_LENGTH_MAX) {
02475       size = TEXT_LENGTH_MAX;
02476    }
02477    memcpy(data, callerid, size);
02478 }

static void change_favorite_icon ( struct unistimsession pte,
unsigned char  status 
) [static]

Definition at line 1403 of file chan_unistim.c.

References d, unistimsession::device, FAVNUM, get_active_softkey(), unistim_device::next, send_favorite(), send_favorite_short(), unistim_device::session, unistim_device::softkeyicon, unistim_device::softkeylabel, unistim_device::sp, unistimsession::state, and STATE_CLEANING.

Referenced by close_client(), handle_dial_page(), send_select_output(), show_main_page(), and unistim_call().

01404 {
01405    struct unistim_device *d = devices;
01406    int i;
01407    /* Update the current phone line softkey icon */
01408    if (pte->state != STATE_CLEANING) {
01409       int softkeylinepos = get_active_softkey(pte);
01410       if (softkeylinepos != -1) {
01411          send_favorite_short(softkeylinepos, status, pte);
01412       }
01413    }
01414    /* Notify other phones if we're in their bookmark */
01415    while (d) {
01416       for (i = 0; i < FAVNUM; i++) {
01417          if (d->sp[i] == pte->device) {  /* It's us ? */
01418             if (d->softkeyicon[i] != status) {      /* Avoid resending the same icon */
01419                d->softkeyicon[i] = status;
01420                if (d->session) {
01421                   send_favorite(i, status + 1, d->session, d->softkeylabel[i]);
01422                }
01423             }
01424          }
01425       }
01426       d = d->next;
01427    }
01428 }

static struct unistimsession* channel_to_session ( struct ast_channel ast  )  [static, read]

Definition at line 4759 of file chan_unistim.c.

References ast_channel_tech_pvt(), ast_log, ast_mutex_lock, ast_mutex_unlock, unistim_device::lock, LOG_WARNING, NULL, unistim_line::parent, unistim_subchannel::parent, unistim_device::session, and sub.

Referenced by unistim_answer(), unistim_call(), unistim_hangup(), unistim_indicate(), unistim_senddigit_begin(), unistim_senddigit_end(), and unistim_sendtext().

04760 {
04761    struct unistim_subchannel *sub;
04762    if (!ast) {
04763       ast_log(LOG_WARNING, "Unistim callback function called with a null channel\n");
04764       return NULL;
04765    }
04766    if (!ast_channel_tech_pvt(ast)) {
04767       ast_log(LOG_WARNING, "Unistim callback function called without a tech_pvt\n");
04768       return NULL;
04769    }
04770    sub = ast_channel_tech_pvt(ast);
04771 
04772    if (!sub->parent) {
04773       ast_log(LOG_WARNING, "Unistim callback function called without a line\n");
04774       return NULL;
04775    }
04776    if (!sub->parent->parent) {
04777       ast_log(LOG_WARNING, "Unistim callback function called without a device\n");
04778       return NULL;
04779    }
04780    ast_mutex_lock(&sub->parent->parent->lock);
04781    if (!sub->parent->parent->session) {
04782       ast_log(LOG_WARNING, "Unistim callback function called without a session\n");
04783       ast_mutex_unlock(&sub->parent->parent->lock);
04784       return NULL;
04785    }
04786    ast_mutex_unlock(&sub->parent->parent->lock);
04787    return sub->parent->parent->session;
04788 }

static void check_send_queue ( struct unistimsession pte  )  [static]

Definition at line 1083 of file chan_unistim.c.

References ast_verb, unistimsession::last_buf_available, unistimsession::last_seq_ack, unistimsession::seq_server, and set_ping_timer().

Referenced by parsing().

01084 {
01085    /* Check if our send queue contained only one element */
01086    if (pte->last_buf_available == 1) {
01087       if (unistimdebug) {
01088          ast_verb(0, "Our single packet was ACKed.\n");
01089       }
01090       pte->last_buf_available--;
01091       set_ping_timer(pte);
01092       return;
01093    }
01094    /* Check if this ACK catch up our latest packet */
01095    else if (pte->last_seq_ack + 1 == pte->seq_server + 1) {
01096       if (unistimdebug) {
01097          ast_verb(0, "Our send queue is completely ACKed.\n");
01098       }
01099       pte->last_buf_available = 0;    /* Purge the send queue */
01100       set_ping_timer(pte);
01101       return;
01102    }
01103    if (unistimdebug) {
01104       ast_verb(0, "We still have packets in our send queue\n");
01105    }
01106    return;
01107 }

static void close_call ( struct unistimsession pte  )  [static]

Definition at line 2569 of file chan_unistim.c.

References unistim_subchannel::alreadygone, AST_CAUSE_NORMAL_CLEARING, ast_log, ast_queue_hangup(), ast_queue_hangup_with_cause(), ast_verb, attempt_transfer(), change_callerid(), unistimsession::device, FAV_LINE_ICON, get_sub(), LOG_WARNING, unistim_device::missed_call, unistim_device::name, unistim_line::name, unistim_subchannel::owner, unistim_subchannel::parent, unistim_device::redial_number, send_favorite_short(), send_stop_timer(), show_main_page(), unistim_subchannel::softkey, sub, SUB_REAL, SUB_THREEWAY, and write_history().

Referenced by key_call(), process_request(), and unistim_hangup().

02570 {
02571    struct unistim_subchannel *sub, *sub_transf;
02572 
02573    sub = get_sub(pte->device, SUB_REAL);
02574    sub_transf = get_sub(pte->device, SUB_THREEWAY);
02575    send_stop_timer(pte);
02576    if (!sub) {
02577       ast_log(LOG_WARNING, "Close call without sub\n");
02578       return;
02579    }
02580    send_favorite_short(sub->softkey, FAV_LINE_ICON, pte);
02581    if (sub->owner) {
02582       sub->alreadygone = 1;
02583       if (sub_transf) {
02584          sub_transf->alreadygone = 1;
02585          if (attempt_transfer(sub, sub_transf) < 0) {
02586             ast_verb(0, "attempt_transfer failed.\n");
02587          }
02588       } else {
02589          ast_queue_hangup(sub->owner);
02590       }
02591    } else {
02592       if (sub_transf) {
02593          if (sub_transf->owner) {
02594             ast_queue_hangup_with_cause(sub_transf->owner, AST_CAUSE_NORMAL_CLEARING);
02595          } else {
02596             ast_log(LOG_WARNING, "threeway sub without owner\n");
02597          }
02598       } else {
02599          ast_verb(0, "USTM(%s@%s-%d) channel already destroyed\n", sub->parent->name,
02600                   pte->device->name, sub->softkey);
02601       }
02602    }
02603    change_callerid(pte, 0, pte->device->redial_number);
02604    change_callerid(pte, 1, "");
02605    write_history(pte, 'o', pte->device->missed_call);
02606    pte->device->missed_call = 0;
02607    show_main_page(pte);
02608    return;
02609 }

static void close_client ( struct unistimsession s  )  [static]

Definition at line 1455 of file chan_unistim.c.

References AST_CAUSE_NETWORK_OUT_OF_ORDER, ast_debug, ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log, ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, ast_queue_hangup_with_cause(), ast_strlen_zero, ast_verb, change_favorite_icon(), unistimsession::device, unistim_device::extension_number, FAV_ICON_NONE, unistimsession::lock, unistim_device::lock, LOG_WARNING, unistim_device::name, unistim_line::name, unistimsession::next, NULL, unistim_subchannel::owner, unistim_subchannel::parent, unistim_device::session, sessionlock, unistimsession::state, STATE_CLEANING, sub, unistim_device::subs, unistim_subchannel::subtype, unistim_free_sub(), and unregister_extension().

Referenced by parsing(), and send_retransmit().

01456 {
01457    struct unistim_subchannel *sub = NULL;
01458    struct unistimsession *cur, *prev = NULL;
01459    ast_mutex_lock(&sessionlock);
01460    cur = sessions;
01461    /* Looking for the session in the linked chain */
01462    while (cur) {
01463       if (cur == s) {
01464          break;
01465       }
01466       prev = cur;
01467       cur = cur->next;
01468    }
01469    if (cur) {                 /* Session found ? */
01470       if (cur->device) {         /* This session was registered ? */
01471          s->state = STATE_CLEANING;
01472          if (unistimdebug) {
01473             ast_verb(0, "close_client session %p device %p\n", s, s->device);
01474          }
01475          change_favorite_icon(s, FAV_ICON_NONE);
01476          ast_mutex_lock(&s->device->lock);
01477          AST_LIST_LOCK(&s->device->subs);
01478          AST_LIST_TRAVERSE_SAFE_BEGIN(&s->device->subs, sub, list) {
01479             if (!sub) {
01480                continue;
01481             }
01482             if (sub->owner) {       /* Call in progress ? */
01483                if (unistimdebug) {
01484                   ast_verb(0, "Aborting call\n");
01485                }
01486                ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NETWORK_OUT_OF_ORDER);
01487             } else {
01488                if (unistimdebug) {
01489                   ast_debug(1, "Released sub %u of channel %s@%s\n", sub->subtype, sub->parent->name, s->device->name);
01490                }
01491                AST_LIST_REMOVE_CURRENT(list);
01492                unistim_free_sub(sub);
01493             }
01494          }
01495          AST_LIST_TRAVERSE_SAFE_END;
01496          AST_LIST_UNLOCK(&s->device->subs);
01497 
01498          if (!ast_strlen_zero(s->device->extension_number)) {
01499             unregister_extension(s);
01500          }
01501          cur->device->session = NULL;
01502          ast_mutex_unlock(&s->device->lock);
01503       } else {
01504          if (unistimdebug) {
01505             ast_verb(0, "Freeing an unregistered client\n");
01506          }
01507       }
01508       if (prev) {
01509          prev->next = cur->next;
01510       } else {
01511          sessions = cur->next;
01512       }
01513       ast_mutex_destroy(&s->lock);
01514       ast_free(s);
01515    } else {
01516       ast_log(LOG_WARNING, "Trying to delete non-existent session %p?\n", s);
01517    }
01518    ast_mutex_unlock(&sessionlock);
01519    return;
01520 }

static char* control2str ( int  ind  )  [static]

Definition at line 5243 of file chan_unistim.c.

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_OFFHOOK, AST_CONTROL_OPTION, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_TAKEOFFHOOK, and AST_CONTROL_WINK.

05244 {
05245    switch (ind) {
05246    case AST_CONTROL_HANGUP:
05247       return "Other end has hungup";
05248    case AST_CONTROL_RING:
05249       return "Local ring";
05250    case AST_CONTROL_RINGING:
05251       return "Remote end is ringing";
05252    case AST_CONTROL_ANSWER:
05253       return "Remote end has answered";
05254    case AST_CONTROL_BUSY:
05255       return "Remote end is busy";
05256    case AST_CONTROL_TAKEOFFHOOK:
05257       return "Make it go off hook";
05258    case AST_CONTROL_OFFHOOK:
05259       return "Line is off hook";
05260    case AST_CONTROL_CONGESTION:
05261       return "Congestion (circuits busy)";
05262    case AST_CONTROL_FLASH:
05263       return "Flash hook";
05264    case AST_CONTROL_WINK:
05265       return "Wink";
05266    case AST_CONTROL_OPTION:
05267       return "Set a low-level option";
05268    case AST_CONTROL_RADIO_KEY:
05269       return "Key Radio";
05270    case AST_CONTROL_RADIO_UNKEY:
05271       return "Un-Key Radio";
05272    case AST_CONTROL_CONNECTED_LINE:
05273       return "Remote end changed";
05274    case AST_CONTROL_SRCCHANGE:
05275       return "RTP source updated";
05276    case AST_CONTROL_SRCUPDATE:
05277       return "Source of media changed";
05278    case -1:
05279       return "Stop tone";
05280    }
05281    return "UNKNOWN";
05282 }

static struct unistimsession* create_client ( const struct sockaddr_in *  addr_from  )  [static, read]

Definition at line 1031 of file chan_unistim.c.

References ast_calloc, ast_inet_ntoa(), ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_verb, unistimsession::buf, wsabuf::buf, get_tick_count(), get_to_address(), unistimsession::lock, MAX_BUF_NUMBER, unistimsession::next, NULL, RETRANSMIT_TIMER, sessionlock, unistimsession::sin, unistimsession::sout, unistimsession::state, STATE_INIT, unistimsession::tick_next_ping, unistimsession::timeout, tmp(), and unistimsession::wsabufsend.

Referenced by parsing().

01032 {
01033    int tmp;
01034    struct unistimsession *s;
01035 
01036    if (!(s = ast_calloc(1, sizeof(*s))))
01037       return NULL;
01038 
01039    memcpy(&s->sin, addr_from, sizeof(struct sockaddr_in));
01040    get_to_address(unistimsock, &s->sout);
01041    s->sout.sin_family = AF_INET;
01042    if (unistimdebug) {
01043       ast_verb(0, "Creating a new entry for the phone from %s received via server ip %s\n",
01044           ast_inet_ntoa(addr_from->sin_addr), ast_inet_ntoa(s->sout.sin_addr));
01045    }
01046    ast_mutex_init(&s->lock);
01047    ast_mutex_lock(&sessionlock);
01048    s->next = sessions;
01049    sessions = s;
01050 
01051    s->timeout = get_tick_count() + RETRANSMIT_TIMER;
01052    s->state = STATE_INIT;
01053    s->tick_next_ping = get_tick_count() + unistim_keepalive;
01054    /* Initialize struct wsabuf  */
01055    for (tmp = 0; tmp < MAX_BUF_NUMBER; tmp++) {
01056       s->wsabufsend[tmp].buf = s->buf[tmp];
01057    }
01058    ast_mutex_unlock(&sessionlock);
01059    return s;
01060 }

static void discard_call ( struct unistimsession pte  )  [static]

Definition at line 2617 of file chan_unistim.c.

References AST_CAUSE_NORMAL_CLEARING, ast_queue_hangup_with_cause(), unistimsession::device, get_sub(), unistim_subchannel::owner, sub, and SUB_RING.

Referenced by key_ringing().

02618 {
02619    struct unistim_subchannel* sub;
02620    sub = get_sub(pte->device, SUB_RING);
02621    if (!sub) {
02622        return;
02623    }
02624 
02625    ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NORMAL_CLEARING);
02626    return;
02627 }

static void display_last_error ( const char *  sz_msg  )  [static]

Definition at line 884 of file chan_unistim.c.

References ast_log, errno, and LOG_WARNING.

Referenced by key_history(), open_history(), send_raw_client(), show_entry_history(), write_entry_history(), and write_history().

00885 {
00886    /* Display the error message */
00887    ast_log(LOG_WARNING, "%s : (%d) %s\n", sz_msg, errno, strerror(errno));
00888 }

static void* do_monitor ( void *  data  )  [static]

Definition at line 5811 of file chan_unistim.c.

References ast_io_add(), AST_IO_IN, ast_io_wait(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero, ast_verb, DEBUG_TIMER, unistimsession::device, get_tick_count(), handle_call_outgoing(), IDLE_WAIT, unistimsession::last_buf_available, unistim_device::lines, unistim_line::mailbox, unistimsession::next, unistim_device::nextdial, unistim_device::nextmsgcheck, NULL, unistim_line::parent, reload_config(), send_ping(), send_retransmit(), sessionlock, unistimsession::timeout, unistim_reload_lock, unistim_send_mwi_to_peer(), and unistimsock_read().

05812 {
05813    struct unistimsession *cur = NULL;
05814    unsigned int dw_timeout = 0;
05815    unsigned int tick;
05816    int res;
05817    int reloading;
05818 
05819    /* Add an I/O event to our UDP socket */
05820    if (unistimsock > -1) {
05821       ast_io_add(io, unistimsock, unistimsock_read, AST_IO_IN, NULL);
05822    }
05823    /* This thread monitors our UDP socket and timers */
05824    for (;;) {
05825       /* This loop is executed at least every IDLE_WAITus (1s) or every time a packet is received */
05826       /* Looking for the smallest time-out value */
05827       tick = get_tick_count();
05828       dw_timeout = UINT_MAX;
05829       ast_mutex_lock(&sessionlock);
05830       cur = sessions;
05831       DEBUG_TIMER("checking timeout for session %p with tick = %u\n", cur, tick);
05832       while (cur) {
05833          DEBUG_TIMER("checking timeout for session %p timeout = %u\n", cur,
05834                   cur->timeout);
05835          /* Check if we have miss something */
05836          if (cur->timeout <= tick) {
05837             DEBUG_TIMER("Event for session %p\n", cur);
05838             /* If the queue is empty, send a ping */
05839             if (cur->last_buf_available == 0) {
05840                send_ping(cur);
05841             } else {
05842                if (send_retransmit(cur)) {
05843                   DEBUG_TIMER("The chained link was modified, restarting...\n");
05844                   cur = sessions;
05845                   dw_timeout = UINT_MAX;
05846                   continue;
05847                }
05848             }
05849          }
05850          if (dw_timeout > cur->timeout - tick) {
05851             dw_timeout = cur->timeout - tick;
05852          }
05853          /* Checking if the phone is logged on for a new MWI */
05854          if (cur->device) {
05855             struct unistim_line *l;
05856             AST_LIST_LOCK(&cur->device->lines);
05857             AST_LIST_TRAVERSE(&cur->device->lines, l, list) {
05858                if ((!ast_strlen_zero(l->mailbox)) && (tick >= l->parent->nextmsgcheck)) {
05859                   DEBUG_TIMER("Checking mailbox for MWI\n");
05860                   unistim_send_mwi_to_peer(l, tick);
05861                   break;
05862                }
05863             }
05864             AST_LIST_UNLOCK(&cur->device->lines);
05865             if (cur->device->nextdial && tick >= cur->device->nextdial) {
05866                handle_call_outgoing(cur);
05867                cur->device->nextdial = 0;
05868             }
05869          }
05870          cur = cur->next;
05871       }
05872       ast_mutex_unlock(&sessionlock);
05873       DEBUG_TIMER("Waiting for %dus\n", dw_timeout);
05874       res = dw_timeout;
05875       /* We should not wait more than IDLE_WAIT */
05876       if ((res < 0) || (res > IDLE_WAIT)) {
05877          res = IDLE_WAIT;
05878       }
05879       /* Wait for UDP messages for a maximum of res us */
05880       res = ast_io_wait(io, res);     /* This function will call unistimsock_read if a packet is received */
05881       /* Check for a reload request */
05882       ast_mutex_lock(&unistim_reload_lock);
05883       reloading = unistim_reloading;
05884       unistim_reloading = 0;
05885       ast_mutex_unlock(&unistim_reload_lock);
05886       if (reloading) {
05887          ast_verb(1, "Reloading unistim.conf...\n");
05888          reload_config();
05889       }
05890       pthread_testcancel();
05891    }
05892    /* Never reached */
05893    return NULL;
05894 }

static void dummy ( char *  unused,
  ... 
) [static]

static int find_language ( const char *  lang  )  [static]

Definition at line 3772 of file chan_unistim.c.

References NULL.

Referenced by handle_select_language(), init_phone_step2(), reload_config(), send_charset_update(), and ustmtext().

03773 {
03774    int i = 0;
03775    while (options_languages[i].lang_short != NULL) {
03776       if(!strcmp(options_languages[i].lang_short, lang)) {
03777          return i;
03778       }
03779       i++;
03780    }
03781    return 0;
03782 }

static struct unistim_line* find_line_by_number ( struct unistim_device d,
const char *  val 
) [static, read]

Definition at line 6384 of file chan_unistim.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, unistim_device::lines, unistim_line::name, and NULL.

Referenced by build_device().

06384                                                                                            {
06385    struct unistim_line *l, *ret = NULL;
06386 
06387    AST_LIST_LOCK(&d->lines);
06388    AST_LIST_TRAVERSE(&d->lines, l, list) {
06389       if (!strcmp(l->name, val)) {
06390          ret = l;
06391          break;
06392       }
06393    }
06394    AST_LIST_UNLOCK(&d->lines);
06395    return ret;
06396 }

static int find_rtp_port ( struct unistim_subchannel s  )  [static]

Definition at line 2655 of file chan_unistim.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_rtp_instance_get_remote_address, ast_sockaddr_to_sin, NULL, unistim_line::parent, unistim_subchannel::parent, unistim_subchannel::rtp, unistim_device::rtp_port, sub, and unistim_device::subs.

Referenced by start_rtp().

02656 {
02657    struct unistim_subchannel *sub = NULL;
02658    int rtp_start = s->parent->parent->rtp_port;
02659    struct ast_sockaddr us_tmp;
02660    struct sockaddr_in us = { 0, };
02661 
02662    AST_LIST_LOCK(&s->parent->parent->subs);
02663    AST_LIST_TRAVERSE(&s->parent->parent->subs, sub, list) {
02664       if (!sub) {
02665          continue;
02666       }
02667       if (sub->rtp) {
02668          ast_rtp_instance_get_remote_address(sub->rtp, &us_tmp);
02669          ast_sockaddr_to_sin(&us_tmp, &us);
02670          if (htons(us.sin_port)) {
02671             rtp_start = htons(us.sin_port) + 1;
02672             break;
02673          }
02674       }
02675    }
02676    AST_LIST_UNLOCK(&s->parent->parent->subs);
02677    return rtp_start;
02678 }

static struct unistim_subchannel* find_subchannel_by_name ( const char *  dest  )  [static, read]

Definition at line 5385 of file chan_unistim.c.

References ast_copy_string(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_verb, d, devicelock, get_sub(), unistim_device::lines, LOG_NOTICE, LOG_WARNING, unistim_line::name, unistim_device::name, unistim_device::next, NULL, unistim_subchannel::owner, unistim_subchannel::parent, unistim_subchannel::ringstyle, unistim_subchannel::ringvolume, sub, SUB_ONHOLD, SUB_REAL, and unistim_alloc_sub().

Referenced by unistim_request(), and unistim_sp().

05386 {
05387    struct unistim_line *l;
05388    struct unistim_device *d;
05389    struct unistim_subchannel *sub = NULL;
05390    char line[256];
05391    char *at;
05392    char *device;
05393 
05394    ast_copy_string(line, dest, sizeof(line));
05395    at = strchr(line, '@');
05396    if (!at) {
05397       ast_log(LOG_NOTICE, "Device '%s' has no @ (at) sign!\n", dest);
05398       return NULL;
05399    }
05400    *at = '\0';
05401    at++;
05402    device = at;
05403    ast_mutex_lock(&devicelock);
05404    d = devices;
05405    at = strchr(device, '/');       /* Extra options ? */
05406    if (at) {
05407       *at = '\0';
05408    }
05409    while (d) {
05410       if (!strcasecmp(d->name, device)) {
05411          if (unistimdebug) {
05412             ast_verb(0, "Found device: %s\n", d->name);
05413          }
05414          /* Found the device */
05415          AST_LIST_LOCK(&d->lines);
05416          AST_LIST_TRAVERSE(&d->lines, l, list) {
05417             /* Search for the right line */
05418             if (!strcasecmp(l->name, line)) {
05419                if (unistimdebug) {
05420                   ast_verb(0, "Found line: %s\n", l->name);
05421                }
05422                sub = get_sub(d, SUB_REAL);
05423                if (!sub) {
05424                   sub = unistim_alloc_sub(d, SUB_REAL);
05425                }
05426                if (sub->owner) {
05427                   /* Allocate additional channel if asterisk channel already here */
05428                   sub = unistim_alloc_sub(d, SUB_ONHOLD);
05429                }
05430                sub->ringvolume = -1;
05431                sub->ringstyle = -1;
05432                if (at) {       /* Other options ? */
05433                   at++;   /* Skip slash */
05434                   if (*at == 'r') {       /* distinctive ring */
05435                      at++;
05436                      if ((*at < '0') || (*at > '7')) { /* ring style */
05437                         ast_log(LOG_WARNING, "Invalid ring selection (%s)", at);
05438                      } else {
05439                         char ring_volume = -1;
05440                         char ring_style = *at - '0';
05441                         at++;
05442                         if ((*at >= '0') && (*at <= '3')) {      /* ring volume */
05443                            ring_volume = *at - '0';
05444                         }
05445                         if (unistimdebug) {
05446                            ast_verb(0, "Distinctive ring: style #%d volume %d\n",
05447                                ring_style, ring_volume);
05448                         }
05449                         sub->ringvolume = ring_volume;
05450                         sub->ringstyle = ring_style;
05451                      }
05452                   }
05453                }
05454                sub->parent = l;
05455                break;
05456             }
05457          }
05458          AST_LIST_UNLOCK(&d->lines);
05459          if (sub) {
05460             ast_mutex_unlock(&devicelock);
05461             return sub;
05462          }
05463       }
05464       d = d->next;
05465    }
05466    /* Device not found */
05467    ast_mutex_unlock(&devicelock);
05468 
05469    return NULL;
05470 }

static void finish_bookmark ( void   )  [static]

Definition at line 6356 of file chan_unistim.c.

References ast_log, ast_mutex_lock, ast_mutex_unlock, d, devicelock, LOG_NOTICE, unistim_device::name, unistim_device::next, NULL, unistim_device::softkeydevice, unistim_device::softkeyicon, and unistim_device::sp.

Referenced by reload_config().

06357 {
06358    struct unistim_device *d = devices;
06359    int i;
06360    ast_mutex_lock(&devicelock);
06361    while (d) {
06362       for (i = 0; i < 6; i++) {
06363          if (d->softkeyicon[i] == 1) {   /* Something for us */
06364             struct unistim_device *d2 = devices;
06365             while (d2) {
06366                if (!strcmp(d->softkeydevice[i], d2->name)) {
06367                   d->sp[i] = d2;
06368                   d->softkeyicon[i] = 0;
06369                   break;
06370                }
06371                d2 = d2->next;
06372             }
06373             if (d->sp[i] == NULL) {
06374                ast_log(LOG_NOTICE, "Bookmark entry with device %s not found\n",
06375                      d->softkeydevice[i]);
06376             }
06377          }
06378       }
06379       d = d->next;
06380    }
06381    ast_mutex_unlock(&devicelock);
06382 }

static int get_active_softkey ( struct unistimsession pte  )  [static]

Definition at line 1365 of file chan_unistim.c.

References unistimsession::device, and unistim_device::selected.

Referenced by change_favorite_icon().

01366 {
01367    return pte->device->selected;
01368 }

static int get_avail_softkey ( struct unistimsession pte,
const char *  name 
) [static]

Definition at line 1370 of file chan_unistim.c.

References ast_verb, unistimsession::device, FAVNUM, is_key_line(), unistim_line::name, unistim_device::selected, unistim_device::sline, soft_key_visible(), and unistim_device::ssub.

Referenced by handle_call_outgoing(), key_main_page(), process_request(), and unistim_request().

01371 {
01372    int i;
01373 
01374    if (!is_key_line(pte->device, pte->device->selected)) {
01375       pte->device->selected = -1;
01376    }
01377    for (i = 0; i < FAVNUM; i++) {
01378       if (pte->device->selected != -1 && pte->device->selected != i) {
01379          continue;
01380       }
01381       if (!soft_key_visible(pte->device, i)) {
01382          continue;
01383       }
01384       if (pte->device->ssub[i]) {
01385          continue;
01386       }
01387       if (is_key_line(pte->device, i)) {
01388          if (name && strcmp(name, pte->device->sline[i]->name)) {
01389             continue;
01390          }
01391          if (unistimdebug) {
01392             ast_verb(0, "Found softkey %d for device %s\n", i, name);
01393          }
01394          return i;
01395       }
01396    }
01397    return -1;
01398 }

static struct unistim_subchannel* get_sub ( struct unistim_device device,
int  type 
) [static, read]

static unsigned int get_tick_count ( void   )  [static]

Definition at line 890 of file chan_unistim.c.

References ast_tvnow().

Referenced by create_client(), do_monitor(), key_dial_page(), send_client(), send_ping(), and send_retransmit().

00891 {
00892    struct timeval now = ast_tvnow();
00893 
00894    return (now.tv_sec * 1000) + (now.tv_usec / 1000);
00895 }

static int get_to_address ( int  fd,
struct sockaddr_in *  toAddr 
) [static]

Definition at line 997 of file chan_unistim.c.

References ast_log, errno, len(), and LOG_WARNING.

Referenced by create_client().

00998 {
00999 #ifdef HAVE_PKTINFO
01000    int err;
01001    struct msghdr msg;
01002    struct {
01003       struct cmsghdr cm;
01004       int len;
01005       struct in_addr address;
01006    } ip_msg;
01007 
01008    /* Zero out the structures before we use them */
01009    /* This sets several key values to NULL */
01010    memset(&msg, 0, sizeof(msg));
01011    memset(&ip_msg, 0, sizeof(ip_msg));
01012 
01013    /* Initialize the message structure */
01014    msg.msg_control = &ip_msg;
01015    msg.msg_controllen = sizeof(ip_msg);
01016    /* Get info about the incoming packet */
01017    err = recvmsg(fd, &msg, MSG_PEEK);
01018    if (err == -1) {
01019       ast_log(LOG_WARNING, "recvmsg returned an error: %s\n", strerror(errno));
01020    }
01021    memcpy(&toAddr->sin_addr, &ip_msg.address, sizeof(struct in_addr));
01022    return err;
01023 #else
01024    memcpy(&toAddr, &public_ip, sizeof(&toAddr));
01025    return 0;
01026 #endif
01027 }

static void handle_call_incoming ( struct unistimsession s  )  [static]

Definition at line 3247 of file chan_unistim.c.

References AST_CONTROL_ANSWER, ast_log, ast_queue_control(), ast_verb, unistimsession::device, FAV_ICON_OFFHOOK_BLACK, FAV_LINE_ICON, FAVNUM, get_sub(), LOG_WARNING, unistim_device::missed_call, MUTE_OFF, unistim_line::name, unistim_device::name, NULL, unistim_device::output, OUTPUT_HANDSET, OUTPUT_SPEAKER, unistim_subchannel::owner, unistim_subchannel::parent, unistim_device::receiver_state, unistim_subchannel::rtp, send_favorite_short(), send_no_ring(), send_select_output(), send_start_timer(), send_text(), send_text_status(), unistim_device::sline, unistim_subchannel::softkey, unistim_device::ssub, start_rtp(), unistimsession::state, STATE_CALL, STATE_ONHOOK, sub, sub_hold(), SUB_REAL, SUB_RING, unistim_subchannel::subtype, TEXT_LINE2, TEXT_NORMAL, ustmtext(), unistim_device::volume, and write_history().

Referenced by handle_key_fav(), key_ringing(), and process_request().

03248 {
03249    struct unistim_subchannel *sub = NULL;
03250    int i;
03251 
03252    s->state = STATE_CALL;
03253    s->device->missed_call = 0;
03254    send_no_ring(s);
03255    sub = get_sub(s->device, SUB_RING); /* Put other SUB_REAL call on hold */
03256    if (!sub) {
03257       ast_log(LOG_WARNING, "No ringing lines on: %s\n", s->device->name);
03258       return;
03259    }
03260    /* Change icons for all ringing keys */
03261    for (i = 0; i < FAVNUM; i++) {
03262       if (!s->device->ssub[i]) { /* No sub assigned - skip */
03263          continue;
03264       }
03265       if (s->device->ssub[i]->subtype == SUB_REAL) {
03266          sub_hold(s, s->device->ssub[i]);
03267       }
03268       if (s->device->ssub[i] != sub) {
03269          continue;
03270       }
03271       if (sub->softkey == i) { /* If softkey assigned at this moment - do not erase */
03272          continue;
03273       }
03274       if (sub->softkey < 0) { /* If softkey not defined - first one used */
03275          sub->softkey = i;
03276          continue;
03277       }
03278       send_favorite_short(i, FAV_LINE_ICON, s);
03279       s->device->ssub[i] = NULL;
03280    }
03281    if (sub->softkey < 0) {
03282       ast_log(LOG_WARNING, "Can not assign softkey for incoming call on: %s\n", s->device->name);
03283       return;
03284    }
03285    send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, s);
03286    sub->parent = s->device->sline[sub->softkey];
03287    sub->subtype = SUB_REAL;
03288    if (unistimdebug) {
03289       ast_verb(0, "Handle Call Incoming for %s@%s\n", sub->parent->name,
03290                s->device->name);
03291    }
03292    start_rtp(sub);
03293    if (!sub->rtp) {
03294       ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", sub->parent->name, s->device->name);
03295       return;
03296    }
03297    if (sub->owner) {
03298       ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
03299    }
03300    send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("is on-line", s));
03301    send_text_status(s, ustmtext("       Transf        Hangup", s));
03302    send_start_timer(s);
03303 
03304    if ((s->device->output == OUTPUT_HANDSET) &&
03305       (s->device->receiver_state == STATE_ONHOOK)) {
03306       send_select_output(s, OUTPUT_SPEAKER, s->device->volume, MUTE_OFF);
03307    } else {
03308       send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
03309    }
03310    write_history(s, 'i', 0);
03311    return;
03312 }

static void handle_call_outgoing ( struct unistimsession s  )  [static]

Definition at line 3096 of file chan_unistim.c.

References ao2_cleanup, AST_CAUSE_CALL_REJECTED, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_SWITCH_CONGESTION, ast_channel_hangupcause_set(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_debug, ast_get_chan_features_pickup_config(), ast_hangup(), ast_log, ast_pickup_call(), ast_pthread_create, AST_PTHREADT_NULL, ast_queue_hangup_with_cause(), AST_STATE_DOWN, ast_strdupa, ast_verb, c, d, unistimsession::device, FAV_ICON_OFFHOOK_BLACK, get_avail_softkey(), get_sub(), unistim_device::height, LOG_ERROR, LOG_NOTICE, LOG_WARNING, MUTE_OFF, unistim_device::name, unistim_line::name, NULL, unistim_device::output, unistim_subchannel::owner, unistim_subchannel::parent, unistim_device::phone_number, RAII_VAR, unistim_subchannel::rtp, unistim_device::selected, send_favorite_short(), send_select_output(), send_start_timer(), send_text(), send_text_status(), send_tone(), unistim_device::sline, unistim_subchannel::softkey, unistim_subchannel::ss_thread, unistim_device::ssub, start_rtp(), unistimsession::state, STATE_CALL, sub, sub_hold(), SUB_REAL, sub_stop_silence(), SUB_THREEWAY, unistim_subchannel::subtype, swap_subs(), TEXT_LINE0, TEXT_LINE1, TEXT_LINE2, TEXT_NORMAL, unistim_alloc_sub(), unistim_new(), unistim_ss(), ustmtext(), and unistim_device::volume.

Referenced by do_monitor(), key_dial_page(), key_favorite(), and key_main_page().

03097 {
03098    struct ast_channel *c;
03099    struct unistim_subchannel *sub;
03100    int softkey;
03101 
03102    s->state = STATE_CALL;
03103 
03104    sub = get_sub(s->device, SUB_THREEWAY);
03105    if (sub) {
03106       /* If sub for threway call created than we use transfer behaviuor */
03107       struct unistim_subchannel *sub_trans = NULL;
03108       struct unistim_device *d = s->device;
03109 
03110       sub_trans = get_sub(d, SUB_REAL);
03111       if (sub_trans) {
03112          ast_log(LOG_WARNING, "Can't transfer while active subchannel exists!\n");
03113          return;
03114       }
03115       if (!sub->owner) {
03116          ast_log(LOG_WARNING, "Unable to find subchannel with music on hold\n");
03117          return;
03118       }
03119 
03120       sub_trans = unistim_alloc_sub(d, SUB_REAL);
03121       if (!sub_trans) {
03122          ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
03123          return;
03124       }
03125       sub_trans->parent = sub->parent;
03126       sub_stop_silence(s, sub);
03127       send_tone(s, 0, 0);
03128       /* Make new channel */
03129       c = unistim_new(sub_trans, AST_STATE_DOWN, NULL, NULL);
03130       if (!c) {
03131          ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", sub->parent);
03132          return;
03133       }
03134       /* Swap things around between the three-way and real call */
03135       swap_subs(sub, sub_trans);
03136       send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
03137       if (s->device->height == 1) {
03138          send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
03139       } else {
03140          send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling (pre-transfer)", s));
03141          send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
03142          send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Dialing...", s));
03143       }
03144       send_text_status(s, ustmtext("TransfrCancel", s));
03145 
03146       if (ast_pthread_create(&sub->ss_thread, NULL, unistim_ss, c)) {
03147          ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", c);
03148          sub->ss_thread = AST_PTHREADT_NULL;
03149          ast_hangup(c);
03150          return;
03151       }
03152       if (unistimdebug) {
03153          ast_verb(0, "Started three way call on channel %p (%s) subchan %u\n",
03154              sub_trans->owner, ast_channel_name(sub_trans->owner), sub_trans->subtype);
03155       }
03156       return;
03157    }
03158 
03159    softkey = get_avail_softkey(s, NULL);
03160    if (softkey == -1) {
03161       ast_log(LOG_WARNING, "Have no avail softkey for calling\n");
03162       return;
03163    }
03164    sub = get_sub(s->device, SUB_REAL);
03165    if (sub) { /* have already call assigned */
03166       sub_hold(s, sub); /* Need to put on hold */
03167    }
03168    if (!(sub = unistim_alloc_sub(s->device, SUB_REAL))) {
03169       ast_log(LOG_WARNING, "Unable to allocate subchannel!\n");
03170       return;
03171    }
03172    sub->parent = s->device->sline[softkey];
03173    s->device->ssub[softkey] = sub;
03174    sub->softkey = softkey;
03175 
03176    if (unistimdebug) {
03177       ast_verb(0, "Using softkey %d, line %p\n", sub->softkey, sub->parent);
03178    }
03179    send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, s);
03180    s->device->selected = -1;
03181    if (!sub->owner) {            /* A call is already in progress ? */
03182       RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
03183       const char *pickupexten;
03184 
03185       c = unistim_new(sub, AST_STATE_DOWN, NULL, NULL);   /* No, starting a new one */
03186       if (!sub->rtp) { /* Need to start RTP before calling ast_pbx_run */
03187          start_rtp(sub);
03188       }
03189       if (c) {
03190          ast_channel_lock(c);
03191          pickup_cfg = ast_get_chan_features_pickup_config(c);
03192          if (!pickup_cfg) {
03193             ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
03194             pickupexten = "";
03195          } else {
03196             pickupexten = ast_strdupa(pickup_cfg->pickupexten);
03197          }
03198          ast_channel_unlock(c);
03199       }
03200       if (c && !strcmp(s->device->phone_number, pickupexten)) {
03201          if (unistimdebug) {
03202             ast_verb(0, "Try to pickup in unistim_new\n");
03203          }
03204          send_text(TEXT_LINE0, TEXT_NORMAL, s, "");
03205          send_text_status(s, ustmtext("       Transf        Hangup", s));
03206          send_start_timer(s);
03207          if (ast_pickup_call(c)) {
03208             ast_log(LOG_NOTICE, "Nothing to pick up\n");
03209             ast_channel_hangupcause_set(c, AST_CAUSE_CALL_REJECTED);
03210          } else {
03211             ast_channel_hangupcause_set(c, AST_CAUSE_NORMAL_CLEARING);
03212          }
03213          ast_hangup(c);
03214          c = NULL;
03215                 } else if (c) {
03216          send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
03217          send_tone(s, 0, 0); /* Dialing empty number should also stop dial tone */
03218          if (s->device->height == 1) {
03219             if (strlen(s->device->phone_number) > 0) {
03220                send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
03221             } else {
03222                send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling...", s));
03223             }
03224          } else {
03225             send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling :", s));
03226             send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
03227             send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Dialing...", s));
03228          }
03229          send_text_status(s, ustmtext("                     Hangup", s));
03230 
03231          /* start switch */
03232          if (ast_pthread_create(&sub->ss_thread, NULL, unistim_ss, c)) {
03233             ast_log(LOG_WARNING, "Unable to create switch thread\n");
03234             sub->ss_thread = AST_PTHREADT_NULL;
03235             ast_queue_hangup_with_cause(c, AST_CAUSE_SWITCH_CONGESTION);
03236          }
03237       } else
03238          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n",
03239                sub->parent->name, s->device->name);
03240    } else {
03241       ast_debug(1, "Current sub [%s] already has owner\n", ast_channel_name(sub->owner));
03242    }
03243    return;
03244 }

static void handle_dial_page ( struct unistimsession pte  )  [static]

Definition at line 2968 of file chan_unistim.c.

References ast_copy_string(), ast_strlen_zero, unistim_device::call_forward, change_favorite_icon(), unistimsession::device, FAV_ICON_NONE, FAV_ICON_PHONE_BLACK, unistim_device::height, unistim_device::lastmsgssent, LED_BAR_OFF, unistim_device::missed_call, MUTE_OFF, unistim_device::output, OUTPUT_HANDSET, OUTPUT_SPEAKER, unistim_device::phone_number, unistim_device::receiver_state, unistim_device::redial_number, send_dial_tone(), send_icon(), send_led_update(), send_select_output(), send_text(), send_text_status(), show_phone_number(), unistim_device::size_phone_number, unistimsession::state, STATE_DIALPAGE, STATE_ONHOOK, TEXT_LINE0, TEXT_LINE1, TEXT_NORMAL, ustmtext(), and unistim_device::volume.

Referenced by handle_key_fav(), key_main_page(), process_request(), and transfer_call_step1().

02969 {
02970    pte->state = STATE_DIALPAGE;
02971    if (pte->device->call_forward[0] == -1) {
02972       send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
02973       send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Enter forward", pte));
02974       send_text_status(pte, ustmtext("Fwd    Cancel BackSp Erase", pte));
02975       if (pte->device->call_forward[1] != 0) {
02976          ast_copy_string(pte->device->phone_number, pte->device->call_forward + 1,
02977                      sizeof(pte->device->phone_number));
02978          show_phone_number(pte);
02979          send_led_update(pte, LED_BAR_OFF);
02980          return;
02981       }
02982    } else {
02983       if ((pte->device->output == OUTPUT_HANDSET) &&
02984          (pte->device->receiver_state == STATE_ONHOOK)) {
02985          send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
02986       } else {
02987          send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
02988       }
02989       send_dial_tone(pte);
02990 
02991       if (pte->device->height > 1) {
02992          send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Enter the number to dial", pte));
02993          send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("and press Call", pte));
02994       }
02995       if (ast_strlen_zero(pte->device->redial_number)) {
02996          send_text_status(pte, ustmtext("Call          BackSp Erase", pte));
02997       } else {
02998          send_text_status(pte, ustmtext("Call   Redial BackSp Erase", pte));
02999       }
03000    }
03001 
03002    pte->device->size_phone_number = 0;
03003    pte->device->phone_number[0] = 0;
03004    show_phone_number(pte);
03005    change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
03006    send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
03007    pte->device->missed_call = 0;
03008    send_led_update(pte, LED_BAR_OFF);
03009    pte->device->lastmsgssent = -1;
03010    return;
03011 }

static void handle_key_fav ( struct unistimsession pte,
char  keycode 
) [static]

Definition at line 3353 of file chan_unistim.c.

References ast_verb, unistimsession::device, FAV_LINE_ICON, get_sub(), handle_call_incoming(), handle_dial_page(), is_key_favorite(), is_key_line(), KEY_FAV0, key_favorite(), MUTE_OFF, unistim_device::output, OUTPUT_HANDSET, OUTPUT_SPEAKER, unistim_device::receiver_state, unistim_device::selected, send_callerid_screen(), send_favorite_selected(), send_select_output(), send_stop_timer(), send_tone(), show_main_page(), unistim_subchannel::softkey, unistim_device::ssub, unistimsession::state, STATE_CALL, STATE_DIALPAGE, STATE_ONHOOK, sub, sub_hold(), SUB_ONHOLD, SUB_REAL, SUB_RING, sub_unhold(), unistim_subchannel::subtype, and unistim_device::volume.

Referenced by key_call(), key_dial_page(), key_main_page(), and key_ringing().

03354 {
03355    int keynum = keycode - KEY_FAV0;
03356    struct unistim_subchannel *sub;
03357 
03358    sub = get_sub(pte->device, SUB_REAL);
03359 
03360    /* Make an action on selected favorite key */
03361    if (!pte->device->ssub[keynum]) { /* Key have no assigned call */
03362       send_favorite_selected(FAV_LINE_ICON, pte);
03363       if (is_key_line(pte->device, keynum)) {
03364          if (unistimdebug) {
03365             ast_verb(0, "Handle line w/o sub - dialpage\n");
03366          }
03367          pte->device->selected = keynum;
03368          sub_hold(pte, sub); /* Put active call on hold */
03369          send_stop_timer(pte);
03370          handle_dial_page(pte);
03371       } else if (is_key_favorite(pte->device, keynum)) {
03372          /* Put active call on hold in handle_call_outgoing function, after preparation and
03373           checking if lines available for calling */
03374          if (unistimdebug) {
03375             ast_verb(0, "Handle favorite w/o sub - dialing\n");
03376          }
03377          if ((pte->device->output == OUTPUT_HANDSET) &&
03378             (pte->device->receiver_state == STATE_ONHOOK)) {
03379             send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
03380          } else {
03381             send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
03382          }
03383          key_favorite(pte, keycode);
03384       }
03385    } else {
03386       sub = pte->device->ssub[keynum];
03387       /* Favicon have assigned sub, activate it and put current on hold */
03388       if (sub->subtype == SUB_REAL) {
03389          sub_hold(pte, sub);
03390          show_main_page(pte);
03391       } else if (sub->subtype == SUB_RING) {
03392          sub->softkey = keynum;
03393          handle_call_incoming(pte);
03394       } else if (sub->subtype == SUB_ONHOLD) {
03395          if (pte->state == STATE_DIALPAGE){
03396             send_tone(pte, 0, 0);
03397          }
03398          send_callerid_screen(pte, sub);
03399          sub_unhold(pte, sub);
03400          pte->state = STATE_CALL;
03401       }
03402    }
03403 }

static void handle_select_codec ( struct unistimsession pte  )  [static]

Definition at line 3697 of file chan_unistim.c.

References ast_copy_string(), buf, buf2, unistim_device::codec_number, unistimsession::device, SELECTCODEC_MSG, SELECTCODEC_START_ENTRY_POS, send_blink_cursor(), send_cursor_pos(), send_text(), send_text_status(), unistimsession::size_buff_entry, unistimsession::state, STATE_SELECTCODEC, TEXT_INVERSE, TEXT_LINE0, TEXT_LINE1, TEXT_LINE2, TEXT_NORMAL, and ustmtext().

03698 {
03699    char buf[30], buf2[5];
03700 
03701    pte->state = STATE_SELECTCODEC;
03702    ast_copy_string(buf, ustmtext("Using codec", pte), sizeof(buf));
03703    snprintf(buf2, sizeof(buf2), " %d", pte->device->codec_number);
03704    strcat(buf, buf2);
03705    strcat(buf, " (G711u=0,");
03706 
03707    send_text(TEXT_LINE0, TEXT_NORMAL, pte, buf);
03708    send_text(TEXT_LINE1, TEXT_NORMAL, pte, "G723=4,G711a=8,G729A=18)");
03709    send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
03710    send_blink_cursor(pte);
03711    send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
03712    pte->size_buff_entry = 0;
03713    send_text_status(pte, ustmtext("Select BackSp Erase  Cancel", pte));
03714    return;
03715 }

static void handle_select_language ( struct unistimsession pte  )  [static]

Definition at line 3784 of file chan_unistim.c.

References ast_copy_string(), unistimsession::buff_entry, unistimsession::device, unistim_languages::encoding, find_language(), unistim_languages::label, unistim_languages::lang_short, unistim_device::language, send_charset_update(), send_text(), send_text_status(), unistimsession::size_buff_entry, unistimsession::state, STATE_SELECTLANGUAGE, TEXT_LINE0, TEXT_NORMAL, and ustmtext().

Referenced by key_select_language().

03785 {
03786    char tmp_language[40];
03787    struct unistim_languages lang;
03788 
03789    if (pte->state != STATE_SELECTLANGUAGE) {
03790       pte->state = STATE_SELECTLANGUAGE;
03791       pte->size_buff_entry = 1;
03792       pte->buff_entry[0] = find_language(pte->device->language);
03793    }
03794    lang = options_languages[(int)pte->buff_entry[0]];
03795    ast_copy_string(tmp_language, pte->device->language, sizeof(tmp_language));
03796    ast_copy_string(pte->device->language, lang.lang_short, sizeof(pte->device->language));
03797    send_charset_update(pte, lang.encoding);
03798    send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext(lang.label, pte));
03799 
03800    ast_copy_string(pte->device->language, tmp_language, sizeof(pte->device->language));
03801    lang = options_languages[find_language(pte->device->language)];
03802    send_charset_update(pte, lang.encoding);
03803    send_text_status(pte, ustmtext("Select               Cancel", pte));
03804    return;
03805 }

static void handle_select_option ( struct unistimsession pte  )  [static]

Definition at line 3652 of file chan_unistim.c.

References unistimsession::buff_entry, unistim_menu_item::label, send_text(), send_text_status(), unistimsession::size_buff_entry, unistimsession::state, STATE_SELECTOPTION, TEXT_LINE0, TEXT_NORMAL, tmp(), and ustmtext().

Referenced by key_main_page(), key_select_language(), and key_select_option().

03653 {
03654    char tmp[128];
03655 
03656    if (pte->state != STATE_SELECTOPTION) {
03657       pte->state = STATE_SELECTOPTION;
03658       pte->size_buff_entry = 1;
03659       pte->buff_entry[0] = 0; /* Position in menu */
03660    }
03661    snprintf(tmp, sizeof(tmp), "%d. %s", pte->buff_entry[0] + 1, ustmtext(options_menu[(int)pte->buff_entry[0]].label, pte));
03662    send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmp);
03663    send_text_status(pte, ustmtext("Select               Cancel", pte));
03664    return;
03665 }

static void ignore_call ( struct unistimsession pte  )  [static]

Definition at line 2611 of file chan_unistim.c.

References send_no_ring().

Referenced by key_ringing().

02612 {
02613    send_no_ring(pte);
02614    return;
02615 }

static void in_band_indication ( struct ast_channel ast,
const struct ast_tone_zone tz,
const char *  indication 
) [static]

Definition at line 5284 of file chan_unistim.c.

References ast_get_indication_tone(), ast_log, ast_playtones_start(), ast_tone_zone_sound_unref(), ast_tone_zone_sound::data, LOG_WARNING, and NULL.

Referenced by unistim_indicate().

05286 {
05287    struct ast_tone_zone_sound *ts = NULL;
05288 
05289    if ((ts = ast_get_indication_tone(tz, indication))) {
05290       ast_playtones_start(ast, 0, ts->data, 1);
05291       ts = ast_tone_zone_sound_unref(ts);
05292    } else {
05293       ast_log(LOG_WARNING, "Unable to get indication tone for %s\n", indication);
05294    }
05295 }

static void init_phone_step2 ( struct unistimsession pte  )  [static]

Definition at line 4346 of file chan_unistim.c.

References ast_verb, AUTOPROVISIONING_TN, BUFFSEND, unistim_device::contrast, unistimsession::device, unistim_languages::encoding, FAVNUM, find_language(), unistim_device::language, LED_BAR_OFF, unistimsession::macaddr, NULL, refresh_all_favorite(), send_charset_update(), send_client(), send_date_time2(), send_date_time3(), send_favorite(), send_led_update(), send_no_ring(), send_ping(), send_text(), send_text_status(), send_texttitle(), show_extension_page(), show_main_page(), SIZE_HEADER, unistimsession::state, STATE_MAINPAGE, TEXT_LINE0, TEXT_LINE1, TEXT_LINE2, TEXT_NORMAL, tmp(), and ustmtext().

Referenced by process_request().

04347 {
04348    BUFFSEND;
04349    if (unistimdebug) {
04350       ast_verb(0, "Sending S4\n");
04351    }
04352    memcpy(buffsend + SIZE_HEADER, packet_send_s4, sizeof(packet_send_s4));
04353    send_client(SIZE_HEADER + sizeof(packet_send_s4), buffsend, pte);
04354    send_date_time2(pte);
04355    send_date_time3(pte);
04356    if (unistimdebug) {
04357       ast_verb(0, "Sending S7\n");
04358    }
04359    memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
04360    send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
04361    if (unistimdebug) {
04362       ast_verb(0, "Sending Contrast\n");
04363    }
04364    memcpy(buffsend + SIZE_HEADER, packet_send_Contrast, sizeof(packet_send_Contrast));
04365    if (pte->device != NULL) {
04366       buffsend[9] = pte->device->contrast;
04367    }
04368    send_client(SIZE_HEADER + sizeof(packet_send_Contrast), buffsend, pte);
04369 
04370    if (unistimdebug) {
04371       ast_verb(0, "Sending S9\n");
04372    }
04373    memcpy(buffsend + SIZE_HEADER, packet_send_s9, sizeof(packet_send_s9));
04374    send_client(SIZE_HEADER + sizeof(packet_send_s9), buffsend, pte);
04375    send_no_ring(pte);
04376 
04377    if (unistimdebug) {
04378       ast_verb(0, "Sending S7\n");
04379    }
04380    memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
04381    send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
04382    send_led_update(pte, LED_BAR_OFF);
04383    send_ping(pte);
04384    if (unistimdebug) {
04385       ast_verb(0, "Sending init language\n");
04386    }
04387    if (pte->device) {
04388       send_charset_update(pte, options_languages[find_language(pte->device->language)].encoding);
04389    }
04390    if (pte->state < STATE_MAINPAGE) {
04391       if (autoprovisioning == AUTOPROVISIONING_TN) {
04392          show_extension_page(pte);
04393          return;
04394       } else {
04395          int i;
04396          char tmp[30];
04397 
04398          for (i = 1; i < FAVNUM; i++) {
04399             send_favorite(i, 0, pte, "");
04400          }
04401          send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Phone is not registered", pte));
04402          send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("in unistim.conf", pte));
04403          strcpy(tmp, "MAC = ");
04404          strcat(tmp, pte->macaddr);
04405          send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
04406          send_text_status(pte, "");
04407          send_texttitle(pte, "UNISTIM for*");
04408          return;
04409       }
04410    }
04411    show_main_page(pte);
04412    refresh_all_favorite(pte);
04413    if (unistimdebug) {
04414       ast_verb(0, "Sending arrow\n");
04415    }
04416    memcpy(buffsend + SIZE_HEADER, packet_send_arrow, sizeof(packet_send_arrow));
04417    send_client(SIZE_HEADER + sizeof(packet_send_arrow), buffsend, pte);
04418    return;
04419 }

static int is_key_favorite ( struct unistim_device d,
int  fav 
) [static]

Definition at line 1337 of file chan_unistim.c.

References unistim_device::sline, and unistim_device::softkeynumber.

Referenced by handle_key_fav(), is_key_line(), and key_favorite().

01338 {
01339    if ((fav < 0) && (fav > 5)) {
01340       return 0;
01341    }
01342    if (d->sline[fav]) {
01343       return 0;
01344    }
01345    if (d->softkeynumber[fav][0] == '\0') {
01346       return 0;
01347    }
01348    return 1;
01349 }

static int is_key_line ( struct unistim_device d,
int  fav 
) [static]

Definition at line 1351 of file chan_unistim.c.

References is_key_favorite(), and unistim_device::sline.

Referenced by get_avail_softkey(), handle_key_fav(), unistim_call(), and unistim_hangup().

01352 {
01353    if ((fav < 0) && (fav > 5)) {
01354       return 0;
01355    }
01356    if (!d->sline[fav]) {
01357       return 0;
01358    }
01359    if (is_key_favorite(d, fav)) {
01360       return 0;
01361    }
01362    return 1;
01363 }

static void key_call ( struct unistimsession pte,
char  keycode 
) [static]

Definition at line 3405 of file chan_unistim.c.

References AST_STATE_UP, close_call(), unistimsession::device, get_sub(), handle_key_fav(), KEY_0, KEY_FAV0, KEY_FAV1, KEY_FAV2, KEY_FAV3, KEY_FAV4, KEY_FAV5, KEY_FUNC1, KEY_FUNC2, KEY_FUNC4, KEY_HANGUP, KEY_HEADPHN, KEY_LOUDSPK, KEY_ONHOLD, KEY_SHARP, KEY_STAR, MUTE_OFF, unistim_device::output, OUTPUT_HANDSET, OUTPUT_HEADPHONE, OUTPUT_SPEAKER, unistim_subchannel::owner, unistim_device::previous_output, unistim_device::selected, send_select_output(), unistim_device::ssub, sub, sub_hold(), SUB_REAL, SUB_THREEWAY, transfer_call_step1(), transfer_cancel_step2(), unistim_do_senddigit(), and unistim_device::volume.

Referenced by process_request().

03406 {
03407    struct unistim_subchannel *sub = get_sub(pte->device, SUB_REAL);
03408    struct unistim_subchannel *sub_3way = get_sub(pte->device, SUB_THREEWAY);
03409 
03410    if (!sub) {
03411       return;
03412    }
03413    if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
03414       if (keycode == KEY_SHARP) {
03415          keycode = '#';
03416       } else if (keycode == KEY_STAR) {
03417          keycode = '*';
03418       } else {
03419          keycode -= 0x10;
03420       }
03421       unistim_do_senddigit(pte, keycode);
03422       return;
03423    }
03424    switch (keycode) {
03425    case KEY_FUNC1:
03426       if (sub->owner && ast_channel_state(sub->owner) == AST_STATE_UP) {
03427          if (sub_3way) {
03428             close_call(pte);
03429          }
03430       }
03431       break;
03432    case KEY_FUNC2:
03433       if (sub_3way) {
03434          transfer_cancel_step2(pte);
03435       } else if (ast_channel_state(sub->owner) == AST_STATE_UP) {
03436          transfer_call_step1(pte);
03437       }
03438       break;
03439    case KEY_HANGUP:
03440    case KEY_FUNC4:
03441       if (!sub_3way) {
03442          close_call(pte);
03443       }
03444       break;
03445    case KEY_FAV0:
03446    case KEY_FAV1:
03447    case KEY_FAV2:
03448    case KEY_FAV3:
03449    case KEY_FAV4:
03450    case KEY_FAV5:
03451       handle_key_fav(pte, keycode);
03452       break;
03453    case KEY_HEADPHN:
03454       if (pte->device->output == OUTPUT_HEADPHONE) {
03455          send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
03456       } else {
03457          send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
03458       }
03459       break;
03460    case KEY_LOUDSPK:
03461       if (pte->device->output != OUTPUT_SPEAKER)
03462          send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
03463       else
03464          send_select_output(pte, pte->device->previous_output, pte->device->volume,
03465                       MUTE_OFF);
03466       break;
03467    case KEY_ONHOLD:
03468       if (!sub) {
03469          if(pte->device->ssub[pte->device->selected]) {
03470             sub_hold(pte, pte->device->ssub[pte->device->selected]);
03471          }
03472       } else {
03473          sub_hold(pte, sub);
03474       }
03475       break;
03476    }
03477    return;
03478 }

static void key_dial_page ( struct unistimsession pte,
char  keycode 
) [static]

Definition at line 3526 of file chan_unistim.c.

References ast_copy_string(), ast_exists_extension(), ast_matchmore_extension(), ast_queue_unhold(), ast_strlen_zero, unistim_device::call_forward, unistim_device::context, unistimsession::device, FAV_LINE_ICON, get_sub(), get_tick_count(), handle_call_outgoing(), handle_key_fav(), unistim_device::interdigit_timer, KEY_0, KEY_FAV0, KEY_FAV1, KEY_FAV2, KEY_FAV3, KEY_FAV4, KEY_FAV5, KEY_FUNC1, KEY_FUNC2, KEY_FUNC3, KEY_FUNC4, KEY_HANGUP, KEY_HEADPHN, KEY_LOUDSPK, KEY_SHARP, KEY_STAR, LED_HEADPHONE_OFF, LED_SPEAKER_OFF, unistim_subchannel::moh, MUTE_OFF, unistim_device::nextdial, NULL, unistim_device::output, OUTPUT_HANDSET, OUTPUT_HEADPHONE, OUTPUT_SPEAKER, unistim_subchannel::owner, unistim_device::phone_number, unistim_device::previous_output, unistim_device::receiver_state, unistim_device::redial_number, unistim_device::selected, send_callerid_screen(), send_favorite_selected(), send_led_update(), send_select_output(), send_text_status(), send_tone(), unistim_device::sharp_dial, show_main_page(), show_phone_number(), unistim_device::size_phone_number, unistimsession::state, STATE_CALL, STATE_OFFHOOK, sub, SUB_REAL, sub_stop_silence(), SUB_THREEWAY, unistim_subchannel::subtype, ustmtext(), and unistim_device::volume.

Referenced by key_main_page(), and process_request().

03527 {
03528    struct unistim_subchannel *sub = get_sub(pte->device, SUB_THREEWAY);
03529 
03530    pte->device->nextdial = 0;
03531    if (keycode == KEY_FUNC3) {
03532       if (pte->device->size_phone_number <= 1) {
03533          keycode = KEY_FUNC4;
03534       } else {
03535          pte->device->size_phone_number -= 2;
03536          keycode = pte->device->phone_number[pte->device->size_phone_number] + 0x10;
03537       }
03538    }
03539    if (keycode == KEY_SHARP && pte->device->sharp_dial == 1) {
03540       keycode = KEY_FUNC1;
03541    }
03542    if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
03543       int i = pte->device->size_phone_number;
03544 
03545       if (pte->device->size_phone_number == 0) {
03546          send_tone(pte, 0, 0);
03547       }
03548       if (keycode == KEY_SHARP) {
03549          keycode = '#';
03550       } else if (keycode == KEY_STAR) {
03551          keycode = '*';
03552       } else {
03553          keycode -= 0x10;
03554       }
03555       pte->device->phone_number[i] = keycode;
03556       pte->device->size_phone_number++;
03557       pte->device->phone_number[i + 1] = 0;
03558       show_phone_number(pte);
03559 
03560       if (ast_exists_extension(NULL, pte->device->context, pte->device->phone_number, 1, NULL) &&
03561          !ast_matchmore_extension(NULL, pte->device->context, pte->device->phone_number, 1, NULL)) {
03562          keycode = KEY_FUNC1;
03563       } else {
03564          if (pte->device->interdigit_timer) {
03565             pte->device->nextdial = get_tick_count() + pte->device->interdigit_timer;
03566          }
03567       }
03568    }
03569    if (keycode == KEY_FUNC4) {
03570       pte->device->size_phone_number = 0;
03571       show_phone_number(pte);
03572       return;
03573    }
03574 
03575    if (pte->device->call_forward[0] == -1) {
03576       if (keycode == KEY_FUNC1) {
03577          ast_copy_string(pte->device->call_forward, pte->device->phone_number,
03578                      sizeof(pte->device->call_forward));
03579          show_main_page(pte);
03580       } else if ((keycode == KEY_FUNC2) || (keycode == KEY_HANGUP)) {
03581          pte->device->call_forward[0] = '\0';
03582          send_led_update(pte, LED_SPEAKER_OFF);
03583          send_led_update(pte, LED_HEADPHONE_OFF);
03584          show_main_page(pte);
03585       }
03586       return;
03587    }
03588    switch (keycode) {
03589    case KEY_FUNC2:
03590       if (ast_strlen_zero(pte->device->redial_number)) {
03591          break;
03592       }
03593       ast_copy_string(pte->device->phone_number, pte->device->redial_number,
03594                   sizeof(pte->device->phone_number));
03595    case KEY_FUNC1:
03596       handle_call_outgoing(pte);
03597       break;
03598    case KEY_HANGUP:
03599       if (sub && sub->owner) {
03600          sub_stop_silence(pte, sub);
03601          send_tone(pte, 0, 0);
03602          ast_queue_unhold(sub->owner);
03603          sub->moh = 0;
03604          sub->subtype = SUB_REAL;
03605          pte->state = STATE_CALL;
03606 
03607          send_text_status(pte, ustmtext("       Transf        Hangup", pte));
03608          send_callerid_screen(pte, sub);
03609       } else {
03610          send_led_update(pte, LED_SPEAKER_OFF);
03611          send_led_update(pte, LED_HEADPHONE_OFF);
03612          show_main_page(pte);
03613       }
03614       break;
03615    case KEY_FAV0:
03616    case KEY_FAV1:
03617    case KEY_FAV2:
03618    case KEY_FAV3:
03619    case KEY_FAV4:
03620    case KEY_FAV5:
03621       send_favorite_selected(FAV_LINE_ICON, pte);
03622       pte->device->selected = -1;
03623       handle_key_fav(pte, keycode);
03624       break;
03625    case KEY_LOUDSPK:
03626       if (pte->device->output == OUTPUT_SPEAKER) {
03627          if (pte->device->receiver_state == STATE_OFFHOOK) {
03628             send_select_output(pte, pte->device->previous_output, pte->device->volume,
03629                          MUTE_OFF);
03630          } else {
03631             show_main_page(pte);
03632          }
03633       } else {
03634          send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
03635       }
03636       break;
03637    case KEY_HEADPHN:
03638       if (pte->device->output == OUTPUT_HEADPHONE) {
03639          if (pte->device->receiver_state == STATE_OFFHOOK) {
03640             send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
03641          } else {
03642             show_main_page(pte);
03643          }
03644       } else {
03645          send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
03646       }
03647       break;
03648    }
03649    return;
03650 }

static void key_favorite ( struct unistimsession pte,
char  keycode 
) [static]

Definition at line 3513 of file chan_unistim.c.

References ast_copy_string(), ast_log, unistimsession::device, handle_call_outgoing(), is_key_favorite(), KEY_FAV0, LOG_WARNING, unistim_device::phone_number, and unistim_device::softkeynumber.

Referenced by handle_key_fav().

03514 {
03515    int fav = keycode - KEY_FAV0;
03516    if (!is_key_favorite(pte->device, fav)) {
03517       ast_log(LOG_WARNING, "It's not a favorite key\n");
03518       return;
03519    }
03520    ast_copy_string(pte->device->phone_number, pte->device->softkeynumber[fav],
03521                sizeof(pte->device->phone_number));
03522    handle_call_outgoing(pte);
03523    return;
03524 }

static void key_history ( struct unistimsession pte,
char  keycode 
) [static]

Definition at line 4259 of file chan_unistim.c.

References ast_copy_string(), ast_strlen_zero, unistimsession::buff_entry, unistimsession::device, display_last_error(), f, unistim_device::height, KEY_DOWN, KEY_FUNC1, KEY_FUNC2, KEY_FUNC3, KEY_FUNC4, KEY_HANGUP, KEY_LEFT, key_main_page(), KEY_RCVHIST, KEY_RIGHT, KEY_SNDHIST, KEY_UP, unistim_device::lst_cid, open_history(), unistim_device::redial_number, show_entry_history(), show_history(), show_main_page(), and TEXT_LENGTH_MAX.

Referenced by process_request().

04260 {
04261    FILE *f;
04262    char count;
04263    long offset;
04264    int flag = 0;
04265 
04266    switch (keycode) {
04267    case KEY_LEFT:
04268       if (pte->device->height == 1) {
04269          if (pte->buff_entry[3] <= 1) {
04270             return;
04271          }
04272          pte->buff_entry[3]--;
04273          flag = 1;
04274          break;
04275       }
04276    case KEY_UP:
04277    case KEY_FUNC1:
04278       if (pte->buff_entry[2] <= 1) {
04279          return;
04280       }
04281       pte->buff_entry[2]--;
04282       flag = 1;
04283       break;
04284    case KEY_RIGHT:
04285       if (pte->device->height == 1) {
04286          if (pte->buff_entry[3] == 3) {
04287             return;
04288          }
04289          pte->buff_entry[3]++;
04290          flag = 1;
04291          break;
04292       }
04293    case KEY_DOWN:
04294    case KEY_FUNC2:
04295       if (pte->buff_entry[2] >= pte->buff_entry[1]) {
04296          return;
04297       }
04298       pte->buff_entry[2]++;
04299       flag = 1;
04300       break;
04301    case KEY_FUNC3:
04302       if (ast_strlen_zero(pte->device->lst_cid)) {
04303          break;
04304       }
04305       ast_copy_string(pte->device->redial_number, pte->device->lst_cid,
04306                   sizeof(pte->device->redial_number));
04307       key_main_page(pte, KEY_FUNC2);
04308       break;
04309    case KEY_FUNC4:
04310    case KEY_HANGUP:
04311       show_main_page(pte);
04312       break;
04313    case KEY_SNDHIST:
04314       if (pte->buff_entry[0] == 'i') {
04315          show_history(pte, 'o');
04316       } else {
04317          show_main_page(pte);
04318       }
04319       break;
04320    case KEY_RCVHIST:
04321       if (pte->buff_entry[0] == 'i') {
04322          show_main_page(pte);
04323       } else {
04324          show_history(pte, 'i');
04325       }
04326       break;
04327    }
04328 
04329    if (flag) {
04330       count = open_history(pte, pte->buff_entry[0], &f);
04331       if (!count) {
04332          return;
04333       }
04334       offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
04335       if (fseek(f, offset, SEEK_CUR)) {
04336          display_last_error("Unable to seek history entry.");
04337          fclose(f);
04338          return;
04339       }
04340       show_entry_history(pte, &f);
04341    }
04342 
04343    return;
04344 }

static void key_main_page ( struct unistimsession pte,
char  keycode 
) [static]

Definition at line 4156 of file chan_unistim.c.

References ao2_cleanup, ast_copy_string(), ast_get_chan_features_pickup_config(), ast_log, ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero, unistimsession::buff_entry, unistim_device::call_forward, unistimsession::device, devicelock, unistim_device::extension, EXTENSION_ASK, unistim_device::extension_number, EXTENSION_TN, FAV_ICON_NONE, get_avail_softkey(), handle_call_outgoing(), handle_dial_page(), handle_key_fav(), handle_select_option(), unistim_device::id, KEY_0, KEY_CONF, key_dial_page(), KEY_FAV0, KEY_FAV1, KEY_FAV2, KEY_FAV3, KEY_FAV4, KEY_FAV5, KEY_FUNC1, KEY_FUNC2, KEY_FUNC3, KEY_FUNC4, KEY_HEADPHN, KEY_LOUDSPK, KEY_RCVHIST, KEY_SHARP, KEY_SNDHIST, LOG_ERROR, unistim_device::missed_call, MUTE_OFF, NULL, unistim_device::output, OUTPUT_HANDSET, OUTPUT_HEADPHONE, OUTPUT_SPEAKER, unistim_device::phone_number, RAII_VAR, unistim_device::receiver_state, unistim_device::redial_number, unistim_device::selected, send_icon(), send_select_output(), unistim_device::session, show_extension_page(), show_history(), show_main_page(), unistimsession::size_buff_entry, STATE_ONHOOK, TEXT_LINE0, unregister_extension(), and unistim_device::volume.

Referenced by key_history(), and process_request().

04157 {
04158    if (pte->device->missed_call) {
04159       send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
04160       pte->device->missed_call = 0;
04161    }
04162    if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
04163       handle_dial_page(pte);
04164       key_dial_page(pte, keycode);
04165       return;
04166    }
04167    switch (keycode) {
04168    case KEY_FUNC1:
04169       pte->device->selected = get_avail_softkey(pte, NULL);
04170       handle_dial_page(pte);
04171       break;
04172    case KEY_FUNC2:
04173       if (ast_strlen_zero(pte->device->redial_number)) {
04174          break;
04175       }
04176       if ((pte->device->output == OUTPUT_HANDSET) &&
04177          (pte->device->receiver_state == STATE_ONHOOK)) {
04178          send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
04179       } else {
04180          send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
04181       }
04182       ast_copy_string(pte->device->phone_number, pte->device->redial_number,
04183                   sizeof(pte->device->phone_number));
04184       handle_call_outgoing(pte);
04185       break;
04186    case KEY_FUNC3:
04187       if (!ast_strlen_zero(pte->device->call_forward)) {
04188          /* Cancel call forwarding */
04189          memmove(pte->device->call_forward + 1, pte->device->call_forward,
04190                sizeof(pte->device->call_forward) - 1);
04191          pte->device->call_forward[0] = '\0';
04192          send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
04193          pte->device->output = OUTPUT_HANDSET;   /* Seems to be reseted somewhere */
04194          show_main_page(pte);
04195          break;
04196       }
04197       pte->device->call_forward[0] = -1;
04198       handle_dial_page(pte);
04199       break;
04200    case KEY_FUNC4:
04201       if (pte->device->extension == EXTENSION_ASK) {
04202          unregister_extension(pte);
04203          pte->device->extension_number[0] = '\0';
04204          show_extension_page(pte);
04205       } else if (pte->device->extension == EXTENSION_TN) {
04206          ast_mutex_lock(&devicelock);
04207          strcpy(pte->device->id, pte->device->extension_number);
04208          pte->buff_entry[0] = '\0';
04209          pte->size_buff_entry = 0;
04210          pte->device->session = NULL;
04211          pte->device = NULL;
04212          ast_mutex_unlock(&devicelock);
04213          show_extension_page(pte);
04214       } else { /* Pickup function */
04215          /* XXX Is there a way to get a specific channel here? */
04216          RAII_VAR(struct ast_features_pickup_config *, pickup_cfg,
04217                ast_get_chan_features_pickup_config(NULL), ao2_cleanup);
04218 
04219          if (!pickup_cfg) {
04220             ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
04221             break;
04222          }
04223 
04224          pte->device->selected = -1;
04225          ast_copy_string(pte->device->phone_number, pickup_cfg->pickupexten,
04226                   sizeof(pte->device->phone_number));
04227          handle_call_outgoing(pte);
04228                 }
04229       break;
04230    case KEY_FAV0:
04231    case KEY_FAV1:
04232    case KEY_FAV2:
04233    case KEY_FAV3:
04234    case KEY_FAV4:
04235    case KEY_FAV5:
04236       handle_key_fav(pte, keycode);
04237       break;
04238    case KEY_CONF:
04239       handle_select_option(pte);
04240       break;
04241    case KEY_LOUDSPK:
04242       send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
04243       handle_dial_page(pte);
04244       break;
04245    case KEY_HEADPHN:
04246       send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
04247       handle_dial_page(pte);
04248       break;
04249    case KEY_SNDHIST:
04250       show_history(pte, 'o');
04251       break;
04252    case KEY_RCVHIST:
04253       show_history(pte, 'i');
04254       break;
04255    }
04256    return;
04257 }

static void key_ringing ( struct unistimsession pte,
char  keycode 
) [static]

Definition at line 3480 of file chan_unistim.c.

References unistimsession::device, discard_call(), handle_call_incoming(), handle_key_fav(), ignore_call(), KEY_FAV0, KEY_FAV1, KEY_FAV2, KEY_FAV3, KEY_FAV4, KEY_FAV5, KEY_FUNC1, KEY_FUNC3, KEY_FUNC4, KEY_HANGUP, KEY_HEADPHN, KEY_LOUDSPK, unistim_device::output, OUTPUT_HEADPHONE, and OUTPUT_SPEAKER.

Referenced by process_request().

03481 {
03482    switch (keycode) {
03483    case KEY_FAV0:
03484    case KEY_FAV1:
03485    case KEY_FAV2:
03486    case KEY_FAV3:
03487    case KEY_FAV4:
03488    case KEY_FAV5:
03489       handle_key_fav(pte, keycode);
03490       break;
03491    case KEY_FUNC3:
03492       ignore_call(pte);
03493       break;
03494    case KEY_HANGUP:
03495    case KEY_FUNC4:
03496       discard_call(pte);
03497       break;
03498    case KEY_LOUDSPK:
03499       pte->device->output = OUTPUT_SPEAKER;
03500       handle_call_incoming(pte);
03501       break;
03502    case KEY_HEADPHN:
03503       pte->device->output = OUTPUT_HEADPHONE;
03504       handle_call_incoming(pte);
03505       break;
03506    case KEY_FUNC1:
03507       handle_call_incoming(pte);
03508       break;
03509    }
03510    return;
03511 }

static void key_select_codec ( struct unistimsession pte,
char  keycode 
) [static]

Definition at line 3717 of file chan_unistim.c.

References unistimsession::buff_entry, unistim_device::codec_number, unistimsession::device, KEY_0, KEY_9, KEY_FUNC1, KEY_FUNC2, KEY_FUNC3, KEY_FUNC4, KEY_HANGUP, SELECTCODEC_MAX_LENGTH, SELECTCODEC_MSG, SELECTCODEC_START_ENTRY_POS, send_blink_cursor(), send_cursor_pos(), send_text(), show_main_page(), unistimsession::size_buff_entry, TEXT_INVERSE, and TEXT_LINE2.

Referenced by process_request().

03718 {
03719    if (keycode == KEY_FUNC2) {
03720       if (pte->size_buff_entry <= 1) {
03721          keycode = KEY_FUNC3;
03722       } else {
03723          pte->size_buff_entry -= 2;
03724          keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
03725       }
03726    }
03727    if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
03728       char tmpbuf[] = SELECTCODEC_MSG;
03729       int i = 0;
03730 
03731       if (pte->size_buff_entry >= SELECTCODEC_MAX_LENGTH) {
03732          return;
03733       }
03734       while (i < pte->size_buff_entry) {
03735          tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = pte->buff_entry[i];
03736          i++;
03737       }
03738       tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = keycode - 0x10;
03739       pte->buff_entry[i] = keycode - 0x10;
03740       pte->size_buff_entry++;
03741       send_text(TEXT_LINE2, TEXT_INVERSE, pte, tmpbuf);
03742       send_blink_cursor(pte);
03743       send_cursor_pos(pte,
03744                  (unsigned char) (TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS + 1 + i));
03745       return;
03746    }
03747 
03748    switch (keycode) {
03749    case KEY_FUNC1:
03750       if (pte->size_buff_entry == 1) {
03751          pte->device->codec_number = pte->buff_entry[0] - 48;
03752       } else if (pte->size_buff_entry == 2) {
03753          pte->device->codec_number =
03754             ((pte->buff_entry[0] - 48) * 10) + (pte->buff_entry[1] - 48);
03755       }
03756       show_main_page(pte);
03757       break;
03758    case KEY_FUNC3:
03759       pte->size_buff_entry = 0;
03760       send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
03761       send_blink_cursor(pte);
03762       send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
03763       break;
03764    case KEY_HANGUP:
03765    case KEY_FUNC4:
03766       show_main_page(pte);
03767       break;
03768    }
03769    return;
03770 }

static void key_select_extension ( struct unistimsession pte,
char  keycode 
) [static]

Definition at line 3855 of file chan_unistim.c.

References ast_copy_string(), ast_mutex_lock, ast_mutex_unlock, AUTOPROVISIONING_TN, unistimsession::buff_entry, unistim_device::codec_number, d, DEFAULT_CODEC, unistimsession::device, devicelock, unistim_device::extension, unistim_device::extension_number, EXTENSION_TN, unistim_device::id, KEY_0, KEY_9, KEY_FUNC1, KEY_FUNC2, KEY_FUNC3, unistimsession::macaddr, unistim_device::missed_call, unistim_device::next, unistim_device::receiver_state, refresh_all_favorite(), register_extension(), SELECTEXTENSION_MAX_LENGTH, SELECTEXTENSION_MSG, SELECTEXTENSION_START_ENTRY_POS, send_blink_cursor(), send_cursor_pos(), send_text(), unistim_device::session, show_main_page(), unistimsession::size_buff_entry, STATE_ONHOOK, TEXT_LINE0, TEXT_LINE1, TEXT_LINE2, TEXT_NORMAL, and ustmtext().

Referenced by process_request().

03856 {
03857    if (keycode == KEY_FUNC2) {
03858       if (pte->size_buff_entry <= 1) {
03859          keycode = KEY_FUNC3;
03860       } else {
03861          pte->size_buff_entry -= 2;
03862          keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
03863       }
03864    }
03865    if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
03866       char tmpbuf[] = SELECTEXTENSION_MSG;
03867       int i = 0;
03868 
03869       if (pte->size_buff_entry >= SELECTEXTENSION_MAX_LENGTH) {
03870          return;
03871       }
03872       while (i < pte->size_buff_entry) {
03873          tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = pte->buff_entry[i];
03874          i++;
03875       }
03876       tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = keycode - 0x10;
03877       pte->buff_entry[i] = keycode - 0x10;
03878       pte->size_buff_entry++;
03879       send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
03880       send_blink_cursor(pte);
03881       send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS + 1 + i));
03882       return;
03883    }
03884 
03885    switch (keycode) {
03886    case KEY_FUNC1:
03887       if (pte->size_buff_entry < 1) {
03888          return;
03889       }
03890       if (autoprovisioning == AUTOPROVISIONING_TN) {
03891          struct unistim_device *d;
03892 
03893          /* First step : looking for this TN in our device list */
03894          ast_mutex_lock(&devicelock);
03895          d = devices;
03896          pte->buff_entry[pte->size_buff_entry] = '\0';
03897          while (d) {
03898             if (d->id[0] == 'T') {  /* It's a TN device ? */
03899                /* It's the TN we're looking for ? */
03900                if (!strcmp((d->id) + 1, pte->buff_entry)) {
03901                   pte->device = d;
03902                   d->session = pte;
03903                   d->codec_number = DEFAULT_CODEC;
03904                   d->missed_call = 0;
03905                   d->receiver_state = STATE_ONHOOK;
03906                   strcpy(d->id, pte->macaddr);
03907                   pte->device->extension_number[0] = 'T';
03908                   pte->device->extension = EXTENSION_TN;
03909                   ast_copy_string((pte->device->extension_number) + 1,
03910                               pte->buff_entry, pte->size_buff_entry + 1);
03911                   ast_mutex_unlock(&devicelock);
03912                   show_main_page(pte);
03913                   refresh_all_favorite(pte);
03914                   return;
03915                }
03916             }
03917             d = d->next;
03918          }
03919          ast_mutex_unlock(&devicelock);
03920          send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Invalid Terminal Number.", pte));
03921          send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Please try again :", pte));
03922          send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS +
03923                                  pte->size_buff_entry));
03924          send_blink_cursor(pte);
03925       } else {
03926          ast_copy_string(pte->device->extension_number, pte->buff_entry,
03927                      pte->size_buff_entry + 1);
03928          if (register_extension(pte)) {
03929             send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Invalid extension.", pte));
03930             send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Please try again :", pte));
03931             send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 +
03932                                  SELECTEXTENSION_START_ENTRY_POS +
03933                                  pte->size_buff_entry));
03934             send_blink_cursor(pte);
03935          } else
03936             show_main_page(pte);
03937       }
03938       break;
03939    case KEY_FUNC3:
03940       pte->size_buff_entry = 0;
03941       send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
03942       send_blink_cursor(pte);
03943       send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
03944       break;
03945    }
03946    return;
03947 }

static void key_select_language ( struct unistimsession pte,
char  keycode 
) [static]

Definition at line 3807 of file chan_unistim.c.

References ast_copy_string(), unistimsession::buff_entry, unistimsession::device, unistim_languages::encoding, handle_select_language(), handle_select_option(), KEY_DOWN, KEY_FUNC1, KEY_FUNC4, KEY_HANGUP, KEY_UP, unistim_languages::label, unistim_languages::lang_short, unistim_device::language, NULL, refresh_all_favorite(), send_charset_update(), and show_main_page().

Referenced by process_request().

03808 {
03809    switch (keycode) {
03810    case KEY_DOWN:
03811       pte->buff_entry[0]++;
03812       if (options_languages[(int)pte->buff_entry[0]].label == NULL) {
03813          pte->buff_entry[0]--;
03814       }
03815       break;
03816    case KEY_UP:
03817       if (pte->buff_entry[0] > 0) {
03818          pte->buff_entry[0]--;
03819       }
03820       break;
03821    case KEY_FUNC1:
03822       ast_copy_string(pte->device->language, options_languages[(int)pte->buff_entry[0]].lang_short, sizeof(pte->device->language));
03823       send_charset_update(pte, options_languages[(int)pte->buff_entry[0]].encoding);
03824       refresh_all_favorite(pte);
03825       show_main_page(pte);
03826       return;
03827    case KEY_HANGUP:
03828    case KEY_FUNC4:
03829       handle_select_option(pte);
03830       return;
03831    }
03832 
03833    handle_select_language(pte);
03834    return;
03835 }

static void key_select_option ( struct unistimsession pte,
char  keycode 
) [static]

Definition at line 3667 of file chan_unistim.c.

References unistimsession::buff_entry, unistim_menu_item::handle_option, handle_select_option(), KEY_DOWN, KEY_FUNC1, KEY_FUNC4, KEY_HANGUP, KEY_UP, unistim_menu_item::label, NULL, and show_main_page().

Referenced by process_request().

03668 {
03669    switch (keycode) {
03670    case KEY_DOWN:
03671       pte->buff_entry[0]++;
03672       if (options_menu[(int)pte->buff_entry[0]].label == NULL) {
03673          pte->buff_entry[0]--;
03674       }
03675       break;
03676    case KEY_UP:
03677       if (pte->buff_entry[0] > 0) {
03678          pte->buff_entry[0]--;
03679       }
03680       break;
03681    case KEY_FUNC1:
03682       options_menu[(int)pte->buff_entry[0]].handle_option(pte);
03683       return;
03684    case KEY_HANGUP:
03685    case KEY_FUNC4:
03686       show_main_page(pte);
03687       return;
03688    }
03689 
03690    handle_select_option(pte);
03691    return;
03692 }

static int lang_cmp_fn ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 789 of file chan_unistim.c.

References CMP_MATCH, CMP_STOP, and ustm_lang_entry::str_orig.

Referenced by ustmtext().

00790 {
00791    struct ustm_lang_entry *entry1 = obj;
00792    struct ustm_lang_entry *entry2 = arg;
00793 
00794    return (!strcmp(entry1->str_orig, entry2->str_orig)) ? (CMP_MATCH | CMP_STOP) : 0;
00795 }

static int lang_hash_fn ( const void *  obj,
const int  flags 
) [static]

Definition at line 783 of file chan_unistim.c.

References ast_str_hash(), and ustm_lang_entry::str_orig.

Referenced by ustmtext().

00784 {
00785    const struct ustm_lang_entry *entry = obj;
00786    return ast_str_hash(entry->str_orig);
00787 }

int load_module ( void   )  [static]

XXX

Todo:
Leaking anything allocated by reload_config() ...

Definition at line 7050 of file chan_unistim.c.

References ao2_cleanup, ao2_ref, ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_format_alaw, ast_format_cap_alloc, ast_format_cap_append, ast_format_cap_append_from_cap(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_ulaw, ast_free, ast_log, ast_malloc, AST_MEDIA_TYPE_AUDIO, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_rtp_glue_register, ast_sched_context_create(), ast_sched_context_destroy(), ast_channel_tech::capabilities, io_context_create(), io_context_destroy(), LOG_ERROR, NULL, reload_config(), restart_monitor(), and SIZE_PAGE.

07051 {
07052    int res;
07053 
07054    if (!(global_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
07055       goto buff_failed;
07056    }
07057    if (!(unistim_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
07058       goto buff_failed;
07059    }
07060 
07061    ast_format_cap_append(global_cap, ast_format_ulaw, 0);
07062    ast_format_cap_append(global_cap, ast_format_alaw, 0);
07063    ast_format_cap_append_from_cap(unistim_tech.capabilities, global_cap, AST_MEDIA_TYPE_AUDIO);
07064 
07065    if (!(buff = ast_malloc(SIZE_PAGE))) {
07066       goto buff_failed;
07067    }
07068 
07069    io = io_context_create();
07070    if (!io) {
07071       ast_log(LOG_ERROR, "Failed to allocate IO context\n");
07072       goto io_failed;
07073    }
07074 
07075    sched = ast_sched_context_create();
07076    if (!sched) {
07077       ast_log(LOG_ERROR, "Failed to allocate scheduler context\n");
07078       goto sched_failed;
07079    }
07080 
07081    res = reload_config();
07082    if (res) {
07083       ao2_ref(unistim_tech.capabilities, -1);
07084       ao2_ref(global_cap, -1);
07085       ast_sched_context_destroy(sched);
07086       io_context_destroy(io);
07087       return AST_MODULE_LOAD_DECLINE;
07088    }
07089    /* Make sure we can register our unistim channel type */
07090    if (ast_channel_register(&unistim_tech)) {
07091       ast_log(LOG_ERROR, "Unable to register channel type '%s'\n", channel_type);
07092       goto chanreg_failed;
07093    }
07094 
07095    ast_rtp_glue_register(&unistim_rtp_glue);
07096 
07097    ast_cli_register_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
07098 
07099    restart_monitor();
07100 
07101    return AST_MODULE_LOAD_SUCCESS;
07102 
07103 chanreg_failed:
07104    /*! XXX \todo Leaking anything allocated by reload_config() ... */
07105    ast_sched_context_destroy(sched);
07106    sched = NULL;
07107 sched_failed:
07108    io_context_destroy(io);
07109    io = NULL;
07110 io_failed:
07111    ast_free(buff);
07112    buff = NULL;
07113 buff_failed:
07114    ao2_cleanup(global_cap);
07115    global_cap = NULL;
07116    ao2_cleanup(unistim_tech.capabilities);
07117    unistim_tech.capabilities = NULL;
07118    return AST_MODULE_LOAD_FAILURE;
07119 }

static void microphone_mute_toggle ( struct unistimsession pte  )  [static]

Definition at line 4422 of file chan_unistim.c.

References unistimsession::device, LED_MUTE_OFF, LED_MUTE_ON, unistim_device::microphone, MUTE_OFF, MUTE_ON, send_led_update(), and send_mute().

Referenced by process_request().

04423 {
04424    if (pte->device->microphone == MUTE_OFF) {
04425       pte->device->microphone = MUTE_ON;
04426       send_led_update(pte, LED_MUTE_ON);
04427    } else if (pte->device->microphone == MUTE_ON) {
04428       pte->device->microphone = MUTE_OFF;
04429       send_led_update(pte, LED_MUTE_OFF);
04430    }
04431    send_mute(pte, (pte->device->microphone & 0x01));
04432 }

static char open_history ( struct unistimsession pte,
char  way,
FILE **  f 
) [static]

Definition at line 4023 of file chan_unistim.c.

References ast_config_AST_LOG_DIR, AST_CONFIG_MAX_PATH, ast_log, unistimsession::device, display_last_error(), LOG_WARNING, MAX_ENTRY_LOG, unistim_device::name, NULL, tmp(), and USTM_LOG_DIR.

Referenced by key_history(), and show_history().

04024 {
04025    char tmp[AST_CONFIG_MAX_PATH];
04026    char count;
04027 
04028    snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
04029           USTM_LOG_DIR, pte->device->name, way);
04030    *f = fopen(tmp, "r");
04031    if (!*f) {
04032       display_last_error("Unable to open history file");
04033       return 0;
04034    }
04035    if (fread(&count, 1, 1, *f) != 1) {
04036       display_last_error("Unable to read history header - display.");
04037       fclose(*f);
04038       *f = NULL;
04039       return 0;
04040    }
04041    if (count > MAX_ENTRY_LOG) {
04042       ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
04043             count, MAX_ENTRY_LOG);
04044       fclose(*f);
04045       *f = NULL;
04046       return 0;
04047    }
04048    return count;
04049 }

static int parse_bookmark ( const char *  text,
struct unistim_device d 
) [static]

Definition at line 6273 of file chan_unistim.c.

References ast_copy_string(), ast_log, ast_strlen_zero, ast_verb, FAV_ICON_SHARP, FAVNUM, len(), LOG_NOTICE, LOG_WARNING, unistim_device::softkeydevice, unistim_device::softkeyicon, unistim_device::softkeylabel, and unistim_device::softkeynumber.

Referenced by build_device().

06274 {
06275    char line[256];
06276    char *at;
06277    char *number;
06278    char *icon;
06279    int p;
06280    int len = strlen(text);
06281 
06282    ast_copy_string(line, text, sizeof(line));
06283    /* Position specified ? */
06284    if ((len > 2) && (line[1] == '@')) {
06285       p = line[0];
06286       if ((p >= '0') && (p <= '5')) {
06287          p -= '0';
06288       } else {
06289          ast_log(LOG_WARNING,
06290                "Invalid position for bookmark : must be between 0 and 5\n");
06291          return 0;
06292       }
06293       if (d->softkeyicon[p] != 0) {
06294          ast_log(LOG_WARNING, "Invalid position %d for bookmark : already used:\n", p);
06295          return 0;
06296       }
06297       memmove(line, line + 2, sizeof(line) - 2);
06298    } else {
06299       /* No position specified, looking for a free slot */
06300       for (p = 0; p < FAVNUM; p++) {
06301          if (!d->softkeyicon[p]) {
06302             break;
06303          }
06304       }
06305       if (p == FAVNUM) {
06306          ast_log(LOG_WARNING, "No more free bookmark position\n");
06307          return 0;
06308       }
06309    }
06310    at = strchr(line, '@');
06311    if (!at) {
06312       ast_log(LOG_NOTICE, "Bookmark entry '%s' has no @ (at) sign!\n", text);
06313       return 0;
06314    }
06315    *at = '\0';
06316    at++;
06317    number = at;
06318    at = strchr(at, '@');
06319    if (ast_strlen_zero(number)) {
06320       ast_log(LOG_NOTICE, "Bookmark entry '%s' has no number\n", text);
06321       return 0;
06322    }
06323    if (ast_strlen_zero(line)) {
06324       ast_log(LOG_NOTICE, "Bookmark entry '%s' has no description\n", text);
06325       return 0;
06326    }
06327 
06328    at = strchr(number, '@');
06329    if (!at) {
06330       d->softkeyicon[p] = FAV_ICON_SHARP;     /* default icon */
06331    } else {
06332       *at = '\0';
06333       at++;
06334       icon = at;
06335       if (ast_strlen_zero(icon)) {
06336          ast_log(LOG_NOTICE, "Bookmark entry '%s' has no icon value\n", text);
06337          return 0;
06338       }
06339       if (strncmp(icon, "USTM/", 5)) {
06340          d->softkeyicon[p] = atoi(icon);
06341       } else {
06342          d->softkeyicon[p] = 1;
06343          ast_copy_string(d->softkeydevice[p], icon + 5, sizeof(d->softkeydevice[p]));
06344       }
06345    }
06346    ast_copy_string(d->softkeylabel[p], line, sizeof(d->softkeylabel[p]));
06347    ast_copy_string(d->softkeynumber[p], number, sizeof(d->softkeynumber[p]));
06348    if (unistimdebug) {
06349       ast_verb(0, "New bookmark at pos %d label='%s' number='%s' icon=%#x\n",
06350                p, d->softkeylabel[p], d->softkeynumber[p], (unsigned)d->softkeyicon[p]);
06351    }
06352    return 1;
06353 }

static void parsing ( int  size,
unsigned char *  buf,
struct unistimsession pte,
struct sockaddr_in *  addr_from 
) [static]

Definition at line 4598 of file chan_unistim.c.

References ast_inet_ntoa(), ast_log, ast_mutex_lock, ast_mutex_unlock, ast_verb, check_send_queue(), close_client(), create_client(), unistimsession::last_seq_ack, unistimsession::lock, LOG_NOTICE, LOG_WARNING, unistimsession::nb_retransmit, process_request(), send_raw_client(), send_retransmit(), seq, unistimsession::seq_phone, unistimsession::seq_server, SIZE_HEADER, unistimsession::sout, unistimsession::state, and STATE_INIT.

Referenced by load_module(), unistimsock_read(), and unload_module().

04600 {
04601    unsigned short *sbuf = (unsigned short *) buf;
04602    unsigned short seq;
04603    char tmpbuf[255];
04604 
04605    strcpy(tmpbuf, ast_inet_ntoa(addr_from->sin_addr));
04606 
04607    if (size < 10) {
04608       if (size == 0) {
04609          ast_log(LOG_WARNING, "%s Read error\n", tmpbuf);
04610       } else {
04611          ast_log(LOG_NOTICE, "%s Packet too short - ignoring\n", tmpbuf);
04612       }
04613       return;
04614    }
04615    if (sbuf[0] == 0xffff) {   /* Starting with 0xffff ? *//* Yes, discovery packet ? */
04616       if (size != sizeof(packet_rcv_discovery)) {
04617          ast_log(LOG_NOTICE, "%s Invalid size of a discovery packet\n", tmpbuf);
04618       } else {
04619          if (memcmp(buf, packet_rcv_discovery, sizeof(packet_rcv_discovery)) == 0) {
04620             if (unistimdebug) {
04621                ast_verb(0, "Discovery packet received - Sending Discovery ACK\n");
04622             }
04623             if (pte) {        /* A session was already active for this IP ? */
04624                if (pte->state == STATE_INIT) { /* Yes, but it's a dupe */
04625                   if (unistimdebug) {
04626                      ast_verb(1, "Duplicated Discovery packet\n");
04627                   }
04628                   send_raw_client(sizeof(packet_send_discovery_ack),
04629                              packet_send_discovery_ack, addr_from, &pte->sout);
04630                   pte->seq_phone = (short) 0x0000; /* reset sequence number */
04631                } else { /* No, probably a reboot, phone side */
04632                   close_client(pte);       /* Cleanup the previous session */
04633                   if (create_client(addr_from)) {
04634                      send_raw_client(sizeof(packet_send_discovery_ack),
04635                                 packet_send_discovery_ack, addr_from, &pte->sout);
04636                   }
04637                }
04638             } else {
04639                /* Creating new entry in our phone list */
04640                if ((pte = create_client(addr_from))) {
04641                   send_raw_client(sizeof(packet_send_discovery_ack),
04642                              packet_send_discovery_ack, addr_from, &pte->sout);
04643                }
04644             }
04645             return;
04646          }
04647          ast_log(LOG_NOTICE, "%s Invalid discovery packet\n", tmpbuf);
04648       }
04649       return;
04650    }
04651    if (!pte) {
04652       if (unistimdebug) {
04653          ast_verb(0, "%s Not a discovery packet from an unknown source : ignoring\n", tmpbuf);
04654       }
04655       return;
04656    }
04657 
04658    if (sbuf[0] != 0) {          /* Starting with something else than 0x0000 ? */
04659       ast_log(LOG_NOTICE, "Unknown packet received - ignoring\n");
04660       return;
04661    }
04662    if (buf[5] != 2) {
04663       ast_log(LOG_NOTICE, "%s Wrong direction : got 0x%02hhx expected 0x02\n", tmpbuf, buf[5]);
04664       return;
04665    }
04666    seq = ntohs(sbuf[1]);
04667    if (buf[4] == 1) {
04668       ast_mutex_lock(&pte->lock);
04669       if (unistimdebug) {
04670          ast_verb(0, "ACK received for packet #0x%04x\n", (unsigned)seq);
04671       }
04672       pte->nb_retransmit = 0;
04673 
04674       if ((pte->last_seq_ack) + 1 == seq) {
04675          pte->last_seq_ack++;
04676          check_send_queue(pte);
04677          ast_mutex_unlock(&pte->lock);
04678          return;
04679       }
04680       if (pte->last_seq_ack > seq) {
04681          if (pte->last_seq_ack == 0xffff) {
04682             ast_verb(0, "ACK at 0xffff, restarting counter.\n");
04683             pte->last_seq_ack = 0;
04684          } else {
04685             ast_log(LOG_NOTICE,
04686                   "%s Warning : ACK received for an already ACKed packet : #0x%04x we are at #0x%04x\n",
04687                   tmpbuf, (unsigned)seq, (unsigned)pte->last_seq_ack);
04688          }
04689          ast_mutex_unlock(&pte->lock);
04690          return;
04691       }
04692       if (pte->seq_server < seq) {
04693          ast_log(LOG_NOTICE,
04694                "%s Error : ACK received for a non-existent packet : #0x%04x\n",
04695                tmpbuf, (unsigned)pte->seq_server);
04696          ast_mutex_unlock(&pte->lock);
04697          return;
04698       }
04699       if (unistimdebug) {
04700          ast_verb(0, "%s ACK gap : Received ACK #0x%04x, previous was #0x%04x\n",
04701                   tmpbuf, (unsigned)seq, (unsigned)pte->last_seq_ack);
04702       }
04703       pte->last_seq_ack = seq;
04704       check_send_queue(pte);
04705       ast_mutex_unlock(&pte->lock);
04706       return;
04707    }
04708    if (buf[4] == 2) {
04709       if (unistimdebug) {
04710          ast_verb(0, "Request received\n");
04711       }
04712       if (pte->seq_phone == seq) {
04713          /* Send ACK */
04714          buf[4] = 1;
04715          buf[5] = 1;
04716          send_raw_client(SIZE_HEADER, buf, addr_from, &pte->sout);
04717          pte->seq_phone++;
04718 
04719          process_request(size, buf, pte);
04720          return;
04721       }
04722       if (pte->seq_phone > seq) {
04723          ast_log(LOG_NOTICE,
04724                "%s Warning : received a retransmitted packet : #0x%04x (we are at #0x%04x)\n",
04725                tmpbuf, (unsigned)seq, (unsigned)pte->seq_phone);
04726          /* BUG ? pte->device->seq_phone = seq; */
04727          /* Send ACK */
04728          buf[4] = 1;
04729          buf[5] = 1;
04730          send_raw_client(SIZE_HEADER, buf, addr_from, &pte->sout);
04731          return;
04732       }
04733       ast_log(LOG_NOTICE,
04734             "%s Warning : we lost a packet : received #0x%04x (we are at #0x%04x)\n",
04735             tmpbuf, (unsigned)seq, (unsigned)pte->seq_phone);
04736       return;
04737    }
04738    if (buf[4] == 0) {
04739       ast_log(LOG_NOTICE, "%s Retransmit request for packet #0x%04x\n", tmpbuf, (unsigned)seq);
04740       if (pte->last_seq_ack > seq) {
04741          ast_log(LOG_NOTICE,
04742                "%s Error : received a request for an already ACKed packet : #0x%04x\n",
04743                tmpbuf, (unsigned)pte->last_seq_ack);
04744          return;
04745       }
04746       if (pte->seq_server < seq) {
04747          ast_log(LOG_NOTICE,
04748                "%s Error : received a request for a non-existent packet : #0x%04x\n",
04749                tmpbuf, (unsigned)pte->seq_server);
04750          return;
04751       }
04752       send_retransmit(pte);
04753       return;
04754    }
04755    ast_log(LOG_NOTICE, "%s Unknown request : got 0x%02hhx expected 0x00,0x01 or 0x02\n", tmpbuf, buf[4]);
04756    return;
04757 }

static void process_request ( int  size,
unsigned char *  buf,
struct unistimsession pte 
) [static]

Definition at line 4434 of file chan_unistim.c.

References ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log, ast_verb, close_call(), unistimsession::device, unistimsession::firmware, get_avail_softkey(), handle_call_incoming(), handle_dial_page(), unistim_device::height, init_phone_step2(), key_call(), key_dial_page(), key_history(), key_main_page(), KEY_MUTE, key_ringing(), key_select_codec(), key_select_extension(), key_select_language(), key_select_option(), LOG_WARNING, microphone_mute_toggle(), MUTE_OFF, unistim_device::nextdial, NULL, unistim_device::output, OUTPUT_HANDSET, OUTPUT_HEADPHONE, OUTPUT_SPEAKER, ptestate_tostr(), rcv_mac_addr(), rcv_resume_connection_with_server(), unistim_device::receiver_state, unistim_device::selected, send_select_output(), show_main_page(), unistimsession::sin, SIZE_HEADER, unistimsession::state, STATE_AUTHDENY, STATE_CALL, STATE_DIALPAGE, STATE_EXTENSION, STATE_HISTORY, STATE_INIT, STATE_MAINPAGE, STATE_OFFHOOK, STATE_ONHOOK, STATE_RINGING, STATE_SELECTCODEC, STATE_SELECTLANGUAGE, STATE_SELECTOPTION, type, and unistim_device::volume.

Referenced by parsing().

04435 {
04436    char tmpbuf[255];
04437    if (memcmp
04438       (buf + SIZE_HEADER, packet_recv_resume_connection_with_server,
04439        sizeof(packet_recv_resume_connection_with_server)) == 0) {
04440       rcv_resume_connection_with_server(pte);
04441       return;
04442    }
04443    if (memcmp(buf + SIZE_HEADER, packet_recv_firm_version, sizeof(packet_recv_firm_version)) == 0) {
04444       buf[size] = 0;
04445       if (unistimdebug) {
04446          ast_verb(0, "Got the firmware version : '%s'\n", buf + 13);
04447       }
04448       ast_copy_string(pte->firmware, (char *) (buf + 13), sizeof(pte->firmware));
04449       init_phone_step2(pte);
04450       return;
04451    }
04452    if (memcmp(buf + SIZE_HEADER, packet_recv_it_type, sizeof(packet_recv_it_type)) == 0) {
04453       char type = buf[13];
04454       if (unistimdebug) {
04455          ast_verb(0, "Got the equipment type: '%d'\n", type);
04456       }
04457       switch (type) {
04458       case 0x03: /* i2002 */
04459          if (pte->device) {
04460             pte->device->height = 1;
04461          }
04462          break;
04463       }
04464       return;
04465    }
04466    if (memcmp(buf + SIZE_HEADER, packet_recv_mac_addr, sizeof(packet_recv_mac_addr)) == 0) {
04467       rcv_mac_addr(pte, buf);
04468       return;
04469    }
04470    if (memcmp(buf + SIZE_HEADER, packet_recv_r2, sizeof(packet_recv_r2)) == 0) {
04471       if (unistimdebug) {
04472          ast_verb(0, "R2 received\n");
04473       }
04474       return;
04475    }
04476 
04477    if (pte->state < STATE_MAINPAGE) {
04478       if (unistimdebug) {
04479          ast_verb(0, "Request not authorized in this state\n");
04480       }
04481       return;
04482    }
04483    if (!memcmp(buf + SIZE_HEADER, packet_recv_expansion_pressed_key, sizeof(packet_recv_expansion_pressed_key))) {
04484       char keycode = buf[13];
04485       
04486       if (unistimdebug) {
04487          ast_verb(0, "Expansion key pressed: keycode = 0x%02hhx - current state: %s\n", (unsigned char)keycode,
04488                   ptestate_tostr(pte->state));
04489       }
04490    }
04491    if (!memcmp(buf + SIZE_HEADER, packet_recv_pressed_key, sizeof(packet_recv_pressed_key))) {
04492       char keycode = buf[13];
04493 
04494       if (unistimdebug) {
04495          ast_verb(0, "Key pressed: keycode = 0x%02hhx - current state: %s\n", (unsigned char)keycode,
04496                   ptestate_tostr(pte->state));
04497       }
04498       if (keycode == KEY_MUTE) {
04499          microphone_mute_toggle(pte);
04500       }
04501       switch (pte->state) {
04502       case STATE_INIT:
04503          if (unistimdebug) {
04504             ast_verb(0, "No keys allowed in the init state\n");
04505          }
04506          break;
04507       case STATE_AUTHDENY:
04508          if (unistimdebug) {
04509             ast_verb(0, "No keys allowed in authdeny state\n");
04510          }
04511          break;
04512       case STATE_MAINPAGE:
04513          key_main_page(pte, keycode);
04514          break;
04515       case STATE_DIALPAGE:
04516          key_dial_page(pte, keycode);
04517          break;
04518       case STATE_RINGING:
04519          key_ringing(pte, keycode);
04520          break;
04521       case STATE_CALL:
04522          key_call(pte, keycode);
04523          break;
04524       case STATE_EXTENSION:
04525          key_select_extension(pte, keycode);
04526          break;
04527       case STATE_SELECTOPTION:
04528          key_select_option(pte, keycode);
04529          break;
04530       case STATE_SELECTCODEC:
04531          key_select_codec(pte, keycode);
04532          break;
04533       case STATE_SELECTLANGUAGE:
04534          key_select_language(pte, keycode);
04535          break;
04536       case STATE_HISTORY:
04537          key_history(pte, keycode);
04538          break;
04539       default:
04540          ast_log(LOG_WARNING, "Key : Unknown state\n");
04541       }
04542       return;
04543    }
04544    if (memcmp(buf + SIZE_HEADER, packet_recv_pick_up, sizeof(packet_recv_pick_up)) == 0) {
04545       if (unistimdebug) {
04546          ast_verb(0, "Handset off hook, current state: %s\n", ptestate_tostr(pte->state));
04547       }
04548       if (!pte->device) {         /* We are not yet registered (asking for a TN in AUTOPROVISIONING_TN) */
04549          return;
04550       }
04551       pte->device->receiver_state = STATE_OFFHOOK;
04552       if (pte->device->output == OUTPUT_HEADPHONE) {
04553          send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
04554       } else {
04555          send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
04556       }
04557       if (pte->state == STATE_RINGING) {
04558          handle_call_incoming(pte);
04559       } else if ((pte->state == STATE_DIALPAGE) || (pte->state == STATE_CALL)) {
04560          send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
04561       } else if (pte->state == STATE_EXTENSION) { /* We must have a TN before calling */
04562          return;
04563       } else {
04564          pte->device->selected = get_avail_softkey(pte, NULL);
04565          send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
04566          handle_dial_page(pte);
04567       }
04568       return;
04569    }
04570    if (memcmp(buf + SIZE_HEADER, packet_recv_hangup, sizeof(packet_recv_hangup)) == 0) {
04571       if (unistimdebug) {
04572          ast_verb(0, "Handset on hook, current state: %s\n", ptestate_tostr(pte->state));
04573       }
04574       if (!pte->device) {
04575          return;
04576       }
04577       pte->device->receiver_state = STATE_ONHOOK;
04578       if (pte->state == STATE_CALL) {
04579          if (pte->device->output != OUTPUT_SPEAKER) {
04580             close_call(pte);
04581          }
04582       } else if (pte->state == STATE_EXTENSION) {
04583          return;
04584       } else {
04585          pte->device->nextdial = 0;
04586          show_main_page(pte);
04587       }
04588       return;
04589    }
04590    strcpy(tmpbuf, ast_inet_ntoa(pte->sin.sin_addr));
04591    strcat(tmpbuf, " Unknown request packet\n");
04592    if (unistimdebug) {
04593       ast_debug(1, "%s", tmpbuf);
04594    }
04595    return;
04596 }

static const char* ptestate_tostr ( const int  type  )  [static]

Definition at line 2027 of file chan_unistim.c.

References STATE_AUTHDENY, STATE_CALL, STATE_CLEANING, STATE_DIALPAGE, STATE_EXTENSION, STATE_HISTORY, STATE_INIT, STATE_MAINPAGE, STATE_RINGING, STATE_SELECTCODEC, STATE_SELECTLANGUAGE, and STATE_SELECTOPTION.

Referenced by process_request(), unistim_hangup(), and unistim_show_info().

02028 {
02029    switch (type) {
02030    case STATE_INIT:
02031       return "INIT";
02032    case STATE_AUTHDENY:
02033       return "AUTHDENY";
02034    case STATE_MAINPAGE:
02035       return "MAINPAGE";
02036    case STATE_EXTENSION:
02037       return "EXTENSION";
02038    case STATE_DIALPAGE:
02039       return "DIALPAGE";
02040    case STATE_RINGING:
02041       return "RINGING";
02042    case STATE_CALL:
02043       return "CALL";
02044    case STATE_SELECTOPTION:
02045       return "SELECTOPTION";
02046    case STATE_SELECTCODEC:
02047       return "SELECTCODEC";
02048    case STATE_SELECTLANGUAGE:
02049       return "SELECTLANGUAGE";
02050    case STATE_CLEANING:
02051       return "CLEARING";
02052    case STATE_HISTORY:
02053       return "HISTORY";
02054    }
02055    return "UNKNOWN";
02056 }

static void rcv_mac_addr ( struct unistimsession pte,
const unsigned char *  buf 
) [static]

Definition at line 2058 of file chan_unistim.c.

References ast_copy_string(), ast_free, AST_LIST_FIRST, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log, ast_malloc, ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero, ast_verb, AUTOPROVISIONING_NO, AUTOPROVISIONING_TN, AUTOPROVISIONING_YES, BUFFSEND, d, unistimsession::device, devicelock, unistim_device::extension, EXTENSION_ASK, EXTENSION_LINE, EXTENSION_NONE, unistim_device::extension_number, EXTENSION_TN, unistim_line::fullname, unistim_device::lines, LOG_ERROR, LOG_WARNING, unistimsession::macaddr, unistim_line::name, unistim_device::name, unistimsession::next, unistim_device::next, NULL, unistim_line::parent, register_extension(), send_client(), send_date_time(), SIZE_HEADER, unistimsession::state, STATE_AUTHDENY, STATE_EXTENSION, STATE_MAINPAGE, STATE_ONHOOK, sub, unistim_device::subs, tmp(), unistim_line_alloc(), unistim_line_copy(), and unistim_register().

Referenced by process_request().

02059 {
02060    BUFFSEND;
02061    int tmp, i = 0;
02062    char addrmac[19];
02063    int res = 0;
02064    for (tmp = 15; tmp < 15 + SIZE_HEADER; tmp++) {
02065       sprintf(&addrmac[i], "%02hhx", buf[tmp]);
02066       i += 2;
02067    }
02068    if (unistimdebug) {
02069       ast_verb(0, "MAC Address received: %s\n", addrmac);
02070    }
02071    strcpy(pte->macaddr, addrmac);
02072    res = unistim_register(pte);
02073    if (!res) {
02074       switch (autoprovisioning) {
02075       case AUTOPROVISIONING_NO:
02076          ast_log(LOG_WARNING, "No entry found for this phone : %s\n", addrmac);
02077          pte->state = STATE_AUTHDENY;
02078          break;
02079       case AUTOPROVISIONING_YES:
02080          {
02081             struct unistim_device *d = NULL, *newd = NULL;
02082             struct unistim_line *newl = NULL, *l = NULL;
02083             if (unistimdebug) {
02084                ast_verb(0, "New phone, autoprovisioning on\n");
02085             }
02086             /* First : locate the [template] section */
02087             ast_mutex_lock(&devicelock);
02088             d = devices;
02089             while (d) {
02090                if (strcasecmp(d->name, "template")) {
02091                   d = d->next;
02092                   continue;
02093                }
02094                /* Found, cloning this entry */
02095                if (!(newd = ast_malloc(sizeof(*newd)))) {
02096                   ast_mutex_unlock(&devicelock);
02097                   return;
02098                }
02099                memcpy(newd, d, sizeof(*newd));
02100                ast_mutex_init(&newd->lock);
02101                newd->lines.first = NULL;
02102                newd->lines.last = NULL;
02103                AST_LIST_LOCK(&d->lines);
02104                AST_LIST_TRAVERSE(&d->lines, l, list) {
02105                   if (!(newl = unistim_line_alloc())) {
02106                      break;
02107                   }
02108                   unistim_line_copy(l, newl);
02109                   newl->parent = newd;
02110                   ast_copy_string(newl->name, l->name, sizeof(newl->name));
02111                   snprintf(newl->fullname, sizeof(newl->fullname), "USTM/%s@%s",
02112                          newl->name, newd->name);
02113                   snprintf(l->name, sizeof(l->name), "%d", atoi(l->name) + 1);
02114 
02115                   AST_LIST_LOCK(&newd->lines);
02116                   AST_LIST_INSERT_TAIL(&newd->lines, newl, list);
02117                   AST_LIST_UNLOCK(&newd->lines);
02118                }
02119                AST_LIST_UNLOCK(&d->lines);
02120                if (!newl) {
02121                   ast_free(newd);
02122                   ast_mutex_unlock(&devicelock);
02123                }
02124 
02125                /* Ok, now updating some fields */
02126                ast_copy_string(newd->id, addrmac, sizeof(newd->id));
02127                ast_copy_string(newd->name, addrmac, sizeof(newd->name));
02128                if (newd->extension == EXTENSION_NONE) {
02129                   newd->extension = EXTENSION_ASK;
02130                }
02131 
02132                newd->receiver_state = STATE_ONHOOK;
02133                newd->session = pte;
02134                newd->language[0] = '\0';
02135                newd->to_delete = -1;
02136                newd->next = NULL;
02137                pte->device = newd;
02138 
02139                /* Go to the end of the linked chain */
02140                while (d->next) {
02141                   d = d->next;
02142                }
02143                d->next = newd;
02144                d = newd;
02145                break;
02146             }
02147             ast_mutex_unlock(&devicelock);
02148             if (!d) {
02149                ast_log(LOG_WARNING, "No entry [template] found in unistim.conf\n");
02150                pte->state = STATE_AUTHDENY;
02151             }
02152          }
02153          break;
02154       case AUTOPROVISIONING_TN:
02155          pte->state = STATE_AUTHDENY;
02156          break;
02157       default:
02158          ast_log(LOG_WARNING, "Internal error : unknown autoprovisioning value = %u\n",
02159                autoprovisioning);
02160       }
02161    }
02162    if (pte->state != STATE_AUTHDENY) {
02163       struct unistim_line *line;
02164       struct unistim_subchannel *sub;
02165 
02166       ast_verb(3, "Device '%s' successfuly registered\n", pte->device->name);
02167 
02168       AST_LIST_LOCK(&pte->device->subs);
02169       AST_LIST_TRAVERSE_SAFE_BEGIN(&pte->device->subs, sub, list) {
02170          if (sub) {
02171             ast_log(LOG_ERROR, "Subchannel lost sice reboot. Hanged channel may apear!\n");
02172             AST_LIST_REMOVE_CURRENT(list);
02173             ast_free(sub);
02174          }
02175       }
02176       AST_LIST_TRAVERSE_SAFE_END;
02177       AST_LIST_UNLOCK(&pte->device->subs);
02178 
02179       switch (pte->device->extension) {
02180       case EXTENSION_NONE:
02181          pte->state = STATE_MAINPAGE;
02182          break;
02183       case EXTENSION_ASK:
02184          /* Checking if we already have an extension number */
02185          if (ast_strlen_zero(pte->device->extension_number)) {
02186             pte->state = STATE_EXTENSION;
02187          } else {
02188             /* Yes, because of a phone reboot. We don't ask again for the TN */
02189             if (register_extension(pte)) {
02190                pte->state = STATE_EXTENSION;
02191             } else {
02192                pte->state = STATE_MAINPAGE;
02193             }
02194          }
02195          break;
02196       case EXTENSION_LINE:
02197          line = AST_LIST_FIRST(&pte->device->lines);
02198          ast_copy_string(pte->device->extension_number, line->name,
02199                      sizeof(pte->device->extension_number));
02200          if (register_extension(pte)) {
02201             pte->state = STATE_EXTENSION;
02202          } else {
02203             pte->state = STATE_MAINPAGE;
02204          }
02205          break;
02206       case EXTENSION_TN:
02207          /* If we are here, it's because of a phone reboot */
02208          pte->state = STATE_MAINPAGE;
02209          break;
02210       default:
02211          ast_log(LOG_WARNING, "Internal error, extension value unknown : %u\n",
02212                pte->device->extension);
02213          pte->state = STATE_AUTHDENY;
02214          break;
02215       }
02216    }
02217    if (pte->state == STATE_EXTENSION) {
02218       if (pte->device->extension != EXTENSION_TN) {
02219          pte->device->extension = EXTENSION_ASK;
02220       }
02221       pte->device->extension_number[0] = '\0';
02222    }
02223    if (unistimdebug) {
02224       ast_verb(0, "\nSending S1\n");
02225    }
02226    memcpy(buffsend + SIZE_HEADER, packet_send_S1, sizeof(packet_send_S1));
02227    send_client(SIZE_HEADER + sizeof(packet_send_S1), buffsend, pte);
02228 
02229    if (unistimdebug) {
02230       ast_verb(0, "Sending query_basic_manager_04\n");
02231    }
02232    memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_04,
02233          sizeof(packet_send_query_basic_manager_04));
02234    send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_04), buffsend, pte);
02235 
02236    if (unistimdebug) {
02237       ast_verb(0, "Sending query_basic_manager_10\n");
02238    }
02239    memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_10,
02240          sizeof(packet_send_query_basic_manager_10));
02241    send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_10), buffsend, pte);
02242 
02243    send_date_time(pte);
02244    return;
02245 }

static void rcv_resume_connection_with_server ( struct unistimsession pte  )  [static]

Definition at line 1892 of file chan_unistim.c.

References ast_verb, BUFFSEND, send_client(), and SIZE_HEADER.

Referenced by process_request().

01893 {
01894    BUFFSEND;
01895    if (unistimdebug) {
01896       ast_verb(0, "ResumeConnectionWithServer received\n");
01897       ast_verb(0, "Sending packet_send_query_mac_address\n");
01898    }
01899    memcpy(buffsend + SIZE_HEADER, packet_send_query_mac_address,
01900          sizeof(packet_send_query_mac_address));
01901    send_client(SIZE_HEADER + sizeof(packet_send_query_mac_address), buffsend, pte);
01902    return;
01903 }

static void refresh_all_favorite ( struct unistimsession pte  )  [static]

Definition at line 1306 of file chan_unistim.c.

References ast_db_get(), AST_LIST_FIRST, ast_verb, unistimsession::device, EXPNUM, FAV_ICON_NONE, FAV_ICON_SPEAKER_ONHOOK_WHITE, FAVNUM, unistim_device::hasexp, unistim_device::lines, unistim_line::name, send_expansion_short(), send_favorite_short(), soft_key_visible(), unistim_device::softkeyicon, unistim_device::softkeylabel, and status.

Referenced by init_phone_step2(), key_select_extension(), key_select_language(), and reload_config().

01307 {
01308    unsigned char i = 0;
01309    char data[256];
01310    struct unistim_line *line;
01311    line = AST_LIST_FIRST(&pte->device->lines);
01312 
01313    if (unistimdebug) {
01314       ast_verb(0, "Refreshing all favorite\n");
01315    }
01316    for (i = 0; i < FAVNUM; i++) {
01317       unsigned char status = pte->device->softkeyicon[i];
01318 
01319       if (!soft_key_visible(pte->device, i)) {
01320          continue;
01321       }
01322       if (!strcasecmp(pte->device->softkeylabel[i], "DND") && line) {
01323          if (!ast_db_get("DND", line->name, data, sizeof(data))) {
01324             status = FAV_ICON_SPEAKER_ONHOOK_WHITE;
01325          }
01326       }
01327 
01328       send_favorite_short(i, status, pte);
01329    }
01330    if (pte->device->hasexp) {
01331       for (i = 0; i < EXPNUM; i++) {
01332          send_expansion_short(i, FAV_ICON_NONE, pte);
01333       }
01334    }
01335 }

static int register_extension ( const struct unistimsession pte  )  [static]

Definition at line 1430 of file chan_unistim.c.

References ast_add_extension(), AST_LIST_FIRST, ast_verb, unistim_device::context, unistimsession::device, unistim_device::extension_number, unistim_line::fullname, unistim_device::lines, and NULL.

Referenced by key_select_extension(), and rcv_mac_addr().

01431 {
01432    struct unistim_line *line;
01433    line = AST_LIST_FIRST(&pte->device->lines);
01434    if (unistimdebug) {
01435       ast_verb(0, "Trying to register extension '%s' into context '%s' to %s\n",
01436                pte->device->extension_number, pte->device->context,
01437                line->fullname);
01438    }
01439    return ast_add_extension(pte->device->context, 0,
01440                       pte->device->extension_number, 1, NULL, NULL, "Dial",
01441                       line->fullname, 0, "Unistim");
01442 }

int reload ( void   )  [static]

reload: Part of Asterisk module interface ---

Definition at line 7155 of file chan_unistim.c.

References ast_mutex_lock, ast_mutex_unlock, ast_verb, restart_monitor(), and unistim_reload_lock.

07156 {
07157    if (unistimdebug) {
07158       ast_verb(0, "reload unistim\n");
07159    }
07160    ast_mutex_lock(&unistim_reload_lock);
07161    if (!unistim_reloading) {
07162       unistim_reloading = 1;
07163    }
07164    ast_mutex_unlock(&unistim_reload_lock);
07165 
07166    restart_monitor();
07167 
07168    return 0;
07169 }

static int reload_config ( void   )  [static]

Definition at line 6736 of file chan_unistim.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load, ast_free, ast_gethostbyname(), ast_inet_ntoa(), ast_jb_read_conf(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log, ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, ast_set_qos(), ast_str2cos(), ast_str2tos(), ast_strlen_zero, ast_tone_zone_unref(), ast_variable_browse(), ast_verb, AUTOPROVISIONING_NO, AUTOPROVISIONING_TN, AUTOPROVISIONING_YES, build_device(), config, CONFIG_STATUS_FILEINVALID, d, unistimsession::device, devicelock, errno, find_language(), finish_bookmark(), global_jbconf, hp, unistim_device::language, ast_variable::lineno, unistim_device::lines, unistim_device::lock, unistimsession::lock, unistim_line::lock, unistim_subchannel::lock, LOG_ERROR, LOG_WARNING, unistim_device::name, ast_variable::name, NB_MAX_RETRANSMIT, unistimsession::next, unistim_device::next, ast_variable::next, NULL, unistim_subchannel::owner, qos, refresh_all_favorite(), RETRANSMIT_TIMER, send_charset_update(), unistim_device::session, sessionlock, sub, SUB_REAL, SUB_THREEWAY, unistim_device::subs, unistim_subchannel::subtype, unistim_device::to_delete, unistim_device::tz, unistim_line_destroy(), and ast_variable::value.

06737 {
06738    struct ast_config *cfg;
06739    struct ast_variable *v;
06740    struct ast_hostent ahp;
06741    struct hostent *hp;
06742    struct sockaddr_in bindaddr = { 0, };
06743    char *config = "unistim.conf";
06744    char *cat;
06745    struct unistim_device *d;
06746    const int reuseFlag = 1;
06747    struct unistimsession *s;
06748    struct ast_flags config_flags = { 0, };
06749 
06750    cfg = ast_config_load(config, config_flags);
06751    /* We *must* have a config file otherwise stop immediately */
06752    if (!cfg) {
06753       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
06754       return -1;
06755    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
06756       ast_log(LOG_ERROR, "Config file %s is in an invalid format.  Aborting.\n", config);
06757       return -1;
06758    }
06759 
06760    /* Copy the default jb config over global_jbconf */
06761    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
06762 
06763    unistim_keepalive = 120;
06764    unistim_port = 0;
06765    v = ast_variable_browse(cfg, "general");
06766    while (v) {
06767       /* handle jb conf */
06768       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
06769          continue;
06770       }
06771       if (!strcasecmp(v->name, "keepalive")) {
06772          unistim_keepalive = atoi(v->value);
06773       } else if (!strcasecmp(v->name, "port")) {
06774          unistim_port = atoi(v->value);
06775       } else if (!strcasecmp(v->name, "tos")) {
06776                         if (ast_str2tos(v->value, &qos.tos)) {
06777                             ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
06778          }
06779                 } else if (!strcasecmp(v->name, "tos_audio")) {
06780                         if (ast_str2tos(v->value, &qos.tos_audio)) {
06781                             ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
06782          }
06783                 } else if (!strcasecmp(v->name, "cos")) {
06784                         if (ast_str2cos(v->value, &qos.cos)) {
06785                             ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
06786          }
06787                 } else if (!strcasecmp(v->name, "cos_audio")) {
06788                         if (ast_str2cos(v->value, &qos.cos_audio)) {
06789                             ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
06790          }
06791       } else if (!strcasecmp(v->name, "debug")) {
06792          if (!strcasecmp(v->value, "no")) {
06793             unistimdebug = 0;
06794          } else if (!strcasecmp(v->value, "yes")) {
06795             unistimdebug = 1;
06796          }
06797       } else if (!strcasecmp(v->name, "autoprovisioning")) {
06798          if (!strcasecmp(v->value, "no")) {
06799             autoprovisioning = AUTOPROVISIONING_NO;
06800          } else if (!strcasecmp(v->value, "yes")) {
06801             autoprovisioning = AUTOPROVISIONING_YES;
06802          } else if (!strcasecmp(v->value, "tn")) {
06803             autoprovisioning = AUTOPROVISIONING_TN;
06804          } else {
06805             ast_log(LOG_WARNING, "Unknown autoprovisioning option.\n");
06806          }
06807       } else if (!strcasecmp(v->name, "public_ip")) {
06808          if (!ast_strlen_zero(v->value)) {
06809             if (!(hp = ast_gethostbyname(v->value, &ahp))) {
06810                ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
06811             } else {
06812                memcpy(&public_ip.sin_addr, hp->h_addr, sizeof(public_ip.sin_addr));
06813                public_ip.sin_family = AF_INET;
06814             }
06815          }
06816       }
06817       v = v->next;
06818    }
06819    if ((unistim_keepalive < 10) ||
06820       (unistim_keepalive >
06821        255 - (((NB_MAX_RETRANSMIT + 1) * RETRANSMIT_TIMER) / 1000))) {
06822       ast_log(LOG_ERROR, "keepalive is invalid in %s\n", config);
06823       ast_config_destroy(cfg);
06824       return -1;
06825    }
06826    packet_send_ping[4] =
06827       unistim_keepalive + (((NB_MAX_RETRANSMIT + 1) * RETRANSMIT_TIMER) / 1000);
06828    if ((unistim_port < 1) || (unistim_port > 65535)) {
06829       ast_log(LOG_ERROR, "port is not set or invalid in %s\n", config);
06830       ast_config_destroy(cfg);
06831       return -1;
06832    }
06833    unistim_keepalive *= 1000;
06834 
06835    ast_mutex_lock(&devicelock);
06836    d = devices;
06837    while (d) {
06838       if (d->to_delete >= 0) {
06839          d->to_delete = 1;
06840       }
06841       d = d->next;
06842    }
06843    ast_mutex_unlock(&devicelock);
06844    /* load the device sections */
06845    cat = ast_category_browse(cfg, NULL);
06846    while (cat) {
06847       if (strcasecmp(cat, "general")) {
06848          d = build_device(cat, ast_variable_browse(cfg, cat));
06849       }
06850       cat = ast_category_browse(cfg, cat);
06851    }
06852    ast_mutex_lock(&devicelock);
06853    d = devices;
06854    while (d) {
06855       if (d->to_delete) {
06856          struct unistim_line *l;
06857          struct unistim_subchannel *sub;
06858 
06859          if (unistimdebug) {
06860             ast_verb(0, "Removing device '%s'\n", d->name);
06861          }
06862          AST_LIST_LOCK(&d->subs);
06863          AST_LIST_TRAVERSE_SAFE_BEGIN(&d->subs, sub, list){
06864             if (sub->subtype == SUB_REAL) {
06865                if (!sub) {
06866                   ast_log(LOG_ERROR, "Device '%s' without a subchannel !, aborting\n",
06867                         d->name);
06868                   ast_config_destroy(cfg);
06869                   return 0;
06870                }
06871                if (sub->owner) {
06872                   ast_log(LOG_WARNING,
06873                         "Device '%s' was not deleted : a call is in progress. Try again later.\n",
06874                         d->name);
06875                   d = d->next;
06876                   continue;
06877                }
06878             }
06879             if (sub->subtype == SUB_THREEWAY) {
06880                ast_log(LOG_WARNING,
06881                      "Device '%s' with threeway call subchannels allocated, aborting.\n",
06882                      d->name);
06883                break;
06884             }
06885             AST_LIST_REMOVE_CURRENT(list);
06886             ast_mutex_destroy(&sub->lock);
06887             ast_free(sub);
06888          }
06889          AST_LIST_TRAVERSE_SAFE_END
06890          AST_LIST_UNLOCK(&d->subs);
06891 
06892 
06893          AST_LIST_LOCK(&d->lines);
06894          AST_LIST_TRAVERSE_SAFE_BEGIN(&d->lines, l, list){
06895             AST_LIST_REMOVE_CURRENT(list);
06896             ast_mutex_destroy(&l->lock);
06897             unistim_line_destroy(l);
06898          }
06899          AST_LIST_TRAVERSE_SAFE_END
06900          AST_LIST_UNLOCK(&d->lines);
06901 
06902          if (d->session) {
06903             if (sessions == d->session) {
06904                sessions = d->session->next;
06905             } else {
06906                s = sessions;
06907                while (s) {
06908                   if (s->next == d->session) {
06909                      s->next = d->session->next;
06910                      break;
06911                   }
06912                   s = s->next;
06913                }
06914             }
06915             ast_mutex_destroy(&d->session->lock);
06916             ast_free(d->session);
06917          }
06918          if (devices == d) {
06919             devices = d->next;
06920          } else {
06921             struct unistim_device *d2 = devices;
06922             while (d2) {
06923                if (d2->next == d) {
06924                   d2->next = d->next;
06925                   break;
06926                }
06927                d2 = d2->next;
06928             }
06929          }
06930          if (d->tz) {
06931             d->tz = ast_tone_zone_unref(d->tz);
06932          }
06933          ast_mutex_destroy(&d->lock);
06934          ast_free(d);
06935          d = devices;
06936          continue;
06937       }
06938       d = d->next;
06939    }
06940    finish_bookmark();
06941    ast_mutex_unlock(&devicelock);
06942    ast_config_destroy(cfg);
06943    ast_mutex_lock(&sessionlock);
06944    s = sessions;
06945    while (s) {
06946       if (s->device) {
06947          refresh_all_favorite(s);
06948          if (ast_strlen_zero(s->device->language)) {
06949             struct unistim_languages lang;
06950             lang = options_languages[find_language(s->device->language)];
06951             send_charset_update(s, lang.encoding);
06952          }
06953       }
06954       s = s->next;
06955    }
06956    ast_mutex_unlock(&sessionlock);
06957    /* We don't recreate a socket when reloading (locks would be necessary). */
06958    if (unistimsock > -1) {
06959       return 0;
06960    }
06961    bindaddr.sin_addr.s_addr = INADDR_ANY;
06962    bindaddr.sin_port = htons(unistim_port);
06963    bindaddr.sin_family = AF_INET;
06964    unistimsock = socket(AF_INET, SOCK_DGRAM, 0);
06965    if (unistimsock < 0) {
06966       ast_log(LOG_WARNING, "Unable to create UNISTIM socket: %s\n", strerror(errno));
06967       return -1;
06968    }
06969 #ifdef HAVE_PKTINFO
06970    {
06971       const int pktinfoFlag = 1;
06972       setsockopt(unistimsock, IPPROTO_IP, IP_PKTINFO, &pktinfoFlag,
06973                sizeof(pktinfoFlag));
06974    }
06975 #else
06976    if (public_ip.sin_family == 0) {
06977       ast_log(LOG_WARNING,
06978             "Your OS does not support IP_PKTINFO, you must set public_ip.\n");
06979       unistimsock = -1;
06980       return -1;
06981    }
06982 #endif
06983    setsockopt(unistimsock, SOL_SOCKET, SO_REUSEADDR, (const char *) &reuseFlag,
06984             sizeof(reuseFlag));
06985    if (bind(unistimsock, (struct sockaddr *) &bindaddr, sizeof(bindaddr)) < 0) {
06986       ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
06987             ast_inet_ntoa(bindaddr.sin_addr), htons(bindaddr.sin_port),
06988             strerror(errno));
06989       close(unistimsock);
06990       unistimsock = -1;
06991    } else {
06992       ast_verb(2, "UNISTIM Listening on %s:%d\n", ast_inet_ntoa(bindaddr.sin_addr), htons(bindaddr.sin_port));
06993       ast_set_qos(unistimsock, qos.tos, qos.cos, "UNISTIM");
06994    }
06995    return 0;
06996 }

static int restart_monitor ( void   )  [static]

Definition at line 5897 of file