aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_skinny.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels/chan_skinny.c')
-rw-r--r--channels/chan_skinny.c160
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);