misdn.patch
来自「一个非常美妙的proxy。功能强大。基于sip的协议。如果还要的话」· PATCH 代码 · 共 2,345 行 · 第 1/5 页
PATCH
2,345 行
+ + for (i = 0 ; i < 256 ; i++) {+ unsigned char sample = 0 ;+ for (k = 0; k<8; k++) {+ if ( i & 1 << k ) sample |= 0x80 >> k;+ }+ flip_table[i] = sample;+ }+}++static unsigned char * flip_buf_bits ( unsigned char * buf , int len)+{+ int i;+ char * start = buf;+ + for (i = 0 ; i < len; i++) {+ buf[i] = flip_table[buf[i]];+ }+ + return start;+}++++void+dsp_cancel_tx(dsp_t *dsp, u8 *data, int len)+{+ if (!dsp ) return ;+ if (!data) return;+ + if (dsp->txbuflen + len < ECHOCAN_BUFLEN) {+ memcpy(&dsp->txbuf[dsp->txbuflen],data,len);+ dsp->txbuflen+=len;+ } else {+ printk("ECHOCAN: TXBUF Overflow len:%d newlen:%d\n",dsp->txbuflen,len);+ dsp->txbuflen=0;+ }+ +}++void+dsp_cancel_rx(dsp_t *dsp, u8 *data, int len)+{+ if (!dsp ) return ;+ if (!data) return;+ + if (len <= dsp->txbuflen) {+ char tmp[ECHOCAN_BUFLEN];+ + int delta=dsp->txbuflen-len;+ + memcpy(tmp,&dsp->txbuf[len],delta);+ + flip_buf_bits(data,len);+ flip_buf_bits(dsp->txbuf,len);+ bchdev_echocancel_chunk(dsp, data, dsp->txbuf, len);+ flip_buf_bits(data,len);+ + memcpy(dsp->txbuf,tmp,delta);+ dsp->txbuflen=delta;+ //dsp->txbuflen=0;+ + //bchdev_echocancel_chunk(dsp, dsp->txbuf, data, len);+ } else {+ printk("ECHOCAN: TXBUF Underrun len:%d newlen:%d\n",dsp->txbuflen,len);+ }+ +}++int+dsp_cancel_init(dsp_t *dsp, int deftaps, int training, int delay)+{+ + if (!dsp) return -1;+ + printk("DSP_CANCEL_INIT called\n");+ + if (delay < 0)+ {+ printk("Disabling EC\n");+ dsp->cancel_enable = 0;+ + dsp->txbuflen=0;+ + bchdev_echocancel_deactivate(dsp);+ + return(0);+ }+ + dsp->txbuflen=0;+ dsp->rxbuflen=0;+ + + bchdev_echocancel_activate(dsp,deftaps, training);+ + printk("Enabling EC\n");+ dsp->cancel_enable = 1;+ return(0);+}++++++/*****************************************************/+#define __ECHO_STATE_MUTE (1 << 8)+#define ECHO_STATE_IDLE (0)+#define ECHO_STATE_PRETRAINING (1 | (__ECHO_STATE_MUTE))+#define ECHO_STATE_STARTTRAINING (2 | (__ECHO_STATE_MUTE))+#define ECHO_STATE_AWAITINGECHO (3 | (__ECHO_STATE_MUTE))+#define ECHO_STATE_TRAINING (4 | (__ECHO_STATE_MUTE))+#define ECHO_STATE_ACTIVE (5)++#define AMI_MASK 0x55+++static unsigned char linear2alaw (short linear)+{+ int mask;+ int seg;+ int pcm_val;+ static int seg_end[8] =+ {+ 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF+ };+ + pcm_val = linear;+ if (pcm_val >= 0)+ {+ /* Sign (7th) bit = 1 */+ mask = AMI_MASK | 0x80;+ }+ else+ {+ /* Sign bit = 0 */+ mask = AMI_MASK;+ pcm_val = -pcm_val;+ }++ /* Convert the scaled magnitude to segment number. */+ for (seg = 0; seg < 8; seg++)+ {+ if (pcm_val <= seg_end[seg])+ break;+ }+ /* Combine the sign, segment, and quantization bits. */+ return ((seg << 4) | ((pcm_val >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^ mask;+}++/*- End of function --------------------------------------------------------*/++static short int alaw2linear (uint8_t alaw)+{+ int i;+ int seg;++ alaw ^= AMI_MASK;+ i = ((alaw & 0x0F) << 4);+ seg = (((int) alaw & 0x70) >> 4);+ if (seg)+ i = (i + 0x100) << (seg - 1);+ return (short int) ((alaw & 0x80) ? i : -i);+}+++/** @return string of given echo cancellation state */+char* bchdev_echocancel_statestr(uint16_t state)+{+ switch(state) {+ case ECHO_STATE_IDLE:+ return "idle";+ break;+ case ECHO_STATE_PRETRAINING:+ return "pre-training";+ break;+ case ECHO_STATE_STARTTRAINING:+ return "transmit impulse";+ break;+ case ECHO_STATE_AWAITINGECHO:+ return "awaiting echo";+ break;+ case ECHO_STATE_TRAINING:+ return "training start";+ break;+ case ECHO_STATE_ACTIVE:+ return "training finished";+ break;+ default:+ return "unknown";+ }+}++/** Changes state of echo cancellation to given state */+void bchdev_echocancel_setstate(dsp_t* dev, uint16_t state)+{+ char* statestr = bchdev_echocancel_statestr(state);+ + printk("bchdev: echo cancel state %d (%s)\n", state & 0xff, statestr);+ if (state == ECHO_STATE_ACTIVE)+ printk("bchdev: %d taps trained\n", dev->echolastupdate);+ dev->echostate = state;+}++static int buf_size=0;+static int ec_timer=2000;+//static int ec_timer=1000;+++/** Activates echo cancellation for the given bch_dev, device must have been locked before! */+int bchdev_echocancel_activate(dsp_t* dev, int deftaps, int training)+{+ int taps;+ + if (! dev) return -EINVAL;+ + if (dev->ec && dev->ecdis_rd && dev->ecdis_wr) {+ // already active+ return 0;+ }+ + if (deftaps>0) {+ taps=deftaps;+ } else {+ taps=128;+ }+ + + switch (buf_size) {+ case 0: taps += 0; break;+ case 1: taps += 256-128; break;+ case 2: taps += 512-128; break;+ default: taps += 1024-128;+ }+ + if (!dev->ec) dev->ec = echo_can_create(taps, 0);+ if (!dev->ec) {+ return -ENOMEM;+ }+ + dev->echolastupdate = 0;++ if (!training) {+ dev->echotimer=0;+ bchdev_echocancel_setstate(dev, ECHO_STATE_IDLE);+ } else {+ if (training<10) + training= ec_timer;+ + dev->echotimer = training;+ bchdev_echocancel_setstate(dev, ECHO_STATE_PRETRAINING);++ }+ + if (!dev->ecdis_rd) dev->ecdis_rd = kmalloc(sizeof(echo_can_disable_detector_state_t), GFP_KERNEL);+ if (!dev->ecdis_rd) {+ kfree(dev->ec); dev->ec = NULL;+ return -ENOMEM;+ }+ echo_can_disable_detector_init(dev->ecdis_rd);+ + if (!dev->ecdis_wr) dev->ecdis_wr = kmalloc(sizeof(echo_can_disable_detector_state_t), GFP_KERNEL);+ if (!dev->ecdis_wr) {+ kfree(dev->ec); dev->ec = NULL;+ kfree(dev->ecdis_rd); dev->ecdis_rd = NULL;+ return -ENOMEM;+ }+ echo_can_disable_detector_init(dev->ecdis_wr);++ return 0;+}++/** Deactivates echo cancellation for the given bch_dev, device must have been locked before! */+void bchdev_echocancel_deactivate(dsp_t* dev)+{+ if (! dev) return;++ //chan_misdn_log("bchdev: deactivating echo cancellation on port=%04x, chan=%02x\n", dev->stack->port, dev->channel);+ + if (dev->ec) echo_can_free(dev->ec);+ dev->ec = NULL;+ + dev->echolastupdate = 0;+ dev->echotimer = 0;+ bchdev_echocancel_setstate(dev, ECHO_STATE_IDLE);++ if (dev->ecdis_rd) kfree(dev->ecdis_rd);+ dev->ecdis_rd = NULL;+ + if (dev->ecdis_wr) kfree(dev->ecdis_wr);+ dev->ecdis_wr = NULL;+}++/** Processes one TX- and one RX-packet with echocancellation */+void bchdev_echocancel_chunk(dsp_t* dev, uint8_t *rxchunk, uint8_t *txchunk, uint16_t size)+{+ int16_t rxlin, txlin;+ uint16_t pos;++ /* Perform echo cancellation on a chunk if requested */+ if (dev->ec) {+ if (dev->echostate & __ECHO_STATE_MUTE) {+ if (dev->echostate == ECHO_STATE_STARTTRAINING) {+ // Transmit impulse now+ txchunk[0] = linear2alaw(16384);+ memset(txchunk+1, 0, size-1);+ bchdev_echocancel_setstate(dev, ECHO_STATE_TRAINING); //AWAITINGECHO);+ } else {+ // train the echo cancellation+ for (pos = 0; pos < size; pos++) {+ rxlin = alaw2linear(rxchunk[pos]);+ txlin = alaw2linear(txchunk[pos]);+ if (dev->echostate == ECHO_STATE_PRETRAINING) {+ if (dev->echotimer <= 0) {+ dev->echotimer = 0;+ bchdev_echocancel_setstate(dev, ECHO_STATE_STARTTRAINING);+ } else {+ dev->echotimer--;+ }+ }+ if ((dev->echostate == ECHO_STATE_AWAITINGECHO) && (txlin > 8000)) {+ dev->echolastupdate = 0;+ bchdev_echocancel_setstate(dev, ECHO_STATE_TRAINING);+ }+ if (dev->echostate == ECHO_STATE_TRAINING) {+ if (echo_can_traintap(dev->ec, dev->echolastupdate++, rxlin)) {+ bchdev_echocancel_setstate(dev, ECHO_STATE_ACTIVE);+ }+ }++ rxchunk[pos] = linear2alaw(0);+ txchunk[pos] = linear2alaw(0);+ }+ }+ } else {+ for (pos = 0; pos < size; pos++) {+ rxlin = alaw2linear(rxchunk[pos]);+ txlin = alaw2linear(txchunk[pos]);++ if (echo_can_disable_detector_update(dev->ecdis_rd, rxlin) || + echo_can_disable_detector_update(dev->ecdis_wr, txlin)) {+ bchdev_echocancel_deactivate(dev);+ printk("EC: Fax detected, EC disabled\n");+ return ;+ } else {+ rxlin = echo_can_update(dev->ec, txlin, rxlin);+ rxchunk[pos] = linear2alaw(rxlin);+ }+ }+ }+ }+}++/******************************************************/diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/dsp_core.c mISDN/drivers/isdn/hardware/mISDN/dsp_core.c--- /tmp/mISDN/drivers/isdn/hardware/mISDN/dsp_core.c 2005-01-29 17:15:21.000000000 +0100+++ mISDN/drivers/isdn/hardware/mISDN/dsp_core.c 2005-12-02 09:57:08.000000000 +0100@@ -42,17 +42,11 @@ * v | * +-----+-------------+-----+ * |(3)(4) |- * | |- * | | * | CMX | * | |- * | |- * | |- * | | * | +-------------+ * | | ^ * | | |- * | | | * |+---------+| +----+----+ * ||(1) || |(5) | * || || | |@@ -62,7 +56,6 @@ * |+----+----+| +----+----+ * +-----+-----+ ^ * | | - * | | * v | * +----+----+ +----+----+ * |(5) | |(2) |@@ -74,8 +67,18 @@ * | ^ * | | * v |+ * +----+-------------+----++ * |(7) |+ * | |+ * | Echo Cancellation |+ * | |+ * | |+ * +----+-------------+----++ * | ^ + * | |+ * v | * +----+----+ +----+----+- * |(7) | |(7) |+ * |(8) | |(8) | * | | | | * | Encrypt | | Decrypt | * | | | |@@ -115,6 +118,13 @@ * data to/form upper layer may be swithed on/off individually without loosing * features of CMX, Tones and DTMF. *+ * Echo Cancellation: Sometimes we like to cancel echo from the interface.+ * Note that a VoIP call may not have echo caused by the IP phone. The echo+ * is generated by the telephone line connected to it. Because the delay+ * is high, it becomes an echo. RESULT: Echo Cachelation is required if+ * both echo AND delay is applied to an interface.+ * Remember that software CMX always generates a more or less delay.+ * * If all used features can be realized in hardware, and if transmit and/or * receive data ist disabled, the card may not send/receive any data at all. * Not receiving is usefull if only announcements are played. Not sending is@@ -215,6 +225,9 @@ printk(KERN_ERR "%s: failed to create tx packet\n", __FUNCTION__); return; }+ /* if echo cancellation is enabled */+ if (dsp->cancel_enable)+ dsp_cancel_tx(dsp, nskb->data, nskb->len); /* crypt if enabled */ if (dsp->bf_enable) dsp_bf_encrypt(dsp, nskb->data, nskb->len);@@ -380,6 +393,34 @@ if (dsp_debug & DEBUG_DSP_CMX) dsp_cmx_debug(dsp); break;+ case ECHOCAN_ON: /* turn echo calcellation on */+ + if (len<4) {+ ret = -EINVAL;+ break;+ }+ int ec_arr[2];+ + memcpy(&ec_arr,data,sizeof(ec_arr));+ + + printk("data[0]: %d data[1]: %d, len :%d\n",ec_arr[0],+ ec_arr[1] ,len);+ + if (dsp_debug & DEBUG_DSP_CORE)+ printk(KERN_DEBUG "%s: turn echo cancelation on (delay=%d attenuation-shift=%d\n", __FUNCTION__, ec_arr[0], ec_arr[1]);+ + ret = dsp_cancel_init(dsp, ec_arr[0], ec_arr[1] ,1);+ + dsp_cmx_hardware(dsp->conf, dsp);+ break;+ case ECHOCAN_OFF: /* turn echo calcellation off */+ if (dsp_debug & DEBUG_DSP_CORE)+ printk(KERN_DEBUG "%s: turn echo cancelation off\n", __FUNCTION__);+ + ret = dsp_cancel_init(dsp, 0,0,-1);+ dsp_cmx_hardware(dsp->conf, dsp);+ break; case BF_ENABLE_KEY: /* turn blowfish on */ if (len<4 || len>56) { ret = -EINVAL;@@ -522,6 +563,9 @@ /* decrypt if enabled */ if (dsp->bf_enable) dsp_bf_decrypt(dsp, skb->data, skb->len);+ /* if echo cancellation is enabled */+ if (dsp->cancel_enable)+ dsp_cancel_rx(dsp, skb->data, skb->len); /* check if dtmf soft decoding is turned on */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?