--- a/drivers/dahdi/dahdi_echocan_oslec.c +++ b/drivers/dahdi/dahdi_echocan_oslec.c @@ -37,6 +37,161 @@ #define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args) +#define OSLEC_ECHOCAN_USE_ZAPTAP +#ifdef OSLEC_ECHOCAN_USE_ZAPTAP +#include +#include + +#define SAMPLE_BUF_SZ 1000 +#define SAMPLE_IDLE 0 +#define SAMPLE_PING 1 +#define SAMPLE_PONG 2 + +static DECLARE_WAIT_QUEUE_HEAD(sample_wait); +static int sample_state; +static int samples; +static short *psample; +static short ping[3*SAMPLE_BUF_SZ]; +static short pong[3*SAMPLE_BUF_SZ]; +static int sample_ch = 1; +static int sample_impulse; +static int tmp1, tmp2; + +static inline void sample_echo_before(int channo, short rxlin, short txlin) +{ + /* Sample echo canceller signals + * Notes: + * 1. Samples are multiplexed in buffer: + * tx sample + * rx sample + * ec sample + * 2. We needs to sample rx here before echo can as it is + * overwritten. + */ + tmp1++; + tmp2 = channo; + if ((sample_state != SAMPLE_IDLE) && (channo == sample_ch)) { + *psample++ = txlin; + *psample++ = rxlin; + } +} + +static inline void sample_echo_after(int channo, short rxlin) +{ + if ((sample_state == SAMPLE_IDLE) || (channo != sample_ch)) + return; + + *psample++ = rxlin; + + /* sample collection ping-pong buffer logic */ + + samples++; + if (samples >= SAMPLE_BUF_SZ) { + /* time to swap buffers */ + samples = 0; + + if (sample_state == SAMPLE_PING) { + sample_state = SAMPLE_PONG; + psample = pong; + } else { + sample_state = SAMPLE_PING; + psample = ping; + } + wake_up_interruptible(&sample_wait); + } +} + +static int sample_open(struct inode *inode, struct file *file) +{ + module_printk(KERN_DEBUG, "sample_open:\n"); + tmp1 = tmp2 = -1; + + psample = ping; + samples = 0; + sample_state = SAMPLE_PING; + + return 0; +} + +static int sample_release(struct inode *inode, struct file *file) +{ + module_printk(KERN_DEBUG, "sample_release: tmp1 = %d tmp2 = %d\n", + tmp1, tmp2); + + sample_state = SAMPLE_IDLE; + sample_impulse = 0; + samples = 0; + + return 0; +} + +static ssize_t sample_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + int err, len; + short *pread; + + /* Wait for next buffer to be prepared by ISR, we read + alternate buffer just after transition. + */ + interruptible_sleep_on(&sample_wait); + + if (sample_state == SAMPLE_PING) + pread = pong; + else + pread = ping; + + len = 3*sizeof(short)*SAMPLE_BUF_SZ; + err = copy_to_user(buf, pread, len); + + if (err != 0) + return -EFAULT; + + return len; +} + +/* ioctls for sample */ +#define SAMPLE_SET_CHANNEL 0 +#define SAMPLE_TX_IMPULSE 1 + +static int sample_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int retval = 0; + + switch (cmd) { + case SAMPLE_SET_CHANNEL: + if (copy_from_user(&sample_ch, (__user int *)arg, + sizeof(int))) + return -EFAULT; + module_printk(KERN_INFO, "%s: sample_ch = %d\n", + __func__, sample_ch); + break; + case SAMPLE_TX_IMPULSE: + sample_impulse = 1; + module_printk(KERN_INFO, "%s: under impulse power\n", + __func__); + break; + default: + retval = -EINVAL; + } + + return retval; +} + +static const struct file_operations sample_fops = { + .owner = THIS_MODULE, + .read = sample_read, + .ioctl = sample_ioctl, + .open = sample_open, + .release = sample_release +}; + +#define SAMPLE_NAME "sample" +#define SAMPLE_MAJOR 33 + +#endif /*ifdef OSLEC_ECHOCAN_USE_ZAPTAP*/ + static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); @@ -59,6 +214,9 @@ static const struct dahdi_echocan_ops my_ops = { struct ec_pvt { struct oslec_state *oslec; struct dahdi_echocan_state dahdi; +#ifdef OSLEC_ECHOCAN_USE_ZAPTAP + int channo; +#endif }; #define dahdi_to_pvt(a) container_of(a, struct ec_pvt, dahdi) @@ -79,8 +237,10 @@ static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const for (SampleNum = 0; SampleNum < size; SampleNum++, iref++) { short iCleanSample; + sample_echo_before(pvt->channo, *iref, *isig); iCleanSample = oslec_update(pvt->oslec, *iref, *isig); *isig++ = iCleanSample; + sample_echo_after(pvt->channo, iCleanSample); } } @@ -99,6 +259,9 @@ static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams * return -ENOMEM; pvt->dahdi.ops = &my_ops; +#ifdef OSLEC_ECHOCAN_USE_ZAPTAP + pvt->channo = chan->channo; +#endif pvt->oslec = oslec_create(ecp->tap_length, ECHO_CAN_USE_ADAPTION | ECHO_CAN_USE_NLP | ECHO_CAN_USE_CLIP | ECHO_CAN_USE_TX_HPF | ECHO_CAN_USE_RX_HPF); @@ -119,12 +282,29 @@ static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val) static int __init mod_init(void) { +#ifdef OSLEC_ECHOCAN_USE_ZAPTAP + int res; +#endif if (dahdi_register_echocan_factory(&my_factory)) { module_printk(KERN_ERR, "could not register with DAHDI core\n"); return -EPERM; } +#ifdef OSLEC_ECHOCAN_USE_ZAPTAP + sample_state = SAMPLE_IDLE; + sample_impulse = 0; + res = register_chrdev(SAMPLE_MAJOR, SAMPLE_NAME, &sample_fops); + if (res) { + module_printk(KERN_ERR, "Unable to register 'sample' char driver on %d\n", + SAMPLE_MAJOR); + return res; + } + module_printk(KERN_INFO, + "Registered 'sample' char driver on major %d\n", + SAMPLE_MAJOR); +#endif /*defined OSLEC_ECHOCAN_USE_ZAPTAP*/ + module_printk(KERN_INFO, "Registered echo canceler '%s'\n", my_factory.name); return 0; @@ -132,6 +312,9 @@ static int __init mod_init(void) static void __exit mod_exit(void) { +#ifdef OSLEC_ECHOCAN_USE_ZAPTAP + unregister_chrdev(SAMPLE_MAJOR, SAMPLE_NAME); +#endif dahdi_unregister_echocan_factory(&my_factory); } -- 1.5.6.5