--- wctdm.c 2008-03-27 22:17:46.000000000 +0100 +++ wctdm.c-mod 2008-05-03 12:20:59.000000000 +0200 @@ -193,6 +193,14 @@ BATTERY_LOST, }; +enum cid_hook_state { + CID_STATE_IDLE = 0, + CID_STATE_RING_ON, + CID_STATE_RING_OFF, + CID_STATE_WAIT_RING_FINISH +}; + + struct wctdm { struct pci_dev *dev; char *variety; @@ -254,8 +262,13 @@ volatile unsigned int *writechunk; /* Double-word aligned write memory */ volatile unsigned int *readchunk; /* Double-word aligned read memory */ struct zt_chan chans[NUM_CARDS]; -}; + char *cid_history_buf[NUM_CARDS]; /* used to support global cid */ + int cid_history_ptr[NUM_CARDS]; + int cid_history_clone_cnt[NUM_CARDS]; + enum cid_hook_state cid_state[NUM_CARDS]; + +}; struct wctdm_desc { char *name; @@ -293,6 +306,10 @@ static int fxstxgain = 0; static int fxsrxgain = 0; +static int cidbeforering = 0; +static int cidbuflen = 3000; /* in msec, default 3000 */ +static int cidtimeout = 6*1000; /* in msec, default 6000 */ + static int wctdm_init_proslic(struct wctdm *wc, int card, int fast , int manual, int sane); static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char ints) @@ -415,10 +432,60 @@ wc->chans[0].readchunk[x] = (readchunk[x]) & 0xff; #endif } + + if(cidbeforering) + { + for(x=0; xmodtype[wc->chans[x].chanpos - 1] == MOD_TYPE_FXO) + if(wc->mod[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; + } + } + } + } + } + #ifdef AUDIO_RINGCHECK for (x=0;xcards;x++) ring_check(wc, x); -#endif +#endif + /* XXX We're wasting 8 taps. We should get closer :( */ for (x = 0; x < NUM_CARDS; x++) { if (wc->cardflag & (1 << x)) @@ -780,7 +847,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; @@ -789,7 +864,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)) { @@ -803,7 +893,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); } @@ -814,7 +912,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); } @@ -1979,6 +2092,13 @@ case ZT_TXSIG_OFFHOOK: wc->mod[chan->chanpos - 1].fxo.offhook = 1; wctdm_setreg(wc, chan->chanpos - 1, 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); + } break; case ZT_TXSIG_ONHOOK: wc->mod[chan->chanpos - 1].fxo.offhook = 0; @@ -2268,6 +2388,7 @@ struct wctdm_desc *d = (struct wctdm_desc *)ent->driver_data; int x; int y; + int j; for (x=0;xcid_history_buf[j] = kmalloc(len, GFP_KERNEL); + wc->cid_history_ptr[j] = 0; + wc->cid_history_clone_cnt[j] = 0; + wc->cid_state[j] = CID_STATE_IDLE; + } + } + + wctdm_post_initialize(wc); /* Enable interrupts */ @@ -2387,6 +2523,13 @@ zt_unregister(&wc->span); if (wc->freeregion) release_region(wc->ioaddr, 0xff); + if(cidbeforering) + { + int x; + for (x = 0; x < NUM_CARDS; x++) + kfree(wc->cid_history_buf[x]); + } + kfree(wc); printk("Freed a Wildcard\n"); } @@ -2523,6 +2666,9 @@ module_param(fxorxgain, int, 0600); module_param(fxstxgain, int, 0600); module_param(fxsrxgain, int, 0600); +module_param(cidbeforering, int, 0600); +module_param(cidbuflen, int, 0600); +module_param(cidtimeout, int, 0600); #else MODULE_PARM(debug, "i"); MODULE_PARM(loopcurrent, "i"); @@ -2545,6 +2691,9 @@ MODULE_PARM(fxorxgain, "i"); MODULE_PARM(fxstxgain, "i"); MODULE_PARM(fxsrxgain, "i"); +MODULE_PARM(cidbeforering, "i"); +MODULE_PARM(cidbuflen, "i"); +MODULE_PARM(cidtimeout, "i"); #endif MODULE_DESCRIPTION("Wildcard TDM400P Zaptel Driver"); MODULE_AUTHOR("Mark Spencer ");