diff options
Diffstat (limited to 'drivers')
30 files changed, 1149 insertions, 943 deletions
diff --git a/drivers/dahdi/Kbuild b/drivers/dahdi/Kbuild index b25ad29..0157d83 100644 --- a/drivers/dahdi/Kbuild +++ b/drivers/dahdi/Kbuild @@ -1,7 +1,3 @@ -ifdef ECHO_CAN_NAME - ECHO_CAN_CFLAGS := -DECHO_CAN_FROMENV -DECHO_CAN_$(ECHO_CAN_NAME) -endif - obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI) += dahdi.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DUMMY) += dahdi_dummy.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC) += dahdi_dynamic.o @@ -24,8 +20,13 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_PCIRADIO) += pciradio.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPP) += xpp/ +obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_JPAH) += dahdi_echocan_jpah.o +obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_STEVE) += dahdi_echocan_sec.o +obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_STEVE2) += dahdi_echocan_sec2.o +obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_KB1) += dahdi_echocan_kb1.o +obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_MG2) += dahdi_echocan_mg2.o + CFLAGS_MODULE += -I$(src) -EXTRA_CFLAGS += $(ECHO_CAN_CFLAGS) ifndef HOTPLUG_FIRMWARE ifneq (,$(filter y m,$(CONFIG_FW_LOADER))) @@ -45,23 +46,25 @@ endif dahdi-objs := dahdi-base.o +dahdi_echocan_hpec-objs := hpec/dahdi_echocan_hpec.o +CFLAGS_dahdi_echocan_hpec.o := -I$(src)/hpec + ifeq ($(ARCH),i386) ifneq ($(wildcard $(src)/hpec/hpec_x86_32.o_shipped),) HPEC_PRESENT=yes -dahdi-objs += hpec/hpec_x86_32.o +dahdi_echocan_hpec-objs += hpec/hpec_x86_32.o endif endif ifeq ($(ARCH),x86_64) ifneq ($(wildcard $(src)/hpec/hpec_x86_64.o_shipped),) HPEC_PRESENT=yes -dahdi-objs += hpec/hpec_x86_64.o +dahdi_echocan_hpec-objs += hpec/hpec_x86_64.o endif endif ifeq ($(HPEC_PRESENT),yes) -EXTRA_CFLAGS += -DECHO_CAN_HPEC -I$(src)/hpec -$(obj)/dahdi-base.o: $(src)/hpec/hpec_dahdi.h $(src)/hpec/hpec_user.h +obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_HPEC) += dahdi_echocan_hpec.o endif $(obj)/pciradio.o: $(obj)/radfw.h diff --git a/drivers/dahdi/Kconfig b/drivers/dahdi/Kconfig index 4402e58..22a448a 100644 --- a/drivers/dahdi/Kconfig +++ b/drivers/dahdi/Kconfig @@ -14,7 +14,60 @@ menuconfig DAHDI If unsure, say Y. -if DAHDI +config DAHDI_ECHOCAN + tristate "DADHI Echo Cancelers (software)" + depends on DAHDI + default DAHDI + +config DAHDI_ECHOCAN_MG2 + tristate "DADHI MG2 Echo Canceler" + depends on DAHDI_ECHOCAN + default DAHDI_ECHOCAN + ---help--- + To compile this driver as a module, choose M here: the + module will be called dahdi_echocancel_mg2. + + If unsure, say Y. + +config DAHDI_ECHOCAN_KB1 + tristate "DADHI KB1 Echo Canceler" + depends on DAHDI_ECHOCAN + default DAHDI_ECHOCAN + ---help--- + To compile this driver as a module, choose M here: the + module will be called dahdi_echocancel_kb1. + + If unsure, say Y. + +config DAHDI_ECHOCAN_SEC + tristate "DADHI SEC Echo Canceler" + depends on DAHDI_ECHOCAN + default DAHDI_ECHOCAN + ---help--- + To compile this driver as a module, choose M here: the + module will be called dahdi_echocancel_sec. + + If unsure, say Y. + +config DAHDI_ECHOCAN_SEC2 + tristate "DADHI SEC2 Echo Canceler" + depends on DAHDI_ECHOCAN + default DAHDI_ECHOCAN + ---help--- + To compile this driver as a module, choose M here: the + module will be called dahdi_echocancel_sec2. + + If unsure, say Y. + +config DAHDI_ECHOCAN_HPEC + tristate "DADHI HPEC Echo Canceler" + depends on DAHDI_ECHOCAN + default DAHDI_ECHOCAN + ---help--- + To compile this driver as a module, choose M here: the + module will be called dahdi_echocancel_hpec. + + If unsure, say Y. config DAHDI_WCTDM tristate "Digium Wildcard TDM400P Support" @@ -48,6 +101,7 @@ config DAHDI_WCT4XXP config DAHDI_TRANSCODE tristate "DAHDI transcoding support" + depends on DAHDI default DAHDI ---help--- DAHDI transcoding infrastructure. @@ -59,7 +113,7 @@ config DAHDI_TRANSCODE config DAHDI_WCTC4XXP tristate "Digium Wildcard TC400B Support" - depends on DAHDI && DAHDI_TRANSCODE && PCI + depends on DAHDI_TRANSCODE && PCI default DAHDI ---help--- This driver provides support for the Digium Wildcard TC400B. @@ -210,5 +264,3 @@ config DAHDI_WCTE11XP If unsure, say Y. source "drivers/dahdi/xpp/Kconfig" - -endif # DAHDI diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c index fa733de..8b13454 100644 --- a/drivers/dahdi/dahdi-base.c +++ b/drivers/dahdi/dahdi-base.c @@ -47,6 +47,7 @@ #include <linux/ctype.h> #include <linux/kmod.h> #include <linux/moduleparam.h> +#include <linux/list.h> #ifdef CONFIG_DAHDI_NET #include <linux/netdevice.h> @@ -61,6 +62,8 @@ #include <asm/atomic.h> +#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args) + #ifndef CONFIG_OLD_HDLC_API #define NEW_HDLC_INTERFACE #endif @@ -83,6 +86,8 @@ #include <dahdi/kernel.h> #include <dahdi/user.h> +#include "hpec/hpec_user.h" + /* Get helper arithmetic */ #include "arith.h" #if defined(CONFIG_DAHDI_MMX) || defined(ECHO_CAN_FP) @@ -141,13 +146,15 @@ EXPORT_SYMBOL(dahdi_alarm_channel); EXPORT_SYMBOL(dahdi_register_chardev); EXPORT_SYMBOL(dahdi_unregister_chardev); +EXPORT_SYMBOL(dahdi_register_echocan); +EXPORT_SYMBOL(dahdi_unregister_echocan); + +EXPORT_SYMBOL(dahdi_set_hpec_ioctl); + #ifdef CONFIG_PROC_FS static struct proc_dir_entry *proc_entries[DAHDI_MAX_SPANS]; #endif -/* udev necessary data structures. Yeah! */ -#ifdef CONFIG_DAHDI_UDEV - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) #define CLASS_DEV_CREATE(class, devt, device, name) \ class_device_create(class, NULL, devt, device, name) @@ -166,8 +173,6 @@ static struct class_simple *dahdi_class = NULL; #define class_device_destroy(a, b) class_simple_device_remove(b) #endif -#endif /* CONFIG_DAHDI_UDEV */ - static int deftaps = 64; static int debug; @@ -329,24 +334,69 @@ static rwlock_t chan_lock = RW_LOCK_UNLOCKED; static struct dahdi_zone *tone_zones[DAHDI_TONE_ZONE_MAX]; -#define NUM_SIGS 10 - - -/* Echo cancellation */ -#if defined(ECHO_CAN_HPEC) -#include "hpec/hpec_dahdi.h" -#elif defined(ECHO_CAN_STEVE) -#include "sec.h" -#elif defined(ECHO_CAN_STEVE2) -#include "sec-2.h" -#elif defined(ECHO_CAN_KB1) -#include "kb1ec.h" -#elif defined(ECHO_CAN_MG2) -#include "mg2ec.h" -#elif defined(ECHO_CAN_JP1) -#include "jpah.h" +#define NUM_SIGS 10 + +#ifdef DEFINE_RWLOCK +static DEFINE_RWLOCK(echocan_list_lock); +#else +static rwlock_t echocan_list_lock = RW_LOCK_UNLOCKED; #endif +LIST_HEAD(echocan_list); + +struct echocan { + const struct dahdi_echocan *ec; + struct module *owner; + struct list_head list; +}; + +int dahdi_register_echocan(const struct dahdi_echocan *ec) +{ + struct echocan *cur; + + write_lock(&echocan_list_lock); + + /* make sure it isn't already registered */ + list_for_each_entry(cur, &echocan_list, list) { + if (cur->ec == ec) { + write_unlock(&echocan_list_lock); + return -EPERM; + } + } + + if (!(cur = kmalloc(sizeof(*cur), GFP_KERNEL))) { + write_unlock(&echocan_list_lock); + return -ENOMEM; + } + + memset(cur, 0, sizeof(*cur)); + + cur->ec = ec; + INIT_LIST_HEAD(&cur->list); + + list_add_tail(&cur->list, &echocan_list); + + write_unlock(&echocan_list_lock); + + return 0; +} + +void dahdi_unregister_echocan(const struct dahdi_echocan *ec) +{ + struct echocan *cur, *next; + + write_lock(&echocan_list_lock); + + list_for_each_entry_safe(cur, next, &echocan_list, list) { + if (cur->ec == ec) { + list_del(&cur->list); + break; + } + } + + write_unlock(&echocan_list_lock); +} + static inline void rotate_sums(void) { /* Rotate where we sum and so forth */ @@ -361,26 +411,26 @@ static inline void rotate_sums(void) /* return quiescent (idle) signalling states, for the various signalling types */ static int dahdi_q_sig(struct dahdi_chan *chan) { -int x; - -static unsigned int in_sig[NUM_SIGS][2] = { - { DAHDI_SIG_NONE, 0}, - { DAHDI_SIG_EM, 0 | (DAHDI_ABIT << 8)}, - { DAHDI_SIG_FXSLS,DAHDI_BBIT | (DAHDI_BBIT << 8)}, - { DAHDI_SIG_FXSGS,DAHDI_ABIT | DAHDI_BBIT | ((DAHDI_ABIT | DAHDI_BBIT) << 8)}, - { DAHDI_SIG_FXSKS,DAHDI_BBIT | DAHDI_BBIT | ((DAHDI_ABIT | DAHDI_BBIT) << 8)}, - { DAHDI_SIG_FXOLS,0 | (DAHDI_ABIT << 8)}, - { DAHDI_SIG_FXOGS,DAHDI_BBIT | ((DAHDI_ABIT | DAHDI_BBIT) << 8)}, - { DAHDI_SIG_FXOKS,0 | (DAHDI_ABIT << 8)}, - { DAHDI_SIG_SF, 0}, - { DAHDI_SIG_EM_E1, DAHDI_DBIT | ((DAHDI_ABIT | DAHDI_DBIT) << 8) }, + int x; + + static unsigned int in_sig[NUM_SIGS][2] = { + { DAHDI_SIG_NONE, 0}, + { DAHDI_SIG_EM, 0 | (DAHDI_ABIT << 8)}, + { DAHDI_SIG_FXSLS,DAHDI_BBIT | (DAHDI_BBIT << 8)}, + { DAHDI_SIG_FXSGS,DAHDI_ABIT | DAHDI_BBIT | ((DAHDI_ABIT | DAHDI_BBIT) << 8)}, + { DAHDI_SIG_FXSKS,DAHDI_BBIT | DAHDI_BBIT | ((DAHDI_ABIT | DAHDI_BBIT) << 8)}, + { DAHDI_SIG_FXOLS,0 | (DAHDI_ABIT << 8)}, + { DAHDI_SIG_FXOGS,DAHDI_BBIT | ((DAHDI_ABIT | DAHDI_BBIT) << 8)}, + { DAHDI_SIG_FXOKS,0 | (DAHDI_ABIT << 8)}, + { DAHDI_SIG_SF, 0}, + { DAHDI_SIG_EM_E1, DAHDI_DBIT | ((DAHDI_ABIT | DAHDI_DBIT) << 8) }, } ; - + /* must have span to begin with */ if (!chan->span) return(-1); - /* if RBS does not apply, return error */ + /* if RBS does not apply, return error */ if (!(chan->span->flags & DAHDI_FLAG_RBS) || - !chan->span->rbsbits) return(-1); + !chan->span->rbsbits) return(-1); if (chan->sig == DAHDI_SIG_CAS) return chan->idlebits; for (x=0;x<NUM_SIGS;x++) { @@ -540,15 +590,20 @@ static int dahdi_proc_read(char *page, char **start, off_t off, int count, int * len += sprintf(page + len, "Master "); } } - if ((chans[x]->flags & DAHDI_FLAG_OPEN)) { + if (test_bit(DAHDI_FLAGBIT_OPEN, &chans[x]->flags)) { len += sprintf(page + len, "(In use) "); } #ifdef OPTIMIZE_CHANMUTE - if ((chans[x]->chanmute)) { + if (chans[x]->chanmute) { len += sprintf(page + len, "(no pcm) "); } #endif len += fill_alarm_string(page + len, count - len, chans[x]->chan_alarms); + + if (chans[x]->ec_factory) { + len += sprintf(page + len, " (EC: %s) ", chans[x]->ec_factory->name); + } + len += sprintf(page + len, "\n"); } if (len <= off) { /* If everything printed so far is before beginning of request */ @@ -930,11 +985,68 @@ static inline int hw_echocancel_off(struct dahdi_chan *chan) return ret; } +static const struct dahdi_echocan *find_echocan(const char *name) +{ + struct echocan *cur; + char name_upper[strlen(name) + 1]; + char *c; + const char *d; + char modname_buf[128] = "dahdi_echocan_"; + unsigned int tried_once = 0; + int res; + + for (c = name_upper, d = name; *d; c++, d++) { + *c = toupper(*d); + } + + *c = '\0'; + +retry: + read_lock(&echocan_list_lock); + + list_for_each_entry(cur, &echocan_list, list) { + if (!strcmp(name_upper, cur->ec->name)) { + if ((res = try_module_get(cur->owner))) { + read_unlock(&echocan_list_lock); + return cur->ec; + } else { + read_unlock(&echocan_list_lock); + return NULL; + } + } + } + + read_unlock(&echocan_list_lock); + + if (tried_once) { + return NULL; + } + + /* couldn't find it, let's try to load it */ + + for (c = &modname_buf[strlen(modname_buf)], d = name; *d; c++, d++) { + *c = tolower(*d); + } + + request_module(modname_buf); + + tried_once = 1; + + /* and try one more time */ + goto retry; +} + +static void release_echocan(const struct dahdi_echocan *ec) +{ + module_put(ec->owner); +} + static void close_channel(struct dahdi_chan *chan) { unsigned long flags; void *rxgain = NULL; - struct echo_can_state *ec = NULL; + struct echo_can_state *ec_state; + const struct dahdi_echocan *ec_current; int oldconf; short *readchunkpreec; #ifdef CONFIG_DAHDI_PPP @@ -949,8 +1061,10 @@ static void close_channel(struct dahdi_chan *chan) ppp = chan->ppp; chan->ppp = NULL; #endif - ec = chan->ec; - chan->ec = NULL; + ec_state = chan->ec_state; + chan->ec_state = NULL; + ec_current = chan->ec_current; + chan->ec_current = NULL; readchunkpreec = chan->readchunkpreec; chan->readchunkpreec = NULL; chan->curtone = NULL; @@ -1007,14 +1121,17 @@ static void close_channel(struct dahdi_chan *chan) if (chan->span && chan->span->dacs && oldconf) chan->span->dacs(chan, NULL); + if (ec_state) { + ec_current->echo_can_free(ec_state); + release_echocan(ec_current); + } + spin_unlock_irqrestore(&chan->lock, flags); hw_echocancel_off(chan); if (rxgain) kfree(rxgain); - if (ec) - echo_can_free(ec); if (readchunkpreec) kfree(readchunkpreec); @@ -1074,7 +1191,7 @@ static int dahdi_register_tone_zone(int num, struct dahdi_zone *zone) write_unlock(&zone_lock); if (!res) - printk(KERN_INFO "Registered tone zone %d (%s)\n", num, zone->name); + module_printk(KERN_INFO, "Registered tone zone %d (%s)\n", num, zone->name); return res; } @@ -1098,7 +1215,7 @@ static int start_tone(struct dahdi_chan *chan, int tone) if (__warnonce) { __warnonce = 0; /* The tonezones are loaded by ztcfg based on /etc/dahdi.conf. */ - printk(KERN_WARNING "DAHDI: Cannot start tones until tone zone is loaded.\n"); + module_printk(KERN_WARNING, "DAHDI: Cannot start tones until tone zone is loaded.\n"); } /* Note that no tone zone exists at the moment */ res = -ENODATA; @@ -1274,7 +1391,7 @@ static int dahdi_chan_reg(struct dahdi_chan *chan) } write_unlock_irqrestore(&chan_lock, flags); if (x >= DAHDI_MAX_CHANNELS) - printk(KERN_ERR "No more channels available\n"); + module_printk(KERN_ERR, "No more channels available\n"); return res; } @@ -1305,15 +1422,15 @@ static int dahdi_net_open(hdlc_device *hdlc) int res; #endif if (!ms) { - printk("dahdi_net_open: nothing??\n"); + module_printk(KERN_NOTICE, "dahdi_net_open: nothing??\n"); return -EINVAL; } - if (ms->flags & DAHDI_FLAG_OPEN) { - printk("%s is already open!\n", ms->name); + if (test_bit(DAHDI_FLAGBIT_OPEN, &ms->flags)) { + module_printk(KERN_NOTICE, "%s is already open!\n", ms->name); return -EBUSY; } if (!(ms->flags & DAHDI_FLAG_NETDEV)) { - printk("%s is not a net device!\n", ms->name); + module_printk(KERN_NOTICE, "%s is not a net device!\n", ms->name); return -EINVAL; } ms->txbufpolicy = DAHDI_POLICY_IMMEDIATE; @@ -1330,7 +1447,7 @@ static int dahdi_net_open(hdlc_device *hdlc) netif_start_queue(ztchan_to_dev(ms)); #ifdef CONFIG_DAHDI_DEBUG - printk("DAHDINET: Opened channel %d name %s\n", ms->channo, ms->name); + module_printk(KERN_NOTICE, "DAHDINET: Opened channel %d name %s\n", ms->channo, ms->name); #endif return 0; } @@ -1366,19 +1483,19 @@ static void dahdi_net_close(hdlc_device *hdlc) struct dahdi_chan *ms = hdlc_to_ztchan(hdlc); if (!ms) { #ifdef NEW_HDLC_INTERFACE - printk("dahdi_net_stop: nothing??\n"); + module_printk(KERN_NOTICE, "dahdi_net_stop: nothing??\n"); return 0; #else - printk("dahdi_net_close: nothing??\n"); + module_printk(KERN_NOTICE, "dahdi_net_close: nothing??\n"); return; #endif } if (!(ms->flags & DAHDI_FLAG_NETDEV)) { #ifdef NEW_HDLC_INTERFACE - printk("dahdi_net_stop: %s is not a net device!\n", ms->name); + module_printk(KERN_NOTICE, "dahdi_net_stop: %s is not a net device!\n", ms->name); return 0; #else - printk("dahdi_net_close: %s is not a net device!\n", ms->name); + module_printk(KERN_NOTICE, "dahdi_net_close: %s is not a net device!\n", ms->name); return; #endif } @@ -1456,7 +1573,7 @@ static int dahdi_xmit(hdlc_device *hdlc, struct sk_buff *skb) /* See if we have any buffers */ spin_lock_irqsave(&ss->lock, flags); if (skb->len > ss->blocksize - 2) { - printk(KERN_ERR "dahdi_xmit(%s): skb is too large (%d > %d)\n", dev->name, skb->len, ss->blocksize -2); + module_printk(KERN_ERR, "dahdi_xmit(%s): skb is too large (%d > %d)\n", dev->name, skb->len, ss->blocksize -2); stats->tx_dropped++; retval = 0; } else if (ss->inwritebuf >= 0) { @@ -1494,7 +1611,7 @@ static int dahdi_xmit(hdlc_device *hdlc, struct sk_buff *skb) stats->tx_packets++; stats->tx_bytes += ss->writen[oldbuf]; #ifdef CONFIG_DAHDI_DEBUG - printk("Buffered %d bytes to go out in buffer %d\n", ss->writen[oldbuf], oldbuf); + module_printk(KERN_NOTICE, "Buffered %d bytes to go out in buffer %d\n", ss->writen[oldbuf], oldbuf); for (x=0;x<ss->writen[oldbuf];x++) printk("%02x ", ss->writebuf[oldbuf][x]); printk("\n"); @@ -1540,11 +1657,11 @@ static int dahdi_ppp_xmit(struct ppp_channel *ppp, struct sk_buff *skb) /* See if we have any buffers */ spin_lock_irqsave(&ss->lock, flags); - if (!(ss->flags & DAHDI_FLAG_OPEN)) { - printk("Can't transmit on closed channel\n"); + if (!(test_bit(DAHDI_FLAGBIT_OPEN, &ss->flags))) { + module_printk(KERN_ERR, "Can't transmit on closed channel\n"); retval = 1; } else if (skb->len > ss->blocksize - 4) { - printk(KERN_ERR "dahdi_ppp_xmit(%s): skb is too large (%d > %d)\n", ss->name, skb->len, ss->blocksize -2); + module_printk(KERN_ERR, "dahdi_ppp_xmit(%s): skb is too large (%d > %d)\n", ss->name, skb->len, ss->blocksize -2); retval = 1; } else if (ss->inwritebuf >= 0) { /* We have a place to put this packet */ @@ -1595,7 +1712,7 @@ static int dahdi_ppp_xmit(struct ppp_channel *ppp, struct sk_buff *skb) ss->outwritebuf = oldbuf; } #ifdef CONFIG_DAHDI_DEBUG - printk("Buffered %d bytes (skblen = %d) to go out in buffer %d\n", ss->writen[oldbuf], skb->len, oldbuf); + module_printk(KERN_NOTICE, "Buffered %d bytes (skblen = %d) to go out in buffer %d\n", ss->writen[oldbuf], skb->len, oldbuf); for (x=0;x<ss->writen[oldbuf];x++) printk("%02x ", ss->writebuf[oldbuf][x]); printk("\n"); @@ -1644,7 +1761,7 @@ static void dahdi_chan_unreg(struct dahdi_chan *chan) } #ifdef CONFIG_DAHDI_PPP if (chan->ppp) { - printk("HUH??? PPP still attached??\n"); + module_printk(KERN_NOTICE, "HUH??? PPP still attached??\n"); } #endif maxchans = 0; @@ -1717,8 +1834,8 @@ static ssize_t dahdi_chan_read(struct file *file, char *usrbuf, size_t count, in int x; if (amnt > chan->readn[res]) myamnt = chan->readn[res]; - printk("dahdi_chan_read(unit: %d, inwritebuf: %d, outwritebuf: %d amnt: %d\n", - unit, chan->inwritebuf, chan->outwritebuf, myamnt); + module_printk(KERN_NOTICE, "dahdi_chan_read(unit: %d, inwritebuf: %d, outwritebuf: %d amnt: %d\n", + unit, chan->inwritebuf, chan->outwritebuf, myamnt); printk("\t("); for (x = 0; x < myamnt; x++) printk((x ? " %02x" : "%02x"), (unsigned char)usrbuf[x]); printk(")\n"); } @@ -1820,14 +1937,14 @@ static ssize_t dahdi_chan_write(struct file *file, const char *usrbuf, size_t co } #ifdef CONFIG_DAHDI_DEBUG - printk("dahdi_chan_write(unit: %d, res: %d, outwritebuf: %d amnt: %d\n", - unit, chan->res, chan->outwritebuf, amnt); + module_printk(KERN_NOTICE, "dahdi_chan_write(unit: %d, res: %d, outwritebuf: %d amnt: %d\n", + unit, chan->res, chan->outwritebuf, amnt); #endif #if 0 if ((unit == 24) || (unit == 48) || (unit == 16) || (unit == 47)) { int x; - printk("dahdi_chan_write/in(unit: %d, res: %d, outwritebuf: %d amnt: %d, txdisable: %d)\n", - unit, res, chan->outwritebuf, amnt, chan->txdisable); + module_printk(KERN_NOTICE, "dahdi_chan_write/in(unit: %d, res: %d, outwritebuf: %d amnt: %d, txdisable: %d)\n", + unit, res, chan->outwritebuf, amnt, chan->txdisable); printk("\t("); for (x = 0; x < amnt; x++) printk((x ? " %02x" : "%02x"), (unsigned char)usrbuf[x]); printk(")\n"); } @@ -1960,15 +2077,15 @@ who cares what the sig bits are as long as they are stable */ /* if no span, return doing nothing */ if (!chan->span) return; if (!chan->span->flags & DAHDI_FLAG_RBS) { - printk("dahdi_rbs: Tried to set RBS hook state on non-RBS channel %s\n", chan->name); + module_printk(KERN_NOTICE, "dahdi_rbs: Tried to set RBS hook state on non-RBS channel %s\n", chan->name); return; } if ((txsig > 3) || (txsig < 0)) { - printk("dahdi_rbs: Tried to set RBS hook state %d (> 3) on channel %s\n", txsig, chan->name); + module_printk(KERN_NOTICE, "dahdi_rbs: Tried to set RBS hook state %d (> 3) on channel %s\n", txsig, chan->name); return; } if (!chan->span->rbsbits && !chan->span->hooksig) { - printk("dahdi_rbs: Tried to set RBS hook state %d on channel %s while span %s lacks rbsbits or hooksig function\n", + module_printk(KERN_NOTICE, "dahdi_rbs: Tried to set RBS hook state %d on channel %s while span %s lacks rbsbits or hooksig function\n", txsig, chan->name, chan->span->name); return; } @@ -2007,7 +2124,7 @@ who cares what the sig bits are as long as they are stable */ for (x=0;x<NUM_SIGS;x++) { if (outs[x][0] == chan->sig) { #ifdef CONFIG_DAHDI_DEBUG - printk("Setting bits to %d for channel %s state %d in %d signalling\n", outs[x][txsig + 1], chan->name, txsig, chan->sig); + module_printk(KERN_NOTICE, "Setting bits to %d for channel %s state %d in %d signalling\n", outs[x][txsig + 1], chan->name, txsig, chan->sig); #endif chan->txhooksig = txsig; chan->txsig = outs[x][txsig+1]; @@ -2017,7 +2134,7 @@ who cares what the sig bits are as long as they are stable */ } } } - printk("dahdi_rbs: Don't know RBS signalling type %d on channel %s\n", chan->sig, chan->name); + module_printk(KERN_NOTICE, "dahdi_rbs: Don't know RBS signalling type %d on channel %s\n", chan->sig, chan->name); } static int dahdi_cas_setbits(struct dahdi_chan *chan, int bits) @@ -2028,7 +2145,7 @@ static int dahdi_cas_setbits(struct dahdi_chan *chan, int bits) chan->txsig = bits; chan->span->rbsbits(chan, bits); } else { - printk("Huh? CAS setbits, but no RBS bits function\n"); + module_printk(KERN_NOTICE, "Huh? CAS setbits, but no RBS bits function\n"); } return 0; } @@ -2102,7 +2219,9 @@ static int initialize_channel(struct dahdi_chan *chan) int res; unsigned long flags; void *rxgain=NULL; - struct echo_can_state *ec=NULL; + struct echo_can_state *ec_state; + const struct dahdi_echocan *ec_current; + if ((res = dahdi_reallocbufs(chan, DAHDI_DEFAULT_BLOCKSIZE, DAHDI_DEFAULT_NUM_BUFS))) return res; @@ -2111,9 +2230,10 @@ static int initialize_channel(struct dahdi_chan *chan) chan->rxbufpolicy = DAHDI_POLICY_IMMEDIATE; chan->txbufpolicy = DAHDI_POLICY_IMMEDIATE; - /* Free up the echo canceller if there is one */ - ec = chan->ec; - chan->ec = NULL; + ec_state = chan->ec_state; + chan->ec_state = NULL; + ec_current = chan->ec_current; + chan->ec_current = NULL; chan->echocancel = 0; chan->echostate = ECHO_STATE_IDLE; chan->echolastupdate = 0; @@ -2210,15 +2330,20 @@ static int initialize_channel(struct dahdi_chan *chan) chan->ringcadence[1] = DAHDI_RINGOFFTIME; } + if (ec_state) { + ec_current->echo_can_free(ec_state); + release_echocan(ec_current); + } + spin_unlock_irqrestore(&chan->lock, flags); + set_tone_zone(chan, -1); hw_echocancel_off(chan); if (rxgain) kfree(rxgain); - if (ec) - echo_can_free(ec); + return 0; } @@ -2263,7 +2388,7 @@ static int dahdi_timer_release(struct inode *inode, struct file *file) } spin_unlock_irqrestore(&zaptimerlock, flags); if (!cur) { - printk("DAHDI Timer: Not on list??\n"); + module_printk(KERN_NOTICE, "Timer: Not on list??\n"); return 0; } kfree(t); @@ -2456,7 +2581,7 @@ static ssize_t dahdi_read(struct file *file, char *usrbuf, size_t count, loff_t if (unit == 255) { chan = file->private_data; if (!chan) { - printk("No pseudo channel structure to read?\n"); + module_printk(KERN_NOTICE, "No pseudo channel structure to read?\n"); return -EINVAL; } return dahdi_chan_read(file, usrbuf, count, chan->channo); @@ -2487,7 +2612,7 @@ static ssize_t dahdi_write(struct file *file, const char *usrbuf, size_t count, if (unit == 255) { chan = file->private_data; if (!chan) { - printk("No pseudo channel structure to read?\n"); + module_printk(KERN_NOTICE, "No pseudo channel structure to read?\n"); return -EINVAL; } return dahdi_chan_write(file, usrbuf, count, chan->channo); @@ -2544,7 +2669,7 @@ static int ioctl_load_zone(unsigned long data) data += sizeof(th); if ((th.count < 0) || (th.count > MAX_TONES)) { - printk("Too many tones included\n"); + module_printk(KERN_NOTICE, "Too many tones included\n"); return -EINVAL; } @@ -2579,7 +2704,7 @@ static int ioctl_load_zone(unsigned long data) if (space < sizeof(*t)) { kfree(slab); - printk("Insufficient tone zone space\n"); + module_printk(KERN_NOTICE, "Insufficient tone zone space\n"); return -EINVAL; } @@ -2603,7 +2728,7 @@ static int ioctl_load_zone(unsigned long data) /* Make sure the "next" one is sane */ if ((next[x] >= th.count) || (next[x] < 0)) { - printk("Invalid 'next' pointer: %d\n", next[x]); + module_printk(KERN_NOTICE, "Invalid 'next' pointer: %d\n", next[x]); kfree(slab); return -EINVAL; } @@ -2628,7 +2753,7 @@ static int ioctl_load_zone(unsigned long data) td.tone -= DAHDI_TONE_MFR2_REV_BASE; t = &z->mfr2_rev[td.tone]; } else { - printk("Invalid tone (%d) defined\n", td.tone); + module_printk(KERN_NOTICE, "Invalid tone (%d) defined\n", td.tone); kfree(slab); return -EINVAL; } @@ -2720,7 +2845,7 @@ struct dahdi_tone *dahdi_mf_tone(const struct dahdi_chan *chan, char digit, int if (__warnonce) { __warnonce = 0; /* The tonezones are loaded by ztcfg based on /etc/dahdi.conf. */ - printk(KERN_WARNING "DAHDI: Cannot get dtmf tone until tone zone is loaded.\n"); + module_printk(KERN_WARNING, "Cannot get dtmf tone until tone zone is loaded.\n"); } return NULL; } @@ -2937,7 +3062,7 @@ static int dahdi_release(struct inode *inode, struct file *file) res = dahdi_specchan_release(inode, file, chan->channo); dahdi_free_pseudo(chan); } else { - printk("Pseudo release and no private data??\n"); + module_printk(KERN_NOTICE, "Pseudo release and no private data??\n"); res = 0; } return res; @@ -2991,7 +3116,7 @@ void dahdi_alarm_notify(struct dahdi_span *span) for (x=1; x<maxspans; x++) { if (spans[x] && !spans[x]->alarms && (spans[x]->flags & DAHDI_FLAG_RUNNING)) { if(master != spans[x]) - printk("DAHDI: Master changed to %s\n", spans[x]->name); + module_printk(KERN_NOTICE, "Master changed to %s\n", spans[x]->name); master = spans[x]; break; } @@ -3336,39 +3461,39 @@ static int dahdi_common_ioctl(struct inode *node, struct file *file, unsigned in /* release it. */ spin_unlock_irqrestore(&chans[j]->lock, flags); - printk(KERN_INFO "Dump of DAHDI Channel %d (%s,%d,%d):\n\n",j, + module_printk(KERN_INFO, "Dump of DAHDI Channel %d (%s,%d,%d):\n\n",j, mychan->name,mychan->channo,mychan->chanpos); - printk(KERN_INFO "flags: %x hex, writechunk: %08lx, readchunk: %08lx\n", + module_printk(KERN_INFO, "flags: %x hex, writechunk: %08lx, readchunk: %08lx\n", (unsigned int) mychan->flags, (long) mychan->writechunk, (long) mychan->readchunk); - printk(KERN_INFO "rxgain: %08lx, txgain: %08lx, gainalloc: %d\n", + module_printk(KERN_INFO, "rxgain: %08lx, txgain: %08lx, gainalloc: %d\n", (long) mychan->rxgain, (long)mychan->txgain, mychan->gainalloc); - printk(KERN_INFO "span: %08lx, sig: %x hex, sigcap: %x hex\n", + module_printk(KERN_INFO, "span: %08lx, sig: %x hex, sigcap: %x hex\n", (long)mychan->span, mychan->sig, mychan->sigcap); - printk(KERN_INFO "inreadbuf: %d, outreadbuf: %d, inwritebuf: %d, outwritebuf: %d\n", + module_printk(KERN_INFO, "inreadbuf: %d, outreadbuf: %d, inwritebuf: %d, outwritebuf: %d\n", mychan->inreadbuf, mychan->outreadbuf, mychan->inwritebuf, mychan->outwritebuf); - printk(KERN_INFO "blocksize: %d, numbufs: %d, txbufpolicy: %d, txbufpolicy: %d\n", + module_printk(KERN_INFO, "blocksize: %d, numbufs: %d, txbufpolicy: %d, txbufpolicy: %d\n", mychan->blocksize, mychan->numbufs, mychan->txbufpolicy, mychan->rxbufpolicy); - printk(KERN_INFO "txdisable: %d, rxdisable: %d, iomask: %d\n", + module_printk(KERN_INFO, "txdisable: %d, rxdisable: %d, iomask: %d\n", mychan->txdisable, mychan->rxdisable, mychan->iomask); - printk(KERN_INFO "curzone: %08lx, tonezone: %d, curtone: %08lx, tonep: %d\n", + module_printk(KERN_INFO, "curzone: %08lx, tonezone: %d, curtone: %08lx, tonep: %d\n", (long) mychan->curzone, mychan->tonezone, (long) mychan->curtone, mychan->tonep); - printk(KERN_INFO "digitmode: %d, txdialbuf: %s, dialing: %d, aftdialtimer: %d, cadpos. %d\n", + module_printk(KERN_INFO, "digitmode: %d, txdialbuf: %s, dialing: %d, aftdialtimer: %d, cadpos. %d\n", mychan->digitmode, mychan->txdialbuf, mychan->dialing, mychan->afterdialingtimer, mychan->cadencepos); - printk(KERN_INFO "confna: %d, confn: %d, confmode: %d, confmute: %d\n", + module_printk(KERN_INFO, "confna: %d, confn: %d, confmode: %d, confmute: %d\n", mychan->confna, mychan->_confn, mychan->confmode, mychan->confmute); - printk(KERN_INFO "ec: %08lx, echocancel: %d, deflaw: %d, xlaw: %08lx\n", - (long) mychan->ec, mychan->echocancel, mychan->deflaw, (long) mychan->xlaw); - printk(KERN_INFO "echostate: %02x, echotimer: %d, echolastupdate: %d\n", + module_printk(KERN_INFO, "ec: %08lx, echocancel: %d, deflaw: %d, xlaw: %08lx\n", + (long) mychan->ec_state, mychan->echocancel, mychan->deflaw, (long) mychan->xlaw); + module_printk(KERN_INFO, "echostate: %02x, echotimer: %d, echolastupdate: %d\n", (int) mychan->echostate, mychan->echotimer, mychan->echolastupdate); - printk(KERN_INFO "itimer: %d, otimer: %d, ringdebtimer: %d\n\n", + module_printk(KERN_INFO, "itimer: %d, otimer: %d, ringdebtimer: %d\n\n", mychan->itimer, mychan->otimer, mychan->ringdebtimer); #if 0 - if (mychan->ec) { + if (mychan->ec_state) { int x; /* Dump the echo canceller parameters */ - for (x=0;x<mychan->ec->taps;x++) { - printk(KERN_INFO "tap %d: %d\n", x, mychan->ec->fir_taps[x]); + for (x=0;x<mychan->ec_state->taps;x++) { + module_printk(KERN_INFO, "tap %d: %d\n", x, mychan->ec_state->fir_taps[x]); } } #endif @@ -3387,6 +3512,13 @@ void dahdi_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data)) dahdi_dynamic_ioctl = func; } +static int (*dahdi_hpec_ioctl)(unsigned int cmd, unsigned long data); + +void dahdi_set_hpec_ioctl(int (*func)(unsigned int cmd, unsigned long data)) +{ + dahdi_hpec_ioctl = func; +} + static void recalc_slaves(struct dahdi_chan *chan) { int x; @@ -3397,15 +3529,15 @@ static void recalc_slaves(struct dahdi_chan *chan) return; #ifdef CONFIG_DAHDI_DEBUG - printk("Recalculating slaves on %s\n", chan->name); + module_printk(KERN_NOTICE, "Recalculating slaves on %s\n", chan->name); #endif /* Link all slaves appropriately */ for (x=chan->chanpos;x<chan->span->channels;x++) if (chan->span->chans[x].master == chan) { #ifdef CONFIG_DAHDI_DEBUG - printk("Channel %s, slave to %s, last is %s, its next will be %d\n", - chan->span->chans[x].name, chan->name, last->name, x); + module_printk(KERN_NOTICE, "Channel %s, slave to %s, last is %s, its next will be %d\n", + chan->span->chans[x].name, chan->name, last->name, x); #endif last->nextslave = x; last = &chan->span->chans[x]; @@ -3413,7 +3545,7 @@ static void recalc_slaves(struct dahdi_chan *chan) /* Terminate list */ last->nextslave = 0; #ifdef CONFIG_DAHDI_DEBUG - printk("Done Recalculating slaves on %s (last is %s)\n", chan->name, last->name); + module_printk(KERN_NOTICE, "Done Recalculating slaves on %s (last is %s)\n", chan->name, last->name); #endif } @@ -3481,6 +3613,34 @@ static int dahdi_ctl_ioctl(struct inode *inode, struct file *file, unsigned int res = spans[j]->shutdown(spans[j]); spans[j]->flags &= ~DAHDI_FLAG_RUNNING; return 0; + case DAHDI_ATTACH_ECHOCAN: + { + struct dahdi_attach_echocan ae; + const struct dahdi_echocan *new = NULL, *old; + + if (copy_from_user(&ae, (struct dahdi_attach_echocan *) data, sizeof(ae))) { + return -EFAULT; + } + + VALID_CHANNEL(ae.chan); + + if (ae.echocan[0]) { + if (!(new = find_echocan(ae.echocan))) { + return -EINVAL; + } + } + + spin_lock_irqsave(&chans[ae.chan]->lock, flags); + old = chans[ae.chan]->ec_factory; + chans[ae.chan]->ec_factory = new; + spin_unlock_irqrestore(&chans[ae.chan]->lock, flags); + + if (old) { + release_echocan(old); + } + + break; + } case DAHDI_CHANCONFIG: { struct dahdi_chanconfig ch; @@ -3510,7 +3670,7 @@ static int dahdi_ctl_ioctl(struct inode *inode, struct file *file, unsigned int if (chans[ch.chan]->flags & DAHDI_FLAG_NETDEV) { if (ztchan_to_dev(chans[ch.chan])->flags & IFF_UP) { spin_unlock_irqrestore(&chans[ch.chan]->lock, flags); - printk(KERN_WARNING "Can't switch HDLC net mode on channel %s, since current interface is up\n", chans[ch.chan]->name); + module_printk(KERN_WARNING, "Can't switch HDLC net mode on channel %s, since current interface is up\n", chans[ch.chan]->name); return -EBUSY; } spin_unlock_irqrestore(&chans[ch.chan]->lock, flags); @@ -3523,9 +3683,9 @@ static int dahdi_ctl_ioctl(struct inode *inode, struct file *file, unsigned int } #else if (ch.sigtype == DAHDI_SIG_HDLCNET) { - spin_unlock_irqrestore(&chans[ch.chan]->lock, flags); - printk(KERN_WARNING "DAHDI networking not supported by this build.\n"); - return -ENOSYS; + spin_unlock_irqrestore(&chans[ch.chan]->lock, flags); + module_printk(KERN_WARNING, "DAHDI networking not supported by this build.\n"); + return -ENOSYS; } #endif sigcap = chans[ch.chan]->sigcap; @@ -3535,15 +3695,17 @@ static int dahdi_ctl_ioctl(struct inode *inode, struct file *file, unsigned int sigcap |= (DAHDI_SIG_HDLCRAW | DAHDI_SIG_HDLCFCS | DAHDI_SIG_HDLCNET | DAHDI_SIG_DACS); if ((sigcap & ch.sigtype) != ch.sigtype) - res = -EINVAL; + res = -EINVAL; if (!res && chans[ch.chan]->span->chanconfig) res = chans[ch.chan]->span->chanconfig(chans[ch.chan], ch.sigtype); + if (chans[ch.chan]->master) { /* Clear the master channel */ recalc_slaves(chans[ch.chan]->master); chans[ch.chan]->nextslave = 0; } + if (!res) { chans[ch.chan]->sig = ch.sigtype; if (chans[ch.chan]->sig == DAHDI_SIG_CAS) @@ -3579,12 +3741,13 @@ static int dahdi_ctl_ioctl(struct inode *inode, struct file *file, unsigned int chans[ch.chan]->confna = ch.idlebits; if (chans[ch.chan]->span && chans[ch.chan]->span->dacs && - chans[ch.idlebits] && - chans[ch.chan]->span && - (chans[ch.chan]->span->dacs == chans[ch.idlebits]->span->dacs)) + chans[ch.idlebits] && + chans[ch.chan]->span && + (chans[ch.chan]->span->dacs == chans[ch.idlebits]->span->dacs)) chans[ch.chan]->span->dacs(chans[ch.chan], chans[ch.idlebits]); - } else if (chans[ch.chan]->span && chans[ch.chan]->span->dacs) + } else if (chans[ch.chan]->span && chans[ch.chan]->span->dacs) { chans[ch.chan]->span->dacs(chans[ch.chan], NULL); + } chans[ch.chan]->master = newmaster; /* Note new slave if we are not our own master */ if (newmaster != chans[ch.chan]) { @@ -3594,8 +3757,9 @@ static int dahdi_ctl_ioctl(struct inode *inode, struct file *file, unsigned int chans[ch.chan]->flags &= ~DAHDI_FLAG_FCS; chans[ch.chan]->flags &= ~DAHDI_FLAG_HDLC; chans[ch.chan]->flags |= DAHDI_FLAG_NOSTDTXRX; - } else + } else { chans[ch.chan]->flags &= ~DAHDI_FLAG_NOSTDTXRX; + } if ((ch.sigtype & DAHDI_SIG_MTP2) == DAHDI_SIG_MTP2) chans[ch.chan]->flags |= DAHDI_FLAG_MTP2; @@ -3604,12 +3768,13 @@ static int dahdi_ctl_ioctl(struct inode *inode, struct file *file, unsigned int } #ifdef CONFIG_DAHDI_NET if (!res && - (newmaster == chans[ch.chan]) && - (chans[ch.chan]->sig == DAHDI_SIG_HDLCNET)) { + (newmaster == chans[ch.chan]) && + (chans[ch.chan]->sig == DAHDI_SIG_HDLCNET)) { chans[ch.chan]->hdlcnetdev = dahdi_hdlc_alloc(); if (chans[ch.chan]->hdlcnetdev) { /* struct hdlc_device *hdlc = chans[ch.chan]->hdlcnetdev; struct net_device *d = hdlc_to_dev(hdlc); mmm...get it right later --byg */ + chans[ch.chan]->hdlcnetdev->netdev = alloc_hdlcdev(chans[ch.chan]->hdlcnetdev); if (chans[ch.chan]->hdlcnetdev->netdev) { chans[ch.chan]->hdlcnetdev->chan = chans[ch.chan]; @@ -3628,13 +3793,13 @@ static int dahdi_ctl_ioctl(struct inode *inode, struct file *file, unsigned int res = dahdi_register_hdlc_device(chans[ch.chan]->hdlcnetdev->netdev, ch.netdev_name); spin_lock_irqsave(&chans[ch.chan]->lock, flags); } else { - printk("Unable to allocate hdlc: *shrug*\n"); + module_printk(KERN_NOTICE, "Unable to allocate hdlc: *shrug*\n"); res = -1; } if (!res) chans[ch.chan]->flags |= DAHDI_FLAG_NETDEV; } else { - printk("Unable to allocate netdev: out of memory\n"); + module_printk(KERN_NOTICE, "Unable to allocate netdev: out of memory\n"); res = -1; } } @@ -3642,7 +3807,7 @@ static int dahdi_ctl_ioctl(struct inode *inode, struct file *file, unsigned int if ((chans[ch.chan]->sig == DAHDI_SIG_HDLCNET) && (chans[ch.chan] == newmaster) && !(chans[ch.chan]->flags & DAHDI_FLAG_NETDEV)) - printk("Unable to register HDLC device for channel %s\n", chans[ch.chan]->name); + module_printk(KERN_NOTICE, "Unable to register HDLC device for channel %s\n", chans[ch.chan]->name); if (!res) { /* Setup default law */ chans[ch.chan]->deflaw = ch.deflaw; @@ -3654,13 +3819,15 @@ static int dahdi_ctl_ioctl(struct inode *inode, struct file *file, unsigned int /* And hangup */ dahdi_hangup(chans[ch.chan]); y = dahdi_q_sig(chans[ch.chan]) & 0xff; - if (y >= 0) chans[ch.chan]->rxsig = (unsigned char)y; + if (y >= 0) + chans[ch.chan]->rxsig = (unsigned char) y; chans[ch.chan]->rxhooksig = DAHDI_RXSIG_INITIAL; } #ifdef CONFIG_DAHDI_DEBUG - printk("Configured channel %s, flags %04x, sig %04x\n", chans[ch.chan]->name, chans[ch.chan]->flags, chans[ch.chan]->sig); + module_printk(KERN_NOTICE, "Configured channel %s, flags %04x, sig %04x\n", chans[ch.chan]->name, chans[ch.chan]->flags, chans[ch.chan]->sig); #endif spin_unlock_irqrestore(&chans[ch.chan]->lock, flags); + return res; } case DAHDI_SFCONFIG: @@ -3765,10 +3932,27 @@ static int dahdi_ctl_ioctl(struct inode *inode, struct file *file, unsigned int case DAHDI_GETVERSION: { struct dahdi_versioninfo vi; + struct echocan *cur; + size_t space = sizeof(vi.echo_canceller) - 1; memset(&vi, 0, sizeof(vi)); dahdi_copy_string(vi.version, DAHDI_VERSION, sizeof(vi.version)); - echo_can_identify(vi.echo_canceller, sizeof(vi.echo_canceller) - 1); + read_lock(&echocan_list_lock); + list_for_each_entry(cur, &echocan_list, list) { + strncat(vi.echo_canceller + strlen(vi.echo_canceller), cur->ec->name, space); + space -= strlen(cur->ec->name); + if (space < 1) { + break; + } + if (cur->list.next && (cur->list.next != &echocan_list)) { + strncat(vi.echo_canceller + strlen(vi.echo_canceller), ", ", space); + space -= 2; + if (space < 1) { + break; + } + } + } + read_unlock(&echocan_list_lock); if (copy_to_user((struct dahdi_versioninfo *) data, &vi, sizeof(vi))) return -EFAULT; break; @@ -3811,7 +3995,7 @@ static int dahdi_ctl_ioctl(struct inode *inode, struct file *file, unsigned int spin_lock_irqsave(&spans[maint.spanno]->lock, flags); break; default: - printk("DAHDI: Unknown maintenance event: %d\n", maint.command); + module_printk(KERN_NOTICE, "Unknown maintenance event: %d\n", maint.command); } dahdi_alarm_notify(spans[maint.spanno]); /* process alarm-related events */ spin_unlock_irqrestore(&spans[maint.spanno]->lock, flags); @@ -3819,19 +4003,24 @@ static int dahdi_ctl_ioctl(struct inode *inode, struct file *file, unsigned int } case DAHDI_DYNAMIC_CREATE: case DAHDI_DYNAMIC_DESTROY: - if (dahdi_dynamic_ioctl) + if (dahdi_dynamic_ioctl) { return dahdi_dynamic_ioctl(cmd, data); - else { + } else { request_module("dahdi_dynamic"); if (dahdi_dynamic_ioctl) return dahdi_dynamic_ioctl(cmd, data); } return -ENOSYS; -#if defined(ECHO_CAN_HPEC) case DAHDI_EC_LICENSE_CHALLENGE: case DAHDI_EC_LICENSE_RESPONSE: - return hpec_license_ioctl(cmd, data); -#endif /* defined(ECHO_CAN_HPEC) */ + if (dahdi_hpec_ioctl) { + return dahdi_hpec_ioctl(cmd, data); + } else { + request_module("dahdi_echocan_hpec"); + if (dahdi_hpec_ioctl) + return dahdi_hpec_ioctl(cmd, data); + } + return -ENOSYS; default: return dahdi_common_ioctl(inode, file, cmd, data, 0); } @@ -3861,7 +4050,7 @@ static int ioctl_dahdi_dial(struct dahdi_chan *chan, unsigned long data) if (!chan->curzone) { spin_unlock_irqrestore(&chan->lock, flags); /* The tone zones are loaded by ztcfg from /etc/dahdi.conf */ - printk(KERN_WARNING "DAHDI: Cannot dial until a tone zone is loaded.\n"); + module_printk(KERN_WARNING, "Cannot dial until a tone zone is loaded.\n"); return -ENODATA; } switch (tdo->op) { @@ -4296,24 +4485,23 @@ static int dahdi_chanandpseudo_ioctl(struct inode *inode, struct file *file, uns if (!chans[k]) continue; /* skip if not in this conf */ if (chans[k]->confna != i) continue; - if (!c) printk("Conf #%d:\n",i); + if (!c) module_printk(KERN_NOTICE, "Conf #%d:\n",i); c = 1; - printk("chan %d, mode %x\n", - k,chans[k]->confmode); + module_printk(KERN_NOTICE, "chan %d, mode %x\n", k,chans[k]->confmode); } rv = 0; for(k = 1; k <= DAHDI_MAX_CONF; k++) { if (conf_links[k].dst == i) { - if (!c) printk("Conf #%d:\n",i); + if (!c) module_printk(KERN_NOTICE, "Conf #%d:\n",i); c = 1; - if (!rv) printk("Snooping on:\n"); + if (!rv) module_printk(KERN_NOTICE, "Snooping on:\n"); rv = 1; - printk("conf %d\n",conf_links[k].src); + module_printk(KERN_NOTICE, "conf %d\n",conf_links[k].src); } } - if (c) printk("\n"); + if (c) module_printk(KERN_NOTICE, "\n"); } break; case DAHDI_CHANNO: /* get channel number of stream */ @@ -4413,7 +4601,8 @@ static void do_ppp_calls(unsigned long data) static int ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, void *data) { - struct echo_can_state *ec = NULL, *tec; + struct echo_can_state *ec = NULL, *ec_state; + const struct dahdi_echocan *ec_current; struct dahdi_echocanparam *params; int ret; unsigned long flags; @@ -4424,16 +4613,20 @@ static int ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams if (ecp->tap_length == 0) { /* disable mode, don't need to inspect params */ spin_lock_irqsave(&chan->lock, flags); - tec = chan->ec; - chan->ec = NULL; + ec_state = chan->ec_state; + chan->ec_state = NULL; + ec_current = chan->ec_current; + chan->ec_current = NULL; chan->echocancel = 0; chan->echostate = ECHO_STATE_IDLE; chan->echolastupdate = 0; chan->echotimer = 0; spin_unlock_irqrestore(&chan->lock, flags); + if (ec_state) { + ec_current->echo_can_free(ec_state); + release_echocan(ec_current); + } hw_echocancel_off(chan); - if (tec) - echo_can_free(tec); return 0; } @@ -4457,13 +4650,16 @@ static int ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams } spin_lock_irqsave(&chan->lock, flags); - tec = chan->ec; - chan->ec = NULL; + ec_state = chan->ec_state; + chan->ec_state = NULL; + ec_current = chan->ec_current; + chan->ec_current = NULL; spin_unlock_irqrestore(&chan->lock, flags); + if (ec_state) { + ec_current->echo_can_free(ec_state); + release_echocan(ec_current); + } - if (tec) - echo_can_free(tec); - ret = -ENODEV; /* attempt to use the span's echo canceler; fall back to built-in @@ -4475,7 +4671,9 @@ static int ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams ret = chan->span->echocan(chan, ecp->tap_length); } - if (ret == -ENODEV) { + if ((ret == -ENODEV) && chan->ec_factory) { + const struct dahdi_echocan *ec_current; + switch (ecp->tap_length) { case 32: case 64: @@ -4488,12 +4686,27 @@ static int ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams ecp->tap_length = deftaps; } - if ((ret = echo_can_create(ecp, params, &ec))) + /* try to get another reference to the module providing + this channel's echo canceler */ + if (!try_module_get(chan->ec_factory->owner)) { + module_printk(KERN_ERR, "Cannot get a reference to the '%s' echo canceler\n", chan->ec_factory->name); goto exit_with_free; + } + + /* got the reference, copy the pointer and use it for making + an echo canceler instance if possible */ + ec_current = chan->ec_current; + + if ((ret = ec_current->echo_can_create(ecp, params, &ec))) { + release_echocan(ec_current); + + goto exit_with_free; + } spin_lock_irqsave(&chan->lock, flags); chan->echocancel = ecp->tap_length; - chan->ec = ec; + chan->ec_current = ec_current; + chan->ec_state = ec; chan->echostate = ECHO_STATE_IDLE; chan->echolastupdate = 0; chan->echotimer = 0; @@ -4504,6 +4717,7 @@ static int ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams exit_with_free: kfree(params); + return ret; } @@ -4515,7 +4729,6 @@ static int dahdi_chan_ioctl(struct inode *inode, struct file *file, unsigned int int ret; int oldconf; void *rxgain=NULL; - struct echo_can_state *ec; if (!chan) return -ENOSYS; @@ -4553,6 +4766,9 @@ static int dahdi_chan_ioctl(struct inode *inode, struct file *file, unsigned int /* Coming out of audio mode, also clear all conferencing and gain related info as well as echo canceller */ + struct echo_can_state *ec_state; + const struct dahdi_echocan *ec_current; + spin_lock_irqsave(&chan->lock, flags); chan->flags &= ~DAHDI_FLAG_AUDIO; /* save old conf number, if any */ @@ -4567,8 +4783,10 @@ static int dahdi_chan_ioctl(struct inode *inode, struct file *file, unsigned int memset(chan->conflast, 0, sizeof(chan->conflast)); memset(chan->conflast1, 0, sizeof(chan->conflast1)); memset(chan->conflast2, 0, sizeof(chan->conflast2)); - ec = chan->ec; - chan->ec = NULL; + ec_state = chan->ec_state; + chan->ec_state = NULL; + ec_current = chan->ec_current; + chan->ec_current = NULL; /* release conference resource, if any to release */ reset_conf(chan); if (chan->gainalloc && chan->rxgain) @@ -4579,15 +4797,18 @@ static int dahdi_chan_ioctl(struct inode *inode, struct file *file, unsigned int chan->rxgain = defgain; chan->txgain = defgain; chan->gainalloc = 0; - /* Disable any native echo cancellation as well */ spin_unlock_irqrestore(&chan->lock, flags); + if (ec_state) { + ec_current->echo_can_free(ec_state); + release_echocan(ec_current); + } + + /* Disable any native echo cancellation as well */ hw_echocancel_off(chan); if (rxgain) kfree(rxgain); - if (ec) - echo_can_free(ec); if (oldconf) dahdi_check_conf(oldconf); } break; @@ -4620,8 +4841,8 @@ static int dahdi_chan_ioctl(struct inode *inode, struct file *file, unsigned int chan->ppp = NULL; return ret; } - tec = chan->ec; - chan->ec = NULL; + tec = chan->ec_state; + chan->ec_state = NULL; chan->echocancel = 0; chan->echostate = ECHO_STATE_IDLE; chan->echolastupdate = 0; @@ -4637,7 +4858,7 @@ static int dahdi_chan_ioctl(struct inode *inode, struct file *file, unsigned int hw_echocancel_off(chan); if (tec) - echo_can_free(tec); + chan->ec->echo_can_free(tec); } else return -ENOMEM; } @@ -4653,7 +4874,7 @@ static int dahdi_chan_ioctl(struct inode *inode, struct file *file, unsigned int } } #else - printk("DAHDI: DAHDI PPP support not compiled in\n"); + module_printk(KERN_NOTICE, "PPP support not compiled in\n"); return -ENOSYS; #endif break; @@ -4708,7 +4929,7 @@ static int dahdi_chan_ioctl(struct inode *inode, struct file *file, unsigned int if ((j < 0) || (j >= DAHDI_MAX_PRETRAINING)) return -EINVAL; j <<= 3; - if (chan->ec) { + if (chan->ec_state) { /* Start pretraining stage */ chan->echostate = ECHO_STATE_PRETRAINING; chan->echotimer = j; @@ -4774,7 +4995,7 @@ static int dahdi_chan_ioctl(struct inode *inode, struct file *file, unsigned int spin_lock_irqsave(&chan->lock, flags); if (!chan->curzone) { spin_unlock_irqrestore(&chan->lock, flags); - printk(KERN_WARNING "DAHDI: Cannot start tone until a tone zone is loaded.\n"); + module_printk(KERN_WARNING, "Cannot start tone until a tone zone is loaded.\n"); return -ENODATA; } if (chan->txstate != DAHDI_TXSTATE_ONHOOK) { @@ -4866,7 +5087,7 @@ static int dahdi_prechan_ioctl(struct inode *inode, struct file *file, unsigned int res; if (chan) { - printk("Huh? Prechan already has private data??\n"); + module_printk(KERN_NOTICE, "Huh? Prechan already has private data??\n"); } switch(cmd) { case DAHDI_SPECIFY: @@ -4919,7 +5140,7 @@ static int dahdi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (unit == 255) { chan = file->private_data; if (!chan) { - printk("No pseudo channel structure to read?\n"); + module_printk(KERN_NOTICE, "No pseudo channel structure to read?\n"); return -EINVAL; } return dahdi_chanandpseudo_ioctl(inode, file, cmd, data, chan->channo); @@ -4937,12 +5158,12 @@ int dahdi_register(struct dahdi_span *span, int prefmaster) if (!span) return -EINVAL; if (span->flags & DAHDI_FLAG_REGISTERED) { - printk(KERN_ERR "Span %s already appears to be registered\n", span->name); + module_printk(KERN_ERR, "Span %s already appears to be registered\n", span->name); return -EBUSY; } for (x=1;x<maxspans;x++) if (spans[x] == span) { - printk(KERN_ERR "Span %s already in list\n", span->name); + module_printk(KERN_ERR, "Span %s already in list\n", span->name); return -EBUSY; } for (x=1;x<DAHDI_MAX_SPANS;x++) @@ -4953,19 +5174,19 @@ int dahdi_register(struct dahdi_span *span, int prefmaster) if (maxspans < x + 1) maxspans = x + 1; } else { - printk(KERN_ERR "Too many DAHDI spans registered\n"); + module_printk(KERN_ERR, "Too many DAHDI spans registered\n"); return -EBUSY; } span->flags |= DAHDI_FLAG_REGISTERED; span->spanno = x; spin_lock_init(&span->lock); if (!span->deflaw) { - printk("DAHDI: Span %s didn't specify default law. Assuming mulaw, please fix driver!\n", span->name); + module_printk(KERN_NOTICE, "Span %s didn't specify default law. Assuming mulaw, please fix driver!\n", span->name); span->deflaw = DAHDI_LAW_MULAW; } if (span->echocan && span->echocan_with_params) { - printk("DAHDI: Span %s implements both echocan and echocan_with_params functions, preserving only echocan_with_params, please fix driver!\n", span->name); + module_printk(KERN_NOTICE, "Span %s implements both echocan and echocan_with_params functions, preserving only echocan_with_params, please fix driver!\n", span->name); span->echocan = NULL; } @@ -4979,7 +5200,6 @@ int dahdi_register(struct dahdi_span *span, int prefmaster) proc_entries[span->spanno] = create_proc_read_entry(tempfile, 0444, NULL , dahdi_proc_read, (int *)(long)span->spanno); #endif -#ifdef CONFIG_DAHDI_UDEV for (x = 0; x < span->channels; x++) { char chan_name[50]; if (span->chans[x].channo < 250) { @@ -4987,14 +5207,13 @@ int dahdi_register(struct dahdi_span *span, int prefmaster) CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, span->chans[x].channo), NULL, chan_name); } } -#endif /* CONFIG_DAHDI_UDEV */ if (debug) - printk("Registered Span %d ('%s') with %d channels\n", span->spanno, span->name, span->channels); + module_printk(KERN_NOTICE, "Registered Span %d ('%s') with %d channels\n", span->spanno, span->name, span->channels); if (!master || prefmaster) { master = span; if (debug) - printk("Span ('%s') is new master\n", span->name); + module_printk(KERN_NOTICE, "Span ('%s') is new master\n", span->name); } return 0; } @@ -5010,7 +5229,7 @@ int dahdi_unregister(struct dahdi_span *span) #endif /* CONFIG_PROC_FS */ if (!(span->flags & DAHDI_FLAG_REGISTERED)) { - printk(KERN_ERR "Span %s does not appear to be registered\n", span->name); + module_printk(KERN_ERR, "Span %s does not appear to be registered\n", span->name); return -1; } /* Shutdown the span if it's running */ @@ -5019,22 +5238,20 @@ int dahdi_unregister(struct dahdi_span *span) span->shutdown(span); if (spans[span->spanno] != span) { - printk(KERN_ERR "Span %s has spanno %d which is something else\n", span->name, span->spanno); + module_printk(KERN_ERR, "Span %s has spanno %d which is something else\n", span->name, span->spanno); return -1; } if (debug) - printk("Unregistering Span '%s' with %d channels\n", span->name, span->channels); + module_printk(KERN_NOTICE, "Unregistering Span '%s' with %d channels\n", span->name, span->channels); #ifdef CONFIG_PROC_FS sprintf(tempfile, "dahdi/%d", span->spanno); remove_proc_entry(tempfile, NULL); #endif /* CONFIG_PROC_FS */ -#ifdef CONFIG_DAHDI_UDEV for (x = 0; x < span->channels; x++) { if (span->chans[x].channo < 250) class_device_destroy(dahdi_class, MKDEV(DAHDI_MAJOR, span->chans[x].channo)); } -#endif /* CONFIG_DAHDI_UDEV */ spans[span->spanno] = NULL; span->spanno = 0; @@ -5055,8 +5272,8 @@ int dahdi_unregister(struct dahdi_span *span) maxspans = new_maxspans; if (master != new_master) if (debug) - printk("%s: Span ('%s') is new master\n", __FUNCTION__, - (new_master)? new_master->name: "no master"); + module_printk(KERN_NOTICE, "%s: Span ('%s') is new master\n", __FUNCTION__, + (new_master)? new_master->name: "no master"); master = new_master; return 0; @@ -5230,17 +5447,19 @@ static inline void __dahdi_process_getaudio_chunk(struct dahdi_chan *ss, unsigne for (x=0;x<DAHDI_CHUNKSIZE;x++) getlin[x] = DAHDI_XLAW(txb[x], ms); #ifndef NO_ECHOCAN_DISABLE - if (ms->ec) { + if (ms->ec_state) { for (x=0;x<DAHDI_CHUNKSIZE;x++) { /* Check for echo cancel disabling tone */ if (echo_can_disable_detector_update(&ms->txecdis, getlin[x])) { - printk("DAHDI Disabled echo canceller because of tone (tx) on channel %d\n", ss->channo); + module_printk(KERN_NOTICE, "Disabled echo canceller because of tone (tx) on channel %d\n", ss->channo); ms->echocancel = 0; ms->echostate = ECHO_STATE_IDLE; ms->echolastupdate = 0; ms->echotimer = 0; - echo_can_free(ms->ec); - ms->ec = NULL; + ms->ec_current->echo_can_free(ms->ec_state); + ms->ec_state = NULL; + release_echocan(ms->ec_current); + ms->ec_current = NULL; __qevent(ss, DAHDI_EVENT_EC_DISABLED); break; } @@ -5412,14 +5631,14 @@ static inline void __dahdi_process_getaudio_chunk(struct dahdi_chan *ss, unsigne if (!chans[ms->confna]) break; if (chans[ms->confna]->flags & DAHDI_FLAG_PSEUDO) { - if (ms->ec) { + if (ms->ec_state) { for (x=0;x<DAHDI_CHUNKSIZE;x++) txb[x] = DAHDI_LIN2X(chans[ms->confna]->getlin[x], ms); } else { memcpy(txb, chans[ms->confna]->getraw, DAHDI_CHUNKSIZE); } } else { - if (ms->ec) { + if (ms->ec_state) { for (x=0;x<DAHDI_CHUNKSIZE;x++) txb[x] = DAHDI_LIN2X(chans[ms->confna]->putlin[x], ms); } else { @@ -5919,7 +6138,7 @@ static void __dahdi_hooksig_pvt(struct dahdi_chan *chan, dahdi_rxsig_t rxsig) } chan->kewlonhook = 0; #ifdef CONFIG_DAHDI_DEBUG - printk("Off hook on channel %d, itimer = %d, gotgs = %d\n", chan->channo, chan->itimer, chan->gotgs); + module_printk(KERN_NOTICE, "Off hook on channel %d, itimer = %d, gotgs = %d\n", chan->channo, chan->itimer, chan->gotgs); #endif if (chan->itimer) /* if timer still running */ { @@ -6045,7 +6264,7 @@ static inline void __dahdi_ec_chunk(struct dahdi_chan *ss, unsigned char *rxchun } /* Perform echo cancellation on a chunk if necessary */ - if (ss->ec) { + if (ss->ec_state) { #if defined(CONFIG_DAHDI_MMX) || defined(ECHO_CAN_FP) dahdi_kernel_fpu_begin(); #endif @@ -6065,9 +6284,9 @@ static inline void __dahdi_ec_chunk(struct dahdi_chan *ss, unsigned char *rxchun ss->echostate = ECHO_STATE_TRAINING; } if (ss->echostate == ECHO_STATE_TRAINING) { - if (echo_can_traintap(ss->ec, ss->echolastupdate++, rxlin)) { + if (ss->ec_current->echo_can_traintap(ss->ec_state, ss->echolastupdate++, rxlin)) { #if 0 - printk("Finished training (%d taps trained)!\n", ss->echolastupdate); + module_printk(KERN_NOTICE, "Finished training (%d taps trained)!\n", ss->echolastupdate); #endif ss->echostate = ECHO_STATE_ACTIVE; } @@ -6076,22 +6295,14 @@ static inline void __dahdi_ec_chunk(struct dahdi_chan *ss, unsigned char *rxchun rxchunk[x] = DAHDI_LIN2X((int)rxlin, ss); } } else { -#if !defined(DAHDI_EC_ARRAY_UPDATE) - for (x=0;x<DAHDI_CHUNKSIZE;x++) { - rxlin = DAHDI_XLAW(rxchunk[x], ss); - rxlin = echo_can_update(ss->ec, DAHDI_XLAW(txchunk[x], ss), rxlin); - rxchunk[x] = DAHDI_LIN2X((int) rxlin, ss); - } -#else /* defined(DAHDI_EC_ARRAY_UPDATE) */ short rxlins[DAHDI_CHUNKSIZE], txlins[DAHDI_CHUNKSIZE]; for (x = 0; x < DAHDI_CHUNKSIZE; x++) { rxlins[x] = DAHDI_XLAW(rxchunk[x], ss); txlins[x] = DAHDI_XLAW(txchunk[x], ss); } - echo_can_array_update(ss->ec, rxlins, txlins); + ss->ec_current->echo_can_array_update(ss->ec_state, rxlins, txlins); for (x = 0; x < DAHDI_CHUNKSIZE; x++) rxchunk[x] = DAHDI_LIN2X((int) rxlins[x], ss); -#endif /* defined(DAHDI_EC_ARRAY_UPDATE) */ } #if defined(CONFIG_DAHDI_MMX) || defined(ECHO_CAN_FP) kernel_fpu_end(); @@ -6109,7 +6320,7 @@ void dahdi_ec_span(struct dahdi_span *span) { int x; for (x = 0; x < span->channels; x++) { - if (span->chans[x].ec) + if (span->chans[x].ec_current) __dahdi_ec_chunk(&span->chans[x], span->chans[x].readchunk, span->chans[x].writechunk); } } @@ -6185,16 +6396,18 @@ static inline void __dahdi_process_putaudio_chunk(struct dahdi_chan *ss, unsigne } #ifndef NO_ECHOCAN_DISABLE - if (ms->ec) { + if (ms->ec_state) { for (x=0;x<DAHDI_CHUNKSIZE;x++) { if (echo_can_disable_detector_update(&ms->rxecdis, putlin[x])) { - printk("DAHDI Disabled echo canceller because of tone (rx) on channel %d\n", ss->channo); + module_printk(KERN_NOTICE, "Disabled echo canceller because of tone (rx) on channel %d\n", ss->channo); ms->echocancel = 0; ms->echostate = ECHO_STATE_IDLE; ms->echolastupdate = 0; ms->echotimer = 0; - echo_can_free(ms->ec); - ms->ec = NULL; + ms->ec_current->echo_can_free(ms->ec_state); + ms->ec_state = NULL; + release_echocan(ms->ec_current); + ms->ec_current = NULL; break; } } @@ -6480,7 +6693,7 @@ static inline void __putbuf_chunk(struct dahdi_chan *ss, unsigned char *rxb, int /* Pay attention to the possibility of an overrun */ if (ms->readidx[ms->inreadbuf] >= ms->blocksize) { if (!ss->span->alarms) - printk(KERN_WARNING "HDLC Receiver overrun on channel %s (master=%s)\n", ss->name, ss->master->name); + module_printk(KERN_WARNING, "HDLC Receiver overrun on channel %s (master=%s)\n", ss->name, ss->master->name); abort=DAHDI_EVENT_OVERRUN; /* Force the HDLC state back to frame-search mode */ ms->rxhdlc.state = 0; @@ -6509,7 +6722,7 @@ static inline void __putbuf_chunk(struct dahdi_chan *ss, unsigned char *rxb, int ms->infcs = PPP_INITFCS; ms->readn[ms->inreadbuf] = ms->readidx[ms->inreadbuf]; #ifdef CONFIG_DAHDI_DEBUG - printk("EOF, len is %d\n", ms->readn[ms->inreadbuf]); + module_printk(KERN_NOTICE, "EOF, len is %d\n", ms->readn[ms->inreadbuf]); #endif #if defined(CONFIG_DAHDI_NET) || defined(CONFIG_DAHDI_PPP) if (ms->flags & (DAHDI_FLAG_NETDEV | DAHDI_FLAG_PPP)) { @@ -6554,7 +6767,7 @@ static inline void __putbuf_chunk(struct dahdi_chan *ss, unsigned char *rxb, int #ifdef CONFIG_DAHDI_PPP if (!ms->do_ppp_error) #endif - printk("Memory squeeze, dropped one\n"); + module_printk(KERN_NOTICE, "Memory squeeze, dropped one\n"); #endif } } @@ -6574,23 +6787,20 @@ static inline void __putbuf_chunk(struct dahdi_chan *ss, unsigned char *rxb, int if (ms->flags & DAHDI_FLAG_MTP2) { comparemessage = (ms->inreadbuf - 1) & (ms->numbufs - 1); - - res = memcmp(ms->readbuf[comparemessage], ms->readbuf[ms->inreadbuf], ms->readn[ms->inreadbuf]); - } - - if ((ms->flags & DAHDI_FLAG_MTP2) && !res) { - /* Our messages are the same, so discard - - * Don't advance buffers, reset indexes and buffer sizes. */ - ms->readn[ms->inreadbuf] = 0; - ms->readidx[ms->inreadbuf] = 0; + if (!memcmp(ms->readbuf[comparemessage], ms->readbuf[ms->inreadbuf], ms->readn[ms->inreadbuf])) { + /* Our messages are the same, so discard - + * Don't advance buffers, reset indexes and buffer sizes. */ + ms->readn[ms->inreadbuf] = 0; + ms->readidx[ms->inreadbuf] = 0; + } } else { ms->inreadbuf = (ms->inreadbuf + 1) % ms->numbufs; if (ms->inreadbuf == ms->outreadbuf) { /* Whoops, we're full, and have no where else - to store into at the moment. We'll drop it - until there's a buffer available */ + to store into at the moment. We'll drop it + until there's a buffer available */ #ifdef CONFIG_DAHDI_DEBUG - printk("Out of storage space\n"); + module_printk(KERN_NOTICE, "Out of storage space\n"); #endif ms->inreadbuf = -1; /* Enable the receiver in case they've got POLICY_WHEN_FULL */ @@ -6613,7 +6823,7 @@ out in the later versions, and is put back now. */ /* Notify a blocked reader that there is data available to be read, unless we're waiting for it to be full */ #ifdef CONFIG_DAHDI_DEBUG - printk("Notifying reader data in block %d\n", oldbuf); + module_printk(KERN_NOTICE, "Notifying reader data in block %d\n", oldbuf); #endif wake_up_interruptible(&ms->readbufq); wake_up_interruptible(&ms->sel); @@ -6646,12 +6856,12 @@ out in the later versions, and is put back now. */ tasklet_schedule(&ms->ppp_calls); } else #endif - - if ((ms->flags & DAHDI_FLAG_OPEN) && !ss->span->alarms) + if (test_bit(DAHDI_FLAGBIT_OPEN, &ms->flags) && !ss->span->alarms) { /* Notify the receiver... */ - __qevent(ss->master, abort); + __qevent(ss->master, abort); + } #if 0 - printk("torintr_receive: Aborted %d bytes of frame on %d\n", amt, ss->master); + module_printk(KERN_NOTICE, "torintr_receive: Aborted %d bytes of frame on %d\n", amt, ss->master); #endif } @@ -6687,7 +6897,7 @@ out in the later versions, and is put back now. */ if (!tmp || (tmp[0] != 0xff) || (tmp[1] != 0x03)) { /* Invalid SKB -- drop */ if (tmp) - printk("Received invalid SKB (%02x, %02x)\n", tmp[0], tmp[1]); + module_printk(KERN_NOTICE, "Received invalid SKB (%02x, %02x)\n", tmp[0], tmp[1]); dev_kfree_skb_irq(skb); } else { skb_queue_tail(&ms->ppp_rq, skb); @@ -6707,7 +6917,7 @@ static void __dahdi_hdlc_abort(struct dahdi_chan *ss, int event) { if (ss->inreadbuf >= 0) ss->readidx[ss->inreadbuf] = 0; - if ((ss->flags & DAHDI_FLAG_OPEN) && !ss->span->alarms) + if (test_bit(DAHDI_FLAGBIT_OPEN, &ss->flags) && !ss->span->alarms) __qevent(ss->master, event); } @@ -6728,7 +6938,7 @@ extern void dahdi_hdlc_putbuf(struct dahdi_chan *ss, unsigned char *rxb, int byt spin_lock_irqsave(&ss->lock, flags); if (ss->inreadbuf < 0) { #ifdef CONFIG_DAHDI_DEBUG - printk("No place to receive HDLC frame\n"); + module_printk(KERN_NOTICE, "No place to receive HDLC frame\n"); #endif spin_unlock_irqrestore(&ss->lock, flags); return; @@ -6746,7 +6956,7 @@ extern void dahdi_hdlc_putbuf(struct dahdi_chan *ss, unsigned char *rxb, int byt /* Something isn't fit into buffer */ if (bytes) { #ifdef CONFIG_DAHDI_DEBUG - printk("HDLC frame isn't fit into buffer space\n"); + module_printk(KERN_NOTICE, "HDLC frame isn't fit into buffer space\n"); #endif __dahdi_hdlc_abort(ss, DAHDI_EVENT_OVERRUN); } @@ -6763,7 +6973,7 @@ extern void dahdi_hdlc_finish(struct dahdi_chan *ss) if ((oldreadbuf = ss->inreadbuf) < 0) { #ifdef CONFIG_DAHDI_DEBUG - printk("No buffers to finish\n"); + module_printk(KERN_NOTICE, "No buffers to finish\n"); #endif spin_unlock_irqrestore(&ss->lock, flags); return; @@ -6771,7 +6981,7 @@ extern void dahdi_hdlc_finish(struct dahdi_chan *ss) if (!ss->readidx[ss->inreadbuf]) { #ifdef CONFIG_DAHDI_DEBUG - printk("Empty HDLC frame received\n"); + module_printk(KERN_NOTICE, "Empty HDLC frame received\n"); #endif spin_unlock_irqrestore(&ss->lock, flags); return; @@ -6782,7 +6992,7 @@ extern void dahdi_hdlc_finish(struct dahdi_chan *ss) if (ss->inreadbuf == ss->outreadbuf) { ss->inreadbuf = -1; #ifdef CONFIG_DAHDI_DEBUG - printk("Notifying reader data in block %d\n", oldreadbuf); + module_printk(KERN_NOTICE, "Notifying reader data in block %d\n", oldreadbuf); #endif ss->rxdisable = 0; } @@ -6958,7 +7168,7 @@ static unsigned int dahdi_poll(struct file *file, struct poll_table_struct *wait if (unit == 255) { chan = file->private_data; if (!chan) { - printk("No pseudo channel structure to read?\n"); + module_printk(KERN_NOTICE, "No pseudo channel structure to read?\n"); return -EINVAL; } return dahdi_chan_poll(file, wait_table, chan->channo); @@ -7222,7 +7432,7 @@ int dahdi_receive(struct dahdi_span *span) { if (span->chans[x].pulsecount > 12) { - printk("Got pulse digit %d on %s???\n", + module_printk(KERN_NOTICE, "Got pulse digit %d on %s???\n", span->chans[x].pulsecount, span->chans[x].name); } else if (span->chans[x].pulsecount > 11) { @@ -7327,12 +7537,8 @@ int dahdi_receive(struct dahdi_span *span) MODULE_AUTHOR("Mark Spencer <markster@digium.com>"); MODULE_DESCRIPTION("DAHDI Telephony Interface"); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif -#ifdef MODULE_VERSION +MODULE_LICENSE("GPL v2"); MODULE_VERSION(DAHDI_VERSION); -#endif module_param(debug, int, 0644); module_param(deftaps, int, 0644); @@ -7370,17 +7576,17 @@ static void watchdog_check(unsigned long ignored) (spans[x]->watchstate == DAHDI_WATCHSTATE_UNKNOWN)) { spans[x]->watchstate = DAHDI_WATCHSTATE_RECOVERING; if (spans[x]->watchdog) { - printk("Kicking span %s\n", spans[x]->name); + module_printk(KERN_NOTICE, "Kicking span %s\n", spans[x]->name); spans[x]->watchdog(spans[x], DAHDI_WATCHDOG_NOINTS); } else { - printk("Span %s is dead with no revival\n", spans[x]->name); + module_printk(KERN_NOTICE, "Span %s is dead with no revival\n", spans[x]->name); spans[x]->watchstate = DAHDI_WATCHSTATE_FAILED; } } } else { if ((spans[x]->watchstate != DAHDI_WATCHSTATE_OK) && (spans[x]->watchstate != DAHDI_WATCHSTATE_UNKNOWN)) - printk("Span %s is alive!\n", spans[x]->name); + module_printk(KERN_NOTICE, "Span %s is alive!\n", spans[x]->name); spans[x]->watchstate = DAHDI_WATCHSTATE_OK; } spans[x]->watchcounter = DAHDI_WATCHDOG_INIT; @@ -7388,7 +7594,7 @@ static void watchdog_check(unsigned long ignored) } local_irq_restore(flags); if (!wdcheck) { - printk("DAHDI watchdog on duty!\n"); + module_printk(KERN_NOTICE, "watchdog on duty!\n"); wdcheck=1; } mod_timer(&watchdogtimer, jiffies + 2); @@ -7414,22 +7620,18 @@ static void __exit watchdog_cleanup(void) int dahdi_register_chardev(struct dahdi_chardev *dev) { -#ifdef CONFIG_DAHDI_UDEV char udevname[strlen(dev->name) + 3]; strcpy(udevname, "dahdi"); strcat(udevname, dev->name); CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, dev->minor), NULL, udevname); -#endif /* CONFIG_DAHDI_UDEV */ return 0; } int dahdi_unregister_chardev(struct dahdi_chardev *dev) { -#ifdef CONFIG_DAHDI_UDEV class_device_destroy(dahdi_class, MKDEV(DAHDI_MAJOR, dev->minor)); -#endif /* CONFIG_DAHDI_UDEV */ return 0; } @@ -7441,26 +7643,22 @@ static int __init dahdi_init(void) { proc_entries[0] = proc_mkdir("dahdi", NULL); #endif -#ifdef CONFIG_DAHDI_UDEV /* udev support functions */ dahdi_class = class_create(THIS_MODULE, "dahdi"); CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, 253), NULL, "dahditimer"); CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, 254), NULL, "dahdichannel"); CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, 255), NULL, "dahdipseudo"); CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, 0), NULL, "dahdictl"); -#endif /* CONFIG_DAHDI_UDEV */ if ((res = register_chrdev(DAHDI_MAJOR, "dahdi", &dahdi_fops))) { - printk(KERN_ERR "Unable to register DAHDI character device handler on %d\n", DAHDI_MAJOR); + module_printk(KERN_ERR, "Unable to register DAHDI character device handler on %d\n", DAHDI_MAJOR); return res; } - printk(KERN_INFO "DAHDI Telephony Interface Registered on major %d\n", DAHDI_MAJOR); - printk(KERN_INFO "DAHDI Version: %s\n", DAHDI_VERSION); - echo_can_init(); + module_printk(KERN_INFO, "Telephony Interface Registered on major %d\n", DAHDI_MAJOR); + module_printk(KERN_INFO, "Version: %s\n", DAHDI_VERSION); dahdi_conv_init(); fasthdlc_precalc(); rotate_sums(); - rwlock_init(&chan_lock); #ifdef CONFIG_DAHDI_WATCHDOG watchdog_init(); #endif @@ -7470,31 +7668,27 @@ static int __init dahdi_init(void) { static void __exit dahdi_cleanup(void) { int x; + unregister_chrdev(DAHDI_MAJOR, "dahdi"); + #ifdef CONFIG_PROC_FS remove_proc_entry("dahdi", NULL); #endif - printk(KERN_INFO "DAHDI Telephony Interface Unloaded\n"); + module_printk(KERN_INFO, "Telephony Interface Unloaded\n"); for (x = 0; x < DAHDI_TONE_ZONE_MAX; x++) { if (tone_zones[x]) kfree(tone_zones[x]); } -#ifdef CONFIG_DAHDI_UDEV class_device_destroy(dahdi_class, MKDEV(DAHDI_MAJOR, 253)); /* timer */ class_device_destroy(dahdi_class, MKDEV(DAHDI_MAJOR, 254)); /* channel */ class_device_destroy(dahdi_class, MKDEV(DAHDI_MAJOR, 255)); /* pseudo */ class_device_destroy(dahdi_class, MKDEV(DAHDI_MAJOR, 0)); /* ctl */ class_destroy(dahdi_class); -#endif /* CONFIG_DAHDI_UDEV */ - - unregister_chrdev(DAHDI_MAJOR, "dahdi"); #ifdef CONFIG_DAHDI_WATCHDOG watchdog_cleanup(); #endif - - echo_can_shutdown(); } module_init(dahdi_init); diff --git a/drivers/dahdi/dahdi_config.h b/drivers/dahdi/dahdi_config.h index 327182b..617b4aa 100644 --- a/drivers/dahdi/dahdi_config.h +++ b/drivers/dahdi/dahdi_config.h @@ -54,61 +54,22 @@ */ /* #define CONFIG_DAHDI_MMX */ -/** If defined: the user must define exactly one ECHO_CAN_ var: */ -#ifndef ECHO_CAN_FROMENV - -/* - * Pick your echo canceller: MARK2, MARK3, STEVE, or STEVE2 :) - * - */ -/* #define ECHO_CAN_STEVE */ -/* #define ECHO_CAN_STEVE2 */ -/* #define ECHO_CAN_KB1 */ -/* This is the new latest and greatest */ -#define ECHO_CAN_MG2 - -/* - * This is only technically an "echo canceller"... - * It purposely drops 2 out of 3 samples and sounds horrible. - * You really only want this for testing "echo cancelled" audio. - */ -/* #define ECHO_CAN_JP1 */ - -/* - * Uncomment for aggressive residual echo suppression under - * MARK2, KB1, and MG2 echo canceler - */ -/* #define AGGRESSIVE_SUPPRESSOR */ -#endif /* ifndef ECHO_CAN_FROMENV */ /* * Define to turn off the echo canceler disable tone detector, - * which will cause dahdi to ignore the 2100 Hz echo cancel disable + * which will cause DAHDI to ignore the 2100 Hz echo cancel disable * tone. */ /* #define NO_ECHOCAN_DISABLE */ -/* udev support */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,1) -#define CONFIG_DAHDI_UDEV -#endif - /* We now use the linux kernel config to detect which options to use */ /* You can still override them below */ #if defined(CONFIG_HDLC) || defined(CONFIG_HDLC_MODULE) -/* #define CONFIG_DAHDI_NET */ /* NEVER implicitly turn on CONFIG_DAHDI_NET */ -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,20) -#define CONFIG_OLD_HDLC_API -#else -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,23) -/* Starting with 2.4.23 the kernel hdlc api changed again */ -/* Now we have to use hdlc_type_trans(skb, dev) instead of htons(ETH_P_HDLC) */ #define DAHDI_HDLC_TYPE_TRANS -#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3) #define HDLC_MAINTAINERS_ARE_MORE_STUPID_THAN_I_THOUGHT #endif #endif -#endif + #ifdef CONFIG_PPP #define CONFIG_DAHDI_PPP #endif @@ -185,7 +146,7 @@ /* * Enable sync_tick() calls. Allows low-level drivers to synchronize - * their internal clocks to the dahdi master clock. + * their internal clocks to the DAHDI master clock. */ #define DAHDI_SYNC_TICK diff --git a/drivers/dahdi/dahdi_dummy.c b/drivers/dahdi/dahdi_dummy.c index 8e9da8a..8263633 100644 --- a/drivers/dahdi/dahdi_dummy.c +++ b/drivers/dahdi/dahdi_dummy.c @@ -332,6 +332,4 @@ module_param(rtc_rate, int, 0600); MODULE_DESCRIPTION("Dummy DAHDI Driver"); MODULE_AUTHOR("Robert Pleh <robert.pleh@hermes.si>"); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif +MODULE_LICENSE("GPL v2"); diff --git a/drivers/dahdi/dahdi_dynamic.c b/drivers/dahdi/dahdi_dynamic.c index 577b5d7..f29bbda 100644 --- a/drivers/dahdi/dahdi_dynamic.c +++ b/drivers/dahdi/dahdi_dynamic.c @@ -626,7 +626,7 @@ static int create_dynamic(DAHDI_DYNAMIC_SPAN *zds) /* Try loading the right module */ char fn[80]; spin_unlock_irqrestore(&dlock, flags); - sprintf(fn, "ztd-%s", zds->driver); + sprintf(fn, "dahdi_dynamic_%s", zds->driver); request_module(fn); spin_lock_irqsave(&dlock, flags); ztd = find_driver(zds->driver); @@ -844,9 +844,7 @@ module_param(debug, int, 0600); MODULE_DESCRIPTION("DAHDI Dynamic Span Support"); MODULE_AUTHOR("Mark Spencer <markster@digium.com>"); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif +MODULE_LICENSE("GPL v2"); module_init(ztdynamic_init); module_exit(ztdynamic_cleanup); diff --git a/drivers/dahdi/dahdi_dynamic_eth.c b/drivers/dahdi/dahdi_dynamic_eth.c index 32ab956..e36522b 100644 --- a/drivers/dahdi/dahdi_dynamic_eth.c +++ b/drivers/dahdi/dahdi_dynamic_eth.c @@ -429,9 +429,7 @@ static void __exit ztdeth_exit(void) MODULE_DESCRIPTION("DAHDI Dynamic TDMoE Support"); MODULE_AUTHOR("Mark Spencer <markster@digium.com>"); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif +MODULE_LICENSE("GPL v2"); module_init(ztdeth_init); module_exit(ztdeth_exit); diff --git a/drivers/dahdi/dahdi_dynamic_loc.c b/drivers/dahdi/dahdi_dynamic_loc.c index 7ed9d7e..6d6262b 100644 --- a/drivers/dahdi/dahdi_dynamic_loc.c +++ b/drivers/dahdi/dahdi_dynamic_loc.c @@ -263,6 +263,5 @@ static struct dahdi_dynamic_driver ztd_local = { module_init(ztdlocal_init); module_exit(ztdlocal_exit); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/dahdi/dahdi_echocan_jpah.c b/drivers/dahdi/dahdi_echocan_jpah.c new file mode 100644 index 0000000..cddbc01 --- /dev/null +++ b/drivers/dahdi/dahdi_echocan_jpah.c @@ -0,0 +1,130 @@ +/* + * ECHO_CAN_JPAH + * + * by Jason Parker + * + * Based upon mg2ec.h - sort of. + * This "echo can" will completely hose your audio. + * Don't use it unless you're absolutely sure you know what you're doing. + * + * Copyright (C) 2007-2008, Digium, Inc. + * + * 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 version 2 as + * published by the Free Software Foundation. + * + * 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 <linux/kernel.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/ctype.h> +#include <linux/moduleparam.h> + +#include <dahdi/kernel.h> + +static int debug; + +#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args) +#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args) + +struct echo_can_state { + int blah; +}; + +static int echo_can_create(struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, + struct echo_can_state **ec) +{ + unsigned int x; + char *c; + + if ((*ec = kmalloc(sizeof(**ec), GFP_KERNEL))) { + memset(ec, 0, sizeof(**ec)); + } + + for (x = 0; x < ecp->param_count; x++) { + for (c = p[x].name; *c; c++) + *c = tolower(*c); + printk(KERN_WARNING "Unknown parameter supplied to JPAH echo canceler: '%s'\n", p[x].name); + kfree(*ec); + + return -EINVAL; + } + + return 0; +} + +static void echo_can_free(struct echo_can_state *ec) +{ + kfree(ec); +} + +static void echo_can_update(struct echo_can_state *ec, short *iref, short *isig) +{ + unsigned int x; + + for (x = 0; x < DAHDI_CHUNKSIZE; x++) { + if (ec->blah < 2) { + ec->blah++; + + *isig++ = 0; + } else { + ec->blah = 0; + + isig++; + } + } +} + +static int echo_can_traintap(struct echo_can_state *ec, int pos, short val) +{ + return 0; +} + +static const struct dahdi_echocan me = { + .name = "JPAH", + .owner = THIS_MODULE, + .echo_can_create = echo_can_create, + .echo_can_free = echo_can_free, + .echo_can_array_update = echo_can_update, + .echo_can_traintap = echo_can_traintap, +}; + +static int __init mod_init(void) +{ + if (dahdi_register_echocan(&me)) { + module_printk(KERN_ERR, "could not register with DAHDI core\n"); + + return -EPERM; + } + + module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", me.name); + + return 0; +} + +static void __exit mod_exit(void) +{ + dahdi_unregister_echocan(&me); +} + +module_param(debug, int, S_IRUGO | S_IWUSR); + +MODULE_DESCRIPTION("DAHDI Jason Parker Audio Hoser"); +MODULE_AUTHOR("Jason Parker <jparker@digium.com>"); +MODULE_LICENSE("GPL v2"); + +module_init(mod_init); +module_exit(mod_exit); diff --git a/drivers/dahdi/kb1ec.h b/drivers/dahdi/dahdi_echocan_kb1.c index e56e89e..391ca51 100644 --- a/drivers/dahdi/kb1ec.h +++ b/drivers/dahdi/dahdi_echocan_kb1.c @@ -3,7 +3,7 @@ * * by Kris Boutilier * - * Based upon mech2.h + * Based upon mec2.h * * Copyright (C) 2002, Digium, Inc. * @@ -23,15 +23,21 @@ * */ -#ifndef _MARK2_ECHO_H -#define _MARK2_ECHO_H - #include <linux/kernel.h> #include <linux/slab.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/init.h> #include <linux/ctype.h> +#include <linux/moduleparam.h> + +#include <dahdi/kernel.h> -#define MALLOC(a) kmalloc((a), GFP_KERNEL) -#define FREE(a) kfree(a) +static int debug; +static int aggressive; + +#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args) +#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args) /* Uncomment to provide summary statistics for overall echo can performance every 4000 samples */ /* #define MEC2_STATS 4000 */ @@ -42,8 +48,71 @@ /* Get optimized routines for math */ #include "arith.h" -/* Bring in definitions for the various constants and thresholds */ -#include "kb1ec_const.h" +/* + Important constants for tuning kb1 echo can + */ + +/* Convergence (aka. adaptation) speed -- higher means slower */ +#define DEFAULT_BETA1_I 2048 + +/* Constants for various power computations */ +#define DEFAULT_SIGMA_LY_I 7 +#define DEFAULT_SIGMA_LU_I 7 +#define DEFAULT_ALPHA_ST_I 5 /* near-end speech detection sensitivity factor */ +#define DEFAULT_ALPHA_YT_I 5 + +#define DEFAULT_CUTOFF_I 128 + +/* Define the near-end speech hangover counter: if near-end speech + * is declared, hcntr is set equal to hangt (see pg. 432) + */ +#define DEFAULT_HANGT 600 /* in samples, so 600 samples = 75ms */ + +/* define the residual error suppression threshold */ +#define DEFAULT_SUPPR_I 16 /* 16 = -24db */ + +/* This is the minimum reference signal power estimate level + * that will result in filter adaptation. + * If this is too low then background noise will cause the filter + * coefficients to constantly be updated. + */ +#define MIN_UPDATE_THRESH_I 4096 + +/* The number of samples used to update coefficients using the + * the block update method (M). It should be related back to the + * length of the echo can. + * ie. it only updates coefficients when (sample number MOD default_m) = 0 + * + * Getting this wrong may cause an oops. Consider yourself warned! + */ +#define DEFAULT_M 16 /* every 16th sample */ + +/* If AGGRESSIVE supression is enabled, then we start cancelling residual + * echos again even while there is potentially the very end of a near-side + * signal present. + * This defines how many samples of DEFAULT_HANGT can remain before we + * kick back in + */ +#define AGGRESSIVE_HCNTR 160 /* in samples, so 160 samples = 20ms */ + + +/***************************************************************/ +/* The following knobs are not implemented in the current code */ + +/* we need a dynamic level of suppression varying with the ratio of the + power of the echo to the power of the reference signal this is + done so that we have a smoother background. + we have a higher suppression when the power ratio is closer to + suppr_ceil and reduces logarithmically as we approach suppr_floor. + */ +#define SUPPR_FLOOR -64 +#define SUPPR_CEIL -24 + +/* in a second departure, we calculate the residual error suppression + * as a percentage of the reference signal energy level. The threshold + * is defined in terms of dB below the reference signal. + */ +#define RES_SUPR_FACTOR -20 #ifndef NULL #define NULL 0 @@ -133,20 +202,6 @@ struct echo_can_state { unsigned int aggressive:1; }; -static void echo_can_init(void) -{ - printk("DAHDI Echo Canceller: KB1\n"); -} - -static void echo_can_identify(char *buf, size_t len) -{ - dahdi_copy_string(buf, "KB1", len); -} - -static void echo_can_shutdown(void) -{ -} - static inline void init_cb_s(echo_can_cb_s *cb, int len, void *where) { cb->buf_d = (short *)where; @@ -238,14 +293,13 @@ static inline void init_cc(struct echo_can_state *ec, int N, int maxy, int maxu) } -static inline void echo_can_free(struct echo_can_state *ec) +static void echo_can_free(struct echo_can_state *ec) { - FREE(ec); + kfree(ec); } -static inline short echo_can_update(struct echo_can_state *ec, short iref, short isig) +static inline short sample_update(struct echo_can_state *ec, short iref, short isig) { - /* Declare local variables that are used more than once */ /* ... */ int k; @@ -521,6 +575,17 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short return u; } +static void echo_can_update(struct echo_can_state *ec, short *iref, short *isig) +{ + unsigned int x; + short result; + + for (x = 0; x < DAHDI_CHUNKSIZE; x++) { + result = sample_update(ec, *iref, *isig); + *isig++ = result; + } +} + static int echo_can_create(struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct echo_can_state **ec) { @@ -548,14 +613,12 @@ static int echo_can_create(struct dahdi_echocanparams *ecp, struct dahdi_echocan 2 * sizeof(short) * (maxu) + /* u_s */ 2 * sizeof(short) * ecp->tap_length; /* y_tilde_s */ - if (!(*ec = MALLOC(size))) + if (!(*ec = kmalloc(size, GFP_KERNEL))) return -ENOMEM; memset(*ec, 0, size); -#ifdef AGGRESSIVE_SUPPRESSOR - (*ec)->aggressive = 1; -#endif + (*ec)->aggressive = aggressive; for (x = 0; x < ecp->param_count; x++) { for (c = p[x].name; *c; c++) @@ -575,7 +638,7 @@ static int echo_can_create(struct dahdi_echocanparams *ecp, struct dahdi_echocan return 0; } -static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val) +static int echo_can_traintap(struct echo_can_state *ec, int pos, short val) { /* Set the hangover counter to the length of the can to * avoid adjustments occuring immediately after initial forced training @@ -594,4 +657,39 @@ static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short va return 0; } -#endif +static const struct dahdi_echocan me = { + .name = "KB1", + .owner = THIS_MODULE, + .echo_can_create = echo_can_create, + .echo_can_free = echo_can_free, + .echo_can_array_update = echo_can_update, + .echo_can_traintap = echo_can_traintap, +}; + +static int __init mod_init(void) +{ + if (dahdi_register_echocan(&me)) { + module_printk(KERN_ERR, "could not register with DAHDI core\n"); + + return -EPERM; + } + + module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", me.name); + + return 0; +} + +static void __exit mod_exit(void) +{ + dahdi_unregister_echocan(&me); +} + +module_param(debug, int, S_IRUGO | S_IWUSR); +module_param(aggressive, int, S_IRUGO | S_IWUSR); + +MODULE_DESCRIPTION("DAHDI 'KB1' Echo Canceler"); +MODULE_AUTHOR("Kris Boutilier"); +MODULE_LICENSE("GPL v2"); + +module_init(mod_init); +module_exit(mod_exit); diff --git a/drivers/dahdi/mg2ec.h b/drivers/dahdi/dahdi_echocan_mg2.c index 55a7caa..9c7d8c6 100644 --- a/drivers/dahdi/mg2ec.h +++ b/drivers/dahdi/dahdi_echocan_mg2.c @@ -23,15 +23,21 @@ * */ -#ifndef _MG2_ECHO_H -#define _MG2_ECHO_H - #include <linux/kernel.h> #include <linux/slab.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/init.h> #include <linux/ctype.h> +#include <linux/moduleparam.h> + +#include <dahdi/kernel.h> -#define MALLOC(a) kmalloc((a), GFP_KERNEL) -#define FREE(a) kfree(a) +static int debug; +static int aggressive; + +#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args) +#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args) #define ABS(a) abs(a!=-32768?a:-32767) @@ -56,8 +62,87 @@ /* Get optimized routines for math */ #include "arith.h" -/* Bring in definitions for the various constants and thresholds */ -#include "mg2ec_const.h" +/* + Important constants for tuning mg2 echo can + */ + +/* Convergence (aka. adaptation) speed -- higher means slower */ +#define DEFAULT_BETA1_I 2048 + +/* Constants for various power computations */ +#define DEFAULT_SIGMA_LY_I 7 +#define DEFAULT_SIGMA_LU_I 7 +#define DEFAULT_ALPHA_ST_I 5 /* near-end speech detection sensitivity factor */ +#define DEFAULT_ALPHA_YT_I 5 + +#define DEFAULT_CUTOFF_I 128 + +/* Define the near-end speech hangover counter: if near-end speech + * is declared, hcntr is set equal to hangt (see pg. 432) + */ +#define DEFAULT_HANGT 600 /* in samples, so 600 samples = 75ms */ + +/* define the residual error suppression threshold */ +#define DEFAULT_SUPPR_I 16 /* 16 = -24db */ + +/* This is the minimum reference signal power estimate level + * that will result in filter adaptation. + * If this is too low then background noise will cause the filter + * coefficients to constantly be updated. + */ +#define MIN_UPDATE_THRESH_I 2048 + +/* The number of samples used to update coefficients using the + * the block update method (M). It should be related back to the + * length of the echo can. + * ie. it only updates coefficients when (sample number MOD default_m) = 0 + * + * Getting this wrong may cause an oops. Consider yourself warned! + */ +#define DEFAULT_M 16 /* every 16th sample */ + +/* If AGGRESSIVE supression is enabled, then we start cancelling residual + * echos again even while there is potentially the very end of a near-side + * signal present. + * This defines how many samples of DEFAULT_HANGT can remain before we + * kick back in + */ +#define AGGRESSIVE_HCNTR 160 /* in samples, so 160 samples = 20ms */ + +/* Treat sample as error if it has a different sign as the + * input signal and is this number larger in ABS() as + * the input-signal */ +#define MAX_SIGN_ERROR 3000 + +/* Number of coefficients really used for calculating the + * simulated echo. The value specifies how many of the + * biggest coefficients are used for calculating rs. + * This helps on long echo-tails by artificially limiting + * the number of coefficients for the calculation and + * preventing overflows. + * Comment this to deactivate the code */ +#define USED_COEFFS 64 + +/* Backup coefficients every this number of samples */ +#define BACKUP 256 + +/***************************************************************/ +/* The following knobs are not implemented in the current code */ + +/* we need a dynamic level of suppression varying with the ratio of the + power of the echo to the power of the reference signal this is + done so that we have a smoother background. + we have a higher suppression when the power ratio is closer to + suppr_ceil and reduces logarithmically as we approach suppr_floor. + */ +#define SUPPR_FLOOR -64 +#define SUPPR_CEIL -24 + +/* in a second departure, we calculate the residual error suppression + * as a percentage of the reference signal energy level. The threshold + * is defined in terms of dB below the reference signal. + */ +#define RES_SUPR_FACTOR -20 #define DC_NORMALIZE @@ -159,20 +244,6 @@ struct echo_can_state { }; -static void echo_can_init(void) -{ - printk("DAHDI Echo Canceller: MG2\n"); -} - -static void echo_can_identify(char *buf, size_t len) -{ - dahdi_copy_string(buf, "MG2", len); -} - -static void echo_can_shutdown(void) -{ -} - static inline void init_cb_s(echo_can_cb_s *cb, int len, void *where) { cb->buf_d = (short *)where; @@ -270,12 +341,12 @@ static inline void init_cc(struct echo_can_state *ec, int N, int maxy, int maxu) } -static inline void echo_can_free(struct echo_can_state *ec) +static void echo_can_free(struct echo_can_state *ec) { #if defined(DC_NORMALIZE) && defined(MEC2_DCBIAS_MESSAGE) printk("EC: DC bias calculated: %d V\n", ec->dc_estimate >> 15); #endif - FREE(ec); + kfree(ec); } #ifdef DC_NORMALIZE @@ -286,9 +357,8 @@ short inline dc_removal(int *dc_estimate, short samp) } #endif -static inline short echo_can_update(struct echo_can_state *ec, short iref, short isig) +static inline short sample_update(struct echo_can_state *ec, short iref, short isig) { - /* Declare local variables that are used more than once */ /* ... */ int k; @@ -642,6 +712,17 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short return u; } +static void echo_can_update(struct echo_can_state *ec, short *iref, short *isig) +{ + unsigned int x; + short result; + + for (x = 0; x < DAHDI_CHUNKSIZE; x++) { + result = sample_update(ec, *iref, *isig); + *isig++ = result; + } +} + static int echo_can_create(struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct echo_can_state **ec) { @@ -670,14 +751,12 @@ static int echo_can_create(struct dahdi_echocanparams *ecp, struct dahdi_echocan 2 * sizeof(short) * (maxu) + /* u_s */ 2 * sizeof(short) * ecp->tap_length; /* y_tilde_s */ - if (!(*ec = MALLOC(size))) + if (!(*ec = kmalloc(size, GFP_KERNEL))) return -ENOMEM; memset(*ec, 0, size); -#ifdef AGGRESSIVE_SUPPRESSOR - (*ec)->aggressive = 1; -#endif + (*ec)->aggressive = aggressive; for (x = 0; x < ecp->param_count; x++) { for (c = p[x].name; *c; c++) @@ -697,7 +776,7 @@ static int echo_can_create(struct dahdi_echocanparams *ecp, struct dahdi_echocan return 0; } -static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val) +static int echo_can_traintap(struct echo_can_state *ec, int pos, short val) { /* Set the hangover counter to the length of the can to * avoid adjustments occuring immediately after initial forced training @@ -722,4 +801,39 @@ static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short va return 0; } -#endif +static const struct dahdi_echocan me = { + .name = "MG2", + .owner = THIS_MODULE, + .echo_can_create = echo_can_create, + .echo_can_free = echo_can_free, + .echo_can_array_update = echo_can_update, + .echo_can_traintap = echo_can_traintap, +}; + +static int __init mod_init(void) +{ + if (dahdi_register_echocan(&me)) { + module_printk(KERN_ERR, "could not register with DAHDI core\n"); + + return -EPERM; + } + + module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", me.name); + + return 0; +} + +static void __exit mod_exit(void) +{ + dahdi_unregister_echocan(&me); +} + +module_param(debug, int, S_IRUGO | S_IWUSR); +module_param(aggressive, int, S_IRUGO | S_IWUSR); + +MODULE_DESCRIPTION("DAHDI 'MG2' Echo Canceler"); +MODULE_AUTHOR("Michael Gernoth"); +MODULE_LICENSE("GPL v2"); + +module_init(mod_init); +module_exit(mod_exit); diff --git a/drivers/dahdi/sec.h b/drivers/dahdi/dahdi_echocan_sec.c index 4c8bd69..dd0a7f4 100644 --- a/drivers/dahdi/sec.h +++ b/drivers/dahdi/dahdi_echocan_sec.c @@ -37,22 +37,20 @@ Improve double talk detector (iterative!) */ -#ifndef _DAHDI_SEC_H -#define _DAHDI_SEC_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> -#define MALLOC(a) malloc(a) -#define FREE(a) free(a) -#endif +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/ctype.h> +#include <linux/moduleparam.h> + +#include <dahdi/kernel.h> + +static int debug; + +#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args) +#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args) #include "arith.h" @@ -100,23 +98,6 @@ struct echo_can_state was skipped, for test purposes */ }; -static void echo_can_init(void) -{ - printk("DAHDI Echo Canceller: STEVE%s\n", DAHDI_ECHO_AGGRESSIVE); -} - -static void echo_can_identify(char *buf, size_t len) -{ - dahdi_copy_string(buf, "STEVE", len); -} - -static void echo_can_shutdown(void) -{ -} - -static void echo_can_free(struct echo_can_state *ec); -static int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx); - /* Original parameters : #define MIN_TX_POWER_FOR_ADAPTION 256 #define MIN_RX_POWER_FOR_ADAPTION 128 @@ -142,7 +123,7 @@ static int echo_can_create(struct dahdi_echocanparams *ecp, struct dahdi_echocan size = sizeof(**ec) + ecp->tap_length * sizeof(int32_t) + ecp->tap_length * 3 * sizeof(int16_t); - if (!(*ec = MALLOC(size))) + if (!(*ec = kmalloc(size, GFP_KERNEL))) return -ENOMEM; memset(*ec, 0, size); @@ -165,13 +146,13 @@ static int echo_can_create(struct dahdi_echocanparams *ecp, struct dahdi_echocan } /*- End of function --------------------------------------------------------*/ -static inline void echo_can_free(struct echo_can_state *ec) +static void echo_can_free(struct echo_can_state *ec) { - FREE(ec); + kfree(ec); } /*- End of function --------------------------------------------------------*/ -static inline int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx) +static inline int16_t sample_update(struct echo_can_state *ec, int16_t tx, int16_t rx) { int32_t echo_value; int clean_rx; @@ -292,7 +273,19 @@ static inline int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int } /*- End of function --------------------------------------------------------*/ -static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val) +static void echo_can_update(struct echo_can_state *ec, short *iref, short *isig) +{ + unsigned int x; + short result; + + for (x = 0; x < DAHDI_CHUNKSIZE; x++) { + result = sample_update(ec, *iref, *isig); + *isig++ = result; + } +} +/*- End of function --------------------------------------------------------*/ + +static int echo_can_traintap(struct echo_can_state *ec, int pos, short val) { /* Reset hang counter to avoid adjustments after initial forced training */ @@ -305,6 +298,40 @@ static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short va return 1; return 0; } +/*- End of function --------------------------------------------------------*/ -/*- End of file ------------------------------------------------------------*/ -#endif +static const struct dahdi_echocan me = { + .name = "SEC", + .owner = THIS_MODULE, + .echo_can_create = echo_can_create, + .echo_can_free = echo_can_free, + .echo_can_array_update = echo_can_update, + .echo_can_traintap = echo_can_traintap, +}; + +static int __init mod_init(void) +{ + if (dahdi_register_echocan(&me)) { + module_printk(KERN_ERR, "could not register with DAHDI core\n"); + + return -EPERM; + } + + module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", me.name); + + return 0; +} + +static void __exit mod_exit(void) +{ + dahdi_unregister_echocan(&me); +} + +module_param(debug, int, S_IRUGO | S_IWUSR); + +MODULE_DESCRIPTION("DAHDI 'SEC' Echo Canceler"); +MODULE_AUTHOR("Steve Underwood <steveu@coppice.org>"); +MODULE_LICENSE("GPL"); + +module_init(mod_init); +module_exit(mod_exit); diff --git a/drivers/dahdi/sec-2.h b/drivers/dahdi/dahdi_echocan_sec2.c index 2a498e1..399d714 100644 --- a/drivers/dahdi/sec-2.h +++ b/drivers/dahdi/dahdi_echocan_sec2.c @@ -36,22 +36,20 @@ Improve double talk detector (iterative!) */ -#ifndef _DAHDI_SEC_H -#define _DAHDI_SEC_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> -#define MALLOC(a) malloc(a) -#define FREE(a) free(a) -#endif +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/ctype.h> +#include <linux/moduleparam.h> + +#include <dahdi/kernel.h> + +static int debug; + +#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args) +#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args) #include "fir.h" @@ -97,23 +95,6 @@ struct echo_can_state was skipped, for test purposes */ }; -static void echo_can_free(struct echo_can_state *ec); -static int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx); - -static void echo_can_init(void) -{ - printk("DAHDI Echo Canceller: STEVE2%s\n", DAHDI_ECHO_AGGRESSIVE); -} - -static void echo_can_identify(char *buf, size_t len) -{ - dahdi_copy_string(buf, "STEVE2", len); -} - -static void echo_can_shutdown(void) -{ -} - /* * According to Jim... */ @@ -138,7 +119,7 @@ static int echo_can_create(struct dahdi_echocanparams *ecp, struct dahdi_echocan size = sizeof(**ec) + ecp->tap_length * sizeof(int32_t) + ecp->tap_length * 3 * sizeof(int16_t); - if (!(*ec = MALLOC(size))) + if (!(*ec = kmalloc(size, GFP_KERNEL))) return -ENOMEM; memset(*ec, 0, size); @@ -160,14 +141,14 @@ static int echo_can_create(struct dahdi_echocanparams *ecp, struct dahdi_echocan } /*- End of function --------------------------------------------------------*/ -static inline void echo_can_free(struct echo_can_state *ec) +static void echo_can_free(struct echo_can_state *ec) { fir16_free(&ec->fir_state); - FREE(ec); + kfree(ec); } /*- End of function --------------------------------------------------------*/ -static inline int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx) +static inline int16_t sample_update(struct echo_can_state *ec, int16_t tx, int16_t rx) { int offset1; int offset2; @@ -297,143 +278,21 @@ static inline int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int return clean_rx; } +/*- End of function --------------------------------------------------------*/ -#if 0 -static inline int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx) +static void echo_can_update(struct echo_can_state *ec, short *iref, short *isig) { - int offset; - int limit; - int32_t echo_value; - int clean_rx; - int nsuppr; - int i; - int correction; - - ec->tx_history[ec->curr_pos] = tx; - - /* Evaluate the echo - i.e. apply the FIR filter */ - /* Assume the gain of the FIR does not exceed unity. Exceeding unity - would seem like a rather poor thing for an echo cancellor to do :) - This means we can compute the result with a total disregard for - overflows. 16bits x 16bits -> 31bits, so no overflow can occur in - any multiply. While accumulating we may overflow and underflow the - 32 bit scale often. However, if the gain does not exceed unity, - everything should work itself out, and the final result will be - OK, without any saturation logic. */ - /* Overflow is very much possible here, and we do nothing about it because - of the compute costs */ - /* 16 bit coeffs for the LMS give lousy results (maths good, actual sound - bad!), but 32 bit coeffs require some shifting. On balance 32 bit seems - best */ - offset = ec->curr_pos; - limit = ec->taps - offset; - echo_value = 0; - for (i = 0; i < limit; i++) - echo_value += (ec->fir_taps[i] >> 16)*ec->tx_history[i + offset]; - offset = ec->taps - ec->curr_pos; - for ( ; i < ec->taps; i++) - echo_value += (ec->fir_taps[i] >> 16)*ec->tx_history[i - offset]; - echo_value >>= 16; - - /* And the answer is..... */ - clean_rx = rx - echo_value; - - /* That was the easy part. Now we need to adapt! */ - if (ec->nonupdate_dwell > 0) - ec->nonupdate_dwell--; - - /* If there is very little being transmitted, any attempt to train is - futile. We would either be training on the far end's noise or signal, - the channel's own noise, or our noise. Either way, this is hardly good - training, so don't do it (avoid trouble). */ - /* If the received power is very low, either we are sending very little or - we are already well adapted. There is little point in trying to improve - the adaption under these circumstanceson, so don't do it (reduce the - compute load). */ - if (ec->tx_power > MIN_TX_POWER_FOR_ADAPTION - && - ec->rx_power > MIN_RX_POWER_FOR_ADAPTION) - { - /* This is a really crude piece of decision logic, but it does OK - for now. */ - if (ec->tx_power > 2*ec->rx_power) - { - /* There is no far-end speech detected */ - if (ec->nonupdate_dwell == 0) - { - /* ... and we are not in the dwell time from previous speech. */ - //nsuppr = saturate((clean_rx << 16)/ec->tx_power); - nsuppr = clean_rx >> 3; + unsigned int x; + short result; - /* Update the FIR taps */ - offset = ec->curr_pos; - limit = ec->taps - offset; - ec->latest_correction = 0; - for (i = 0; i < limit; i++) - { - correction = ec->tx_history[i + offset]*nsuppr; - ec->fir_taps[i] += correction; - //ec->latest_correction += abs(correction); - } - offset = ec->taps - ec->curr_pos; - for ( ; i < ec->taps; i++) - { - correction = ec->tx_history[i - offset]*nsuppr; - ec->fir_taps[i] += correction; - //ec->latest_correction += abs(correction); - } - } - else - { - ec->latest_correction = -3; - } - } - else - { - ec->nonupdate_dwell = NONUPDATE_DWELL_TIME; - ec->latest_correction = -2; + for (x = 0; x < DAHDI_CHUNKSIZE; x++) { + result = sample_update(ec, *iref, *isig); + *isig++ = result; } - } - else - { - ec->nonupdate_dwell = 0; - ec->latest_correction = -1; - } - /* Calculate short term power levels using very simple single pole IIRs */ - /* TODO: Is the nasty modulus approach the fastest, or would a real - tx*tx power calculation actually be faster? */ - ec->tx_power += ((abs(tx) - ec->tx_power) >> 5); - ec->rx_power += ((abs(rx) - ec->rx_power) >> 5); - ec->clean_rx_power += ((abs(clean_rx) - ec->clean_rx_power) >> 5); - -#if defined(XYZZY) - if (ec->use_suppressor) - { - ec->supp_test1 += (ec->tx_history[ec->curr_pos] - ec->tx_history[(ec->curr_pos - 7) & ec->tap_mask]); - ec->supp_test2 += (ec->tx_history[(ec->curr_pos - 24) & ec->tap_mask] - ec->tx_history[(ec->curr_pos - 31) & ec->tap_mask]); - if (ec->supp_test1 > 42 && ec->supp_test2 > 42) - supp_change = 25; - else - supp_change = 50; - supp = supp_change + k1*ec->supp1 + k2*ec->supp2; - ec->supp2 = ec->supp1; - ec->supp1 = supp; - clean_rx *= (1 - supp); - } -#endif - - if (ec->use_nlp && ec->rx_power < 32) - clean_rx = 0; - - /* Roll around the rolling buffer */ - ec->curr_pos = (ec->curr_pos + 1) & ec->tap_mask; - - return clean_rx; } /*- End of function --------------------------------------------------------*/ -#endif -static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val) +static int echo_can_traintap(struct echo_can_state *ec, int pos, short val) { /* Reset hang counter to avoid adjustments after initial forced training */ @@ -447,5 +306,38 @@ static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short va return 0; } -/*- End of file ------------------------------------------------------------*/ -#endif +static const struct dahdi_echocan me = { + .name = "SEC2", + .owner = THIS_MODULE, + .echo_can_create = echo_can_create, + .echo_can_free = echo_can_free, + .echo_can_array_update = echo_can_update, + .echo_can_traintap = echo_can_traintap, +}; + +static int __init mod_init(void) +{ + if (dahdi_register_echocan(&me)) { + module_printk(KERN_ERR, "could not register with DAHDI core\n"); + + return -EPERM; + } + + module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", me.name); + + return 0; +} + +static void __exit mod_exit(void) +{ + dahdi_unregister_echocan(&me); +} + +module_param(debug, int, S_IRUGO | S_IWUSR); + +MODULE_DESCRIPTION("DAHDI 'SEC2' Echo Canceler"); +MODULE_AUTHOR("Steve Underwood <steveu@coppice.org>"); +MODULE_LICENSE("GPL"); + +module_init(mod_init); +module_exit(mod_exit); diff --git a/drivers/dahdi/dahdi_transcode.c b/drivers/dahdi/dahdi_transcode.c index df11dce..31352ef 100644 --- a/drivers/dahdi/dahdi_transcode.c +++ b/drivers/dahdi/dahdi_transcode.c @@ -441,7 +441,7 @@ static struct dahdi_chardev transcode_chardev = { .minor = 250, }; -int zttranscode_init(void) +int dahdi_transcode_init(void) { int res; @@ -460,7 +460,7 @@ int zttranscode_init(void) return 0; } -void zttranscode_cleanup(void) +void dahdi_transcode_cleanup(void) { dahdi_unregister_chardev(&transcode_chardev); @@ -473,9 +473,7 @@ module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_DESCRIPTION("DAHDI Transcoder Support"); MODULE_AUTHOR("Mark Spencer <markster@digium.com>"); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif +MODULE_LICENSE("GPL v2"); -module_init(zttranscode_init); -module_exit(zttranscode_cleanup); +module_init(dahdi_transcode_init); +module_exit(dahdi_transcode_cleanup); diff --git a/drivers/dahdi/datamods/syncppp.c b/drivers/dahdi/datamods/syncppp.c index 5ca283a..2b63a01 100644 --- a/drivers/dahdi/datamods/syncppp.c +++ b/drivers/dahdi/datamods/syncppp.c @@ -1481,5 +1481,4 @@ static void __exit sync_ppp_cleanup(void) module_init(sync_ppp_init); module_exit(sync_ppp_cleanup); module_param(debug, int, 0); -MODULE_LICENSE("GPL"); - +MODULE_LICENSE("GPL v2"); diff --git a/drivers/dahdi/fir.h b/drivers/dahdi/fir.h index 1722285..ee8cffe 100644 --- a/drivers/dahdi/fir.h +++ b/drivers/dahdi/fir.h @@ -51,7 +51,7 @@ static inline void fir16_create (fir16_state_t *fir, fir->taps = taps; fir->curr_pos = taps - 1; fir->coeffs = coeffs; - fir->history = MALLOC (taps*sizeof (int16_t)); + fir->history = kmalloc(taps*sizeof (int16_t), GFP_KERNEL); if (fir->history) memset (fir->history, '\0', taps*sizeof (int16_t)); } @@ -59,7 +59,7 @@ static inline void fir16_create (fir16_state_t *fir, static inline void fir16_free (fir16_state_t *fir) { - FREE (fir->history); + kfree(fir->history); } /*- End of function --------------------------------------------------------*/ @@ -92,7 +92,7 @@ static inline void fir32_create (fir32_state_t *fir, fir->taps = taps; fir->curr_pos = taps - 1; fir->coeffs = coeffs; - fir->history = MALLOC (taps*sizeof (int16_t)); + fir->history = kmalloc(taps*sizeof (int16_t), GFP_KERNEL); if (fir->history) memset (fir->history, '\0', taps*sizeof (int16_t)); } @@ -100,7 +100,7 @@ static inline void fir32_create (fir32_state_t *fir, static inline void fir32_free (fir32_state_t *fir) { - FREE (fir->history); + kfree(fir->history); } /*- End of function --------------------------------------------------------*/ diff --git a/drivers/dahdi/hpec/hpec_dahdi.h b/drivers/dahdi/hpec/dahdi_echocan_hpec.c index bb54e8e..5da8c8c 100644 --- a/drivers/dahdi/hpec/hpec_dahdi.h +++ b/drivers/dahdi/hpec/dahdi_echocan_hpec.c @@ -1,14 +1,13 @@ /* * DAHDI Telephony Interface to Digium High-Performance Echo Canceller * - * Copyright (C) 2006 Digium, Inc. + * Copyright (C) 2006-2008 Digium, Inc. * * 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. + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -20,10 +19,19 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#if !defined(_HPEC_DAHDI_H) -#define _HPEC_DAHDI_H +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/ctype.h> +#include <linux/moduleparam.h> -#define DAHDI_EC_ARRAY_UPDATE +#include <dahdi/kernel.h> + +static int debug; + +#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args) +#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args) #include "hpec_user.h" #include "hpec.h" @@ -59,28 +67,12 @@ static void memfree(void *ptr) kfree(ptr); } -static void echo_can_init(void) -{ - printk("DAHDI Echo Canceller: Digium High-Performance Echo Canceller\n"); - hpec_init(logger, debug, DAHDI_CHUNKSIZE, memalloc, memfree); -} - -static void echo_can_identify(char *buf, size_t len) -{ - dahdi_copy_string(buf, "HPEC", len); -} - -static void echo_can_shutdown(void) -{ - hpec_shutdown(); -} - -static inline void echo_can_free(struct echo_can_state *ec) +static void echo_can_free(struct echo_can_state *ec) { hpec_channel_free(ec); } -static inline void echo_can_array_update(struct echo_can_state *ec, short *iref, short *isig) +static void echo_can_array_update(struct echo_can_state *ec, short *iref, short *isig) { hpec_channel_update(ec, iref, isig); } @@ -143,4 +135,46 @@ static int hpec_license_ioctl(unsigned int cmd, unsigned long data) } } -#endif /* !defined(_HPEC_DAHDI_H) */ +static const struct dahdi_echocan me = { + .name = "HPEC", + .owner = THIS_MODULE, + .echo_can_create = echo_can_create, + .echo_can_free = echo_can_free, + .echo_can_array_update = echo_can_array_update, + .echo_can_traintap = echo_can_traintap, +}; + +static int __init mod_init(void) +{ + if (dahdi_register_echocan(&me)) { + module_printk(KERN_ERR, "could not register with DAHDI core\n"); + + return -EPERM; + } + + module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", me.name); + + hpec_init(logger, debug, DAHDI_CHUNKSIZE, memalloc, memfree); + + dahdi_set_hpec_ioctl(hpec_license_ioctl); + + return 0; +} + +static void __exit mod_exit(void) +{ + dahdi_unregister_echocan(&me); + + dahdi_set_hpec_ioctl(NULL); + + hpec_shutdown(); +} + +module_param(debug, int, S_IRUGO | S_IWUSR); + +MODULE_DESCRIPTION("DAHDI High Performance Echo Canceller"); +MODULE_AUTHOR("Kevin P. Fleming <kpfleming@digium.com>"); +MODULE_LICENSE("Digium Commercial"); + +module_init(mod_init); +module_exit(mod_exit); diff --git a/drivers/dahdi/jpah.h b/drivers/dahdi/jpah.h deleted file mode 100644 index 72b4d00..0000000 --- a/drivers/dahdi/jpah.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * ECHO_CAN_JP1 - * - * by Jason Parker - * - * Based upon mg2ec.h - sort of. - * This "echo can" will completely hose your audio. - * Don't use it unless you're absolutely sure you know what you're doing. - * - * Copyright (C) 2007, 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 _JP_ECHO_H -#define _JP_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> -#define MALLOC(a) malloc(a) -#define FREE(a) free(a) -#endif - -/* Echo canceller definition */ -struct echo_can_state { - /* an arbitrary ID for this echo can - this really should be settable from the calling channel... */ - int id; - - /* absolute time - aka. sample number index - essentially the number of samples since this can was init'ed */ - int i_d; -}; - -static void echo_can_init(void) -{ - printk("DAHDI Audio Hoser: JP1\n"); -} - -static void echo_can_identify(char *buf, size_t len) -{ - dahdi_copy_string(buf, "JP1", len); -} - -static void echo_can_shutdown(void) -{ -} - -static inline void init_cc(struct echo_can_state *ec) -{ - void *ptr = ec; - unsigned long tmp; - /* Double-word align past end of state */ - ptr += sizeof(struct echo_can_state); - tmp = (unsigned long)ptr; - tmp += 3; - tmp &= ~3L; - ptr = (void *)tmp; -} - -static inline void echo_can_free(struct echo_can_state *ec) -{ - FREE(ec); -} - -static inline short echo_can_update(struct echo_can_state *ec, short iref, short isig) -{ - static int blah = 0; - - if (blah < 2) { - blah++; - return 0; - } else { - blah = (blah + 1) % 3; - return isig; - } -} - -static inline struct echo_can_state *echo_can_create(int len, int adaption_mode) -{ - struct echo_can_state *ec; - ec = (struct echo_can_state *)MALLOC(sizeof(struct echo_can_state) + 4); /* align */ - if (ec) { - memset(ec, 0, sizeof(struct echo_can_state) + 4); /* align */ - init_cc(ec); - } - return ec; -} - -static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val) -{ - return 0; -} -#endif diff --git a/drivers/dahdi/kb1ec_const.h b/drivers/dahdi/kb1ec_const.h deleted file mode 100644 index 0849b14..0000000 --- a/drivers/dahdi/kb1ec_const.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - Important constants for tuning kb1 echo can - */ -#ifndef _MEC2_CONST_H -#define _MEC2_CONST_H - - -/* Convergence (aka. adaptation) speed -- higher means slower */ -#define DEFAULT_BETA1_I 2048 - -/* Constants for various power computations */ -#define DEFAULT_SIGMA_LY_I 7 -#define DEFAULT_SIGMA_LU_I 7 -#define DEFAULT_ALPHA_ST_I 5 /* near-end speech detection sensitivity factor */ -#define DEFAULT_ALPHA_YT_I 5 - -#define DEFAULT_CUTOFF_I 128 - -/* Define the near-end speech hangover counter: if near-end speech - * is declared, hcntr is set equal to hangt (see pg. 432) - */ -#define DEFAULT_HANGT 600 /* in samples, so 600 samples = 75ms */ - -/* define the residual error suppression threshold */ -#define DEFAULT_SUPPR_I 16 /* 16 = -24db */ - -/* This is the minimum reference signal power estimate level - * that will result in filter adaptation. - * If this is too low then background noise will cause the filter - * coefficients to constantly be updated. - */ -#define MIN_UPDATE_THRESH_I 4096 - -/* The number of samples used to update coefficients using the - * the block update method (M). It should be related back to the - * length of the echo can. - * ie. it only updates coefficients when (sample number MOD default_m) = 0 - * - * Getting this wrong may cause an oops. Consider yourself warned! - */ -#define DEFAULT_M 16 /* every 16th sample */ - -/* If AGGRESSIVE supression is enabled, then we start cancelling residual - * echos again even while there is potentially the very end of a near-side - * signal present. - * This defines how many samples of DEFAULT_HANGT can remain before we - * kick back in - */ -#define AGGRESSIVE_HCNTR 160 /* in samples, so 160 samples = 20ms */ - - -/***************************************************************/ -/* The following knobs are not implemented in the current code */ - -/* we need a dynamic level of suppression varying with the ratio of the - power of the echo to the power of the reference signal this is - done so that we have a smoother background. - we have a higher suppression when the power ratio is closer to - suppr_ceil and reduces logarithmically as we approach suppr_floor. - */ -#define SUPPR_FLOOR -64 -#define SUPPR_CEIL -24 - -/* in a second departure, we calculate the residual error suppression - * as a percentage of the reference signal energy level. The threshold - * is defined in terms of dB below the reference signal. - */ -#define RES_SUPR_FACTOR -20 - - -#endif /* _MEC2_CONST_H */ - diff --git a/drivers/dahdi/mg2ec_const.h b/drivers/dahdi/mg2ec_const.h deleted file mode 100644 index 08fd897..0000000 --- a/drivers/dahdi/mg2ec_const.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - Important constants for tuning mg2 echo can - */ -#ifndef _MG2_CONST_H -#define _MG2_CONST_H - - -/* Convergence (aka. adaptation) speed -- higher means slower */ -#define DEFAULT_BETA1_I 2048 - -/* Constants for various power computations */ -#define DEFAULT_SIGMA_LY_I 7 -#define DEFAULT_SIGMA_LU_I 7 -#define DEFAULT_ALPHA_ST_I 5 /* near-end speech detection sensitivity factor */ -#define DEFAULT_ALPHA_YT_I 5 - -#define DEFAULT_CUTOFF_I 128 - -/* Define the near-end speech hangover counter: if near-end speech - * is declared, hcntr is set equal to hangt (see pg. 432) - */ -#define DEFAULT_HANGT 600 /* in samples, so 600 samples = 75ms */ - -/* define the residual error suppression threshold */ -#define DEFAULT_SUPPR_I 16 /* 16 = -24db */ - -/* This is the minimum reference signal power estimate level - * that will result in filter adaptation. - * If this is too low then background noise will cause the filter - * coefficients to constantly be updated. - */ -#define MIN_UPDATE_THRESH_I 2048 - -/* The number of samples used to update coefficients using the - * the block update method (M). It should be related back to the - * length of the echo can. - * ie. it only updates coefficients when (sample number MOD default_m) = 0 - * - * Getting this wrong may cause an oops. Consider yourself warned! - */ -#define DEFAULT_M 16 /* every 16th sample */ - -/* If AGGRESSIVE supression is enabled, then we start cancelling residual - * echos again even while there is potentially the very end of a near-side - * signal present. - * This defines how many samples of DEFAULT_HANGT can remain before we - * kick back in - */ -#define AGGRESSIVE_HCNTR 160 /* in samples, so 160 samples = 20ms */ - -/* Treat sample as error if it has a different sign as the - * input signal and is this number larger in ABS() as - * the input-signal */ -#define MAX_SIGN_ERROR 3000 - -/* Number of coefficients really used for calculating the - * simulated echo. The value specifies how many of the - * biggest coefficients are used for calculating rs. - * This helps on long echo-tails by artificially limiting - * the number of coefficients for the calculation and - * preventing overflows. - * Comment this to deactivate the code */ -#define USED_COEFFS 64 - -/* Backup coefficients every this number of samples */ -#define BACKUP 256 - -/***************************************************************/ -/* The following knobs are not implemented in the current code */ - -/* we need a dynamic level of suppression varying with the ratio of the - power of the echo to the power of the reference signal this is - done so that we have a smoother background. - we have a higher suppression when the power ratio is closer to - suppr_ceil and reduces logarithmically as we approach suppr_floor. - */ -#define SUPPR_FLOOR -64 -#define SUPPR_CEIL -24 - -/* in a second departure, we calculate the residual error suppression - * as a percentage of the reference signal energy level. The threshold - * is defined in terms of dB below the reference signal. - */ -#define RES_SUPR_FACTOR -20 - - -#endif /* _MG2_CONST_H */ - diff --git a/drivers/dahdi/pciradio.c b/drivers/dahdi/pciradio.c index 1f90af3..30d49d1 100644 --- a/drivers/dahdi/pciradio.c +++ b/drivers/dahdi/pciradio.c @@ -1888,10 +1888,7 @@ module_param(debug, int, 0600); MODULE_DESCRIPTION("DAHDI Telephony PCI Radio Card Driver"); MODULE_AUTHOR("Jim Dixon <jim@lambdatel.com>"); - -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif +MODULE_LICENSE("GPL v2"); module_init(pciradio_init); module_exit(pciradio_cleanup); diff --git a/drivers/dahdi/tor2.c b/drivers/dahdi/tor2.c index 6fab600..2f51403 100644 --- a/drivers/dahdi/tor2.c +++ b/drivers/dahdi/tor2.c @@ -1483,9 +1483,7 @@ static int tor2_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long d MODULE_AUTHOR("Mark Spencer"); MODULE_DESCRIPTION("Tormenta 2 PCI Quad T1 or E1 DAHDI Driver"); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif +MODULE_LICENSE("GPL v2"); module_param(debug, int, 0600); module_param(loopback, int, 0600); diff --git a/drivers/dahdi/wcfxo.c b/drivers/dahdi/wcfxo.c index c641aa6..f369225 100644 --- a/drivers/dahdi/wcfxo.c +++ b/drivers/dahdi/wcfxo.c @@ -1061,9 +1061,7 @@ module_param(opermode, int, 0444); MODULE_DESCRIPTION("Wildcard X100P DAHDI Driver"); MODULE_AUTHOR("Mark Spencer <markster@digium.com>"); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif +MODULE_LICENSE("GPL v2"); module_init(wcfxo_init); module_exit(wcfxo_cleanup); diff --git a/drivers/dahdi/wct1xxp.c b/drivers/dahdi/wct1xxp.c index 0814e85..54377bf 100644 --- a/drivers/dahdi/wct1xxp.c +++ b/drivers/dahdi/wct1xxp.c @@ -1407,9 +1407,7 @@ module_param(debug, int, 0600); MODULE_DESCRIPTION("Wildcard T100P/E100P DAHDI Driver"); MODULE_AUTHOR("Mark Spencer <markster@digium.com>"); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif +MODULE_LICENSE("GPL v2"); module_init(t1xxp_init); module_exit(t1xxp_cleanup); diff --git a/drivers/dahdi/wct4xxp/base.c b/drivers/dahdi/wct4xxp/base.c index 8e38a01..66d1433 100644 --- a/drivers/dahdi/wct4xxp/base.c +++ b/drivers/dahdi/wct4xxp/base.c @@ -3799,12 +3799,9 @@ static void __exit t4_cleanup(void) MODULE_AUTHOR("Mark Spencer"); MODULE_DESCRIPTION("Unified TE4XXP-TE2XXP PCI Driver"); -#if defined(MODULE_ALIAS) MODULE_ALIAS("wct2xxp"); -#endif -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif +MODULE_LICENSE("GPL v2"); + module_param(pedanticpci, int, 0600); module_param(debug, int, 0600); module_param(loopback, int, 0600); diff --git a/drivers/dahdi/wctc4xxp/base.c b/drivers/dahdi/wctc4xxp/base.c index b0705bf..635c797 100644 --- a/drivers/dahdi/wctc4xxp/base.c +++ b/drivers/dahdi/wctc4xxp/base.c @@ -2013,11 +2013,10 @@ module_param(debug_des_cnt, int, S_IRUGO | S_IWUSR); module_param(debug_notimeout, int, S_IRUGO | S_IWUSR); module_param(force_alert, int, S_IRUGO | S_IWUSR); module_param(mode, charp, S_IRUGO | S_IWUSR); + MODULE_DESCRIPTION("Wildcard TC400P+TC400M Driver"); MODULE_AUTHOR("John Sloan <jsloan@digium.com>"); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif +MODULE_LICENSE("GPL v2"); module_init(ztdte_init); module_exit(ztdte_cleanup); diff --git a/drivers/dahdi/wctdm.c b/drivers/dahdi/wctdm.c index a086223..a50aeff 100644 --- a/drivers/dahdi/wctdm.c +++ b/drivers/dahdi/wctdm.c @@ -2498,12 +2498,8 @@ module_param(fxsrxgain, int, 0600); MODULE_DESCRIPTION("Wildcard TDM400P DAHDI Driver"); MODULE_AUTHOR("Mark Spencer <markster@digium.com>"); -#if defined(MODULE_ALIAS) MODULE_ALIAS("wcfxs"); -#endif -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif +MODULE_LICENSE("GPL v2"); module_init(wctdm_init); module_exit(wctdm_cleanup); diff --git a/drivers/dahdi/wctdm24xxp/base.c b/drivers/dahdi/wctdm24xxp/base.c index d5bbb7e..1e45884 100644 --- a/drivers/dahdi/wctdm24xxp/base.c +++ b/drivers/dahdi/wctdm24xxp/base.c @@ -4009,12 +4009,8 @@ module_param(vpmnlpmaxsupp, int, 0600); MODULE_DESCRIPTION("Wildcard TDM2400P/TDM800P DAHDI Driver"); MODULE_AUTHOR("Mark Spencer <markster@digium.com>"); -#if defined(MODULE_ALIAS) MODULE_ALIAS("wctdm8xxp"); -#endif -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif +MODULE_LICENSE("GPL v2"); module_init(wctdm_init); module_exit(wctdm_cleanup); diff --git a/drivers/dahdi/wcte11xp.c b/drivers/dahdi/wcte11xp.c index 824e8e1..f454bc4 100644 --- a/drivers/dahdi/wcte11xp.c +++ b/drivers/dahdi/wcte11xp.c @@ -1611,9 +1611,7 @@ module_param(j1mode, int, 0600); MODULE_DESCRIPTION("Wildcard TE110P DAHDI Driver"); MODULE_AUTHOR("Mark Spencer <markster@digium.com>"); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif +MODULE_LICENSE("GPL v2"); module_init(t1xxp_init); module_exit(t1xxp_cleanup); diff --git a/drivers/dahdi/wcte12xp/base.c b/drivers/dahdi/wcte12xp/base.c index e98cc35..422b704 100644 --- a/drivers/dahdi/wcte12xp/base.c +++ b/drivers/dahdi/wcte12xp/base.c @@ -1725,9 +1725,7 @@ module_param(vpmdtmfsupport, int, S_IRUGO | S_IWUSR); module_param(vpmtsisupport, int, S_IRUGO | S_IWUSR); #endif -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif +MODULE_LICENSE("GPL v2"); module_init(te12xp_init); module_exit(te12xp_cleanup); |