mISDN/misdn-init

781 lines
19 KiB
Bash
Executable File

#!/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
check_cmd seq
check_cmd sed
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 expand
{
local IFS=$','
for tok in $1; do
if [ "$(echo $tok | ${SED} -ne 's/\([0-9]*\)-\([0-9]*\)/\1 \2/p')" != "" ]; then
${SEQ} $(echo $tok | ${SED} -ne 's/\([0-9]*\)-[0-9]*/\1/p') $(echo $tok | ${SED} -ne 's/[0-9]*-\([0-9]*\)/\1/p')
else
echo $tok
fi
done
}
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)
for li in $(expand "${val}"); do
layermask[${li}]="0xf"
protocol[${li}]=34 # 0x22 == 34
done
;;
te_ptmp)
for li in $(expand "${val}"); do
layermask[${li}]="0xf"
protocol[${li}]=2 # 0x2 == 2
done
;;
nt_*)
for li in $(expand "${val}"); do
layermask[${li}]="0x3"
protocol[${li}]=18 # 0x12 == 18
done
;;
te_capi_ptp)
for li in $(expand "${val}"); do
layermask[${li}]="0x0"
protocol[${li}]=34 # 0x22 == 34
done
export addcapi=1
;;
te_capi_ptmp)
for li in $(expand "${val}"); do
layermask[${li}]="0x0"
protocol[${li}]=2 # 0x2 == 2
done
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