diff options
author | markster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2005-05-02 20:15:07 +0000 |
---|---|---|
committer | markster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2005-05-02 20:15:07 +0000 |
commit | fa78643fc4a67112067ee2b090660c84886e9a04 (patch) | |
tree | 67d56dd508097931ed41b9a4092f3980a6f790ae /zaptel.c | |
parent | 86952759dcdb07b5cada67f976d4d8eb14b55ebf (diff) |
Add support for TE410P/TE405P 2nd gen features (TSI, ECHOCAN, NATIVELAYOUT, IRQ, DTMFDETECT)
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@634 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'zaptel.c')
-rwxr-xr-x | zaptel.c | 105 |
1 files changed, 84 insertions, 21 deletions
@@ -140,6 +140,7 @@ EXPORT_SYMBOL(zt_hooksig); EXPORT_SYMBOL(zt_alarm_notify); EXPORT_SYMBOL(zt_set_dynamic_ioctl); EXPORT_SYMBOL(zt_ec_chunk); +EXPORT_SYMBOL(zt_ec_span); #ifdef CONFIG_PROC_FS static struct proc_dir_entry *proc_entries[ZT_MAX_SPANS]; @@ -958,6 +959,11 @@ static void close_channel(struct zt_chan *chan) memset(chan->conflast1, 0, sizeof(chan->conflast1)); memset(chan->conflast2, 0, sizeof(chan->conflast2)); + if (chan->span && chan->span->echocan) + chan->span->echocan(chan, 0); + if (chan->span && chan->span->dacs && oldconf) + chan->span->dacs(chan, NULL); + spin_unlock_irqrestore(&chan->lock, flags); if (rxgain) @@ -1563,8 +1569,11 @@ static void zt_chan_unreg(struct zt_chan *chan) (chans[x]->confmode == ZT_CONF_DIGITALMON))) { /* Take them out of conference with us */ /* release conference resource if any */ - if (chans[x]->confna) + if (chans[x]->confna) { zt_check_conf(chans[x]->confna); + if (chans[x]->span && chans[x]->span->dacs) + chans[x]->span->dacs(chans[x], NULL); + } chans[x]->confna = 0; chans[x]->_confn = 0; chans[x]->confmode = 0; @@ -2041,6 +2050,8 @@ static int initialize_channel(struct zt_chan *chan) if ((chan->sig & __ZT_SIG_DACS) != __ZT_SIG_DACS) { chan->confna = 0; chan->confmode = 0; + if (chan->span && chan->span->dacs) + chan->span->dacs(chan, NULL); } chan->_confn = 0; memset(chan->conflast, 0, sizeof(chan->conflast)); @@ -2078,6 +2089,8 @@ static int initialize_channel(struct zt_chan *chan) chan->ringcadence[0] = chan->starttime; chan->ringcadence[1] = ZT_RINGOFFTIME; } + if (chan->span && chan->span->echocan) + chan->span->echocan(chan, 0); spin_unlock_irqrestore(&chan->lock, flags); if (rxgain) @@ -3138,7 +3151,14 @@ static int zt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd /* Setup conference properly */ chans[ch.chan]->confmode = ZT_CONF_DIGITALMON; chans[ch.chan]->confna = ch.idlebits; - } + if (chans[ch.chan]->span && + chans[ch.chan]->span->dacs && + chans[ch.idlebits] && + chans[ch.chan]->span && + (chans[ch.chan]->span->dacs == chans[ch.idlebits]->span->dacs)) + chans[ch.chan]->span->dacs(chans[ch.chan], chans[ch.idlebits]); + } else if (chans[ch.chan]->span && chans[ch.chan]->span->dacs) + chans[ch.chan]->span->dacs(chans[ch.chan], NULL); chans[ch.chan]->master = newmaster; /* Note new slave if we are not our own master */ if (newmaster != chans[ch.chan]) { @@ -3658,6 +3678,14 @@ static int zt_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsign chans[i]->_confn = 0; /* Clear confn */ zt_check_conf(j); zt_check_conf(stack.conf.confno); + if (chans[i]->span && chans[i]->span->dacs) { + if ((stack.conf.confmode == ZT_CONF_DIGITALMON) && chans[stack.conf.confno]->span && + (chans[stack.conf.confno]->span->dacs == chans[i]->span->dacs)) { + chans[i]->span->dacs(chans[i], chans[stack.conf.confno]); + } else { + chans[i]->span->dacs(chans[i], NULL); + } + } /* k will be non-zero if in a real conf */ k = stack.conf.confmode & (ZT_CONF_CONF | ZT_CONF_CONFANN | ZT_CONF_CONFMON | ZT_CONF_CONFANNMON | ZT_CONF_REALANDPSEUDO); /* if we are going onto a conf */ @@ -3920,6 +3948,8 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm /* initialize conference variables */ chan->_confn = 0; chan->confna = 0; + if (chan->span && chan->span->dacs) + chan->span->dacs(chan, NULL); chan->confmode = 0; chan->confmute = 0; memset(chan->conflast, 0, sizeof(chan->conflast)); @@ -3937,6 +3967,9 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm chan->rxgain = defgain; chan->txgain = defgain; chan->gainalloc = 0; + /* Disable any native echo cancellation as well */ + if (chan->span && chan->span->echocan) + chan->span->echocan(chan, 0); spin_unlock_irqrestore(&chan->lock, flags); if (rxgain) @@ -3988,6 +4021,8 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm chan->gainalloc = 0; chan->flags &= ~ZT_FLAG_AUDIO; chan->flags |= (ZT_FLAG_PPP | ZT_FLAG_HDLC | ZT_FLAG_FCS); + if (chan->span && chan->span->echocan) + chan->span->echocan(chan, 0); if (tec) echo_can_free(tec); } else @@ -4034,27 +4069,38 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm return -EINVAL; get_user(j, (int *)data); if (j) { - if ((j == 32) || - (j == 64) || - (j == 128) || - (j == 256)) { - /* Okay */ - } else { - j = deftaps; - } - ec = echo_can_create(j, 0); - if (!ec) - return -ENOMEM; spin_lock_irqsave(&chan->lock, flags); /* If we had an old echo can, zap it now */ tec = chan->ec; - chan->echocancel = j; - chan->ec = ec; - chan->echostate = ECHO_STATE_IDLE; - chan->echolastupdate = 0; - chan->echotimer = 0; - echo_can_disable_detector_init(&chan->txecdis); - echo_can_disable_detector_init(&chan->rxecdis); + chan->ec = NULL; + /* Attempt hardware native echo can */ + if (chan->span && chan->span->echocan) + ret = chan->span->echocan(chan, j); + else + ret = -ENOTTY; + if (ret) { + /* Use built-in echo can */ + if ((j == 32) || + (j == 64) || + (j == 128) || + (j == 256)) { + /* Okay */ + } else { + j = deftaps; + } + spin_unlock_irqrestore(&chan->lock, flags); + ec = echo_can_create(j, 0); + if (!ec) + return -ENOMEM; + spin_lock_irqsave(&chan->lock, flags); + chan->echocancel = j; + chan->ec = ec; + chan->echostate = ECHO_STATE_IDLE; + chan->echolastupdate = 0; + chan->echotimer = 0; + echo_can_disable_detector_init(&chan->txecdis); + echo_can_disable_detector_init(&chan->rxecdis); + } spin_unlock_irqrestore(&chan->lock, flags); if (tec) echo_can_free(tec); @@ -4066,6 +4112,9 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm chan->echostate = ECHO_STATE_IDLE; chan->echolastupdate = 0; chan->echotimer = 0; + /* Attempt hardware native echo can */ + if (chan->span && chan->span->echocan) + chan->span->echocan(chan, 0); spin_unlock_irqrestore(&chan->lock, flags); if (tec) echo_can_free(tec); @@ -5228,7 +5277,7 @@ void zt_rbsbits(struct zt_chan *chan, int cursig) spin_unlock_irqrestore(&chan->lock, flags); } -void zt_ec_chunk(struct zt_chan *ss, unsigned char *rxchunk, const unsigned char *txchunk) +static inline void __zt_ec_chunk(struct zt_chan *ss, unsigned char *rxchunk, const unsigned char *txchunk) { short rxlin, txlin; int x; @@ -5279,6 +5328,20 @@ void zt_ec_chunk(struct zt_chan *ss, unsigned char *rxchunk, const unsigned char spin_unlock_irqrestore(&ss->lock, flags); } +void zt_ec_chunk(struct zt_chan *ss, unsigned char *rxchunk, const unsigned char *txchunk) +{ + __zt_ec_chunk(ss, rxchunk, txchunk); +} + +void zt_ec_span(struct zt_span *span) +{ + int x; + for (x = 0; x < span->channels; x++) { + if (span->chans[x].ec) + __zt_ec_chunk(&span->chans[x], span->chans[x].readchunk, span->chans[x].writechunk); + } +} + /* return 0 if nothing detected, 1 if lack of tone, 2 if presence of tone */ /* modifies buffer pointed to by 'amp' with notched-out values */ static inline int sf_detect (sf_detect_state_t *s, |