From b5bf71ba2cf12f107a3c4568cd58a3232a3d110d Mon Sep 17 00:00:00 2001 From: kpfleming Date: Wed, 2 Jan 2008 17:55:09 +0000 Subject: bring back the echocan-params code that was removed in r3545, this time with a small change made to ensure backwards compatibility with existing applications at both the binary and source code level git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@3589 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- zaptel-base.c | 168 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 105 insertions(+), 63 deletions(-) (limited to 'zaptel-base.c') diff --git a/zaptel-base.c b/zaptel-base.c index 309b813..b44974d 100644 --- a/zaptel-base.c +++ b/zaptel-base.c @@ -419,18 +419,12 @@ static struct zt_zone *tone_zones[ZT_TONE_ZONE_MAX]; #include "sec.h" #elif defined(ECHO_CAN_STEVE2) #include "sec-2.h" -#elif defined(ECHO_CAN_MARK) -#include "mec.h" -#elif defined(ECHO_CAN_MARK2) -#include "mec2.h" #elif defined(ECHO_CAN_KB1) #include "kb1ec.h" #elif defined(ECHO_CAN_MG2) #include "mg2ec.h" #elif defined(ECHO_CAN_JP1) #include "jpah.h" -#else -#include "mec3.h" #endif static inline void rotate_sums(void) @@ -4308,6 +4302,95 @@ static void do_ppp_calls(unsigned long data) } #endif +#define MAX_ECHOCANPARAMS 8 + +static int ioctl_echocancel(struct zt_chan *chan, struct zt_echocanparams *ecp, void *data) +{ + struct echo_can_state *ec = NULL, *tec; + struct zt_echocanparam params[MAX_ECHOCANPARAMS]; + int ret; + unsigned long flags; + + if (ecp->param_count > MAX_ECHOCANPARAMS) + return -E2BIG; + + if (ecp->tap_length == 0) { + /* disable mode, don't need to inspect params */ + spin_lock_irqsave(&chan->lock, flags); + tec = chan->ec; + chan->echocancel = 0; + chan->ec = NULL; + chan->echostate = ECHO_STATE_IDLE; + chan->echolastupdate = 0; + chan->echotimer = 0; + spin_unlock_irqrestore(&chan->lock, flags); + if (chan->span && chan->span->echocan) + chan->span->echocan(chan, 0); + if (tec) + echo_can_free(tec); + + return 0; + } + + /* if parameters were supplied and this channel's span provides an echocan, + but not one that takes params, then we must punt here and return an error */ + if (ecp->param_count && chan->span && chan->span->echocan && + !chan->span->echocan_with_params) + return -EINVAL; + + /* enable mode, need the params */ + + if (copy_from_user(params, (struct zt_echocanparam *) data, sizeof(params[0]) * ecp->param_count)) + return -EFAULT; + + spin_lock_irqsave(&chan->lock, flags); + tec = chan->ec; + chan->ec = NULL; + spin_unlock_irqrestore(&chan->lock, flags); + + ret = -ENOTTY; + + /* attempt to use the span's echo canceler; fall back to built-in + if it fails (but not if an error occurs) */ + if (chan->span && chan->span->echocan_with_params) + ret = chan->span->echocan_with_params(chan, ecp, params); + + if (ret == -ENOTTY) { + switch (ecp->tap_length) { + case 32: + case 64: + case 128: + case 256: + case 512: + case 1024: + break; + default: + ecp->tap_length = deftaps; + } + + if ((ret = echo_can_create(ecp, params, &ec))) { + if (tec) + echo_can_free(tec); + return ret; + } + + spin_lock_irqsave(&chan->lock, flags); + chan->echocancel = ecp->tap_length; + 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); + + return ret; +} + static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit) { struct zt_chan *chan = chans[unit]; @@ -4316,7 +4399,8 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm int ret; int oldconf; void *rxgain=NULL; - struct echo_can_state *ec, *tec; + struct echo_can_state *ec; + struct zt_echocanparams ecp; if (!chan) return -ENOSYS; @@ -4478,65 +4562,23 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm fasthdlc_init(&chan->txhdlc); } break; + case ZT_ECHOCANCEL_PARAMS: + if (!(chan->flags & ZT_FLAG_AUDIO)) + return -EINVAL; + if (copy_from_user(&ecp, (struct zt_echocanparams *) data, sizeof(ecp))) + return -EFAULT; + data += sizeof(ecp); + if ((ret = ioctl_echocancel(chan, &ecp, (void *) data))) + return ret; + break; case ZT_ECHOCANCEL: if (!(chan->flags & ZT_FLAG_AUDIO)) return -EINVAL; - get_user(j, (int *)data); - if (j) { - spin_lock_irqsave(&chan->lock, flags); - /* If we had an old echo can, zap it now */ - tec = chan->ec; - chan->ec = NULL; - /* Attempt hardware native echo can */ - spin_unlock_irqrestore(&chan->lock, flags); - - 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) || - (j == 512) || - (j == 1024)) { - /* Okay */ - } else { - j = deftaps; - } - 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); - } else { - spin_lock_irqsave(&chan->lock, flags); - tec = chan->ec; - chan->echocancel = 0; - chan->ec = NULL; - chan->echostate = ECHO_STATE_IDLE; - chan->echolastupdate = 0; - chan->echotimer = 0; - spin_unlock_irqrestore(&chan->lock, flags); - /* Attempt hardware native echo can */ - if (chan->span && chan->span->echocan) - chan->span->echocan(chan, 0); - if (tec) - echo_can_free(tec); - } + get_user(j, (int *) data); + ecp.tap_length = j; + ecp.param_count = 0; + if ((ret = ioctl_echocancel(chan, &ecp, NULL))) + return ret; break; case ZT_ECHOTRAIN: get_user(j, (int *)data); /* get pre-training time from user */ -- cgit v1.2.3