diff options
Diffstat (limited to 'channels/chan_skinny.c')
-rw-r--r-- | channels/chan_skinny.c | 160 |
1 files changed, 79 insertions, 81 deletions
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index b90ba7eba..ea7d16c9e 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -1126,6 +1126,10 @@ static int callnums = 1; #define SKINNY_ALERT 0x24 #define SKINNY_REORDER 0x25 #define SKINNY_CALLWAITTONE 0x2D +#define SKINNY_ZIPZIP 0x31 +#define SKINNY_ZIP 0x32 +#define SKINNY_BEEPBONK 0x33 +#define SKINNY_BARGIN 0x43 #define SKINNY_NOTONE 0x7F #define SKINNY_LAMP_OFF 1 @@ -1164,18 +1168,10 @@ static const char * const skinny_cxmodes[] = { /* driver scheduler */ static struct ast_sched_context *sched = NULL; -static struct io_context *io; -/* Protect the monitoring thread, so only one process can kill or start it, and not - when it's doing something critical. */ -AST_MUTEX_DEFINE_STATIC(monlock); /* Protect the network socket */ AST_MUTEX_DEFINE_STATIC(netlock); -/* This is the thread for the monitor which checks for input on the channels - which are not currently in use. */ -static pthread_t monitor_thread = AST_PTHREADT_NULL; - /* Wait up to 16 seconds for first digit */ static int firstdigittimeout = 16000; @@ -1215,7 +1211,9 @@ struct skinny_subchannel { int blindxfer; int xferor; int substate; - + int aa_sched; + int aa_beep; + int aa_mute; AST_LIST_ENTRY(skinny_subchannel) list; struct skinny_subchannel *related; @@ -1712,6 +1710,16 @@ static struct ast_variable *add_var(const char *buf, struct ast_variable *list) return list; } +static int skinny_sched_del(int sched_id) +{ + return ast_sched_del(sched, sched_id); +} + +static int skinny_sched_add(int when, ast_sched_cb callback, const void *data) +{ + return ast_sched_add(sched, when, callback, data); +} + /* It's quicker/easier to find the subchannel when we know the instance number too */ static struct skinny_subchannel *find_subchannel_by_instance_reference(struct skinny_device *d, int instance, int reference) { @@ -2235,7 +2243,7 @@ static void transmit_speaker_mode(struct skinny_device *d, int mode) req->data.setspeaker.mode = htolel(mode); transmit_response(d, req); } -/* + static void transmit_microphone_mode(struct skinny_device *d, int mode) { struct skinny_req *req; @@ -2246,7 +2254,6 @@ static void transmit_microphone_mode(struct skinny_device *d, int mode) req->data.setmicrophone.mode = htolel(mode); transmit_response(d, req); } -*/ static void transmit_callinfo(struct skinny_subchannel *sub) { @@ -4044,7 +4051,13 @@ static void *skinny_ss(void *data) return NULL; } - +static int skinny_autoanswer_cb(const void *data) +{ + struct skinny_subchannel *sub = (struct skinny_subchannel *)data; + sub->aa_sched = 0; + setsubstate(sub, SKINNY_CONNECTED); + return 0; +} static int skinny_call(struct ast_channel *ast, char *dest, int timeout) { @@ -4052,6 +4065,8 @@ static int skinny_call(struct ast_channel *ast, char *dest, int timeout) struct skinny_subchannel *sub = ast->tech_pvt; struct skinny_line *l = sub->line; struct skinny_device *d = l->device; + struct ast_var_t *current; + int doautoanswer = 0; if (!d->registered) { ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest); @@ -4075,8 +4090,40 @@ static int skinny_call(struct ast_channel *ast, char *dest, int timeout) ast_queue_control(ast, AST_CONTROL_BUSY); return -1; } - + + AST_LIST_TRAVERSE(&ast->varshead, current, entries) { + if (!(strcasecmp(ast_var_name(current),"SKINNY_AUTOANSWER"))) { + if (d->hookstate == SKINNY_ONHOOK && !sub->aa_sched) { + char buf[24]; + int aatime; + char *stringp = buf, *curstr; + ast_copy_string(buf, ast_var_value(current), sizeof(buf)); + curstr = strsep(&stringp, ":"); + ast_verb(3, "test %s\n", curstr); + aatime = atoi(curstr); + while ((curstr = strsep(&stringp, ":"))) { + if (!(strcasecmp(curstr,"BEEP"))) { + sub->aa_beep = 1; + } else if (!(strcasecmp(curstr,"MUTE"))) { + sub->aa_mute = 1; + } + } + if (skinnydebug) + ast_verb(3, "Sub %d - setting autoanswer time=%dms %s%s\n", sub->callid, aatime, sub->aa_beep?"BEEP ":"", sub->aa_mute?"MUTE":""); + if (aatime) { + //sub->aa_sched = ast_sched_add(sched, aatime, skinny_autoanswer_cb, sub); + sub->aa_sched = skinny_sched_add(aatime, skinny_autoanswer_cb, sub); + } else { + doautoanswer = 1; + } + } + } + } + setsubstate(sub, SUBSTATE_RINGIN); + if (doautoanswer) { + setsubstate(sub, SUBSTATE_CONNECTED); + } return res; } @@ -4637,6 +4684,13 @@ static void setsubstate(struct skinny_subchannel *sub, int state) if (sub->substate == SUBSTATE_ONHOOK) { return; } + + if (state != SUBSTATE_RINGIN && sub->aa_sched) { + skinny_sched_del(sub->aa_sched); + sub->aa_sched = 0; + sub->aa_beep = 0; + sub->aa_mute = 0; + } if ((state == SUBSTATE_RINGIN) && ((d->hookstate == SKINNY_OFFHOOK) || (AST_LIST_NEXT(AST_LIST_FIRST(&l->sub), list)))) { actualstate = SUBSTATE_CALLWAIT; @@ -4789,6 +4843,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state) ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); transmit_connect(d, sub); } + transmit_ringer_mode(d, SKINNY_RING_OFF); transmit_activatecallplane(d, l); transmit_stop_tone(d, l->instance, sub->callid); transmit_callinfo(sub); @@ -4798,6 +4853,12 @@ static void setsubstate(struct skinny_subchannel *sub, int state) if (!sub->rtp) { start_rtp(sub); } + if (sub->aa_beep) { + transmit_start_tone(d, SKINNY_ZIP, l->instance, sub->callid); + } + if (sub->aa_mute) { + transmit_microphone_mode(d, SKINNY_MICOFF); + } if (sub->substate == SUBSTATE_RINGIN || sub->substate == SUBSTATE_CALLWAIT) { ast_queue_control(sub->owner, AST_CONTROL_ANSWER); } @@ -6499,59 +6560,6 @@ static void *accept_thread(void *ignore) return 0; } -static void *do_monitor(void *data) -{ - int res; - - /* This thread monitors all the interfaces which are not yet in use - (and thus do not have a separate thread) indefinitely */ - /* From here on out, we die whenever asked */ - for(;;) { - pthread_testcancel(); - /* Wait for sched or io */ - res = ast_sched_wait(sched); - if ((res < 0) || (res > 1000)) { - res = 1000; - } - res = ast_io_wait(io, res); - ast_mutex_lock(&monlock); - if (res >= 0) { - ast_sched_runq(sched); - } - ast_mutex_unlock(&monlock); - } - /* Never reached */ - return NULL; - -} - -static int restart_monitor(void) -{ - /* If we're supposed to be stopped -- stay stopped */ - if (monitor_thread == AST_PTHREADT_STOP) - return 0; - - ast_mutex_lock(&monlock); - if (monitor_thread == pthread_self()) { - ast_mutex_unlock(&monlock); - ast_log(LOG_WARNING, "Cannot kill myself\n"); - return -1; - } - if (monitor_thread != AST_PTHREADT_NULL) { - /* Wake up the thread */ - pthread_kill(monitor_thread, SIGURG); - } else { - /* Start a new monitor */ - if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { - ast_mutex_unlock(&monlock); - ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); - return -1; - } - } - ast_mutex_unlock(&monlock); - return 0; -} - static int skinny_devicestate(void *data) { struct skinny_line *l; @@ -6591,7 +6599,6 @@ static struct ast_channel *skinny_request(const char *type, struct ast_format_ca if (!tmpc) { ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp); } - restart_monitor(); return tmpc; } @@ -7425,13 +7432,13 @@ static int load_module(void) sched = ast_sched_context_create(); if (!sched) { ast_log(LOG_WARNING, "Unable to create schedule context\n"); + return AST_MODULE_LOAD_FAILURE; } - io = io_context_create(); - if (!io) { - ast_log(LOG_WARNING, "Unable to create I/O context\n"); + if (ast_sched_start_thread(sched)) { + ast_sched_context_destroy(sched); + sched = NULL; + return AST_MODULE_LOAD_FAILURE; } - /* And start the monitor for the first time */ - restart_monitor(); return AST_MODULE_LOAD_SUCCESS; } @@ -7483,15 +7490,6 @@ static int unload_module(void) delete_devices(); - ast_mutex_lock(&monlock); - if ((monitor_thread != AST_PTHREADT_NULL) && (monitor_thread != AST_PTHREADT_STOP)) { - pthread_cancel(monitor_thread); - pthread_kill(monitor_thread, SIGURG); - pthread_join(monitor_thread, NULL); - } - monitor_thread = AST_PTHREADT_STOP; - ast_mutex_unlock(&monlock); - ast_mutex_lock(&netlock); if (accept_t && (accept_t != AST_PTHREADT_STOP)) { pthread_cancel(accept_t); |