diff --git a/CHANGES b/CHANGES index 443f1acb02092c8c2165e39065846ce16341bb41..10c179fba9d65d28c943f9f23ac05dd105af0837 100644 --- a/CHANGES +++ b/CHANGES @@ -73,6 +73,11 @@ Chan_local changes * Added a manager event "LocalBridge" for local channel call bridges between the two pseudo-channels created. +Chan_dahdi changes +------------------ + * Added dialtone_detect option for analog ports to disconnect incoming + calls when dialtone is detected. + Codec changes ------------- * Codec lists may now be modified by the '!' character, to allow succinct diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 21214bd88b6e1bdb2399409efc62bf24dbd9618c..d65bb122ef257613575f95bd9cf211b25a7d8945 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -532,6 +532,7 @@ static inline int dahdi_wait_event(int fd) #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE) /*!< 500 ms */ #define MIN_MS_SINCE_FLASH ((2000) ) /*!< 2000 ms */ #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE) /*!< 8,000 ms */ +#define DEFAULT_DIALTONE_DETECT_TIMEOUT ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */ struct dahdi_pvt; @@ -1167,6 +1168,12 @@ struct dahdi_pvt { * \note Set from the "waitfordialtone" value read in from chan_dahdi.conf */ int waitfordialtone; + /*! + * \brief Number of frames to watch for dialtone in incoming calls + * \note Set from the "dialtone_detect" value read in from chan_dahdi.conf + */ + int dialtone_detect; + int dialtone_scanning_time_elapsed; /*!< Amount of audio scanned for dialtone, in frames */ struct timeval waitingfordt; /*!< Time we started waiting for dialtone */ struct timeval flashtime; /*!< Last flash-hook time */ /*! \brief Opaque DSP configuration structure. */ @@ -9250,7 +9257,7 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast) p->subs[idx].f.data.ptr = NULL; p->subs[idx].f.datalen= 0; } - if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) { + if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec || p->dialtone_detect) && !idx) { /* Perform busy detection etc on the dahdi line */ int mute; @@ -9264,10 +9271,24 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast) } if (f) { + if ((p->dsp_features & DSP_FEATURE_WAITDIALTONE) && (p->dialtone_detect > 0) + && !p->outgoing && ast_channel_state(ast) == AST_STATE_UP) { + if (++p->dialtone_scanning_time_elapsed >= p->dialtone_detect) { + p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE; + ast_dsp_set_features(p->dsp, p->dsp_features); + } + } if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) { if ((ast_channel_state(ast) == AST_STATE_UP) && !p->outgoing) { - /* Treat this as a "hangup" instead of a "busy" on the assumption that - a busy */ + /* + * Treat this as a "hangup" instead of a "busy" on the + * assumption that a busy means the incoming call went away. + */ + f = NULL; + } + } else if (p->dialtone_detect && !p->outgoing && f->frametype == AST_FRAME_VOICE) { + if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE) && (ast_dsp_get_tcount(p->dsp) > 9)) { + /* Dialtone detected on inbound call; hangup the channel */ f = NULL; } } else if (f->frametype == AST_FRAME_DTMF_BEGIN @@ -9691,7 +9712,7 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb features |= DSP_FEATURE_BUSY_DETECT; if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i)) features |= DSP_FEATURE_CALL_PROGRESS; - if ((i->waitfordialtone) && CANPROGRESSDETECT(i)) + if ((i->waitfordialtone || i->dialtone_detect) && CANPROGRESSDETECT(i)) features |= DSP_FEATURE_WAITDIALTONE; if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) || (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) { @@ -9737,6 +9758,8 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb } } + i->dialtone_scanning_time_elapsed = 0; + if (state == AST_STATE_RING) ast_channel_rings_set(tmp, 1); ast_channel_tech_pvt_set(tmp, i); @@ -12873,6 +12896,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, tmp->busy_cadence = conf->chan.busy_cadence; tmp->callprogress = conf->chan.callprogress; tmp->waitfordialtone = conf->chan.waitfordialtone; + tmp->dialtone_detect = conf->chan.dialtone_detect; tmp->cancallforward = conf->chan.cancallforward; tmp->dtmfrelax = conf->chan.dtmfrelax; tmp->callwaiting = tmp->permcallwaiting; @@ -17281,6 +17305,16 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct confp->chan.callprogress |= CALLPROGRESS_PROGRESS; } else if (!strcasecmp(v->name, "waitfordialtone")) { confp->chan.waitfordialtone = atoi(v->value); + } else if (!strcasecmp(v->name, "dialtone_detect")) { + if (!strcasecmp(v->value, "always")) { + confp->chan.dialtone_detect = -1; + } else if (ast_true(v->value)) { + confp->chan.dialtone_detect = DEFAULT_DIALTONE_DETECT_TIMEOUT; + } else if (ast_false(v->value)) { + confp->chan.dialtone_detect = 0; + } else { + confp->chan.dialtone_detect = ast_strlen_zero(v->value) ? 0 : (8 * atoi(v->value)) / READ_SIZE; + } } else if (!strcasecmp(v->name, "faxdetect")) { confp->chan.callprogress &= ~CALLPROGRESS_FAX; if (!strcasecmp(v->value, "incoming")) { diff --git a/configs/chan_dahdi.conf.sample b/configs/chan_dahdi.conf.sample index 10c55ca7564aa17a82c887b23bc58131be44ae1e..d83bba8d9b38a88166051c0f0a1f987af3c82297 100644 --- a/configs/chan_dahdi.conf.sample +++ b/configs/chan_dahdi.conf.sample @@ -551,6 +551,17 @@ usecallerid=yes ; marking the line as once again available for use with outgoing calls. ;waitfordialtone=yes ; +; For analog lines, enables Asterisk to use dialtone detection per channel +; if an incoming call was hung up before it was answered. If dialtone is +; detected, the call is hung up. +; no: Disabled. (Default) +; yes: Look for dialtone for 10000 ms after answer. +; <number>: Look for dialtone for the specified number of ms after answer. +; always: Look for dialtone for the entire call. Dialtone may return +; if the far end hangs up first. +; +;dialtone_detect=no +; ; The following option enables receiving MWI on FXO lines. The default ; value is no. ; The mwimonitor can take the following values