Index: drivers/dahdi/wctdm.c =================================================================== --- drivers/dahdi/wctdm.c (revision 6690) +++ drivers/dahdi/wctdm.c (working copy) @@ -227,6 +227,8 @@ int lastpol; int polarity; int polaritydebounce; + int readcid; + unsigned int cidtimer; } fxo; struct fxs { int oldrxhook; @@ -283,22 +285,23 @@ static unsigned int battalarm; static unsigned int battthresh; static int ringdebounce = DEFAULT_RING_DEBOUNCE; -static int fwringdetect = 0; -static int debug = 0; -static int robust = 0; -static int timingonly = 0; -static int lowpower = 0; -static int boostringer = 0; -static int fastringer = 0; -static int _opermode = 0; +static int fwringdetect; +static int debug; +static int robust; +static int timingonly; +static int lowpower; +static int boostringer; +static int fastringer; +static int _opermode; static char *opermode = "FCC"; -static int fxshonormode = 0; -static int alawoverride = 0; -static int fastpickup = 0; -static int fxotxgain = 0; -static int fxorxgain = 0; -static int fxstxgain = 0; -static int fxsrxgain = 0; +static int fxshonormode; +static int alawoverride; +static int fastpickup; +static int fxotxgain; +static int fxorxgain; +static int fxstxgain; +static int fxsrxgain; +static int dtmf; static int wctdm_init_proslic(struct wctdm *wc, int card, int fast , int manual, int sane); @@ -391,6 +394,41 @@ } } #endif + +static void wctdm_dtmfcheck_fakepolarity(struct wctdm *wc, int card, int x) +{ + int sample; + struct fxo *const fxo = &wc->mod[card].fxo; + + /* only look for sound on the line if dtmf flag is on, it is an fxo + * card and line is onhook */ + if (!dtmf || !(wc->cardflag & (1 << card)) || + wc->modtype[card] != MOD_TYPE_FXO || fxo->offhook) + return; + + /* don't look for noise if we're already processing it, or there is a + * ringing tone */ + if (!fxo->readcid && !fxo->wasringing && + wc->intcount > fxo->cidtimer + 400) { + sample = DAHDI_XLAW(wc->chans[card]->readchunk[x], + wc->chans[card]); + if (sample > 2000 || sample < -2000) { + fxo->readcid = 1; + fxo->cidtimer = wc->intcount; + if (debug) { + printk(KERN_DEBUG "DTMF CLIP on %i\n", + card + 1); + } + dahdi_qevent_lock(wc->chans[card], + DAHDI_EVENT_POLARITY); + } + } else if (fxo->readcid && wc->intcount > fxo->cidtimer + 2000) { + /* reset flags if it's been a while */ + fxo->cidtimer = wc->intcount; + fxo->readcid = 0; + } +} + static inline void wctdm_receiveprep(struct wctdm *wc, unsigned char ints) { volatile unsigned int *readchunk; @@ -405,21 +443,29 @@ #ifdef __BIG_ENDIAN if (wc->cardflag & (1 << 3)) wc->chans[3]->readchunk[x] = (readchunk[x]) & 0xff; + wctdm_dtmfcheck_fakepolarity(wc, 3, x); if (wc->cardflag & (1 << 2)) wc->chans[2]->readchunk[x] = (readchunk[x] >> 8) & 0xff; + wctdm_dtmfcheck_fakepolarity(wc, 2, x); if (wc->cardflag & (1 << 1)) wc->chans[1]->readchunk[x] = (readchunk[x] >> 16) & 0xff; + wctdm_dtmfcheck_fakepolarity(wc, 1, x); if (wc->cardflag & (1 << 0)) wc->chans[0]->readchunk[x] = (readchunk[x] >> 24) & 0xff; + wctdm_dtmfcheck_fakepolarity(wc, 0, x); #else if (wc->cardflag & (1 << 3)) wc->chans[3]->readchunk[x] = (readchunk[x] >> 24) & 0xff; + wctdm_dtmfcheck_fakepolarity(wc, 3, x); if (wc->cardflag & (1 << 2)) wc->chans[2]->readchunk[x] = (readchunk[x] >> 16) & 0xff; + wctdm_dtmfcheck_fakepolarity(wc, 2, x); if (wc->cardflag & (1 << 1)) wc->chans[1]->readchunk[x] = (readchunk[x] >> 8) & 0xff; + wctdm_dtmfcheck_fakepolarity(wc, 1, x); if (wc->cardflag & (1 << 0)) wc->chans[0]->readchunk[x] = (readchunk[x]) & 0xff; + wctdm_dtmfcheck_fakepolarity(wc, 0, x); #endif } #ifdef AUDIO_RINGCHECK @@ -786,6 +832,8 @@ (fxo->battery == BATTERY_PRESENT)) { if (!fxo->wasringing) { fxo->wasringing = 1; + fxo->readcid = 0; + fxo->cidtimer = wc->intcount; if (debug) printk(KERN_DEBUG "RING on %d/%d!\n", wc->span.spanno, card + 1); dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING); @@ -795,6 +843,8 @@ } else if (!res) { if ((fxo->ringdebounce == 0) && fxo->wasringing) { fxo->wasringing = 0; + fxo->readcid = 0; + fxo->cidtimer = wc->intcount; if (debug) printk(KERN_DEBUG "NO RING on %d/%d!\n", wc->span.spanno, card + 1); dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK); @@ -811,6 +861,8 @@ if (fxo->ringdebounce >= DAHDI_CHUNKSIZE * ringdebounce) { if (!fxo->wasringing) { fxo->wasringing = 1; + fxo->readcid = 0; + fxo->cidtimer = wc->intcount; dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING); if (debug) printk(KERN_DEBUG "RING on %d/%d!\n", wc->span.spanno, card + 1); @@ -822,6 +874,8 @@ if (fxo->ringdebounce <= 0) { if (fxo->wasringing) { fxo->wasringing = 0; + fxo->readcid = 0; + fxo->cidtimer = wc->intcount; dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK); if (debug) printk(KERN_DEBUG "NO RING on %d/%d!\n", wc->span.spanno, card + 1); @@ -2572,6 +2626,7 @@ module_param(fxorxgain, int, 0600); module_param(fxstxgain, int, 0600); module_param(fxsrxgain, int, 0600); +module_param(dtmf, int, 0600); MODULE_DESCRIPTION("Wildcard TDM400P Driver"); MODULE_AUTHOR("Mark Spencer "); Index: drivers/dahdi/wctdm24xxp/wctdm24xxp.h =================================================================== --- drivers/dahdi/wctdm24xxp/wctdm24xxp.h (revision 6690) +++ drivers/dahdi/wctdm24xxp/wctdm24xxp.h (working copy) @@ -190,6 +190,8 @@ int lastpol; int polarity; int polaritydebounce; + int readcid; + unsigned int cidtimer; int neonmwi_state; int neonmwi_last_voltage; unsigned int neonmwi_debounce; Index: drivers/dahdi/wctdm24xxp/base.c =================================================================== --- drivers/dahdi/wctdm24xxp/base.c (revision 6690) +++ drivers/dahdi/wctdm24xxp/base.c (working copy) @@ -216,6 +216,7 @@ static int vpmnlptype = DEFAULT_NLPTYPE; static int vpmnlpthresh = DEFAULT_NLPTHRESH; static int vpmnlpmaxsupp = DEFAULT_NLPMAXSUPP; +static int dtmf; static int echocan_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); @@ -706,7 +707,7 @@ #endif } -static inline void cmd_decipher_vpmadt032(struct wctdm *wc, unsigned char *readchunk) +static void cmd_decipher_vpmadt032(struct wctdm *wc, const u8 *readchunk) { unsigned long flags; struct vpmadt032 *vpm = wc->vpmadt032; @@ -751,7 +752,7 @@ #endif } -static inline void cmd_decipher(struct wctdm *wc, volatile unsigned char *readchunk, int card) +static void cmd_decipher(struct wctdm *wc, const u8 *readchunk, int card) { unsigned long flags; unsigned char ident; @@ -1014,8 +1015,42 @@ #endif } -static inline void wctdm_receiveprep(struct wctdm *wc, unsigned char *readchunk) +static void wctdm_dtmfcheck_fakepolarity(struct wctdm *wc, int card, u8 sample8) { + u16 sample16; + struct fxo *const fxo = &(wc->mods[card].fxo); + + /* only look for sound on the line if dtmf flag is on, it is an fxo + * card and line is onhook */ + if (!dtmf || !(wc->cardflag & (1 << card)) || + (wc->modtype[card] != MOD_TYPE_FXO) || fxo->offhook) { + return; + } + + /* don't look for noise if we're already processing it, or there is a + * ringing tone */ + if (!fxo->readcid && !fxo->wasringing && + wc->intcount > fxo->cidtimer + 400) { + sample16 = DAHDI_XLAW(sample8, wc->chans[card]); + if (sample16 > 2000 || sample16 < -2000) { + fxo->readcid = 1; + fxo->cidtimer = wc->intcount; + if (debug) { + printk(KERN_DEBUG "DTMF CLIP on %i\n", + card + 1); + } + dahdi_qevent_lock(wc->chans[card], + DAHDI_EVENT_POLARITY); + } + } else if (fxo->readcid && wc->intcount > fxo->cidtimer + 2000) { + /* reset flags if it's been a while */ + fxo->cidtimer = wc->intcount; + fxo->readcid = 0; + } +} + +static inline void wctdm_receiveprep(struct wctdm *wc, const u8 *readchunk) +{ int x,y; unsigned char expected; @@ -1034,13 +1069,15 @@ if (likely(wc->initialized)) { if (y < wc->type) { wc->chans[y]->readchunk[x] = readchunk[y]; + wctdm_dtmfcheck_fakepolarity(wc, y, readchunk[y]); } } cmd_decipher(wc, readchunk, y); } if (wc->vpm100) { - for (y=NUM_CARDS;y < NUM_CARDS + NUM_EC; y++) + for (y = NUM_CARDS; y < NUM_CARDS + NUM_EC; y++) { cmd_decipher(wc, readchunk, y); + } } else if (wc->vpmadt032) { cmd_decipher_vpmadt032(wc, readchunk); } @@ -1359,6 +1396,8 @@ fxo->ringdebounce = ringdebounce / 16; } else if (--fxo->ringdebounce == 0) { fxo->wasringing = 0; + fxo->readcid = 0; + fxo->cidtimer = wc->intcount; if (debug) printk("FW NO RING on %d/%d!\n", wc->span.spanno, card + 1); dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK); @@ -1382,6 +1421,8 @@ if (fxo->ringdebounce <= 0) { if (fxo->wasringing) { fxo->wasringing = 0; + fxo->readcid = 0; + fxo->cidtimer = wc->intcount; dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK); if (debug) printk(KERN_DEBUG "NO RING on %d/%d!\n", wc->span.spanno, card + 1); @@ -3901,6 +3942,7 @@ module_param(fxsrxgain, int, 0600); module_param(ringdebounce, int, 0600); module_param(fwringdetect, int, 0600); +module_param(dtmf, int, 0600); module_param(latency, int, 0600); module_param(neonmwi_monitor, int, 0600); module_param(neonmwi_level, int, 0600);