[svn-commits] nadi: branch nadi/trunk-cm r44863 - in /team/nadi/trunk-cm/channels: ./ misdn/

svn-commits at lists.digium.com svn-commits at lists.digium.com
Wed Oct 11 03:29:40 MST 2006


Author: nadi
Date: Wed Oct 11 05:29:39 2006
New Revision: 44863

URL: http://svn.digium.com/view/asterisk?rev=44863&view=rev
Log:
Huge chan_misdn commit: Bump approx. 1000 lines of code, use configman, csel and all the new stuff. experimental.

Removed:
    team/nadi/trunk-cm/channels/misdn/chan_misdn_config.h
    team/nadi/trunk-cm/channels/misdn_config.c
Modified:
    team/nadi/trunk-cm/channels/Makefile
    team/nadi/trunk-cm/channels/chan_misdn.c
    team/nadi/trunk-cm/channels/misdn/isdn_lib.c
    team/nadi/trunk-cm/channels/misdn/isdn_lib.h
    team/nadi/trunk-cm/channels/misdn/isdn_msg_parser.c

Modified: team/nadi/trunk-cm/channels/Makefile
URL: http://svn.digium.com/view/asterisk/team/nadi/trunk-cm/channels/Makefile?rev=44863&r1=44862&r2=44863&view=diff
==============================================================================
--- team/nadi/trunk-cm/channels/Makefile (original)
+++ team/nadi/trunk-cm/channels/Makefile Wed Oct 11 05:29:39 2006
@@ -111,4 +111,4 @@
 
 misdn_config.o: ASTCFLAGS+=-Imisdn 
 
-$(if $(filter chan_misdn,$(EMBEDDED_MODS)),modules.link,chan_misdn.so): chan_misdn.o misdn_config.o misdn/isdn_lib.o misdn/isdn_msg_parser.o
+$(if $(filter chan_misdn,$(EMBEDDED_MODS)),modules.link,chan_misdn.so): chan_misdn.o misdn/isdn_lib.o misdn/isdn_msg_parser.o

Modified: team/nadi/trunk-cm/channels/chan_misdn.c
URL: http://svn.digium.com/view/asterisk/team/nadi/trunk-cm/channels/chan_misdn.c?rev=44863&r1=44862&r2=44863&view=diff
==============================================================================
--- team/nadi/trunk-cm/channels/chan_misdn.c (original)
+++ team/nadi/trunk-cm/channels/chan_misdn.c Wed Oct 11 05:29:39 2006
@@ -27,10 +27,11 @@
  */
 
 /*** MODULEINFO
-	<depend>isdnnet</depend>
-	<depend>misdn</depend>
-	<depend>suppserv</depend>
+  <depend>isdnnet</depend>
+  <depend>misdn</depend>
+  <depend>suppserv</depend>
  ***/
+
 #include "asterisk.h"
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
@@ -50,6 +51,9 @@
 #include <sys/file.h>
 #include <semaphore.h>
 
+#include "asterisk/configman.h"
+#include "asterisk/csel.h"
+#include "asterisk/hash.h"
 #include "asterisk/channel.h"
 #include "asterisk/config.h"
 #include "asterisk/logger.h"
@@ -63,7 +67,6 @@
 #include "asterisk/musiconhold.h"
 #include "asterisk/dsp.h"
 #include "asterisk/translate.h"
-#include "asterisk/config.h"
 #include "asterisk/file.h"
 #include "asterisk/callerid.h"
 #include "asterisk/indications.h"
@@ -72,422 +75,1195 @@
 #include "asterisk/term.h"
 #include "asterisk/sched.h"
 #include "asterisk/stringfields.h"
-
-#include "chan_misdn_config.h"
+#include <asterisk/strings.h>
+
 #include "isdn_lib.h"
 
-char global_tracefile[BUFFERSIZE+1];
-
-
-struct misdn_jb{
+#define ORG_AST                        1
+#define ORG_MISDN                      2
+#define BUFFERSIZE                     512
+
+#define AST_CID_P(ast)                 ((ast)->cid.cid_num)
+#define AST_BRIDGED_P(ast)             ast_bridged_channel((ast))
+
+#define MISDN_ASTERISK_TECH_PVT(ast)   ((ast)->tech_pvt)
+#define MISDN_ASTERISK_PVT(ast)        1
+
+enum misdn_chan_state {
+	MISDN_NOTHING = 0,			/*!< at beginning */
+	MISDN_WAITING4DIGS, 		/*!< when waiting for infos */
+	MISDN_EXTCANTMATCH, 		/*!< when asterisk couldnt match our ext */
+	MISDN_DIALING, 				/*!< when pbx_start */
+	MISDN_PROGRESS, 			/*!< we got a progress */
+	MISDN_PROCEEDING, 			/*!< we got a progress */
+	MISDN_CALLING, 				/*!< when misdn_call is called */
+	MISDN_CALLING_ACKNOWLEDGE,	/*!< when we get SETUP_ACK */
+	MISDN_ALERTING,				/*!< when Alerting */
+	MISDN_BUSY, 				/*!< when BUSY */
+	MISDN_CONNECTED, 			/*!< when connected */
+	MISDN_PRECONNECTED, 		/*!< when connected */
+	MISDN_DISCONNECTED, 		/*!< when connected */
+	MISDN_RELEASED, 			/*!< when connected */
+	MISDN_BRIDGED, 				/*!< when bridged */
+	MISDN_CLEANING, 			/*!< when hangup from * but we were connected before */
+	MISDN_HUNGUP_FROM_MISDN, 	/*!< when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
+	MISDN_HUNGUP_FROM_AST, 		/*!< when DISCONNECT/RELEASE/REL_COMP came out of */
+	MISDN_HOLDED, 				/*!< if this chan is holded */
+	MISDN_HOLD_DISCONNECT, 		/*!< if this chan is holded */
+	MISDN_FIXUP 				/*!< if this chan is holded */
+};
+
+struct chan_list {
+	char allowed_bearers[BUFFERSIZE];
+	enum misdn_chan_state state;
+	
+	int need_queue_hangup;
+	int need_hangup;
+	int need_busy;
+	int orginator;
+	int norxtone;
+	int notxtone; 
+	int toggle_ec;
+	int incoming_early_audio;
+	int ignore_dtmf;
+	int faxdetect; /* 0:no 1:yes 2:yes+nojump */
+	int faxdetect_timeout;
+	struct timeval faxdetect_tv;
+	int faxhandled;
+	int jb_len;
+	int jb_upper_threshold;
+	struct misdn_jb *jb;
+	int overlap_dial;
+	int overlap_dial_task;
+	ast_mutex_t overlap_tv_lock;
+	struct timeval overlap_tv;
+
+	int pipe[2];
+	char ast_rd_buf[4096];
+	struct ast_frame frame;
+	int ast_dsp;
+	struct ast_dsp *dsp;
+	struct ast_trans_pvt *trans;
+	struct ast_channel *ast;
+	struct misdn_bchannel *bc;
+	struct {
+		int port;
+		int channel;
+	} hold_info;
+
+	unsigned int l3id;
+	int addr;
+	char context[BUFFERSIZE];
+	int dropped_frame_cnt;
+	int far_alerting;
+	int other_pid;
+	struct chan_list *other_ch;
+	const struct tone_zone_sound *ts;
+
+	struct chan_list *next;
+};
+
+struct allowed_bearer {
+	int cap;
+	char *name;
+	char *nicename;
+};
+
+struct misdn_csel_item {
+	int                     port;
+	int                     chan;
+};
+
+struct misdn_jb {
+	ast_mutex_t lock;
 	int size;
 	int upper_threshold;
-	char *samples, *ok;
-	int wp,rp;
+	int wp;
+	int rp;
 	int state_empty;
 	int state_full;
 	int state_buffer;
 	int bytes_wrote;
-	ast_mutex_t mutexjb;
+	char *samples;
+	char *ok;
 };
 
-
-
-/* allocates the jb-structure and initialise the elements*/
-struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
-
-/* frees the data and destroys the given jitterbuffer struct */
-void misdn_jb_destroy(struct misdn_jb *jb);
-
-/* fills the jitterbuffer with len data returns < 0 if there was an
-error (bufferoverun). */
-int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
-
-/* gets len bytes out of the jitterbuffer if available, else only the
-available data is returned and the return value indicates the number
-of data. */
-int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);
-
-
-enum misdn_chan_state {
-	MISDN_NOTHING=0,	/*!< at beginning */
-	MISDN_WAITING4DIGS, /*!<  when waiting for infos */
-	MISDN_EXTCANTMATCH, /*!<  when asterisk couldnt match our ext */
-	MISDN_DIALING, /*!<  when pbx_start */
-	MISDN_PROGRESS, /*!<  we got a progress */
-	MISDN_PROCEEDING, /*!<  we got a progress */
-	MISDN_CALLING, /*!<  when misdn_call is called */
-	MISDN_CALLING_ACKNOWLEDGE, /*!<  when we get SETUP_ACK */
-	MISDN_ALERTING, /*!<  when Alerting */
-	MISDN_BUSY, /*!<  when BUSY */
-	MISDN_CONNECTED, /*!<  when connected */
-	MISDN_PRECONNECTED, /*!<  when connected */
-	MISDN_DISCONNECTED, /*!<  when connected */
-	MISDN_RELEASED, /*!<  when connected */
-	MISDN_BRIDGED, /*!<  when bridged */
-	MISDN_CLEANING, /*!< when hangup from * but we were connected before */
-	MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
-	MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of */
-	/* misdn_hangup */
-	MISDN_HOLDED, /*!< if this chan is holded */
-	MISDN_HOLD_DISCONNECT, /*!< if this chan is holded */
-	MISDN_FIXUP/*!< if this chan is holded */
-  
+/* Global Static Variables */
+static const char             misdn_type[] = "mISDN";
+static cm_t                 * misdn_cm = NULL;
+static int                    max_ports;
+static const int              prefformat = AST_FORMAT_ALAW;
+static char                   tracefile[BUFFERSIZE];
+
+static struct chan_list     * cl_te = NULL;
+static ast_mutex_t            cl_te_lock;
+
+static char                ** misdn_key_vector = NULL;
+static int                    misdn_key_vector_size = 0;
+
+static int                  * misdn_in_calls;
+static int                  * misdn_out_calls;
+
+static struct sched_context * misdn_tasks = NULL;
+static pthread_t              misdn_tasks_thread;
+
+static int                  * misdn_debug = NULL,
+                            * misdn_debug_only = NULL,
+                            * misdn_ports = NULL;
+
+static AST_HASH_STR(, struct csel *) group_csel_hash;
+
+/* mISDN Configuration */
+static const cm_dir_t gen_dirs[] = {
+	{ },
+	{ "debug", "0",
+		"Sets the debugging flag:\n"
+			"\t0 - No Debug\n"
+			"\t1 - mISDN Messages and * - Messages, and * - State changes\n"
+			"\t2 - Messages + Message specific Informations (e.g. bearer capability)\n"
+			"\t3 - very Verbose, the above + lots of Driver specific infos\n"
+			"\t4 - even more Verbose than 3" },
+	{ "misdn_init", "/etc/misdn-init.conf",
+		"Set the path to the misdn-init.conf (for nt_ptp mode checking)." },
+	{ "tracefile", "/var/log/asterisk/misdn.log",
+		"Set the path to the massively growing trace file, if you want that." },
+	{ "bridging", "yes",
+		"Set this to yes if you want mISDN_dsp to bridge the calls in HW." },
+	{ "stop_tone_after_first_digit", "yes",
+		"Stops dialtone after getting first digit on NT Port." },
+	{ "append_digits2exten", "yes",
+		"Wether to append overlapdialed Digits to Extension or not." },
+	{ "dynamic_crypt", "no",
+		"Wether to look out for dynamic crypting attempts." },
+	{ "crypt_prefix", 0,
+		"What is used for crypting Protocol." },
+	{ "crypt_keys", 0,
+		"Keys for cryption, you reference them in the dialplan\n"
+			"\tLater also in dynamic encr." },
+	{ "ntdebugflags", "0",
+		"No description yet."},
+	{ "ntdebugfile", "/var/log/misdn-nt.log",
+		"No description yet." }
 };
 
-#define ORG_AST 1
-#define ORG_MISDN 2
-
-struct hold_info {
-	int port;
-	int channel;
+enum {
+	MCFG_SECNAME = 0,
+	MCFG_DEBUG,
+	MCFG_MISDN_INIT,
+	MCFG_TRACEFILE,
+	MCFG_BRIDGING,
+	MCFG_STOP_TONE_AFTER_FIRST_DIGIT,
+	MCFG_APPEND_DIGITS2EXTEN,
+	MCFG_DYNAMIC_CRYPT,
+	MCFG_CRYPT_PREFIX,
+	MCFG_CRYPT_KEYS,
+	MCFG_NTDEBUGFLAGS,
+	MCFG_NTDEBUGFILE,
+	MCFG_GENERAL_END
 };
 
-struct chan_list {
-  
-	char allowed_bearers[BUFFERSIZE+1];
+static const cm_dir_t port_dirs[] = {
+	{ "groupname", 0,
+		"Name of the portgroup." },
+	{ "ports", 0,
+		"Define your ports, e.g. 1, 2 (depends on mISDN-driver loading order)." },
+	{ "allowed_bearers", "all",
+		"Here you can define which bearers should be allowed." },
+	{ "rxgain", "0",
+		"Set this between -8 and 8 to change the RX Gain." },
+	{ "txgain", "0",
+		"Set this between -8 and 8 to change the TX Gain." },
+	{ "te_choose_channel", "no",
+		"Some telcos espacially in NL seem to need this set to yes,\n"
+			"\talso in switzerland this seems to be important." },
+	{ "far_alerting", "no",
+		"If we should generate ringing for chan_sip and others." },
+	{ "pmp_l1_check", "yes",
+		"This option defines, if chan_misdn should check the L1 on a PMP\n"
+			"\tbefore makeing a group call on it. The L1 may go down for PMP Ports\n"
+			"\tso we might need this.\n"
+			"\tBut be aware! a broken or plugged off cable might be used for a group call\n"
+			"\tas well, since chan_misdn has no chance to distinguish if the L1 is down\n"
+			"\tbecause of a lost Link or because the Provider shut it down..." },
+	{ "block_on_alarm", "yes",
+		"Block this port if we have an alarm on it.\n"
+			"default: yes" },
+	{ "hdlc", "no",
+		"Set this to yes, if you want to bridge a mISDN data channel to\n"
+			"\tanother channel type or to an application." },
+	{ "context", "default",
+		"Context to use for incoming calls." },
+	{ "language", "en",
+		"Language." },
+	{ "musicclass", "default",
+		"Sets the musiconhold class." },
+	{ "callerid", "",
+		"Sets the caller ID." },
+	CM_CSEL_METHOD,
+	CM_CSEL_METHOD_PARMS,
+	{ "dialplan", "0",
+		"Dialplan means Type Of Number in ISDN Terms (for outgoing calls)\n"
+			"\n"
+			"\tThere are different types of the dialplan:\n"
+			"\n"
+			"\tdialplan -> outgoing Number\n"
+			"\tlocaldialplan -> callerid\n"
+			"\tcpndialplan -> connected party number\n"
+			"\n"
+			"\tdialplan options:\n"
+			"\n"
+			"\t0 - unknown\n"
+			"\t1 - International\n"
+			"\t2 - National\n"
+			"\t4 - Subscriber\n"
+			"\n"
+			"\tThis setting is used for outgoing calls." },
+	{ "localdialplan", "0",
+		"Dialplan means Type Of Number in ISDN Terms (for outgoing calls)\n"
+			"\n"
+			"\tThere are different types of the dialplan:\n"
+			"\n"
+			"\tdialplan -> outgoing Number\n"
+			"\tlocaldialplan -> callerid\n"
+			"\tcpndialplan -> connected party number\n"
+			"\n"
+			"\tdialplan options:\n"
+			"\n"
+			"\t0 - unknown\n"
+			"\t1 - International\n"
+			"\t2 - National\n"
+			"\t4 - Subscriber\n"
+			"\n"
+			"\tThis setting is used for outgoing calls" },
+	{ "cpndialplan", "0",
+		"Dialplan means Type Of Number in ISDN Terms (for outgoing calls)\n"
+			"\n"
+			"\tThere are different types of the dialplan:\n"
+			"\n"
+			"\tdialplan -> outgoing Number\n"
+			"\tlocaldialplan -> callerid\n"
+			"\tcpndialplan -> connected party number\n"
+			"\n"
+			"\tdialplan options:\n"
+			"\n"
+			"\t0 - unknown\n"
+			"\t1 - International\n"
+			"\t2 - National\n"
+			"\t4 - Subscriber\n"
+			"\n"
+			"\tThis setting is used for outgoing calls." },
+	{ "nationalprefix", "0",
+		"Prefix for national, this is put before the\n"
+			"\toad if an according dialplan is set by the other end." },
+	{ "internationalprefix", "00",
+		"Prefix for international, this is put before the\n"
+			"\toad if an according dialplan is set by the other end." },
+	{ "presentation", "-1",
+		"These (presentation and screen) are the exact isdn screening and presentation\n"
+			"\tindicators.\n"
+			"\tIf -1 is given for both values, the presentation indicators are used from\n"
+			"\tAsterisks SetCallerPres application.\n"
+			"\n"
+			"\tscreen=0, presentation=0 -> callerid presented not screened\n"
+			"\tscreen=1, presentation=1 -> callerid presented but screened (the remote end doesn't see it!)" },
+	{ "screen", "-1",
+		"These (presentation and screen) are the exact isdn screening and presentation\n"
+			"\tindicators.\n"
+			"\tIf -1 is given for both values, the presentation indicators are used from\n"
+			"\tAsterisks SetCallerPres application.\n"
+			"\n"
+			"\tscreen=0, presentation=0 -> callerid presented not screened\n"
+			"\tscreen=1, presentation=1 -> callerid presented but screened (the remote end doesn't see it!)" },
+	{ "always_immediate", "no",
+		"Enable this to get into the s dialplan-extension.\n"
+			"\tThere you can use DigitTimeout if you can't or don't want to use\n"
+			"\tisdn overlap dial.\n"
+			"\tNOTE: This will jump into the s extension for every exten!" },
+	{ "nodialtone", "no",
+		"Enable this to prevent chan_misdn to generate the dialtone\n"
+			"\tThis makes only sense together with the always_immediate=yes option\n"
+			"\tto generate your own dialtone with Playtones or so."},
+	{ "immediate", "no",
+		"Enable this if you want callers which called exactly the base\n"
+			"\tnumber (so no extension is set) to jump into the s extension.\n"
+			"\tIf the user dials something more, it jumps to the correct extension\n"
+			"\tinstead." },
+	{ "senddtmf", "no",
+		"Enable this if we should produce DTMF Tones ourselves." },
+	{ "hold_allowed", "no",
+		"Enable this to have support for hold and retrieve." },
+	{ "early_bconnect", "yes",
+		"Disable this if you don't mind correct handling of Progress Indicators." },
+	{ "incoming_early_audio", "no",
+		"Turn this on if you like to send Tone Indications to a Incoming\n"
+			"\tisdn channel on a TE Port. Rarely used, only if the Telco allows\n"
+			"\tyou to send indications by yourself, normally the Telco sends the\n"
+			"\tindications to the remote party." },
+	{ "echocancel", "0",
+		"This enables echocancellation, with the given number of taps.\n"
+			"\tBe aware, move this setting only to outgoing portgroups!\n"
+			"\tA value of zero turns echocancellation off.\n"
+			"\n"
+			"\tPossible values are: 0, 32, 64, 128, 256, yes(=128), no(=0)" },
+	{ "echocancelwhenbridged", "no",
+		"This disables echocancellation when the call is bridged between\n"
+			"\tmISDN channels." },
+	{ "need_more_infos", "0",
+		"Send Setup_Acknowledge on incoming calls anyway (instead of PROCEEDING),\n"
+			"\tthis requests additional Infos, so we can waitfordigits without much\n"
+			"\tissues. This works only for PTP Ports" },
+	{ "jitterbuffer", "4000",
+		"The jitterbuffer." },
+	{ "jitterbuffer_upper_threshold", "0",
+		"Change this threshold to enable dejitter functionality." },
+	{ "callgroup", 0,
+		"Callgroup." },
+	{ "pickupgroup", 0,
+		"Pickupgroup." },
+	{ "max_incoming", "-1",
+		"Defines the maximum amount of incoming calls per port for this group.\n"
+			"\tCalls which exceed the maximum will be marked with the channel varible\n"
+			"\tMAX_OVERFLOW. It will contain the amount of overflowed calls" },
+	{ "max_outgoing", "-1",
+		"Defines the maximum amount of outgoing calls per port for this group\n"
+			"\texceeding calls will be rejected" },
+	{ "reject_cause", "21",
+		"Defines the cause with which a third call is rejected on PTMP BRI." },
+	{ "faxdetect", "no",
+		"Setup fax detection:\n"
+			"\t    no        - no fax detection\n"
+			"\t    incoming  - fax detection for incoming calls\n"
+			"\t    outgoing  - fax detection for outgoing calls\n"
+			"\t    both      - fax detection for incoming and outgoing calls\n"
+			"\tAdd +nojump to your value (i.e. faxdetect=both+nojump) if you don't want to jump into the\n"
+			"\tfax-extension but still want to detect the fax and prepare the channel for fax transfer." },
+	{ "faxdetect_timeout", "5",
+		"Number of seconds the fax detection should do its job. After the given period of time,\n"
+			"\twe assume that it's not a fax call and save some CPU time by turning off fax detection.\n"
+			"\tSet this to 0 if you don't want a timeout (never stop detecting)." },
+	{ "faxdetect_context", 0,
+		"Context to jump into if we detect a fax. Don't set this if you want to stay in the current context." },
+	{ "l1watcher_timeout", "0",
+		"Watches the layer 1. If the layer 1 is down, it tries to\n"
+			"\tget it up. The timeout is given in seconds. with 0 as value it\n"
+			"\tdoes not watch the l1 at all\n"
+			"\n"
+			"\tThis option is only read at loading time of chan_misdn, which\n"
+			"\tmeans you need to unload and load chan_misdn to change the value,\n"
+			"\tan Asterisk restart should do the trick." },
+	{ "overlapdial", "0",
+		"Enables overlap dial for the given amount of seconds.\n"
+			"\tPossible values are positive integers or:\n"
+			"\t   yes (= 4 seconds)\n"
+			"\t   no  (= 0 seconds = disabled)" },
+	{ "msns", 0,
+		"MSN's for TE ports, listen on those numbers on the above ports, and\n"
+			"\tindicate the incoming calls to Asterisk.\n"
+			"\tHere you can give a comma seperated list, or simply an '*' for any msn." },
+};
+
+enum {
+	MCFG_GROUPNAME = 0,
+	MCFG_PORTS,
+	MCFG_ALLOWED_BEARERS,
+	MCFG_RXGAIN,
+	MCFG_TXGAIN,
+	MCFG_TE_CHOOSE_CHANNEL,
+	MCFG_FAR_ALERTING,
+	MCFG_PMP_L1_CHECK,
+	MCFG_BLOCK_ON_ALARM,
+	MCFG_HDLC,
+	MCFG_CONTEXT,
+	MCFG_LANGUAGE,
+	MCFG_MUSICCLASS,
+	MCFG_CALLERID,
+	MCFG_METHOD,
+	MCFG_METHOD_PARMS,
+	MCFG_DIALPLAN,
+	MCFG_LOCALDIALPLAN,
+	MCFG_CPNDIALPLAN,
+	MCFG_NATIONALPREFIX,
+	MCFG_INTERNATIONALPREFIX,
+	MCFG_PRESENTATION,
+	MCFG_SCREEN,
+	MCFG_ALWAYS_IMMEDIATE,
+	MCFG_NODIALTONE,
+	MCFG_IMMEDIATE,
+	MCFG_SENDDTMF,
+	MCFG_HOLDALLOWED,
+	MCFG_EARLY_BCONNECT,
+	MCFG_INCOMING_EARLY_AUDIO,
+	MCFG_ECHOCANCEL,
+	MCFG_ECHOCANCELWHENBRIDGED,
+	MCFG_NEED_MORE_INFOS,
+	MCFG_JITTERBUFFER,
+	MCFG_JITTERBUFFER_UPPER_THRES,
+	MCFG_CALLGROUP,
+	MCFG_PICKUPGROUP,
+	MCFG_MAX_INCOMING,
+	MCFG_MAX_OUTGOING,
+	MCFG_REJECT_CAUSE,
+	MCFG_FAXDETECT,
+	MCFG_FAXDETECT_TIMEOUT,
+	MCFG_FAXDETECT_CONTEXT,
+	MCFG_L1WATCHER_TIMEOUT,
+	MCFG_OVERLAPDIAL,
+	MCFG_MSNS,
+	MCFG_PORT_END
+};
+
+static const cm_section_t config_sections[] = {
+	{ "general", NULL, NULL, KTYPE_NONE, sizeof(gen_dirs) / sizeof(cm_dir_t), gen_dirs },
+	{ "port", "default", "ports", KTYPE_INTEGER, sizeof(port_dirs) / sizeof(cm_dir_t), port_dirs },
+};
+
+enum {
+	GENERAL = 0,
+	PORT
+};
+
+static int config_load (void)
+{
+	int cfg_debug = 0,
+		i;
+
+	misdn_cm = cm_create("misdn", config_sections, sizeof(config_sections) / sizeof(cm_section_t));
+	if (!misdn_cm) {
+		ast_log(LOG_ERROR, "Unable to create misdn configman object!\n");
+		return -1;
+	}
+	if (cm_load(misdn_cm, "misdn.conf")) {
+		ast_log(LOG_ERROR, "Unable to load misdn.conf\n");
+		cm_destroy(misdn_cm);
+		misdn_cm = NULL;
+		return -1;
+	}
+
+	cm_get(misdn_cm, tracefile, BUFFERSIZE, GENERAL, MCFG_TRACEFILE);
+	cm_get_int(misdn_cm, cfg_debug, GENERAL, MCFG_DEBUG);
+	if (cfg_debug < 0)
+		cfg_debug = 0;
+
+	misdn_debug = (int *)malloc(sizeof(int) * (max_ports + 1));
+	misdn_debug_only = (int *)calloc(max_ports + 1, sizeof(int));
+	misdn_ports = (int *)malloc(sizeof(int) * (max_ports + 1));
+
+	for (i = 0;  i <= max_ports; ++i) {
+		misdn_debug[i] = cfg_debug;
+		misdn_ports[i] = i;
+	}
+
+	return 0;
+}
+
+static void config_destroy (void)
+{
+	if (misdn_cm) {
+		cm_destroy(misdn_cm);
+		misdn_cm = NULL;
+	}
+	if (misdn_debug) {
+		free(misdn_debug);
+		misdn_debug = NULL;
+	}
+	if (misdn_debug_only) {
+		free(misdn_debug_only);
+		misdn_debug_only = NULL;
+	}
+	if (misdn_ports) {
+		free(misdn_ports);
+		misdn_debug_only = NULL;
+	}
+}
+
+static int config_reload (void)
+{
+	config_destroy();
+	return config_load();
+}
+
+/* Logger Function */
+static void chan_misdn_log (int level, int port, char *tmpl, ...)
+{
+	va_list ap;
+	char buf[1024],
+		 port_buf[8];
+	time_t tm;
+	char *tmp,
+		 *p;
+	FILE *fp;
+
+	if (!((0 <= port) && (port <= max_ports))) {
+		ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
+		port = 0;
+		level = -1;
+	}
+
+	sprintf(port_buf, "P[%2d] ", port);
+
+	va_start(ap, tmpl);
+	vsnprintf(buf, sizeof(buf) - 1, tmpl, ap);
+	va_end(ap);
+
+	if (level == -1) {
+		ast_log(LOG_WARNING, buf);
+	} else if (misdn_debug_only[port] ?
+			   (level == 1 && misdn_debug[port]) || (level == misdn_debug[port]) : level <= misdn_debug[port]) {
+		ast_console_puts(port_buf);
+		ast_console_puts(buf);
+	}
+
+	if ((level <= misdn_debug[0]) && !ast_strlen_zero(tracefile)) {
+		fp = fopen(tracefile, "a+");
+		if (!fp) {
+			ast_console_puts("Error opening Tracefile: [ ");
+			ast_console_puts(tracefile);
+			ast_console_puts(" ] ");
+			ast_console_puts(strerror(errno));
+			ast_console_puts("\n");
+			return ;
+		}
+		tm = time(NULL);
+		tmp = ctime(&tm);
+		p = strchr(tmp, '\n');
+		if (p)
+			*p = ':';
+		fputs(tmp, fp);
+		fputs(" ", fp);
+		fputs(port_buf, fp);
+		fputs(" ", fp);
+		fputs(buf, fp);
+		fclose(fp);
+	}
+}
+
+/* Channel Selection */
+static void * misdn_occupy (void *priv)
+{
+	struct misdn_csel_item *item = priv;
+	struct misdn_bchannel *bc;
+	int l1check,
+		port_up;
+
+	if (cm_get_int(misdn_cm, l1check, PORT, MCFG_PMP_L1_CHECK, item->port))
+		l1check = 0;
+
+	port_up = misdn_lib_port_up(item->port, l1check);
+
+	if (l1check && !port_up)
+		chan_misdn_log(0, item->port, "misdn_occupy: L1 is down!\n");
+
+	if (l1check && port_up < 0)
+		ast_log(LOG_WARNING, "misdn_occupy: port %d is blocked!\n", item->port);
+
+	if (port_up > 0) {
+		bc = misdn_lib_get_free_bc(item->port, item->chan, 0);
+		if (bc) {
+			chan_misdn_log(0, item->port, "misdn_occupy: success! occupied port:%d channel:%d\n", item->port, item->chan);
+			return bc;
+		}
+	}
+
+	return NULL;
+}
+
+static void misdn_csel_init (void)
+{
+	int           port,
+				  num_chans,
+				  i,
+				  *prev = NULL;
+	char          buf[BUFFERSIZE],
+				  method[BUFFERSIZE],
+				  params[BUFFERSIZE];
+	struct csel   *cs = NULL;
+	struct misdn_csel_item *item;
+
+	AST_HASH_INIT_STR(&group_csel_hash, 512);
+
+	for (; cm_get_next_id(misdn_cm, PORT, prev, &port); prev = &port) {
+		if (!cm_get(misdn_cm, buf, sizeof(buf), PORT, MCFG_GROUPNAME, port)) {
+			num_chans = misdn_lib_get_maxchans(port);
+			if (!num_chans)
+				continue;
+			if (AST_HASH_LOOKUP(&group_csel_hash, buf, cs)) {
+				cm_get(misdn_cm, method, sizeof(method), PORT, MCFG_METHOD, port);
+				cm_get(misdn_cm, params, sizeof(params), PORT, MCFG_METHOD_PARMS, port);
+				cs = csel_create(method, params, misdn_occupy, free);
+				if (!cs)
+					continue;
+				AST_HASH_INSERT(&group_csel_hash, strdup(buf), cs);
+			}
+			for (i = 1; i <= num_chans; ++i) {
+				item = malloc(sizeof(struct misdn_csel_item));
+				item->port = port;
+				item->chan = i;
+				csel_add(cs, item);
+			}
+		}
+	}
+}
+
+static void misdn_csel_destroy (void)
+{
+	char         * key;
+	struct csel  * val;
+	int            i;
+
+	AST_HASH_LOCK(&group_csel_hash);
+	AST_HASH_TRAVERSE_NOLOCK(&group_csel_hash, key, val, i)
+		csel_destroy(val);
+	AST_HASH_UNLOCK(&group_csel_hash);
+	AST_HASH_DESTROY(&group_csel_hash);
+}
+
+/* Chanlist Helpers */
+static struct chan_list * init_chan_list (int orig)
+{
+	struct chan_list *cl = calloc(1, sizeof(struct chan_list));
+
+	if (!cl) {
+		chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
+		return NULL;
+	}
+
+	cl->orginator = orig;
+	cl->need_queue_hangup = 1;
+	cl->need_hangup = 1;
+	cl->need_busy = 1;
+	cl->overlap_dial_task = -1;
+
+	return cl;
+}
+
+static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
+{
+	struct chan_list *help = *list;
+
+	chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n", chan);
+
+	ast_mutex_lock(&cl_te_lock);
+	if (!*list) {
+		*list = chan;
+	} else {
+		for (; help->next; help = help->next); 
+		help->next = chan;
+	}
+	chan->next = NULL;
+	ast_mutex_unlock(&cl_te_lock);
+}
+
+static void cl_dequeue_chan (struct chan_list **list, struct chan_list *chan) 
+{
+	struct chan_list *help = *list;
+
+	if (chan->dsp) 
+		ast_dsp_free(chan->dsp);
+
+	if (chan->trans)
+		ast_translator_free_path(chan->trans);
+
+	ast_mutex_lock(&cl_te_lock);
+	if (!help) {
+		ast_mutex_unlock(&cl_te_lock);
+		return;
+	}
+
+	if (help == chan)
+		*list = help->next;
+	else
+		for (; help->next; help = help->next) {
+			if (help->next == chan) {
+				help->next = chan->next;
+				break;
+			}
+		}
 	
-	enum misdn_chan_state state;
-	int need_queue_hangup;
-	int need_hangup;
-	int need_busy;
+	ast_mutex_unlock(&cl_te_lock);
+}
+
+static struct chan_list * find_chan_by_bc (struct chan_list *list, struct misdn_bchannel *bc)
+{
+	for (; list; list = list->next)
+		if (list->bc == bc)
+			return list;
+
+	chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
+	return NULL;
+}
+
+static struct chan_list * find_chan_by_pid (struct chan_list *list, int pid)
+{
+	for (; list; list = list->next)
+		if (list->bc && list->bc->pid == pid)
+			return list;
+
+	chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid);
+	return NULL;
+}
+
+static struct chan_list * find_holded (struct chan_list *list, struct misdn_bchannel *bc)
+{
+	for (; list; list = list->next) {
+		chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",
+					   list->state == MISDN_HOLDED, list->hold_info.channel);
+		if (list->state == MISDN_HOLDED && list->hold_info.port == bc->port)
+			return list;
+	}
 	
-	int orginator;
-
-	int norxtone;
-	int notxtone; 
-
-	int toggle_ec;
-	
-	int incoming_early_audio;
-
-	int ignore_dtmf;
-
-	int pipe[2];
-	char ast_rd_buf[4096];
-	struct ast_frame frame;
-
-	int faxdetect; /* 0:no 1:yes 2:yes+nojump */
-	int faxdetect_timeout;
-	struct timeval faxdetect_tv;
-	int faxhandled;
-
-	int ast_dsp;
-
-	int jb_len;
-	int jb_upper_threshold;
+	chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
+	return NULL;
+}
+
+static struct chan_list * find_holded_l3 (struct chan_list *list, unsigned long l3_id, int w) 
+{
+	for (; list; list = list->next)
+		if (list->state == MISDN_HOLDED && list->l3id == l3_id) 
+			return list;
+
+	return NULL;
+}
+
+/* Jitterbuffer */
+static struct misdn_jb * misdn_jb_init (int size, int upper_threshold)
+{
 	struct misdn_jb *jb;
-	
-	struct ast_dsp *dsp;
-	struct ast_trans_pvt *trans;
-  
-	struct ast_channel * ast;
-
-	int dummy;
-  
-	struct misdn_bchannel *bc;
-
-	struct hold_info hold_info;
-
-	unsigned int l3id;
-	int addr;
-
-	char context[BUFFERSIZE];
-
-	int zero_read_cnt;
-	int dropped_frame_cnt;
-
-	int far_alerting;
-	int other_pid;
-	struct chan_list *other_ch;
-
-	const struct tone_zone_sound *ts;
-	
-	int overlap_dial;
-	int overlap_dial_task;
-	ast_mutex_t overlap_tv_lock;
-	struct timeval overlap_tv;
-  
-	struct chan_list *peer;
-	struct chan_list *next;
-	struct chan_list *prev;
-	struct chan_list *first;
+
+	jb = calloc(1, sizeof(struct misdn_jb));
+	jb->size = size;
+	jb->upper_threshold = upper_threshold;
+	jb->samples = malloc(size * sizeof(char));
+	jb->ok = calloc(size, sizeof(char));
+	ast_mutex_init(&jb->lock);
+
+	return jb;
+}
+
+static void misdn_jb_destroy (struct misdn_jb *jb)
+{
+	ast_mutex_destroy(&jb->lock);
+	free(jb->ok);
+	free(jb->samples);
+	free(jb);
+}
+
+static int misdn_jb_fill (struct misdn_jb *jb, const char *data, int len)
+{
+	int i,
+		j,
+		rp,
+		wp;
+
+	if (!jb || !data)
+		return 0;
+
+	ast_mutex_lock(&jb->lock);
+
+	wp = jb->wp;
+	rp = jb->rp;
+
+	for(i = 0; i < len; ++i) {
+		jb->samples[wp] = data[i];
+		jb->ok[wp] = 1;
+		wp = (wp != jb->size - 1) ? wp + 1 : 0;
+		if (wp == jb->rp)
+			jb->state_full = 1;
+	}
+
+	if (wp >= rp)
+		jb->state_buffer = wp-rp;
+	else
+		jb->state_buffer = jb->size-rp + wp;
+
+	if (jb->state_full) {
+		jb->wp = wp;
+		rp = wp;
+		for (j = 0; j < jb->upper_threshold; j++)
+			rp = rp != 0 ? rp - 1 : jb->size - 1;
+		jb->rp = rp;
+		jb->state_full = 0;
+		jb->state_empty = 1;
+		ast_mutex_unlock(&jb->lock);
+		return -1;
+	}
+
+	if (!jb->state_empty) {
+		jb->bytes_wrote += len;
+		if (jb->bytes_wrote >= jb->upper_threshold) {
+			jb->state_empty = 1;
+			jb->bytes_wrote = 0;
+		}
+	}
+	jb->wp = wp;
+
+	ast_mutex_unlock(&jb->lock);
+	return 0;
+}
+
+static int misdn_jb_empty (struct misdn_jb *jb, char *data, int len)
+{
+	int i,
+		wp,
+		rp,
+		read = 0;
+
+	ast_mutex_lock(&jb->lock);
+
+	rp = jb->rp;
+	wp = jb->wp;
+
+	if (jb->state_empty) {	
+		for (i = 0; i < len; ++i) {
+			if(wp == rp) {
+				jb->rp = rp;
+				jb->state_empty = 0;
+				ast_mutex_unlock(&jb->lock);
+				return read;
+			} else {
+				if (jb->ok[rp] == 1) {
+					data[i] = jb->samples[rp];
+					jb->ok[rp] = 0;
+					rp = (rp != jb->size - 1) ? rp + 1 : 0;
+					read += 1;
+				}
+			}
+		}
+		if (wp >= rp)
+			jb->state_buffer = wp-rp;
+		else
+			jb->state_buffer = jb->size-rp+wp;
+		jb->rp = rp;
+	}
+
+	ast_mutex_unlock(&jb->lock);
+	return read;
+}
+
+static int bc_jb_empty (struct misdn_bchannel *bc, char *buf, int len) 
+{
+	struct chan_list *ch = find_chan_by_bc(cl_te, bc);
+
+	if (ch && ch->jb)
+		return misdn_jb_empty(ch->jb, buf, len);
+
+	return -1;
+}
+
+/* mISDN Tech Function Headers */
+static struct ast_channel *   misdn_request        (const char *type, int format, void *data, int *cause);
+static int                    misdn_digit_begin    (struct ast_channel *chan, char digit);
+static int                    misdn_digit_end      (struct ast_channel *ast, char digit);
+static int                    misdn_call           (struct ast_channel *ast, char *dest, int timeout);
+static enum ast_bridge_result misdn_bridge         (struct ast_channel *c0, struct ast_channel *c1, int flags,
+													struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
+static int                    misdn_hangup         (struct ast_channel *ast);
+static int                    misdn_answer         (struct ast_channel *ast);
+static struct ast_frame *     misdn_read           (struct ast_channel *ast);
+static int                    misdn_write          (struct ast_channel *ast, struct ast_frame *frame);
+static int                    misdn_indication     (struct ast_channel *ast, int cond, const void *data, size_t datalen);
+static int                    misdn_fixup          (struct ast_channel *oldast, struct ast_channel *ast);
+static int                    misdn_send_text      (struct ast_channel *chan, const char *text);
+
+/* Other Function Headers */
+static int                    misdn_set_opt_exec   (struct ast_channel *chan, void *data);
+static int                    config_bc_echocancel (struct misdn_bchannel *bc);
+
+/* Tech Structs */
+static struct ast_channel_tech misdn_tech = {
+	.type             = "mISDN",
+	.description      = "Channel driver for mISDN Support (Bri/Pri)",
+	.capabilities     = AST_FORMAT_ALAW,
+	.requester        = misdn_request,
+	.send_digit_begin = misdn_digit_begin,
+	.send_digit_end   = misdn_digit_end,
+	.call             = misdn_call,
+	.bridge           = misdn_bridge, 
+	.hangup           = misdn_hangup,
+	.answer           = misdn_answer,
+	.read             = misdn_read,
+	.write            = misdn_write,
+	.indicate         = misdn_indication,
+	.fixup            = misdn_fixup,
+	.send_text        = misdn_send_text,
+	.properties       = 0
 };
 
-
-
-void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
-void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
-
-struct robin_list {
-	char *group;
-	int port;
-	int channel;
-	struct robin_list *next;
-	struct robin_list *prev;
+static struct ast_channel_tech misdn_tech_wo_bridge = {
+	.type             = "mISDN",
+	.description      = "Channel driver for mISDN Support (Bri/Pri)",
+	.capabilities     = AST_FORMAT_ALAW,
+	.requester        = misdn_request,
+	.send_digit_begin = misdn_digit_begin,
+	.send_digit_end   = misdn_digit_end,
+	.call             = misdn_call,
+	.hangup           = misdn_hangup,
+	.answer           = misdn_answer,
+	.read             = misdn_read,
+	.write            = misdn_write,
+	.indicate         = misdn_indication,
+	.fixup            = misdn_fixup,
+	.send_text        = misdn_send_text,
+	.properties       = 0
 };
-static struct robin_list *robin = NULL;
-
-
-
-static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
-
-
-
-static inline void free_robin_list_r (struct robin_list *r)
-{
-        if (r) {
-                if (r->next) free_robin_list_r(r->next);
-                if (r->group) free(r->group);
-                free(r);
-        }
-}
-
-static void free_robin_list ( void )
-{
-	free_robin_list_r(robin);
-	robin = NULL;
-}
-
-static struct robin_list* get_robin_position (char *group) 
-{
-	struct robin_list *iter = robin;
-	for (; iter; iter = iter->next) {
-		if (!strcasecmp(iter->group, group))
-			return iter;
-	}
-	struct robin_list *new = (struct robin_list *)calloc(1, sizeof(struct robin_list));
-	new->group = strndup(group, strlen(group));
-	new->channel = 1;
-	if (robin) {
-		new->next = robin;
-		robin->prev = new;
-	}
-	robin = new;
-	return robin;
-}
-
-
-/* the main schedule context for stuff like l1 watcher, overlap dial, ... */
-static struct sched_context *misdn_tasks = NULL;
-static pthread_t misdn_tasks_thread;
-
-static int *misdn_ports;
-
-static void chan_misdn_log(int level, int port, char *tmpl, ...);
-
-static struct ast_channel *misdn_new(struct chan_list *cl, int state,  char *exten, char *callerid, int format, int port, int c);
-static void send_digit_to_chan(struct chan_list *cl, char digit );
-
-static void hangup_chan(struct chan_list *ch);
-static int pbx_start_chan(struct chan_list *ch);
-
-
-#define AST_CID_P(ast) ast->cid.cid_num
-#define AST_BRIDGED_P(ast) ast_bridged_channel(ast) 
-#define AST_LOAD_CFG ast_config_load
-#define AST_DESTROY_CFG ast_config_destroy
-
-#define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
-#define MISDN_ASTERISK_PVT(ast) 1
-
-#include <asterisk/strings.h>
-
-/* #define MISDN_DEBUG 1 */
-
-static const char misdn_type[] = "mISDN";
-
-static int tracing = 0 ;
-
-static char **misdn_key_vector=NULL;
-static int misdn_key_vector_size=0;
-
-/* Only alaw and mulaw is allowed for now */
-static int prefformat =  AST_FORMAT_ALAW ; /*  AST_FORMAT_SLINEAR ;  AST_FORMAT_ULAW | */
-
-static int *misdn_debug;
-static int *misdn_debug_only;
-static int max_ports;
-
-static int *misdn_in_calls;
-static int *misdn_out_calls;
-
-
-struct chan_list dummy_cl;
-
-struct chan_list *cl_te=NULL;
-ast_mutex_t cl_te_lock;
-
-static enum event_response_e
-cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
-
-static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch);
-
-static void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
-static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
-static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
-static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid);
-
-
-
-static int dialtone_indicate(struct chan_list *cl);
-static int hanguptone_indicate(struct chan_list *cl);
-static int stop_indicate(struct chan_list *cl);
-
-static int start_bc_tones(struct chan_list *cl);
-static int stop_bc_tones(struct chan_list *cl);
-static void release_chan(struct misdn_bchannel *bc);
-
-static int misdn_set_opt_exec(struct ast_channel *chan, void *data);
-static int misdn_facility_exec(struct ast_channel *chan, void *data);
-
-int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
-
-
-void debug_numplan(int port, int numplan, char *type);
-
-
-int add_out_calls(int port);
-int add_in_calls(int port);
-
-
-static int update_ec_config(struct misdn_bchannel *bc);
-
-
-
-
-/*protos*/ 
-
-int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len); 
-
-/*************** Helpers *****************/
-
-static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
+
+static struct allowed_bearer allowed_bearers[] = {
+	{ INFO_CAPABILITY_SPEECH,               "speech",               "Speech" },
+	{ INFO_CAPABILITY_AUDIO_3_1K,           "3_1khz",               "Audio 3.1k" },
+	{ INFO_CAPABILITY_DIGITAL_UNRESTRICTED, "digital_unrestricted", "Unres Digital" },
+	{ INFO_CAPABILITY_DIGITAL_RESTRICTED,   "digital_restriced",    "Res Digital" },
+	{ INFO_CAPABILITY_VIDEO,                "video",                "Video" }
+};
+
+/* Simple Helpers */
+static struct chan_list * get_chan_by_ast (struct ast_channel *ast)
 {
 	struct chan_list *tmp;
-  
-	for (tmp=cl_te; tmp; tmp = tmp->next) {
-		if ( tmp->ast == ast ) return tmp;
-	}
-  
+
+	for (tmp = cl_te; tmp; tmp = tmp->next)
+		if (tmp->ast == ast)
+			return tmp;
+
 	return NULL;
 }
 
-static struct chan_list * get_chan_by_ast_name(char *name)
+static struct chan_list * get_chan_by_ast_name (char *name)
 {
 	struct chan_list *tmp;
-  
-	for (tmp=cl_te; tmp; tmp = tmp->next) {
-		if ( tmp->ast  && strcmp(tmp->ast->name,name) == 0) return tmp;
-	}
-  
+
+	for (tmp = cl_te; tmp; tmp = tmp->next)
+		if (tmp->ast && !strcmp(tmp->ast->name, name))
+			return tmp;
+
 	return NULL;
 }
 
-
-
-struct allowed_bearers {
-	int cap;
-	int val;
-	char *name;
-};
-
-struct allowed_bearers allowed_bearers_array[]={
-	{INFO_CAPABILITY_SPEECH,1,"speech"},
-	{INFO_CAPABILITY_AUDIO_3_1K,2,"3_1khz"},
-	{INFO_CAPABILITY_DIGITAL_UNRESTRICTED,4,"digital_unrestricted"},
-	{INFO_CAPABILITY_DIGITAL_RESTRICTED,8,"digital_restriced"},
-	{INFO_CAPABILITY_VIDEO,16,"video"}
-};
-
-static char *bearer2str(int cap) {
-	static char *bearers[]={
-		"Speech",
-		"Audio 3.1k",
-		"Unres Digital",
-		"Res Digital",
-		"Video",
-		"Unknown Bearer"
+static char * get_ch_state (struct chan_list *p) 
+{
+	struct ch_state {
+		enum misdn_chan_state state;
+		char txt[255] ;
 	};
-	
+	static struct ch_state ch_states[] = {
+		{ MISDN_NOTHING, "NOTHING" }, /* at beginning */
+		{ MISDN_WAITING4DIGS, "WAITING4DIGS" }, /*  when waiting for infos */

[... 7631 lines stripped ...]


More information about the svn-commits mailing list