Index: channels/chan_zap.c =================================================================== --- channels/chan_zap.c (revision 113646) +++ channels/chan_zap.c (working copy) @@ -648,6 +648,8 @@ int busy_tonelength; int busy_quietlength; int callprogress; + int waitfordialtone; + struct timeval waitingfordt; /*!< Time we started waiting for dialtone */ struct timeval flashtime; /*!< Last flash-hook time */ struct ast_dsp *dsp; int cref; /*!< Call reference number */ @@ -2113,6 +2115,7 @@ ast_mutex_unlock(&p->lock); return -1; } + p->waitingfordt.tv_sec = 0; p->dialednone = 0; if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ { @@ -2336,6 +2339,21 @@ p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; } else p->echobreak = 0; + + /* waitfordialtone ? */ +#ifdef ZAPATA_PRI + if (!p->pri) { +#endif + if( p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp ) { + ast_log(LOG_DEBUG, "Defer dialling for %dms or dialtone\n", p->waitfordialtone); + gettimeofday(&p->waitingfordt,NULL); + ast_setstate(ast, AST_STATE_OFFHOOK); + break; + } +#ifdef ZAPATA_PRI + } +#endif + if (!res) { if (ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &p->dop)) { x = ZT_ONHOOK; @@ -3261,6 +3279,7 @@ p->callwaitcas = 0; p->callwaiting = p->permcallwaiting; p->hidecallerid = p->permhidecallerid; + p->waitingfordt.tv_sec = 0; p->dialing = 0; p->rdnis[0] = '\0'; update_conf(p); @@ -4996,6 +5015,7 @@ case ZT_EVENT_HOOKCOMPLETE: if (p->inalarm) break; if ((p->radio || (p->oprmode < 0))) break; + if (p->waitingfordt.tv_sec) break; switch (mysig) { case SIG_FXSLS: /* only interesting for FXS */ case SIG_FXSGS: @@ -5449,7 +5469,7 @@ p->subs[index].f.data = NULL; p->subs[index].f.datalen= 0; } - if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) { + if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !index) { /* Perform busy detection. etc on the zap line */ int mute; @@ -5481,6 +5501,36 @@ #endif /* DSP clears us of being pulse */ p->pulsedial = 0; + } else if (p->waitingfordt.tv_sec) { + if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) { + p->waitingfordt.tv_sec = 0; + ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel); + f=NULL; + } else if (f->frametype == AST_FRAME_VOICE) { + f->frametype = AST_FRAME_NULL; + f->subclass = 0; + if (ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE && ast_dsp_get_tcount(p->dsp) > 9) { + p->waitingfordt.tv_sec = 0; + p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE; + ast_dsp_set_features(p->dsp, p->dsp_features); + ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n"); + if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */ + res = ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &p->dop); + if (res < 0) { + ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p-> +channel); + p->dop.dialstr[0] = '\0'; + return NULL; + } else { + ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); + p->dialing = 1; + p->dop.dialstr[0] = '\0'; + p->dop.op = ZT_DIAL_OP_REPLACE; + ast_setstate(ast, AST_STATE_DIALING); + } + } + } + } } } } else @@ -5892,6 +5942,8 @@ features |= DSP_FEATURE_BUSY_DETECT; if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i)) features |= DSP_FEATURE_CALL_PROGRESS; + if ((i->waitfordialtone) && CANPROGRESSDETECT(i)) + features |= DSP_FEATURE_WAITDIALTONE; if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) || (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) { features |= DSP_FEATURE_FAX_DETECT; @@ -8431,6 +8483,7 @@ tmp->busy_tonelength = conf.chan.busy_tonelength; tmp->busy_quietlength = conf.chan.busy_quietlength; tmp->callprogress = conf.chan.callprogress; + tmp->waitfordialtone = conf.chan.waitfordialtone; tmp->cancallforward = conf.chan.cancallforward; tmp->dtmfrelax = conf.chan.dtmfrelax; tmp->callwaiting = tmp->permcallwaiting; @@ -13319,6 +13372,8 @@ confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS; if (ast_true(v->value)) confp->chan.callprogress |= CALLPROGRESS_PROGRESS; + } else if (!strcasecmp(v->name, "waitfordialtone")) { + confp->chan.waitfordialtone = atoi(v->value); } else if (!strcasecmp(v->name, "faxdetect")) { confp->chan.callprogress &= ~CALLPROGRESS_FAX; if (!strcasecmp(v->value, "incoming")) { Index: include/asterisk/dsp.h =================================================================== --- include/asterisk/dsp.h (revision 113646) +++ include/asterisk/dsp.h (working copy) @@ -41,6 +41,7 @@ #define DSP_PROGRESS_BUSY (1 << 18) /*!< Enable busy tone detection */ #define DSP_PROGRESS_CONGESTION (1 << 19) /*!< Enable congestion tone detection */ #define DSP_FEATURE_CALL_PROGRESS (DSP_PROGRESS_TALK | DSP_PROGRESS_RINGING | DSP_PROGRESS_BUSY | DSP_PROGRESS_CONGESTION) +#define DSP_FEATURE_WAITDIALTONE (1 << 20) /*!< Enable dial tone detection */ #define DSP_FAXMODE_DETECT_CNG (1 << 0) #define DSP_FAXMODE_DETECT_CED (1 << 1) Index: main/dsp.c =================================================================== --- main/dsp.c (revision 113646) +++ main/dsp.c (working copy) @@ -82,7 +82,9 @@ HZ_425 = 0, /*! For UK mode */ - HZ_400 = 0 + HZ_350UK = 0, + HZ_400UK, + HZ_440UK }; static struct progalias { @@ -102,7 +104,7 @@ } modes[] = { { GSAMP_SIZE_NA, { 350, 440, 480, 620, 950, 1400, 1800 } }, /*!< North America */ { GSAMP_SIZE_CR, { 425 } }, /*!< Costa Rica, Brazil */ - { GSAMP_SIZE_UK, { 400 } }, /*!< UK */ + { GSAMP_SIZE_UK, { 350, 400, 440 } }, /*!< UK */ }; #define DEFAULT_THRESHOLD 512 @@ -993,8 +995,10 @@ newstate = DSP_TONE_STATE_SILENCE; break; case PROG_MODE_UK: - if (hz[HZ_400] > TONE_MIN_THRESH * TONE_THRESH) { + if (hz[HZ_400UK] > TONE_MIN_THRESH * TONE_THRESH) { newstate = DSP_TONE_STATE_HUNGUP; + } else if (pair_there(hz[HZ_350UK], hz[HZ_440UK], hz[HZ_400UK], hz[HZ_400UK], dsp->genergy)) { + newstate = DSP_TONE_STATE_DIALTONE; } break; default: @@ -1399,7 +1403,8 @@ ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res); } } - } + } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) + res = __ast_dsp_call_progress(dsp, shortdata, len); done: /* Mute fragment of the frame */