Index: include/dahdi/user.h =================================================================== --- include/dahdi/user.h (revision 6837) +++ include/dahdi/user.h (working copy) @@ -985,6 +985,16 @@ #define DAHDI_SETPOLARITY _IOW(DAHDI_CODE, 92, int) /* + * \brief Struct for passing hook data, polarity flag + * and caller-ID to zaptel driver. + */ +typedef struct zt_hook_data { + int x; /* Hook operation */ + int polarity; /* '1'=Polarity switch before caller-ID, '0' no switch. */ + char dtmfCidData[DAHDI_MAX_DTMF_BUF]; /* DTMF caller-ID string. */ +} ZT_HOOK_DATA; + +/* * Transcoder operations */ @@ -1027,6 +1037,23 @@ #define DAHDI_ECHOCANCEL_FAX_MODE _IOW(DAHDI_CODE, 102, int) +/* + * Set polarity -- implemented by individual driver. 0 = forward, 1 = reverse + When called from kernel space + */ +#define DAHDI_SETPOLARITY_KS _IOW(DAHDI_CODE, 103, int) + +/* +Control audio xmit 0 = Off, 1 = On + */ +#define DAHDI_AUDIO_XMIT_CTL _IOW(DAHDI_CODE, 104, int) + +/* +Control audio xmit 0 = Off, 1 = On +Called from kernel space + */ +#define DAHDI_AUDIO_XMIT_CTL_KS _IOW(DAHDI_CODE, 105, int) + struct torisa_debug { unsigned int txerrors; unsigned int irqcount; Index: include/dahdi/kernel.h =================================================================== --- include/dahdi/kernel.h (revision 6837) +++ include/dahdi/kernel.h (working copy) @@ -130,6 +130,7 @@ int lastdetect; }; + struct dahdi_tone_state { int v1_1; int v2_1; Index: drivers/dahdi/wctdm.c =================================================================== --- drivers/dahdi/wctdm.c (revision 6837) +++ drivers/dahdi/wctdm.c (working copy) @@ -1850,7 +1850,9 @@ struct dahdi_hwgain hwgain; struct wctdm *wc = chan->pvt; int x; - switch (cmd) { + int ks=0; + + switch (cmd) { case DAHDI_ONHOOKTRANSFER: if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; @@ -1864,16 +1866,27 @@ wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook); } break; + case DAHDI_SETPOLARITY_KS: + ks=1; case DAHDI_SETPOLARITY: - if (get_user(x, (__user int *) data)) - return -EFAULT; - if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) + if (ks == 0) { + if (get_user(x, (__user int *) data)) + return -EFAULT; + } + else { + + x=*(int *)data; + } + if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS){ + printk("ZT_SETPOLARITY: EINVAL(1)\n"); return -EINVAL; + } /* Can't change polarity while ringing or when open */ if ((wc->mod[chan->chanpos -1 ].fxs.lasttxhook == 0x04) || - (wc->mod[chan->chanpos -1 ].fxs.lasttxhook == 0x00)) + (wc->mod[chan->chanpos -1 ].fxs.lasttxhook == 0x00)){ + printk("ZT_SETPOLARITY: EINVAL(2)\n"); return -EINVAL; - + } wc->mod[chan->chanpos - 1].fxs.reversepolarity = x; if ( POLARITY_XOR(chan->chanpos - 1) ) wc->mod[chan->chanpos - 1].fxs.lasttxhook |= 0x04; @@ -1881,6 +1894,23 @@ wc->mod[chan->chanpos - 1].fxs.lasttxhook &= ~0x04; wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook); break; + case DAHDI_AUDIO_XMIT_CTL_KS: + ks=1; + case DAHDI_AUDIO_XMIT_CTL: + if (ks == 0) { + if (get_user(x, (int *)data)) { + printk("ZT_AUDIO_XMIT_CTL: EFAULT x=%d\n", x); + return -EFAULT; + } + } else { + x=*(int *)data; + } + regop.indirect=0; + regop.reg=64; + regop.val=(x == 0 ? 5 : 6) & 0xff; + wctdm_setreg(wc, chan->chanpos - 1, regop.reg, regop.val); + break; + case DAHDI_VMWI_CONFIG: if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; Index: drivers/dahdi/dahdi-base.c =================================================================== --- drivers/dahdi/dahdi-base.c (revision 6837) +++ drivers/dahdi/dahdi-base.c (working copy) @@ -214,6 +214,9 @@ DAHDI_TXSTATE_PULSEBREAK, DAHDI_TXSTATE_PULSEMAKE, DAHDI_TXSTATE_PULSEAFTER, + DAHDI_TXSTATE_CID_1, + DAHDI_TXSTATE_CID_2, + DAHDI_TXSTATE_CID_FINAL }; typedef short sumtype[DAHDI_MAX_CHUNKSIZE]; @@ -3049,6 +3052,7 @@ { unsigned int tone_index; + if (!chan->curzone) { static int __warnonce = 1; if (__warnonce) { @@ -3090,11 +3094,24 @@ tone_index = DAHDI_TONE_DTMF_p; break; case 'A': + case 'a': + tone_index = DAHDI_TONE_DTMF_A; + break; case 'B': + case 'b': + tone_index = DAHDI_TONE_DTMF_B; + break; case 'C': - case 'D': - tone_index = DAHDI_TONE_DTMF_A + (digit - 'A'); + case 'c': + tone_index = DAHDI_TONE_DTMF_C; + break; + case 'D': + case 'd': + tone_index = DAHDI_TONE_DTMF_D; + break; case 'W': + case 'w': return &tone_pause; default: return NULL; @@ -3231,6 +3248,8 @@ return; } } else { + case 'w': + case 'W': chan->curtone = dahdi_mf_tone(chan, c, chan->digitmode); chan->tonep = 0; if (chan->curtone) { @@ -3243,7 +3262,13 @@ /* Notify userspace process if there is nothing left */ chan->dialing = 0; - __qevent(chan, DAHDI_EVENT_DIALCOMPLETE); + /* Check so that we don't do a caller-ID event. */ + if (chan->txstate != DAHDI_TXSTATE_CID_1 + && chan->txstate != DAHDI_TXSTATE_CID_2 + && chan->txstate != DAHDI_TXSTATE_CID_FINAL) + { + __qevent(chan, DAHDI_EVENT_DIALCOMPLETE); + } } static int dahdi_release(struct inode *inode, struct file *file) @@ -5016,8 +5041,9 @@ int ret; int oldconf; void *rxgain=NULL; + ZT_HOOK_DATA hook_data; - WARN_ON(!chan->master); + WARN_ON(!chan->master); if (!chan) return -ENOSYS; @@ -5267,7 +5293,10 @@ spin_unlock_irqrestore(&chan->lock, flags); break; case DAHDI_HOOK: - get_user(j,(int *)data); +/* get_user(j,(int *)data);*/ + if (copy_from_user(&hook_data, (ZT_HOOK_DATA *) data, sizeof(ZT_HOOK_DATA))) + return -EFAULT; + j=hook_data.x; if (chan->flags & DAHDI_FLAG_CLEAR) return -EINVAL; if (chan->sig == DAHDI_SIG_CAS) @@ -5314,8 +5343,22 @@ if (chan->sig & __DAHDI_SIG_FXO) { ret = 0; chan->cadencepos = 0; + /* If we shall reverse the polarity before CID do that now. */ + if (hook_data.polarity == 1) { + ret=1; + chan->span->ioctl(chan, DAHDI_SETPOLARITY_KS, (unsigned long)&ret); + } + + /* If we have CallerID string to send as DTMF. */ + if (strlen(hook_data.dtmfCidData) > 0) { + strcpy(chan->txdialbuf, hook_data.dtmfCidData); + ret=200; + dahdi_rbs_sethook(chan, DAHDI_TXSIG_ONHOOK, DAHDI_TXSTATE_CID_1, ret); + } else { + chan->cadencepos = 0; ret = chan->ringcadence[0]; dahdi_rbs_sethook(chan, DAHDI_TXSIG_START, DAHDI_TXSTATE_RINGON, ret); + } } else dahdi_rbs_sethook(chan, DAHDI_TXSIG_START, DAHDI_TXSTATE_START, chan->starttime); spin_unlock_irqrestore(&chan->lock, flags); @@ -6200,11 +6243,55 @@ static inline void __rbs_otimer_expire(struct dahdi_chan *chan) { int len = 0; - /* Called with chan->lock held */ + int x; + /* Called with chan->lock held */ chan->otimer = 0; /* Move to the next timer state */ switch(chan->txstate) { + case DAHDI_TXSTATE_CID_1: /* Send DTMF tones. */ + chan->dialing = 1; + __do_dtmf(chan); + x=1; + chan->span->ioctl(chan, DAHDI_AUDIO_XMIT_CTL_KS, (unsigned long)&x); + len=200; + dahdi_rbs_sethook(chan, DAHDI_TXSIG_ONHOOK, DAHDI_TXSTATE_CID_2, len); + break; + + case DAHDI_TXSTATE_CID_2: + if (chan->dialing == 1) { + /* Still sending - wait some more. + TODO: Infinite loop check? */ + + /* We seem to need to do the ZT_AUDIO_XMIT_CTL_KS every time + in order to be able to transmit the DTMF tones. */ + x=1; + chan->span->ioctl(chan, DAHDI_AUDIO_XMIT_CTL_KS, (unsigned long)&x); + + len=200; + dahdi_rbs_sethook(chan, DAHDI_TXSIG_ONHOOK, DAHDI_TXSTATE_CID_2, len); + } else { + /* wait before switch back of polarity. */ + len=300; + dahdi_rbs_sethook(chan, DAHDI_TXSIG_ONHOOK, DAHDI_TXSTATE_CID_FINAL, len); + } + break; + + case DAHDI_TXSTATE_CID_FINAL: + /* Switch back polarity and wait another 100ms before sending + first ring. */ + x=0; + chan->span->ioctl(chan, DAHDI_AUDIO_XMIT_CTL_KS, (unsigned long)&x); + /* We don't really need to check polarity flag here, + * since resetting the polarity should be harmless here. + */ + x=0; + chan->span->ioctl(chan, DAHDI_SETPOLARITY_KS, (unsigned long)&x); + chan->cadencepos = 0; + len = chan->ringcadence[0]; + dahdi_rbs_sethook(chan, DAHDI_TXSIG_START, DAHDI_TXSTATE_RINGON, len); + break; + case DAHDI_TXSTATE_RINGOFF: /* Turn on the ringer now that the silent time has passed */ ++chan->cadencepos; @@ -6233,7 +6320,7 @@ len = chan->curzone->ringcadence[chan->cadencepos]; } - dahdi_rbs_sethook(chan, DAHDI_TXSIG_OFFHOOK, DAHDI_TXSTATE_RINGOFF, len); + dahdi_rbs_sethook(chan, DAHDI_TXSIG_ONHOOK, DAHDI_TXSTATE_RINGOFF, len); __qevent(chan, DAHDI_EVENT_RINGEROFF); break;