263 lines
8.2 KiB
Diff
263 lines
8.2 KiB
Diff
--- zaptel.c.orig 2005-12-29 11:24:30.000000000 -0500
|
|
+++ zaptel.c 2006-02-01 17:19:35.000000000 -0500
|
|
@@ -299,6 +299,7 @@
|
|
#include "digits.h"
|
|
|
|
static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit);
|
|
+static void zt_ec_chunk_spike_store(struct zt_chan *ss, unsigned char *rxchunk);
|
|
|
|
#if defined(CONFIG_ZAPTEL_MMX) || defined(ECHO_CAN_FP)
|
|
/* XXX kernel_fpu_begin() is NOT exported properly (in 2.4), so we have to make
|
|
@@ -1704,6 +1705,7 @@
|
|
unsigned long flags;
|
|
struct zt_chan *chan = chans[unit];
|
|
int res, amnt, oldbuf, rv,x;
|
|
+
|
|
/* Make sure count never exceeds 65k, and make sure it's unsigned */
|
|
count &= 0xffff;
|
|
if (!chan)
|
|
@@ -4147,11 +4149,20 @@
|
|
tec = chan->ec;
|
|
chan->ec = NULL;
|
|
/* Attempt hardware native echo can */
|
|
- if (chan->span && chan->span->echocan)
|
|
+ if (chan->span && chan->span->echocan){
|
|
ret = chan->span->echocan(chan, j);
|
|
- else
|
|
+ }else{
|
|
ret = -ENOTTY;
|
|
- if (ret) {
|
|
+ }
|
|
+
|
|
+ if(!ret){
|
|
+ chan->echo_spike_struct.is_hw_ec_used = 1;
|
|
+ }else{
|
|
+ chan->echo_spike_struct.is_hw_ec_used = 0;
|
|
+ }
|
|
+
|
|
+ /* the Echo Spike code needs chan->ec to be initialized!! */
|
|
+ if (ret || 1) {
|
|
/* Use built-in echo can */
|
|
if ((j == 32) ||
|
|
(j == 64) ||
|
|
@@ -4171,6 +4182,8 @@
|
|
chan->echostate = ECHO_STATE_IDLE;
|
|
chan->echolastupdate = 0;
|
|
chan->echotimer = 0;
|
|
+ chan->echo_spike_struct.state_bits = ECHO_INITIAL_STATE;
|
|
+ chan->echo_spike_struct.sample_len_counter = 0;
|
|
echo_can_disable_detector_init(&chan->txecdis);
|
|
echo_can_disable_detector_init(&chan->rxecdis);
|
|
}
|
|
@@ -4328,6 +4341,83 @@
|
|
return -EINVAL;
|
|
break;
|
|
#endif
|
|
+
|
|
+ case GET_ECHO_SPIKE_SAMPLE:
|
|
+ if(chan->echo_spike_struct.sample_buffer){
|
|
+ unsigned char *tmp_ptr = (unsigned char*)data;
|
|
+
|
|
+ chan->echo_spike_struct.return_code = ECHO_OK;
|
|
+ chan->echo_spike_struct.spanno = chan->span->spanno;
|
|
+ chan->echo_spike_struct.echocancel = chan->echocancel;
|
|
+
|
|
+ if(chan->xlaw == __zt_mulaw){
|
|
+ chan->echo_spike_struct.law = ZT_LAW_MULAW;
|
|
+ }else{
|
|
+ chan->echo_spike_struct.law = ZT_LAW_ALAW;
|
|
+ }
|
|
+
|
|
+ /* first copy the 'echo_spike_struct_t' structure */
|
|
+ copy_to_user(tmp_ptr, &chan->echo_spike_struct, sizeof(echo_spike_struct_t));
|
|
+
|
|
+ /* second copy the data AFTER the 'echo_spike_struct_t' structure */
|
|
+ copy_to_user (&tmp_ptr[sizeof(echo_spike_struct_t)],
|
|
+ chan->echo_spike_struct.sample_buffer,
|
|
+ ECHO_SPIKE_SAMPLE_LEN);
|
|
+
|
|
+ /* free the sample buffer */
|
|
+ kfree(chan->echo_spike_struct.sample_buffer);
|
|
+ /* very important to set to NULL after deallocation!! */
|
|
+ chan->echo_spike_struct.sample_buffer = NULL;
|
|
+
|
|
+ chan->echo_spike_struct.state_bits = ECHO_INITIAL_STATE;
|
|
+ chan->echo_spike_struct.sample_len_counter = 0;
|
|
+ }else{
|
|
+ unsigned char *tmp_ptr = (unsigned char*)data;
|
|
+
|
|
+ chan->echo_spike_struct.return_code = ECHO_NO_ACTIVE_CALL_OR_EC_OFF;
|
|
+ /* copy the 'echo_spike_struct_t' structure */
|
|
+ copy_to_user(tmp_ptr, &chan->echo_spike_struct, sizeof(echo_spike_struct_t));
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case SEND_ECHO_SPIKE:
|
|
+ copy_from_user(&chan->echo_spike_struct, (void*)data, sizeof(echo_spike_struct_t));
|
|
+
|
|
+ /* allocate EchoTest buffer. OUSIDE of spin_lock. */
|
|
+ chan->echo_spike_struct.sample_buffer = kmalloc(ECHO_SPIKE_SAMPLE_LEN, GFP_KERNEL);
|
|
+ if (chan->echo_spike_struct.sample_buffer == NULL) {
|
|
+ printk(KERN_INFO "channo: %d: Failed to allocate %d bytes for EchoTest storage!!!\n",
|
|
+ chan->channo, ECHO_SPIKE_SAMPLE_LEN);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ spin_lock_irqsave(&chan->lock, flags);
|
|
+ /* send echo spike */
|
|
+ if (chan->ec) {
|
|
+ chan->echo_spike_struct.return_code = ECHO_OK;
|
|
+
|
|
+ chan->echo_spike_struct.state_bits = ECHO_INITIAL_STATE;
|
|
+ chan->echo_spike_struct.sample_len_counter = 0;
|
|
+ /* these two lines will make zaptel to send the spike: */
|
|
+ chan->echostate = ECHO_STATE_PRETRAINING;
|
|
+ chan->echotimer = 2048; /*Number of silence bytes to transmit before the spike.
|
|
+ It makes the line clean from noise, so spike is easy
|
|
+ to detect on return.*/
|
|
+ }else{
|
|
+ printk(KERN_INFO "channo: %d: SEND_ECHO_SPIKE: chan->ec is NULL!!\n",
|
|
+ chan->channo);
|
|
+
|
|
+ chan->echo_spike_struct.return_code = ECHO_NO_ACTIVE_CALL_OR_EC_OFF;
|
|
+ }
|
|
+ /* Must unlock here, BEFORE copy_to_user() call.
|
|
+ Or will get warnings from the kernel. */
|
|
+ spin_unlock_irqrestore(&chan->lock, flags);
|
|
+
|
|
+ /* copy the 'echo_spike_struct_t' structure back to user. so return_code
|
|
+ can be accessed. */
|
|
+ copy_to_user((void*)data, &chan->echo_spike_struct, sizeof(echo_spike_struct_t));
|
|
+ break;
|
|
+
|
|
default:
|
|
return zt_chanandpseudo_ioctl(inode, file, cmd, data, unit);
|
|
}
|
|
@@ -4343,6 +4433,7 @@
|
|
if (chan) {
|
|
printk("Huh? Prechan already has private data??\n");
|
|
}
|
|
+
|
|
switch(cmd) {
|
|
case ZT_SPECIFY:
|
|
get_user(channo,(int *)data);
|
|
@@ -4382,10 +4473,26 @@
|
|
}
|
|
if (unit == 254) {
|
|
chan = file->private_data;
|
|
- if (chan)
|
|
+ if (chan){
|
|
return zt_chan_ioctl(inode, file, cmd, data, chan->channo);
|
|
- else
|
|
- return zt_prechan_ioctl(inode, file, cmd, data, unit);
|
|
+ }else{
|
|
+ int channo;
|
|
+
|
|
+ switch(cmd)
|
|
+ {
|
|
+ case GET_ECHO_SPIKE_SAMPLE:
|
|
+ case SEND_ECHO_SPIKE:
|
|
+ get_user(channo,(int *)data);
|
|
+
|
|
+ if (channo < 1 || channo > ZT_MAX_CHANNELS){
|
|
+ printk(KERN_INFO "Invalid channel %d!!\n", channo);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ return zt_chan_ioctl(inode, file, cmd, data, channo);
|
|
+ default:
|
|
+ return zt_prechan_ioctl(inode, file, cmd, data, unit);
|
|
+ }
|
|
+ }
|
|
}
|
|
if (unit == 255) {
|
|
chan = file->private_data;
|
|
@@ -5416,7 +5523,13 @@
|
|
short rxlin, txlin;
|
|
int x;
|
|
unsigned long flags;
|
|
+
|
|
spin_lock_irqsave(&ss->lock, flags);
|
|
+
|
|
+ if(ss->echo_spike_struct.collect_sample_before_ec == 1){
|
|
+ zt_ec_chunk_spike_store(ss, rxchunk);
|
|
+ }
|
|
+
|
|
/* Perform echo cancellation on a chunk if necessary */
|
|
if (ss->ec) {
|
|
#if defined(CONFIG_ZAPTEL_MMX) || defined(ECHO_CAN_FP)
|
|
@@ -5436,8 +5549,13 @@
|
|
if ((ss->echostate == ECHO_STATE_AWAITINGECHO) && (txlin > 8000)) {
|
|
ss->echolastupdate = 0;
|
|
ss->echostate = ECHO_STATE_TRAINING;
|
|
+
|
|
+ if(ss->echo_spike_struct.state_bits == ECHO_INITIAL_STATE){
|
|
+ ss->echo_spike_struct.state_bits = ECHO_BUSY_COLLECTING_SAMPLE;
|
|
+ ss->echo_spike_struct.sample_len_counter = 0;
|
|
+ }
|
|
}
|
|
- if (ss->echostate == ECHO_STATE_TRAINING) {
|
|
+ if (ss->echostate == ECHO_STATE_TRAINING){
|
|
if (echo_can_traintap(ss->ec, ss->echolastupdate++, rxlin)) {
|
|
#if 0
|
|
printk("Finished training (%d taps trained)!\n", ss->echolastupdate);
|
|
@@ -5449,16 +5567,20 @@
|
|
rxchunk[x] = ZT_LIN2X((int)rxlin, ss);
|
|
}
|
|
} else {
|
|
- for (x=0;x<ZT_CHUNKSIZE;x++) {
|
|
- rxlin = ZT_XLAW(rxchunk[x], ss);
|
|
- rxlin = echo_can_update(ss->ec, ZT_XLAW(txchunk[x], ss), rxlin);
|
|
- rxchunk[x] = ZT_LIN2X((int)rxlin, ss);
|
|
+ if(ss->echo_spike_struct.is_hw_ec_used == 0){
|
|
+ for (x=0;x<ZT_CHUNKSIZE;x++) {
|
|
+ rxlin = ZT_XLAW(rxchunk[x], ss);
|
|
+ rxlin = echo_can_update(ss->ec, ZT_XLAW(txchunk[x], ss), rxlin);
|
|
+ rxchunk[x] = ZT_LIN2X((int)rxlin, ss);
|
|
+ }
|
|
}
|
|
}
|
|
+
|
|
#if defined(CONFIG_ZAPTEL_MMX) || defined(ECHO_CAN_FP)
|
|
kernel_fpu_end();
|
|
#endif
|
|
}
|
|
+
|
|
spin_unlock_irqrestore(&ss->lock, flags);
|
|
}
|
|
|
|
@@ -6591,3 +6713,34 @@
|
|
|
|
module_init(zt_init);
|
|
module_exit(zt_cleanup);
|
|
+
|
|
+static void zt_ec_chunk_spike_store(struct zt_chan *ss, unsigned char *rxchunk)
|
|
+{
|
|
+ int x;
|
|
+
|
|
+ if(ss->echo_spike_struct.state_bits != ECHO_BUSY_COLLECTING_SAMPLE ||
|
|
+ ss->echo_spike_struct.sample_buffer == NULL){
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* check input values */
|
|
+ if(ss->echo_spike_struct.sample_len_counter >= ECHO_SPIKE_SAMPLE_LEN){
|
|
+ printk(KERN_INFO "chan: %d: Invalid sample_len_counter! (%d)\n",
|
|
+ ss->channo, ss->echo_spike_struct.sample_len_counter);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if(ss->echo_spike_struct.state_bits == ECHO_BUSY_COLLECTING_SAMPLE){
|
|
+ for (x = 0; x < ZT_CHUNKSIZE; x++) {
|
|
+ ss->echo_spike_struct.sample_buffer[ss->echo_spike_struct.sample_len_counter] =
|
|
+ rxchunk[x];
|
|
+ ss->echo_spike_struct.sample_len_counter++;
|
|
+ if(ss->echo_spike_struct.sample_len_counter >= ECHO_SPIKE_SAMPLE_LEN){
|
|
+ /* finished collecting the sample */
|
|
+ ss->echo_spike_struct.state_bits = ECHO_FINISHED_COLLECTING_SAMPLE;
|
|
+ break;
|
|
+ }/*if()*/
|
|
+ }/*for()*/
|
|
+ }/*if()*/
|
|
+}
|
|
+
|