--- base.c 2008-04-04 19:47:58.000000000 +0200 +++ base.c-mod 2008-05-03 10:59:42.000000000 +0200 @@ -196,6 +196,10 @@ #ifdef VPM_SUPPORT static int vpmsupport = 1; static int vpmdtmfsupport = 0; +static int cidbeforering = 0; +static int cidbuflen = 3000; /* in msec, default 3000 */ +static int cidtimeout = 6*1000; /* in msec, default 6000 */ + #define VPM_DEFAULT_DTMFTHRESHOLD 1250 static int dtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD; /* @@ -875,6 +879,55 @@ readchunk += (EFRAME_SIZE + EFRAME_GAP); } + + if(cidbeforering) + { + for(x=0; xmax_cards; x++) + { + if (wc->modtype[wc->chans[x].chanpos - 1] == MOD_TYPE_FXO) + if(wc->mods[wc->chans[x].chanpos - 1].fxo.offhook == 0) + { + /*unsigned int *p_readchunk, *p_cid_history; + + p_readchunk = (unsigned int*)wc->chans[x].readchunk; + p_cid_history = (unsigned int*)(wc->cid_history_buf[x] + wc->cid_history_ptr[x]);*/ + + if(wc->cid_state[x] == CID_STATE_IDLE) /* we need copy data to the cid voice buffer */ + { + memcpy(wc->cid_history_buf[x] + wc->cid_history_ptr[x], wc->chans[x].readchunk, ZT_CHUNKSIZE); + wc->cid_history_ptr[x] = (wc->cid_history_ptr[x] + ZT_CHUNKSIZE)%(cidbuflen * ZT_MAX_CHUNKSIZE); + } + else if (wc->cid_state[x] == CID_STATE_RING_ON) + wc->cid_history_clone_cnt[x] = cidbuflen; + else if (wc->cid_state[x] == CID_STATE_RING_OFF) + { + if(wc->cid_history_clone_cnt[x]) + { + memcpy(wc->chans[x].readchunk, wc->cid_history_buf[x] + wc->cid_history_ptr[x], ZT_MAX_CHUNKSIZE); + wc->cid_history_clone_cnt[x]--; + wc->cid_history_ptr[x] = (wc->cid_history_ptr[x] + ZT_MAX_CHUNKSIZE)%(cidbuflen * ZT_MAX_CHUNKSIZE); + } + else + { + wc->cid_state[x] = CID_STATE_WAIT_RING_FINISH; + wc->cid_history_clone_cnt[x] = cidtimeout; /* wait 6 sec, if no ring, return to idle */ + } + } + else if(wc->cid_state[x] == CID_STATE_WAIT_RING_FINISH) + { + if(wc->cid_history_clone_cnt[x] > 0) + wc->cid_history_clone_cnt[x]--; + else + { + wc->cid_state[x] = CID_STATE_IDLE; + wc->cid_history_ptr[x] = 0; + wc->cid_history_clone_cnt[x] = 0; + } + } + } + } + } + /* XXX We're wasting 8 taps. We should get closer :( */ if (likely(wc->initialized)) { for (x=0;xtype;x++) { @@ -1150,7 +1203,15 @@ fxo->wasringing = 1; if (debug) printk("RING on %d/%d!\n", wc->span.spanno, card + 1); - zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); + if(cidbeforering) + { + if(wc->cid_state[card] == CID_STATE_IDLE) + wc->cid_state[card] = CID_STATE_RING_ON; + else + zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); + } + else + zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); } fxo->lastrdtx = res; fxo->ringdebounce = 10; @@ -1159,7 +1220,22 @@ fxo->wasringing = 0; if (debug) printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); - zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); + if(cidbeforering) + { + if(wc->cid_state[card] == CID_STATE_RING_ON) + { + zt_qevent_lock(&wc->chans[card], ZT_EVENT_POLARITY); + wc->cid_state[card] = CID_STATE_RING_OFF; + } + else + { + if(wc->cid_state[card] == CID_STATE_WAIT_RING_FINISH) + wc->cid_history_clone_cnt[card] = cidtimeout; + zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); + } + } + else + zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); } } } else if (res && (fxo->battery == BATTERY_PRESENT)) { @@ -1173,7 +1249,15 @@ if (fxo->ringdebounce >= ZT_CHUNKSIZE * ringdebounce) { if (!fxo->wasringing) { fxo->wasringing = 1; - zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); + if(cidbeforering) + { + if(wc->cid_state[card] == CID_STATE_IDLE) + wc->cid_state[card] = CID_STATE_RING_ON; + else + zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); + } + else + zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); if (debug) printk("RING on %d/%d!\n", wc->span.spanno, card + 1); } @@ -1184,7 +1268,22 @@ if (fxo->ringdebounce <= 0) { if (fxo->wasringing) { fxo->wasringing = 0; - zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); + if(cidbeforering) + { + if(wc->cid_state[card] == CID_STATE_RING_ON) + { + zt_qevent_lock(&wc->chans[card], ZT_EVENT_POLARITY); + wc->cid_state[card] = CID_STATE_RING_OFF; + } + else + { + if(wc->cid_state[card] == CID_STATE_WAIT_RING_FINISH) + wc->cid_history_clone_cnt[card] = cidtimeout; + zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); + } + } + else + zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); if (debug) printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); } @@ -2684,6 +2783,13 @@ case ZT_TXSIG_OFFHOOK: wc->mods[chan->chanpos - 1].fxo.offhook = 1; wc->sethook[chan->chanpos - 1] = CMD_WR(5, 0x9); + if(cidbeforering) + { + wc->cid_state[chan->chanpos - 1] = CID_STATE_IDLE; + wc->cid_history_clone_cnt[chan->chanpos - 1] = 0; + wc->cid_history_ptr[chan->chanpos - 1] = 0; + //memset(wc->cid_history_buf[chan->chanpos - 1], ZT_LIN2X(0, chan), cidbuflen * ZT_MAX_CHUNKSIZE); + } /* wctdm_setreg(wc, chan->chanpos - 1, 5, 0x9); */ break; case ZT_TXSIG_ONHOOK: @@ -3760,6 +3866,7 @@ struct wctdm_desc *d = (struct wctdm_desc *)ent->driver_data; int i; int y; + int x; int ret; retry: @@ -3837,6 +3944,21 @@ wctdm_release(wc); goto retry; } + + if(cidbeforering) + { + int len = cidbuflen * ZT_MAX_CHUNKSIZE; + if(debug) + printk("cidbeforering support enabled, length is %d msec\n", cidbuflen); + for (x = 0; x < wc->max_cards/*MAX_NUM_CARDS*/; x++) + { + wc->cid_history_buf[x] = kmalloc(len, GFP_KERNEL); + wc->cid_history_ptr[x] = 0; + wc->cid_history_clone_cnt[x] = 0; + wc->cid_state[x] = CID_STATE_IDLE; + } + } + /* Final initialization */ wctdm_post_initialize(wc); @@ -3872,6 +3994,13 @@ break; ifaces[i] = NULL; spin_unlock(&ifacelock); + + if(cidbeforering) + { + int x; + for (x = 0; x < wc->max_cards/*MAX_NUM_CARDS*/; x++) + kfree(wc->cid_history_buf[x]); + } kfree(wc); } @@ -4012,6 +4141,9 @@ module_param(ringdebounce, int, 0600); module_param(fwringdetect, int, 0600); module_param(latency, int, 0600); +module_param(cidbeforering, int, 0600); +module_param(cidbuflen, int, 0600); +module_param(cidtimeout, int, 0600); #ifdef VPM_SUPPORT module_param(vpmsupport, int, 0600); module_param(vpmdtmfsupport, int, 0600); @@ -4041,6 +4173,9 @@ MODULE_PARM(fxsrxgain, "i"); MODULE_PARM(ringdebounce, "i"); MODULE_PARM(fwringdetect, "i"); +MODULE_PARM(cidbeforering, "i"); +MODULE_PARM(cidbuflen, "i"); +MODULE_PARM(cidtimeout, "i"); #ifdef VPM_SUPPORT MODULE_PARM(vpmsupport, "i"); MODULE_PARM(vpmdtmfsupport, "i");