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=yes
dialtone_detect=5000
dialtone_detect=always
(closes issue ASTERISK-19316)
Reported by: Jeremy Pepper
Patch by: Jeremy Pepper
Tested by: rmudgett,Jeremy Pepper
Review: https://reviewboard.asterisk.org/r/1737/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358344
65c4cc65-6c06-0410-ace0-
fbb531ad65f3
* Added a manager event "LocalBridge" for local channel call bridges between
the two pseudo-channels created.
* 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
Codec changes
-------------
* Codec lists may now be modified by the '!' character, to allow succinct
#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 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 */
* \note Set from the "waitfordialtone" value read in from chan_dahdi.conf
*/
int waitfordialtone;
* \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. */
struct timeval waitingfordt; /*!< Time we started waiting for dialtone */
struct timeval flashtime; /*!< Last flash-hook time */
/*! \brief Opaque DSP configuration structure. */
p->subs[idx].f.data.ptr = NULL;
p->subs[idx].f.datalen= 0;
}
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;
/* Perform busy detection etc on the dahdi line */
int mute;
+ 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) {
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
f = NULL;
}
} else if (f->frametype == AST_FRAME_DTMF_BEGIN
features |= DSP_FEATURE_BUSY_DETECT;
if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
features |= DSP_FEATURE_CALL_PROGRESS;
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))) {
features |= DSP_FEATURE_WAITDIALTONE;
if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
(i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
+ i->dialtone_scanning_time_elapsed = 0;
+
if (state == AST_STATE_RING)
ast_channel_rings_set(tmp, 1);
ast_channel_tech_pvt_set(tmp, i);
if (state == AST_STATE_RING)
ast_channel_rings_set(tmp, 1);
ast_channel_tech_pvt_set(tmp, i);
tmp->busy_cadence = conf->chan.busy_cadence;
tmp->callprogress = conf->chan.callprogress;
tmp->waitfordialtone = conf->chan.waitfordialtone;
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;
tmp->cancallforward = conf->chan.cancallforward;
tmp->dtmfrelax = conf->chan.dtmfrelax;
tmp->callwaiting = tmp->permcallwaiting;
confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
} else if (!strcasecmp(v->name, "waitfordialtone")) {
confp->chan.waitfordialtone = atoi(v->value);
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")) {
} else if (!strcasecmp(v->name, "faxdetect")) {
confp->chan.callprogress &= ~CALLPROGRESS_FAX;
if (!strcasecmp(v->value, "incoming")) {
; marking the line as once again available for use with outgoing calls.
;waitfordialtone=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
; The following option enables receiving MWI on FXO lines. The default
; value is no.
; The mwimonitor can take the following values