Compare commits
11 Commits
master
...
mISDN_1_2_
Author | SHA1 | Date |
---|---|---|
Nadi Sarrar | 06244ce555 | |
Chrisian Richter | 434e78c55a | |
Nadi Sarrar | 749541c595 | |
Nadi Sarrar | 7eae689857 | |
Nadi Sarrar | fc7d16fd5d | |
Nadi Sarrar | 3adb3ed79d | |
Nadi Sarrar | c8210a32da | |
Chrisian Richter | dd092efb7e | |
Nadi Sarrar | 35da393f82 | |
Nadi Sarrar | eeb7623c7e | |
Nadi Sarrar | 9fb78bc0c9 |
16
Makefile
16
Makefile
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
58
config/mISDN
58
config/mISDN
|
@ -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=""
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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] =
|
||||
|
|
|
@ -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), ¶m, 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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************/
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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__ */
|
|
@ -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);
|
||||
|
|
@ -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))
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
@ -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__ */
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
776
misdn-init
776
misdn-init
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue