Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
voip:asterisk18:isdn [04.08.2011 06:13. ] – [automatischer Programmstart] djangovoip:asterisk18:isdn [20.04.2018 09:00. ] (aktuell) – Externe Bearbeitung 127.0.0.1
Zeile 1: Zeile 1:
 +====== Asterisk Anbindung ans ISDN ======
 +
 +{{voip:asterisk.gif|Asterisk Logo}} \\
 +\\
 +Da wir mit unserem Asterisk nicht nur //hausintern// telefonieren wollen, sondern auch raus in der große weite Welt, werden wir eine Verbindung zum ISDN herstellen. Hierzu verwenden wir eine [[http://www.avm.de/de/Produkte/Weitere/FRITZ_Card_PCI/index.php|FRITZ!Card PCI]].\\
 +===== Installation =====
 +Dank des [[voip:asterisk18:repo|Asterisk-Repository]] gestaltet sich die Installation von **mISDN** und der für **Asterisk 1.6** sehr einfach.\\
 +Wir installieren uns also die folgenden Pakete: **asterisk16-misdn**, **mISDN**, **mISDNuser** und **kmod-mISDN**
 +  # yum install asterisk18-misdn mISDN mISDNuser kmod-mISDN
 +Was uns die Pakete alles mitbringt, offenbart uns jeweils der Aufruf von **rpm -iql** *PAKETNAME*.
 +==== asterisk18-misdn ====
 +   # rpm -iql asterisk18-misdn
 +<code>Name        : asterisk18-misdn             Relocations: (not relocatable)
 +Version     : 1.8.0                             Vendor: Digium, Inc.
 +Release     : 1_centos5                     Build Date: Fr 22 Okt 2010 19:17:37 CEST
 +Install Date: Mo 29 Nov 2010 15:29:42 CET      Build Host: localhost.localdomain
 +Group       : Utilities/System              Source RPM: asterisk18-1.8.0-1_centos5.src.rpm
 +Size        : 1101048                          License: GPL
 +Signature   : (none)
 +Packager    : Jason Parker <jparker@digium.com>
 +URL         : http://www.asterisk.org
 +Summary     : mISDN channel driver for Asterisk
 +Description :
 +mISDN channel driver for Asterisk
 +/usr/lib/asterisk/modules/chan_misdn.so</code>
 +==== mISDN ====
 +   # rpm -iql mISDN
 +<code>Name        : mISDN                        Relocations: (not relocatable)
 +Version     : 1.1.7.2                           Vendor: mISDN
 +Release     : 3_centos5                     Build Date: Do 30 Jul 2009 23:59:51 CEST
 +Install Date: Mo 29 Nov 2010 15:29:42 CET      Build Host: localhost.localdomain
 +Group       : Utilities/System              Source RPM: mISDN-1.1.7.2-3_centos5.src.rpm
 +Size        : 65785                            License: GPL
 +Signature   : (none)
 +Packager    : Jason Parker <jparker@digium.com>
 +URL         : http://www.misdn.org/
 +Summary     : The mISDN project
 +Description :
 +The mISDN project
 +/etc/init.d/mISDN
 +/etc/init.d/misdn-init
 +/etc/modprobe.d/mISDN
 +/etc/modules.d/mISDN
 +/usr/lib/mISDN
 +/usr/lib/mISDN/mISDN.conf.bnx.xsl
 +/usr/lib/mISDN/mISDN.conf.hfcmulti.xsl
 +/usr/lib/mISDN/mISDN.conf.hfcsusb.xsl
 +/usr/lib/mISDN/mISDN.conf.inc.xsl
 +/usr/lib/mISDN/mISDN.conf.l1oip.xsl
 +/usr/lib/mISDN/mISDN.conf.mISDN_debugtool.xsl
 +/usr/lib/mISDN/mISDN.conf.mISDN_dsp.xsl
 +/usr/lib/mISDN/mISDN.conf.singlepci.xsl
 +/usr/lib/mISDN/mISDN.conf.xhfc.xsl
 +/usr/lib/mISDN/mISDN.conf.xsl
 +/usr/sbin/mISDN
 +/usr/sbin/misdn-init</code>
 +==== mISDNuser ====
 +   # rpm -iql mISDNuser
 +<code>Name        : mISDNuser                    Relocations: (not relocatable)
 +Version     : 1.1.7.2                           Vendor: mISDN
 +Release     : 1_centos5                     Build Date: Mi 06 Aug 2008 18:04:25 CEST
 +Install Date: Mo 29 Nov 2010 15:29:32 CET      Build Host: localhost.localdomain
 +Group       : Utilities/System              Source RPM: mISDNuser-1.1.7.2-1_centos5.src.rpm
 +Size        : 859322                           License: GPL
 +Signature   : (none)
 +Packager    : Jason Parker <jparker@digium.com>
 +URL         : http://www.misdn.org/
 +Summary     : The mISDNuser project
 +Description :
 +The open source mISDNuser project
 +/usr/bin/loadfirm
 +/usr/bin/mISDNdebugtool
 +/usr/bin/misdnportinfo
 +/usr/bin/sendhwctrl
 +/usr/bin/testcon
 +/usr/bin/testcon_l2
 +/usr/bin/testlayer1
 +/usr/bin/testlayer3
 +/usr/bin/testlib
 +/usr/bin/tstlib
 +/usr/bin/voipisdn
 +/usr/lib/libisdnnet.so
 +/usr/lib/libmISDN.so
 +/usr/lib/libsuppserv.so</code>
 +==== kmod-mISDN ====
 +   # rpm -iql kmod-mISDN
 +<code>Name        : kmod-mISDN                   Relocations: (not relocatable)
 +Version     : 1.1.7.2                           Vendor: beroNet GmbH
 +Release     : 3_centos5.2.6.18_194.26.1.el5   Build Date: Mi 10 Nov 2010 17:19:31 CET
 +Install Date: Mo 29 Nov 2010 15:29:37 CET      Build Host: localhost.localdomain
 +Group       : System Environment/Kernel     Source RPM: mISDN-kmod-1.1.7.2-3_centos5.2.6.18_194.26.1.el5.src.rpm
 +Size        : 8466730                          License: GPL
 +Signature   : (none)
 +Packager    : Jason Parker <jparker@digium.com>
 +URL         : http://www.misdn.org/
 +Summary     : mISDN kernel module(s)
 +Description :
 +This package provides the mISDN kernel modules built for the Linux
 +kernel 2.6.18-194.26.1.el5 for the i686 family of processors.
 +/lib/modules/2.6.18-194.26.1.el5
 +/lib/modules/2.6.18-194.26.1.el5/extra
 +/lib/modules/2.6.18-194.26.1.el5/extra/avmfritz.ko
 +/lib/modules/2.6.18-194.26.1.el5/extra/hfcmulti.ko
 +/lib/modules/2.6.18-194.26.1.el5/extra/hfcpci.ko
 +/lib/modules/2.6.18-194.26.1.el5/extra/hfcsmini.ko
 +/lib/modules/2.6.18-194.26.1.el5/extra/hfcsusb.ko
 +/lib/modules/2.6.18-194.26.1.el5/extra/l3udss1.ko
 +/lib/modules/2.6.18-194.26.1.el5/extra/mISDN_capi.ko
 +/lib/modules/2.6.18-194.26.1.el5/extra/mISDN_core.ko
 +/lib/modules/2.6.18-194.26.1.el5/extra/mISDN_debugtool.ko
 +/lib/modules/2.6.18-194.26.1.el5/extra/mISDN_dsp.ko
 +/lib/modules/2.6.18-194.26.1.el5/extra/mISDN_dtmf.ko
 +/lib/modules/2.6.18-194.26.1.el5/extra/mISDN_isac.ko
 +/lib/modules/2.6.18-194.26.1.el5/extra/mISDN_l1.ko
 +/lib/modules/2.6.18-194.26.1.el5/extra/mISDN_l2.ko
 +/lib/modules/2.6.18-194.26.1.el5/extra/mISDN_x25dte.ko
 +/lib/modules/2.6.18-194.26.1.el5/extra/sedlfax.ko
 +/lib/modules/2.6.18-194.26.1.el5/extra/w6692pci.ko
 +/lib/modules/2.6.18-194.26.1.el5/extra/xhfc.ko</code>
 +===== Konfiguration =====
 +Als erstes suchen wir nach unserer/unseren installierten ISDN-Karten. Hierzu rufen wir den **mISDN-Daemon** mit der Option //scan// auf.
 +  # service mISDN scan
 +<code>1 mISDN compatible device(s) found:
 +>> avmfritz</code>
 +Als nächstes legen wir die Konfigurationsdatei für mISDN unter //**/etc/mISDN.conf**// an - auch das geht einfach von Statten. Wir rufen den Daemon mit der Option //config// auf.
 +  # service mISDN config
 +<code>Writing /etc/mISDN.conf for 1 mISDN compatible device(s):
 +>> avmfritz</code>
 +Mit Hilfe des vorgenannten Aufrufes wird automatisch folgende Konfigurationsdatei angelegt:
 +<code><?xml version="1.0"?>
 +<!--
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Card Type: BN2S0, BN4S0, BN8S0
 +Card Attributes: ulaw=(yes|no), dtmf=(yes|no), pcm_slave=(yes|no),
 +                 ignore_pcm_frameclock=(yes|no), rxclock=(yes|no),
 +                 crystalclock=(yes|no), watchdog=(yes|no)
 +Port Attributes: mode=(te|nt), link=(ptp|ptmp), master-clock=(yes|no),
 +                 capi=(yes|no)
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Card Type: BN2E1
 +Card Attributes: ulaw=(yes|no), dtmf=(yes|no), pcm_slave=(yes|no),
 +                 ignore_pcm_frameclock=(yes|no), rxclock=(yes|no),
 +                 crystalclock=(yes|no), watchdog=(yes|no)
 +Port Attributes: mode=(te|nt), link=(ptp|ptmp), optical=(yes|no), los=(yes|no),
 +                 ais=(yes|no), slip=(yes|no), nocrc4=(yes|no), capi=(yes|no)
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Card Type: hfcmulti, avmfritz, w6692pci
 +Port Attributes: mode=(te|nt), link=(ptp|ptmp), capi=(yes|no)
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Module: hfcmulti
 +Options: poll=<number>, pcm=<number>, debug=<number>, timer=(yes|no)
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Module: hfcsusb
 +Options: debug=<number> poll=<number>
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Module: xhfc
 +Options: debug=<number>
 +Port Attributes: mode=(te|nt), link=(ptp|ptmp), line=(s0|up) capi=(yes|no)
 +                 lineloop_b1=(yes|no) lineloop_b2=(yes|no), lineloop_d=(yes|no)
 +                 polx=(yes|no)
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Module: mISDN_dsp
 +Options: debug=<number>, options=<number>, poll=<number>,
 +         dtmfthreshold=<number>
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +-->
 +<mISDNconf>
 +        <module poll="128" debug="0" timer="no">hfcmulti</module>
 +        <module debug="0" options="0">mISDN_dsp</module>
 +        <devnode user="root" group="root" mode="644">mISDN</devnode>
 +        <card type="avmfritz">
 +                <port mode="te" link="ptmp">1</port>
 +        </card>
 +</mISDNconf></code>
 +Damit es später beim Betrieb keine Probleme mit den Zugriffsrechten auf die Gerätedatei gibt passen wir noch den **user** und die **group** des //**devnode**// an.
 +Ansonsten könnte es Bsp. zu folgender Fehlermeldung kommen:
 +<code>  == Using SIP RTP CoS mark 5
 +[Nov 30 10:35:53] ERROR[5043]: chan_sip.c:27876 setup_srtp: No SRTP module loaded, can't
 +setup SRTP session.
 +    -- Executing [08936046666@default:1] Dial("SIP/14-00000003",
 +"mISDN/g:Mnet/08936046666") in new stack
 +[Nov 30 10:35:53] WARNING[7281]: channel.c:5353 ast_request: No channel type registered
 +for 'mISDN'
 +[Nov 30 10:35:53] WARNING[7281]: app_dial.c:2030 dial_exec_full: Unable to create channel
 +of type 'mISDN' (cause 66 - Channel not implemented)
 +  == Everyone is busy/congested at this time (1:0/0/1)
 +    -- Executing [08936046666@default:2] Hangup("SIP/14-00000003", "") in new stack
 +  == Spawn extension (default, 08936046666, 2) exited non-zero on 'SIP/14-00000003'
 +asterisk*CLI>
 +</code>
 +Wir ändern also \\
 +**<devnode user="root" group="root" mode="644">mISDN</devnode>** \\
 +in \\
 +//**<devnode user="asterisk" group="asterisk" mode="644">mISDN</devnode>**//
 +   # vim /etc/mISDN
 +<code><?xml version="1.0"?>
 +<!--
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Card Type: BN2S0, BN4S0, BN8S0
 +Card Attributes: ulaw=(yes|no), dtmf=(yes|no), pcm_slave=(yes|no),
 +                 ignore_pcm_frameclock=(yes|no), rxclock=(yes|no),
 +                 crystalclock=(yes|no), watchdog=(yes|no)
 +Port Attributes: mode=(te|nt), link=(ptp|ptmp), master-clock=(yes|no),
 +                 capi=(yes|no)
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Card Type: BN2E1
 +Card Attributes: ulaw=(yes|no), dtmf=(yes|no), pcm_slave=(yes|no),
 +                 ignore_pcm_frameclock=(yes|no), rxclock=(yes|no),
 +                 crystalclock=(yes|no), watchdog=(yes|no)
 +Port Attributes: mode=(te|nt), link=(ptp|ptmp), optical=(yes|no), los=(yes|no),
 +                 ais=(yes|no), slip=(yes|no), nocrc4=(yes|no), capi=(yes|no)
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Card Type: hfcmulti, avmfritz, w6692pci
 +Port Attributes: mode=(te|nt), link=(ptp|ptmp), capi=(yes|no)
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Module: hfcmulti
 +Options: poll=<number>, pcm=<number>, debug=<number>, timer=(yes|no)
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Module: hfcsusb
 +Options: debug=<number> poll=<number>
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Module: xhfc
 +Options: debug=<number>
 +Port Attributes: mode=(te|nt), link=(ptp|ptmp), line=(s0|up) capi=(yes|no)
 +                 lineloop_b1=(yes|no) lineloop_b2=(yes|no), lineloop_d=(yes|no)
 +                 polx=(yes|no)
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Module: mISDN_dsp
 +Options: debug=<number>, options=<number>, poll=<number>,
 +         dtmfthreshold=<number>
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +-->
 +<mISDNconf>
 +        <module poll="128" debug="0" timer="no">hfcmulti</module>
 +        <module debug="0" options="0">mISDN_dsp</module>
 +        <devnode user="asterisk" group="asterisk" mode="644">mISDN</devnode>
 +        <card type="avmfritz">
 +                <port mode="te" link="ptmp">1</port>
 +        </card>
 +</mISDNconf>
 +</code>
 +===== mISDN Daemon starten =====
 +==== erster Programmstart ====
 +Zum Laden der Kernelmodule und zum Starten des **mISDN**-Daemon erfolgt mit:
 +  # service mISDN start
 +<code>-- Loading mISDN modules --
 +>> /sbin/modprobe --ignore-install capi
 +>> /sbin/modprobe --ignore-install mISDN_core debug=0
 +>> /sbin/modprobe --ignore-install mISDN_l1 debug=0
 +>> /sbin/modprobe --ignore-install mISDN_l2 debug=0
 +>> /sbin/modprobe --ignore-install l3udss1 debug=0
 +>> /sbin/modprobe --ignore-install mISDN_capi
 +>> /sbin/modprobe --ignore-install avmfritz protocol=0x2 layermask=0xf
 +>> /sbin/modprobe --ignore-install mISDN_dsp debug=0 options=0</code>
 +Der Start wird uns im **syslog** entsprechend positiv vermerkt.
 +<code>Nov 29 15:47:24 office kernel: Modular ISDN Stack core version (1_1_7_2) revision ($Revision: 1.40 $)
 +Nov 29 15:47:24 office kernel: ISDN L1 driver version 1.20
 +Nov 29 15:47:24 office kernel: ISDN L2 driver version 1.32
 +Nov 29 15:47:24 office kernel: mISDN: DSS1 Rev. 1.47
 +Nov 29 15:47:24 office kernel: mISDN Capi 2.0 driver file version 1.21
 +Nov 29 15:47:24 office kernel: ISAC module $Revision: 1.18 $
 +Nov 29 15:47:24 office kernel: AVM Fritz PCI/PnP driver Rev. 1.43
 +Nov 29 15:47:24 office kernel: PCI: Enabling device 0000:06:01.0 (0000 -> 0003)
 +Nov 29 15:47:24 office kernel: ACPI: PCI Interrupt 0000:06:01.0[A] -> GSI 19 (level, low) -> IRQ 177
 +Nov 29 15:47:24 office kernel: mISDN_fcpcipnp: found adapter Fritz!Card PCI v2 at 0000:06:01.0
 +Nov 29 15:47:24 office kernel: AVM PCI V2: stat 0x240020e
 +Nov 29 15:47:24 office kernel: AVM PCI V2: Class E Rev 2
 +Nov 29 15:47:24 office kernel: AVM PnP: HDLC version 2
 +Nov 29 15:47:24 office kernel: mISDN: AVM Fritz!PCIv2 config irq:177 base:0xD000
 +Nov 29 15:47:24 office kernel: AVM PCI/PnP: reset
 +Nov 29 15:47:24 office kernel: AVM PCI/PnP: S0/S1 40/2
 +Nov 29 15:47:24 office kernel: mISDN_isac_init: ISACSX
 +Nov 29 15:47:24 office kernel: AVM Fritz!PCI: IRQ 177 count 2
 +Nov 29 15:47:24 office kernel: fritz 1 cards installed
 +Nov 29 15:47:24 office kernel: mISDN_dsp: Audio DSP  Rev. 1.29 (debug=0x0) EchoCancellor MG2 dtmfthreshold(100)
 +Nov 29 15:47:24 office kernel: mISDN_dsp: DSP clocks every 64 samples. This equals 8 jiffies.</code>
 +Mit **misdnportinfo** kann nun zum einen geprüft werden, ob die Module korrekt geladen wurden, und zum anderen die momentane Portkonfiguration ausgegeben werden: 
 +   # misdnportinfo
 +<code>
 +Port  1: TE-mode BRI S/T interface line (for phone lines)
 + -> Protocol: DSS1 (Euro ISDN)
 + -> childcnt: 2
 +--------
 +
 +mISDN_close: fid(3) isize(131072) inbuf(0x968d060) irp(0x968d060) iend(0x968d060)
 +</code>
 +
 +==== automatischer Programmstart ====
 +Damit unser mISDN-Daemon automatisch bei jedem Systemstart starten kann ergänzen wir noch das startscript //**/etc/init.d/mISDN**//. Am Anfang der Datei tragen wir folgende Zeilen ein.
 +<code># Django: 29.11.2010
 +#
 +# mISDN       Start up mISDN subsystem
 +#
 +# chkconfig: 2345 10 90
 +# description: Activates/Deactivates mISDN subsystem for Asterisk telephony server
 +#
 +### BEGIN INIT INFO
 +# Provides: $mISDN
 +### END INIT INFO</code>
 +   # vim /etc/init.d/mISDN
 +Somit ergibt sich folgendes Startscript in Gänze:
 +<code>#!/bin/bash
 +
 +# Django: 29.11.2010
 +#
 +# mISDN       Start up mISDN subsystem
 +#
 +# chkconfig: 2345 10 90
 +# description: Activates/Deactivates mISDN subsystem for Asterisk telephony server
 +#
 +### BEGIN INIT INFO
 +# Provides: $mISDN
 +### END INIT INFO
 +
 +#----------------------------------------------
 +#
 +# CONFIGURATION:
 +#
 +MISDN_CONF="/etc/mISDN.conf"
 +MISDN_CONF_XSL="/usr/lib/mISDN/mISDN.conf.xsl"
 +#
 +#----------------------------------------------
 +
 +SELF="${0}"
 +USAGE="Usage: ${SELF} start|stop|restart|config|scan|help"
 +
 +function die {
 +        echo "[!!] ${1}"
 +        exit 1
 +}
 +
 +function check_cmd
 +{
 +        if ! which "${1}" > /dev/null; then
 +                if [ "${2}" = "opt" ]; then
 +                        return
 +                fi
 +                if [ "$(id -u)" != "0" ]; then
 +                        die "$1 not in path, please install and/or be root."
 +                else
 +                        die "$1 not in path, please install."
 +                fi
 +                exit 1
 +        else
 +                local var=$(echo ${1} | tr a-z A-Z)
 +                eval "$var=`which ${1}`"
 +        fi
 +}
 +
 +function check_misdn_conf
 +{
 +        if [ ! -f ${MISDN_CONF} ]; then
 +                die "${MISDN_CONF} not found. Please run: ${SELF} config"
 +        fi
 +}
 +
 +check_cmd sed
 +check_cmd cut
 +check_cmd cp
 +check_cmd wc
 +check_cmd grep
 +check_cmd xsltproc
 +check_cmd modprobe
 +check_cmd sleep
 +check_cmd lspci
 +check_cmd lsusb opt
 +check_cmd mknod
 +check_cmd chown
 +check_cmd chmod
 +
 +declare -a START_COMMANDS
 +declare -a STOP_COMMANDS
 +
 +declare -a HFCMULTI_card
 +declare -a HFCMULTI_type
 +declare -a HFCMULTI_protocol
 +declare -a HFCMULTI_layermask
 +HFCMULTI_options=''
 +MISDNDSP_options=''
 +L1OIP_options=''
 +
 +AVMFRITZ_protocol=''
 +AVMFRITZ_layermask=''
 +
 +HFCPCI_protocol=''
 +HFCPCI_layermask=''
 +
 +HFCSUSB_protocol=''
 +HFCSUSB_layermask=''
 +HFCSUSB_options=''
 +
 +XHFC_protocol=''
 +XHFC_layermask=''
 +XHFC_options=''
 +
 +L1OIP_type=''
 +L1OIP_protocol=''
 +L1OIP_layermask=''
 +L1OIP_codec=''
 +L1OIP_ip=''
 +L1OIP_port=''
 +L1OIP_localport=''
 +L1OIP_ondemand=''
 +L1OIP_id=''
 +
 +DEVNODE_user='root'
 +DEVNODE_group='root'
 +DEVNODE_mode='0644'
 +
 +declare -a SCAN_card
 +declare -a SCAN_opts
 +declare -a SCAN_num_ports
 +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 extra_modules val
 +        local IFS=$'\n'
 +
 +        START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install capi"
 +        START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install mISDN_core debug=0"
 +        START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install mISDN_l1 debug=0"
 +        START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install mISDN_l2 debug=0"
 +        START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install l3udss1 debug=0"
 +        START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install mISDN_capi"
 +
 +        for line in ${CONFIG}; do
 +                case "${line}" in
 +                        DEVNODE:mISDN*)
 +                                tmpstr=$(echo ${line} | ${SED} -n 's/.*user:\([^ ]*\).*/\1/p')
 +                                if [ ! -z "${tmpstr}" ]; then
 +                                        DEVNODE_user="${tmpstr}"
 +                                fi
 +                                tmpstr=$(echo ${line} | ${SED} -n 's/.*group:\([^ ]*\).*/\1/p')
 +                                if [ ! -z "${tmpstr}" ]; then
 +                                        DEVNODE_group="${tmpstr}"
 +                                fi
 +                                tmpstr=$(echo ${line} | ${SED} -n 's/.*mode:\([^ ]*\).*/\1/p')
 +                                if [ ! -z "${tmpstr}" ]; then
 +                                        DEVNODE_mode="${tmpstr}"
 +                                fi
 +                                ;;
 +                        MODULE:hfcmulti*)
 +                                HFCMULTI_options=${line:16}
 +                                ;;
 +                        MODULE:hfcsusb*)
 +                                HFCSUSB_options=${line:15}
 +                                ;;
 +                        MODULE:xhfc*)
 +                                XHFC_options=${line:12}
 +                                ;;
 +                        MODULE:mISDN_debugtool*)
 +                                extra_modules[${#extra_modules[@]}]=${line:7}
 +                                ;;
 +                        MODULE:mISDN_dsp*)
 +                                MISDNDSP_options=${line:17}
 +                                ;;
 +                        MODULE:l1oip*)
 +                                L1OIP_options=${line:13}
 +                                ;;
 +                        CARD:BN*)
 +                                curr='hfcmulti'
 +                                i=${#HFCMULTI_type[@]}
 +                                let "t = $(echo ${line} | ${SED} -n 's/.*type:\([^,]*\).*/\1/p')"
 +                                HFCMULTI_type[${i}]=$(printf "0x%x" ${t})
 +
 +# this is for the BN2E1 card that needs two type numbers
 +                                t=$(echo ${line} | ${SED} -n 's/.*type:[^,]*,\([^ ]*\).*/\1/p')
 +                                if [ ! -z "${t}" ]; then
 +                                        let "t = ${t}"
 +                                        HFCMULTI_type[${i}]="${HFCMULTI_type[${i}]},$(printf "0x%x" ${t})"
 +                                fi
 +
 +                                HFCMULTI_card[${i}]=$(echo ${line:5} | ${CUT} -d" " -f1)
 +                                ;;
 +                        CARD:hfcpci*)
 +                                curr='hfcpci'
 +                                ;;
 +                        CARD:hfcsusb*)
 +                                curr='hfcsusb'
 +                                ;;
 +                        CARD:xhfc*)
 +                                curr='xhfc'
 +                                ;;
 +                        CARD:avmfritz*)
 +                                curr='avmfritz'
 +                                ;;
 +                        CARD:l1oip*)
 +                                curr='l1oip'
 +                                ;;
 +                        PORT*)
 +                                case "${curr}" in
 +                                        hfcmulti)
 +                                                let "p = $(echo ${line} | ${SED} -n 's/.*protocol:\([^ ]*\).*/\1/p')"
 +                                                HFCMULTI_protocol[${i}]="${HFCMULTI_protocol[${i}]:+"${HFCMULTI_protocol[${i}]},"}$(printf "0x%x" ${p})"
 +                                                let "l = $(echo ${line} | ${SED} -n 's/.*layermask:\([^ ]*\).*/\1/p')"
 +                                                HFCMULTI_layermask[${i}]="${HFCMULTI_layermask[${i}]:+"${HFCMULTI_layermask[${i}]},"}$(printf "0x%x" ${l})"
 +                                                ;;
 +                                        hfcpci)
 +                                                let "p = $(echo ${line} | ${SED} -n 's/.*protocol:\([^ ]*\).*/\1/p')"
 +                                                HFCPCI_protocol="${HFCPCI_protocol:+"${HFCPCI_protocol},"}$(printf "0x%x" ${p})"
 +                                                let "l = $(echo ${line} | ${SED} -n 's/.*layermask:\([^ ]*\).*/\1/p')"
 +                                                HFCPCI_layermask="${HFCPCI_layermask:+"${HFCPCI_layermask},"}$(printf "0x%x" ${l})"
 +                                                ;;
 +                                        hfcsusb)
 +                                                let "p = $(echo ${line} | ${SED} -n 's/.*protocol:\([^ ]*\).*/\1/p')"
 +                                                HFCSUSB_protocol="${HFCSUSB_protocol:+"${HFCSUSB_protocol},"}$(printf "0x%x" ${p})"
 +                                                let "l = $(echo ${line} | ${SED} -n 's/.*layermask:\([^ ]*\).*/\1/p')"
 +                                                HFCSUSB_layermask="${HFCSUSB_layermask:+"${HFCSUSB_layermask},"}$(printf "0x%x" ${l})"
 +                                                ;;
 +                                        xhfc)
 +                                                let "p = $(echo ${line} | ${SED} -n 's/.*protocol:\([^ ]*\).*/\1/p')"
 +                                                XHFC_protocol="${XHFC_protocol:+"${XHFC_protocol},"}$(printf "0x%x" ${p})"
 +                                                let "l = $(echo ${line} | ${SED} -n 's/.*layermask:\([^ ]*\).*/\1/p')"
 +                                                XHFC_layermask="${XHFC_layermask:+"${XHFC_layermask},"}$(printf "0x%x" ${l})"
 +                                                ;;
 +                                        avmfritz)
 +                                                let "p = $(echo ${line} | ${SED} -n 's/.*protocol:\([^ ]*\).*/\1/p')"
 +                                                AVMFRITZ_protocol="${AVMFRITZ_protocol:+"${AVMFRITZ_protocol},"}$(printf "0x%x" ${p})"
 +                                                let "l = $(echo ${line} | ${SED} -n 's/.*layermask:\([^ ]*\).*/\1/p')"
 +                                                AVMFRITZ_layermask="${AVMFRITZ_layermask:+"${AVMFRITZ_layermask},"}$(printf "0x%x" ${l})"
 +                                                ;;
 +                                        l1oip)
 +                                                let "val = $(echo ${line} | ${SED} -n 's/.*type:\([^ ]*\).*/\1/p')"
 +                                                L1OIP_type="${L1OIP_type:+"${L1OIP_type},"}$(printf "0x%x" ${val})"
 +                                                let "val = $(echo ${line} | ${SED} -n 's/.*protocol:\([^ ]*\).*/\1/p')"
 +                                                L1OIP_protocol="${L1OIP_protocol:+"${L1OIP_protocol},"}$(printf "0x%x" ${val})"
 +                                                let "val = $(echo ${line} | ${SED} -n 's/.*layermask:\([^ ]*\).*/\1/p')"
 +                                                L1OIP_layermask="${L1OIP_layermask:+"${L1OIP_layermask},"}$(printf "0x%x" ${val})"
 +                                                val="$(echo ${line} | ${SED} -n 's/.*codec:\([^ ]*\).*/\1/p')"
 +                                                L1OIP_codec="${L1OIP_codec:+"${L1OIP_codec},"}${val}"
 +                                                val="$(echo ${line} | ${SED} -n 's/.*ip:\([^ ]*\).*/\1/p')"
 +                                                L1OIP_ip="${L1OIP_ip:+"${L1OIP_ip},"}${val}"
 +                                                val="$(echo ${line} | ${SED} -n 's/.*port:\([^ ]*\).*/\1/p')"
 +                                                L1OIP_port="${L1OIP_port:+"${L1OIP_port},"}${val}"
 +                                                val="$(echo ${line} | ${SED} -n 's/.*localport:\([^ ]*\).*/\1/p')"
 +                                                L1OIP_localport="${L1OIP_localport:+"${L1OIP_localport},"}${val}"
 +                                                val="$(echo ${line} | ${SED} -n 's/.*ondemand:\([^ ]*\).*/\1/p')"
 +                                                L1OIP_ondemand="${L1OIP_ondemand:+"${L1OIP_ondemand},"}${val}"
 +                                                val="$(echo ${line} | ${SED} -n 's/.*id:\([^ ]*\).*/\1/p')"
 +                                                L1OIP_id="${L1OIP_id:+"${L1OIP_id},"}${val}"
 +                                                ;;
 +                                esac
 +                                ;;
 +                esac
 +        done
 +
 +        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}"
 +        fi
 +
 +        if [ ! -z "${HFCSUSB_protocol}" ]; then
 +                START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install hfcsusb protocol=${HFCSUSB_protocol} layermask=${HFCSUSB_layermask} ${HFCSUSB_options}"
 +        fi
 +
 +        if [ ! -z "${XHFC_protocol}" ]; then
 +                START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install xhfc protocol=${XHFC_protocol} layermask=${XHFC_layermask} ${XHFC_options}"
 +        fi
 +
 +        if [ ! -z "${AVMFRITZ_protocol}" ]; then
 +                START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install avmfritz protocol=${AVMFRITZ_protocol} layermask=${AVMFRITZ_layermask}"
 +        fi
 +
 +        if [ ! -z "${L1OIP_type}" ]; then
 +                START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install l1oip type=${L1OIP_type} protocol=${L1OIP_protocol} layermask=${L1OIP_layermask} codec=${L1OIP_codec} ip=${L1OIP_ip} port=${L1OIP_port} localport=${L1OIP_localport} ondemand=${L1OIP_ondemand} id=${L1OIP_id} ${L1OIP_options}"
 +        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
 +{
 +        local i=0
 +
 +        echo "-- Loading mISDN modules --"
 +        while [ ! -z "${START_COMMANDS[${i}]}" ]; do
 +                echo ">> ${START_COMMANDS[${i}]}"
 +                eval "${START_COMMANDS[${i}]}"
 +                let "i = ${i} + 1"
 +        done
 +}
 +
 +function run_stop_commands
 +{
 +        local mod i=0
 +
 +        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 | hfcpci | hfcsusb | xhfc | avmfritz | l1oip)
 +                                STOP_COMMANDS[0]="${STOP_COMMANDS[0]:-"${MODPROBE} -r --ignore-remove"} ${mod}"
 +                                ;;
 +                        mISDN_debugtool)
 +                                STOP_COMMANDS[1]="${MODPROBE} -r --ignore-remove mISDN_debugtool"
 +                                ;;
 +                        mISDN_core)
 +                                STOP_COMMANDS[2]="${MODPROBE} -r --ignore-remove mISDN_core"
 +                                ;;
 +                esac
 +        done
 +
 +        echo "-- Unloading mISDN modules --"
 +        for i in `seq 0 1 2`; do
 +                if [ ! -z "${STOP_COMMANDS[${i}]}" ]; then
 +                        echo ">> ${STOP_COMMANDS[${i}]}"
 +                        eval "${STOP_COMMANDS[${i}]}"
 +                fi
 +        done
 +}
 +
 +function scan_devices
 +{
 +        local skipnext=0 IFS=$'\n'
 +        local NL="
 +"
 +
 +        function addcard {
 +                SCAN_card[${#SCAN_card[@]}]="${1}"
 +                SCAN_opts[${#SCAN_opts[@]}]="${2}"
 +                SCAN_num_ports[${#SCAN_num_ports[@]}]="${3}"
 +                SCAN_port_opts[${#SCAN_port_opts[@]}]="${4}"
 +        }
 +
 +        for line in $(${LSPCI} -n -d 0xd161:b410); do
 +                addcard "BN4S0" "" 4 'mode="te" link="ptmp"'
 +        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 "BN1E1" "" 1 'mode="nt" link="ptp"'
 +                                                ;;
 +                                        *)
 +                                                if [ $(${LSPCI} -n -s "${line:5:3}" -d 0x1397:30b1 | ${WC} -l) -eq 2 ]; then
 +                                                        addcard "BN2E1" "" 2 'mode="nt" link="ptp"'
 +                                                        skipnext=1
 +                                                else
 +                                                        addcard "BN1E1" "" 1 'mode="nt" link="ptp"'
 +                                                fi
 +                                                ;;
 +                                esac
 +                                ;;
 +                        16b8*)
 +                                addcard "BN8S0" "" 8 'mode="te" link="ptmp"'
 +                                ;;
 +                        08b4*)
 +                                if ${LSPCI} -n -v -s "${line:5}" | ${GREP} "Subsystem" | ${GREP} "1397:b567" > /dev/null ; then
 +                                        addcard "BN1S0" "" 1 'mode="te" link="ptmp"'
 +                                elif ${LSPCI} -n -v -s "${line:5}" | ${GREP} "Subsystem" | ${GREP} "1397:b566\|1397:b569" > /dev/null ; then
 +                                        addcard "BN2S0" "" 2 'mode="te" link="ptmp"'
 +                                else
 +                                        addcard "BN4S0" "" 4 'mode="te" link="ptmp"'
 +                                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 "hfcpci" "" 1 'mode="te" link="ptmp"'
 +        done
 +        for line in $(${LSPCI} -n -d 0x1397:a003); do
 +                addcard "xhfc" "" 4 'mode="te" link="ptmp"'
 +        done
 +        for line in $(${LSPCI} -n | ${GREP} "1244:\(0a00\|0e00\)"); do
 +                addcard "avmfritz" "" 1 'mode="te" link="ptmp"'
 +        done
 +        for line in $(${LSPCI} -n -d 1050:6692); do
 +                addcard "w6692pci" "" 1 'mode="te" link="ptmp"'
 +        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 "hfcsusb" "" 1 'mode="te" link="ptmp"'
 +                done
 +        fi
 +}
 +
 +function write_mISDN_conf
 +{
 +        local NL="
 +"
 +        local TAB="     "
 +        local HEADER="<?xml version=\"1.0\"?>
 +<!--
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Card Type: BN2S0, BN4S0, BN8S0
 +Card Attributes: ulaw=(yes|no), dtmf=(yes|no), pcm_slave=(yes|no),
 +                 ignore_pcm_frameclock=(yes|no), rxclock=(yes|no),
 +                 crystalclock=(yes|no), watchdog=(yes|no)
 +Port Attributes: mode=(te|nt), link=(ptp|ptmp), master-clock=(yes|no),
 +                 capi=(yes|no)
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Card Type: BN2E1
 +Card Attributes: ulaw=(yes|no), dtmf=(yes|no), pcm_slave=(yes|no),
 +                 ignore_pcm_frameclock=(yes|no), rxclock=(yes|no),
 +                 crystalclock=(yes|no), watchdog=(yes|no)
 +Port Attributes: mode=(te|nt), link=(ptp|ptmp), optical=(yes|no), los=(yes|no),
 +                 ais=(yes|no), slip=(yes|no), nocrc4=(yes|no), capi=(yes|no)
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Card Type: hfcmulti, avmfritz, w6692pci
 +Port Attributes: mode=(te|nt), link=(ptp|ptmp), capi=(yes|no)
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Module: hfcmulti
 +Options: poll=<number>, pcm=<number>, debug=<number>, timer=(yes|no)
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Module: hfcsusb
 +Options: debug=<number> poll=<number>
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Module: xhfc
 +Options: debug=<number>
 +Port Attributes: mode=(te|nt), link=(ptp|ptmp), line=(s0|up) capi=(yes|no)
 +                 lineloop_b1=(yes|no) lineloop_b2=(yes|no), lineloop_d=(yes|no)
 +                 polx=(yes|no)
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +Module: mISDN_dsp
 +Options: debug=<number>, options=<number>, poll=<number>,
 +         dtmfthreshold=<number>
 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 +-->
 +<mISDNconf>
 +${TAB}<module poll=\"128\" debug=\"0\" timer=\"no\">hfcmulti</module>
 +${TAB}<module debug=\"0\" options=\"0\">mISDN_dsp</module>
 +${TAB}<devnode user=\"root\" group=\"root\" mode=\"644\">mISDN</devnode>"
 +        local FOOTER="</mISDNconf>"
 +        local i=0 j=0 MAIN=""
 +
 +        echo "Writing ${MISDN_CONF} for ${#SCAN_card[@]} mISDN compatible device(s):"
 +        while [ ! -z "${SCAN_card[${i}]}" ]; do
 +                echo ">> ${SCAN_card[${i}]}"
 +                MAIN="${MAIN}${NL}${TAB}<card type=\"${SCAN_card[${i}]}\"${SCAN_opts[${i}]:+" ${SCAN_opts[${i}]}"}>"
 +                j=1
 +                while [ ${j} -le ${SCAN_num_ports[${i}]} ]; do
 +                        MAIN="${MAIN}${NL}${TAB}${TAB}<port${SCAN_port_opts[${i}]:+" ${SCAN_port_opts[${i}]}"}>${j}</port>"
 +                        let "j = ${j} + 1"
 +                done
 +                MAIN="${MAIN}${NL}${TAB}</card>"
 +                let "i = ${i} + 1"
 +        done
 +
 +        if [ -f ${MISDN_CONF} ]; then
 +                echo "${MISDN_CONF} already present, saving a backup: ${MISDN_CONF}.bak"
 +                ${CP} "${MISDN_CONF}" "${MISDN_CONF}.bak" || die "Could not backup your existing ${MISDN_CONF}!"
 +        fi
 +        echo "${HEADER}${MAIN}${NL}${FOOTER}" > ${MISDN_CONF}
 +}
 +
 +function print_scan_results
 +{
 +        local i=0
 +
 +        echo "${#SCAN_card[@]} mISDN compatible device(s) found:"
 +        while [ ! -z "${SCAN_card[${i}]}" ]; do
 +                echo ">> ${SCAN_card[${i}]}"
 +                let "i = ${i} + 1"
 +        done
 +}
 +
 +function mk_misdn_dev
 +{
 +        if [ ! -e /dev/mISDN ]; then
 +                echo "creating device node: /dev/mISDN"
 +                ${MKNOD} /dev/mISDN c 46 0
 +        fi
 +        ${CHOWN} ${DEVNODE_user}:${DEVNODE_group} /dev/mISDN
 +        ${CHMOD} ${DEVNODE_mode} /dev/mISDN
 +}
 +
 +#
 +# MAIN
 +#
 +
 +case "${1}" in
 +
 +        start|--start)
 +
 +                check_misdn_conf
 +                parse_config
 +                run_start_commands
 +                mk_misdn_dev
 +                ;;
 +
 +        stop|--stop)
 +
 +                run_stop_commands
 +                ;;
 +
 +        restart|--restart)
 +
 +                check_misdn_conf
 +                parse_config
 +                run_stop_commands
 +                ${SLEEP} 2
 +                run_start_commands
 +                mk_misdn_dev
 +                ;;
 +
 +        config|--config)
 +
 +                scan_devices
 +                write_mISDN_conf
 +                ;;
 +
 +        scan|--scan)
 +
 +                scan_devices
 +                print_scan_results
 +                ;;
 +
 +        help|--help)
 +                echo "${USAGE}"
 +                exit 0
 +                ;;
 +
 +        *)
 +                echo "${USAGE}"
 +                exit 2
 +                ;;
 +
 +esac
 +
 +</code>
 +Der Automatische Start kann nun durch Aufruf des folgenden Befehles erreicht werden:
 +  # chkconfig mISDN on
 +Ein Überprüfung ob der Dienst (Daemon) mISDN wirklich bei jedem Systemstart automatisch mit gestartet wird, kann durch folgenden Befehl erreicht werden:
 +  # chkconfig --list | grep mISDN
 +  mISDN            0:Aus   1:Aus   2:Aus   3:Ein   4:Ein   5:Ein   6:Aus
 +
 +Wichtig ist jeweils der Schalter **on** bei den Runleveln - **3 4 5**. 
 +