Compare commits

...

11 Commits

Author SHA1 Message Date
Nadi Sarrar 06244ce555 remove deprecated misdn-init and update Makefile and README 2007-04-03 08:39:08 +00:00
Chrisian Richter 434e78c55a committed kwenzels modification to read out the DIP switches on all boards where it is possible, for that we enlarged the PCI_ENTRY struct with a DIP Capability :) . also moved a few While Loops to For Loops which is much more easy to read. fixed also the behaviour of the LEDs, and made an improvement regarding I/O when setting the LED state. also some fixes regarding the ztdummy timer-register stuff, like we don't unregister when we never have registered before. 2007-04-03 07:28:40 +00:00
Nadi Sarrar 749541c595 make the protocol parameters available via sysfs. i.e.
/sys/class/mISDN-stacks/st-00000100/protocol
contains the protocol parameter value from the first stack.
2007-04-02 15:39:31 +00:00
Nadi Sarrar 7eae689857 don't load hfcmulti if no hfcmulti cards configured 2007-03-28 11:06:06 +00:00
Nadi Sarrar fc7d16fd5d adding a hackisch buildin pipeline element to make use of the hw echocanceller 2007-03-27 10:27:54 +00:00
Nadi Sarrar 3adb3ed79d remove kernel type from header, update Makefile to reflect the changes in Makefile.v2.6 2007-03-26 14:46:29 +00:00
Nadi Sarrar c8210a32da merge with r1.28 2007-03-26 14:45:10 +00:00
Chrisian Richter dd092efb7e workaround for Kernel Oops.. fixing real root soon :) 2007-03-23 17:31:13 +00:00
Nadi Sarrar 35da393f82 Adding the octware GPL'ed echo canceller kernel module. To make it work, you will
need the octvqed userspace daemon.
2007-03-23 15:30:46 +00:00
Nadi Sarrar eeb7623c7e very simple audio pipeline implementation, dsp modules can register themselves
as pipeline elements and the pipeline is configured with a configuration string
via a new PH_CONTROL parameter: PIPELINE_CFG.
The config-string is as follows: mec2(training=1)|kb1ec
With this example, the audio data would flow through mec2 (instantiated with the
parameter-string "training=1") and then through kb1ec (instantiated without
parameters).
The three echo cancellers are now build as separate modules, named mISDN_dsp_*.
2007-03-23 13:50:06 +00:00
Nadi Sarrar 9fb78bc0c9 very simple audio pipeline implementation, dsp modules can register themselves
as pipeline elements and the pipeline is configured with a configuration string
via a new PH_CONTROL parameter: PIPELINE_CFG.
The config-string is as follows: mec2(training=1)|kb1ec
With this example, the audio data would flow through mec2 (instantiated with the
parameter-string "training=1") and then through kb1ec (instantiated without
parameters).
The three echo cancellers are now build as separate modules, named mISDN_dsp_*.
2007-03-23 13:48:57 +00:00
33 changed files with 3095 additions and 1637 deletions

View File

@ -51,7 +51,7 @@ all: VERSION test_old_misdn
cp $(MISDNDIR)/drivers/isdn/hardware/mISDN/Makefile.v2.6 $(MISDNDIR)/drivers/isdn/hardware/mISDN/Makefile
export MINCLUDES=$(MISDNDIR)/include ; export MISDNVERSION=$(MISDNVERSION); make -C $(LINUX) SUBDIRS=$(MISDN_SRC) modules $(CONFIGS)
install: all modules-install misdn-init
install: all modules-install
$(DEPMOD)
$(UPDATE_MODULES)
$(MODULES_UPDATE)
@ -62,18 +62,6 @@ modules-install:
mkdir -p $(INSTALL_PREFIX)/usr/include/linux/
cp $(MISDNDIR)/include/linux/*.h $(INSTALL_PREFIX)/usr/include/linux/
misdn-init:
mkdir -p $(INSTALL_PREFIX)/usr/sbin/
install -m755 misdn-init $(INSTALL_PREFIX)/usr/sbin/
if [ -d $(INSTALL_PREFIX)/etc/init.d ]; then \
if [ -e $(INSTALL_PREFIX)/etc/init.d/misdn-init ]; then rm -rf $(INSTALL_PREFIX)/etc/init.d/misdn-init; fi; \
ln -s $(INSTALL_PREFIX)/usr/sbin/misdn-init $(INSTALL_PREFIX)/etc/init.d/misdn-init; \
fi
mkdir -p $(INSTALL_PREFIX)/etc/modprobe.d
cp mISDN.modprobe.d $(INSTALL_PREFIX)/etc/modprobe.d/mISDN
mkdir -p $(INSTALL_PREFIX)/etc/modules.d
cp mISDN.modprobe.d $(INSTALL_PREFIX)/etc/modules.d/mISDN
test_old_misdn:
@if echo -ne "#include <linux/mISDNif.h>" | gcc -C -E - 2>/dev/null 1>/dev/null ; then \
if ! echo -ne "#include <linux/mISDNif.h>\n#if MISDN_MAJOR_VERSION < 4\n#error old mISDNif.h\n#endif\n" | gcc -C -E - 2>/dev/null 1>/dev/null ; then \
@ -85,7 +73,7 @@ test_old_misdn:
.PHONY: modules-install install all clean misdn-init VERSION
.PHONY: modules-install install all clean VERSION
force:
rm -f $(LINUX)/include/linux/mISDNif.h

View File

@ -1,55 +0,0 @@
misdn-init: init-script to auto-configure and load the mISDN kernel drivers
===========================================================================
This script makes it easy to configure and activate mISDN compatible
adapter cards. It scans an eyecandy config file named misdn-init.conf
for your card and port settings, then it loads the driver modules properly.
The misdn-init.conf can also be autogenerated by the misdn-init script.
---------------------------------------------------------------------------
Usage: /usr/sbin/misdn-init start|stop|restart|config|scan|help
--start scan /etc/misdn-init.conf and load the mISDN drivers
--stop unload the mISDN drivers
--restart see stop, then start
--config scan your PCI bus for mISDN compatible hardware and generate
a /etc/misdn-init.conf
--scan scan your PCI bus for mISDN compatible hardware and print
the results to the console
--help print the usage info
---------------------------------------------------------------------------
* Here is a quick overview on how to use misdn-init:
1) Get and install misdn-init:
$ wget http://www.beronet.com/downloads/chan_misdn/stable/chan_misdn.tar.gz
$ tar zxf chan_misdn.tar.gz
$ (as root) cp chan_misdn/misdn-init /usr/sbin/misdn-init
2) Let misdn-init scan your PCI bus for mISDN compatible hardware and write
the results into /etc/misdn-init.conf:
$ (as root) /usr/sbin/misdn-init config
3) (optional) Edit /etc/misdn-init.conf and set everything the way you want it.
This file is heavily commented, hence it should be self-explaining.
4) (optional, but recommended) Add misdn-init to your run level.
This is distribution dependend. Here an example for a debian system:
ATTENTION: If you have services in your runlevels that depend
on mISDN, make sure that misdn-init starts before, and
stops after them (this is done by changing the values
that are set to 60 in this example, more info: read the
manpage for update-rc.d).
$ (as root) update-rc.d misdn-init start 60 2 3 4 5 . stop 60 0 1 6 .
5) Run the following to start mISDN:
$ (as root) /usr/sbin/misdn-init start
---------------------------------------------------------------------------
* Report Bugs:
If you experience any bugs or have a feature request, please visit:
www.isdn4linux.de/mantis

View File

@ -3,7 +3,7 @@
This script makes it easy to configure and activate mISDN compatible
adapter cards. It scans an eyecandy config file named mISDN.conf
for your card and port settings, then it loads the driver modules properly.
The misdn-init.conf can also be autogenerated by the mISDN script.
The mISDN.conf can also be autogenerated by the mISDN script.
---------------------------------------------------------------------------
@ -17,9 +17,9 @@ xsltproc on debian, just type:
On other distros the package name might be libxmtools or likewise.
---------------------------------------------------------------------------
Usage: /usr/sbin/misdn-init start|stop|restart|config|scan|help
Usage: /usr/sbin/mISDN start|stop|restart|config|scan|help
--start scan /etc/misdn-init.conf and load the mISDN drivers
--start scan /etc/mISDN.conf and load the mISDN drivers
--stop unload the mISDN drivers
--restart see stop, then start
--config scan your PCI bus for mISDN compatible hardware and generate

View File

@ -84,7 +84,7 @@ declare -a SCAN_port_opts
function parse_config
{
local CONFIG=$(${XSLTPROC} ${MISDN_CONF_XSL} ${MISDN_CONF})
local t p l line i tmpcmd curr tmpstr
local t p l line i tmpcmd curr tmpstr extra_modules
local IFS=$'\n'
START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install capi"
@ -113,6 +113,9 @@ function parse_config
MODULE:hfcmulti*)
HFCMULTI_options=${line:16}
;;
MODULE:mISDN_dsp_*)
extra_modules[${#extra_modules[@]}]=${line:7}
;;
MODULE:mISDN_dsp*)
MISDNDSP_options=${line:17}
;;
@ -161,26 +164,28 @@ function parse_config
;;
esac
done
tmpcmd="${MODPROBE} --ignore-install hfcmulti type=${HFCMULTI_type[0]}"
i=1
while [ ! -z "${HFCMULTI_type[${i}]}" ]; do
tmpcmd="${tmpcmd},${HFCMULTI_type[${i}]}"
let "i = ${i} + 1"
done
tmpcmd="${tmpcmd} protocol=${HFCMULTI_protocol[0]}"
i=1
while [ ! -z "${HFCMULTI_protocol[${i}]}" ]; do
tmpcmd="${tmpcmd},${HFCMULTI_protocol[${i}]}"
let "i = ${i} + 1"
done
tmpcmd="${tmpcmd} layermask=${HFCMULTI_layermask[0]}"
i=1
while [ ! -z "${HFCMULTI_layermask[${i}]}" ]; do
tmpcmd="${tmpcmd},${HFCMULTI_layermask[${i}]}"
let "i = ${i} + 1"
done
START_COMMANDS[${#START_COMMANDS[@]}]="${tmpcmd} ${HFCMULTI_options}"
if [ ! -z "${HFCMULTI_protocol[0]}" ]; then
tmpcmd="${MODPROBE} --ignore-install hfcmulti type=${HFCMULTI_type[0]}"
i=1
while [ ! -z "${HFCMULTI_type[${i}]}" ]; do
tmpcmd="${tmpcmd},${HFCMULTI_type[${i}]}"
let "i = ${i} + 1"
done
tmpcmd="${tmpcmd} protocol=${HFCMULTI_protocol[0]}"
i=1
while [ ! -z "${HFCMULTI_protocol[${i}]}" ]; do
tmpcmd="${tmpcmd},${HFCMULTI_protocol[${i}]}"
let "i = ${i} + 1"
done
tmpcmd="${tmpcmd} layermask=${HFCMULTI_layermask[0]}"
i=1
while [ ! -z "${HFCMULTI_layermask[${i}]}" ]; do
tmpcmd="${tmpcmd},${HFCMULTI_layermask[${i}]}"
let "i = ${i} + 1"
done
START_COMMANDS[${#START_COMMANDS[@]}]="${tmpcmd} ${HFCMULTI_options}"
fi
if [ ! -z "${HFCPCI_protocol}" ]; then
START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install hfcpci protocol=${HFCPCI_protocol} layermask=${HFCPCI_layermask}"
@ -191,6 +196,12 @@ function parse_config
fi
START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install mISDN_dsp ${MISDNDSP_options}"
i=1
while [ ! -z "${extra_modules[${i}]}" ]; do
START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install ${extra_modules[${i}]}"
let "i = ${i} + 1"
done
}
function run_start_commands
@ -211,7 +222,7 @@ function run_stop_commands
for mod in $(lsmod | ${SED} -ne '/Module/!{s/\([^ ]*\).*/\1/;p}'); do
case "${mod}" in
mISDN_capi | mISDN_dsp | l3udss1 | mISDN_l2 | mISDN_l1 | mISDN_isac | hfcmulti | avmfritz)
mISDN_capi | mISDN_dsp* | l3udss1 | mISDN_l2 | mISDN_l1 | mISDN_isac | hfcmulti | avmfritz)
STOP_COMMANDS[0]="${STOP_COMMANDS[0]:-"${MODPROBE} -r --ignore-remove"} ${mod}"
;;
mISDN_core)
@ -332,6 +343,9 @@ Options: debug=<number>, options=<number>, poll=<number>,
<mISDNconf>
${TAB}<module poll=\"128\" debug=\"0\" timer=\"no\">hfcmulti</module>
${TAB}<module debug=\"0\" options=\"0\">mISDN_dsp</module>
${TAB}<module>mISDN_dsp_mec2</module>
${TAB}<module>mISDN_dsp_mg2ec</module>
${TAB}<module>mISDN_dsp_kb1ec</module>
${TAB}<devnode user=\"root\" group=\"root\" mode=\"644\">mISDN</devnode>"
local FOOTER="</mISDNconf>"
local i=0 j=0 MAIN=""

View File

@ -84,21 +84,19 @@
<xsl:with-param name="match-true">te</xsl:with-param>
<xsl:with-param name="match-false">nt</xsl:with-param>
<xsl:with-param name="val-true">34</xsl:with-param>
<xsl:with-param name="val-false">18</xsl:with-param>
<xsl:with-param name="val-false">50</xsl:with-param>
<xsl:with-param name="val-default">34</xsl:with-param>
</xsl:call-template>
<xsl:text>+</xsl:text>
<xsl:if test="@mode!='nt'">
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@link" />
<xsl:with-param name="match-true">ptp</xsl:with-param>
<xsl:with-param name="match-false">ptmp</xsl:with-param>
<xsl:with-param name="val-true">0</xsl:with-param>
<xsl:with-param name="val-false">(-32)</xsl:with-param>
<xsl:with-param name="val-default">(-32)</xsl:with-param>
</xsl:call-template>
<xsl:text>+</xsl:text>
</xsl:if>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@link" />
<xsl:with-param name="match-true">ptp</xsl:with-param>
<xsl:with-param name="match-false">ptmp</xsl:with-param>
<xsl:with-param name="val-true">0</xsl:with-param>
<xsl:with-param name="val-false">(-32)</xsl:with-param>
<xsl:with-param name="val-default">(-32)</xsl:with-param>
</xsl:call-template>
<xsl:text>+</xsl:text>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@master-clock" />
<xsl:with-param name="val-true">(2**16)</xsl:with-param>

View File

@ -29,6 +29,12 @@
<xsl:call-template name="MISDNDSPmodule" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat('MODULE:',.)" />
<xsl:text>
</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>

View File

@ -63,7 +63,7 @@ obj-$(CONFIG_MISDN_DRV) += xhfc.o
endif
ifdef CONFIG_MISDN_DSP
obj-$(CONFIG_MISDN_DRV) += mISDN_dsp.o
obj-$(CONFIG_MISDN_DRV) += mISDN_dsp.o mISDN_dsp_mec2.o mISDN_dsp_kb1ec.o mISDN_dsp_mg2ec.o mISDN_dsp_octwareec.o
endif
ifdef CONFIG_MISDN_LOOP
@ -105,7 +105,11 @@ mISDN_capi-objs := capi.o contr.o listen.o appl.o plci.o app_plci.o ncci.o asn1.
asn1_basic_service.o asn1_address.o asn1_enc.o capi_enc.o \
supp_serv.o
mISDN_dtmf-objs := dtmf.o
mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o dsp_cancel.o
mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o dsp_pipeline.o dsp_hwec.o
mISDN_dsp_mec2-objs := dsp_mec2.o
mISDN_dsp_kb1ec-objs := dsp_kb1ec.o
mISDN_dsp_mg2ec-objs := dsp_mg2ec.o
mISDN_dsp_octwareec-objs := dsp_octwareec.o
mISDN_loop-objs := loop.o
mISDN_x25dte-objs := x25_dte.o x25_l3.o
I4LmISDN-objs := i4l_mISDN.o

View File

@ -63,7 +63,7 @@ obj-$(CONFIG_MISDN_DRV) += xhfc.o
endif
ifdef CONFIG_MISDN_DSP
obj-$(CONFIG_MISDN_DRV) += mISDN_dsp.o
obj-$(CONFIG_MISDN_DRV) += mISDN_dsp.o mISDN_dsp_mec2.o mISDN_dsp_kb1ec.o mISDN_dsp_mg2ec.o mISDN_dsp_octwareec.o
endif
ifdef CONFIG_MISDN_LOOP
@ -105,7 +105,11 @@ mISDN_capi-objs := capi.o contr.o listen.o appl.o plci.o app_plci.o ncci.o asn1.
asn1_basic_service.o asn1_address.o asn1_enc.o capi_enc.o \
supp_serv.o
mISDN_dtmf-objs := dtmf.o
mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o dsp_cancel.o
mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o dsp_pipeline.o dsp_hwec.o
mISDN_dsp_mec2-objs := dsp_mec2.o
mISDN_dsp_kb1ec-objs := dsp_kb1ec.o
mISDN_dsp_mg2ec-objs := dsp_mg2ec.o
mISDN_dsp_octwareec-objs := dsp_octwareec.o
mISDN_loop-objs := loop.o
mISDN_x25dte-objs := x25_dte.o x25_l3.o
I4LmISDN-objs := i4l_mISDN.o

View File

@ -39,26 +39,6 @@
#include "dsp_ecdis.h"
/*
* You are now able to choose between the Mark2 and the
* kb1 Echo cancellor. Just comment the one and comment
* out the other.
*/
//#define AGGRESSIVE_SUPPRESSOR
//#include "dsp_mec2.h"
//#include "dsp_kb1ec.h"
#include "dsp_mg2ec.h"
/*
* uncomment this one to cancel echo more aggressive
*/
//#define AGGRESSIVE_SUPPRESSOR
extern int dsp_options;
extern int dsp_debug;
extern int dsp_poll;
@ -148,11 +128,13 @@ typedef struct _dtmf_t {
} dtmf_t;
/****************
* cancel stuff *
****************/
/******************
* pipeline stuff *
******************/
typedef struct _dsp_pipeline {
rwlock_t lock;
struct list_head list;
} dsp_pipeline_t;
/***************
* tones stuff *
@ -238,26 +220,7 @@ typedef struct _dsp {
u8 bf_data_out[9];
int bf_sync;
/* echo cancellation stuff */
int queue_cancel[3];
int cancel_enable;
int cancel_hardware; /*we are using hw echo canc*/
struct echo_can_state * ec; /**< == NULL: echo cancellation disabled;
!= NULL: echo cancellation enabled */
echo_can_disable_detector_state_t* ecdis_rd;
echo_can_disable_detector_state_t* ecdis_wr;
uint16_t echotimer;
uint16_t echostate;
uint16_t echolastupdate;
char txbuf[ECHOCAN_BUFLEN];
int txbuflen;
char rxbuf[ECHOCAN_BUFLEN];
int rxbuflen;
dsp_pipeline_t pipeline;
} dsp_t;
/* functions */
@ -290,8 +253,11 @@ extern void dsp_bf_decrypt(dsp_t *dsp, u8 *data, int len);
extern int dsp_bf_init(dsp_t *dsp, const u8 *key, unsigned int keylen);
extern void dsp_bf_cleanup(dsp_t *dsp);
extern void dsp_cancel_tx(dsp_t *dsp, u8 *data, int len);
extern void dsp_cancel_rx(dsp_t *dsp, u8 *data, int len);
extern int dsp_cancel_init(dsp_t *dsp, int taps, int training, int delay);
extern int dsp_pipeline_module_init (void);
extern void dsp_pipeline_module_exit (void);
extern int dsp_pipeline_init (dsp_pipeline_t *pipeline);
extern void dsp_pipeline_destroy (dsp_pipeline_t *pipeline);
extern int dsp_pipeline_build (dsp_pipeline_t *pipeline, const char *cfg);
extern void dsp_pipeline_process_tx (dsp_pipeline_t *pipeline, u8 *data, int len);
extern void dsp_pipeline_process_rx (dsp_pipeline_t *pipeline, u8 *data, int len);

View File

@ -153,9 +153,11 @@ s32 dsp_audio_alaw_to_s32[256] =
};
s32 *dsp_audio_law_to_s32;
EXPORT_SYMBOL(dsp_audio_law_to_s32);
/* signed 16-bit -> law */
u8 dsp_audio_s16_to_law[65536];
EXPORT_SYMBOL(dsp_audio_s16_to_law);
/* table is used to generate s16_to_alaw */
static short dsp_audio_alaw_relations[512] =

View File

@ -1,350 +0,0 @@
/*
*
* Simple but fast Echo cancellation for mISDN_dsp.
*
* Copyright Chrisian Richter
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "layer1.h"
#include "helper.h"
#include "debug.h"
#include "dsp.h"
#ifdef ARCH_I386
#include <asm/i387.h>
#else
#define kernel_fpu_begin()
#define kernel_fpu_end()
#endif
/*
* how this works:
*
*
*
*/
/*
* send HW message to hfc card
*/
static void
dsp_cancel_hw_message(dsp_t *dsp, u32 message, u32 param)
{
struct sk_buff *nskb;
nskb = create_link_skb(PH_CONTROL | REQUEST, message, sizeof(param), &param, 0);
if (!nskb) {
printk(KERN_ERR "%s: No mem for skb.\n", __FUNCTION__);
return;
}
/* unlocking is not required, because we don't expect a response */
if (mISDN_queue_down(&dsp->inst, 0, nskb))
dev_kfree_skb(nskb);
}
void bchdev_echocancel_chunk(dsp_t* dev, uint8_t *rxchunk, uint8_t *txchunk, uint16_t size);
int bchdev_echocancel_activate(dsp_t* dev, int deftaps, int train);
void bchdev_echocancel_deactivate(dsp_t* dev);
void
dsp_cancel_tx(dsp_t *dsp, u8 *data, int len)
{
if (!dsp ) return ;
if (!data) return;
if (dsp->txbuflen + len < ECHOCAN_BUFLEN) {
memcpy(&dsp->txbuf[dsp->txbuflen],data,len);
dsp->txbuflen+=len;
} else {
static int i=0;
if(i==4000) {
printk("ECHOCAN: i:%d TXBUF Overflow txbuflen:%d txcancellen:%d\n", i, dsp->txbuflen,len);
i=0;
}
i+=len;
dsp->txbuflen=0;
}
}
void
dsp_cancel_rx(dsp_t *dsp, u8 *data, int len)
{
if (!dsp ) return ;
if (!data) return;
if (len <= dsp->txbuflen) {
char tmp[ECHOCAN_BUFLEN];
int delta=dsp->txbuflen-len;
memcpy(tmp,&dsp->txbuf[len],delta);
kernel_fpu_begin();
bchdev_echocancel_chunk(dsp, data, dsp->txbuf, len);
kernel_fpu_end();
memcpy(dsp->txbuf,tmp,delta);
dsp->txbuflen=delta;
} else {
static int i=0;
if(i==4000) {
printk("ECHOCAN: i:%d TXBUF Underrun txbuflen:%d rxcancellen:%d\n",i,dsp->txbuflen,len);
i=0;
}
i+=len;
}
}
int
dsp_cancel_init(dsp_t *dsp, int deftaps, int training, int delay)
{
if (!dsp) return -1;
if (dsp->feature_state != FEAT_STATE_RECEIVED) {
dsp->queue_cancel[0]=deftaps;
dsp->queue_cancel[1]=training;
dsp->queue_cancel[2]=delay;
return 0;
}
//printk("DSP_CANCEL_INIT called\n");
if (delay < 0)
{
//printk(KERN_NOTICE "Disabling EC\n");
dsp->cancel_enable = 0;
dsp->txbuflen=0;
if (dsp->features.hfc_echocanhw) {
//printk(KERN_NOTICE "Disabling Hardware EC\n");
dsp_cancel_hw_message(dsp, HW_ECHOCAN_OFF, deftaps);
} else {
bchdev_echocancel_deactivate(dsp);
}
return(0);
}
if (dsp->features.hfc_echocanhw) {
//printk(KERN_NOTICE "Using Hardware EC taps [%d]\n",deftaps);
dsp_cancel_hw_message(dsp, HW_ECHOCAN_ON, deftaps);
return 0;
}
dsp->txbuflen=0;
dsp->rxbuflen=0;
bchdev_echocancel_activate(dsp,deftaps, training);
//printk("Enabling EC\n");
dsp->cancel_enable = 1;
return(0);
}
/*****************************************************/
#define __ECHO_STATE_MUTE (1 << 8)
#define ECHO_STATE_IDLE (0)
#define ECHO_STATE_PRETRAINING (1 | (__ECHO_STATE_MUTE))
#define ECHO_STATE_STARTTRAINING (2 | (__ECHO_STATE_MUTE))
#define ECHO_STATE_AWAITINGECHO (3 | (__ECHO_STATE_MUTE))
#define ECHO_STATE_TRAINING (4 | (__ECHO_STATE_MUTE))
#define ECHO_STATE_ACTIVE (5)
#define AMI_MASK 0x55
/** @return string of given echo cancellation state */
char* bchdev_echocancel_statestr(uint16_t state)
{
switch(state) {
case ECHO_STATE_IDLE:
return "idle";
break;
case ECHO_STATE_PRETRAINING:
return "pre-training";
break;
case ECHO_STATE_STARTTRAINING:
return "transmit impulse";
break;
case ECHO_STATE_AWAITINGECHO:
return "awaiting echo";
break;
case ECHO_STATE_TRAINING:
return "training start";
break;
case ECHO_STATE_ACTIVE:
return "training finished";
break;
default:
return "unknown";
}
}
/** Changes state of echo cancellation to given state */
void bchdev_echocancel_setstate(dsp_t* dev, uint16_t state)
{
#if 0
char* statestr = bchdev_echocancel_statestr(state);
printk("bchdev: echo cancel state %d (%s)\n", state & 0xff, statestr);
if (state == ECHO_STATE_ACTIVE)
printk("bchdev: %d taps trained\n", dev->echolastupdate);
#endif
dev->echostate = state;
}
static int buf_size=0;
static int ec_timer=2000;
//static int ec_timer=1000;
/** Activates echo cancellation for the given bch_dev, device must have been locked before! */
int bchdev_echocancel_activate(dsp_t* dev, int deftaps, int training)
{
int taps;
if (! dev) return -EINVAL;
if (dev->ec && dev->ecdis_rd && dev->ecdis_wr) {
// already active
return 0;
}
if (deftaps>0) {
taps=deftaps;
} else {
taps=128;
}
switch (buf_size) {
case 0: taps += 0; break;
case 1: taps += 256-128; break;
case 2: taps += 512-128; break;
default: taps += 1024-128;
}
if (!dev->ec) dev->ec = echo_can_create(taps, 0);
if (!dev->ec) {
return -ENOMEM;
}
dev->echolastupdate = 0;
if (!training) {
dev->echotimer=0;
bchdev_echocancel_setstate(dev, ECHO_STATE_IDLE);
} else {
if (training<10)
training= ec_timer;
dev->echotimer = training;
bchdev_echocancel_setstate(dev, ECHO_STATE_PRETRAINING);
}
if (!dev->ecdis_rd) dev->ecdis_rd = kmalloc(sizeof(echo_can_disable_detector_state_t), GFP_ATOMIC);
if (!dev->ecdis_rd) {
kfree(dev->ec); dev->ec = NULL;
return -ENOMEM;
}
echo_can_disable_detector_init(dev->ecdis_rd);
if (!dev->ecdis_wr) dev->ecdis_wr = kmalloc(sizeof(echo_can_disable_detector_state_t), GFP_ATOMIC);
if (!dev->ecdis_wr) {
kfree(dev->ec); dev->ec = NULL;
kfree(dev->ecdis_rd); dev->ecdis_rd = NULL;
return -ENOMEM;
}
echo_can_disable_detector_init(dev->ecdis_wr);
return 0;
}
/** Deactivates echo cancellation for the given bch_dev, device must have been locked before! */
void bchdev_echocancel_deactivate(dsp_t* dev)
{
if (! dev) return;
//chan_misdn_log("bchdev: deactivating echo cancellation on port=%04x, chan=%02x\n", dev->stack->port, dev->channel);
if (dev->ec) echo_can_free(dev->ec);
dev->ec = NULL;
dev->echolastupdate = 0;
dev->echotimer = 0;
bchdev_echocancel_setstate(dev, ECHO_STATE_IDLE);
if (dev->ecdis_rd) kfree(dev->ecdis_rd);
dev->ecdis_rd = NULL;
if (dev->ecdis_wr) kfree(dev->ecdis_wr);
dev->ecdis_wr = NULL;
}
/** Processes one TX- and one RX-packet with echocancellation */
void bchdev_echocancel_chunk(dsp_t* ss, uint8_t *rxchunk, uint8_t *txchunk, uint16_t size)
{
int16_t rxlin, txlin;
uint16_t x;
/* Perform echo cancellation on a chunk if requested */
if (ss->ec) {
if (ss->echostate & __ECHO_STATE_MUTE) {
/* Special stuff for training the echo can */
for (x=0;x<size;x++) {
rxlin = dsp_audio_law_to_s32[rxchunk[x]];
txlin = dsp_audio_law_to_s32[txchunk[x]];
if (ss->echostate == ECHO_STATE_PRETRAINING) {
if (--ss->echotimer <= 0) {
ss->echotimer = 0;
ss->echostate = ECHO_STATE_STARTTRAINING;
}
}
if ((ss->echostate == ECHO_STATE_AWAITINGECHO) && (txlin > 8000)) {
ss->echolastupdate = 0;
ss->echostate = ECHO_STATE_TRAINING;
}
if (ss->echostate == ECHO_STATE_TRAINING) {
if (echo_can_traintap(ss->ec, ss->echolastupdate++, rxlin)) {
#if 0
printk("Finished training (%d taps trained)!\n", ss->echolastupdate);
#endif
ss->echostate = ECHO_STATE_ACTIVE;
}
}
rxlin = 0;
rxchunk[x] = dsp_audio_s16_to_law[(int)rxlin];
}
} else {
for (x=0;x<size;x++) {
rxlin = dsp_audio_law_to_s32[rxchunk[x]&0xff];
txlin = dsp_audio_law_to_s32[txchunk[x]&0xff];
rxlin = echo_can_update(ss->ec, txlin, rxlin);
rxchunk[x] = dsp_audio_s16_to_law[rxlin &0xffff];
}
}
}
}
/******************************************************/

View File

@ -0,0 +1,180 @@
/*
* dsp_cancel.h: worker functions for various echo cancellers
*
* Copyright (C) 2007, Nadi Sarrar
*
* Nadi Sarrar <nadi@beronet.com>
*
* Derived from dsp_cancel.c written by Chrisian Richter.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
*/
#include "layer1.h"
#include "helper.h"
#include "debug.h"
#include "dsp.h"
#ifdef ARCH_I386
#include <asm/i387.h>
#else
#define kernel_fpu_begin()
#define kernel_fpu_end()
#endif
#define EC_TIMER 2000
#define __ECHO_STATE_MUTE (1 << 8)
#define ECHO_STATE_IDLE (0)
#define ECHO_STATE_PRETRAINING (1 | (__ECHO_STATE_MUTE))
#define ECHO_STATE_STARTTRAINING (2 | (__ECHO_STATE_MUTE))
#define ECHO_STATE_AWAITINGECHO (3 | (__ECHO_STATE_MUTE))
#define ECHO_STATE_TRAINING (4 | (__ECHO_STATE_MUTE))
#define ECHO_STATE_ACTIVE (5)
#define AMI_MASK 0x55
typedef struct _ec_prv_t {
struct echo_can_state * ec;
uint16_t echotimer;
uint16_t echostate;
uint16_t echolastupdate;
char txbuf[ECHOCAN_BUFLEN];
int txbuflen;
char rxbuf[ECHOCAN_BUFLEN];
int rxbuflen;
int underrun;
int overflow;
} ec_prv_t;
static inline void *dsp_cancel_new (int deftaps, int training)
{
ec_prv_t *p;
p = kmalloc(sizeof(ec_prv_t), GFP_KERNEL);
if (!p)
goto _err1;
p->ec = echo_can_create(deftaps > 0 ? deftaps : 128, 0);
if (!p->ec)
goto _err2;
p->echotimer = training ? training : 0;
p->echostate = training ? ECHO_STATE_PRETRAINING : ECHO_STATE_IDLE;
p->echolastupdate = 0;
p->txbuflen = 0;
p->rxbuflen = 0;
p->underrun = 0;
p->overflow = 0;
return p;
_err2:
kfree(p);
_err1:
return NULL;
}
static inline void dsp_cancel_free (ec_prv_t *p)
{
if (!p)
return;
echo_can_free(p->ec);
kfree(p);
}
/** Processes one TX- and one RX-packet with echocancellation */
static inline void echocancel_chunk(ec_prv_t* p, uint8_t *rxchunk, uint8_t *txchunk, uint16_t size)
{
int16_t rxlin, txlin;
uint16_t x;
if (p->echostate & __ECHO_STATE_MUTE) {
/* Special stuff for training the echo can */
for (x=0;x<size;x++) {
rxlin = dsp_audio_law_to_s32[rxchunk[x]];
txlin = dsp_audio_law_to_s32[txchunk[x]];
if (p->echostate == ECHO_STATE_PRETRAINING) {
if (--p->echotimer <= 0) {
p->echotimer = 0;
p->echostate = ECHO_STATE_STARTTRAINING;
}
}
if ((p->echostate == ECHO_STATE_AWAITINGECHO) && (txlin > 8000)) {
p->echolastupdate = 0;
p->echostate = ECHO_STATE_TRAINING;
}
if (p->echostate == ECHO_STATE_TRAINING) {
if (echo_can_traintap(p->ec, p->echolastupdate++, rxlin)) {
p->echostate = ECHO_STATE_ACTIVE;
}
}
rxlin = 0;
rxchunk[x] = dsp_audio_s16_to_law[(int)rxlin];
}
} else {
for (x=0;x<size;x++) {
rxlin = dsp_audio_law_to_s32[rxchunk[x]&0xff];
txlin = dsp_audio_law_to_s32[txchunk[x]&0xff];
rxlin = echo_can_update(p->ec, txlin, rxlin);
rxchunk[x] = dsp_audio_s16_to_law[rxlin &0xffff];
}
}
}
static inline void dsp_cancel_tx (ec_prv_t *p, u8 *data, int len)
{
if (!p || !data)
return;
if (p->txbuflen + len < ECHOCAN_BUFLEN) {
memcpy(&p->txbuf[p->txbuflen], data, len);
p->txbuflen += len;
} else {
if (p->overflow >= 4000) {
printk("ECHOCAN: TXBUF Overflow:%d txbuflen:%d txcancellen:%d\n", p->overflow, p->txbuflen, len);
p->overflow = 0;
}
p->overflow += len;
p->txbuflen = 0;
}
}
static inline void dsp_cancel_rx (ec_prv_t *p, u8 *data, int len)
{
if (!p || !data)
return;
if (len <= p->txbuflen) {
char tmp[ECHOCAN_BUFLEN];
int delta = p->txbuflen - len;
memcpy(tmp, &p->txbuf[len], delta);
kernel_fpu_begin();
echocancel_chunk(p, data, p->txbuf, len);
kernel_fpu_end();
memcpy(p->txbuf, tmp, delta);
p->txbuflen = delta;
} else {
if (p->underrun >= 4000) {
printk("ECHOCAN: TXBUF Underrun:%d txbuflen:%d rxcancellen:%d\n", p->underrun, p->txbuflen,len);
p->underrun = 0;
}
p->underrun += len;
}
}

View File

@ -526,12 +526,14 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
printk(KERN_DEBUG "%s dsp %s cannot form a conf, because encryption is enabled\n", __FUNCTION__, member->dsp->inst.name);
goto conf_software;
}
#if 0
/* check if echo cancellation is enabled */
if (member->dsp->cancel_enable) {
if (dsp_debug & DEBUG_DSP_CMX)
printk(KERN_DEBUG "%s dsp %s cannot form a conf, because echo cancellation is enabled\n", __FUNCTION__, member->dsp->inst.name);
goto conf_software;
}
#endif
/* check if member is on a card with PCM support */
if (member->dsp->features.pcm_id < 0) {
if (dsp_debug & DEBUG_DSP_CMX)
@ -1220,9 +1222,11 @@ send_packet:
if (dsp->tx_volume)
dsp_change_volume(nskb, dsp->tx_volume);
#if 0
/* cancel echo */
if (dsp->cancel_enable)
dsp_cancel_tx(dsp, nskb->data, nskb->len);
#endif
/* crypt */
if (dsp->bf_enable)

View File

@ -32,7 +32,7 @@
* - (4) echo generation for delay test
* - (5) volume control
* - (6) disable receive data
* - (7) echo cancelation
* - (7) pipelined audio processing
* - (8) encryption/decryption
*
* Look:
@ -71,7 +71,7 @@
* +----+-------------+----+
* |(7) |
* | |
* | Echo Cancellation |
* | Pipelined Processing |
* | |
* | |
* +----+-------------+----+
@ -364,26 +364,12 @@ dsp_control_req(dsp_t *dsp, mISDN_head_t *hh, struct sk_buff *skb)
if (dsp_debug & DEBUG_DSP_CMX)
dsp_cmx_debug(dsp);
break;
case ECHOCAN_ON: /* turn echo calcellation on */
if (len<4) {
case PIPELINE_CFG:
if (len > 0 && ((char *)data)[len - 1]) {
printk(KERN_DEBUG "%s: pipeline config string is not NULL terminated!\n", __FUNCTION__);
ret = -EINVAL;
} else {
int ec_arr[2];
memcpy(&ec_arr,data,sizeof(ec_arr));
if (dsp_debug & DEBUG_DSP_CORE)
printk(KERN_DEBUG "%s: turn echo cancelation on (delay=%d attenuation-shift=%d\n",
__FUNCTION__, ec_arr[0], ec_arr[1]);
ret = dsp_cancel_init(dsp, ec_arr[0], ec_arr[1] ,1);
dsp_cmx_hardware(dsp->conf, dsp);
}
break;
case ECHOCAN_OFF: /* turn echo calcellation off */
if (dsp_debug & DEBUG_DSP_CORE)
printk(KERN_DEBUG "%s: turn echo cancelation off\n", __FUNCTION__);
ret = dsp_cancel_init(dsp, 0,0,-1);
dsp_cmx_hardware(dsp->conf, dsp);
} else
ret = dsp_pipeline_build(&dsp->pipeline, len > 0 ? (char *)data : NULL);
break;
case BF_ENABLE_KEY: /* turn blowfish on */
if (len<4 || len>56) {
@ -461,9 +447,8 @@ dsp_from_up(mISDNinstance_t *inst, struct sk_buff *skb)
if (dsp->tx_volume)
dsp_change_volume(skb, dsp->tx_volume);
/* cancel echo */
if (dsp->cancel_enable)
dsp_cancel_tx(dsp, skb->data, skb->len);
/* pipeline */
dsp_pipeline_process_tx(&dsp->pipeline, skb->data, skb->len);
/* crypt */
if (dsp->bf_enable)
dsp_bf_encrypt(dsp, skb->data, skb->len);
@ -476,6 +461,11 @@ dsp_from_up(mISDNinstance_t *inst, struct sk_buff *skb)
}
} else {
if (dsp->features.pcm_id>=0) {
printk("Not sending Data to CMX -- > returning because of HW bridge\n");
dev_kfree_skb(skb);
break;
}
/* send data to tx-buffer (if no tone is played) */
spin_lock_irqsave(&dsp_obj.lock, flags);
if (!dsp->tone.tone) {
@ -564,9 +554,8 @@ dsp_from_down(mISDNinstance_t *inst, struct sk_buff *skb)
/* decrypt if enabled */
if (dsp->bf_enable)
dsp_bf_decrypt(dsp, skb->data, skb->len);
/* if echo cancellation is enabled */
if (dsp->cancel_enable)
dsp_cancel_rx(dsp, skb->data, skb->len);
/* pipeline */
dsp_pipeline_process_rx(&dsp->pipeline, skb->data, skb->len);
/* check if dtmf soft decoding is turned on */
if (dsp->dtmf.software) {
digits = dsp_dtmf_goertzel_decode(dsp, skb->data, skb->len, (dsp_options&DSP_OPT_ULAW)?1:0);
@ -738,6 +727,8 @@ release_dsp(dsp_t *dsp)
}
}
dsp_pipeline_destroy(&dsp->pipeline);
if (dsp_debug & DEBUG_DSP_MGR)
printk(KERN_DEBUG "%s: remove & destroy object %s\n", __FUNCTION__, dsp->inst.name);
list_del(&dsp->list);
@ -802,15 +793,6 @@ dsp_feat(void *arg)
if (dsp_debug & DEBUG_DSP_CMX)
dsp_cmx_debug(dsp);
}
if (dsp->queue_cancel[2]) {
dsp_cancel_init(dsp,
dsp->queue_cancel[0],
dsp->queue_cancel[1],
dsp->queue_cancel[2]
);
}
break;
}
@ -838,6 +820,9 @@ new_dsp(mISDNstack_t *st, mISDN_pid_t *pid)
}
memset(ndsp, 0, sizeof(dsp_t));
memcpy(&ndsp->inst.pid, pid, sizeof(mISDN_pid_t));
dsp_pipeline_init(&ndsp->pipeline);
mISDN_init_instance(&ndsp->inst, &dsp_obj, ndsp, dsp_function);
if (!mISDN_SetHandledPID(&dsp_obj, &ndsp->inst.pid)) {
int_error();
@ -968,7 +953,7 @@ static int dsp_init(void)
dsp_debug = debug;
/* display revision */
printk(KERN_INFO "mISDN_dsp: Audio DSP Rev. %s (debug=0x%x) EchoCancellor %s dtmfthreshold(%d)\n", mISDN_getrev(dsp_revision), debug, EC_TYPE, dtmfthreshold);
printk(KERN_INFO "mISDN_dsp: Audio DSP Rev. %s (debug=0x%x) dtmfthreshold(%d)\n", mISDN_getrev(dsp_revision), debug, dtmfthreshold);
/* set packet size */
if (poll == 0) {
@ -1017,6 +1002,12 @@ static int dsp_init(void)
dsp_audio_generate_ulaw_samples();
dsp_audio_generate_volume_changes();
/* initialize pipeline */
if ((err = dsp_pipeline_module_init())) {
printk(KERN_ERR "mISDN_dsp: Can't initialize pipeline, %s, error(%d)\n", DSPName, err);
return(err);
}
/* register object */
if ((err = mISDN_register(&dsp_obj))) {
printk(KERN_ERR "mISDN_dsp: Can't register %s error(%d)\n", DSPName, err);
@ -1065,6 +1056,8 @@ static void dsp_cleanup(void)
if (!list_empty(&Conf_list)) {
printk(KERN_ERR "mISDN_dsp: Conference list not empty. Not all memory freed.\n");
}
dsp_pipeline_module_exit();
}
#ifdef MODULE

View File

@ -0,0 +1,127 @@
/*
* dsp_hwec.c: builtin mISDN dsp pipeline element for enabling the hw echocanceller
*
* Copyright (C) 2007, Nadi Sarrar
*
* Nadi Sarrar <nadi@beronet.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
*/
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/mISDNdsp.h>
#include <linux/mISDNif.h>
#include "dsp.h"
#include "helper.h"
static mISDN_dsp_element_t dsp_hwec_p = {
.new = NULL,
.free = NULL,
.process_tx = NULL,
.process_rx = NULL,
.name = "hwec",
};
mISDN_dsp_element_t *dsp_hwec = &dsp_hwec_p;
void dsp_hwec_enable (dsp_t *dsp, const char *arg)
{
struct sk_buff *skb;
int deftaps = 128,
len;
if (!dsp) {
printk(KERN_ERR "%s: failed to enable hwec: dsp is NULL\n", __FUNCTION__);
return;
}
if (!arg)
goto _do;
len = strlen(arg);
if (!len)
goto _do;
{
char _dup[len + 1];
char *dup, *tok, *name, *val;
int tmp;
strcpy(_dup, arg);
dup = _dup;
while ((tok = strsep(&dup, ","))) {
if (!strlen(tok))
continue;
name = strsep(&tok, "=");
val = tok;
if (!val)
continue;
if (!strcmp(name, "deftaps")) {
if (sscanf(val, "%d", &tmp) == 1)
deftaps = tmp;
}
}
}
_do:
skb = create_link_skb(PH_CONTROL | REQUEST, HW_ECHOCAN_ON, sizeof(deftaps), &deftaps, 0);
if (!skb) {
printk(KERN_ERR "%s: failed to enable hwec: out of memory\n", __FUNCTION__);
return;
}
printk(KERN_DEBUG "%s: enabling hwec with deftaps=%d\n", __FUNCTION__, deftaps);
if (mISDN_queue_down(&dsp->inst, 0, skb))
dev_kfree_skb(skb);
}
void dsp_hwec_disable (dsp_t *dsp)
{
struct sk_buff *skb;
if (!dsp) {
printk(KERN_ERR "%s: failed to disable hwec: dsp is NULL\n", __FUNCTION__);
return;
}
skb = create_link_skb(PH_CONTROL | REQUEST, HW_ECHOCAN_OFF, 0, 0, 0);
if (!skb) {
printk(KERN_ERR "%s: failed to disable hwec: out of memory\n", __FUNCTION__);
return;
}
printk(KERN_DEBUG "%s: disabling hwec\n", __FUNCTION__);
if (mISDN_queue_down(&dsp->inst, 0, skb))
dev_kfree_skb(skb);
}
int dsp_hwec_init (void)
{
mISDN_dsp_element_register(dsp_hwec);
return 0;
}
void dsp_hwec_exit (void)
{
mISDN_dsp_element_unregister(dsp_hwec);
}

View File

@ -0,0 +1,120 @@
/*
* dsp_kb1ec.c: mISDN dsp pipeline element for the kb1ec echo canceller
*
* Copyright (C) 2007, Nadi Sarrar
*
* Nadi Sarrar <nadi@beronet.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mISDNdsp.h>
#include "dsp_kb1ec.h"
#include "dsp_cancel.h"
static void* new (const char *arg)
{
int deftaps = 128,
training = 0,
len;
if (!arg)
goto _out;
len = strlen(arg);
if (!len)
goto _out;
{
char _dup[len + 1];
char *dup, *tok, *name, *val;
int tmp;
strcpy(_dup, arg);
dup = _dup;
while ((tok = strsep(&dup, ","))) {
if (!strlen(tok))
continue;
name = strsep(&tok, "=");
val = tok;
if (!val)
continue;
if (!strcmp(name, "deftaps")) {
if (sscanf(val, "%d", &tmp) == 1)
deftaps = tmp;
} else if (!strcmp(name, "training")) {
if (sscanf(val, "%d", &tmp) == 1)
training = tmp;
}
}
}
_out:
printk(KERN_DEBUG "%s: creating %s with deftaps=%d and training=%d\n", __FUNCTION__, EC_TYPE, deftaps, training);
return dsp_cancel_new(deftaps, training);
}
static void free (void *p)
{
dsp_cancel_free(p);
}
static void process_tx (void *p, u8 *data, int len)
{
dsp_cancel_tx(p, data, len);
}
static void process_rx (void *p, u8 *data, int len)
{
dsp_cancel_rx(p, data, len);
}
static mISDN_dsp_element_t dsp_kb1ec = {
.new = new,
.free = free,
.process_tx = process_tx,
.process_rx = process_rx,
.name = "kb1ec",
};
#ifdef MODULE
static int __init dsp_kb1ec_init (void)
{
mISDN_dsp_element_register(&dsp_kb1ec);
return 0;
}
static void __exit dsp_kb1ec_exit (void)
{
mISDN_dsp_element_unregister(&dsp_kb1ec);
}
module_init(dsp_kb1ec_init);
module_exit(dsp_kb1ec_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Nadi Sarrar <nadi@beronet.com>");
#endif

View File

@ -0,0 +1,121 @@
/*
* dsp_mec2.c: mISDN dsp pipeline element for the mec2 echo canceller
*
* Copyright (C) 2007, Nadi Sarrar
*
* Nadi Sarrar <nadi@beronet.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/mISDNdsp.h>
#include "dsp_mec2.h"
#include "dsp_cancel.h"
static void* new (const char *arg)
{
int deftaps = 128,
training = 0,
len;
if (!arg)
goto _out;
len = strlen(arg);
if (!len)
goto _out;
{
char _dup[len + 1];
char *dup, *tok, *name, *val;
int tmp;
strcpy(_dup, arg);
dup = _dup;
while ((tok = strsep(&dup, ","))) {
if (!strlen(tok))
continue;
name = strsep(&tok, "=");
val = tok;
if (!val)
continue;
if (!strcmp(name, "deftaps")) {
if (sscanf(val, "%d", &tmp) == 1)
deftaps = tmp;
} else if (!strcmp(name, "training")) {
if (sscanf(val, "%d", &tmp) == 1)
training = tmp;
}
}
}
_out:
printk(KERN_DEBUG "%s: creating %s with deftaps=%d and training=%d\n", __FUNCTION__, EC_TYPE, deftaps, training);
return dsp_cancel_new(deftaps, training);
}
static void free (void *p)
{
dsp_cancel_free(p);
}
static void process_tx (void *p, u8 *data, int len)
{
dsp_cancel_tx(p, data, len);
}
static void process_rx (void *p, u8 *data, int len)
{
dsp_cancel_rx(p, data, len);
}
static mISDN_dsp_element_t dsp_mec2 = {
.new = new,
.free = free,
.process_tx = process_tx,
.process_rx = process_rx,
.name = "mec2",
};
#ifdef MODULE
static int __init dsp_mec2_init (void)
{
mISDN_dsp_element_register(&dsp_mec2);
return 0;
}
static void __exit dsp_mec2_exit (void)
{
mISDN_dsp_element_unregister(&dsp_mec2);
}
module_init(dsp_mec2_init);
module_exit(dsp_mec2_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Nadi Sarrar <nadi@beronet.com>");
#endif

View File

@ -0,0 +1,120 @@
/*
* dsp_mg2ec.c: mISDN dsp pipeline element for the mg2ec echo canceller
*
* Copyright (C) 2007, Nadi Sarrar
*
* Nadi Sarrar <nadi@beronet.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mISDNdsp.h>
#include "dsp_mg2ec.h"
#include "dsp_cancel.h"
static void* new (const char *arg)
{
int deftaps = 128,
training = 0,
len;
if (!arg)
goto _out;
len = strlen(arg);
if (!len)
goto _out;
{
char _dup[len + 1];
char *dup, *tok, *name, *val;
int tmp;
strcpy(_dup, arg);
dup = _dup;
while ((tok = strsep(&dup, ","))) {
if (!strlen(tok))
continue;
name = strsep(&tok, "=");
val = tok;
if (!val)
continue;
if (!strcmp(name, "deftaps")) {
if (sscanf(val, "%d", &tmp) == 1)
deftaps = tmp;
} else if (!strcmp(name, "training")) {
if (sscanf(val, "%d", &tmp) == 1)
training = tmp;
}
}
}
_out:
printk(KERN_DEBUG "%s: creating %s with deftaps=%d and training=%d\n", __FUNCTION__, EC_TYPE, deftaps, training);
return dsp_cancel_new(deftaps, training);
}
static void free (void *p)
{
dsp_cancel_free(p);
}
static void process_tx (void *p, u8 *data, int len)
{
dsp_cancel_tx(p, data, len);
}
static void process_rx (void *p, u8 *data, int len)
{
dsp_cancel_rx(p, data, len);
}
static mISDN_dsp_element_t dsp_mg2ec = {
.new = new,
.free = free,
.process_tx = process_tx,
.process_rx = process_rx,
.name = "mg2ec",
};
#ifdef MODULE
static int __init dsp_mg2ec_init (void)
{
mISDN_dsp_element_register(&dsp_mg2ec);
return 0;
}
static void __exit dsp_mg2ec_exit (void)
{
mISDN_dsp_element_unregister(&dsp_mg2ec);
}
module_init(dsp_mg2ec_init);
module_exit(dsp_mg2ec_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Nadi Sarrar <nadi@beronet.com>");
#endif

View File

@ -0,0 +1,121 @@
/*
* dsp_octwareec.c: mISDN dsp pipeline element for the octware echo canceller
*
* Copyright (C) 2007, Nadi Sarrar
*
* Nadi Sarrar <nadi@beronet.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/mISDNdsp.h>
#include "dsp_octwareec.h"
#include "dsp_cancel.h"
static void* new (const char *arg)
{
int deftaps = 128,
training = 0,
len;
if (!arg)
goto _out;
len = strlen(arg);
if (!len)
goto _out;
{
char _dup[len + 1];
char *dup, *tok, *name, *val;
int tmp;
strcpy(_dup, arg);
dup = _dup;
while ((tok = strsep(&dup, ","))) {
if (!strlen(tok))
continue;
name = strsep(&tok, "=");
val = tok;
if (!val)
continue;
if (!strcmp(name, "deftaps")) {
if (sscanf(val, "%d", &tmp) == 1)
deftaps = tmp;
} else if (!strcmp(name, "training")) {
if (sscanf(val, "%d", &tmp) == 1)
training = tmp;
}
}
}
_out:
printk(KERN_DEBUG "%s: creating %s with deftaps=%d and training=%d\n", __FUNCTION__, EC_TYPE, deftaps, training);
return dsp_cancel_new(deftaps, training);
}
static void free (void *p)
{
dsp_cancel_free(p);
}
static void process_tx (void *p, u8 *data, int len)
{
dsp_cancel_tx(p, data, len);
}
static void process_rx (void *p, u8 *data, int len)
{
dsp_cancel_rx(p, data, len);
}
static mISDN_dsp_element_t dsp_octwareec = {
.new = new,
.free = free,
.process_tx = process_tx,
.process_rx = process_rx,
.name = "octwareec",
};
#ifdef MODULE
static int __init dsp_octwareec_init (void)
{
mISDN_dsp_element_register(&dsp_octwareec);
return 0;
}
static void __exit dsp_octwareec_exit (void)
{
mISDN_dsp_element_unregister(&dsp_octwareec);
}
module_init(dsp_octwareec_init);
module_exit(dsp_octwareec_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Nadi Sarrar <nadi@beronet.com>");
#endif

View File

@ -0,0 +1,82 @@
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
File: octasicec14.h
Copyright (c) 2007 Octasic Inc. All rights reserved.
Description:
This file contains the functions used as the entry point to Octasic's
echo cancellation software.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#ifndef __OCTWARE_EC_H__
#define __OCTWARE_EC_H__
#include <linux/kernel.h>
#include "octvqe/octvqe_linux.h"
#define EC_TYPE "OCTWARE"
#if 0
static void echo_can_init(void)
{
printk( "Zaptel Echo Canceller: OCTVQE\n" );
}
static void echo_can_shutdown(void)
{
}
#endif
struct echo_can_state
{
void * pvOctvqeEchoCanceller;
};
static inline struct echo_can_state *echo_can_create(int len, int adaption_mode)
{
struct echo_can_state *pEchoCanceller = NULL;
/* Allocate echo canceller state structure. */
pEchoCanceller = (struct echo_can_state *) kmalloc(sizeof(struct echo_can_state), GFP_KERNEL);
if (pEchoCanceller != NULL)
{
pEchoCanceller->pvOctvqeEchoCanceller = ZapOctVqeApiEcChannelInitialize(len, adaption_mode);
if (pEchoCanceller->pvOctvqeEchoCanceller == NULL)
{
printk( KERN_ERR "ZapOctVqeApiEcChannelInitialize failure!\n" );
/* Cleanup. */
kfree(pEchoCanceller);
pEchoCanceller = NULL;
}
}
else
{
printk( KERN_ERR "echo_can_create error: kmalloc failed (requested %u bytes)\n",
sizeof(struct echo_can_state) );
}
return pEchoCanceller;
}
static inline short echo_can_update(struct echo_can_state *ec, short iref, short isig)
{
return ZapOctVqeApiEcChannelProcess(ec->pvOctvqeEchoCanceller, iref, isig);
}
static inline void echo_can_free(struct echo_can_state *ec)
{
/* Tell OCTVQE module that this channel is not used anymore. */
ZapOctVqeApiEcChannelFree(ec->pvOctvqeEchoCanceller);
kfree(ec);
}
static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val)
{
return ZapOctVqeApiEcChannelTrainTap(ec->pvOctvqeEchoCanceller, pos, val);
}
#endif /* __OCTWARE_EC_H__ */

View File

@ -0,0 +1,295 @@
/*
* dsp_pipeline.c: pipelined audio processing
*
* Copyright (C) 2007, Nadi Sarrar
*
* Nadi Sarrar <nadi@beronet.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
*/
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/string.h>
#include <linux/mISDNif.h>
#include <linux/mISDNdsp.h>
#include "layer1.h"
#include "dsp.h"
extern mISDN_dsp_element_t *dsp_hwec;
extern void dsp_hwec_enable (dsp_t *dsp, const char *arg);
extern void dsp_hwec_disable (dsp_t *dsp);
extern int dsp_hwec_init (void);
extern void dsp_hwec_exit (void);
typedef struct _dsp_pipeline_entry {
mISDN_dsp_element_t *elem;
void *p;
struct list_head list;
} dsp_pipeline_entry_t;
typedef struct _dsp_element_entry {
mISDN_dsp_element_t *elem;
struct list_head list;
} dsp_element_entry_t;
static rwlock_t dsp_elements_lock;
static LIST_HEAD(dsp_elements);
int mISDN_dsp_element_register (mISDN_dsp_element_t *elem)
{
dsp_element_entry_t *entry;
u_long flags;
if (!elem)
return -EINVAL;
entry = kmalloc(sizeof(dsp_element_entry_t), GFP_KERNEL);
if (!entry)
return -ENOMEM;
entry->elem = elem;
write_lock_irqsave(&dsp_elements_lock, flags);
list_add_tail(&entry->list, &dsp_elements);
write_unlock_irqrestore(&dsp_elements_lock, flags);
printk(KERN_DEBUG "%s: %s registered\n", __FUNCTION__, elem->name);
return 0;
}
void mISDN_dsp_element_unregister (mISDN_dsp_element_t *elem)
{
dsp_element_entry_t *entry, *n;
u_long flags;
if (!elem)
return;
write_lock_irqsave(&dsp_elements_lock, flags);
list_for_each_entry_safe(entry, n, &dsp_elements, list)
if (entry->elem == elem) {
list_del(&entry->list);
write_unlock_irqrestore(&dsp_elements_lock, flags);
kfree(entry);
printk(KERN_DEBUG "%s: %s unregistered\n", __FUNCTION__, elem->name);
return;
}
write_unlock_irqrestore(&dsp_elements_lock, flags);
}
int dsp_pipeline_module_init (void)
{
rwlock_init(&dsp_elements_lock);
printk(KERN_DEBUG "%s: dsp pipeline module initialized\n", __FUNCTION__);
dsp_hwec_init();
return 0;
}
void dsp_pipeline_module_exit (void)
{
dsp_element_entry_t *entry, *n;
u_long flags;
dsp_hwec_exit();
write_lock_irqsave(&dsp_elements_lock, flags);
list_for_each_entry_safe(entry, n, &dsp_elements, list) {
list_del(&entry->list);
printk(KERN_DEBUG "%s: element was still registered: %s\n", __FUNCTION__, entry->elem->name);
kfree(entry);
}
write_unlock_irqrestore(&dsp_elements_lock, flags);
printk(KERN_DEBUG "%s: dsp pipeline module exited\n", __FUNCTION__);
}
int dsp_pipeline_init (dsp_pipeline_t *pipeline)
{
if (!pipeline)
return -EINVAL;
INIT_LIST_HEAD(&pipeline->list);
rwlock_init(&pipeline->lock);
printk(KERN_DEBUG "%s: dsp pipeline ready\n", __FUNCTION__);
return 0;
}
static inline void _dsp_pipeline_destroy (dsp_pipeline_t *pipeline)
{
dsp_pipeline_entry_t *entry, *n;
list_for_each_entry_safe(entry, n, &pipeline->list, list) {
list_del(&entry->list);
if (entry->elem == dsp_hwec)
dsp_hwec_disable(container_of(pipeline, dsp_t, pipeline));
else
entry->elem->free(entry->p);
kfree(entry);
}
}
void dsp_pipeline_destroy (dsp_pipeline_t *pipeline)
{
u_long flags;
if (!pipeline)
return;
write_lock_irqsave(&pipeline->lock, flags);
_dsp_pipeline_destroy(pipeline);
write_unlock_irqrestore(&pipeline->lock, flags);
printk(KERN_DEBUG "%s: dsp pipeline destroyed\n", __FUNCTION__);
}
int dsp_pipeline_build (dsp_pipeline_t *pipeline, const char *cfg)
{
int len, incomplete = 0, found = 0;
char *dup, *tok, *name, *args;
dsp_element_entry_t *entry, *n;
dsp_pipeline_entry_t *pipeline_entry;
mISDN_dsp_element_t *elem;
u_long elements_flags, pipeline_flags;
if (!pipeline)
return -EINVAL;
write_lock_irqsave(&pipeline->lock, pipeline_flags);
if (!list_empty(&pipeline->list))
_dsp_pipeline_destroy(pipeline);
if (!cfg) {
write_unlock_irqrestore(&pipeline->lock, pipeline_flags);
return 0;
}
len = strlen(cfg);
if (!len) {
write_unlock_irqrestore(&pipeline->lock, pipeline_flags);
return 0;
}
char _dup[len + 1];
strcpy(_dup, cfg);
dup = _dup;
while ((tok = strsep(&dup, "|"))) {
if (!strlen(tok))
continue;
name = strsep(&tok, "(");
args = strsep(&tok, ")");
if (args && !*args)
args = 0;
read_lock_irqsave(&dsp_elements_lock, elements_flags);
list_for_each_entry_safe(entry, n, &dsp_elements, list)
if (!strcmp(entry->elem->name, name)) {
elem = entry->elem;
read_unlock_irqrestore(&dsp_elements_lock, elements_flags);
pipeline_entry = kmalloc(sizeof(dsp_pipeline_entry_t), GFP_KERNEL);
if (!pipeline_entry) {
printk(KERN_DEBUG "%s: failed to add entry to pipeline: %s (out of memory)\n", __FUNCTION__, elem->name);
incomplete = 1;
goto _out;
}
pipeline_entry->elem = elem;
if (elem == dsp_hwec) {
/* This is a hack to make the hwec available as a pipeline module */
dsp_hwec_enable(container_of(pipeline, dsp_t, pipeline), args);
list_add_tail(&pipeline_entry->list, &pipeline->list);
} else {
pipeline_entry->p = elem->new(args);
if (pipeline_entry->p) {
list_add_tail(&pipeline_entry->list, &pipeline->list);
printk(KERN_DEBUG "%s: created instance of %s%s%s\n", __FUNCTION__, name, args ? " with args " : "", args ? args : "");
} else {
printk(KERN_DEBUG "%s: failed to add entry to pipeline: %s (new() returned NULL)\n", __FUNCTION__, elem->name);
kfree(pipeline_entry);
incomplete = 1;
}
}
found = 1;
break;
}
if (found)
found = 0;
else {
read_unlock_irqrestore(&dsp_elements_lock, elements_flags);
printk(KERN_DEBUG "%s: element not found, skipping: %s\n", __FUNCTION__, name);
incomplete = 1;
}
}
_out:
write_unlock_irqrestore(&pipeline->lock, pipeline_flags);
printk(KERN_DEBUG "%s: dsp pipeline built%s: %s\n", __FUNCTION__, incomplete ? " incomplete" : "", cfg);
return 0;
}
void dsp_pipeline_process_tx (dsp_pipeline_t *pipeline, u8 *data, int len)
{
dsp_pipeline_entry_t *entry;
if (!pipeline)
return;
if (!read_trylock(&pipeline->lock)) {
printk(KERN_DEBUG "%s: bypassing pipeline because it is locked (TX)\n", __FUNCTION__);
return;
}
list_for_each_entry(entry, &pipeline->list, list)
if (entry->elem->process_tx)
entry->elem->process_tx(entry->p, data, len);
read_unlock(&pipeline->lock);
}
void dsp_pipeline_process_rx (dsp_pipeline_t *pipeline, u8 *data, int len)
{
dsp_pipeline_entry_t *entry;
if (!pipeline)
return;
if (!read_trylock(&pipeline->lock)) {
printk(KERN_DEBUG "%s: bypassing pipeline because it is locked (RX)\n", __FUNCTION__);
return;
}
list_for_each_entry_reverse(entry, &pipeline->list, list)
if (entry->elem->process_rx)
entry->elem->process_rx(entry->p, data, len);
read_unlock(&pipeline->lock);
}
EXPORT_SYMBOL(mISDN_dsp_element_register);
EXPORT_SYMBOL(mISDN_dsp_element_unregister);

View File

@ -22,6 +22,7 @@ mISDN_set_dchannel_pid(mISDN_pid_t *pid, int protocol, int layermask)
memset(pid, 0, sizeof(mISDN_pid_t));
pid->layermask = layermask;
pid->modparm_protocol = protocol;
if (layermask & ISDN_LAYER(0))
pid->protocol[0] = ISDN_PID_L0_TE_S0;
if (layermask & ISDN_LAYER(1))

View File

@ -140,6 +140,9 @@ extern void ztdummy_extern_interrupt(void);
static void (* hfc_interrupt)(void);
extern void ztdummy_register_interrupt(void);
static void (* register_interrupt)(void);
extern int ztdummy_unregister_interrupt(void);
static int (* unregister_interrupt)(void);
static int interrupt_registered = 0;
/* table entry in the PCI devices list */
typedef struct {
@ -154,15 +157,20 @@ typedef struct {
int clock2;
int leds;
int opticalsupport;
int dip_type;
} PCI_ENTRY;
static int poll_timer = 6; /* default = 128 samples = 16ms */
/* number of POLL_TIMER interrupts for G2 timeout (min 120ms) */
static int nt_t1_count[] = { 480, 240, 120, 60, 30, 15, 8, 4 };
/* number of POLL_TIMER interrupts for G2 timeout (ca 1s) */
static int nt_t1_count[] = { 3840, 1920, 960, 480, 240, 120, 64, 32 };
//static int nt_t1_count[] = { 480, 240, 120, 60, 30, 15, 8, 4 };
#define CLKDEL_TE 0x0f /* CLKDEL in TE mode */
#define CLKDEL_NT 0x0c /* CLKDEL in NT mode (0x60 MUST not be included!) */
static u_char silence = 0xff; /* silence by LAW */
#define DIP_4S 0x1 /* DIP Switches for Beronet 1S/2S/4S cards */
#define DIP_8S 0x2 /* DIP Switches for Beronet 8S+ cards */
#define DIP_E1 0x3 /* DIP Switches for Beronet E1 cards */
/* enable 32 bit fifo access (PC usage) */
#define FIFO_32BIT_ACCESS
@ -183,58 +191,58 @@ static const PCI_ENTRY id_list[] =
"HFC-E1 CCAG Eval", 1, 0, 1}, /* E1 only supports single clock */
#endif
{CCAG_VID, CCAG_VID, HFC4S_ID, 0x08B4, VENDOR_CCD,
"HFC-4S CCAG Eval (old)", 0, 4, 0, 0, 0},
"HFC-4S CCAG Eval (old)", 0, 4, 0, 0, 0, 0},
{CCAG_VID, CCAG_VID, HFC8S_ID, 0x16B8, VENDOR_CCD,
"HFC-8S CCAG Eval (old)", 0, 8, 0, 0, 0},
"HFC-8S CCAG Eval (old)", 0, 8, 0, 0, 0, 0},
{CCAG_VID, CCAG_VID, HFCE1_ID, 0x30B1, VENDOR_CCD,
"HFC-E1 CCAG Eval (old)", 1, 1, 0, 0, 0},
"HFC-E1 CCAG Eval (old)", 1, 1, 0, 0, 0, 0},
{CCAG_VID, CCAG_VID, HFC4S_ID, 0xB520, VENDOR_CCD,
"HFC-4S IOB4ST", 0, 4, 1, 2, 0},
"HFC-4S IOB4ST", 0, 4, 1, 2, 0, 0},
{CCAG_VID, CCAG_VID, HFC4S_ID, 0xB620, VENDOR_CCD,
"HFC-4S", 0, 4, 1, 2, 0},
"HFC-4S", 0, 4, 1, 2, 0, 0},
{CCAG_VID, CCAG_VID, HFC4S_ID, 0xB550, VENDOR_CCD,
"HFC-4S (junghanns 2.0)", 0, 4, 1, 2, 0},
"HFC-4S (junghanns 2.0)", 0, 4, 1, 2, 0, 0},
{CCAG_VID, CCAG_VID, HFC4S_ID, 0xB560, VENDOR_CCD,
"HFC-4S Beronet Card", 0, 4, 1, 2, 0},
"HFC-4S Beronet Card", 0, 4, 1, 2, 0, DIP_4S},
{CCAG_VID, CCAG_VID, HFC4S_ID, 0xB568, VENDOR_CCD,
"HFC-4S Beronet Card (mini PCI)", 0, 4, 1, 2, 0},
"HFC-4S Beronet Card (mini PCI)", 0, 4, 1, 2, 0, 0},
{0xD161, 0xD161, 0xB410, 0xB410, VENDOR_CCD,
"HFC-4S Digium Card", 0, 4, 0, 2, 0},
"HFC-4S Digium Card", 0, 4, 0, 2, 0, 0},
{CCAG_VID, CCAG_VID, HFC4S_ID, 0xB540, VENDOR_CCD,
"HFC-4S Swyx 4xS0 SX2 QuadBri", 0, 4, 1, 2, 0},
"HFC-4S Swyx 4xS0 SX2 QuadBri", 0, 4, 1, 2, 0, 0},
{CCAG_VID, CCAG_VID, HFC8S_ID, 0xB521, VENDOR_CCD,
"HFC-8S IOB4ST Recording", 0, 8, 1, 0, 0},
"HFC-8S IOB4ST Recording", 0, 8, 1, 0, 0, 0},
{CCAG_VID, CCAG_VID, HFC8S_ID, 0xB522, VENDOR_CCD,
"HFC-8S IOB8ST", 0, 8, 1, 0, 0},
"HFC-8S IOB8ST", 0, 8, 1, 0, 0, 0},
{CCAG_VID, CCAG_VID, HFC8S_ID, 0xB552, VENDOR_CCD,
"HFC-8S", 0, 8, 1, 0, 0},
"HFC-8S", 0, 8, 1, 0, 0, 0},
{CCAG_VID, CCAG_VID, HFC8S_ID, 0xB622, VENDOR_CCD,
"HFC-8S", 0, 8, 1, 0, 0},
"HFC-8S", 0, 8, 1, 0, 0, 0},
{CCAG_VID, CCAG_VID, HFC8S_ID, 0xB562, VENDOR_CCD,
"HFC-8S Beronet Card", 0, 8, 1, 0, 0},
"HFC-8S Beronet Card", 0, 8, 1, 0, 0, 0},
{CCAG_VID, CCAG_VID, HFC8S_ID, 0xB56B, VENDOR_CCD,
"HFC-8S Beronet Card (+)", 0, 8, 1, 8, 0},
"HFC-8S Beronet Card (+)", 0, 8, 1, 8, 0, DIP_8S},
{CCAG_VID, CCAG_VID, HFCE1_ID, 0xB523, VENDOR_CCD,
"HFC-E1 IOB1E1", 1, 1, 0, 1, 0}, /* E1 only supports single clock */
"HFC-E1 IOB1E1", 1, 1, 0, 1, 0, 0}, /* E1 only supports single clock */
{CCAG_VID, CCAG_VID, HFCE1_ID, 0xC523, VENDOR_CCD,
"HFC-E1", 1, 1, 0, 1, 0}, /* E1 only supports single clock */
"HFC-E1", 1, 1, 0, 1, 0, 0}, /* E1 only supports single clock */
{CCAG_VID, CCAG_VID, HFCE1_ID, 0xB56A, VENDOR_CCD,
"HFC-E1 Beronet Card (mini PCI)", 1, 1, 0, 1, 0}, /* E1 only supports single clock */
"HFC-E1 Beronet Card (mini PCI)", 1, 1, 0, 1, 0, 0}, /* E1 only supports single clock */
{CCAG_VID, CCAG_VID, HFCE1_ID, 0xB563, VENDOR_CCD,
"HFC-E1 Beronet Card", 1, 1, 0, 1, 0}, /* E1 only supports single clock */
"HFC-E1 Beronet Card", 1, 1, 0, 1, 0, DIP_E1}, /* E1 only supports single clock */
{CCAG_VID, CCAG_VID, HFCE1_ID, 0xB565, VENDOR_CCD,
"HFC-E1+ Beronet Card (Dual)", 1, 1, 0, 1, 0}, /* E1 only supports single clock */
"HFC-E1+ Beronet Card (Dual)", 1, 1, 0, 1, 0, DIP_E1}, /* E1 only supports single clock */
{CCAG_VID, CCAG_VID, HFCE1_ID, 0xB564, VENDOR_CCD,
"HFC-E1 Beronet Card (Dual)", 1, 1, 0, 1, 0}, /* E1 only supports single clock */
"HFC-E1 Beronet Card (Dual)", 1, 1, 0, 1, 0, DIP_E1}, /* E1 only supports single clock */
{0x10B5, CCAG_VID, 0x9030, 0x3136, VENDOR_CCD,
"HFC-4S PCIBridgeEval", 0, 4, 0, 0, 0}, // PLX PCI-Bridge
"HFC-4S PCIBridgeEval", 0, 4, 0, 0, 0, 0}, // PLX PCI-Bridge
{CCAG_VID, CCAG_VID, HFC4S_ID, 0xB566, VENDOR_CCD,
"HFC-2S Beronet Card", 0, 2, 1, 3, 0},
"HFC-2S Beronet Card", 0, 2, 1, 3, 0, DIP_4S},
{CCAG_VID, CCAG_VID, HFC4S_ID, 0xB569, VENDOR_CCD,
"HFC-2S Beronet Card (mini PCI)", 0, 2, 1, 3, 0},
"HFC-2S Beronet Card (mini PCI)", 0, 2, 1, 3, 0, DIP_4S},
{CCAG_VID, CCAG_VID, HFC4S_ID, 0xB567, VENDOR_CCD,
"HFC-1S Beronet Card (mini PCI)", 0, 1, 1, 3, 0},
{0, 0, 0, 0, NULL, NULL, 0, 0, 0, 0},
"HFC-1S Beronet Card (mini PCI)", 0, 1, 1, 3, 0, DIP_4S},
{0, 0, 0, 0, NULL, NULL, 0, 0, 0, 0, 0},
};
@ -758,14 +766,14 @@ init_chip(hfc_multi_t *hc)
HFC_outb(hc, R_RAM_ADDR1, 0);
HFC_outb(hc, R_RAM_ADDR2, 0);
for(i=0;i<256;i++) {
for (i = 0; i < 256; i++) {
HFC_outb(hc, R_RAM_ADDR0,i);
HFC_outb(hc, R_RAM_DATA,((i*3)&0xff));
//udelay(5);
//HFC_outb(hc, R_RAM_DATA,((i*3)&0xff));
}
for(i=0;i<256;i++) {
for (i = 0; i < 256; i++) {
HFC_outb(hc, R_RAM_ADDR0,i);
HFC_inb(hc, R_RAM_DATA);
rval=HFC_inb(hc, R_INT_DATA);
@ -811,13 +819,11 @@ init_chip(hfc_multi_t *hc)
}
i = 0;
while (i < 256) {
for (i = 0; i < 256; i++) {
HFC_outb_(hc, R_SLOT, i);
HFC_outb_(hc, A_SL_CFG, 0);
HFC_outb_(hc, A_CONF, 0);
hc->slot_owner[i] = -1;
i++;
}
/* set clock speed */
@ -871,6 +877,7 @@ init_chip(hfc_multi_t *hc)
if (timer!=0 && hfc_interrupt && register_interrupt) {
/* only one chip should use this interrupt */
timer = 0;
interrupt_registered = 1;
hc->hw.r_irqmsk_misc |= V_PROC_IRQMSK;
/* deactivate other interrupts in ztdummy */
register_interrupt();
@ -967,7 +974,8 @@ hfcmulti_watchdog(hfc_multi_t *hc)
static void
hfcmulti_leds(hfc_multi_t *hc)
{
int i, state, active;
unsigned long lled, leddw;
int i, state, active, leds;
channel_t *dch;
int led[4];
@ -977,176 +985,87 @@ hfcmulti_leds(hfc_multi_t *hc)
switch(hc->leds) {
case 1: /* HFC-E1 OEM */
/* 2 red blinking: LOS
1 red: AIS
left green: PH_ACTIVATE
right green flashing: FIFO activity
*/
i = HFC_inb(hc, R_GPI_IN0) & 0xf0;
if (!(i & 0x40)) { /* LOS */
if (hc->e1_switch != i) {
hc->e1_switch = i;
hc->hw.r_tx0 &= ~V_OUT_EN;
HFC_outb(hc, R_TX0, hc->hw.r_tx0);
}
if (hc->ledcount & 512)
led[0] = led[1] = 1;
else
led[0] = led[1] = 0;
led[2] = led[3] = 0;
} else
if (!(i & 0x80)) { /* AIS */
if (hc->e1_switch != i) {
hc->e1_switch = i;
hc->hw.r_tx0 |= V_OUT_EN;
hc->hw.r_tx1 |= V_AIS_OUT;
HFC_outb(hc, R_TX0, hc->hw.r_tx0);
HFC_outb(hc, R_TX1, hc->hw.r_tx1);
}
if (hc->ledcount & 512)
led[2] = led[3] = 1;
else
led[2] = led[3] = 0;
led[0] = led[1] = 0;
} else {
if (hc->e1_switch != i) {
/* reset LOS/AIS */
hc->e1_switch = i;
hc->hw.r_tx0 |= V_OUT_EN;
hc->hw.r_tx1 &= ~V_AIS_OUT;
HFC_outb(hc, R_TX0, hc->hw.r_tx0);
HFC_outb(hc, R_TX1, hc->hw.r_tx1);
}
if (HFC_inb_(hc, R_RX_STA0) & V_SIG_LOS) {
if (hc->ledcount>>11)
led[0] = led[1] = 1; /* both red blinking */
/* 2 red blinking: LOS
1 red: AIS
left green: PH_ACTIVATE
right green flashing: FIFO activity
*/
i = HFC_inb(hc, R_GPI_IN0) & 0xf0;
if (!(i & 0x40)) { /* LOS */
if (hc->e1_switch != i) {
hc->e1_switch = i;
hc->hw.r_tx0 &= ~V_OUT_EN;
HFC_outb(hc, R_TX0, hc->hw.r_tx0);
}
if (hc->ledcount & 512)
led[0] = led[1] = 1;
else
led[0] = led[1] = 0;
} else
if (HFC_inb_(hc, R_RX_STA0) & V_AIS) {
led[0] = led[1] = 1; /* both red */
led[2] = led[3] = 0;
} else {
led[0] = led[1] = 0; /* no red */
}
state = 0;
active = 1;
dch = hc->chan[16].ch;
if (dch && test_bit(FLG_DCHANNEL, &dch->Flags))
state = dch->state;
if (state == active) {
led[2] = 1; /* left green */
if (hc->activity[0]) {
led[3] = 1; /* right green */
hc->activity[0] = 0;
} else
led[3] = 0; /* no right green */
} else
led[2] = led[3] = 0; /* no green */
}
HFC_outb(hc, R_GPIO_OUT1,
(led[0] | (led[1]<<2) | (led[2]<<1) | (led[3]<<3))^0xf); /* leds are inverted */
break;
case 2: /* HFC-4S OEM */
/* red blinking = PH_DEACTIVATE
red steady = PH_ACTIVATE
green flashing = fifo activity
*/
i = 0;
while(i < 4) {
state = 0;
active = -1;
dch = hc->chan[(i<<2)|2].ch;
if (dch && test_bit(FLG_DCHANNEL, &dch->Flags)) {
state = dch->state;
active = test_bit(HFC_CFG_NTMODE, &hc->chan[dch->channel].cfg)?3:7;
}
if (state) {
if (state==active) {
if (hc->activity[i]) {
led[i] = 1; /* led green */
hc->activity[i] = 0;
if (!(i & 0x80)) { /* AIS */
if (hc->e1_switch != i) {
hc->e1_switch = i;
hc->hw.r_tx0 |= V_OUT_EN;
hc->hw.r_tx1 |= V_AIS_OUT;
HFC_outb(hc, R_TX0, hc->hw.r_tx0);
HFC_outb(hc, R_TX1, hc->hw.r_tx1);
}
if (hc->ledcount & 512)
led[2] = led[3] = 1;
else
led[2] = led[3] = 0;
led[0] = led[1] = 0;
} else {
if (hc->e1_switch != i) {
/* reset LOS/AIS */
hc->e1_switch = i;
hc->hw.r_tx0 |= V_OUT_EN;
hc->hw.r_tx1 &= ~V_AIS_OUT;
HFC_outb(hc, R_TX0, hc->hw.r_tx0);
HFC_outb(hc, R_TX1, hc->hw.r_tx1);
}
if (HFC_inb_(hc, R_RX_STA0) & V_SIG_LOS) {
if (hc->ledcount>>11)
led[0] = led[1] = 1; /* both red blinking */
else
led[0] = led[1] = 0;
} else
led[i] = 2; /* led red */
} else if (hc->ledcount>>11)
led[i] = 2; /* led red */
else
led[i] = 0; /* led off */
} else
led[i] = 0; /* led off */
i++;
}
if (HFC_inb_(hc, R_RX_STA0) & V_AIS) {
led[0] = led[1] = 1; /* both red */
} else {
led[0] = led[1] = 0; /* no red */
}
state = 0;
active = 1;
dch = hc->chan[16].ch;
if (dch && test_bit(FLG_DCHANNEL, &dch->Flags))
state = dch->state;
if (state == active) {
led[2] = 1; /* left green */
if (hc->activity[0]) {
led[3] = 1; /* right green */
hc->activity[0] = 0;
} else
led[3] = 0; /* no right green */
if (test_bit(HFC_CHIP_DIGICARD, &hc->chip)) {
int leds=0;
for (i=0; i<4; i++) {
if (led[i]==1) {
/*green*/
leds |=( 0x2 <<(i*2));
} else if (led[i]==2) {
/*red*/
leds |=( 0x1 <<(i*2));
} else
led[2] = led[3] = 0; /* no green */
}
}
vpm_out(hc, 0, 0x1a8+3,leds);
} else {
HFC_outb(hc, R_GPIO_EN1,
((led[0]>0)<<0) | ((led[1]>0)<<1) |
((led[2]>0)<<2) | ((led[3]>0)<<3));
HFC_outb(hc, R_GPIO_OUT1,
((led[0]&1)<<0) | ((led[1]&1)<<1) |
((led[2]&1)<<2) | ((led[3]&1)<<3));
}
break;
case 3:
/* red blinking = PH_DEACTIVATE
red steady = PH_ACTIVATE
green flashing = fifo activity
*/
for(i=0;i<2;i++) {
state = 0;
active = -1;
dch = hc->chan[(i<<2)|2].ch;
if (dch && test_bit(FLG_DCHANNEL, &dch->Flags)) {
state = dch->state;
active = test_bit(HFC_CFG_NTMODE, &hc->chan[dch->channel].cfg)?3:7;
leds = (led[0] | (led[1]<<2) | (led[2]<<1) | (led[3]<<3))^0xf; /* leds are inverted */
if (leds != (int)hc->ledstate) {
HFC_outb(hc, R_GPIO_OUT1, leds);
hc->ledstate = leds;
}
if (state) {
if (state==active) {
if (hc->activity[i]) {
led[i] = 1; /* led green */
hc->activity[i] = 0;
} else
led[i] = 2; /* led red */
} else if (hc->ledcount>>11)
led[i] = 2; /* led red */
else
led[i] = 0; /* led off */
} else
led[i] = 0; /* led off */
}
break;
// printk("leds %d %d\n", led[0], led[1]);
//LEDME
HFC_outb(hc, R_GPIO_EN1,
((led[0]>0)<<2) | ((led[1]>0)<<3) );
HFC_outb(hc, R_GPIO_OUT1,
((led[0]&1)<<2) | ((led[1]&1)<<3) );
break;
case 8:
{
unsigned long led=0;
int off=0;
if (hc->ledcount>2048)
off=1;
for (i=0;i<8;i++) {
case 2: /* HFC-4S OEM */
/* red blinking = PH_DEACTIVATE NT Mode
red steady = PH_DEACTIVATE TE Mode
green steady = PH_ACTIVATE
*/
for (i=0; i < 4; i++) {
state = 0;
active = -1;
dch = hc->chan[(i<<2)|2].ch;
@ -1155,21 +1074,119 @@ hfcmulti_leds(hfc_multi_t *hc)
active = test_bit(HFC_CFG_NTMODE, &hc->chan[dch->channel].cfg)?3:7;
}
if (state) {
if (state!=active && off)
led |= 1<<i;
if (state==active) {
led[i] = 1; /* led green */
} else if (!test_bit(HFC_CFG_NTMODE, &hc->chan[dch->channel].cfg))
/* TE mode: led red */
led[i] = 2;
else if (hc->ledcount>>11)
led[i] = 2; /* led red */
else
led[i] = 0; /* led off */
} else
led |= 1<<i;
led[i] = 0; /* led off */
}
unsigned long leddw=led << 24 | led << 16 | led << 8 | led;
//HFC_outb(hc, R_BRG_PCM_CFG, 1);
//HFC_outb(c, R_BRG_PCM_CFG, (0x0 << 6) | 0x3); /*was _io before*/
HFC_outb(hc, R_BRG_PCM_CFG, 1 | V_PCM_CLK);
outw(0x4000, hc->pci_iobase + 4);
outl(leddw, hc->pci_iobase);
HFC_outb(hc, R_BRG_PCM_CFG, V_PCM_CLK);
}
break;
if (test_bit(HFC_CHIP_DIGICARD, &hc->chip)) {
leds = 0;
for (i=0; i<4; i++) {
if (led[i]==1) {
/*green*/
leds |=( 0x2 <<(i*2));
} else if (led[i]==2) {
/*red*/
leds |=( 0x1 <<(i*2));
}
}
if (leds != (int)hc->ledstate) {
vpm_out(hc, 0, 0x1a8+3, leds);
hc->ledstate = leds;
}
} else {
leds = ((led[3]>0)<<0) | ((led[1]>0)<<1) |
((led[0]>0)<<2) | ((led[2]>0)<<3) |
((led[3]&1)<<4) | ((led[1]&1)<<5) |
((led[0]&1)<<6) | ((led[2]&1)<<7);
if (leds != (int)hc->ledstate) {
HFC_outb(hc, R_GPIO_EN1, leds & 0x0F);
HFC_outb(hc, R_GPIO_OUT1, leds >> 4);
hc->ledstate = leds;
}
}
break;
case 3: /* HFC 1S/2S Beronet */
/* red blinking = PH_DEACTIVATE NT Mode
red steady = PH_DEACTIVATE TE Mode
green steady = PH_ACTIVATE
*/
for (i = 0; i < 2; i++) {
state = 0;
active = -1;
dch = hc->chan[(i<<2)|2].ch;
if (dch && test_bit(FLG_DCHANNEL, &dch->Flags)) {
state = dch->state;
active = test_bit(HFC_CFG_NTMODE, &hc->chan[dch->channel].cfg)?3:7;
}
if (state) {
if (state==active) {
led[i] = 1; /* led green */
} else if (!test_bit(HFC_CFG_NTMODE, &hc->chan[dch->channel].cfg))
/* TE mode: led red */
led[i] = 2;
else if (hc->ledcount>>11)
led[i] = 2; /* led red */
else
led[i] = 0; /* led off */
} else
led[i] = 0; /* led off */
}
// printk("leds %d %d\n", led[0], led[1]);
//LEDME
leds = (led[0]>0) | ((led[1]>0)<<1) | ((led[0]&1)<<2) | ((led[1]&1)<<3);
if (leds != (int)hc->ledstate) {
HFC_outb(hc, R_GPIO_EN1,
((led[0]>0)<<2) | ((led[1]>0)<<3) );
HFC_outb(hc, R_GPIO_OUT1,
((led[0]&1)<<2) | ((led[1]&1)<<3) );
hc->ledstate = leds;
}
break;
case 8: /* HFC 8S+ Beronet */
lled = 0;
for (i = 0; i < 8; i++) {
state = 0;
active = -1;
dch = hc->chan[(i<<2)|2].ch;
if (dch && test_bit(FLG_DCHANNEL, &dch->Flags)) {
state = dch->state;
active = test_bit(HFC_CFG_NTMODE, &hc->chan[dch->channel].cfg)?3:7;
}
if (state) {
if (state==active) {
lled |= 0<<i;
} else if (hc->ledcount>>11)
lled |= 0<<i;
else
lled |= 1<<i;
} else
lled |= 1<<i;
}
leddw = lled << 24 | lled << 16 | lled << 8 | lled;
if (leddw != hc->ledstate) {
//HFC_outb(hc, R_BRG_PCM_CFG, 1);
//HFC_outb(c, R_BRG_PCM_CFG, (0x0 << 6) | 0x3); /*was _io before*/
HFC_outb(hc, R_BRG_PCM_CFG, 1 | V_PCM_CLK);
outw(0x4000, hc->pci_iobase + 4);
outl(leddw, hc->pci_iobase);
HFC_outb(hc, R_BRG_PCM_CFG, V_PCM_CLK);
hc->ledstate = leddw;
}
break;
}
}
/**************************/
@ -1191,27 +1208,22 @@ hfcmulti_dtmf(hfc_multi_t *hc)
if (debug & DEBUG_HFCMULTI_DTMF)
printk(KERN_DEBUG "%s: dtmf detection irq\n", __FUNCTION__);
ch = 0;
while(ch < 32) {
for (ch = 0; ch < 32; ch++) {
// only process enabled B-channels
bch = hc->chan[ch].ch;
if ((!bch) || !test_bit(FLG_BCHANNEL, &bch->Flags)) {
ch++;
continue;
}
if (!hc->created[hc->chan[ch].port]) {
ch++;
continue;
}
if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) {
ch++;
continue;
}
if (debug & DEBUG_HFCMULTI_DTMF)
printk(KERN_DEBUG "%s: dtmf channel %d:", __FUNCTION__, ch);
dtmf = 1;
co = 0;
while(co < 8) {
for (co = 0; co < 8; co++) {
// read W(n-1) coefficient
addr = hc->DTMFbase + ((co<<7) | (ch<<2));
HFC_outb_(hc, R_RAM_ADDR0, addr);
@ -1261,12 +1273,10 @@ hfcmulti_dtmf(hfc_multi_t *hc)
// store coefficient
coeff[(co<<1)|1] = mantissa;
co++;
}
skb = create_link_skb(PH_CONTROL | INDICATION, HW_HFC_COEFF, sizeof(coeff), coeff, 0);
if (!skb) {
printk(KERN_WARNING "%s: No memory for skb\n", __FUNCTION__);
ch++;
continue;
}
if (debug & DEBUG_HFCMULTI_DTMF) {
@ -1284,7 +1294,6 @@ hfcmulti_dtmf(hfc_multi_t *hc)
if (mISDN_queue_up(&bch->inst, 0, skb))
dev_kfree_skb(skb);
ch++;
}
// restart DTMF processing
@ -1778,8 +1787,7 @@ handle_timer_irq(hfc_multi_t *hc)
int ch, temp;
channel_t *chan;
ch = 0;
while(ch < 32) {
for (ch = 0; ch < 32; ch++) {
chan = hc->chan[ch].ch;
if (chan && hc->created[hc->chan[ch].port]) {
hfcmulti_tx(hc, ch, chan);
@ -1795,7 +1803,6 @@ handle_timer_irq(hfc_multi_t *hc)
}
}
}
ch++;
}
if (hc->type == 1 && hc->created[0]) {
chan = hc->chan[16].ch;
@ -1913,10 +1920,8 @@ hfcmulti_interrupt(int intno, void *dev_id, struct pt_regs *regs)
#ifdef CONFIG_PLX_PCI_BRIDGE
plx_acc=(u_short*)(hc->plx_membase+0x4c);
wval=*plx_acc;
if(!(wval&0x04))
{
if(wval&0x20)
{
if(!(wval&0x04)) {
if(wval&0x20) {
//printk(KERN_WARNING "NO irq LINTI1:%x\n",wval);
printk(KERN_WARNING "got irq LINTI2\n");
}
@ -1967,8 +1972,7 @@ hfcmulti_interrupt(int intno, void *dev_id, struct pt_regs *regs)
if (r_irq_statech) {
if (hc->type != 1) {
/* state machine */
ch = 0;
while(ch < 32) {
for (ch = 0; ch < 32; ch++) {
chan = hc->chan[ch].ch;
if (chan && test_bit(FLG_DCHANNEL, &chan->Flags)) {
if (r_irq_statech & 1) {
@ -1989,7 +1993,6 @@ hfcmulti_interrupt(int intno, void *dev_id, struct pt_regs *regs)
}
r_irq_statech >>= 1;
}
ch++;
}
}
}
@ -2037,8 +2040,7 @@ hfcmulti_interrupt(int intno, void *dev_id, struct pt_regs *regs)
/* FIFO IRQ */
r_irq_oview = HFC_inb_(hc, R_IRQ_OVIEW);
//if(r_irq_oview) printk(KERN_DEBUG "OV:%x\n",r_irq_oview);
i = 0;
while(i < 8) {
for (i = 0; i < 8; i++) {
if (r_irq_oview & (1 << i)) {
r_irq_fifo_bl = HFC_inb_(hc, R_IRQ_FIFO_BL0 + i);
//r_irq_fifo_bl = HFC_inb_(hc, R_INT_DATA);
@ -2047,8 +2049,7 @@ hfcmulti_interrupt(int intno, void *dev_id, struct pt_regs *regs)
//bl2 = HFC_inb_(hc, R_IRQ_FIFO_BL0);
//printk(KERN_DEBUG "zero:%x :%x\n",bl1,bl2);
r_irq_fifo_bl = HFC_inb_(hc, R_IRQ_FIFO_BL0 + i);
j = 0;
while(j < 8) {
for (j = 0; j < 8; j++) {
ch = (i<<2) + (j>>1);
if (ch >= 16) {
if (ch == 16)
@ -2074,10 +2075,8 @@ hfcmulti_interrupt(int intno, void *dev_id, struct pt_regs *regs)
//printk(KERN_DEBUG "rxchan:%d\n",ch);
}
}
j++;
}
}
i++;
}
}
@ -3064,17 +3063,14 @@ hfcmulti_initmode(hfc_multi_t *hc)
hc->chan[16].ch->timer.data = (long) &hc->chan[16].ch;
init_timer(&hc->chan[16].ch->timer);
i = 0;
while (i < 30) {
for (i = 0; i < 30; i++) {
hc->chan[i+1+(i>=15)].slot_tx = -1;
hc->chan[i+1+(i>=15)].slot_rx = -1;
hc->chan[i+1+(i>=15)].conf = -1;
mode_hfcmulti(hc, i+1+(i>=15), ISDN_PID_NONE, -1, 0, -1, 0);
i++;
}
} else {
i = 0;
while (i < hc->ports) {
for (i = 0; i < hc->ports; i++) {
nt_mode = test_bit(HFC_CFG_NTMODE, &hc->chan[(i<<2)+2].cfg);
hc->chan[(i<<2)+2].slot_tx = -1;
hc->chan[(i<<2)+2].slot_rx = -1;
@ -3092,7 +3088,6 @@ hfcmulti_initmode(hfc_multi_t *hc)
hc->chan[(i<<2)+1].slot_rx = -1;
hc->chan[(i<<2)+1].conf = -1;
mode_hfcmulti(hc, (i<<2)+1, ISDN_PID_NONE, -1, 0, -1, 0);
i++;
}
}
@ -3100,11 +3095,9 @@ hfcmulti_initmode(hfc_multi_t *hc)
if (hc->type != 1) {
/* ST */
r_sci_msk = 0;
i = 0;
while(i < 32) {
for (i = 0; i < 32; i++) {
dch = hc->chan[i].ch;
if (!dch || !test_bit(FLG_DCHANNEL, &dch->Flags)) {
i++;
continue;
}
port = hc->chan[i].port;
@ -3141,7 +3134,6 @@ hfcmulti_initmode(hfc_multi_t *hc)
udelay(6); /* wait at least 5,21us */
HFC_outb(hc, A_ST_WR_STATE, a_st_wr_state);
r_sci_msk |= 1 << port;
i++;
}
/* state machine interrupts */
HFC_outb(hc, R_SCI_MSK, r_sci_msk);
@ -3423,6 +3415,7 @@ setup_pci(hfc_multi_t *hc, struct pci_dev *pdev, int id_idx)
return (-EIO);
}
hc->leds = id_list[id_idx].leds;
hc->ledstate = 0xFFFFFFFF;
hc->opticalsupport = id_list[id_idx].opticalsupport;
#ifdef CONFIG_HFCMULTI_PCIMEM
@ -3641,8 +3634,7 @@ release_port(hfc_multi_t *hc, int port)
}
/* free channels */
i = 0;
while(i < 32) {
for (i = 0; i < 32; i++) {
if (hc->chan[i].ch) {
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: free port %d %c-channel %d (1..32)\n",
@ -3660,7 +3652,6 @@ release_port(hfc_multi_t *hc, int port)
kfree(hc->chan[i].ch);
hc->chan[i].ch = NULL;
}
i++;
}
hc->created[port]=0;
@ -3689,8 +3680,7 @@ HFC_manager(void *data, u_int prim, void *arg)
/* find channel and card */
spin_lock_irqsave(&HFCM_obj.lock, flags);
list_for_each_entry(hc, &HFCM_obj.ilist, list) {
i = 0;
while(i < 32) {
for (i = 0; i < 32; i++) {
//printk(KERN_DEBUG "comparing (D-channel) card=%08x inst=%08x with inst=%08x\n", hc, &hc->dch[i].inst, inst);
if ((hc->chan[i].ch) &&
(&hc->chan[i].ch->inst == inst)) {
@ -3698,7 +3688,6 @@ HFC_manager(void *data, u_int prim, void *arg)
chan = hc->chan[i].ch;
break;
}
i++;
}
if (ch >= 0)
break;
@ -3964,8 +3953,7 @@ static int __devinit hfcpci_probe(struct pci_dev *pdev, const struct pci_device_
spin_lock_init(&hc->lock);
pt = 0;
while (pt < hc->ports) {
for (pt = 0; pt < hc->ports; pt++) {
if (port_idx >= MAX_PORTS) {
printk(KERN_ERR "Invalid HFC type.\n");
ret_err = -EINVAL;
@ -4003,8 +3991,7 @@ static int __devinit hfcpci_probe(struct pci_dev *pdev, const struct pci_device_
goto free_channels;
hc->chan[ch].ch = chan;
i=0;
while(i < bchperport) {
for (i = 0; i < bchperport; i++) {
if (hc->type == 1)
ch2 = i + 1 + (i>=15);
else
@ -4038,7 +4025,6 @@ static int __devinit hfcpci_probe(struct pci_dev *pdev, const struct pci_device_
chan->dev->wport.pif.fdata = chan;
}
#endif
i++;
}
chan = hc->chan[ch].ch;
@ -4180,7 +4166,6 @@ static int __devinit hfcpci_probe(struct pci_dev *pdev, const struct pci_device_
memcpy(&pids[pt], &pid, sizeof(pid));
pt++;
port_idx++;
}
@ -4205,37 +4190,65 @@ static int __devinit hfcpci_probe(struct pci_dev *pdev, const struct pci_device_
hfcmulti_initmode(hc);
/* check if Port Jumper config matches module param 'protocol' */
if (!hc->type && hc->ports<=4) {
// Dip Setting: (collect GPIO 13/14/15 (R_GPIO_IN1) + GPI 19/20/23 (R_GPI_IN2))
dips = ((HFC_inb(hc, R_GPIO_IN1) >> 5) & 0x7) | (HFC_inb(hc, R_GPI_IN2) & 0x98);
switch (id_list[id_idx].dip_type) {
case DIP_4S:
/* get DIP Setting for beroNet 1S/2S/4S cards
check if Port Jumper config matches module param 'protocol'
DIP Setting: (collect GPIO 13/14/15 (R_GPIO_IN1) + GPI 19/23 (R_GPI_IN2)) */
dips = ((~HFC_inb(hc, R_GPIO_IN1) & 0xE0 ) >> 5) |
((~HFC_inb(hc, R_GPI_IN2) & 0x80) >> 3) | (~HFC_inb(hc, R_GPI_IN2) & 0x08);
// Port mode (TE/NT) jumpers
pmj = ((HFC_inb(hc, R_GPI_IN3) >> 4) & 0xf);
// Port mode (TE/NT) jumpers
pmj = ((HFC_inb(hc, R_GPI_IN3) >> 4) & 0xf);
if (test_bit(HFC_CHIP_DIGICARD, &hc->chip))
pmj = ~pmj & 0xf;
if (test_bit(HFC_CHIP_DIGICARD, &hc->chip))
pmj = ~pmj & 0xf;
printk(KERN_INFO "%s: DIPs(0x%x) jumpers(0x%x)\n", __FUNCTION__, dips, pmj);
printk(KERN_INFO "%s: %s DIPs(0x%x) jumpers(0x%x)\n", __FUNCTION__, id_list[id_idx].card_name, dips, pmj);
pt = 0;
while(pt < hc->type) {
chan = hc->chan[(pt<<2)+2].ch;
// check for protocol param mismatch
if (((pmj & (1 << pt)) && (chan->inst.pid.protocol[0] == ISDN_PID_L0_TE_S0)) ||
((!(pmj & (1 << pt))) && (chan->inst.pid.protocol[0] == ISDN_PID_L0_NT_S0))) {
printk ("%s: protocol WARNING: port %i is jumpered for %s mode!\n",
__FUNCTION__,
pt,
(pmj & (1 << pt)?"NT":"TE")
);
for (pt = 0; pt < hc->type; pt++) {
chan = hc->chan[(pt<<2)+2].ch;
// check for protocol param mismatch
if (((pmj & (1 << pt)) && (chan->inst.pid.protocol[0] == ISDN_PID_L0_TE_S0)) ||
((!(pmj & (1 << pt))) && (chan->inst.pid.protocol[0] == ISDN_PID_L0_NT_S0))) {
printk ("%s: protocol WARNING: port %i is jumpered for %s mode!\n",
__FUNCTION__,
pt,
(pmj & (1 << pt)?"NT":"TE")
);
}
}
pt++;
}
break;
case DIP_8S:
/* get DIP Setting for beroNet 8S0+ cards
enable PCI auxbridge function */
HFC_outb(hc, R_BRG_PCM_CFG, 1 | V_PCM_CLK);
// disables interrupts
disable_hwirq(hc);
// prepare access to auxport
outw(0x4000, hc->pci_iobase + 4);
// some dummy reads are required to read valid DIP switch data
dips = inb(hc->pci_iobase);
dips = inb(hc->pci_iobase);
dips = inb(hc->pci_iobase);
dips = ~inb(hc->pci_iobase) & 0x3F;
// enable interrups
enable_hwirq(hc);
outw(0x0, hc->pci_iobase + 4);
// disable PCI auxbridge function
HFC_outb(hc, R_BRG_PCM_CFG, V_PCM_CLK);
printk(KERN_INFO "%s: %s DIPs(0x%x)\n", __FUNCTION__, id_list[id_idx].card_name, dips);
break;
case DIP_E1:
/* get DIP Setting for beroNet E1 cards
DIP Setting: collect GPI 4/5/6/7 (R_GPI_IN0) */
dips = (~HFC_inb(hc, R_GPI_IN0) & 0xF0)>>4;
printk(KERN_INFO "%s: %s DIPs(0x%x)\n", __FUNCTION__, id_list[id_idx].card_name, dips);
break;
}
/* add stacks */
pt = 0;
while(pt < hc->ports) {
for (pt = 0; pt < hc->ports; pt++) {
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: Adding d-stack: card(%d) port(%d)\n", __FUNCTION__, HFC_idx+1, pt+1);
if (hc->type == 1)
@ -4257,8 +4270,7 @@ free_release:
dst = chan->inst.st;
i = 0;
while(i < bchperport) {
for (i = 0; i < bchperport; i++) {
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: Adding b-stack: card(%d) port(%d) B-channel(%d)\n", __FUNCTION__, HFC_idx+1, pt+1, i+1);
if (hc->type == 1)
@ -4271,7 +4283,6 @@ free_delstack:
mISDN_ctrl(dst, MGR_DELSTACK | REQUEST, NULL);
goto free_release;
}
i++;
}
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: (before MGR_SETSTACK REQUEST) layermask=0x%x\n", __FUNCTION__, pids[pt].layermask);
@ -4290,7 +4301,6 @@ free_delstack:
/* tell stack, that we are ready */
mISDN_ctrl(dst, MGR_CTRLREADY | INDICATION, NULL);
pt++;
}
/* now turning on irq */
@ -4307,8 +4317,7 @@ free_delstack:
/* if an error ocurred */
free_channels:
i = 0;
while(i < 32) {
for (i = 0; i < 32; i++) {
if (hc->chan[i].ch) {
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: free %c-channel %d (1..32)\n",
@ -4318,7 +4327,6 @@ free_delstack:
kfree(hc->chan[i].ch);
hc->chan[i].ch = NULL;
}
i++;
}
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: before REMOVE_FROM_LIST (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
@ -4434,6 +4442,13 @@ HFCmulti_cleanup(void)
if (register_interrupt) {
symbol_put(ztdummy_register_interrupt);
}
if (unregister_interrupt) {
if (interrupt_registered) {
interrupt_registered = 0;
unregister_interrupt();
}
symbol_put(ztdummy_unregister_interrupt);
}
/* unregister mISDN object */
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: entered (refcnt = %d HFC_cnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt, HFC_cnt);
@ -4486,6 +4501,7 @@ HFCmulti_init(void)
/* get interrupt function pointer */
hfc_interrupt = symbol_get(ztdummy_extern_interrupt);
register_interrupt = symbol_get(ztdummy_register_interrupt);
unregister_interrupt = symbol_get(ztdummy_unregister_interrupt);
printk(KERN_INFO "mISDN: HFC-multi driver Rev. %s\n", mISDN_getrev(tmpstr));
switch(poll) {

View File

@ -136,6 +136,7 @@ struct hfc_multi {
u_int slots; /* number of PCM slots */
u_int leds; /* type of leds */
u_int ledcount; /* used to animate leds */
u_long ledstate; /* save last state of leds */
int opticalsupport; /* has the e1 board an optical Interface*/
u_long wdcount; /* every 500 ms we need to send the watchdog a signal */

View File

@ -0,0 +1,99 @@
#
# Makefile for Octasic OCTVQE echo canceller software
#
# Copyright (C) 2006 Octasic, Inc.
#
#
.PHONY: clean all install modules linux24 linux26
INSTALL=/usr/bin/install
CC=gcc
#kernel version
KVERS:=$(shell uname -r)
ifeq ($(PWD),)
PWD=$(shell pwd)
endif
ifeq ($(DEB_HOST_GNU_TYPE),)
UNAME_M:=$(shell uname -m)
else
UNAME_M:=$(DEB_HOST_GNU_TYPE)
endif
ifdef CONFIG_MODULES
ifdef CONFIG_MODVERSIONS
MODFLAGS += -DMODVERSIONS -include $(HPATH)/linux/modversions.h
endif
endif
ifndef KSRC
ifneq (,$(wildcard /lib/modules/$(KVERS)/build))
KSRC:=/lib/modules/$(KVERS)/build
else
KSRC_SEARCH_PATH:=/usr/src/linux-2.4 /usr/src/linux
KSRC:=$(shell for dir in $(KSRC_SEARCH_PATH); do if [ -d $$dir ]; then echo $$dir; break; fi; done)
endif
endif
KVERS_MAJ:=$(shell echo $(KVERS) | cut -d. -f1-2)
KINCLUDES:=$(KSRC)/include
KFLAGS=-I$(KINCLUDES) -O2
KFLAGS+=-DMODULE -D__KERNEL__ -DEXPORT_SYMTAB -Wall -I. -Wno-unused-function -Wstrict-prototypes -fomit-frame-pointer -fno-strict-aliasing
ifneq (,$(wildcard $(KINCLUDES)/linux/modversions.h))
KFLAGS+=-DMODVERSIONS -include $(KINCLUDES)/linux/modversions.h
endif
ifneq (,$(findstring ppc,$(UNAME_M)))
KFLAGS_PPC:=-msoft-float -fsigned-char
endif
KFLAGS+=$(KFLAGS_PPC)
ifeq ($(KVERS_MAJ),2.4)
ifneq (,$(findstring x86_64,$(UNAME_M)))
KFLAGS+=-mcmodel=kernel
endif
endif
OCTOBJS = octvqe_linux.o
obj-m:= octvqe.o
octvqe-objs:= $(OCTOBJS)
KMAKE = $(MAKE) -C $(KSRC) SUBDIRS=$(PWD)
KMAKE_INST = $(KMAKE) \
INSTALL_MOD_PATH=$(INSTALL_PREFIX) INSTALL_MOD_DIR=misc modules_install
ifeq ($(KVERS_MAJ),2.4)
BUILDVER:=linux24
else
BUILDVER:=linux26
endif
MOD_DIR:=$(INSTALL_PREFIX)/lib/modules/$(KVERS)/misc
all: $(BUILDVER)
linux24: octvqe.o
linux26:
@if [ -z "$(KSRC)" -o ! -d "$(KSRC)" ]; then echo "The sources for $(KVERS) kernel cannot be found."; exit 1 ; fi
$(KMAKE) modules
octvqe.o: octvqe_linux.c
$(CC) $(KFLAGS) -o octvqe.o -c octvqe_linux.c
install: all
ifeq ($(BUILDVER),linux26)
$(KMAKE_INST)
else
$(INSTALL) -d $(MOD_DIR)
$(INSTALL) -m 644 octvqe.o $(MOD_DIR)
endif
clean:
rm -f Modules.symvers
rm -f octvqe.ko
rm -f octvqe.o
rm -f octvqe_linux.o
rm -f .*o.cmd
rm -f *.mod.c
rm -f *.mod.o

View File

@ -0,0 +1,46 @@
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
File: octvqe_linux.h
This file is part of the OCTVQE GPL kernel module. The OCTVQE GPL kernel module
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.
The OCTVQE GPL module 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 the OCTVQE GPL module; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Description: Zaptel OCTVQE module I/O control defines
$Octasic_Release: OCTVQE8-01.01.02-PR $
$Octasic_Revision: 4 $
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#ifndef __OCTVQE_IOCTL_H__
#define __OCTVQE_IOCTL_H__
/* Use o as magic number */
#define OCTDEV_IOCTL_MAGIC 'o'
#define OCTDEV_IOCTL_TAIL_LENGTH _IOW( OCTDEV_IOCTL_MAGIC, 0, int )
#define OCTDEV_IOCTL_TAIL_DISPLACEMENT _IOW( OCTDEV_IOCTL_MAGIC, 1, int )
#define OCTDEV_IOCTL_ERL _IOW( OCTDEV_IOCTL_MAGIC, 2, int )
#define OCTDEV_IOCTL_RIN_ANR _IOW( OCTDEV_IOCTL_MAGIC, 3, int )
#define OCTDEV_IOCTL_SOUT_ANR _IOW( OCTDEV_IOCTL_MAGIC, 4, int )
#define OCTDEV_IOCTL_RIN_CURRENT_ENERGY _IOW( OCTDEV_IOCTL_MAGIC, 5, int )
#define OCTDEV_IOCTL_SIN_CURRENT_ENERGY _IOW( OCTDEV_IOCTL_MAGIC, 6, int )
#define OCTDEV_IOCTL_RIN_AVERAGE_ENERGY _IOW( OCTDEV_IOCTL_MAGIC, 7, int )
#define OCTDEV_IOCTL_SIN_AVERAGE_ENERGY _IOW( OCTDEV_IOCTL_MAGIC, 8, int )
#define OCTDEV_IOCTL_AVERAGE_TIME_US _IOW( OCTDEV_IOCTL_MAGIC, 9, int )
#define OCTDEV_IOCTL_MAX_TIME_US _IOW( OCTDEV_IOCTL_MAGIC, 10, int )
#define OCTDEV_IOCTL_MAXNR 10
#endif /* __OCTVQE_IOCTL_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
File: octvqe_linux.h
This file is part of the OCTVQE GPL kernel module. The OCTVQE GPL kernel module
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.
The OCTVQE GPL module 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 the OCTVQE GPL module; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Description: Zaptel Linux OCTVQE module header
$Octasic_Release: OCTVQE8-01.01.02-PR $
$Octasic_Revision: 5 $
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#ifndef __OCTVQE_LINUX_H__
#define __OCTVQE_LINUX_H__
/***************************** FUNCTIONS ***********************************/
void * ZapOctVqeApiEcChannelInitialize(int f_iLen, int f_iAdaptionMode);
int ZapOctVqeApiEcChannelTrainTap(void * f_pvEcChan, int f_iPos, short f_sVal);
short ZapOctVqeApiEcChannelProcess(void * f_pvEcChan, short f_sRin, short f_sSin);
void ZapOctVqeApiEcChannelFree(void * f_pvEcChan);
#endif /* __OCTVQE_LINUX_H__ */

View File

@ -19,6 +19,13 @@ static ssize_t show_st_id(struct class_device *class_dev, char *buf)
}
static CLASS_DEVICE_ATTR(id, S_IRUGO, show_st_id, NULL);
static ssize_t show_st_protocol(struct class_device *class_dev, char *buf)
{
mISDNstack_t *st = to_mISDNstack(class_dev);
return sprintf(buf, "0x%08x\n", st->pid.modparm_protocol);
}
static CLASS_DEVICE_ATTR(protocol, S_IRUGO, show_st_protocol, NULL);
static ssize_t show_st_status(struct class_device *class_dev, char *buf)
{
mISDNstack_t *st = to_mISDNstack(class_dev);
@ -247,6 +254,7 @@ mISDN_register_sysfs_stack(mISDNstack_t *st)
class_device_create_file(&st->class_dev, &class_device_attr_id);
class_device_create_file(&st->class_dev, &class_device_attr_qlen);
class_device_create_file(&st->class_dev, &class_device_attr_protocol);
class_device_create_file(&st->class_dev, &class_device_attr_status);
#ifdef SYSFS_SUPPORT

16
include/linux/mISDNdsp.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef __mISDNdsp_H__
#define __mISDNdsp_H__
typedef struct _mISDN_dsp_element {
void* (* new) (const char *arg);
void (* free) (void *p);
void (* process_tx) (void *p, unsigned char *data, int len);
void (* process_rx) (void *p, unsigned char *data, int len);
char name[];
} mISDN_dsp_element_t;
extern int mISDN_dsp_element_register (mISDN_dsp_element_t *elem);
extern void mISDN_dsp_element_unregister (mISDN_dsp_element_t *elem);
#endif

View File

@ -19,7 +19,7 @@
* - changed if any interface is extended but backwards compatible
*
*/
#define MISDN_MAJOR_VERSION 5
#define MISDN_MAJOR_VERSION 6
#define MISDN_MINOR_VERSION 0
#define MISDN_VERSION ((MISDN_MAJOR_VERSION<<16) | MISDN_MINOR_VERSION)
@ -190,8 +190,7 @@
#define BF_DISABLE 0x2315
#define BF_ACCEPT 0x2316
#define BF_REJECT 0x2317
#define ECHOCAN_ON 0x2318
#define ECHOCAN_OFF 0x2319
#define PIPELINE_CFG 0x2318
#define HW_POTS_ON 0x1001
#define HW_POTS_OFF 0x1002
#define HW_POTS_SETMICVOL 0x1100
@ -615,6 +614,7 @@ typedef struct _mISDN_pid {
u16 param[MAX_LAYER_NR +1];
u16 global;
u16 pidx;
u_char modparm_protocol;
u_char *pbuf;
} mISDN_pid_t;

View File

@ -1,25 +0,0 @@
install hfcmulti /usr/sbin/misdn-init start hfcmulti
remove hfcmulti /usr/sbin/misdn-init stop
install hfcpci /usr/sbin/misdn-init start hfcpci
remove hfcpci /usr/sbin/misdn-init stop
install hfcsusb /usr/sbin/misdn-init start hfcsusb
remove hfcsusb /usr/sbin/misdn-init stop
install hfcsmini /usr/sbin/misdn-init start hfcsmini
remove hfcsmini /usr/sbin/misdn-init stop
install xhfc /usr/sbin/misdn-init start xhfc
remove xhfc /usr/sbin/misdn-init stop
install avmfritz /usr/sbin/misdn-init start avmfritz
remove avmfritz /usr/sbin/misdn-init stop
install w6692pci /usr/sbin/misdn-init start w6692pci
remove w6692pci /usr/sbin/misdn-init stop
install sedlfax /usr/sbin/misdn-init start sedlfax
remove sedlfax /usr/sbin/misdn-init stop

View File

@ -1,776 +0,0 @@
#!/bin/bash
################################################################################
#
# misdn-init init script
#
# Copyright (C) 2005, Nadi Sarrar
#
# Nadi Sarrar <nadi@beronet.com>
#
# This program is free software, distributed under the terms of
# the GNU General Public License
#
#
# USAGE:
#
# /usr/sbin/misdn-init start|stop|restart|config|scan|help
#
# chkconfig: 2345 35 60
# description: mISDN Kernel Modules
#
# CONFIGURATION:
#
# Path to your misdn-init.conf:
#
misdn_init_conf="/etc/misdn-init.conf"
#
################################################################################
#
# change this to modify the user/group settings of /dev/mISDN
#
USER=asterisk
GROUP=asterisk
# HFC 8/4 (S0) Options
master_clock=17
# HFC-E1 Options
optical=17
los=19
ais=20
slip=21
nocrc4=24
# Card Settings
ulaw=9
dtmf=10
pcm_slave=12
ignore_pcm_frameclock=13
rxclock=14
crystalclock=19
watchdog=20
#dsp defaults
dsp_options=0
poll_option=
dsp_poll_option=
dtmfthreshold_option=
function check_cmd {
if ! which "${1}" > /dev/null; then
if [ "$(id -u)" != "0" ]; then
echo "[!!] FATAL: $1 not in path, please install and/or be root."
else
echo "[!!] FATAL: $1 not in path, please install."
fi
if [ "${2}" != "notfatal" ] ; then
exit 1
fi
else
var=$(echo ${1} | tr a-z A-Z)
eval "$var=`which ${1}`"
fi
}
check_cmd modprobe
check_cmd rmmod
check_cmd insmod
check_cmd lspci
check_cmd lsusb notfatal
check_cmd mknod
check_cmd bc
check_cmd cut
check_cmd wc
function check_asterisk {
if ps ax | grep -v grep | grep asterisk > /dev/null ; then asterisk -rx "stop now" ; fi
}
function create_card_db
{
cardline=""
cardcount=1
skipnext=0
IFS=$'\n'
NL="
"
function addcard {
cardline="${cardline}${cardcount},${1}${NL}"
let "cardcount = ${cardcount} + 1"
}
function addport {
let "portcount = ${portcount} + ${1}"
}
for line in $(${LSPCI} -n -d 0xd161:b410); do
addcard "4,0x4"
done
for line in $(${LSPCI} -n | sed -n 's/^\(0000:\|\)\([0-9a-f]\{2\}:[0-9a-f]\{2\}.[0-9a-f]\{1\}\)\( Class \| \)[0-9a-f]\{4\}: 1397:\([0-9a-f]\{4\}\).*$/\4 \2/p'); do
if [ ${skipnext} -eq 1 ]; then
skipnext=0
continue
fi
case "${line}" in
30b1*)
case "${line:5}" in
00*)
addcard "1,0x1"
;;
*)
if [ $(${LSPCI} -n -s ${line:5:3} | ${WC} -l) -eq 2 ]; then
addcard "2,2E1"
skipnext=1
else
addcard "1,0x1"
fi
;;
esac
;;
16b8*)
addcard "8,0x8"
;;
08b4*)
if ${LSPCI} -n -v -s "${line:5}" | grep "Subsystem" | grep "1397:b567" > /dev/null ; then
addcard "1,0x4"
elif ${LSPCI} -n -v -s "${line:5}" | grep "Subsystem" | grep "1397:b566\|1397:b569" > /dev/null ; then
addcard "2,0x4"
else
addcard "4,0x4"
fi
;;
esac
done
for line in $(${LSPCI} -n | grep "1397:\(2bd\(0\|6\|7\|8\|9\|a\|b\|c\)\|b100\)\|1043:0675\|0871:ffa\(1\|2\)\|1051:0100\|15b0:2bd0\|114f:007\(0\|1\|2\|3\)\|13d1:2bd1\|182d:3069"); do
addcard "1,hfcpci"
done
for line in $(${LSPCI} -n | grep "1244:\(0a00\|0e00\)"); do
addcard "1,avmfritz"
done
for line in $(${LSPCI} -n -d 1050:6692); do
addcard "1,w6692pci"
done
if [ -e ${LSUSB} ]; then
for line in $(${LSUSB} | grep "0959:2bd0\|0675:1688\|07b0:0007\|0742:200\(7\|8\|9\|A\)\|08e3:0301\|07fa:084\(7\|8\)\|07ba:0006"); do
addcard "1,hfcsusb"
done
fi
echo "${cardline}"
}
function load_card_modules {
carddb=$(create_card_db)
function find_carddb_line {
i=1
for l in ${carddb} ; do
if [ $i -eq $1 ] ; then
echo $l
return
fi
let "i=$i+1"
done
}
if [ ! -z "$1" ] ; then
echo "Loading only $1"
fi
IFS=$'\n'
skipnr=0
for line in $(sed -n -e '/^[^#]/p' ${misdn_init_conf});
do
var=$(echo "${line}" | ${CUT} -d "=" -f1)
val=$(echo "${line}" | ${CUT} -d "=" -f2)
case "${var}" in
card)
#echo "processing line: $val"
nr=$(echo "${val}" | ${CUT} -d "," -f1)
mod=$(echo "${val}" | ${CUT} -d "," -f2)
opns=$(echo "${val}" | ${CUT} -d "," -f3-)
#getting portcount from carddb
ports=$(find_carddb_line $nr | ${CUT} -d "," -f2)
let "nr = ${nr} + ${skipnr}"
#echo "nr $nr ports $ports mod $mod opns: $opns"
case "${mod}" in
2E1)
hfcmulti[${nr}]=1
hfcmulti[$((${nr} + 1))]=1
let "hfcports = ${hfcports} + ${ports}"
IFS=$','
for li in ${opns}; do
hfcmulti[${nr}]=$(echo "obase=10;2^(${!li}-1)+${hfcmulti[${nr}]}" | ${BC})
if [ "${li}" != "pcm_slave" ]; then
hfcmulti[$((${nr} + 1))]=$(echo "obase=10;2^(${!li}-1)+${hfcmulti[$((${nr}+1))]}" | ${BC})
fi
done
IFS=$'\n'
hfcmulti[$((${nr} + 1))]=$(echo "obase=10;2^(${pcm_slave}-1)+${hfcmulti[$((${nr}+1))]}" | ${BC})
let "skipnr = ${skipnr} + 1"
;;
0x*)
hfcmulti[${nr}]=$(echo ${mod} | sed -e "s/^0x\([0-9]*\)/\1/")
let "hfcports = ${hfcports} + ${ports}"
IFS=$','
for li in ${opns}; do
hfcmulti[${nr}]=$(echo "obase=10;2^(${!li}-1)+${hfcmulti[${nr}]}" | ${BC})
done
IFS=$'\n'
;;
*)
other_card[${nr}]=${mod}
;;
esac
;;
te_ptp)
IFS=$','
for li in ${val}; do
layermask[${li}]="0xf"
protocol[${li}]=34 # 0x22 == 34
done
IFS=$'\n'
;;
te_ptmp)
IFS=$','
for li in ${val}; do
layermask[${li}]="0xf"
protocol[${li}]=2 # 0x2 == 2
done
IFS=$'\n'
;;
nt_*)
IFS=$','
for li in ${val}; do
layermask[${li}]="0x3"
protocol[${li}]=18 # 0x12 == 18
done
IFS=$'\n'
;;
te_capi_ptp)
IFS=$','
for li in ${val}; do
layermask[${li}]="0x0"
protocol[${li}]=34 # 0x22 == 34
done
IFS=$'\n'
export addcapi=1
;;
te_capi_ptmp)
IFS=$','
for li in ${val}; do
layermask[${li}]="0x0"
protocol[${li}]=2 # 0x2 == 2
done
IFS=$'\n'
export addcapi=1
;;
option)
port=`echo "${val}" | sed -e "s/^\([0-9]*\),.*/\1/"`
opt=`echo "${val}" | sed -e "s/^[0-9]*,\(.*\)/\1/"`
if [ -z ${protocol[${port}]} ]; then
protocol[${port}]="0"
fi
IFS=$','
for li in ${opt}; do
protocol[${port}]=$(echo "obase=10;2^(${!li}-1)+${protocol[${port}]}" | ${BC})
done
IFS=$'\n'
;;
poll)
poll=${val}
poll_option=poll=${val}
;;
dsp_poll)
dsp_poll_option=poll=${val}
;;
pcm)
pcm=${val}
;;
dsp_options)
export dsp_options=${val}
;;
dtmfthreshold)
export dtmfthreshold_option="dtmfthreshold=${val}"
;;
debug)
debug=${val}
;;
timer)
timer=${val}
;;
*)
echo "unknown variable: ${var}"
;;
esac
done
echo "-----------------------------------------"
echo " Loading module(s) for your misdn-cards:"
echo "-----------------------------------------"
card_index=1
port_index=1
while [ ! -z ${hfcmulti[${card_index}]} ] || [ ! -z ${other_card[${card_index}]} ];
do
if [ ! -z ${hfcmulti[${card_index}]} ]; then
# MODPROBE COMMAND FOR hfcmulti CARD
hfcmulti_type="type="
hfcmulti_prot="protocol="
hfcmulti_layer="layermask="
while [ ! -z ${hfcmulti[${card_index}]} ];
do
hfcmulti_type="${hfcmulti_type}$(echo "obase=16;\"0x\";${hfcmulti[${card_index}]}" | ${BC} ),"
let "card_index = ${card_index} + 1"
done
while [ ${hfcports} -gt 0 ];
do
if [ ! -z ${protocol[${port_index}]} ]; then
hfcmulti_prot="${hfcmulti_prot}$(echo "obase=16;\"0x\";${protocol[${port_index}]}" | ${BC}),"
else
hfcmulti_prot="${hfcmulti_prot}0x2,"
fi
if [ ! -z ${layermask[${port_index}]} ]; then
hfcmulti_layer="${hfcmulti_layer}${layermask[${port_index}]},"
else
hfcmulti_layer="${hfcmulti_layer}0xf,"
fi
let "port_index = ${port_index} + 1"
let "hfcports = ${hfcports} - 1"
done
hfcmulti_type="$(echo ${hfcmulti_type} | sed -e 's/^\(.*\),$/\1/')"
hfcmulti_prot="$(echo ${hfcmulti_prot} | sed -e 's/^\(.*\),$/\1/')"
hfcmulti_layer="$(echo ${hfcmulti_layer} | sed -e 's/^\(.*\),$/\1/')"
hfcmulti_cmd="${MODPROBE} --ignore-install hfcmulti ${hfcmulti_type} ${hfcmulti_prot} ${hfcmulti_layer}"
if [ ! -z ${poll} ]; then
hfcmulti_cmd="${hfcmulti_cmd} poll=${poll}"
fi
if [ ! -z ${pcm} ]; then
hfcmulti_cmd="${hfcmulti_cmd} pcm=${pcm}"
fi
if [ ! -z ${debug} ]; then
hfcmulti_cmd="${hfcmulti_cmd} debug=${debug}"
fi
if [ ! -z ${timer} ]; then
hfcmulti_cmd="${hfcmulti_cmd} timer=${timer}"
fi
if [ -z "$1" ] ; then
echo ${hfcmulti_cmd}
eval ${hfcmulti_cmd}
else
if [ "$1" = "hfcmulti" ] ; then
echo ${hfcmulti_cmd}
eval ${hfcmulti_cmd}
fi
fi
else
# MODPROBE COMMAND FOR _NON_ hfcmulti CARD
other_mod="${other_card[${card_index}]}"
other_cmd="${MODPROBE} --ignore-install ${other_mod}"
if [ ! -z ${protocol[${port_index}]} ]; then
other_prot="protocol=$(echo "obase=16;\"0x\";${protocol[${port_index}]}" | ${BC}),"
else
other_prot="protocol=0x2,"
fi
if [ ! -z ${layermask[${port_index}]} ]; then
other_layer="layermask=${layermask[${port_index}]},"
else
other_layer="layermask=0xf,"
fi
other_extra=""
modinfo $other_mod | egrep -q 'parm: *poll' && other_extra="$other_extra ${poll_option}"
let "prev = ${card_index}"
let "card_index = ${card_index} + 1"
let "port_index = ${port_index} + 1"
while [ "${other_card[${card_index}]}" == "${other_card[${prev}]}" ];
do
if [ ! -z ${protocol[${port_index}]} ]; then
other_prot="${other_prot}$(echo "obase=16;\"0x\";${protocol[${port_index}]}" | ${BC}),"
else
other_prot="${other_prot}0x2,"
fi
if [ ! -z ${layermask[${port_index}]} ]; then
other_layer="${other_layer}${layermask[${port_index}]},"
else
other_layer="${other_layer}0xf,"
fi
let "prev = ${card_index}"
let "card_index = ${card_index} + 1"
let "port_index = ${port_index} + 1"
done
other_prot="$(echo ${other_prot} | sed -e 's/^\(.*\),$/\1/')"
other_layer="$(echo ${other_layer} | sed -e 's/^\(.*\),$/\1/')"
other_cmd="${other_cmd} ${other_prot} ${other_layer} ${other_extra}"
if [ -z "$1" ] ; then
echo "${other_cmd}"
eval ${other_cmd}
else
if [ "$1" = "${other_card[${prev}]}" ] ; then
echo ${other_cmd}
eval ${other_cmd}
fi
fi
fi
done
}
function unload_card_modules {
IFS=$'\n'
for line in $(sed -ne '/^[^#]/p' ${misdn_init_conf});
do
var=$(echo "${line}" | ${CUT} -d "=" -f 1)
val=$(echo "${line}" | ${CUT} -d "=" -f 2)
case "${var}" in
card)
nr=$(echo "${val}" | ${CUT} -d "," -f 1)
mod=$(echo "${val}" | ${CUT} -d "," -f 2)
case "${mod}" in
2E1)
modulelist[${nr}]=hfcmulti
;;
0x*)
modulelist[${nr}]=hfcmulti
;;
*)
modulelist[${nr}]=${mod}
;;
esac
;;
esac
done
echo "-------------------------------------------"
echo " Unloading module(s) for your misdn-cards:"
echo "-------------------------------------------"
rmmod_cmd="${RMMOD} ${modulelist[1]}"
echo "${rmmod_cmd}"
eval ${rmmod_cmd}
index=2
prev=1
while [ ! -z ${modulelist[${index}]} ];
do
if [ ${modulelist[${index}]} != ${modulelist[${prev}]} ]; then
rmmod_cmd="${RMMOD} ${modulelist[${index}]}"
echo "${rmmod_cmd}"
eval ${rmmod_cmd}
fi
let "prev = ${index}"
let "index = ${index} + 1"
done
}
function create_misdn_init_conf {
cardline=""
cardcount=1
portcount=0
cardconf=""
IFS=$'\n'
NL="
"
carddb=$(create_card_db)
for line in $carddb ; do
tmp="card=$(echo $line | ${CUT} -d, -f1,3)"
let "portcount = ${portcount} + $(echo $line | ${CUT} -d, -f2)"
cardline="${cardline}${tmp}${NL}"
done
function die {
echo "[!!] ${1}"
exit 1
}
if [ "${1}" == "scan" ]; then
echo "[OK] found the following devices:"
echo "${cardline}[ii] run \"/usr/sbin/misdn-init config\" to store this information to ${misdn_init_conf}"
else
index=1
portline="te_ptmp="
while [ ${index} -le ${portcount} ]; do
portline="${portline}${index},"
let "index = ${index} + 1"
done
portline="$(echo ${portline} | sed -e 's/^\(.*\),$/\1/')"
misdn_cfg_pt1="#
# Configuration file for your misdn hardware
#
# Usage: /usr/sbin/misdn-init start|stop|restart|config|scan|help
#
#
# Card Settings
#
# Syntax: card=<number>,<type>[,<option>...]
#
# <number> count your cards beginning with 1
# <type> either 0x1,0x4 or 0x8 for your hfcmulti hardware,
# or the name of your card driver module.
# <option> ulaw - uLaw (instead of aLaw)
# dtmf - enable DTMF detection on all B-channels
#
# pcm_slave - set PCM bus into slave mode
# If you have a set of cards, all wired via PCM. Set
# all cards into pcm_slave mode and leave one out.
# The left card will automatically be Master.
#
# ignore_pcm_frameclock - this can be set in conjunction with
# pcm_slave. If this card has a
# PCI Bus Position before the Position
# of the Master, then this port cannot
# yet receive a frameclock, so it must
# ignore the pcm frameclock.
#
# rxclock - use clocking for pcm from ST Port
# crystalclock - use clocking for pcm from PLL (genrated on board)
# watchdog - This dual E1 Board has a Watchdog for
# transparent mode
#
#"
misdn_cfg_pt2="#
# Port settings
#
# Syntax: <port_type>=<port_number>[,<port_number>...]
#
# <port_type> te_ptp - TE-Mode, PTP
# te_ptmp - TE-Mode, PTMP
# te_capi_ptp - TE-Mode (capi), PTP
# te_capi_ptmp - TE-Mode (capi), PTMP
# nt_ptp - NT-Mode, PTP
# nt_ptmp - NT-Mode, PTMP
# <port_number> port that should be considered
#"
misdn_cfg_pt3="#
# Port Options
#
# Syntax: option=<port_number>,<option>[,<option>...]
#
# <option> master_clock - use master clock for this S/T interface
# (only once per chip, only for HFC 8/4)
# optical - optical (only HFC-E1)
# los - report LOS (only HFC-E1)
# ais - report AIS (only HFC-E1)
# slip - report SLIP (only HFC-E1)
# nocrc4 - turn off crc4 mode use double frame instead
# (only HFC-E1)
#
# The master_clock option is essential for retrieving and transmitting
# faxes to avoid failures during transmission. It tells the driver to
# synchronize the Card with the given Port which should be a TE Port and
# connected to the PSTN in general.
#
#option=1,master_clock
#option=2,ais,nocrc4
#option=3,optical,los,ais,slip
#
# General Options for your hfcmulti hardware
#
# poll=<number>
#
# Only one poll value must be given for all cards.
# Give the number of samples for each fifo process.
# By default 128 is used. Decrease to reduce delay, increase to
# reduce cpu load. If unsure, don't mess with it!!!
# Valid is 32, 64, 128, 256.
#
# dsp_poll=<number>
# This is the poll option which is used by mISDN_dsp, this might
# differ from the one given by poll= for the hfc based cards, since
# they can only use multiples of 32, the dsp_poll is dependant on
# the kernel timer setting which can be found in the CPU section
# in the kernel config. Defaults are there either 100Hz, 250Hz
# or 1000Hz. If your setting is either 1000 or 250 it is compatible
# with the poll option for the hfc chips, if you have 100 it is
# different and you need here a multiple of 80.
# The default is to have no dsp_poll option, then the dsp itself
# finds out which option is the best to use by itself
#
# pcm=<number>
#
# Give the id of the PCM bus. All PCM busses with the same ID
# are expected to be connected and have equal slots.
# Only one chip of the PCM bus must be master, the others slave.
#
# debug=<number>
#
# Enable debugging (see hfc_multi.h for debug options).
#
# dsp_options=<number>
#
# set this to 2 and you'll have software bridging instead of
# hardware bridging.
#
#
# dtmfthreshold=<milliseconds>
#
# Here you can tune the sensitivity of the dtmf tone recognizer.
#
# timer=<1|0>
#
# set this to 1 if you want hfcmulti to register at ztdummy (zaptel)
# and provide a 1khz timing source for it. This makes it possible
# to have an accurate timing source for asterisk through zaptel from
# hfcmulti to make applications like Meetme and faxing between wctdm
# and hfcmulti work properly.
#
poll=128
dsp_poll=128
dsp_options=0
dtmfthreshold=100
debug=0"
if [ -f ${misdn_init_conf} ]; then
cp "${misdn_init_conf}" "${misdn_init_conf}.save" || die "could not backup your existing ${misdn_init_conf}!"
echo "[OK] ${misdn_init_conf} already present. backing it up to ${misdn_init_conf}.save"
fi
echo "${misdn_cfg_pt1}${NL}${cardline}${NL}${misdn_cfg_pt2}${NL}${portline}${NL}${NL}${misdn_cfg_pt3}" > ${misdn_init_conf} || die "could not write to /etc/misdn-init.conf!"
#echo "${misdn_cfg_pt1}${NL}${cardline}${NL}${misdn_cfg_pt2}${NL}${portline}${NL}${NL}${misdn_cfg_pt3}" > testconf || die "could not write to /etc/misdn-init.conf!"
echo "[OK] ${misdn_init_conf} created. It's now safe to run \"/usr/sbin/misdn-init start\""
if [ ${portcount} -gt 1 ]; then
echo "[ii] make your ports (1-${portcount}) available in asterisk by editing \"/etc/asterisk/misdn.conf\""
elif [ ${portcount} -eq 1 ]; then
echo "[ii] make your port (1) available in asterisk by editing \"/etc/asterisk/misdn.conf\""
fi
fi
}
function check_cfg_file {
if [ ! -f ${misdn_init_conf} ]; then
if [ ! -z "$1" ] ; then
/usr/sbin/misdn-init config
else
echo "[!!] failed to load: ${misdn_init_conf}"
echo "run \"/usr/sbin/misdn-init config\" to scan your devices and generate a basic config file."
exit 1
fi
fi
}
# MAIN #############
case "$1" in
start|--start)
check_cfg_file $2
${MODPROBE} capi
${MODPROBE} mISDN_core debug=0
${MODPROBE} mISDN_l1 debug=0
${MODPROBE} mISDN_l2 debug=0
${MODPROBE} l3udss1 debug=0
${MODPROBE} mISDN_capi
load_card_modules $2
echo "${MODPROBE} mISDN_dsp debug=0x0 options=$dsp_options $dsp_poll_option $dtmfthreshold_option"
${MODPROBE} mISDN_dsp debug=0x0 options=$dsp_options $dsp_poll_option $dtmfthreshold_option
sleep 1
if [ ! -e /dev/mISDN ]; then
$MKNOD /dev/mISDN c 46 0
if grep asterisk /etc/passwd > /dev/null; then
chown $USER:$GROUP /dev/mISDN
fi
echo "[i] creating device node: /dev/mISDN"
fi
;;
stop|--stop)
check_cfg_file
check_asterisk
for mod in $(lsmod | sed -ne '/Module/!{s/\([^ ]*\).*/\1/;p}');
do
case "${mod}" in
mISDN_capi | mISDN_dsp | l3udss1 | mISDN_l2 | mISDN_l1 | mISDN_isac )
eval "${RMMOD} ${mod}"
;;
esac
done
unload_card_modules
${RMMOD} mISDN_core
;;
restart|--restart)
check_cfg_file
sh $0 stop
sleep 2 # some phones will release tei when layer 1 is down
sh $0 start
;;
config|--config)
create_misdn_init_conf
;;
scan|--scan)
create_misdn_init_conf scan
;;
help|--help)
echo "Usage: $0 {start|stop|restart|config|scan|help}"
exit 0
;;
*)
echo "Usage: $0 {start|stop|restart|config|scan|help}"
exit 2
;;
esac