aboutsummaryrefslogtreecommitdiffstats
path: root/1.2-netsec/channels/misdn/mISDN.patch
diff options
context:
space:
mode:
Diffstat (limited to '1.2-netsec/channels/misdn/mISDN.patch')
-rw-r--r--1.2-netsec/channels/misdn/mISDN.patch2500
1 files changed, 0 insertions, 2500 deletions
diff --git a/1.2-netsec/channels/misdn/mISDN.patch b/1.2-netsec/channels/misdn/mISDN.patch
deleted file mode 100644
index ccc8ae4b2..000000000
--- a/1.2-netsec/channels/misdn/mISDN.patch
+++ /dev/null
@@ -1,2500 +0,0 @@
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/arith.h mISDN/drivers/isdn/hardware/mISDN/arith.h
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/arith.h 1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/arith.h 2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,347 @@
-+#ifndef _ZAPTEL_ARITH_H
-+#define _ZAPTEL_ARITH_H
-+/*
-+ * Handy add/subtract functions to operate on chunks of shorts.
-+ * Feel free to add customizations for additional architectures
-+ *
-+ */
-+
-+#ifdef CONFIG_ZAPTEL_MMX
-+#ifdef ZT_CHUNKSIZE
-+static inline void __ACSS(volatile short *dst, const short *src)
-+{
-+ __asm__ __volatile__ (
-+ "movq 0(%0), %%mm0;\n"
-+ "movq 0(%1), %%mm1;\n"
-+ "movq 8(%0), %%mm2;\n"
-+ "movq 8(%1), %%mm3;\n"
-+ "paddsw %%mm1, %%mm0;\n"
-+ "paddsw %%mm3, %%mm2;\n"
-+ "movq %%mm0, 0(%0);\n"
-+ "movq %%mm2, 8(%0);\n"
-+ : "=r" (dst)
-+ : "r" (src), "0" (dst)
-+ : "memory"
-+#if CLOBBERMMX
-+ , "%mm0", "%mm1", "%mm2", "%mm3"
-+#endif
-+ );
-+
-+}
-+static inline void __SCSS(volatile short *dst, const short *src)
-+{
-+ __asm__ __volatile__ (
-+ "movq 0(%0), %%mm0;\n"
-+ "movq 0(%1), %%mm1;\n"
-+ "movq 8(%0), %%mm2;\n"
-+ "movq 8(%1), %%mm3;\n"
-+ "psubsw %%mm1, %%mm0;\n"
-+ "psubsw %%mm3, %%mm2;\n"
-+ "movq %%mm0, 0(%0);\n"
-+ "movq %%mm2, 8(%0);\n"
-+ : "=r" (dst)
-+ : "r" (src), "0" (dst)
-+ : "memory"
-+#if CLOBBERMMX
-+ , "%mm0", "%mm1", "%mm2", "%mm3"
-+#endif
-+ );
-+
-+}
-+
-+#if (ZT_CHUNKSIZE == 8)
-+#define ACSS(a,b) __ACSS(a,b)
-+#define SCSS(a,b) __SCSS(a,b)
-+#elif (ZT_CHUNKSIZE > 8)
-+static inline void ACSS(volatile short *dst, const short *src)
-+{
-+ int x;
-+ for (x=0;x<ZT_CHUNKSIZE;x+=8)
-+ __ACSS(dst + x, src + x);
-+}
-+static inline void SCSS(volatile short *dst, const short *src)
-+{
-+ int x;
-+ for (x=0;x<ZT_CHUNKSIZE;x+=8)
-+ __SCSS(dst + x, src + x);
-+}
-+#else
-+#error No MMX for ZT_CHUNKSIZE < 8
-+#endif
-+#endif
-+static inline int CONVOLVE(const int *coeffs, const short *hist, int len)
-+{
-+ int sum;
-+ /* Divide length by 16 */
-+ len >>= 4;
-+
-+ /* Clear our accumulator, mm4 */
-+
-+ /*
-+
-+ For every set of eight...
-+
-+ Load 16 coefficients into four registers...
-+ Shift each word right 16 to make them shorts...
-+ Pack the resulting shorts into two registers...
-+ With the coefficients now in mm0 and mm2, load the
-+ history into mm1 and mm3...
-+ Multiply/add mm1 into mm0, and mm3 into mm2...
-+ Add mm2 into mm0 (without saturation, alas). Now we have two half-results.
-+ Accumulate in mm4 (again, without saturation, alas)
-+ */
-+ __asm__ (
-+ "pxor %%mm4, %%mm4;\n"
-+ "mov %1, %%edi;\n"
-+ "mov %2, %%esi;\n"
-+ "mov %3, %%ecx;\n"
-+ "1:"
-+ "movq 0(%%edi), %%mm0;\n"
-+ "movq 8(%%edi), %%mm1;\n"
-+ "movq 16(%%edi), %%mm2;\n"
-+ "movq 24(%%edi), %%mm3;\n"
-+ /* can't use 4/5 since 4 is the accumulator for us */
-+ "movq 32(%%edi), %%mm6;\n"
-+ "movq 40(%%edi), %%mm7;\n"
-+ "psrad $16, %%mm0;\n"
-+ "psrad $16, %%mm1;\n"
-+ "psrad $16, %%mm2;\n"
-+ "psrad $16, %%mm3;\n"
-+ "psrad $16, %%mm6;\n"
-+ "psrad $16, %%mm7;\n"
-+ "packssdw %%mm1, %%mm0;\n"
-+ "packssdw %%mm3, %%mm2;\n"
-+ "packssdw %%mm7, %%mm6;\n"
-+ "movq 0(%%esi), %%mm1;\n"
-+ "movq 8(%%esi), %%mm3;\n"
-+ "movq 16(%%esi), %%mm7;\n"
-+ "pmaddwd %%mm1, %%mm0;\n"
-+ "pmaddwd %%mm3, %%mm2;\n"
-+ "pmaddwd %%mm7, %%mm6;\n"
-+ "paddd %%mm6, %%mm4;\n"
-+ "paddd %%mm2, %%mm4;\n"
-+ "paddd %%mm0, %%mm4;\n"
-+ /* Come back and do for the last few bytes */
-+ "movq 48(%%edi), %%mm6;\n"
-+ "movq 56(%%edi), %%mm7;\n"
-+ "psrad $16, %%mm6;\n"
-+ "psrad $16, %%mm7;\n"
-+ "packssdw %%mm7, %%mm6;\n"
-+ "movq 24(%%esi), %%mm7;\n"
-+ "pmaddwd %%mm7, %%mm6;\n"
-+ "paddd %%mm6, %%mm4;\n"
-+ "add $64, %%edi;\n"
-+ "add $32, %%esi;\n"
-+ "dec %%ecx;\n"
-+ "jnz 1b;\n"
-+ "movq %%mm4, %%mm0;\n"
-+ "psrlq $32, %%mm0;\n"
-+ "paddd %%mm0, %%mm4;\n"
-+ "movd %%mm4, %0;\n"
-+ : "=r" (sum)
-+ : "r" (coeffs), "r" (hist), "r" (len)
-+ : "%ecx", "%edi", "%esi"
-+ );
-+
-+ return sum;
-+}
-+
-+static inline void UPDATE(volatile int *taps, const short *history, const int nsuppr, const int ntaps)
-+{
-+ int i;
-+ int correction;
-+ for (i=0;i<ntaps;i++) {
-+ correction = history[i] * nsuppr;
-+ taps[i] += correction;
-+ }
-+}
-+
-+static inline void UPDATE2(volatile int *taps, volatile short *taps_short, const short *history, const int nsuppr, const int ntaps)
-+{
-+ int i;
-+ int correction;
-+#if 0
-+ ntaps >>= 4;
-+ /* First, load up taps, */
-+ __asm__ (
-+ "pxor %%mm4, %%mm4;\n"
-+ "mov %0, %%edi;\n"
-+ "mov %1, %%esi;\n"
-+ "mov %3, %%ecx;\n"
-+ "1:"
-+ "jnz 1b;\n"
-+ "movq %%mm4, %%mm0;\n"
-+ "psrlq $32, %%mm0;\n"
-+ "paddd %%mm0, %%mm4;\n"
-+ "movd %%mm4, %0;\n"
-+ : "=r" (taps), "=r" (taps_short)
-+ : "r" (history), "r" (nsuppr), "r" (ntaps), "0" (taps)
-+ : "%ecx", "%edi", "%esi"
-+ );
-+#endif
-+#if 1
-+ for (i=0;i<ntaps;i++) {
-+ correction = history[i] * nsuppr;
-+ taps[i] += correction;
-+ taps_short[i] = taps[i] >> 16;
-+ }
-+#endif
-+}
-+
-+static inline int CONVOLVE2(const short *coeffs, const short *hist, int len)
-+{
-+ int sum;
-+ /* Divide length by 16 */
-+ len >>= 4;
-+
-+ /* Clear our accumulator, mm4 */
-+
-+ /*
-+
-+ For every set of eight...
-+ Load in eight coefficients and eight historic samples, multliply add and
-+ accumulate the result
-+ */
-+ __asm__ (
-+ "pxor %%mm4, %%mm4;\n"
-+ "mov %1, %%edi;\n"
-+ "mov %2, %%esi;\n"
-+ "mov %3, %%ecx;\n"
-+ "1:"
-+ "movq 0(%%edi), %%mm0;\n"
-+ "movq 8(%%edi), %%mm2;\n"
-+ "movq 0(%%esi), %%mm1;\n"
-+ "movq 8(%%esi), %%mm3;\n"
-+ "pmaddwd %%mm1, %%mm0;\n"
-+ "pmaddwd %%mm3, %%mm2;\n"
-+ "paddd %%mm2, %%mm4;\n"
-+ "paddd %%mm0, %%mm4;\n"
-+ "movq 16(%%edi), %%mm0;\n"
-+ "movq 24(%%edi), %%mm2;\n"
-+ "movq 16(%%esi), %%mm1;\n"
-+ "movq 24(%%esi), %%mm3;\n"
-+ "pmaddwd %%mm1, %%mm0;\n"
-+ "pmaddwd %%mm3, %%mm2;\n"
-+ "paddd %%mm2, %%mm4;\n"
-+ "paddd %%mm0, %%mm4;\n"
-+ "add $32, %%edi;\n"
-+ "add $32, %%esi;\n"
-+ "dec %%ecx;\n"
-+ "jnz 1b;\n"
-+ "movq %%mm4, %%mm0;\n"
-+ "psrlq $32, %%mm0;\n"
-+ "paddd %%mm0, %%mm4;\n"
-+ "movd %%mm4, %0;\n"
-+ : "=r" (sum)
-+ : "r" (coeffs), "r" (hist), "r" (len)
-+ : "%ecx", "%edi", "%esi"
-+ );
-+
-+ return sum;
-+}
-+static inline short MAX16(const short *y, int len, int *pos)
-+{
-+ int k;
-+ short max = 0;
-+ int bestpos = 0;
-+ for (k=0;k<len;k++) {
-+ if (max < y[k]) {
-+ bestpos = k;
-+ max = y[k];
-+ }
-+ }
-+ *pos = (len - 1 - bestpos);
-+ return max;
-+}
-+
-+
-+
-+#else
-+
-+#ifdef ZT_CHUNKSIZE
-+static inline void ACSS(short *dst, short *src)
-+{
-+ int x,sum;
-+ /* Add src to dst with saturation, storing in dst */
-+ for (x=0;x<ZT_CHUNKSIZE;x++) {
-+ sum = dst[x]+src[x];
-+ if (sum > 32767)
-+ sum = 32767;
-+ else if (sum < -32768)
-+ sum = -32768;
-+ dst[x] = sum;
-+ }
-+}
-+
-+static inline void SCSS(short *dst, short *src)
-+{
-+ int x,sum;
-+ /* Add src to dst with saturation, storing in dst */
-+ for (x=0;x<ZT_CHUNKSIZE;x++) {
-+ sum = dst[x]-src[x];
-+ if (sum > 32767)
-+ sum = 32767;
-+ else if (sum < -32768)
-+ sum = -32768;
-+ dst[x] = sum;
-+ }
-+}
-+
-+#endif /* ZT_CHUNKSIZE */
-+
-+static inline int CONVOLVE(const int *coeffs, const short *hist, int len)
-+{
-+ int x;
-+ int sum = 0;
-+ for (x=0;x<len;x++)
-+ sum += (coeffs[x] >> 16) * hist[x];
-+ return sum;
-+}
-+
-+static inline int CONVOLVE2(const short *coeffs, const short *hist, int len)
-+{
-+ int x;
-+ int sum = 0;
-+ for (x=0;x<len;x++)
-+ sum += coeffs[x] * hist[x];
-+ return sum;
-+}
-+
-+static inline void UPDATE(int *taps, const short *history, const int nsuppr, const int ntaps)
-+{
-+ int i;
-+ int correction;
-+ for (i=0;i<ntaps;i++) {
-+ correction = history[i] * nsuppr;
-+ taps[i] += correction;
-+ }
-+}
-+
-+static inline void UPDATE2(int *taps, short *taps_short, const short *history, const int nsuppr, const int ntaps)
-+{
-+ int i;
-+ int correction;
-+ for (i=0;i<ntaps;i++) {
-+ correction = history[i] * nsuppr;
-+ taps[i] += correction;
-+ taps_short[i] = taps[i] >> 16;
-+ }
-+}
-+
-+static inline short MAX16(const short *y, int len, int *pos)
-+{
-+ int k;
-+ short max = 0;
-+ int bestpos = 0;
-+ for (k=0;k<len;k++) {
-+ if (max < y[k]) {
-+ bestpos = k;
-+ max = y[k];
-+ }
-+ }
-+ *pos = (len - 1 - bestpos);
-+ return max;
-+}
-+
-+#endif /* MMX */
-+#endif /* _ZAPTEL_ARITH_H */
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/biquad.h mISDN/drivers/isdn/hardware/mISDN/biquad.h
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/biquad.h 1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/biquad.h 2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,73 @@
-+/*
-+ * SpanDSP - a series of DSP components for telephony
-+ *
-+ * biquad.h - General telephony bi-quad section routines (currently this just
-+ * handles canonic/type 2 form)
-+ *
-+ * Written by Steve Underwood <steveu@coppice.org>
-+ *
-+ * Copyright (C) 2001 Steve Underwood
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+typedef struct
-+{
-+ int32_t gain;
-+ int32_t a1;
-+ int32_t a2;
-+ int32_t b1;
-+ int32_t b2;
-+
-+ int32_t z1;
-+ int32_t z2;
-+} biquad2_state_t;
-+
-+static inline void biquad2_init (biquad2_state_t *bq,
-+ int32_t gain,
-+ int32_t a1,
-+ int32_t a2,
-+ int32_t b1,
-+ int32_t b2)
-+{
-+ bq->gain = gain;
-+ bq->a1 = a1;
-+ bq->a2 = a2;
-+ bq->b1 = b1;
-+ bq->b2 = b2;
-+
-+ bq->z1 = 0;
-+ bq->z2 = 0;
-+}
-+/*- End of function --------------------------------------------------------*/
-+
-+static inline int16_t biquad2 (biquad2_state_t *bq, int16_t sample)
-+{
-+ int32_t y;
-+ int32_t z0;
-+
-+ z0 = sample*bq->gain + bq->z1*bq->a1 + bq->z2*bq->a2;
-+ y = z0 + bq->z1*bq->b1 + bq->z2*bq->b2;
-+
-+ bq->z2 = bq->z1;
-+ bq->z1 = z0 >> 15;
-+ y >>= 15;
-+ return y;
-+}
-+/*- End of function --------------------------------------------------------*/
-+/*- End of file ------------------------------------------------------------*/
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/dsp_cancel.c mISDN/drivers/isdn/hardware/mISDN/dsp_cancel.c
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/dsp_cancel.c 1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/dsp_cancel.c 2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,390 @@
-+/* $Id$
-+ *
-+ * Simple but fast Echo cancellation for mISDN_dsp.
-+ *
-+ * Copyright Andreas Eversberg (jolly@jolly.de)
-+ *
-+ * This software may be used and distributed according to the terms
-+ * of the GNU General Public License, incorporated herein by reference.
-+ *
-+ */
-+
-+#include "layer1.h"
-+#include "helper.h"
-+#include "debug.h"
-+#include "dsp.h"
-+
-+
-+/*
-+ * how this works:
-+ *
-+ *
-+ *
-+ */
-+void bchdev_echocancel_chunk(dsp_t* dev, uint8_t *rxchunk, uint8_t *txchunk, uint16_t size);
-+int bchdev_echocancel_activate(dsp_t* dev, int deftaps, int train);
-+void bchdev_echocancel_deactivate(dsp_t* dev);
-+
-+
-+
-+
-+
-+
-+static char flip_table[256];
-+
-+void dsp_cancel_init_flip_bits()
-+{
-+ int i,k;
-+
-+ 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 */
- if (dsp->dtmf.software) {
- digits = dsp_dtmf_goertzel_decode(dsp, skb->data, skb->len, (dsp_options&DSP_OPT_ULAW)?1:0);
-@@ -919,6 +963,9 @@
- dsp_audio_generate_ulaw_samples();
- dsp_audio_generate_volume_changes();
-
-+
-+ dsp_cancel_init_flip_bits();
-+
- /* init global lock */
- lock_HW_init(&dsp_lock);
-
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/dsp.h mISDN/drivers/isdn/hardware/mISDN/dsp.h
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/dsp.h 2005-01-29 17:15:31.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/dsp.h 2005-12-02 09:57:08.000000000 +0100
-@@ -40,6 +40,13 @@
- #include "memdbg.h"
- #endif
-
-+#include "ecdis.h"
-+#include "mec2.h"
-+
-+//#include "mec.h"
-+//#include "mec3.h"
-+
-+
- extern int dsp_options;
- extern int dsp_debug;
-
-@@ -109,6 +116,8 @@
-
- #define DSP_DTMF_NPOINTS 102
-
-+#define ECHOCAN_BUFLEN 4*128
-+
- typedef struct _dtmf_t {
- int software; /* dtmf uses software decoding */
- int hardware; /* dtmf uses hardware decoding */
-@@ -120,6 +129,13 @@
- } dtmf_t;
-
-
-+/**************
-+ *Cancel Stuff*
-+ ***************/
-+
-+void dsp_cancel_init_flip_bits(void);
-+
-+
- /***************
- * tones stuff *
- ***************/
-@@ -200,6 +216,25 @@
- u8 bf_crypt_inring[16];
- u8 bf_data_out[9];
- int bf_sync;
-+
-+ /* echo cancellation stuff */
-+ int cancel_enable;
-+ echo_can_state_t* ec; /**< == NULL: echo cancellation disabled;
-+ != NULL: echo cancellation enabled */
-+
-+ echo_can_disable_detector_state_t* ecdis_rd;
-+ echo_can_disable_detector_state_t* ecdis_wr;
-+
-+ uint16_t echotimer;
-+ uint16_t echostate;
-+ uint16_t echolastupdate;
-+
-+ char txbuf[ECHOCAN_BUFLEN];
-+ int txbuflen;
-+
-+ char rxbuf[ECHOCAN_BUFLEN];
-+ int rxbuflen;
-+
- } dsp_t;
-
- /* functions */
-@@ -228,4 +263,8 @@
- extern int dsp_bf_init(dsp_t *dsp, const u8 *key, unsigned int keylen);
- extern void dsp_bf_cleanup(dsp_t *dsp);
-
-+extern void dsp_cancel_tx(dsp_t *dsp, u8 *data, int len);
-+extern void dsp_cancel_rx(dsp_t *dsp, u8 *data, int len);
-+extern int dsp_cancel_init(dsp_t *dsp, int taps, int training, int delay);
-+
-
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/ec.c mISDN/drivers/isdn/hardware/mISDN/ec.c
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/ec.c 1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/ec.c 2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,105 @@
-+#include "mec2.h"
-+#include "ec.h"
-+
-+
-+
-+#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);
-+}
-+
-+
-+void ec_chunk(struct echo_can_s *echo_can, unsigned char *rxchunk, const unsigned char *txchunk, int chunk_size)
-+{
-+ short rxlin, txlin;
-+ int x;
-+ //unsigned long flags;
-+ /* Perform echo cancellation on a chunk if necessary */
-+ if (echo_can->ec) {
-+ if (echo_can->echostate & __ECHO_STATE_MUTE) {
-+ /* Special stuff for training the echo can */
-+ for (x=0;x< chunk_size;x++) {
-+ rxlin = alaw2linear(rxchunk[x]);
-+ txlin = alaw2linear(txchunk[x]);
-+ if (echo_can->echostate == ECHO_STATE_PRETRAINING) {
-+ if (--echo_can->echotimer <= 0) {
-+ echo_can->echotimer = 0;
-+ echo_can->echostate = ECHO_STATE_STARTTRAINING;
-+ }
-+ }
-+ if ((echo_can->echostate == ECHO_STATE_AWAITINGECHO) && (txlin > 8000)) {
-+ echo_can->echolastupdate = 0;
-+ echo_can->echostate = ECHO_STATE_TRAINING;
-+ }
-+ if (echo_can->echostate == ECHO_STATE_TRAINING) {
-+ if (echo_can_traintap(echo_can->ec, echo_can->echolastupdate++, rxlin)) {
-+#if 0
-+ printf("Finished training (%d taps trained)!\n", echo_can->echolastupdate);
-+#endif
-+ echo_can->echostate = ECHO_STATE_ACTIVE;
-+ }
-+ }
-+ rxlin = 0;
-+ rxchunk[x] = linear2alaw((int)rxlin);
-+ }
-+ } else {
-+ for (x=0;x<chunk_size;x++) {
-+ rxlin = alaw2linear(rxchunk[x]);
-+ rxlin = echo_can_update(echo_can->ec, alaw2linear(txchunk[x]), rxlin);
-+ rxchunk[x] = linear2alaw((int)rxlin);
-+ }
-+ }
-+ }
-+}
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/ecdis.h mISDN/drivers/isdn/hardware/mISDN/ecdis.h
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/ecdis.h 1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/ecdis.h 2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,118 @@
-+/*
-+ * SpanDSP - a series of DSP components for telephony
-+ *
-+ * ec_disable_detector.h - A detector which should eventually meet the
-+ * G.164/G.165 requirements for detecting the
-+ * 2100Hz echo cancellor disable tone.
-+ *
-+ * Written by Steve Underwood <steveu@coppice.org>
-+ *
-+ * Copyright (C) 2001 Steve Underwood
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+#include "biquad.h"
-+
-+typedef struct
-+{
-+ biquad2_state_t notch;
-+ int notch_level;
-+ int channel_level;
-+ int tone_present;
-+ int tone_cycle_duration;
-+ int good_cycles;
-+ int hit;
-+} echo_can_disable_detector_state_t;
-+
-+
-+#define FALSE 0
-+#define TRUE (!FALSE)
-+
-+static inline void echo_can_disable_detector_init (echo_can_disable_detector_state_t *det)
-+{
-+ /* Elliptic notch */
-+ /* This is actually centred at 2095Hz, but gets the balance we want, due
-+ to the asymmetric walls of the notch */
-+ biquad2_init (&det->notch,
-+ (int32_t) (-0.7600000*32768.0),
-+ (int32_t) (-0.1183852*32768.0),
-+ (int32_t) (-0.5104039*32768.0),
-+ (int32_t) ( 0.1567596*32768.0),
-+ (int32_t) ( 1.0000000*32768.0));
-+
-+ det->channel_level = 0;
-+ det->notch_level = 0;
-+ det->tone_present = FALSE;
-+ det->tone_cycle_duration = 0;
-+ det->good_cycles = 0;
-+ det->hit = 0;
-+}
-+/*- End of function --------------------------------------------------------*/
-+
-+static inline int echo_can_disable_detector_update (echo_can_disable_detector_state_t *det,
-+ int16_t amp)
-+{
-+ int16_t notched;
-+
-+ notched = biquad2 (&det->notch, amp);
-+ /* Estimate the overall energy in the channel, and the energy in
-+ the notch (i.e. overall channel energy - tone energy => noise).
-+ Use abs instead of multiply for speed (is it really faster?).
-+ Damp the overall energy a little more for a stable result.
-+ Damp the notch energy a little less, so we don't damp out the
-+ blip every time the phase reverses */
-+ det->channel_level += ((abs(amp) - det->channel_level) >> 5);
-+ det->notch_level += ((abs(notched) - det->notch_level) >> 4);
-+ if (det->channel_level > 280)
-+ {
-+ /* There is adequate energy in the channel. Is it mostly at 2100Hz? */
-+ if (det->notch_level*6 < det->channel_level)
-+ {
-+ /* The notch says yes, so we have the tone. */
-+ if (!det->tone_present)
-+ {
-+ /* Do we get a kick every 450+-25ms? */
-+ if (det->tone_cycle_duration >= 425*8
-+ &&
-+ det->tone_cycle_duration <= 475*8)
-+ {
-+ det->good_cycles++;
-+ if (det->good_cycles > 2)
-+ det->hit = TRUE;
-+ }
-+ det->tone_cycle_duration = 0;
-+ }
-+ det->tone_present = TRUE;
-+ }
-+ else
-+ {
-+ det->tone_present = FALSE;
-+ }
-+ det->tone_cycle_duration++;
-+ }
-+ else
-+ {
-+ det->tone_present = FALSE;
-+ det->tone_cycle_duration = 0;
-+ det->good_cycles = 0;
-+ }
-+ return det->hit;
-+}
-+/*- End of function --------------------------------------------------------*/
-+/*- End of file ------------------------------------------------------------*/
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/ec.h mISDN/drivers/isdn/hardware/mISDN/ec.h
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/ec.h 1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/ec.h 2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,12 @@
-+
-+
-+
-+struct echo_can_s {
-+ int echostate;
-+ int echotimer;
-+ int echolastupdate;
-+ echo_can_state_t *ec;
-+};
-+
-+
-+
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c 2005-01-31 18:24:03.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c 2005-12-02 09:57:08.000000000 +0100
-@@ -136,7 +136,7 @@
- static int nt_t1_count[] = { 480, 240, 120, 60, 30, 15, 8, 4 };
- #define CLKDEL_TE 0x0f /* CLKDEL in TE mode */
- #define CLKDEL_NT 0x0c /* CLKDEL in NT mode (0x60 MUST not be included!) */
--static u_char silence = 0xff; /* silence by LAW */
-+static u_char mysilence = 0xff; /* silence by LAW */
-
- /* enable 32 bit fifo access (PC usage) */
- #define FIFO_32BIT_ACCESS
-@@ -903,11 +903,11 @@
- bch->tx_idx = bch->tx_len = 0;
- }
- /* now we have no more data, so in case of transparent,
-- * we set the last byte in fifo to 'silence' in case we will get
-+ * we set the last byte in fifo to 'mysilence' in case we will get
- * no more data at all. this prevents sending an undefined value.
- */
- if (!hdlc)
-- HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence);
-+ HFC_outb_(hc, A_FIFO_DATA0_NOINC, mysilence);
- }
-
-
-@@ -1551,7 +1551,7 @@
- HFC_outb(hc, A_IRQ_MSK, 0);
- HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
- HFC_wait(hc);
-- HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence); /* tx silence */
-+ HFC_outb_(hc, A_FIFO_DATA0_NOINC, mysilence); /* tx silence */
- /* enable RX fifo */
- HFC_outb(hc, R_FIFO, (ch<<1)|1);
- HFC_wait(hc);
-@@ -1692,7 +1692,7 @@
-
- /* if off */
- if (len <= 0) {
-- HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence);
-+ HFC_outb_(hc, A_FIFO_DATA0_NOINC, mysilence);
- if (hc->chan[ch].slot_tx>=0) {
- if (debug & DEBUG_HFCMULTI_MODE)
- printk(KERN_DEBUG "%s: connecting PCM due to no more TONE: channel %d slot_tx %d\n", __FUNCTION__, ch, hc->chan[ch].slot_tx);
-@@ -2183,7 +2183,7 @@
- ret = 0;
- break;
-
-- /* set silence */
-+ /* set mysilence */
- case HW_SPL_LOOP_OFF:
- if (debug & DEBUG_HFCMULTI_MSG)
- printk(KERN_DEBUG "%s: HW_SPL_LOOP_OFF\n", __FUNCTION__);
-@@ -2799,7 +2799,13 @@
- if (debug & DEBUG_HFCMULTI_INIT)
- printk(KERN_DEBUG "setup_pci(): investigating card entry %d (looking for type %d)\n", i, hc->type);
- inuse:
-+
-+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
-+ tmp_dev = pci_get_subsys(id_list[i].vendor_id, id_list[i].device_id, id_list[i].vendor_sub, id_list[i].device_sub, tmp_dev);
-+#else
- tmp_dev = pci_find_subsys(id_list[i].vendor_id, id_list[i].device_id, id_list[i].vendor_sub, id_list[i].device_sub, tmp_dev);
-+#endif
-+
- if (tmp_dev) {
- /* skip if already in use */
- list_for_each_entry_safe(hc_tmp, next, &HFCM_obj.ilist, list) {
-@@ -3318,9 +3324,9 @@
- hc->type = type[HFC_cnt] & 0xff;
- if (type[HFC_cnt] & 0x100) {
- test_and_set_bit(HFC_CHIP_ULAW, &hc->chip);
-- silence = 0xff; /* ulaw silence */
-+ mysilence = 0xff; /* ulaw silence */
- } else
-- silence = 0x2a; /* alaw silence */
-+ mysilence = 0x2a; /* alaw silence */
- if (type[HFC_cnt] & 0x200)
- test_and_set_bit(HFC_CHIP_DTMF, &hc->chip);
- // if ((type[HFC_cnt]&0x400) && hc->type==4)
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/l3_udss1.c mISDN/drivers/isdn/hardware/mISDN/l3_udss1.c
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/l3_udss1.c 2005-03-26 11:21:39.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/l3_udss1.c 2005-12-02 09:57:08.000000000 +0100
-@@ -1202,6 +1202,14 @@
- err = check_infoelements(pc, skb, ie_PROGRESS);
- if (err)
- l3dss1_std_ie_err(pc, err);
-+ /* START: patch by steinwej - http://www.beronet.com/bugs/bug_view_page.php?bug_id=0000095 */
-+ /* clear T310 if running */
-+ L3DelTimer(&pc->timer);
-+ if (pc->t303skb) {
-+ dev_kfree_skb(pc->t303skb);
-+ pc->t303skb = NULL;
-+ }
-+ /* END */
- if (ERR_IE_COMPREHENSION != err) {
- if (mISDN_l3up(pc, CC_PROGRESS | INDICATION, skb))
- dev_kfree_skb(skb);
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/Makefile mISDN/drivers/isdn/hardware/mISDN/Makefile
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/Makefile 2005-06-05 14:44:10.000000000 +0200
-+++ mISDN/drivers/isdn/hardware/mISDN/Makefile 2005-12-05 19:03:11.000000000 +0100
-@@ -30,6 +30,7 @@
-
- ifdef CONFIG_MISDN_SPEEDFAX
- obj-$(CONFIG_MISDN_DRV) += sedlfax.o
-+obj-$(CONFIG_MISDN_DRV) += faxl3.o
- endif
-
- ifdef CONFIG_MISDN_W6692
-@@ -70,8 +71,6 @@
- asn1_basic_service.o asn1_address.o asn1_enc.o capi_enc.o \
- supp_serv.o
- mISDN_dtmf-objs := dtmf.o
--mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o
-+mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o dsp_cancel.o
- mISDN_x25dte-objs := x25_dte.o x25_l3.o
- I4LmISDN-objs := i4l_mISDN.o
--
--include Rules.mISDN
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/Makefile.v2.6 mISDN/drivers/isdn/hardware/mISDN/Makefile.v2.6
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/Makefile.v2.6 2005-06-05 14:44:10.000000000 +0200
-+++ mISDN/drivers/isdn/hardware/mISDN/Makefile.v2.6 2005-12-02 09:57:08.000000000 +0100
-@@ -71,6 +71,6 @@
- asn1_basic_service.o asn1_address.o asn1_enc.o capi_enc.o \
- supp_serv.o
- mISDN_dtmf-objs := dtmf.o
--mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o
-+mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o dsp_cancel.o
- mISDN_x25dte-objs := x25_dte.o x25_l3.o
- I4LmISDN-objs := i4l_mISDN.o
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/mec2_const.h mISDN/drivers/isdn/hardware/mISDN/mec2_const.h
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/mec2_const.h 1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/mec2_const.h 2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,25 @@
-+/*
-+ Important constants for tuning mec2 echo can
-+ */
-+#ifndef _MEC2_CONST_H
-+#define _MEC2_CONST_H
-+
-+
-+/* Convergence speed -- higher means slower */
-+#define DEFAULT_BETA1_I 2048
-+#define DEFAULT_SIGMA_LY_I 7
-+#define DEFAULT_SIGMA_LU_I 7
-+#define DEFAULT_ALPHA_ST_I 5
-+#define DEFAULT_ALPHA_YT_I 5
-+#define DEFAULT_CUTOFF_I 128
-+#define DEFAULT_HANGT 600
-+#define DEFAULT_SUPPR_I 16
-+#define MIN_UPDATE_THRESH_I 4096
-+#define DEFAULT_M 16
-+#define SUPPR_FLOOR -64
-+#define SUPPR_CEIL -24
-+#define RES_SUPR_FACTOR -20
-+#define AGGRESSIVE_HCNTR 160 /* 20ms */
-+
-+#endif /* _MEC2_CONST_H */
-+
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/mec2.h mISDN/drivers/isdn/hardware/mISDN/mec2.h
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/mec2.h 1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/mec2.h 2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,409 @@
-+/*
-+ * Mark's Second Echo Canceller
-+ *
-+ * Copyright (C) 2002, Digium, Inc.
-+ *
-+ * This program is free software and may be used and
-+ * distributed according to the terms of the GNU
-+ * General Public License, incorporated herein by
-+ * reference.
-+ *
-+ */
-+#ifndef _MARK2_ECHO_H
-+#define _MARK2_ECHO_H
-+
-+#ifdef __KERNEL__
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#define MALLOC(a) kmalloc((a), GFP_KERNEL)
-+#define FREE(a) kfree(a)
-+#else
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <stdint.h>
-+#include <string.h>
-+#include <math.h>
-+#define MALLOC(a) malloc(a)
-+#define FREE(a) free(a)
-+#endif
-+
-+/* Get optimized routines for math */
-+#include "arith.h"
-+
-+#ifndef NULL
-+#define NULL 0
-+#endif
-+#ifndef FALSE
-+#define FALSE 0
-+#endif
-+#ifndef TRUE
-+#define TRUE (!FALSE)
-+#endif
-+
-+#include "mec2_const.h"
-+
-+/* Circular buffer definition */
-+typedef struct {
-+ int idx_d;
-+ int size_d;
-+ short *buf_d; /* Twice as large as we need */
-+} echo_can_cb_s;
-+
-+// class definition
-+//
-+typedef struct {
-+ /* Echo canceller definition */
-+
-+ /* absolute time */
-+ int i_d;
-+
-+ /* pre-computed constants */
-+
-+ int N_d;
-+ int beta2_i;
-+
-+ // declare accumulators for power computations
-+ //
-+ int Ly_i;
-+ int Lu_i;
-+
-+ // declare an accumulator for the near-end signal detector
-+ //
-+ int s_tilde_i;
-+ int HCNTR_d;
-+
-+ // circular buffers and coefficients
-+ //
-+ int *a_i;
-+ short *a_s;
-+ echo_can_cb_s y_s;
-+ echo_can_cb_s s_s;
-+ echo_can_cb_s u_s;
-+ echo_can_cb_s y_tilde_s;
-+ int y_tilde_i;
-+
-+ /* Max memory */
-+ short max_y_tilde;
-+ int max_y_tilde_pos;
-+
-+} echo_can_state_t;
-+
-+static inline void init_cb_s(echo_can_cb_s *cb, int len, void *where)
-+{
-+ cb->buf_d = (short *)where;
-+ cb->idx_d = 0;
-+ cb->size_d = len;
-+}
-+
-+static inline void add_cc_s(echo_can_cb_s *cb, short newval)
-+{
-+ /* Can't use modulus because N+M isn't a power of two (generally) */
-+ cb->idx_d--;
-+ if (cb->idx_d < (int)0)
-+ {cb->idx_d += cb->size_d;}
-+ /* Load two copies into memory */
-+ cb->buf_d[cb->idx_d] = newval;
-+ cb->buf_d[cb->idx_d + cb->size_d] = newval;
-+}
-+
-+static inline short get_cc_s(echo_can_cb_s *cb, int pos)
-+{
-+ /* Load two copies into memory */
-+ return cb->buf_d[cb->idx_d + pos];
-+}
-+
-+static inline void init_cc(echo_can_state_t *ec, int N, int maxy, int maxu) {
-+
-+ void *ptr = ec;
-+ unsigned long tmp;
-+ /* double-word align past end of state */
-+ ptr += sizeof(echo_can_state_t);
-+ tmp = (unsigned long)ptr;
-+ tmp += 3;
-+ tmp &= ~3L;
-+ ptr = (void *)tmp;
-+
-+ // reset parameters
-+ //
-+ ec->N_d = N;
-+ ec->beta2_i = DEFAULT_BETA1_I;
-+
-+ // allocate coefficient memory
-+ //
-+ ec->a_i = ptr;
-+ ptr += (sizeof(int) * ec->N_d);
-+ ec->a_s = ptr;
-+ ptr += (sizeof(short) * ec->N_d);
-+
-+ /* Reset Y circular buffer (short version) */
-+ init_cb_s(&ec->y_s, maxy, ptr);
-+ ptr += (sizeof(short) * (maxy) * 2);
-+
-+ /* Reset Sig circular buffer (short version for FIR filter) */
-+ init_cb_s(&ec->s_s, (1 << DEFAULT_ALPHA_ST_I), ptr);
-+ ptr += (sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) * 2);
-+
-+ init_cb_s(&ec->u_s, maxu, ptr);
-+ ptr += (sizeof(short) * maxu * 2);
-+
-+ // allocate a buffer for the reference signal power computation
-+ //
-+ init_cb_s(&ec->y_tilde_s, ec->N_d, ptr);
-+
-+
-+ // reset absolute time
-+ //
-+ ec->i_d = (int)0;
-+
-+ // reset the power computations (for y and u)
-+ //
-+ ec->Ly_i = DEFAULT_CUTOFF_I;
-+ ec->Lu_i = DEFAULT_CUTOFF_I;
-+
-+ // reset the near-end speech detector
-+ //
-+ ec->s_tilde_i = 0;
-+ ec->HCNTR_d = (int)0;
-+
-+ // exit gracefully
-+ //
-+}
-+
-+static inline void echo_can_free(echo_can_state_t *ec)
-+{
-+ FREE(ec);
-+}
-+
-+static inline short echo_can_update(echo_can_state_t *ec, short iref, short isig) {
-+
-+ /* declare local variables that are used more than once
-+ */
-+ int k;
-+ int rs;
-+ short u;
-+ int Py_i;
-+ int two_beta_i;
-+
-+ /***************************************************************************
-+ //
-+ // flow A on pg. 428
-+ //
-+ ***************************************************************************/
-+
-+ /* eq. (16): high-pass filter the input to generate the next value;
-+ // push the current value into the circular buffer
-+ //
-+ // sdc_im1_d = sdc_d;
-+ // sdc_d = sig;
-+ // s_i_d = sdc_d;
-+ // s_d = s_i_d;
-+ // s_i_d = (float)(1.0 - gamma_d) * s_i_d
-+ + (float)(0.5 * (1.0 - gamma_d)) * (sdc_d - sdc_im1_d); */
-+
-+
-+ /* Delete last sample from power estimate */
-+ ec->y_tilde_i -= abs(get_cc_s(&ec->y_s, (1 << DEFAULT_ALPHA_YT_I) - 1 )) >> DEFAULT_ALPHA_YT_I;
-+ /* push the reference data onto the circular buffer */
-+ add_cc_s(&ec->y_s, iref);
-+
-+ /* eq. (2): compute r in fixed-point */
-+ rs = CONVOLVE2(ec->a_s, ec->y_s.buf_d + ec->y_s.idx_d, ec->N_d);
-+ rs >>= 15;
-+
-+ /* eq. (3): compute the output value (see figure 3) and the error
-+ // note: the error is the same as the output signal when near-end
-+ // speech is not present
-+ */
-+ u = isig - rs;
-+
-+ add_cc_s(&ec->u_s, u);
-+
-+
-+
-+ /* Delete oldest part of received s_tilde */
-+ ec->s_tilde_i -= abs(get_cc_s(&ec->s_s, (1 << DEFAULT_ALPHA_ST_I) - 1 ));
-+
-+ /* push the signal on the circular buffer, too */
-+ add_cc_s(&ec->s_s, isig);
-+ ec->s_tilde_i += abs(isig);
-+ ec->y_tilde_i += abs(iref) >> DEFAULT_ALPHA_YT_I;
-+
-+ /* Add to our list of recent y_tilde's */
-+ add_cc_s(&ec->y_tilde_s, ec->y_tilde_i);
-+
-+ /****************************************************************************
-+ //
-+ // flow B on pg. 428
-+ //
-+ ****************************************************************************/
-+
-+ /* compute the new convergence factor
-+ */
-+ Py_i = (ec->Ly_i >> DEFAULT_SIGMA_LY_I) * (ec->Ly_i >> DEFAULT_SIGMA_LY_I);
-+ Py_i >>= 15;
-+ if (ec->HCNTR_d > 0) {
-+ Py_i = (1 << 15);
-+ }
-+
-+#if 0
-+ printf("Py: %e, Py_i: %e\n", Py, Py_i * AMPL_SCALE_1);
-+#endif
-+
-+ /* Vary rate of adaptation depending on position in the file
-+ // Do not do this for the first (DEFAULT_UPDATE_TIME) secs after speech
-+ // has begun of the file to allow the echo cancellor to estimate the
-+ // channel accurately
-+ */
-+#if 0
-+ if (ec->start_speech_d != 0 ){
-+ if ( ec->i_d > (DEFAULT_T0 + ec->start_speech_d)*(SAMPLE_FREQ) ){
-+ ec->beta2_d = max_cc_float(MIN_BETA,
-+ DEFAULT_BETA1 * exp((-1/DEFAULT_TAU)*((ec->i_d/(float)SAMPLE_FREQ) -
-+ DEFAULT_T0 -
-+ ec->start_speech_d)));
-+ }
-+ }
-+ else {ec->beta2_d = DEFAULT_BETA1;}
-+#endif
-+
-+ ec->beta2_i = DEFAULT_BETA1_I; /* Fixed point, inverted */
-+
-+ two_beta_i = (ec->beta2_i * Py_i) >> 15; /* Fixed point version, inverted */
-+ if (!two_beta_i)
-+ two_beta_i++;
-+
-+ /* Update Lu_i (Suppressed power estimate) */
-+ ec->Lu_i -= abs(get_cc_s(&ec->u_s, (1 << DEFAULT_SIGMA_LU_I) - 1 )) ;
-+ ec->Lu_i += abs(u);
-+
-+ /* eq. (10): update power estimate of the reference
-+ */
-+ ec->Ly_i -= abs(get_cc_s(&ec->y_s, (1 << DEFAULT_SIGMA_LY_I) - 1)) ;
-+ ec->Ly_i += abs(iref);
-+
-+ if (ec->Ly_i < DEFAULT_CUTOFF_I)
-+ ec->Ly_i = DEFAULT_CUTOFF_I;
-+
-+#if 0
-+ printf("Float: %e, Int: %e\n", ec->Ly_d, (ec->Ly_i >> DEFAULT_SIGMA_LY_I) * AMPL_SCALE_1);
-+#endif
-+
-+ if (ec->y_tilde_i > ec->max_y_tilde) {
-+ /* New highest y_tilde with full life */
-+ ec->max_y_tilde = ec->y_tilde_i;
-+ ec->max_y_tilde_pos = ec->N_d - 1;
-+ } else if (--ec->max_y_tilde_pos < 0) {
-+ /* Time to find new max y tilde... */
-+ ec->max_y_tilde = MAX16(ec->y_tilde_s.buf_d + ec->y_tilde_s.idx_d, ec->N_d, &ec->max_y_tilde_pos);
-+ }
-+
-+ if ((ec->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)) > ec->max_y_tilde)
-+ {
-+ ec->HCNTR_d = DEFAULT_HANGT;
-+ }
-+ else if (ec->HCNTR_d > (int)0)
-+ {
-+ ec->HCNTR_d--;
-+ }
-+
-+ /* update coefficients if no near-end speech and we have enough signal
-+ * to bother trying to update.
-+ */
-+ if (!ec->HCNTR_d && !(ec->i_d % DEFAULT_M) &&
-+ (ec->Lu_i > MIN_UPDATE_THRESH_I)) {
-+ // loop over all filter coefficients
-+ //
-+ for (k=0; k<ec->N_d; k++) {
-+
-+ // eq. (7): compute an expectation over M_d samples
-+ //
-+ int grad2;
-+ grad2 = CONVOLVE2(ec->u_s.buf_d + ec->u_s.idx_d,
-+ ec->y_s.buf_d + ec->y_s.idx_d + k, DEFAULT_M);
-+ // eq. (7): update the coefficient
-+ //
-+ ec->a_i[k] += grad2 / two_beta_i;
-+ ec->a_s[k] = ec->a_i[k] >> 16;
-+ }
-+ }
-+
-+ /* paragraph below eq. (15): if no near-end speech,
-+ // check for residual error suppression
-+ */
-+#ifndef NO_ECHO_SUPPRESSOR
-+#ifdef AGGRESSIVE_SUPPRESSOR
-+ if ((ec->HCNTR_d < AGGRESSIVE_HCNTR) && (ec->Ly_i > (ec->Lu_i << 1))) {
-+ u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I)) + 1);
-+ u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I)) + 1);
-+ }
-+#else
-+ if ((ec->HCNTR_d == 0) && ((ec->Ly_i/(ec->Lu_i + 1)) > DEFAULT_SUPPR_I)) {
-+ u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I + 2)) + 1);
-+ }
-+#endif
-+#endif
-+
-+#if 0
-+ if ((ec->HCNTR_d == 0) && ((ec->Lu_d/ec->Ly_d) < DEFAULT_SUPPR) &&
-+ (ec->Lu_d/ec->Ly_d > EC_MIN_DB_VALUE)) {
-+ suppr_factor = (10/(float)(SUPPR_FLOOR-SUPPR_CEIL))*log(ec->Lu_d/ec->Ly_d)
-+ - SUPPR_CEIL/(float)(SUPPR_FLOOR - SUPPR_CEIL);
-+
-+ u_suppr = pow(10.0,(suppr_factor)*RES_SUPR_FACTOR/10.0)*u_suppr;
-+
-+ }
-+#endif
-+ ec->i_d++;
-+ return u;
-+}
-+
-+static inline echo_can_state_t *echo_can_create(int len, int adaption_mode)
-+{
-+ echo_can_state_t *ec;
-+ int maxy;
-+ int maxu;
-+ maxy = len + DEFAULT_M;
-+ maxu = DEFAULT_M;
-+ if (maxy < (1 << DEFAULT_ALPHA_YT_I))
-+ maxy = (1 << DEFAULT_ALPHA_YT_I);
-+ if (maxy < (1 << DEFAULT_SIGMA_LY_I))
-+ maxy = (1 << DEFAULT_SIGMA_LY_I);
-+ if (maxu < (1 << DEFAULT_SIGMA_LU_I))
-+ maxu = (1 << DEFAULT_SIGMA_LU_I);
-+ ec = (echo_can_state_t *)MALLOC(sizeof(echo_can_state_t) +
-+ 4 + /* align */
-+ sizeof(int) * len + /* a_i */
-+ sizeof(short) * len + /* a_s */
-+ 2 * sizeof(short) * (maxy) + /* y_s */
-+ 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */
-+ 2 * sizeof(short) * (maxu) + /* u_s */
-+ 2 * sizeof(short) * len); /* y_tilde_s */
-+ if (ec) {
-+ memset(ec, 0, sizeof(echo_can_state_t) +
-+ 4 + /* align */
-+ sizeof(int) * len + /* a_i */
-+ sizeof(short) * len + /* a_s */
-+ 2 * sizeof(short) * (maxy) + /* y_s */
-+ 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */
-+ 2 * sizeof(short) * (maxu) + /* u_s */
-+ 2 * sizeof(short) * len); /* y_tilde_s */
-+ init_cc(ec, len, maxy, maxu);
-+ }
-+ return ec;
-+}
-+
-+static inline int echo_can_traintap(echo_can_state_t *ec, int pos, short val)
-+{
-+ /* Reset hang counter to avoid adjustments after
-+ initial forced training */
-+ ec->HCNTR_d = ec->N_d << 1;
-+ if (pos >= ec->N_d)
-+ return 1;
-+ ec->a_i[pos] = val << 17;
-+ ec->a_s[pos] = val << 1;
-+ if (++pos >= ec->N_d)
-+ return 1;
-+ return 0;
-+}
-+
-+#endif
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/mec3.h mISDN/drivers/isdn/hardware/mISDN/mec3.h
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/mec3.h 1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/mec3.h 2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,243 @@
-+/*
-+ * Mark's Third Echo Canceller
-+ *
-+ * Copyright (C) 2003, Digium, Inc.
-+ *
-+ * This program is free software and may be used
-+ * and distributed under the terms of the GNU General Public
-+ * License, incorporated herein by reference.
-+ *
-+ * Dedicated to the crew of the Columbia, STS-107 for their
-+ * bravery and courageous sacrifice for science.
-+ *
-+ */
-+
-+#ifndef _MARK3_ECHO_H
-+#define _MARK3_ECHO_H
-+
-+
-+
-+#ifdef __KERNEL__
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#define MALLOC(a) kmalloc((a), GFP_KERNEL)
-+#define FREE(a) kfree(a)
-+#else
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <stdint.h>
-+#include <string.h>
-+#include <math.h>
-+#define MALLOC(a) malloc(a)
-+#define FREE(a) free(a)
-+#endif
-+
-+/* Features */
-+
-+/*
-+ * DO_BACKUP -- Backup coefficients, and revert in the presense of double talk to try to prevent
-+ * them from diverging during the ramp-up before the DTD kicks in
-+ */
-+/* #define DO_BACKUP */
-+
-+#define STEP_SHIFT 2 /* Convergence rate higher = slower / better (as a shift) */
-+
-+#define SIGMA_REF_PWR 655 /* Keep denominator from being 0 */
-+
-+#define MIN_TX_ENERGY 256 /* Must have at least this much reference */
-+#define MIN_RX_ENERGY 32 /* Must have at least this much receive energy */
-+
-+#define MAX_ATTENUATION_SHIFT 6 /* Maximum amount of loss we care about */
-+#define MAX_BETA 1024
-+
-+#define SUPPR_SHIFT 4 /* Amount of loss at which we suppress audio */
-+
-+#define HANG_TIME 600 /* Hangover time */
-+
-+#define NTAPS 2048 /* Maximum number of echo can taps */
-+
-+#define BACKUP 256 /* Backup every this number of samples */
-+
-+#define POWER_OFFSET 5 /* Shift power by this amount to be sure we don't overflow the
-+ reference power. Higher = less likely to overflow, lower = more accurage */
-+
-+#include "arith.h"
-+
-+typedef struct {
-+ short buf[NTAPS * 2];
-+ short max;
-+ int maxexp;
-+} cbuf_s;
-+
-+typedef struct {
-+ short a_s[NTAPS]; /* Coefficients in shorts */
-+ int a_i[NTAPS]; /* Coefficients in ints*/
-+#ifdef DO_BACKUP
-+ int b_i[NTAPS]; /* Coefficients (backup1) */
-+ int c_i[NTAPS]; /* Coefficients (backup2) */
-+#endif
-+ cbuf_s ref; /* Reference excitation */
-+ cbuf_s sig; /* Signal (echo + near end + noise) */
-+ cbuf_s e; /* Error */
-+ int refpwr; /* Reference power */
-+ int taps; /* Number of taps */
-+ int tappwr; /* Power of taps */
-+ int hcntr; /* Hangtime counter */
-+ int pos; /* Position in curcular buffers */
-+ int backup; /* Backup timer */
-+} echo_can_state_t;
-+
-+static inline void echo_can_free(echo_can_state_t *ec)
-+{
-+ FREE(ec);
-+}
-+
-+static inline void buf_add(cbuf_s *b, short sample, int pos, int taps)
-+{
-+ /* Store and keep track of maxima */
-+ int x;
-+ b->buf[pos] = sample;
-+ b->buf[pos + taps] = sample;
-+ if (sample > b->max) {
-+ b->max = sample;
-+ b->maxexp = taps;
-+ } else {
-+ b->maxexp--;
-+ if (!b->maxexp) {
-+ b->max = 0;
-+ for (x=0;x<taps;x++)
-+ if (b->max < abs(b->buf[pos + x])) {
-+ b->max = abs(b->buf[pos + x]);
-+ b->maxexp = x + 1;
-+ }
-+ }
-+ }
-+}
-+
-+static inline short echo_can_update(echo_can_state_t *ec, short ref, short sig)
-+{
-+ int x;
-+ short u;
-+ int refpwr;
-+ int beta; /* Factor */
-+ int se; /* Simulated echo */
-+#ifdef DO_BACKUP
-+ if (!ec->backup) {
-+ /* Backup coefficients periodically */
-+ ec->backup = BACKUP;
-+ memcpy(ec->c_i,ec->b_i,sizeof(ec->c_i));
-+ memcpy(ec->b_i,ec->a_i,sizeof(ec->b_i));
-+ } else
-+ ec->backup--;
-+#endif
-+ /* Remove old samples from reference power calculation */
-+ ec->refpwr -= ((ec->ref.buf[ec->pos] * ec->ref.buf[ec->pos]) >> POWER_OFFSET);
-+
-+ /* Store signal and reference */
-+ buf_add(&ec->ref, ref, ec->pos, ec->taps);
-+ buf_add(&ec->sig, sig, ec->pos, ec->taps);
-+
-+ /* Add new reference power */
-+ ec->refpwr += ((ec->ref.buf[ec->pos] * ec->ref.buf[ec->pos]) >> POWER_OFFSET);
-+
-+
-+ /* Calculate simulated echo */
-+ se = CONVOLVE2(ec->a_s, ec->ref.buf + ec->pos, ec->taps);
-+ se >>= 15;
-+
-+ u = sig - se;
-+ if (ec->hcntr)
-+ ec->hcntr--;
-+
-+ /* Store error */
-+ buf_add(&ec->e, sig, ec->pos, ec->taps);
-+ if ((ec->ref.max > MIN_TX_ENERGY) &&
-+ (ec->sig.max > MIN_RX_ENERGY) &&
-+ (ec->e.max > (ec->ref.max >> MAX_ATTENUATION_SHIFT))) {
-+ /* We have sufficient energy */
-+ if (ec->sig.max < (ec->ref.max >> 1)) {
-+ /* No double talk */
-+ if (!ec->hcntr) {
-+ refpwr = ec->refpwr >> (16 - POWER_OFFSET);
-+ if (refpwr < SIGMA_REF_PWR)
-+ refpwr = SIGMA_REF_PWR;
-+ beta = (u << 16) / refpwr;
-+ beta >>= STEP_SHIFT;
-+ if (beta > MAX_BETA)
-+ beta = 0;
-+ if (beta < -MAX_BETA)
-+ beta = 0;
-+ /* Update coefficients */
-+ for (x=0;x<ec->taps;x++) {
-+ ec->a_i[x] += beta * ec->ref.buf[ec->pos + x];
-+ ec->a_s[x] = ec->a_i[x] >> 16;
-+ }
-+ }
-+ } else {
-+#ifdef DO_BACKUP
-+ if (!ec->hcntr) {
-+ /* Our double talk detector is turning on for the first time. Revert
-+ our coefficients, since we're probably well into the double talk by now */
-+ memcpy(ec->a_i, ec->c_i, sizeof(ec->a_i));
-+ for (x=0;x<ec->taps;x++) {
-+ ec->a_s[x] = ec->a_i[x] >> 16;
-+ }
-+ }
-+#endif
-+ /* Reset hang-time counter, and prevent backups */
-+ ec->hcntr = HANG_TIME;
-+#ifdef DO_BACKUP
-+ ec->backup = BACKUP;
-+#endif
-+ }
-+ }
-+#ifndef NO_ECHO__SUPPRESSOR
-+ if (ec->e.max < (ec->ref.max >> SUPPR_SHIFT)) {
-+ /* Suppress residual echo */
-+ u *= u;
-+ u >>= 16;
-+ }
-+#endif
-+ ec->pos--;
-+ if (ec->pos < 0)
-+ ec->pos = ec->taps-1;
-+ return u;
-+}
-+
-+static inline echo_can_state_t *echo_can_create(int taps, int adaption_mode)
-+{
-+ echo_can_state_t *ec;
-+ int x;
-+
-+ //taps = NTAPS;
-+ ec = MALLOC(sizeof(echo_can_state_t));
-+ if (ec) {
-+ memset(ec, 0, sizeof(echo_can_state_t));
-+ ec->taps = taps;
-+ ec->pos = ec->taps-1;
-+ for (x=0;x<31;x++) {
-+ if ((1 << x) >= ec->taps) {
-+ ec->tappwr = x;
-+ break;
-+ }
-+ }
-+ }
-+ return ec;
-+}
-+
-+static inline int echo_can_traintap(echo_can_state_t *ec, int pos, short val)
-+{
-+ /* Reset hang counter to avoid adjustments after
-+ initial forced training */
-+ ec->hcntr = ec->taps << 1;
-+ if (pos >= ec->taps)
-+ return 1;
-+ ec->a_i[pos] = val << 17;
-+ ec->a_s[pos] = val << 1;
-+ if (++pos >= ec->taps)
-+ return 1;
-+ return 0;
-+}
-+
-+
-+#endif
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/mec.h mISDN/drivers/isdn/hardware/mISDN/mec.h
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/mec.h 1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/mec.h 2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,308 @@
-+/*
-+ * Mark's Echo Canceller
-+ *
-+ * Mark Spencer <markster@linux-support.net>
-+ *
-+ * Simple, LMS Echo Canceller with double talk detection.
-+ * Partly based on the TI App note:
-+ * "Digital Voice Echo Canceller with a TMS 32020"
-+ *
-+ * Special additional thanks to:
-+ * Jim Dixon (Lambda Telecommunications)
-+ * Iman Ghobrial (Adtran, Inc.)
-+ *
-+ * Copyright (C) 2001, Linux Support Services, Inc.
-+ *
-+ * This program is free software and may be used and
-+ * distributed according to the terms of the GNU
-+ * General Public License, incorporated herein by
-+ * reference.
-+ *
-+ */
-+
-+#ifndef _MEC_H
-+#define _MEC_H
-+
-+/* You have to express the size of the echo canceller in taps as
-+ a power of 2 (6 = 64 taps, 7 = 128 taps, 8 = 256 taps) */
-+#define NUM_TAPS_POW2 6 /* Size of echo canceller in power of 2 (taps) */
-+#define NUM_TAPS (1 << NUM_TAPS_POW2) /* Actual number of taps */
-+#define TAP_MASK (NUM_TAPS-1)
-+
-+
-+#define SIGMA_LU_POW NUM_TAPS_POW2
-+#define SIGMA_LY_POW NUM_TAPS_POW2
-+#define SIGMA_YT_POW (NUM_TAPS_POW2 - 1)
-+#define SIGMA_ST_POW (NUM_TAPS_POW2 - 1)
-+
-+#define BETA_POW 8
-+
-+#define CUTOFF_S 4
-+
-+/* The higher you make this, the better the quality, but the more CPU time required */
-+#define MIN_QUALITY 100
-+
-+/* This optimization saves a lot of processor but may degrade quality */
-+#define OPTIMIZEDIV
-+
-+#if 0
-+/* This converges much more slowly but saves processor */
-+#define MIN_UPDATE 256
-+#define MIN_SKIP 8
-+#endif
-+
-+#define HANG_T 600 /* 600 samples, or 75ms */
-+
-+typedef struct mark_ec {
-+ /* Circular position */
-+ int cpos;
-+ short y[NUM_TAPS]; /* Last N samples (relative to cpos) transmitted */
-+ short y_abs[NUM_TAPS]; /* Last N samples (relative to cpos) transmitted (abs value) */
-+ short s[NUM_TAPS]; /* Last N samples (relative to cpos) received */
-+ short s_abs[NUM_TAPS]; /* Last N samples (relative to cpos) received (abs value) */
-+ short u[NUM_TAPS]; /* Last N samples (relative to cpos) with echo removed */
-+ short u_abs[NUM_TAPS]; /* Last N samples (relative to cpos) with echo removed */
-+
-+ int Ly; /* tx power */
-+ int Lu; /* Power of echo-cancelled output */
-+
-+ int Ty[NUM_TAPS]; /* Short term power estimate of transmit */
-+ int Ts; /* Short term power estimate of received signal */
-+
-+ int a[NUM_TAPS]; /* Tap weight coefficients (not relative) */
-+
-+ short sdc[NUM_TAPS]; /* Near end signal before High Pass Filter */
-+
-+ int samples; /* Sample count */
-+ int pass; /* Number of passes we've made */
-+
-+ int hangt;
-+
-+ int lastmax; /* Optimize maximum search */
-+ int maxTy; /* Maximum Ty */
-+} echo_can_state_t;
-+
-+#define INLINE inline
-+
-+#ifdef __KERNEL__
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#define MALLOC(a) kmalloc((a), GFP_KERNEL)
-+#define FREE(a) kfree((a))
-+#else
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <stdint.h>
-+#include <string.h>
-+#define MALLOC(a) malloc(a)
-+#define FREE(a) free(a)
-+#endif
-+
-+static INLINE echo_can_state_t *echo_can_create(int len, int adaption_mode)
-+{
-+ echo_can_state_t *ec;
-+ /* Uhm, we're only one length, sorry. */
-+ ec = MALLOC(sizeof(echo_can_state_t));
-+ if (ec)
-+ memset(ec, 0, sizeof(*ec));
-+ return ec;
-+}
-+
-+#define PASSPOS 32000
-+#undef PASSPOS
-+
-+static INLINE void echo_can_free(echo_can_state_t *ec)
-+{
-+ FREE(ec);
-+}
-+
-+static INLINE int16_t echo_can_update(echo_can_state_t *ec, int16_t tx, int16_t rx)
-+{
-+ /* Process a sample, where tx is the near end and rx is the far end + echo */
-+
-+ int suppr;
-+ int nsuppr;
-+ short rxabs, txabs;
-+ register int Lu;
-+ register int x;
-+ register int pos;
-+ register int r_hat; /* Estimated echo */
-+ int oldrxabs;
-+ int oldtxabs;
-+ int oldsupprabs;
-+ int supprabs;
-+#ifdef MIN_UPDATE
-+ int totalupd;
-+#endif
-+
-+ txabs = abs(tx);
-+ rxabs = abs(rx);
-+
-+ ec->pass++;
-+
-+ r_hat = 0;
-+
-+ /* Load next value */
-+ ec->y[ec->cpos] = tx;
-+
-+ /* Load next abs value */
-+ oldtxabs = ec->y_abs[ec->cpos];
-+ ec->y_abs[ec->cpos] = txabs;
-+
-+ /* Bring in receive value (near-end signal) */
-+ ec->sdc[ec->cpos] = rx;
-+
-+ /* Bring in receive value absolute value */
-+ oldrxabs = ec->s_abs[ec->cpos];
-+ ec->s_abs[ec->cpos] = rxabs;
-+
-+ Lu = ec->Lu | 1;
-+
-+#if 0
-+ /* Apply first order high pass filter (3 dB @ 160 Hz) */
-+ tx = ec->s[ec->cpos] = (1.0-DEFGAMMA) * ec->s[(ec->cpos - 1) & TAP_MASK] +
-+ 0.5 * (1.0-DEFGAMMA) * ( ec->sdc[(ec->cpos - 1) & TAP_MASK] - ec->sdc[(ec->cpos - 2) & TAP_MASK]);
-+#endif
-+
-+ /* Estimate echo */
-+ pos = ec->cpos;
-+ for (x=0;x<NUM_TAPS;x++) {
-+ r_hat += ec->a[x] * ec->y[pos];
-+ /* Go backwards in time and loop around circular buffer */
-+ pos = (pos - 1) & TAP_MASK;
-+ }
-+
-+ r_hat >>= 16;
-+
-+ if (ec->hangt > 0)
-+ ec->hangt--;
-+
-+ /* printf("rx: %F, rhat: %F\n", rx, r_hat); */
-+ /* Calculate suppressed amount */
-+ suppr = rx - r_hat;
-+
-+ if (ec->pass > NUM_TAPS) {
-+ /* Have to have enough taps to start with */
-+ if (ec->maxTy > ec->Ts) {
-+ /* There is no near-end speech detected */
-+ if (!ec->hangt) {
-+ /* We're not in the hang-time from the end of near-end speech */
-+ if ((ec->Ly > 1024) && ((ec->Ly / Lu) < MIN_QUALITY)) {
-+#ifdef OPTIMIZEDIV
-+ /* We both have enough signal on the transmit */
-+ nsuppr = (suppr << 18) / ec->Ly;
-+
-+ if (nsuppr > 32767)
-+ nsuppr = 32767;
-+ if (nsuppr < -32768)
-+ nsuppr = -32768;
-+
-+ nsuppr /= ec->Ly;
-+#else
-+ /* We both have enough signal on the transmit */
-+ nsuppr = (suppr << 16) / ec->Ly;
-+
-+ if (nsuppr > 32767)
-+ nsuppr = 32767;
-+ if (nsuppr < -32768)
-+ nsuppr = -32768;
-+
-+#endif
-+
-+ /* Update coefficients */
-+ pos = ec->cpos;
-+#ifdef MIN_UPDATE
-+ totalupd =0;
-+#endif
-+ for (x=0;x<NUM_TAPS;x++) {
-+ register int adj;
-+ adj = ec->y[pos] * nsuppr;
-+#ifndef OPTIMIZEDIV
-+ adj /= ec->Ly;
-+ adj >>= BETA_POW;
-+#else
-+ adj >>= BETA_POW + 2;
-+#endif
-+#ifdef PASSPOS
-+ if (ec->pass > PASSPOS)
-+ printf("tx: %d, old %d: %d, adj %d, nsuppr: %d, power: %d\n", tx, x, ec->a[x], adj, nsuppr, ec->Ly);
-+#endif
-+ ec->a[x] += adj;
-+#ifdef MIN_UPDATE
-+ totalupd += abs(adj);
-+#endif
-+ /* Go backwards in time and loop around circular buffer */
-+ pos = (pos - 1) & TAP_MASK;
-+ }
-+#ifdef MIN_UPDATE
-+ /* If we didn't update at least this much, delay for many more taps */
-+ if (totalupd < MIN_UPDATE) {
-+ ec->hangt += MIN_SKIP;
-+ }
-+#endif
-+ }
-+
-+ }
-+ } else
-+ /* Near end speech detected */
-+ ec->hangt = HANG_T;
-+ }
-+
-+ /* Save supression and absolute values */
-+ supprabs = abs(suppr);
-+ oldsupprabs = ec->u_abs[ec->cpos];
-+ ec->u[ec->cpos] = suppr;
-+ ec->u_abs[ec->cpos] = supprabs;
-+
-+ /* Update tx power */
-+ ec->Ly += (txabs >> SIGMA_LY_POW) - (oldtxabs >> SIGMA_LY_POW);
-+
-+ /* Update rx power */
-+ ec->Lu += (supprabs >> SIGMA_LU_POW) - (oldsupprabs >> SIGMA_LU_POW);
-+
-+ /* Short term power of tx */
-+ ec->Ty[ec->cpos] = ec->Ty[(ec->cpos - 1) & TAP_MASK] +
-+ ((txabs >> SIGMA_YT_POW ) - (oldtxabs >> SIGMA_YT_POW));
-+
-+ /* Keep track of highest */
-+ if (ec->lastmax == ec->cpos) {
-+ register int maxTy = 0;
-+ /* Have to loop through and find the new highest since our old highest expired */
-+ /* Estimate echo */
-+ pos = ec->cpos;
-+ for (x=0;x<NUM_TAPS;x++) {
-+ if (ec->Ty[pos] > maxTy)
-+ maxTy = ec->Ty[pos];
-+ /* Go backwards in time and loop around circular buffer */
-+ pos = (pos - 1) & TAP_MASK;
-+ }
-+ ec->maxTy = maxTy;
-+ } else {
-+ /* Just keep the highest */
-+ if (ec->Ty[ec->cpos] > ec->maxTy) {
-+ ec->maxTy = ec->Ty[ec->cpos];
-+ ec->lastmax = ec->cpos;
-+ }
-+ }
-+ ec->Ts += (rxabs >> SIGMA_ST_POW) - (oldrxabs >> SIGMA_ST_POW) ;
-+
-+ /* Increment position memory */
-+ ec->cpos = (ec->cpos + 1 ) & TAP_MASK;
-+
-+ return suppr;
-+}
-+
-+static inline int echo_can_traintap(echo_can_state_t *ec, int pos, short val)
-+{
-+ /* Reset hang counter to avoid adjustments after
-+ initial forced training */
-+ ec->hangt = NUM_TAPS << 1;
-+ if (pos >= NUM_TAPS)
-+ return 1;
-+ ec->a[pos] = val << 17;
-+ if (++pos >= NUM_TAPS)
-+ return 1;
-+ return 0;
-+}
-+
-+#endif
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/sedl_fax.c mISDN/drivers/isdn/hardware/mISDN/sedl_fax.c
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/sedl_fax.c 2004-08-27 21:27:40.000000000 +0200
-+++ mISDN/drivers/isdn/hardware/mISDN/sedl_fax.c 2005-12-02 09:57:08.000000000 +0100
-@@ -811,8 +811,8 @@
- return(err);
- }
-
-- printk(KERN_INFO "mISDN: sedlpci found adapter %s at %s\n",
-- (char *) ent->driver_data, pdev->slot_name);
-+/* printk(KERN_INFO "mISDN: sedlpci found adapter %s at %s\n",
-+ (char *) ent->driver_data, pdev->slot_name); */
-
- card->cfg = pci_resource_start(pdev, 0);
- card->irq = pdev->irq;
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/w6692.c mISDN/drivers/isdn/hardware/mISDN/w6692.c
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/w6692.c 2004-08-27 21:27:40.000000000 +0200
-+++ mISDN/drivers/isdn/hardware/mISDN/w6692.c 2005-12-02 09:57:08.000000000 +0100
-@@ -1502,8 +1502,8 @@
- return(err);
- }
-
-- printk(KERN_INFO "mISDN_w6692: found adapter %s at %s\n",
-- (char *) ent->driver_data, pdev->slot_name);
-+/* printk(KERN_INFO "mISDN_w6692: found adapter %s at %s\n",
-+ (char *) ent->driver_data, pdev->slot_name); */
-
- card->addr = pci_resource_start(pdev, 1);
- card->irq = pdev->irq;
-diff -u -r -P /tmp/mISDN/include/linux/mISDNif.h mISDN/include/linux/mISDNif.h
---- /tmp/mISDN/include/linux/mISDNif.h 2005-02-05 11:18:17.000000000 +0100
-+++ mISDN/include/linux/mISDNif.h 2005-12-02 09:57:08.000000000 +0100
-@@ -173,6 +173,8 @@
- #define BF_DISABLE 0x2315
- #define BF_ACCEPT 0x2316
- #define BF_REJECT 0x2317
-+#define ECHOCAN_ON 0x2318
-+#define ECHOCAN_OFF 0x2319
- #define HW_POTS_ON 0x1001
- #define HW_POTS_OFF 0x1002
- #define HW_POTS_SETMICVOL 0x1100
-diff -u -r -P /tmp/mISDN/Makefile mISDN/Makefile
---- /tmp/mISDN/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/Makefile 2005-12-05 19:08:57.000000000 +0100
-@@ -0,0 +1,54 @@
-+BASEDIR=$(shell pwd)
-+
-+
-+INSTALL_PREFIX := /
-+export INSTALL_PREFIX
-+
-+#PATH to linux source/headers
-+#LINUX=/usr/src/linux
-+LINUX=/lib/modules/$(shell uname -r)/build
-+
-+MISDNDIR=$(BASEDIR)
-+MISDN_SRC=$(MISDNDIR)/drivers/isdn/hardware/mISDN
-+
-+########################################
-+# USER CONFIGS END
-+########################################
-+
-+CONFIGS+=CONFIG_MISDN_DRV=m CONFIG_MISDN_DSP=m
-+CONFIGS+=CONFIG_MISDN_HFCMULTI=m
-+CONFIGS+=CONFIG_MISDN_HFCPCI=m
-+CONFIGS+=CONFIG_MISDN_HFCUSB=m
-+#CONFIGS+=CONFIG_MISDN_AVM_FRITZ=m
-+
-+
-+MINCLUDES+=-I$(MISDNDIR)/include
-+
-+all:
-+ @echo
-+ @echo "Makeing mISDN"
-+ @echo "============="
-+ @echo
-+ cp $(MISDNDIR)/drivers/isdn/hardware/mISDN/Makefile.v2.6 $(MISDNDIR)/drivers/isdn/hardware/mISDN/Makefile
-+
-+ cd $(LINUX) ; make SUBDIRS=$(MISDN_SRC) modules $(CONFIGS) LINUXINCLUDE="$(MINCLUDES) -I$(LINUX)/include"
-+
-+
-+
-+install: all
-+ cd $(LINUX) ; make SUBDIRS=$(MISDN_SRC) modules_install
-+ cp $(MISDNDIR)/include/linux/*.h $(INSTALL_PREFIX)/usr/include/linux/
-+ depmod
-+
-+.PHONY: install all clean
-+
-+clean:
-+ rm -rf drivers/isdn/hardware/mISDN/*.o
-+ rm -rf drivers/isdn/hardware/mISDN/*.ko
-+ rm -rf *~
-+ find . -iname ".*.cmd" -exec rm -rf {} \;
-+ find . -iname ".*.d" -exec rm -rf {} \;
-+ find . -iname "*.mod.c" -exec rm -rf {} \;
-+ find . -iname "*.mod" -exec rm -rf {} \;
-+
-+