summaryrefslogtreecommitdiff
path: root/zaptel.c
diff options
context:
space:
mode:
authormarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2005-05-02 20:15:07 +0000
committermarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2005-05-02 20:15:07 +0000
commitfa78643fc4a67112067ee2b090660c84886e9a04 (patch)
tree67d56dd508097931ed41b9a4092f3980a6f790ae /zaptel.c
parent86952759dcdb07b5cada67f976d4d8eb14b55ebf (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-xzaptel.c105
1 files changed, 84 insertions, 21 deletions
diff --git a/zaptel.c b/zaptel.c
index fae7891..8385f29 100755
--- a/zaptel.c
+++ b/zaptel.c
@@ -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,