diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 84229a127fb5d85d909908b79b8f20b26484f409..31e95020fb3918fbfe4db35080999ff6ee266250 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -2055,6 +2055,44 @@ static void my_set_ringtimeout(void *pvt, int ringt) p->ringt = ringt; } +static void my_set_waitingfordt(void *pvt, struct ast_channel *ast) +{ + struct dahdi_pvt *p = pvt; + + if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) { + ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone); + gettimeofday(&p->waitingfordt, NULL); + ast_setstate(ast, AST_STATE_OFFHOOK); + } +} + +static int my_check_waitingfordt(void *pvt) +{ + struct dahdi_pvt *p = pvt; + + if (p->waitingfordt.tv_usec) { + return 1; + } + + return 0; +} + +static void my_set_confirmanswer(void *pvt, int flag) +{ + struct dahdi_pvt *p = pvt; + p->confirmanswer = flag; +} + +static int my_check_confirmanswer(void *pvt) +{ + struct dahdi_pvt *p = pvt; + if (p->confirmanswer) { + return 1; + } + + return 0; +} + static void my_increase_ss_count(void) { ast_mutex_lock(&ss_thread_lock); @@ -2201,9 +2239,9 @@ static void my_swap_subchannels(void *pvt, enum analog_sub a, struct ast_channel p->subs[db].chan = tchan; if (ast_a) - ast_a->fds[0] = p->subs[da].dfd; + ast_channel_set_fd(ast_a, 0, p->subs[da].dfd); if (ast_b) - ast_b->fds[0] = p->subs[db].dfd; + ast_channel_set_fd(ast_b, 0, p->subs[db].dfd); p->subs[da].owner = ast_a; p->subs[db].owner = ast_b; @@ -2779,6 +2817,10 @@ static struct analog_callback dahdi_analog_callbacks = .set_cadence = my_set_cadence, .set_dialing = my_set_dialing, .set_ringtimeout = my_set_ringtimeout, + .set_waitingfordt = my_set_waitingfordt, + .check_waitingfordt = my_check_waitingfordt, + .set_confirmanswer = my_set_confirmanswer, + .check_confirmanswer = my_check_confirmanswer, }; static struct dahdi_pvt *round_robin[32]; @@ -4994,6 +5036,7 @@ static int dahdi_hangup(struct ast_channel *ast) dahdi_confmute(p, 0); restore_gains(p); p->ignoredtmf = 0; + p->waitingfordt.tv_sec = 0; res = analog_hangup(p->sig_pvt, ast); revert_fax_buffers(p, ast); diff --git a/channels/sig_analog.c b/channels/sig_analog.c index 6678f3fa83008d288aed1169e8cb4f03b649acae..211e0a77ab8cb306fa23043770b39ac9e03d823b 100644 --- a/channels/sig_analog.c +++ b/channels/sig_analog.c @@ -716,6 +716,47 @@ static void analog_set_ringtimeout(struct analog_pvt *p, int ringt) p->calls->set_ringtimeout(p->chan_pvt, ringt); } +static void analog_set_waitingfordt(struct analog_pvt *p, struct ast_channel *ast) +{ + if (p->calls->set_waitingfordt) { + return p->calls->set_waitingfordt(p->chan_pvt, ast); + } +} + +static int analog_check_waitingfordt(struct analog_pvt *p) +{ + if (p->calls->check_waitingfordt) { + return p->calls->check_waitingfordt(p->chan_pvt); + } + + return 0; +} + +static void analog_set_confirmanswer(struct analog_pvt *p, int flag) +{ + if (!p->calls->set_confirmanswer) { + return; + } + p->calls->set_confirmanswer(p->chan_pvt, flag); +} + +static int analog_check_confirmanswer(struct analog_pvt *p) +{ + if (p->calls->check_confirmanswer) { + return p->calls->check_confirmanswer(p->chan_pvt); + } + + return 0; +} + +static int analog_set_linear_mode(struct analog_pvt *p, int index, int linear_mode) +{ + if (p->calls->set_linear_mode) { + return p->calls->set_linear_mode(p->chan_pvt, index, linear_mode); + } else + return -1; +} + int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int timeout) { int res, index,mysig; @@ -923,6 +964,7 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; } else p->echobreak = 0; + analog_set_waitingfordt(p, ast); if (!res) { if (analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop)) { int saveerr = errno; @@ -977,8 +1019,8 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast) if (index > -1) { /* Real channel, do some fixup */ p->subs[index].owner = NULL; - p->subs[index].needcallerid = 0; p->polarity = POLARITY_IDLE; + analog_set_linear_mode(p, index, 0); if (index == ANALOG_SUB_REAL) { if (p->subs[ANALOG_SUB_CALLWAIT].allocd && p->subs[ANALOG_SUB_THREEWAY].allocd) { ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n"); @@ -1070,6 +1112,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast) if (!p->subs[ANALOG_SUB_REAL].owner && !p->subs[ANALOG_SUB_CALLWAIT].owner && !p->subs[ANALOG_SUB_THREEWAY].owner) { p->owner = NULL; analog_set_ringtimeout(p, 0); + analog_set_confirmanswer(p, 0); p->outgoing = 0; p->onhooktime = time(NULL); p->cidrings = 1; @@ -1217,6 +1260,16 @@ void analog_handle_dtmfup(struct analog_pvt *p, struct ast_channel *ast, enum an { struct ast_frame *f = *dest; + if (analog_check_confirmanswer(p)) { + ast_debug(1, "Confirm answer on %s!\n", ast->name); + /* Upon receiving a DTMF digit, consider this an answer confirmation instead + of a DTMF digit */ + p->subs[index].f.frametype = AST_FRAME_CONTROL; + p->subs[index].f.subclass = AST_CONTROL_ANSWER; + *dest = &p->subs[index].f; + /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ + analog_set_confirmanswer(p, 0); + } if (p->callwaitcas) { if ((f->subclass == 'A') || (f->subclass == 'D')) { ast_log(LOG_ERROR, "Got some DTMF, but it's for the CAS\n"); @@ -1290,14 +1343,6 @@ static int analog_distinctive_ring(struct ast_channel *chan, struct analog_pvt * } -static int analog_set_linear_mode(struct analog_pvt *p, int index, int linear_mode) -{ - if (p->calls->set_linear_mode) { - return p->calls->set_linear_mode(p->chan_pvt, index, linear_mode); - } else - return -1; -} - static void analog_get_and_handle_alarms(struct analog_pvt *p) { if (p->calls->get_and_handle_alarms) @@ -2204,7 +2249,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ } } if (ast->_state == AST_STATE_DIALING) { - if ((!p->dialednone && ((mysig == ANALOG_SIG_EM) || (mysig == ANALOG_SIG_EM_E1) || (mysig == ANALOG_SIG_EMWINK) || (mysig == ANALOG_SIG_FEATD) || (mysig == ANALOG_SIG_FEATDMF_TA) || (mysig == ANALOG_SIG_FEATDMF) || (mysig == ANALOG_SIG_E911) || (mysig == ANALOG_SIG_FGC_CAMA) || (mysig == ANALOG_SIG_FGC_CAMAMF) || (mysig == ANALOG_SIG_FEATB) || (mysig == ANALOG_SIG_SF) || (mysig == ANALOG_SIG_SFWINK) || (mysig == ANALOG_SIG_SF_FEATD) || (mysig == ANALOG_SIG_SF_FEATDMF) || (mysig == ANALOG_SIG_SF_FEATB)))) { + if (analog_check_confirmanswer(p) || (!p->dialednone && ((mysig == ANALOG_SIG_EM) || (mysig == ANALOG_SIG_EM_E1) || (mysig == ANALOG_SIG_EMWINK) || (mysig == ANALOG_SIG_FEATD) || (mysig == ANALOG_SIG_FEATDMF_TA) || (mysig == ANALOG_SIG_FEATDMF) || (mysig == ANALOG_SIG_E911) || (mysig == ANALOG_SIG_FGC_CAMA) || (mysig == ANALOG_SIG_FGC_CAMAMF) || (mysig == ANALOG_SIG_FEATB) || (mysig == ANALOG_SIG_SF) || (mysig == ANALOG_SIG_SFWINK) || (mysig == ANALOG_SIG_SF_FEATD) || (mysig == ANALOG_SIG_SF_FEATDMF) || (mysig == ANALOG_SIG_SF_FEATB)))) { ast_setstate(ast, AST_STATE_RINGING); } else if (!p->answeronpolarityswitch) { ast_setstate(ast, AST_STATE_UP); @@ -2375,7 +2420,11 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ ast_debug(1, "channel %d answered\n", p->channel); analog_set_dialing(p, 0); p->callwaitcas = 0; - if (!ast_strlen_zero(p->dop.dialstr)) { + if (analog_check_confirmanswer(p)) { + /* Ignore answer if "confirm answer" is enabled */ + p->subs[index].f.frametype = AST_FRAME_NULL; + p->subs[index].f.subclass = 0; + } else if (!ast_strlen_zero(p->dop.dialstr)) { /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ res = analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop); if (res < 0) { @@ -2449,9 +2498,14 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ p->subs[index].f.subclass = AST_CONTROL_RING; } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { ast_debug(1, "Line answered\n"); - p->subs[index].f.frametype = AST_FRAME_CONTROL; - p->subs[index].f.subclass = AST_CONTROL_ANSWER; - ast_setstate(ast, AST_STATE_UP); + if (analog_check_confirmanswer(p)) { + p->subs[index].f.frametype = AST_FRAME_NULL; + p->subs[index].f.subclass = 0; + } else { + p->subs[index].f.frametype = AST_FRAME_CONTROL; + p->subs[index].f.subclass = AST_CONTROL_ANSWER; + ast_setstate(ast, AST_STATE_UP); + } } else if (ast->_state != AST_STATE_RING) ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); break; @@ -2734,6 +2788,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ break; case ANALOG_EVENT_HOOKCOMPLETE: if (p->inalarm) break; + if (analog_check_waitingfordt(p)) break; switch (mysig) { case ANALOG_SIG_FXSLS: /* only interesting for FXS */ case ANALOG_SIG_FXSGS: diff --git a/channels/sig_analog.h b/channels/sig_analog.h index f33f417b750224b9570eb017472aed8f03884a74..381655021e97e90d5aaa7fd68780007fe9bc3141 100644 --- a/channels/sig_analog.h +++ b/channels/sig_analog.h @@ -194,6 +194,10 @@ struct analog_callback { void (* const set_cadence)(void *pvt, int *cidrings, struct ast_channel *chan); void (* const set_dialing)(void *pvt, int flag); void (* const set_ringtimeout)(void *pvt, int ringt); + void (* const set_waitingfordt)(void *pvt, struct ast_channel *ast); + int (* const check_waitingfordt)(void *pvt); + void (* const set_confirmanswer)(void *pvt, int flag); + int (* const check_confirmanswer)(void *pvt); }; @@ -203,7 +207,6 @@ struct analog_callback { struct analog_subchannel { struct ast_channel *owner; struct ast_frame f; /*!< One frame for each channel. How did this ever work before? */ - unsigned int needcallerid:1; unsigned int inthreeway:1; /* Have we allocated a subchannel yet or not */ unsigned int allocd:1; @@ -292,7 +295,7 @@ struct analog_pvt { char call_forward[AST_MAX_EXTENSION]; /* Ast channel to pass to __ss_analog_thread */ - void *ss_astchan; + struct ast_channel *ss_astchan; /* All variables after this are definitely going to be audited */ unsigned int inalarm:1;