]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
automerge commit
authorAutomerge script <automerge@asterisk.org>
Thu, 17 Aug 2006 22:04:22 +0000 (22:04 +0000)
committerAutomerge script <automerge@asterisk.org>
Thu, 17 Aug 2006 22:04:22 +0000 (22:04 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@40332 65c4cc65-6c06-0410-ace0-fbb531ad65f3

17 files changed:
channels/Makefile
channels/chan_misdn.c
channels/chan_misdn_config.c [deleted file]
channels/misdn/Makefile
channels/misdn/chan_misdn_config.h
channels/misdn/fac.c [new file with mode: 0644]
channels/misdn/fac.h [new file with mode: 0644]
channels/misdn/ie.c
channels/misdn/isdn_lib.c
channels/misdn/isdn_lib.h
channels/misdn/isdn_lib_intern.h
channels/misdn/isdn_msg_parser.c
channels/misdn/mISDN.patch [deleted file]
channels/misdn/portinfo.c [deleted file]
channels/misdn_config.c [new file with mode: 0644]
configs/misdn.conf.sample
doc/README.misdn

index 10ff8c1284a1d90e1d6aae2a265d3820e4dbe2af..3a02cf3bd508c217832943e30e66d1cf9919f81a 100644 (file)
@@ -81,9 +81,9 @@ ifneq ($(wildcard h323/libchanh323.a),)
   CHANNEL_LIBS+=chan_h323.so
 endif
 
-ifneq ($(wildcard misdn/chan_misdn_lib.a),)
+ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/mISDNuser/mISDNlib.h),)
   CHANNEL_LIBS+=chan_misdn.so
-  CFLAGS+=-Imisdn 
+  CFLAGS+=-Imisdn  
 endif
 
 CFLAGS+=-Wno-missing-prototypes -Wno-missing-declarations
@@ -239,11 +239,17 @@ chan_h323.so: chan_h323.o h323/libchanh323.a
        $(CC) $(SOLINK) -o $@ $< h323/libchanh323.a $(CHANH323LIB) -L$(PWLIBDIR)/lib $(PTLIB) -L$(OPENH323DIR)/lib $(H323LIB) -L/usr/lib -lcrypto -lssl -lexpat
 endif
 
-chan_misdn.so: chan_misdn.o chan_misdn_config.o misdn/chan_misdn_lib.a
-       $(CC) -shared -Xlinker -x -L/usr/lib -o $@ $^ -lmISDN -lisdnnet
+misdn/chan_misdn_lib.a:
+       make -C misdn
 
-chan_misdn.o: chan_misdn.c
-       $(CC) $(CFLAGS) -DCHAN_MISDN_VERSION=\"0.2.1\" -c $< -o $@
+chan_misdn.so: chan_misdn.o misdn_config.o misdn/chan_misdn_lib.a 
+       $(CC) -shared -Xlinker -x -L/usr/lib -o $@ $^ -lisdnnet -lmISDN 
+
+chan_misdn.o: chan_misdn.c 
+       $(CC) $(CFLAGS) -DCHAN_MISDN_VERSION=\"0.3.0\" -c $< -o $@
+
+misdn_config.o: misdn_config.c misdn/chan_misdn_config.h
+       $(CC) $(CFLAGS) -DCHAN_MISDN_VERSION=\"0.3.0\" -c $< -o $@
 
 #chan_modem.so : chan_modem.o
 #      $(CC) -rdynamic -shared -Xlinker -x -o $@ $<
index a170105ff159b06603100a1154ffd479741f0eaf..5b322f6bf16bdbf3d888451acf68749e21a0c36f 100644 (file)
 #include <asterisk/app.h>
 #include <asterisk/features.h>
 
-#include "chan_misdn_config.h"
-#include "isdn_lib.h"
+#include <chan_misdn_config.h>
+#include <isdn_lib.h>
+
+char global_tracefile[BUFFERSIZE+1];
+
+
+struct misdn_jb{
+       int size;
+       int upper_threshold;
+       char *samples, *ok;
+       int wp,rp;
+       int state_empty;
+       int state_full;
+       int state_buffer;
+       int bytes_wrote;
+       ast_mutex_t mutexjb;
+};
+
+
+
+/* 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);
 
-ast_mutex_t release_lock_mutex;
 
-#define release_lock ast_mutex_lock(&release_lock_mutex)
-#define release_unlock ast_mutex_unlock(&release_lock_mutex)
 
 
 /* BEGIN: chan_misdn.h */
 
+
+
 enum misdn_chan_state {
        MISDN_NOTHING,          /*!< 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 */
@@ -98,13 +133,24 @@ struct chan_list {
   
        ast_mutex_t lock;
 
+       char allowed_bearers[BUFFERSIZE+1];
+       
        enum misdn_chan_state state;
-       int holded; 
+       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 pipe[2];
        char ast_rd_buf[4096];
        struct ast_frame frame;
@@ -113,17 +159,34 @@ struct chan_list {
        int faxhandled;
 
        int ast_dsp;
+
+       int jb_len;
+       int jb_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 misdn_bchannel *holded_bc;
 
        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;
        
        struct chan_list *peer;
        struct chan_list *next;
@@ -131,6 +194,11 @@ struct chan_list {
        struct chan_list *first;
 };
 
+
+
+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;
@@ -140,13 +208,19 @@ struct robin_list {
 };
 static struct robin_list *robin = NULL;
 
+
+
+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);
-       }
+        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 )
@@ -155,7 +229,7 @@ static void free_robin_list ( void )
        robin = NULL;
 }
 
-struct robin_list* get_robin_position (char *group) 
+static struct robin_list* get_robin_position (char *group) 
 {
        struct robin_list *iter = robin;
        for (; iter; iter = iter->next) {
@@ -173,8 +247,11 @@ struct robin_list* get_robin_position (char *group)
        return robin;
 }
 
-struct ast_channel *misdn_new(struct chan_list *cl, int state, char * name, char * context, char *exten, char *callerid, int format, int port, int c);
-void send_digit_to_chan(struct chan_list *cl, char digit );
+
+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 );
 
 
 #define AST_CID_P(ast) ast->cid.cid_num
@@ -184,48 +261,50 @@ void send_digit_to_chan(struct chan_list *cl, char digit );
 
 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
 #define MISDN_ASTERISK_PVT(ast) 1
-#define MISDN_ASTERISK_TYPE(ast) ast->tech->type
-
-/* END: chan_misdn.h */
 
 #include <asterisk/strings.h>
 
 /* #define MISDN_DEBUG 1 */
 
-static  char *desc = "Channel driver for mISDN Support (Bri/Pri)";
-static  char *type = "mISDN";
+static char *desc = "Channel driver for mISDN Support (Bri/Pri)";
+static const char misdn_type[] = "mISDN";
 
-int tracing = 0 ;
+static int tracing = 0 ;
 
 static int usecnt=0;
 
-char **misdn_key_vector=NULL;
-int misdn_key_vector_size=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 ast_mutex_t usecnt_lock; 
 
-int *misdn_debug;
-int *misdn_debug_only;
-int max_ports;
+static int *misdn_debug;
+static int *misdn_debug_only;
+static int max_ports;
 
 struct chan_list dummy_cl;
 
 struct chan_list *cl_te=NULL;
 ast_mutex_t cl_te_lock;
 
-enum event_response_e
+static enum event_response_e
 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
 
-void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc);
+static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch);
 
-void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
-void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
-struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
-void chan_misdn_log(int level, int port, char *tmpl, ...);
-void chan_misdn_trace_call(struct ast_channel *chan, int debug, char *tmpl, ...);
+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);
@@ -234,6 +313,10 @@ 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);
+
+static int update_ec_config(struct misdn_bchannel *bc);
+
 /*************** Helpers *****************/
 
 static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
@@ -258,25 +341,21 @@ static struct chan_list * get_chan_by_ast_name(char *name)
        return NULL;
 }
 
-static char* tone2str(struct misdn_bchannel *bc)
-{
-       static struct {
-               char name[16];
-               enum tone_e tone;
-       } *tone, tone_buf[] = {
-               {"NOTONE",TONE_NONE},
-               {"DIAL",TONE_DIAL},
-               {"BUSY",TONE_BUSY},
-               {"ALERT",TONE_ALERTING},
-               {"",TONE_NONE}
-       };
-  
-  
-       for (tone=&tone_buf[0]; tone->name[0]; tone++) {
-               if (tone->tone == bc->tone) return tone->name;
-       }
-       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[]={
@@ -284,6 +363,7 @@ static char *bearer2str(int cap) {
                "Audio 3.1k",
                "Unres Digital",
                "Res Digital",
+               "Video",
                "Unknown Bearer"
        };
        
@@ -300,9 +380,30 @@ static char *bearer2str(int cap) {
        case INFO_CAPABILITY_DIGITAL_RESTRICTED:
                return bearers[3];
                break;
-       default:
+       case INFO_CAPABILITY_VIDEO:
                return bearers[4];
                break;
+       default:
+               return bearers[5];
+               break;
+       }
+}
+
+
+static void print_facility( struct misdn_bchannel *bc)
+{
+       switch (bc->fac_type) {
+       case FACILITY_CALLDEFLECT:
+               chan_misdn_log(2,bc->port," --> calldeflect: %s\n",
+                              bc->fac.calldeflect_nr);
+               break;
+       case FACILITY_CENTREX:
+               chan_misdn_log(2,bc->port," --> centrex: %s\n",
+                              bc->fac.cnip);
+               break;
+       default:
+               chan_misdn_log(2,bc->port," --> unknown\n");
+               
        }
 }
 
@@ -322,7 +423,7 @@ static void print_bearer(struct misdn_bchannel *bc)
 }
 /*************** Helpers END *************/
 
-void send_digit_to_chan(struct chan_list *cl, char digit )
+static void send_digit_to_chan(struct chan_list *cl, char digit )
 {
        static const char* dtmf_tones[] = {
                "!941+1336/100,!0/100", /* 0 */
@@ -416,10 +517,38 @@ static int misdn_set_debug(int fd, int argc, char *argv[])
        return 0;
 }
 
-
 static int misdn_set_crypt_debug(int fd, int argc, char *argv[])
 {
-       if (argc != 5 )return RESULT_SHOWUSAGE; 
+       if (argc != 5) return RESULT_SHOWUSAGE; 
+
+       return 0;
+}
+
+
+static int misdn_port_block(int fd, int argc, char *argv[])
+{
+       int port;
+  
+       if (argc != 4)
+               return RESULT_SHOWUSAGE;
+  
+       port = atoi(argv[3]);
+
+       misdn_lib_port_block(port);
+
+       return 0;
+}
+
+static int misdn_port_unblock(int fd, int argc, char *argv[])
+{
+       int port;
+  
+       if (argc != 4)
+               return RESULT_SHOWUSAGE;
+  
+       port = atoi(argv[3]);
+
+       misdn_lib_port_unblock(port);
 
        return 0;
 }
@@ -453,6 +582,20 @@ static int misdn_port_up (int fd, int argc, char *argv[])
        return 0;
 }
 
+static int misdn_port_down (int fd, int argc, char *argv[])
+{
+       int port;
+       
+       if (argc != 4)
+               return RESULT_SHOWUSAGE;
+       
+       port = atoi(argv[3]);
+       
+       misdn_lib_get_port_down(port);
+  
+       return 0;
+}
+
 
 static int misdn_show_config (int fd, int argc, char *argv[])
 {
@@ -470,12 +613,12 @@ static int misdn_show_config (int fd, int argc, char *argv[])
        
        if (argc == 3 || onlyport == 0) {
                ast_cli(fd,"Misdn General-Config: \n"); 
-               ast_cli(fd," ->  VERSION: " CHAN_MISDN_VERSION "\n");
-               
+               ast_cli(fd," -> Version: chan_misdn-" CHAN_MISDN_VERSION "\n");
                for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
                        misdn_cfg_get_config_string( 0, elem, buffer, BUFFERSIZE);
                        ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
                }
+               ast_cli(fd, "\n");
        }
 
        if (onlyport < 0) {
@@ -505,23 +648,26 @@ static int misdn_show_config (int fd, int argc, char *argv[])
        return 0;
 }
 
-
-
 struct state_struct {
        enum misdn_chan_state state;
        char txt[255] ;
 } ;
 
-struct state_struct state_array[] = {
+static struct state_struct state_array[] = {
        {MISDN_NOTHING,"NOTHING"}, /* at beginning */
        {MISDN_WAITING4DIGS,"WAITING4DIGS"}, /*  when waiting for infos */
        {MISDN_EXTCANTMATCH,"EXTCANTMATCH"}, /*  when asterisk couldnt match our ext */
        {MISDN_DIALING,"DIALING"}, /*  when pbx_start */
        {MISDN_PROGRESS,"PROGRESS"}, /*  when pbx_start */
+       {MISDN_PROCEEDING,"PROCEEDING"}, /*  when pbx_start */
        {MISDN_CALLING,"CALLING"}, /*  when misdn_call is called */
+       {MISDN_CALLING_ACKNOWLEDGE,"CALLING_ACKNOWLEDGE"}, /*  when misdn_call is called */
        {MISDN_ALERTING,"ALERTING"}, /*  when Alerting */
        {MISDN_BUSY,"BUSY"}, /*  when BUSY */
        {MISDN_CONNECTED,"CONNECTED"}, /*  when connected */
+       {MISDN_PRECONNECTED,"PRECONNECTED"}, /*  when connected */
+       {MISDN_DISCONNECTED,"DISCONNECTED"}, /*  when connected */
+       {MISDN_RELEASED,"RELEASED"}, /*  when connected */
        {MISDN_BRIDGED,"BRIDGED"}, /*  when bridged */
        {MISDN_CLEANING,"CLEANING"}, /* when hangup from * but we were connected before */
        {MISDN_HUNGUP_FROM_MISDN,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
@@ -531,45 +677,44 @@ struct state_struct state_array[] = {
        /* misdn_hangup */
 };
 
-
-
-
-char *misdn_get_ch_state(struct chan_list *p) 
+static char *misdn_get_ch_state(struct chan_list *p) 
 {
        int i;
+       static char state[8];
+       
        if( !p) return NULL;
   
        for (i=0; i< sizeof(state_array)/sizeof(struct state_struct); i++) {
                if ( state_array[i].state == p->state) return state_array[i].txt; 
        }
-  
-       return NULL;
+
+       sprintf(state,"%d",p->state) ;
+
+       return state;
 }
 
-static int misdn_reload (int fd, int argc, char *argv[])
+
+
+void reload_config(void)
 {
        int i, cfg_debug;
        
-       ast_cli(fd, "Reloading mISDN Config\n");
-       chan_misdn_log(0, 0, "Dynamic Crypting Activation is not support during reload at the moment\n");
-       
        free_robin_list();
-
        misdn_cfg_reload();
-
-       {
-               char tempbuf[BUFFERSIZE];
-               misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
-               if (strlen(tempbuf))
-                       tracing = 1;
-       }
-
+       misdn_cfg_update_ptp();
+       misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
        misdn_cfg_get( 0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int));
+
        for (i = 0;  i <= max_ports; i++) {
                misdn_debug[i] = cfg_debug;
                misdn_debug_only[i] = 0;
        }
-       
+}
+
+static int misdn_reload (int fd, int argc, char *argv[])
+{
+       ast_cli(fd, "Reloading mISDN Config\n");
+       reload_config();
        return 0;
 }
 
@@ -577,12 +722,14 @@ static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel
 {
        struct ast_channel *ast=help->ast;
        ast_cli(fd,
-               "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s ctx:%s state:%s\n",
+               "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
+
                bc->pid, bc->port, bc->channel,
                bc->nt?"NT":"TE",
                help->orginator == ORG_AST?"*":"I",
                ast?ast->exten:NULL,
                ast?AST_CID_P(ast):NULL,
+               bc->rad,
                ast?ast->context:NULL,
                misdn_get_ch_state(help)
                );
@@ -593,9 +740,9 @@ static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel
                        "  --> ch_addr: %x\n"
                        "  --> bc_addr: %x\n"
                        "  --> bc_l3id: %x\n"
-                       "  --> tone: %s\n"
                        "  --> display: %s\n"
                        "  --> activated: %d\n"
+                       "  --> state: %s\n"
                        "  --> capability: %s\n"
                        "  --> echo_cancel: %d\n"
                        "  --> notone : rx %d tx:%d\n"
@@ -605,19 +752,19 @@ static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel
                        help->addr,
                        bc->addr,
                        bc?bc->l3_id:-1,
-                       tone2str(bc),
                        bc->display,
                        
                        bc->active,
+                       bc_state2str(bc->bc_state),
                        bearer2str(bc->capability),
                        bc->ec_enable,
+
                        help->norxtone,help->notxtone,
                        bc->holded, help->holded_bc?1:0
                        );
   
 }
 
-
 static int misdn_show_cls (int fd, int argc, char *argv[])
 {
        struct chan_list *help=cl_te;
@@ -642,8 +789,6 @@ static int misdn_show_cls (int fd, int argc, char *argv[])
        return 0;
 }
 
-
-
 static int misdn_show_cl (int fd, int argc, char *argv[])
 {
        struct chan_list *help=cl_te;
@@ -680,13 +825,12 @@ static int misdn_set_tics (int fd, int argc, char *argv[])
        return 0;
 }
 
-
-
 static int misdn_show_stacks (int fd, int argc, char *argv[])
 {
        int port;
-       
+
        ast_cli(fd, "BEGIN STACK_LIST:\n");
+
        for (port=misdn_cfg_get_next_port(0); port > 0;
             port=misdn_cfg_get_next_port(port)) {
                char buf[128];
@@ -746,8 +890,6 @@ static int misdn_send_cd (int fd, int argc, char *argv[])
        return 0; 
 }
 
-
-
 static int misdn_send_digit (int fd, int argc, char *argv[])
 {
        char *channame; 
@@ -806,9 +948,11 @@ static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
                        ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
                        return 0; 
                } else {
-                       tmp->bc->ec_enable=tmp->bc->ec_enable?0:1;
+                       
+                       tmp->toggle_ec=tmp->toggle_ec?0:1;
 
-                       if (tmp->bc->ec_enable) {
+                       if (tmp->toggle_ec) {
+                               update_ec_config(tmp->bc);
                                manager_ec_enable(tmp->bc);
                        } else {
                                manager_ec_disable(tmp->bc);
@@ -819,8 +963,6 @@ static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
        return 0; 
 }
 
-
-
 static int misdn_send_display (int fd, int argc, char *argv[])
 {
        char *channame; 
@@ -838,9 +980,7 @@ static int misdn_send_display (int fd, int argc, char *argv[])
                tmp=get_chan_by_ast_name(channame);
     
                if (tmp && tmp->bc) {
-                       int l = sizeof(tmp->bc->display);
-                       strncpy(tmp->bc->display, msg, l);
-                       tmp->bc->display[l-1] = 0;
+                       ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
                        misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
                } else {
                        ast_cli(fd,"No such channel %s\n",channame);
@@ -851,9 +991,6 @@ static int misdn_send_display (int fd, int argc, char *argv[])
        return RESULT_SUCCESS ;
 }
 
-
-
-
 static char *complete_ch_helper(char *line, char *word, int pos, int state, int rpos)
 {
        struct ast_channel *c;
@@ -909,7 +1046,6 @@ static struct ast_cli_entry cli_send_cd =
   complete_ch
 };
 
-
 static struct ast_cli_entry cli_send_digit =
 { {"misdn","send","digit", NULL},
   misdn_send_digit,
@@ -920,7 +1056,6 @@ static struct ast_cli_entry cli_send_digit =
   complete_ch
 };
 
-
 static struct ast_cli_entry cli_toggle_echocancel =
 { {"misdn","toggle","echocancel", NULL},
   misdn_toggle_echocancel,
@@ -929,8 +1064,6 @@ static struct ast_cli_entry cli_toggle_echocancel =
   complete_ch
 };
 
-
-
 static struct ast_cli_entry cli_send_display =
 { {"misdn","send","display", NULL},
   misdn_send_display,
@@ -941,7 +1074,6 @@ static struct ast_cli_entry cli_send_display =
   complete_ch
 };
 
-
 static struct ast_cli_entry cli_show_config =
 { {"misdn","show","config", NULL},
   misdn_show_config,
@@ -949,7 +1081,6 @@ static struct ast_cli_entry cli_show_config =
   "Usage: misdn show config [port | 0]\n       use 0 to only print the general config.\n"
 };
  
-
 static struct ast_cli_entry cli_reload =
 { {"misdn","reload", NULL},
   misdn_reload,
@@ -964,7 +1095,6 @@ static struct ast_cli_entry cli_set_tics =
   "\n"
 };
 
-
 static struct ast_cli_entry cli_show_cls =
 { {"misdn","show","channels", NULL},
   misdn_show_cls,
@@ -980,6 +1110,19 @@ static struct ast_cli_entry cli_show_cl =
   complete_ch
 };
 
+static struct ast_cli_entry cli_port_block=
+{ {"misdn","port","block", NULL},
+  misdn_port_block,
+  "Blocks the given port", 
+  "Usage: misdn port block\n"
+};
+
+static struct ast_cli_entry cli_port_unblock=
+{ {"misdn","port","unblock", NULL},
+  misdn_port_unblock,
+  "Unblocks the given port", 
+  "Usage: misdn port unblock\n"
+};
 
 
 static struct ast_cli_entry cli_restart_port =
@@ -989,7 +1132,6 @@ static struct ast_cli_entry cli_restart_port =
   "Usage: misdn restart port\n"
 };
 
-
 static struct ast_cli_entry cli_port_up =
 { {"misdn","port","up", NULL},
   misdn_port_up,
@@ -997,6 +1139,14 @@ static struct ast_cli_entry cli_port_up =
   "Usage: misdn port up <port>\n"
 };
 
+static struct ast_cli_entry cli_port_down =
+{ {"misdn","port","down", NULL},
+  misdn_port_down,
+  "Tries to deacivate the L1 on the given port", 
+  "Usage: misdn port down <port>\n"
+};
+
+
 
 static struct ast_cli_entry cli_show_stacks =
 { {"misdn","show","stacks", NULL},
@@ -1012,8 +1162,6 @@ static struct ast_cli_entry cli_show_port =
   "Usage: misdn show port <port>\n"
 };
 
-
-
 static struct ast_cli_entry cli_set_debug =
 { {"misdn","set","debug", NULL},
   misdn_set_debug,
@@ -1031,243 +1179,437 @@ static struct ast_cli_entry cli_set_crypt_debug =
 /*** CLI END ***/
 
 
-/*****************************/
-/*** AST Indications Start ***/
-/*****************************/
-
-static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
+static int update_config (struct chan_list *ch, int orig) 
 {
-       int port=0;
-       int r;
-       struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
-       struct misdn_bchannel *newbc;
-       char *opts=NULL, *ext=NULL;
-       char dest_cp[256];
-       char *tokb;
-       
-       {
-               strncpy(dest_cp,dest,sizeof(dest_cp)-1);
-               dest_cp[sizeof(dest_cp)]=0;
-               
-               ext=strtok_r(dest_cp,"/",&tokb);
-               
-               if (ext) {
-                       ext=strtok_r(NULL,"/",&tokb);
-                       if (ext) {
-                               opts=strtok_r(NULL,"/",&tokb);
-                       } else {
-                               chan_misdn_log(-1,0,"misdn_call: No Extension given!\n");
-                               return -1;
-                       }
-               }
-               
-               
-       }
-
-       if (!ast) {
-               ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
-               return -1;
-       }
-
-       if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest  ) {
-               ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
-               ast->hangupcause=41;
-               ast_setstate(ast, AST_STATE_DOWN);
-               return -1;
-       }
-
-
        if (!ch) {
-               ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
-               ast->hangupcause=41;
-               ast_setstate(ast, AST_STATE_DOWN);
+               ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
                return -1;
        }
        
-       newbc=ch->bc;
-       
-       if (!newbc) {
-               ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
-               ast->hangupcause=41;
-               ast_setstate(ast, AST_STATE_DOWN);
+       struct ast_channel *ast=ch->ast;
+       struct misdn_bchannel *bc=ch->bc;
+       if (! ast || ! bc ) {
+               ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
                return -1;
        }
-
-       port=newbc->port;
-
-       ast_copy_string(newbc->dad, ext, sizeof(newbc->dad));
-       ast_copy_string(ast->exten, ext, sizeof(ast->exten));
        
-       chan_misdn_log(1, 0, "* CALL: %s\n",dest);
+       int port=bc->port;
        
-       chan_misdn_log(1, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
+       chan_misdn_log(1,port,"update_config: Getting Config\n");
+
+
+       int hdlc=0;
+       misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
        
-       {
-               char context[BUFFERSIZE];
-               
-               misdn_cfg_get( port, MISDN_CFG_CONTEXT, context, sizeof(ast->context));
-               {
-                       int l = sizeof(ast->context);
-                       strncpy(ast->context,context, l);
-                       ast->context[l-1] = 0;
+       if (hdlc) {
+               switch (bc->capability) {
+               case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
+               case INFO_CAPABILITY_DIGITAL_RESTRICTED:
+                       chan_misdn_log(1,bc->port," --> CONF HDLC\n");
+                       bc->hdlc=1;
+                       break;
                }
-               chan_misdn_log(2, port, " --> * Setting Context to %s\n",context);
-               misdn_cfg_get( port, MISDN_CFG_LANGUAGE, ast->language, BUFFERSIZE);
-               
-               misdn_cfg_get( port, MISDN_CFG_TXGAIN, &newbc->txgain, sizeof(int));
-               misdn_cfg_get( port, MISDN_CFG_RXGAIN, &newbc->rxgain, sizeof(int));
                
-               misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(newbc->te_choose_channel), sizeof(int));
+       }
+       
+       
+       int pres, screen;
+                       
+       misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
+       misdn_cfg_get( port, MISDN_CFG_SCREEN, &screen, sizeof(int));
+       chan_misdn_log(2,port," --> pres: %d screen: %d\n",pres, screen);
                
+       if ( (pres + screen) < 0 ) {
 
-               {
-                       char callerid[BUFFERSIZE];
-                       misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
-                       if ( ! ast_strlen_zero(callerid) ) {
-                               chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
-                               {
-                                       int l = sizeof(newbc->oad);
-                                       strncpy(newbc->oad,callerid, l);
-                                       newbc->oad[l-1] = 0;
-                               }
-                       }
-
+               chan_misdn_log(2,port," --> pres: %x\n", ast->cid.cid_pres);
                        
-                       misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &newbc->dnumplan, sizeof(int));
-                       switch (newbc->dnumplan) {
-                       case NUMPLAN_INTERNATIONAL:
-                               chan_misdn_log(2, port, " --> TON: International\n");
-                               break;
-                       case NUMPLAN_NATIONAL:
-                               chan_misdn_log(2, port, " --> TON: National\n");
-                               break;
-                       case NUMPLAN_SUBSCRIBER:
-                               chan_misdn_log(2, port, " --> TON: Subscriber\n");
-                               break;
-                       case NUMPLAN_UNKNOWN:
-                               chan_misdn_log(2, port, " --> TON: Unknown\n");
-                               break;
-                               /* Maybe we should cut off the prefix if present ? */
-                       default:
-                                       chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
-                                       break;
-                       }
-
-
-                       misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &newbc->onumplan, sizeof(int));
-                       switch (newbc->onumplan) {
-                       case NUMPLAN_INTERNATIONAL:
-                               chan_misdn_log(2, port, " --> TON: International\n");
-                               break;
-                       case NUMPLAN_NATIONAL:
-                               chan_misdn_log(2, port, " --> TON: National\n");
-                               break;
-                       case NUMPLAN_SUBSCRIBER:
-                               chan_misdn_log(2, port, " --> TON: Subscriber\n");
-                               break;
-                       case NUMPLAN_UNKNOWN:
-                               chan_misdn_log(2, port, " --> TON: Unknown\n");
-                               break;
-                               /* Maybe we should cut off the prefix if present ? */
-                       default:
-                                       chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
-                                       break;
-                       }
+               switch (ast->cid.cid_pres & 0x60){
+                               
+               case AST_PRES_RESTRICTED:
+                       bc->pres=1;
+                       chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
+                       break;
+                               
+                               
+               case AST_PRES_UNAVAILABLE:
+                       bc->pres=2;
+                       chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
+                       break;
+                               
+               default:
+                       bc->pres=0;
+                       chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
                }
+                       
+               switch (ast->cid.cid_pres & 0x3){
+                               
+               case AST_PRES_USER_NUMBER_UNSCREENED:
+                       bc->screen=0;
+                       chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
+                       break;
+
+               case AST_PRES_USER_NUMBER_PASSED_SCREEN:
+                       bc->screen=1;
+                       chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
+                       break;
+               case AST_PRES_USER_NUMBER_FAILED_SCREEN:
+                       bc->screen=2;
+                       chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
+                       break;
+                               
+               case AST_PRES_NETWORK_NUMBER:
+                       bc->screen=3;
+                       chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
+                       break;
+                               
+               default:
+                       bc->screen=0;
+                       chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
+               }
+
+                       
+       } else {
+               bc->screen=screen;
+               bc->pres=pres;
+       }
+
+       return 0;
+       
+}
+
 
 
 
+void config_jitterbuffer(struct chan_list *ch)
+{
+       struct misdn_bchannel *bc=ch->bc;
+       int len=ch->jb_len, threshold=ch->jb_upper_threshold;
+       
+       chan_misdn_log(5,bc->port, "config_jb: Called\n");
+       
+       if ( ! len ) {
+               chan_misdn_log(1,bc->port, "config_jb: Deactivating Jitterbuffer\n");
+               bc->nojitter=1;
+       } else {
                
-               {
-                       int eb3;
-                       
-                       misdn_cfg_get( port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
-                       newbc->early_bconnect=eb3;
-                       
+               if (len <=100 || len > 8000) {
+                       chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
+                       len=1000;
+               }
+               
+               if ( threshold > len ) {
+                       chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
+               }
+               
+               if ( ch->jb) {
+                       cb_log(0,bc->port,"config_jb: We've got a Jitterbuffer Already on this port.\n");
+                       misdn_jb_destroy(ch->jb);
+                       ch->jb=NULL;
                }
                
+               ch->jb=misdn_jb_init(len, threshold);
 
+               if (!ch->jb ) 
+                       bc->nojitter=1;
+       }
+}
+
+
+void debug_numplan(int port, int numplan, char *type)
+{
+       switch (numplan) {
+       case NUMPLAN_INTERNATIONAL:
+               chan_misdn_log(2, port, " --> %s: International\n",type);
+               break;
+       case NUMPLAN_NATIONAL:
+               chan_misdn_log(2, port, " --> %s: National\n",type);
+               break;
+       case NUMPLAN_SUBSCRIBER:
+               chan_misdn_log(2, port, " --> %s: Subscriber\n",type);
+               break;
+       case NUMPLAN_UNKNOWN:
+               chan_misdn_log(2, port, " --> %s: Unknown\n",type);
+               break;
+               /* Maybe we should cut off the prefix if present ? */
+       default:
+               chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
+               break;
+       }
+}
+
+
+
+
+static int update_ec_config(struct misdn_bchannel *bc)
+{
+       int ec;
+       int port=bc->port;
                
-               /* Will be overridden by asterisk in head! */
-               {
-                       int pres;
-                       
-                       misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
-                       newbc->pres=pres?0:1;
-                       
+       misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
+       
+       if (ec == 1 ) {
+               bc->ec_enable=1;
+       } else if ( ec > 1 ) {
+               bc->ec_enable=1;
+               bc->ec_deftaps=ec;
+       }
+
+       return 0;
+}
+
+
+static int read_config(struct chan_list *ch, int orig) {
+
+       if (!ch) {
+               ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
+               return -1;
+       }
+
+       struct ast_channel *ast=ch->ast;
+       struct misdn_bchannel *bc=ch->bc;
+       if (! ast || ! bc ) {
+               ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
+               return -1;
+       }
+       
+       int port=bc->port;
+       
+       chan_misdn_log(5,port,"read_config: Getting Config\n");
+       
+       char lang[BUFFERSIZE+1];
+
+       misdn_cfg_get( port, MISDN_CFG_LANGUAGE, lang, BUFFERSIZE);
+       ast_copy_string(ast->language, lang, sizeof(ast->language));
+       
+       char musicclass[BUFFERSIZE+1];
+       
+       misdn_cfg_get( port, MISDN_CFG_MUSICCLASS, musicclass, BUFFERSIZE);
+       ast_copy_string(ast->musicclass, musicclass, sizeof(ast->musicclass));
+       
+       misdn_cfg_get( port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(int));
+       misdn_cfg_get( port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(int));
+       
+       misdn_cfg_get( port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(int));
+       
+       misdn_cfg_get( port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(int));
+
+       misdn_cfg_get( port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(int));
+       
+       misdn_cfg_get( port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(int));
+
+       misdn_cfg_get( port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, BUFFERSIZE);
+       
+       
+       int hdlc=0;
+       misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
+       
+       if (hdlc) {
+               switch (bc->capability) {
+               case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
+               case INFO_CAPABILITY_DIGITAL_RESTRICTED:
+                       chan_misdn_log(1,bc->port," --> CONF HDLC\n");
+                       bc->hdlc=1;
+                       break;
                }
                
-               int def_callingpres;
-               misdn_cfg_get( port, MISDN_CFG_USE_CALLINGPRES, &def_callingpres, sizeof(int));
-               if ( def_callingpres) {
-                       
-                       switch (ast->cid.cid_pres & 0x60){
-                               
-                       case AST_PRES_RESTRICTED:
-                               chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
-                               newbc->pres=1;
-                               break;
-                               
-                               
-                       case AST_PRES_UNAVAILABLE:
-                               chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
-                               newbc->pres=2;
-                               break;
-                               
-                       default:
-                               chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
-                               newbc->pres=0;
+       }
+       /*Initialize new Jitterbuffer*/
+       {
+               misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(int));
+               misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(int));
+               
+               config_jitterbuffer(ch);
+       }
+       
+       misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
+       
+       ast_copy_string (ast->context,ch->context,sizeof(ast->context));        
+
+       update_ec_config(bc);
+
+       {
+               int eb3;
+               
+               misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
+               bc->early_bconnect=eb3;
+       }
+       
+       port=bc->port;
+       
+       {
+               char buf[256];
+               ast_group_t pg,cg;
+               
+               misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
+               misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
+               
+               chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
+               ast->pickupgroup=pg;
+               ast->callgroup=cg;
+       }
+       
+       if ( orig  == ORG_AST) {
+               misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(int));
+               
+               {
+                       char callerid[BUFFERSIZE+1];
+                       misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
+                       if ( ! ast_strlen_zero(callerid) ) {
+                               chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
+                               {
+                                       int l = sizeof(bc->oad);
+                                       strncpy(bc->oad,callerid, l);
+                                       bc->oad[l-1] = 0;
+                               }
+
                        }
+
                        
-                       switch (ast->cid.cid_pres & 0x3){
-                               
-                       case AST_PRES_USER_NUMBER_UNSCREENED:
-                               chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
-                               newbc->screen=0;
-                               break;
+                       misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(int));
+                       misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(int));
+                       misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
+                       debug_numplan(port, bc->dnumplan,"TON");
+                       debug_numplan(port, bc->onumplan,"LTON");
+                       debug_numplan(port, bc->cpnnumplan,"CTON");
+               }
 
-                       case AST_PRES_USER_NUMBER_PASSED_SCREEN:
-                               chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
-                               newbc->screen=1;
-                               break;
-                       case AST_PRES_USER_NUMBER_FAILED_SCREEN:
-                               chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
-                               newbc->screen=2;
-                               break;
-                               
-                       case AST_PRES_NETWORK_NUMBER:
-                               chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
-                               newbc->screen=3;
-                               break;
-                               
-                       default:
-                               chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
-                               newbc->screen=0;
-                       }
+               
+               
+       } else { /** ORIGINATOR MISDN **/
+       
+               misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
+               debug_numplan(port, bc->cpnnumplan,"CTON");
+               
+               char prefix[BUFFERSIZE+1]="";
+               switch( bc->onumplan ) {
+               case NUMPLAN_INTERNATIONAL:
+                       misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
+                       break;
+                       
+               case NUMPLAN_NATIONAL:
+                       misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
+                       break;
+               default:
+                       break;
+               }
+               
+               {
+                       int l = strlen(prefix) + strlen(bc->oad);
+                       char tmp[l+1];
+                       strcpy(tmp,prefix);
+                       strcat(tmp,bc->oad);
+                       strcpy(bc->oad,tmp);
+               }
+               
+               if (!ast_strlen_zero(bc->dad)) {
+                       ast_copy_string(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
+               }
+               
+               if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
+                       ast_copy_string(bc->dad,bc->keypad, sizeof(bc->dad));
                }
 
+               prefix[0] = 0;
+               
+               switch( bc->dnumplan ) {
+               case NUMPLAN_INTERNATIONAL:
+                       misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
+                       break;
+               case NUMPLAN_NATIONAL:
+                       misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
+                       break;
+               default:
+                       break;
+               }
                
                {
-                       int ec, ectr;
-                       
-                       misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
-                       
-                       misdn_cfg_get( port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
-                       if (ec == 1 ) {
-                               newbc->ec_enable=1;
-                       } else if ( ec > 1 ) {
-                               newbc->ec_enable=1;
-                               newbc->ec_deftaps=ec;
-                       }
+                       int l = strlen(prefix) + strlen(bc->dad);
+                       char tmp[l+1];
+                       strcpy(tmp,prefix);
+                       strcat(tmp,bc->dad);
+                       strcpy(bc->dad,tmp);
+               }
+               
+               if ( strcmp(bc->dad,ast->exten)) {
+                       ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
+               }
+               
+               ast_set_callerid(ast, bc->oad, NULL, bc->oad);
+               
+               if ( !ast_strlen_zero(bc->rad) ) 
+                       ast->cid.cid_rdnis=strdup(bc->rad);
+               
+       } /* ORIG MISDN END */
+       
+       return 0;
+}
 
 
-                       if (ectr>=0) {
-                               newbc->ec_training=ectr;
+/*****************************/
+/*** AST Indications Start ***/
+/*****************************/
+
+static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
+{
+       int port=0;
+       int r;
+       struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
+       struct misdn_bchannel *newbc;
+       char *opts=NULL, *ext,*tokb;
+       char dest_cp[256];
+       
+       {
+               strncpy(dest_cp,dest,sizeof(dest_cp)-1);
+               dest_cp[sizeof(dest_cp)]=0;
+               
+               ext=strtok_r(dest_cp,"/",&tokb);
+               
+               if (ext) {
+                       ext=strtok_r(NULL,"/",&tokb);
+                       if (ext) {
+                               opts=strtok_r(NULL,"/",&tokb);
+                       } else {
+                               chan_misdn_log(0,0,"misdn_call: No Extension given!\n");
+                               return -1;
                        }
-                       
                }
-               
-       } 
+       }
+
+       if (!ast) {
+               ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
+               return -1;
+       }
+
+       if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest  ) {
+               ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
+               ast->hangupcause=41;
+               ast_setstate(ast, AST_STATE_DOWN);
+               return -1;
+       }
+
+       if (!ch) {
+               ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
+               ast->hangupcause=41;
+               ast_setstate(ast, AST_STATE_DOWN);
+               return -1;
+       }
+       
+       newbc=ch->bc;
+       
+       if (!newbc) {
+               ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
+               ast->hangupcause=41;
+               ast_setstate(ast, AST_STATE_DOWN);
+               return -1;
+       }
+       
+       port=newbc->port;
+       strncpy(newbc->dad,ext,sizeof( newbc->dad));
+       strncpy(ast->exten,ext,sizeof(ast->exten));
+       
+       chan_misdn_log(1, port, "* CALL: %s\n",dest);
+       
+       chan_misdn_log(1, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
        
        chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten);
        if (ast->exten) {
@@ -1278,6 +1620,7 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
        newbc->rad[0]=0;
        chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",AST_CID_P(ast));
        if (ast_strlen_zero(newbc->oad) && AST_CID_P(ast) ) {
+
                if (AST_CID_P(ast)) {
                        int l = sizeof(newbc->oad);
                        strncpy(newbc->oad,AST_CID_P(ast), l);
@@ -1288,14 +1631,7 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
        {
                struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
                if (!ch) { ast_verbose("No chan_list in misdn_call"); return -1;}
-               ch->bc = newbc;
-               ch->orginator=ORG_AST;
-               ch->ast = ast;
-               
-               MISDN_ASTERISK_TECH_PVT(ast) = ch ;
-               
                
-      
                newbc->capability=ast->transfercapability;
                pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability));
                if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
@@ -1303,17 +1639,19 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
                }
                
 
+               /* update screening and presentation */ 
+               update_config(ch,ORG_AST);
+               
+               /* fill in some ies from channel vary*/
+               import_ch(ast, newbc, ch);
+               
                /* Finally The Options Override Everything */
                if (opts)
                        misdn_set_opt_exec(ast,opts);
                else
-                       chan_misdn_log(1,0,"NO OPTS GIVEN\n");
+                       chan_misdn_log(2,port,"NO OPTS GIVEN\n");
                
-               
-               cl_queue_chan(&cl_te, ch) ;
                ch->state=MISDN_CALLING;
-
-               chan_misdn_trace_call(ast,1,"*->I: EVENT_CALL\n" );
                
                r=misdn_lib_send_event( newbc, EVENT_SETUP );
                
@@ -1332,21 +1670,20 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
        chan_misdn_log(1, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
 
        ast_setstate(ast, AST_STATE_DIALING);
-       
        ast->hangupcause=16;
+       
+       if (newbc->nt) stop_bc_tones(ch);
+       
        return 0; 
 }
 
 
-int misdn_answer(struct ast_channel *ast)
+static int misdn_answer(struct ast_channel *ast)
 {
        struct chan_list *p;
 
        
-       if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
-       p = MISDN_ASTERISK_TECH_PVT(ast) ;
-       
-       chan_misdn_trace_call(ast,1,"*->I: EVENT_ANSWER\n");
+       if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
        
        chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n");
        
@@ -1362,7 +1699,7 @@ int misdn_answer(struct ast_channel *ast)
        }
 
        {
-               char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
+               const char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
                
                if (tmp_key ) {
                        chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
@@ -1378,27 +1715,35 @@ int misdn_answer(struct ast_channel *ast)
        }
 
        {
-               char *async=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
-               if (async) {
+               const char *nodsp=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
+               if (nodsp) {
                        chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
-                       p->bc->async=1;
+                       p->bc->nodsp=1;
+                       p->bc->hdlc=0;
+                       p->bc->nojitter=1;
                }
        }
        
        p->state = MISDN_CONNECTED;
+       misdn_lib_echo(p->bc,0);
+       stop_indicate(p);
+
+       if ( ast_strlen_zero(p->bc->cad) ) {
+               chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
+               ast_copy_string(p->bc->cad,p->bc->dad,sizeof(p->bc->cad));
+       }
+
        misdn_lib_send_event( p->bc, EVENT_CONNECT);
        start_bc_tones(p);
        
        return 0;
 }
 
-int misdn_digit(struct ast_channel *ast, char digit )
+static int misdn_digit(struct ast_channel *ast, char digit )
 {
        struct chan_list *p;
        
-       if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
-       p = MISDN_ASTERISK_TECH_PVT(ast) ;
-       
+       if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) return -1;
 
        struct misdn_bchannel *bc=p->bc;
        chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit);
@@ -1452,14 +1797,13 @@ int misdn_digit(struct ast_channel *ast, char digit )
 }
 
 
-int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
+static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
 {
        struct chan_list *p;
        
-       if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
-       p = MISDN_ASTERISK_TECH_PVT(ast) ;
+       if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
        
-       chan_misdn_log(1, p->bc?p->bc->port:0, "* IND: Got Fixup State:%s Holded:%d L3id:%x\n", misdn_get_ch_state(p), p->holded, p->l3id);
+       chan_misdn_log(1, p->bc?p->bc->port:0, "* IND: Got Fixup State:%s L3id:%x\n", misdn_get_ch_state(p), p->l3id);
        
        p->ast = ast ;
        p->state=MISDN_CONNECTED;
@@ -1468,29 +1812,16 @@ int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
 }
 
 
-int misdn_transfer (struct ast_channel *ast, char *dest)
-{
-       struct chan_list *p;
-       
-       if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
-       p = MISDN_ASTERISK_TECH_PVT(ast) ;
 
-       chan_misdn_log(1, p->bc?p->bc->port:0, "* IND : Got Transfer %s\n",dest);
-       return 0;
-}
-
-
-
-int misdn_indication(struct ast_channel *ast, int cond)
+static int misdn_indication(struct ast_channel *ast, int cond)
 {
        struct chan_list *p;
 
   
-       if (!ast || ! MISDN_ASTERISK_PVT(ast)) {
+       if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
                ast_log(LOG_WARNING, "Returnded -1 in misdn_indication\n");
                return -1;
        }
-       p = MISDN_ASTERISK_TECH_PVT(ast) ;
        
        if (!p->bc ) {
                chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten);
@@ -1498,56 +1829,85 @@ int misdn_indication(struct ast_channel *ast, int cond)
                return -1;
        }
        
-       chan_misdn_log(1, p->bc->port, "* IND : Indication from %s\n",ast->exten);
+       chan_misdn_log(1, p->bc->port, "* IND : Indication [%d] from %s\n",cond, ast->exten);
        
        switch (cond) {
        case AST_CONTROL_BUSY:
                chan_misdn_log(1, p->bc->port, "* IND :\tbusy\n");
                chan_misdn_log(1, p->bc->port, " --> * SEND: State Busy pid:%d\n",p->bc?p->bc->pid:-1);
                ast_setstate(ast,AST_STATE_BUSY);
-               
+
                p->bc->out_cause=17;
                if (p->state != MISDN_CONNECTED) {
+                       start_bc_tones(p);
                        misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
-                       manager_send_tone(p->bc, TONE_BUSY);
                } else {
-                       chan_misdn_log(0, p->bc->port, " --> !! Got Busy in Connected State !?! port:%d ast:%s\n",
-                                      p->bc->port, ast->name);
+                       chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name);
                }
+               return -1;
                break;
        case AST_CONTROL_RING:
                chan_misdn_log(1, p->bc->port, " --> * IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
+               return -1;
                break;
+               
        case AST_CONTROL_RINGING:
-               if ( p->state == MISDN_ALERTING) {
-                       chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but I ws Ringing before, so ignoreing it\n",p->bc?p->bc->pid:-1);
-                       break;
+               switch (p->state) {
+                       case MISDN_ALERTING:
+                               chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoreing it\n",p->bc?p->bc->pid:-1);
+                               break;
+                       case MISDN_CONNECTED:
+                               chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n",p->bc?p->bc->pid:-1);
+                               return -1;
+                               break;
+                       default:
+                               p->state=MISDN_ALERTING;
+                               chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
+                               misdn_lib_send_event( p->bc, EVENT_ALERTING);
+                       
+                               if (p->other_ch && p->other_ch->bc) {
+                                       if (misdn_inband_avail(p->other_ch->bc)) {
+                                               chan_misdn_log(1,p->bc->port, " --> other End is mISDN and has inband info available\n");
+                                               break;
+                                       }
+
+                                       if (!p->other_ch->bc->nt) {
+                                               chan_misdn_log(1,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
+                                               break;
+                                       }
+                               }
+
+                               chan_misdn_log(1, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
+                               ast_setstate(ast,AST_STATE_RINGING);
+                       
+                               if ( !p->bc->nt && (p->orginator==ORG_MISDN) && !p->incoming_early_audio ) 
+                                       chan_misdn_log(1,p->bc->port, " --> incoming_early_audio off\n");
+                               else 
+                                       return -1;
                }
-               p->state=MISDN_ALERTING;
-               
-               chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
-               
-               misdn_lib_send_event( p->bc, EVENT_ALERTING);
-               
-               manager_send_tone(p->bc, TONE_ALERTING);
-               chan_misdn_log(1, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
-               ast_setstate(ast,AST_STATE_RINGING);
                break;
-               
        case AST_CONTROL_ANSWER:
                chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1);
+               start_bc_tones(p);
                break;
        case AST_CONTROL_TAKEOFFHOOK:
                chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1);
+               return -1;
                break;
        case AST_CONTROL_OFFHOOK:
                chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1);
+               return -1;
                break; 
        case AST_CONTROL_FLASH:
                chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1);
                break;
        case AST_CONTROL_PROGRESS:
                chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1);
+               misdn_lib_send_event( p->bc, EVENT_PROGRESS);
+               break;
+       case AST_CONTROL_PROCEEDING:
+               chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n",p->bc?p->bc->pid:-1);
+               misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
                break;
        case AST_CONTROL_CONGESTION:
                chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1);
@@ -1555,18 +1915,25 @@ int misdn_indication(struct ast_channel *ast, int cond)
                p->bc->out_cause=42;
                if (p->state != MISDN_CONNECTED) {
                        start_bc_tones(p);
-                       //misdn_lib_send_event( p->bc, EVENT_RELEASE_COMPLETE);
                        misdn_lib_send_event( p->bc, EVENT_RELEASE);
                } else {
                        misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
                }
+
                if (p->bc->nt) {
-                       manager_send_tone(p->bc, TONE_BUSY);
+                       hanguptone_indicate(p);
                }
                break;
        case -1 :
-               chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! pid:%d\n",p->bc?p->bc->pid:-1);
+               chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n",p->bc?p->bc->pid:-1);
+               
+               stop_indicate(p);
+
+               if (p->state == MISDN_CONNECTED) 
+                       start_bc_tones(p);
+
                break;
+
        case AST_CONTROL_HOLD:
                chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1);
                break;
@@ -1574,35 +1941,29 @@ int misdn_indication(struct ast_channel *ast, int cond)
                chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
                break;
        default:
-               ast_log(LOG_WARNING, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
+               ast_log(LOG_NOTICE, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
        }
   
        return 0;
 }
 
-int misdn_hangup(struct ast_channel *ast)
+static int misdn_hangup(struct ast_channel *ast)
 {
        struct chan_list *p;
        struct misdn_bchannel *bc=NULL;
        
        if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
        
-       release_lock;
-
-       chan_misdn_trace_call(ast,1,"*->I: EVENT_HANGUP cause=%d\n",ast->hangupcause);
-       
        ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
        
        if (!p) {
                chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
-               release_unlock;
                return 0 ;
        }
        
        bc=p->bc;
 
        if (!bc) {
-               release_unlock;
                ast_log(LOG_WARNING,"Hangup with private but no bc ?\n");
                return 0;
        }
@@ -1611,31 +1972,32 @@ int misdn_hangup(struct ast_channel *ast)
        MISDN_ASTERISK_TECH_PVT(ast)=NULL;
        p->ast=NULL;
 
+       bc=p->bc;
+       
        if (ast->_state == AST_STATE_RESERVED) {
                /* between request and call */
                MISDN_ASTERISK_TECH_PVT(ast)=NULL;
-               release_unlock;
                
                cl_dequeue_chan(&cl_te, p);
                free(p);
-
-               misdn_lib_release(bc);
+               
+               if (bc)
+                       misdn_lib_release(bc);
                
                return 0;
        }
 
-       stop_bc_tones(p);
-       
-       release_unlock;
-       
-       
-       
-       
-       
+       p->need_hangup=0;
+       p->need_queue_hangup=0;
+
+
+       if (!p->bc->nt) 
+               stop_bc_tones(p);
+
        
        {
-               char *varcause=NULL;
-               bc->cause=ast->hangupcause?ast->hangupcause:16;
+               const char *varcause=NULL;
+               bc->out_cause=ast->hangupcause?ast->hangupcause:16;
                
                if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
                     (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
@@ -1647,6 +2009,7 @@ int misdn_hangup(struct ast_channel *ast)
                chan_misdn_log(2, bc->port, " --> l3id:%x\n",p->l3id);
                chan_misdn_log(1, bc->port, " --> cause:%d\n",bc->cause);
                chan_misdn_log(1, bc->port, " --> out_cause:%d\n",bc->out_cause);
+               chan_misdn_log(1, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
                
                switch (p->state) {
                case MISDN_CALLING:
@@ -1656,81 +2019,112 @@ int misdn_hangup(struct ast_channel *ast)
                case MISDN_HOLDED:
                case MISDN_DIALING:
                        start_bc_tones(p);
-                       manager_send_tone(bc, TONE_BUSY);
-                       p->state=MISDN_CLEANING;
-                       
-                       misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
-      
+                       hanguptone_indicate(p);
+               
+                       if (bc->need_disconnect)
+                               misdn_lib_send_event( bc, EVENT_DISCONNECT);
+                       break;
+
+               case MISDN_CALLING_ACKNOWLEDGE:
+                       start_bc_tones(p);
+                       hanguptone_indicate(p);
+               
+                       if (bc->need_disconnect)
+                               misdn_lib_send_event( bc, EVENT_DISCONNECT);
                        break;
       
                case MISDN_ALERTING:
-                       chan_misdn_log(2, bc->port, " --> * State Alerting\n");
-
+               case MISDN_PROGRESS:
+               case MISDN_PROCEEDING:
                        if (p->orginator != ORG_AST) 
-                               manager_send_tone(bc, TONE_BUSY);
+                               hanguptone_indicate(p);
       
-                       p->state=MISDN_CLEANING;
-                       misdn_lib_send_event( bc, EVENT_DISCONNECT);
+                       /*p->state=MISDN_CLEANING;*/
+                       if (bc->need_disconnect)
+                               misdn_lib_send_event( bc, EVENT_DISCONNECT);
                        break;
                case MISDN_CONNECTED:
+               case MISDN_PRECONNECTED:
                        /*  Alerting or Disconect */
-                       chan_misdn_log(2, bc->port, " --> * State Connected\n");
-                       start_bc_tones(p);
-                       manager_send_tone(bc, TONE_BUSY);
-                       misdn_lib_send_event( bc, EVENT_DISCONNECT);
-      
+                       if (p->bc->nt) {
+                               start_bc_tones(p);
+                               hanguptone_indicate(p);
+                               p->bc->progress_indicator=8;
+                       }
+                       if (bc->need_disconnect)
+                               misdn_lib_send_event( bc, EVENT_DISCONNECT);
+
+                       /*p->state=MISDN_CLEANING;*/
+                       break;
+               case MISDN_DISCONNECTED:
+                       misdn_lib_send_event( bc, EVENT_RELEASE);
                        p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
                        break;
 
+               case MISDN_RELEASED:
                case MISDN_CLEANING:
+                       p->state=MISDN_CLEANING;
+                       break;
+
+               case MISDN_BUSY:
                        break;
       
                case MISDN_HOLD_DISCONNECT:
                        /* need to send release here */
-                       chan_misdn_log(2, bc->port, " --> state HOLD_DISC\n");
                        chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
                        chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
                        
+                       bc->out_cause=-1;
                        misdn_lib_send_event(bc,EVENT_RELEASE);
+                       p->state=MISDN_CLEANING;
                        break;
                default:
-                       /*  Alerting or Disconect */
-                       if (bc->nt)
+                       if (bc->nt) {
+                               bc->out_cause=-1;
                                misdn_lib_send_event(bc, EVENT_RELEASE);
-                       else
-                               misdn_lib_send_event(bc, EVENT_DISCONNECT);
-                       p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
+                               p->state=MISDN_CLEANING; 
+                       } else {
+                               if (bc->need_disconnect)
+                                       misdn_lib_send_event(bc, EVENT_DISCONNECT);
+                       }
                }
+
+               p->state=MISDN_CLEANING;
     
        }
        
-       chan_misdn_log(1, bc->port, "Channel: %s hanguped\n",ast->name);
+
+       chan_misdn_log(1, bc->port, "Channel: %s hanguped new state:%s\n",ast->name,misdn_get_ch_state(p));
        
        return 0;
 }
 
-struct ast_frame  *misdn_read(struct ast_channel *ast)
+static struct ast_frame  *misdn_read(struct ast_channel *ast)
 {
        struct chan_list *tmp;
+       int len;
        
-       char blah[255];
-       int len =0 ;
-       
-       if (!ast) return NULL;
-       if (! (tmp=MISDN_ASTERISK_TECH_PVT(ast)) ) return NULL;
-       if (!tmp->bc) return NULL;
-       
-       
-       read(tmp->pipe[0],blah,sizeof(blah));
-       
-       
-       len = misdn_ibuf_usedcount(tmp->bc->astbuf);
+       if (!ast) {
+               chan_misdn_log(1,0,"misdn_read called without ast\n");
+               return NULL;
+       }
+       if (! (tmp=MISDN_ASTERISK_TECH_PVT(ast)) ) {
+               chan_misdn_log(1,0,"misdn_read called without ast->pvt\n");
+               return NULL;
+       }
+       if (!tmp->bc) {
+               chan_misdn_log(1,0,"misdn_read called without bc\n");
+               return NULL;
+       }
 
-       /*shrinken len if necessary, we transmit at maximum 4k*/
-       len = len<=sizeof(tmp->ast_rd_buf)?len:sizeof(tmp->ast_rd_buf);
-       
-       misdn_ibuf_memcpy_r(tmp->ast_rd_buf, tmp->bc->astbuf,len);
+       len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
        
+       if (len<=0) {
+               /* we hangup here, since our pipe is closed */
+               chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
+               return NULL;
+       }
+
        tmp->frame.frametype  = AST_FRAME_VOICE;
        tmp->frame.subclass = AST_FORMAT_ALAW;
        tmp->frame.datalen = len;
@@ -1739,41 +2133,59 @@ struct ast_frame  *misdn_read(struct ast_channel *ast)
        tmp->frame.offset= 0 ;
        tmp->frame.src = NULL;
        tmp->frame.data = tmp->ast_rd_buf ;
-
-       chan_misdn_trace_call(tmp->ast,3,"*->I: EVENT_READ len=%d\n",len);
+       
+       if (tmp->faxdetect || tmp->ast_dsp ) {
+               return process_ast_dsp(tmp, &tmp->frame);
+       }
+       
        return &tmp->frame;
 }
 
-int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
+
+static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
 {
-       struct chan_list *p;
+       struct chan_list *ch;
        int i  = 0;
        
-       if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
+       if (!ast || ! (ch=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
        
-       if (!p->bc ) {
+       if (!ch->bc ) {
                ast_log(LOG_WARNING, "private but no bc\n");
                return -1;
        }
        
-       if (p->bc->tone != TONE_NONE)
-               manager_send_tone(p->bc,TONE_NONE);
-       
-       
-       if (p->holded ) {
-               chan_misdn_log(5, p->bc->port, "misdn_write: Returning because holded\n");
+       if (ch->state == MISDN_HOLDED) {
+               chan_misdn_log(8, ch->bc->port, "misdn_write: Returning because holded\n");
                return 0;
        }
        
-       if (p->notxtone) {
-               chan_misdn_log(5, p->bc->port, "misdn_write: Returning because notxone\n");
+       if (ch->notxtone) {
+               chan_misdn_log(9, ch->bc->port, "misdn_write: Returning because notxone\n");
+               return 0;
+       }
+
+
+       if ( !frame->subclass) {
+               chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
                return 0;
        }
        
        if ( !(frame->subclass & prefformat)) {
-               chan_misdn_log(0, p->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
+               
+               chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
+               return 0;
        }
        
+
+       if ( !frame->samples ) {
+               chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
+               return 0;
+       }
+
+       if ( ! ch->bc->addr ) {
+               chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
+               return 0;
+       }
        
 #if MISDN_DEBUG
        {
@@ -1785,13 +2197,48 @@ int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
                printf ("\n");
        }
 #endif
-       chan_misdn_trace_call(ast,3,"*->I: EVENT_WRITE len=%d\n",frame->samples);
-       i= manager_tx2misdn_frm(p->bc, frame->data, frame->samples);
+
+
+       switch (ch->bc->bc_state) {
+               case BCHAN_ACTIVATED:
+               case BCHAN_BRIDGED:
+                       break;
+               default:
+               if (!ch->dropped_frame_cnt)
+                       chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d\n",frame->samples,ch->bc->addr, ast->exten, ast->cid.cid_num,misdn_get_ch_state( ch), ch->bc->bc_state);
+               
+               ch->dropped_frame_cnt++;
+               if (ch->dropped_frame_cnt > 100) {
+                       ch->dropped_frame_cnt=0;
+                       chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x  dropped > 100 frames!\n",frame->samples,ch->bc->addr);
+
+               }
+
+               return 0;
+       }
+
+       chan_misdn_log(9, ch->bc->port, "Sending :%d bytes 2 MISDN\n",frame->samples);
+       
+       if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
+               /* Buffered Transmit (triggert by read from isdn side)*/
+               if (misdn_jb_fill(ch->jb,frame->data,frame->samples) < 0) {
+                       if (ch->bc->active)
+                               cb_log(0,ch->bc->port,"Misdn Jitterbuffer Overflow.\n");
+               }
+               
+       } else {
+               /*transmit without jitterbuffer*/
+               i=misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
+       }
+
+       
        
        return 0;
 }
 
 
+
+
 enum ast_bridge_result  misdn_bridge (struct ast_channel *c0,
                                      struct ast_channel *c1, int flags,
                                      struct ast_frame **fo,
@@ -1819,47 +2266,69 @@ enum ast_bridge_result  misdn_bridge (struct ast_channel *c0,
        int bridging;
        misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
        if (bridging) {
-               int ecwb;
-               misdn_cfg_get( ch1->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
-               if ( !ecwb ) {
-                       chan_misdn_log(0, ch1->bc->port, "Disabling Echo Cancellor when Bridged\n");
+               int ec;
+               misdn_cfg_get( ch1->bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
+               if ( ec ) {
+                       chan_misdn_log(2, ch1->bc->port, "Disabling Echo Cancellor when Bridged\n");
                        ch1->bc->ec_enable=0;
                        manager_ec_disable(ch1->bc);
                }
-               misdn_cfg_get( ch2->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
-               if ( !ecwb ) {
-                       chan_misdn_log(0, ch2->bc->port, "Disabling Echo Cancellor when Bridged\n");
+               misdn_cfg_get( ch2->bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
+               if ( ec ) {
+                       chan_misdn_log(2, ch2->bc->port, "Disabling Echo Cancellor when Bridged\n");
                        ch2->bc->ec_enable=0;
-                       manager_ec_disable(ch2->bc);
+                       manager_ec_disable(ch2->bc); 
                }
                
                /* trying to make a mISDN_dsp conference */
-               chan_misdn_log(0, ch1->bc->port, "I SEND: Making conference with Number:%d\n", (ch1->bc->pid<<1) +1);
-
+               chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid +1);
+               
                misdn_lib_bridge(ch1->bc,ch2->bc);
        }
        
-       chan_misdn_log(1, ch1->bc->port, "* Makeing Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
-  
+       chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
+
+
+       if (! (flags&AST_BRIDGE_DTMF_CHANNEL_0) )
+               ch1->ignore_dtmf=1;
+       
+       if (! (flags&AST_BRIDGE_DTMF_CHANNEL_1) )
+               ch2->ignore_dtmf=1;
+       
+       
        while(1) {
                to=-1;
                who = ast_waitfor_n(carr, 2, &to);
 
                if (!who) {
-                       ast_log(LOG_DEBUG,"misdn_bridge: empty read\n");
-                       continue;
+                       ast_log(LOG_NOTICE,"misdn_bridge: empty read, breaking out\n");
+                       break;
                }
                f = ast_read(who);
     
                if (!f || f->frametype == AST_FRAME_CONTROL) {
                        /* got hangup .. */
+
+                       if (!f) 
+                               chan_misdn_log(1,ch1->bc->port,"Read Null Frame\n");
+                       else
+                               chan_misdn_log(1,ch1->bc->port,"Read Frame Controll class:%d\n",f->subclass);
+                       
                        *fo=f;
                        *rc=who;
       
                        break;
                }
-    
-    
+               
+               if ( f->frametype == AST_FRAME_DTMF ) {
+                       chan_misdn_log(1,0,"Read DTMF %d from %s\n",f->subclass, who->exten);
+
+                       *fo=f;
+                       *rc=who;
+                       break;
+               }
+               
+               
                if (who == c0) {
                        ast_write(c1,f);
                }
@@ -1868,20 +2337,67 @@ enum ast_bridge_result  misdn_bridge (struct ast_channel *c0,
                }
     
        }
-  
-       if (bridging) {
-               misdn_lib_split_bridge(ch1->bc,ch2->bc);
+       
+       chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
+       
+       misdn_lib_split_bridge(ch1->bc,ch2->bc);
+       
+       
+       return AST_BRIDGE_COMPLETE;
+}
+
+/** AST INDICATIONS END **/
+
+static int dialtone_indicate(struct chan_list *cl)
+{
+       const struct tone_zone_sound *ts= NULL;
+       struct ast_channel *ast=cl->ast;
+
+
+       int nd=0;
+       misdn_cfg_get( cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
+
+       if (nd) {
+               chan_misdn_log(1,cl->bc->port,"Not sending Dialtone, because config wants it\n");
+               return 0;
        }
-  
+       
+       chan_misdn_log(3,cl->bc->port," --> Dial\n");
+       ts=ast_get_indication_tone(ast->zone,"dial");
+       cl->ts=ts;      
+       
+       if (ts) {
+               cl->notxtone=0;
+               cl->norxtone=0;
+               ast_playtones_start(ast,0, ts->data, 0);
+               chan_misdn_log(4,cl->bc->port,"Starting Playtones\n");
+               misdn_lib_tone_generator_start(cl->bc);
+       }
+
+       return 0;
+}
+
+static int hanguptone_indicate(struct chan_list *cl)
+{
+       misdn_lib_send_tone(cl->bc,TONE_HANGUP);
+       return 0;
+}
+
+static int stop_indicate(struct chan_list *cl)
+{
+       struct ast_channel *ast=cl->ast;
+       chan_misdn_log(3,cl->bc->port," --> None\n");
+       misdn_lib_tone_generator_stop(cl->bc);
+       ast_playtones_stop(ast);
+       /*ast_deactivate_generator(ast);*/
+       
        return 0;
 }
 
-/** AST INDICATIONS END **/
 
 static int start_bc_tones(struct chan_list* cl)
 {
-       manager_bchannel_activate(cl->bc);
-       manager_send_tone(cl->bc ,TONE_NONE);
+       misdn_lib_tone_generator_stop(cl->bc);
        cl->notxtone=0;
        cl->norxtone=0;
        return 0;
@@ -1889,9 +2405,8 @@ static int start_bc_tones(struct chan_list* cl)
 
 static int stop_bc_tones(struct chan_list *cl)
 {
-       if (cl->bc) {
-               manager_bchannel_deactivate(cl->bc);
-       }
+       if (!cl) return -1;
+
        cl->notxtone=1;
        cl->norxtone=1;
        
@@ -1899,16 +2414,21 @@ static int stop_bc_tones(struct chan_list *cl)
 }
 
 
-struct chan_list *init_chan_list(void)
+static struct chan_list *init_chan_list(int orig)
 {
        struct chan_list *cl=malloc(sizeof(struct chan_list));
        
        if (!cl) {
-               chan_misdn_log(0, 0, "misdn_request: malloc failed!");
+               chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
                return NULL;
        }
        
        memset(cl,0,sizeof(struct chan_list));
+
+       cl->orginator=orig;
+       cl->need_queue_hangup=1;
+       cl->need_hangup=1;
+       cl->need_busy=1;
        
        return cl;
        
@@ -1918,30 +2438,22 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
 
 {
        struct ast_channel *tmp = NULL;
-       char group[BUFFERSIZE]="";
+       char group[BUFFERSIZE+1]="";
        char buf[128];
        char buf2[128], *ext=NULL, *port_str;
        char *tokb=NULL, *p=NULL;
        int channel=0, port=0;
        struct misdn_bchannel *newbc = NULL;
        
-       struct chan_list *cl=init_chan_list();
+       struct chan_list *cl=init_chan_list(ORG_AST);
+       
+       sprintf(buf,"%s/%s",misdn_type,(char*)data);
+       ast_copy_string(buf2,data, 128);
        
-       sprintf(buf,"%s/%s",type,(char*)data);
-       strncpy(buf2,data, 128);
-       buf2[127] = 0;
        port_str=strtok_r(buf2,"/", &tokb);
 
        ext=strtok_r(NULL,"/", &tokb);
 
-       /*
-         if (!ext) {
-         ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITH WRONG ARGS, check extension.conf\n",ext);
-         
-         return NULL;
-         }
-       */
-       
        if (port_str) {
                if (port_str[0]=='g' && port_str[1]==':' ) {
                        /* We make a group call lets checkout which ports are in my group */
@@ -1951,11 +2463,11 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
                        chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
                } 
                else if ((p = strchr(port_str, ':'))) {
-                       // we have a preselected channel
+                       /* we have a preselected channel */
                        *p = 0;
                        channel = atoi(++p);
                        port = atoi(port_str);
-                       chan_misdn_log(2, port, " --> Call on preselected Channel (%d) on Port %d\n", channel, port);
+                       chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
                }
                else {
                        port = atoi(port_str);
@@ -1969,7 +2481,7 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
 
        if (!ast_strlen_zero(group)) {
        
-               char cfg_group[BUFFERSIZE];
+               char cfg_group[BUFFERSIZE+1];
                struct robin_list *rr = NULL;
 
                if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
@@ -1993,8 +2505,9 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
                                        if (port >= port_start)
                                                next_chan = 1;
                                        
-                                       if (port < port_start && next_chan) {
-                                               if (++robin_channel >= MAX_BCHANS) {
+                                       if (port <= port_start && next_chan) {
+                                               int maxbchans=misdn_lib_get_maxchans(port);
+                                               if (++robin_channel >= maxbchans) {
                                                        robin_channel = 1;
                                                }
                                                next_chan = 0;
@@ -2003,17 +2516,25 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
                                        misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
                                        
                                        if (!strcasecmp(cfg_group, group)) {
-                                               int l1, port_up;
-                                       
-                                               misdn_cfg_get( 0, MISDN_GEN_L1_INFO_OK, &l1, sizeof(l1));
-                                               port_up = misdn_lib_port_up(port);
+                                               int port_up;
+                                               int check;
+                                               misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
+                                               port_up = misdn_lib_port_up(port, check);
+
+                                               if (check && !port_up) 
+                                                       chan_misdn_log(1,port,"L1 is not Up on this Port\n");
+                                               
+                                               if (check && port_up<0) {
+                                                       ast_log(LOG_WARNING,"This port (%d) is blocked\n", port);
+                                               }
+                                               
                                                
-                                               if ((l1 && port_up) || !l1)     {
+                                               if ( port_up>0 )        {
                                                        newbc = misdn_lib_get_free_bc(port, robin_channel);
                                                        if (newbc) {
                                                                chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
                                                                if (port_up)
-                                                                       chan_misdn_log(4, port, "def_l1:%d, portup:%d\n", l1, port_up);
+                                                                       chan_misdn_log(4, port, "portup:%d\n",  port_up);
                                                                rr->port = newbc->port;
                                                                rr->channel = newbc->channel;
                                                                break;
@@ -2024,7 +2545,7 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
                        } while (!newbc && robin_channel != rr->channel);
                        
                        if (!newbc)
-                               chan_misdn_log(4, port, " Failed! No free channel in group %d!", group);
+                               chan_misdn_log(-1, port, " Failed! No free channel in group %d!", group);
                }
                
                else {          
@@ -2032,16 +2553,17 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
                                 port=misdn_cfg_get_next_port(port)) {
                                
                                misdn_cfg_get( port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
-                               
+
+                               chan_misdn_log(3,port, "Group [%s] Port [%d]\n", group, port);
                                if (!strcasecmp(cfg_group, group)) {
-                                       int l1, port_up;
+                                       int port_up;
+                                       int check;
+                                       misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
+                                       port_up = misdn_lib_port_up(port, check);
                                        
-                                       misdn_cfg_get( 0, MISDN_GEN_L1_INFO_OK, &l1, sizeof(l1));
-                                       port_up = misdn_lib_port_up(port);
-
-                                       chan_misdn_log(4, port, "def_l1:%d, portup:%d\n", l1, port_up);
+                                       chan_misdn_log(4, port, "portup:%d\n", port_up);
                                        
-                                       if ((l1 && port_up) || !l1)     {
+                                       if ( port_up>0 ) {
                                                newbc = misdn_lib_get_free_bc(port, 0);
                                                if (newbc)
                                                        break;
@@ -2057,20 +2579,45 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
        }
        
        if (!newbc) {
-               chan_misdn_log(1, 0, " --> ! No free channel chan ext:%s even after Group Call\n",ext);
-               chan_misdn_log(1, 0, " --> SEND: State Down\n");
+               chan_misdn_log(-1, 0, "Could not create channel on port:%d with extensions:%s\n",port,ext);
                return NULL;
        }
-       
+
+       /* create ast_channel and link all the objects together */
        cl->bc=newbc;
        
-       tmp = misdn_new(cl, AST_STATE_RESERVED, buf, "default", ext, ext, format, port, channel);
+       tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
+       cl->ast=tmp;
+       
+       /* register chan in local list */
+       cl_queue_chan(&cl_te, cl) ;
+       
+       /* fill in the config into the objects */
+       read_config(cl, ORG_AST);
+
+       /* important */
+       cl->need_hangup=0;
        
        return tmp;
 }
 
 
-struct ast_channel_tech misdn_tech = {
+int misdn_send_text (struct ast_channel *chan, const char *text)
+{
+       struct chan_list *tmp=chan->tech_pvt;
+       
+       if (tmp && tmp->bc) {
+               ast_copy_string(tmp->bc->display,text,sizeof(tmp->bc->display));
+               misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
+       } else {
+               ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
+               return -1;
+       }
+       
+       return 0;
+}
+
+static struct ast_channel_tech misdn_tech = {
        .type="mISDN",
        .description="Channel driver for mISDN Support (Bri/Pri)",
        .capabilities= AST_FORMAT_ALAW ,
@@ -2084,11 +2631,11 @@ struct ast_channel_tech misdn_tech = {
        .write=misdn_write,
        .indicate=misdn_indication,
        .fixup=misdn_fixup,
+       .send_text=misdn_send_text,
        .properties=0
-       /* .transfer=misdn_transfer */
 };
 
-struct ast_channel_tech misdn_tech_wo_bridge = {
+static struct ast_channel_tech misdn_tech_wo_bridge = {
        .type="mISDN",
        .description="Channel driver for mISDN Support (Bri/Pri)",
        .capabilities=AST_FORMAT_ALAW ,
@@ -2101,69 +2648,64 @@ struct ast_channel_tech misdn_tech_wo_bridge = {
        .write=misdn_write,
        .indicate=misdn_indication,
        .fixup=misdn_fixup,
+       .send_text=misdn_send_text,
        .properties=0
-       /* .transfer=misdn_transfer */
 };
 
 
-unsigned long glob_channel=0;
+static unsigned long glob_channel=0;
 
-struct ast_channel *misdn_new(struct chan_list *chlist, int state, char * name, char * context, char *exten, char *callerid, int format, int port, int c)
+static struct ast_channel *misdn_new(struct chan_list *chlist, int state,  char *exten, char *callerid, int format, int port, int c)
 {
        struct ast_channel *tmp;
        
        tmp = ast_channel_alloc(1);
        
        if (tmp) {
-               chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s ctx:%s\n",exten,callerid, context);
+               chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten,callerid);
                
                
                if (c<=0) {
                        c=glob_channel++;
                        snprintf(tmp->name, sizeof(tmp->name), "%s/%d-u%d",
-                                type, port, c);
+                                misdn_type, port, c);
                } else {
                        snprintf(tmp->name, sizeof(tmp->name), "%s/%d-%d",
-                                type, port, c);
+                                misdn_type, port, c);
                }
                
-               tmp->type = type;
-    
+               tmp->type = misdn_type;
+               
                tmp->nativeformats = prefformat;
+
                tmp->readformat = format;
+               tmp->rawreadformat = format;
                tmp->writeformat = format;
+               tmp->rawwriteformat = format;
     
                tmp->tech_pvt = chlist;
-
+               
                int bridging;
                misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
                if (bridging)
                        tmp->tech = &misdn_tech;
                else
                        tmp->tech = &misdn_tech_wo_bridge;
-    
-    
+               
                tmp->writeformat = format;
                tmp->readformat = format;
                tmp->priority=1;
-    
-               
-               if (context) {
-                       ast_copy_string(tmp->context, context, sizeof(tmp->context));
-               }  else {
-                       chan_misdn_log(1,0,"misdn_new: no context given.\n");
-               }
                
-               if (exten) {
+               if (exten) 
                        ast_copy_string(tmp->exten, exten,  sizeof(tmp->exten));
-               } else {
+               else
                        chan_misdn_log(1,0,"misdn_new: no exten given.\n");
-               }
                
                if (callerid) {
                        char *cid_name, *cid_num;
       
                        ast_callerid_parse(callerid, &cid_name, &cid_num);
+
                        if (!ast_strlen_zero(cid_num)) {
                                tmp->cid.cid_num = strdup(cid_num);
                                tmp->cid.cid_ani = strdup(cid_num);
@@ -2180,193 +2722,107 @@ struct ast_channel *misdn_new(struct chan_list *chlist, int state, char * name,
                        
                }
                
-               if (chlist->bc) {
-                       int port=chlist->bc->port;
-                       misdn_cfg_get( port, MISDN_CFG_LANGUAGE, tmp->language, sizeof(tmp->language));
-                       
-                       {
-                               char buf[256];
-                               ast_group_t pg,cg;
-                               
-                               misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
-                               misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
-                               
-                               chan_misdn_log(2, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
-                               tmp->pickupgroup=pg;
-                               tmp->callgroup=cg;
-                       }
-                       misdn_cfg_get(port, MISDN_CFG_TXGAIN, &chlist->bc->txgain, sizeof(int));
-                       misdn_cfg_get(port, MISDN_CFG_RXGAIN, &chlist->bc->rxgain, sizeof(int));
-                       chan_misdn_log(2, port, " --> rxgain:%d txgain:%d\n",chlist->bc->rxgain,chlist->bc->txgain);
-                       
-               } else {
-                       chan_misdn_log(3, 0, " --> Not Setting Pickupgroup, we have no bc yet\n");
-               }
-               
                ast_setstate(tmp, state);
                if (state == AST_STATE_RING)
                        tmp->rings = 1;
                else
                        tmp->rings = 0;
+               
+               
        } else {
-               ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
-               chan_misdn_log(0,0,"Unable to allocate channel structure\n");
+               chan_misdn_log(-1,0,"Unable to allocate channel structure\n");
        }
        
        return tmp;
 }
 
 
-
-int misdn_tx2ast_frm(struct chan_list * tmp, char * buf,  int len )
+struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
 {
-       struct ast_frame frame;
-       
-       /* If in hold state we drop frame .. */
-       if (tmp->holded ) return 0;
-
-       switch(tmp->state) {
-       case MISDN_CLEANING:
-       case MISDN_EXTCANTMATCH:
-       case MISDN_WAITING4DIGS:
-               return 0;
-       default:
-               break;
-       }
-       
-       if (tmp->norxtone) {
-               chan_misdn_log(3, tmp->bc->port, "misdn_tx2ast_frm: Returning because norxtone\n");
-               return 0;
+       struct ast_frame *f,*f2;
+       if (tmp->trans)
+               f2=ast_translate(tmp->trans, frame,0);
+       else {
+               chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
+               return NULL;
        }
        
-       frame.frametype  = AST_FRAME_VOICE;
-       frame.subclass = AST_FORMAT_ALAW;
-       frame.datalen = len;
-       frame.samples = len ;
-       frame.mallocd =0 ;
-       frame.offset= 0 ;
-       frame.src = NULL;
-       frame.data = buf ;
-       
-       if (tmp->faxdetect || tmp->ast_dsp ) {
-               struct ast_frame *f,*f2;
-               if (tmp->trans)
-                       f2=ast_translate(tmp->trans, &frame,0);
-               else {
-                       chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
-                       return 0;
-               }
-               
-               f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
-               if (f && (f->frametype == AST_FRAME_DTMF)) {
-                       ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c", f->subclass);
-                       if (f->subclass == 'f' && tmp->faxdetect) {
-                               /* Fax tone -- Handle and return NULL */
-                               struct ast_channel *ast = tmp->ast;
-                               if (!tmp->faxhandled) {
-                                       tmp->faxhandled++;
-                                       if (strcmp(ast->exten, "fax")) {
-                                               if (ast_exists_extension(ast, ast_strlen_zero(ast->macrocontext)? ast->context : ast->macrocontext, "fax", 1, AST_CID_P(ast))) {
-                                                       if (option_verbose > 2)
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
-                                                       /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
-                                                       pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
-                                                       if (ast_async_goto(ast, ast->context, "fax", 1))
-                                                               ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, ast->context);
-                                               } else
-                                                       ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n",ast->context, ast->exten);
+       f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
+       if (f && (f->frametype == AST_FRAME_DTMF)) {
+               ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c", f->subclass);
+               if (f->subclass == 'f' && tmp->faxdetect) {
+                       /* Fax tone -- Handle and return NULL */
+                       struct ast_channel *ast = tmp->ast;
+                       if (!tmp->faxhandled) {
+                               tmp->faxhandled++;
+                               if (strcmp(ast->exten, "fax")) {
+                                       if (ast_exists_extension(ast, ast_strlen_zero(ast->macrocontext)? ast->context : ast->macrocontext, "fax", 1, AST_CID_P(ast))) {
+                                               if (option_verbose > 2)
+                                                       ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
+                                               /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
+                                               pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
+                                               if (ast_async_goto(ast, ast->context, "fax", 1))
+                                                       ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, ast->context);
                                        } else
-                                               ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
+                                               ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n",ast->context, ast->exten);
                                } else
-                                       ast_log(LOG_DEBUG, "Fax already handled\n");
-                               frame.frametype = AST_FRAME_NULL;
-                               frame.subclass = 0;
-                               f = &frame;
-                       }  else if ( tmp->ast_dsp) {
-                               struct ast_frame fr;
-                               memset(&fr, 0 , sizeof(fr));
-                               fr.frametype = AST_FRAME_DTMF;
-                               fr.subclass = f->subclass ;
-                               fr.src=NULL;
-                               fr.data = NULL ;
-                               fr.datalen = 0;
-                               fr.samples = 0 ;
-                               fr.mallocd =0 ;
-                               fr.offset= 0 ;
-                               
-                               chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n",f->subclass);
-                               ast_queue_frame(tmp->ast, &fr);
-                               
-                               frame.frametype = AST_FRAME_NULL;
-                               frame.subclass = 0;
-                               f = &frame;
-                       }
+                                       ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
+                       } else
+                               ast_log(LOG_DEBUG, "Fax already handled\n");
+                       
+               }  else if ( tmp->ast_dsp) {
+                       chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n",f->subclass);
+                       return f;
                }
        }
-       
-       if (tmp && tmp->ast && MISDN_ASTERISK_PVT (tmp->ast) && MISDN_ASTERISK_TECH_PVT(tmp->ast) ) {
-#if MISDN_DEBUG
-               int i, max=5>len?len:5;
-    
-               printf("write2* %p %d bytes: ",tmp, len);
-    
-               for (i=0; i<  max ; i++) printf("%2.2x ",((char*) frame.data)[i]);
-               printf ("\n");
-#endif
-               chan_misdn_log(9, tmp->bc->port, "Queueing %d bytes 2 Asterisk\n",len);
-               ast_queue_frame(tmp->ast,&frame);
-               
-       }  else {
-               ast_log (LOG_WARNING, "No ast || ast->pvt || ch\n");
-       }
-       
-       return 0;
+
+       frame->frametype = AST_FRAME_NULL;
+       frame->subclass = 0;
+       return frame;
 }
 
-/** Channel Queue ***/
 
-struct chan_list *find_chan_by_l3id(struct chan_list *list, unsigned long l3id)
+static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
 {
        struct chan_list *help=list;
        for (;help; help=help->next) {
-               if (help->l3id == l3id ) return help;
+               if (help->bc == bc) return help;
        }
   
-       chan_misdn_log(4, list? (list->bc? list->bc->port : 0) : 0, "$$$ find_chan: No channel found with l3id:%x\n",l3id);
+       chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
   
        return NULL;
 }
 
-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)
 {
        struct chan_list *help=list;
        for (;help; help=help->next) {
-               if (help->bc == bc) return help;
+               if (help->bc->pid == pid) return help;
        }
   
-       chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
+       chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n",pid);
   
        return NULL;
 }
 
-
-struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
+static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
 {
        struct chan_list *help=list;
        
-       chan_misdn_log(4, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
+       chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
        for (;help; help=help->next) {
                chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->bc->holded, help->bc->channel);
                if (help->bc->port == bc->port
                    && help->bc->holded ) return help;
        }
        
-       chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
+       chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
   
        return NULL;
 }
 
-void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
+static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
 {
        chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
   
@@ -2382,12 +2838,13 @@ void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
        ast_mutex_unlock(&cl_te_lock);
 }
 
-void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan) 
+static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan) 
 {
        if (chan->dsp) 
                ast_dsp_free(chan->dsp);
        if (chan->trans)
                ast_translator_free_path(chan->trans);
+
        
 
        ast_mutex_lock(&cl_te_lock);
@@ -2419,35 +2876,88 @@ void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
 /** Channel Queue End **/
 
 
+int pbx_start_chan(struct chan_list *ch)
+{
+       int ret=ast_pbx_start(ch->ast); 
+
+       if (ret>=0) 
+               ch->need_hangup=0;
+       else
+               ch->need_hangup=1;
+
+       return ret;
+}
+
+static void hangup_chan(struct chan_list *ch)
+{
+       if (!ch) {
+               cb_log(1,0,"Cannot hangup chan, no ch\n");
+               return;
+       }
+
+       cb_log(1,ch->bc?ch->bc->port:0,"hangup_chan\n");
+
+       if (ch->need_hangup) 
+       {
+               cb_log(1,ch->bc->port,"-> hangup\n");
+               send_cause2ast(ch->ast,ch->bc,ch);
+               ch->need_hangup=0;
+               ch->need_queue_hangup=0;
+               if (ch->ast)
+                       ast_hangup(ch->ast);
+               return;
+       }
+
+       if (!ch->need_queue_hangup) {
+               cb_log(1,ch->bc->port,"No need to queue hangup\n");
+       }
+
+       ch->need_queue_hangup=0;
+       if (ch->ast) {
+               send_cause2ast(ch->ast,ch->bc,ch);
+
+               if (ch->ast)
+                       ast_queue_hangup(ch->ast);
+               cb_log(1,ch->bc->port,"-> queue_hangup\n");
+       } else {
+               cb_log(1,ch->bc->port,"Cannot hangup chan, no ast\n");
+       }
+}
 
 /** Isdn asks us to release channel, pendant to misdn_hangup **/
 static void release_chan(struct misdn_bchannel *bc) {
        struct ast_channel *ast=NULL;
-       
        {
                struct chan_list *ch=find_chan_by_bc(cl_te, bc);
-               if (!ch) ch=find_chan_by_l3id (cl_te, bc->l3_id);
+               if (!ch)  {
+                       chan_misdn_log(0, bc->port, "release_chan: Ch not found!\n");
+                       return;
+               }
                
-               release_lock;
                if (ch->ast) {
                        ast=ch->ast;
                } 
-               release_unlock;
                
-               chan_misdn_log(1, bc->port, "Trying to Release bc with l3id: %x\n",bc->l3_id);
+               chan_misdn_log(1, bc->port, "release_chan: bc with l3id: %x\n",bc->l3_id);
+               
+               /*releaseing jitterbuffer*/
+               if (ch->jb ) {
+                       misdn_jb_destroy(ch->jb);
+                       ch->jb=NULL;
+               } else {
+                       if (!bc->nojitter)
+                               chan_misdn_log(5,bc->port,"Jitterbuffer already destroyed.\n");
+               }
+               
                if (ch) {
-                       if (ast)
-                               chan_misdn_trace_call(ast,1,"I->*: EVENT_RELEASE\n");
                        
                        close(ch->pipe[0]);
                        close(ch->pipe[1]);
+
                        
-                       if (ast && MISDN_ASTERISK_PVT(ast)) {
+                       if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
                                chan_misdn_log(1, bc->port, "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s state: %s\n",bc?bc->pid:-1, ast->context, ast->exten,AST_CID_P(ast),misdn_get_ch_state(ch));
                                chan_misdn_log(3, bc->port, " --> * State Down\n");
-                               /* copy cause */
-                               send_cause2ast(ast,bc);
-                               
                                MISDN_ASTERISK_TECH_PVT(ast)=NULL;
                                
       
@@ -2455,58 +2965,9 @@ static void release_chan(struct misdn_bchannel *bc) {
                                        chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
                                        ast_setstate(ast, AST_STATE_DOWN);
                                }
-                               
-                               switch(ch->state) {
-                               case MISDN_EXTCANTMATCH:
-                               case MISDN_WAITING4DIGS:
-                               {
-                                       chan_misdn_log(3,  bc->port, " --> * State Wait4dig | ExtCantMatch\n");
-                                       ast_hangup(ast);
-                               }
-                               break;
-                               
-                               case MISDN_DIALING:
-                               case MISDN_CALLING_ACKNOWLEDGE:
-                               case MISDN_PROGRESS:
-                                       chan_misdn_log(2,  bc->port, "* --> In State Dialin\n");
-                                       chan_misdn_log(2,  bc->port, "* --> Queue Hangup\n");
-                                       
-
-                                       ast_queue_hangup(ast);
-                                       break;
-                               case MISDN_CALLING:
-                                       
-                                       chan_misdn_log(2,  bc->port, "* --> In State Callin\n");
-                                       
-                                       if (!bc->nt) {
-                                               chan_misdn_log(2,  bc->port, "* --> Queue Hangup\n");
-                                               ast_queue_hangup(ast);
-                                       } else {
-                                               chan_misdn_log(2,  bc->port, "* --> Hangup\n");
-                                               ast_queue_hangup(ast);
-                                               //ast_hangup(ast);
-                                       }
-                                       break;
-                                       
-                               case MISDN_CLEANING:
-                                       /* this state comes out of ast so we mustnt call a ast function ! */
-                                       chan_misdn_log(2,  bc->port, "* --> In StateCleaning\n");
-                                       break;
-                               case MISDN_HOLD_DISCONNECT:
-                                       chan_misdn_log(2,  bc->port, "* --> In HOLD_DISC\n");
-                                       break;
-                               default:
-                                       chan_misdn_log(2,  bc->port, "* --> In State Default\n");
-                                       chan_misdn_log(2,  bc->port, "* --> Queue Hangup\n");
-       
-                                       
-                                       if (ast && MISDN_ASTERISK_PVT(ast)) {
-                                               ast_queue_hangup(ast);
-                                       } else {
-                                               chan_misdn_log (0,  bc->port, "!! Not really queued!\n");
-                                       }
-                               }
                        }
+                               
+                       ch->state=MISDN_CLEANING;
                        cl_dequeue_chan(&cl_te, ch);
                        
                        free(ch);
@@ -2517,7 +2978,7 @@ static void release_chan(struct misdn_bchannel *bc) {
 }
 /*** release end **/
 
-void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
+static void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
 {
        chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name);
        
@@ -2526,14 +2987,12 @@ void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
        ast_moh_stop(AST_BRIDGED_P(holded_chan->ast));
 
        holded_chan->state=MISDN_CONNECTED;
-       holded_chan->holded=0;
        misdn_lib_transfer(holded_chan->bc?holded_chan->bc:holded_chan->holded_bc);
-       
        ast_channel_masquerade(holded_chan->ast, AST_BRIDGED_P(tmp_ch->ast));
 }
 
 
-void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
+static void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
 {
        char predial[256]="";
        char *p = predial;
@@ -2543,7 +3002,7 @@ void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct
        strncpy(predial, ast->exten, sizeof(predial) -1 );
   
        ch->state=MISDN_DIALING;
-       
+
        if (bc->nt) {
                int ret; 
                ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
@@ -2556,15 +3015,20 @@ void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct
                }
        }
 
-       manager_send_tone(bc,TONE_DIAL);  
+       if ( !bc->nt && (ch->orginator==ORG_MISDN) && !ch->incoming_early_audio ) 
+               chan_misdn_log(1,bc->port, " --> incoming_early_audio off\n");
+        else  
+               dialtone_indicate(ch);
   
        chan_misdn_log(1, bc->port, "* Starting Ast ctx:%s dad:%s oad:%s with 's' extension\n", ast->context, ast->exten, AST_CID_P(ast));
   
        strncpy(ast->exten,"s", 2);
   
-       if (ast_pbx_start(ast)<0) {
+       if (pbx_start_chan(ch)<0) {
                ast=NULL;
-               manager_send_tone(bc,TONE_BUSY);
+               hangup_chan(ch);
+               hanguptone_indicate(ch);
+
                if (bc->nt)
                        misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
                else
@@ -2591,7 +3055,19 @@ void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct
 
 
 
-void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc) {
+static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch) {
+       if (!ast) {
+               chan_misdn_log(1,0,"send_cause2ast: No Ast\n");
+               return;
+       }
+       if (!bc) {
+               chan_misdn_log(1,0,"send_cause2ast: No BC\n");
+               return;
+       }
+       if (!ch) {
+               chan_misdn_log(1,0,"send_cause2ast: No Ch\n");
+               return;
+       }
        
        ast->hangupcause=bc->cause;
        
@@ -2603,55 +3079,122 @@ void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc) {
        case 4:
        case 22:
        case 27:
+               /*
+                * Not Queueing the Congestion anymore, since we want to hear
+                * the inband message
+                *
                chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Congestion pid:%d\n", bc?bc->pid:-1);
+               ch->state=MISDN_BUSY;
                
                ast_queue_control(ast, AST_CONTROL_CONGESTION);
+               */
                break;
                
        case 21:
        case 17: /* user busy */
+       
+               ch->state=MISDN_BUSY;
+                       
+               if (!ch->need_busy) {
+                       chan_misdn_log(1,bc?bc->port:0, "Queued busy already\n");
+                       break;
+               }
+               
                chan_misdn_log(1,  bc?bc->port:0, " --> * SEND: Queue Busy pid:%d\n", bc?bc->pid:-1);
                
                ast_queue_control(ast, AST_CONTROL_BUSY);
                
+               ch->need_busy=0;
+               
                break;
        }
 }
 
+void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
+{
+       char *tmp;
+       tmp=pbx_builtin_getvar_helper(chan,"MISDN_PID");
+       if (tmp) {
+               ch->other_pid=atoi(tmp);
+               chan_misdn_log(1,bc->port,"IMPORT_PID: importing pid:%s\n",tmp);
+
+               if (ch->other_pid >0) {
+                       ch->other_ch=find_chan_by_pid(cl_te,ch->other_pid);
+                       if (ch->other_ch) ch->other_ch->other_ch=ch;
+               }
+       }
+}
+void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
+{
+       char tmp[32];
+
+       chan_misdn_log(1,bc->port,"EXPORT_PID: pid:%d\n",bc->pid);
+       sprintf(tmp,"%d",bc->pid);
+       pbx_builtin_setvar_helper(chan,"_MISDN_PID",tmp);
+}
+
+
+
 /************************************************************/
 /*  Receive Events from isdn_lib  here                     */
 /************************************************************/
-enum event_response_e
+static enum event_response_e
 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
 {
        struct chan_list *ch=find_chan_by_bc(cl_te, bc);
        
-       if (!ch)
-               ch=find_chan_by_l3id(cl_te, bc->l3_id);
+       if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /*  Debug Only Non-Bchan */
+               int debuglevel=1;
        
-       if (event != EVENT_BCHAN_DATA) { /*  Debug Only Non-Bchan */
-               chan_misdn_log(1, bc->port, "I IND :%s oad:%s dad:%s port:%d\n", manager_isdn_get_info(event), bc->oad, bc->dad, bc->port);
-               misdn_lib_log_ies(bc);
+               if ( event==EVENT_CLEANUP && !user_data)
+                       debuglevel=5;
+
+               chan_misdn_log(debuglevel, bc->port, "I IND :%s oad:%s dad:%s pid:%d state:%s\n", manager_isdn_get_info(event), bc->oad, bc->dad, bc->pid, ch?misdn_get_ch_state(ch):"none");
+               if (debuglevel==1) {
+                       misdn_lib_log_ies(bc);
+                       chan_misdn_log(4,bc->port," --> bc_state:%s\n",bc_state2str(bc->bc_state));
+               }
        }
        
-       if (event != EVENT_SETUP) {
-               if (!ch) {
-                       if (event != EVENT_CLEANUP )
-                               ast_log(LOG_WARNING, "Chan not existing at the moment bc->l3id:%x bc:%p event:%s port:%d channel:%d\n",bc->l3_id, bc, manager_isdn_get_info( event), bc->port,bc->channel);
-                       return -1;
+       if (!ch) {
+               switch(event) {
+                       case EVENT_SETUP:
+                       case EVENT_DISCONNECT:
+                       case EVENT_PORT_ALARM:
+                       case EVENT_RETRIEVE:
+                       case EVENT_NEW_BC:
+                               break;
+                       case EVENT_RELEASE_COMPLETE:
+                               chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
+                               break;
+                       case EVENT_CLEANUP:
+                       case EVENT_TONE_GENERATE:
+                       case EVENT_BCHAN_DATA:
+                               return -1;
+
+                       default:
+                               chan_misdn_log(1,bc->port, "Chan not existing at the moment bc->l3id:%x bc:%p event:%s port:%d channel:%d\n",bc->l3_id, bc, manager_isdn_get_info( event), bc->port,bc->channel);
+                               return -1;
                }
        }
        
        if (ch ) {
                switch (event) {
+               case EVENT_TONE_GENERATE:
+               break;
+               case EVENT_DISCONNECT:
                case EVENT_RELEASE:
                case EVENT_RELEASE_COMPLETE:
                case EVENT_CLEANUP:
+               case EVENT_TIMEOUT:
+                       if (!ch->ast)
+                               chan_misdn_log(3,bc->port,"ast_hangup already called, so we have no ast ptr anymore in event(%s)\n",manager_isdn_get_info(event));
                        break;
                default:
                        if ( !ch->ast  || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
                                if (event!=EVENT_BCHAN_DATA)
-                                       ast_log(LOG_WARNING, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
+                                       ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
                                return -1;
                        }
                }
@@ -2659,13 +3202,38 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
        
        
        switch (event) {
+       case EVENT_PORT_ALARM:
+               {
+                       int boa=0;
+
+                       misdn_cfg_get( bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(int));
+                       if (boa) {
+                               cb_log(1,bc->port," --> blocking\n");
+                               misdn_lib_port_block(bc->port); 
+                       }
+               }
+               break;
+
+       case EVENT_BCHAN_ACTIVATED:
+               break;
+               
        case EVENT_NEW_L3ID:
                ch->l3id=bc->l3_id;
+               ch->addr=bc->addr;
                break;
 
        case EVENT_NEW_BC:
+               if (!ch) {
+                       ch=find_holded(cl_te,bc);
+               }
+               
+               if (!ch) {
+                       ast_log(LOG_WARNING,"NEW_BC without chan_list?\n");
+                       break;
+               }
+
                if (bc)
-                       ch->bc=bc;
+                       ch->bc=(struct misdn_bchannel*)user_data;
                break;
                
        case EVENT_DTMF_TONE:
@@ -2682,9 +3250,12 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                fr.mallocd =0 ;
                fr.offset= 0 ;
                
-               chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
-               
-               ast_queue_frame(ch->ast, &fr);
+               if (!ch->ignore_dtmf) {
+                       chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
+                       ast_queue_frame(ch->ast, &fr);
+               } else {
+                       chan_misdn_log(2, bc->port, " --> Ingoring DTMF:%c due to bridge flags\n", bc->dtmf);
+               }
        }
        break;
        case EVENT_STATUS:
@@ -2694,8 +3265,8 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
        {
                int stop_tone;
                misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
-               if ( stop_tone && bc->tone != TONE_NONE) {
-                       manager_send_tone(bc,TONE_NONE);
+               if ( stop_tone ) {
+                       stop_indicate(ch);
                }
                
                if (ch->state == MISDN_WAITING4DIGS ) {
@@ -2714,31 +3285,46 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        }
 /*                     chan_misdn_log(5, bc->port, "Can Match Extension: dad:%s oad:%s\n",bc->dad,bc->oad);*/
                        
-                       char bc_context[BUFFERSIZE];
-                       misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
-                       if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
-                               chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
-                               manager_send_tone(bc,TONE_BUSY);
+                       /* Check for Pickup Request first */
+                       if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
+                               int ret;/** Sending SETUP_ACK**/
+                               ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
+                               if (ast_pickup_call(ch->ast)) {
+                                       hangup_chan(ch);
+                               } else {
+                                       struct ast_channel *chan=ch->ast;
+                                       ch->state = MISDN_CALLING_ACKNOWLEDGE;
+                                       ast_setstate(chan, AST_STATE_DOWN);
+                                       hangup_chan(ch);
+                                       ch->ast=NULL;
+                                       break;
+                               }
+                       }
+                       
+                       if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
+
+                               chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n");
+                               if (bc->nt)
+                                       hanguptone_indicate(ch);
                                ch->state=MISDN_EXTCANTMATCH;
                                bc->out_cause=1;
-                               if (bc->nt)
-                                       misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
-                               else
-                                       misdn_lib_send_event(bc, EVENT_DISCONNECT );
+
+                               misdn_lib_send_event(bc, EVENT_DISCONNECT );
+
                                break;
                        }
-                       if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
+                       if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
                                ch->state=MISDN_DIALING;
          
-                               manager_send_tone(bc,TONE_NONE);
-/*                             chan_misdn_log(1, bc->port, " --> * Starting Ast ctx:%s\n", ch->ast->context);*/
-                               if (ast_pbx_start(ch->ast)<0) {
-                                       chan_misdn_log(0, bc->port, "ast_pbx_start returned < 0 in INFO\n");
-                                       manager_send_tone(bc,TONE_BUSY);
-                                       if (bc->nt)
-                                               misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
-                                       else
-                                               misdn_lib_send_event(bc, EVENT_DISCONNECT );
+                               stop_indicate(ch);
+/*                             chan_misdn_log(1, bc->port, " --> * Starting Ast ctx:%s\n", ch->context);*/
+                               if (pbx_start_chan(ch)<0) {
+                                       hangup_chan(ch);
+
+                                       chan_misdn_log(-1, bc->port, "ast_pbx_start returned < 0 in INFO\n");
+                                       if (bc->nt) hanguptone_indicate(ch);
+
+                                       misdn_lib_send_event(bc, EVENT_DISCONNECT );
                                }
                        }
        
@@ -2771,7 +3357,6 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                                
                                ast_queue_frame(ch->ast, &fr);
                        }
-                       
                }
        }
        break;
@@ -2784,6 +3369,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                }
        }
        
+
        int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
        if (!bc->nt && ! msn_valid) {
                chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
@@ -2793,119 +3379,61 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
        print_bearer(bc);
     
        {
-               struct chan_list *ch=init_chan_list();
+               struct chan_list *ch=init_chan_list(ORG_MISDN);
                struct ast_channel *chan;
-               char name[128];
-               if (!ch) { chan_misdn_log(0, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
+
+               if (!ch) { chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
                
                ch->bc = bc;
                ch->l3id=bc->l3_id;
                ch->addr=bc->addr;
                ch->orginator = ORG_MISDN;
 
+               chan=misdn_new(ch, AST_STATE_RESERVED,bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
+               ch->ast = chan;
+
+               read_config(ch, ORG_MISDN);
                
-               {
-                       char prefix[BUFFERSIZE]="";
-                       switch( bc->onumplan ) {
-                       case NUMPLAN_INTERNATIONAL:
-                               misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
-                               break;
-         
-                       case NUMPLAN_NATIONAL:
-                               misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
-                               break;
-         
-         
-                       case NUMPLAN_SUBSCRIBER:
-                               /* dunno what to do here ? */
-                               break;
+               export_ch(chan, bc, ch);
 
-                       case NUMPLAN_UNKNOWN:
-                               break;
-                       default:
-                               break;
-                       }
+               ch->ast->rings=1;
+               ast_setstate(ch->ast, AST_STATE_RINGING);
 
-                       {
-                               int l = strlen(prefix) + strlen(bc->oad);
-                               char tmp[l+1];
-                               strcpy(tmp,prefix);
-                               strcat(tmp,bc->oad);
-                               strcpy(bc->oad,tmp);
-                       }
-                       
-                       if (!ast_strlen_zero(bc->oad))
-                               sprintf(name,"mISDN/%d/%s",bc->port,bc->oad);
-                       else
-                               sprintf(name,"mISDN/%d",bc->port);
+               int pres,screen;
 
+               switch (bc->pres) {
+                       case 1:
+                       pres=AST_PRES_RESTRICTED; chan_misdn_log(2,bc->port," --> PRES: Restricted (1)\n");
+                       break;
+                       case 2:
+                       pres=AST_PRES_UNAVAILABLE; chan_misdn_log(2,bc->port," --> PRES: Restricted (2)\n");
+                       break;
+                       default:
+                       pres=AST_PRES_ALLOWED; chan_misdn_log(2,bc->port," --> PRES: Restricted (%d)\n", bc->pres);
+               }
 
-                       if (!ast_strlen_zero(bc->dad)) {
-                               strncpy(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
-                               bc->orig_dad[sizeof(bc->orig_dad)-1] = 0;
-                       }
-                       
-                       if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
-                               strncpy(bc->dad,bc->keypad, sizeof(bc->dad));
-                               bc->dad[sizeof(bc->dad)-1] = 0;
-                       }
-                       prefix[0] = 0;
-                       
-                       switch( bc->dnumplan ) {
-                       case NUMPLAN_INTERNATIONAL:
-                               misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
-                               break;
-                               
-                       case NUMPLAN_NATIONAL:
-                               misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
-                               break;
-                               
-                               
-                       case NUMPLAN_SUBSCRIBER:
-                               /* dunno what to do here ? */
-                               break;
-                               
-                       case NUMPLAN_UNKNOWN:
-                               break;
+               switch (bc->screen) {
+                       case 0:
+                       screen=AST_PRES_USER_NUMBER_UNSCREENED;  chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (0)\n");
+                       break;
+                       case 1:
+                       screen=AST_PRES_USER_NUMBER_PASSED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: Passed screen (1)\n");
+                       break;
+                       case 2:
+                       screen=AST_PRES_USER_NUMBER_FAILED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: failed screen (2)\n");
+                       break;
+                       case 3:
+                       screen=AST_PRES_NETWORK_NUMBER; chan_misdn_log(2,bc->port," --> SCREEN: Network Number (3)\n");
+                       break;
                        default:
-                               break;
-                       }
-               
-                       {
-                               int l = strlen(prefix) + strlen(bc->dad);
-                               char tmp[l+1];
-                               strcpy(tmp,prefix);
-                               strcat(tmp,bc->dad);
-                               strcpy(bc->dad,tmp);
-                       }
-                       
-                       char bc_context[BUFFERSIZE];
-                       misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
-                       chan=misdn_new(ch, AST_STATE_RING,name ,bc_context, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
-                       
-                       if (!chan) {
-                               misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
-                               return 0;
-                       }
-                       
-                       ch->ast = chan;
-                       pbx_builtin_setvar_helper(ch->ast,"REDIRECTING_NUMBER",bc->rad);
-                       
+                       screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (%d)\n",bc->screen);
                }
 
-               
+               chan->cid.cid_pres=pres+screen;
 
-               chan_misdn_trace_call(chan,1,"I->*: EVENT_SETUP\n");
-               
-               if ( bc->pres ) {
-                       chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
-               }  else {
-                       chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
-               }
-      
                pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
                chan->transfercapability=bc->capability;
-      
+               
                switch (bc->capability) {
                case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
                        pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL");
@@ -2917,113 +3445,88 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                /** queue new chan **/
                cl_queue_chan(&cl_te, ch) ;
 
-               
-               /*
-                 added support for s extension hope it will help those poor cretains
-                 which haven't overlap dial.
-               */
-               {
-                       
-                       misdn_cfg_get( bc->port, MISDN_CFG_LANGUAGE, chan->language, sizeof(chan->language));                   
-                       
-               }
-
-               {
-                       int eb3;
-                       
-                       misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
-                       bc->early_bconnect=eb3;
-                       
-               }
 
-               {
-                       int ec, ectr;
-                       
-                       misdn_cfg_get( bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
-                       
-                       misdn_cfg_get( bc->port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
-                       if (ec == 1 ) {
-                               bc->ec_enable=1;
-                       } else if ( ec > 1 ) {
-                               bc->ec_enable=1;
-                               bc->ec_deftaps=ec;
-                       }
-                       
-                       if ( ectr>=0 ) {
-                               bc->ec_training=ectr;
+               if (!strstr(ch->allowed_bearers,"all")) {
+                       int i;
+                       for (i=0; i< sizeof(allowed_bearers_array)/sizeof(struct allowed_bearers); i++) {
+                               if (allowed_bearers_array[i].cap == bc->capability) {
+                                       if (  !strstr( ch->allowed_bearers, allowed_bearers_array[i].name)) {
+                                               chan_misdn_log(0,bc->port,"Bearer Not allowed\b");
+                                               bc->out_cause=88;
+                                               
+                                               ch->state=MISDN_EXTCANTMATCH;
+                                               misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
+                                               return RESPONSE_OK;
+                                       }
+                               }
+                               
                        }
                }
                
-
-               if (bc->urate>0) {
-                       char buf[16];
-                       snprintf(buf,16,"%d",bc->urate);
-                       pbx_builtin_setvar_helper(chan,"MISDN_URATE",buf);
-               }
-
-
-
-               /**
-                  from here on  we start the PBX, so no configuration should
-                  be considered anymore
-               **/
-               
-               int ai;
-               misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
-               if ( ai ) {
-                       do_immediate_setup(bc, ch , chan);
-                       break;
-               }
-               
-                       
-               int immediate;
-               misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &immediate, sizeof(int));
-               
-               if (ast_strlen_zero(bc->orig_dad) && immediate ) {
-                       do_immediate_setup(bc, ch , chan);
-                       break;
-               }
-               
                /* Check for Pickup Request first */
                if (!strcmp(chan->exten, ast_pickup_ext())) {
                        int ret;/** Sending SETUP_ACK**/
                        ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
-       
                        if (ast_pickup_call(chan)) {
-                               ast_hangup(chan);
+                               hangup_chan(ch);
                        } else {
                                ch->state = MISDN_CALLING_ACKNOWLEDGE;
-         
-                               ch->ast=NULL;
-         
                                ast_setstate(chan, AST_STATE_DOWN);
-                               ast_hangup(chan); 
-         
+                               hangup_chan(ch);
+                               ch->ast=NULL;
                                break;
                        }
                }
                
-               /** Now after we've finished configuring our channel object
-                   we'll jump into the dialplan **/
+               /*
+                 added support for s extension hope it will help those poor cretains
+                 which haven't overlap dial.
+               */
+               {
+                       int ai;
+                       misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
+                       if ( ai ) {
+                               do_immediate_setup(bc, ch , chan);
+                               break;
+                       }
+                       
+                       
+                       
+               }
+
+               /* check if we should jump into s when we have no dad */
+               {
+                       int im;
+                       misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
+                       if ( im && ast_strlen_zero(bc->dad) ) {
+                               do_immediate_setup(bc, ch , chan);
+                               break;
+                       }
+               }
+
                
-               char bc_context[BUFFERSIZE];
-               misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
-               if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
-                       chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
-                       manager_send_tone(bc,TONE_BUSY);
+                       chan_misdn_log(5,bc->port,"CONTEXT:%s\n",ch->context);
+                       if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
+                       
+                       chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n");
+
+                       if (bc->nt)
+                               hanguptone_indicate(ch);
                        ch->state=MISDN_EXTCANTMATCH;
                        bc->out_cause=1;
+
                        if (bc->nt)
                                misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
                        else
-                               misdn_lib_send_event(bc, EVENT_DISCONNECT );
+                               misdn_lib_send_event(bc, EVENT_RELEASE );
+                               
                        break;
                }
                
-               if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
+               if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
                        ch->state=MISDN_DIALING;
-       
-                       if (bc->nt) {
+                       
+                       if (bc->nt || (bc->need_more_infos && misdn_lib_is_ptp(bc->port)) ) {
                                int ret; 
                                ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
                        } else {
@@ -3031,31 +3534,53 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                                ret= misdn_lib_send_event(bc, EVENT_PROCEEDING );
                        }
        
-                       if (ast_pbx_start(chan)<0) {
-                               chan_misdn_log(0, bc->port, "ast_pbx_start returned <0 in SETUP\n");
+                       if (pbx_start_chan(ch)<0) {
+                               hangup_chan(ch);
+
+                               chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
                                chan=NULL;
-                               manager_send_tone(bc,TONE_BUSY);
-                               if (bc->nt)
+
+                               if (bc->nt) {
+                                       hanguptone_indicate(ch);
                                        misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
-                               else
-                                       misdn_lib_send_event(bc, EVENT_DISCONNECT );
+                               else
+                                       misdn_lib_send_event(bc, EVENT_RELEASE);
                        }
                } else {
-                       int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
-                       if (ret == -ENOCHAN) {
-                               ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n");
-                               misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
+
+                       if (bc->sending_complete) {
+                               ch->state=MISDN_EXTCANTMATCH;
+                               bc->out_cause=1;
+
+                               if (bc->nt)  {
+                                       chan_misdn_log(0,bc->port," --> sending_complete so we never match ..\n");
+                                       misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
+                               } else {
+                                       chan_misdn_log(0,bc->port," --> sending_complete so we never match ..\n");
+                                       misdn_lib_send_event(bc, EVENT_RELEASE);
+                               }
+
+                       } else {
+                               
+                               int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
+                               if (ret == -ENOCHAN) {
+                                       ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n");
+                                       misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
+                               }
+                               /*  send tone to phone :) */
+                               
+                               /** ADD IGNOREPAT **/
+                               
+                               int stop_tone;
+                               misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
+                               if ( (!ast_strlen_zero(bc->dad)) && stop_tone ) 
+                                       stop_indicate(ch);
+                               else {
+                                       dialtone_indicate(ch);
+                               }
+                               
+                               ch->state=MISDN_WAITING4DIGS;
                        }
-                       /*  send tone to phone :) */
-                       
-                       int stop_tone;
-                       misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
-                       if ( (!ast_strlen_zero(bc->dad)) && stop_tone ) 
-                               manager_send_tone(bc,TONE_NONE);
-                       else
-                               manager_send_tone(bc,TONE_DIAL);
-       
-                       ch->state=MISDN_WAITING4DIGS;
                }
       
        }
@@ -3094,6 +3619,10 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                     misdn_inband_avail(bc) ) {
                        start_bc_tones(ch);
                }
+
+               ch->state = MISDN_PROCEEDING;
+               
+               ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
        }
        break;
        case EVENT_PROGRESS:
@@ -3121,162 +3650,272 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                cb_log(1,bc->port,"Set State Ringing\n");
                
                if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
-                        start_bc_tones(ch);
-                }
+                       cb_log(1,bc->port,"Starting Tones, we have inband Data\n");
+                       start_bc_tones(ch);
+               } else {
+                       cb_log(1,bc->port,"We have no inband Data, the other end must create ringing\n");
+                       if (ch->far_alerting) {
+                               cb_log(1,bc->port,"The other end can not do ringing eh ?.. we must do all ourself..");
+                               start_bc_tones(ch);
+                               /*tone_indicate(ch, TONE_FAR_ALERTING);*/
+                       }
+               }
        }
        break;
        case EVENT_CONNECT:
+       {
+               /*we answer when we've got our very new L3 ID from the NT stack */
                misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE);
+       
+               struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
+               
+               misdn_lib_echo(bc,0);
+               stop_indicate(ch);
+
+               if (bridged && !strcasecmp(bridged->tech->type,"mISDN")) {
+                       struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged);
+
+                       chan_misdn_log(1,bc->port," --> copying cpndialplan:%d and cad:%s to the A-Channel\n",bc->cpnnumplan,bc->cad);
+                       if (bridged_ch) {
+                               bridged_ch->bc->cpnnumplan=bc->cpnnumplan;
+                               ast_copy_string(bridged_ch->bc->cad,bc->cad,sizeof(bc->cad));
+                       }
+               }
+       }
+       
+       
+       /* notice that we don't break here!*/
+
        case EVENT_CONNECT_ACKNOWLEDGE:
        {
-               bc->state=STATE_CONNECTED;
-               
                ch->l3id=bc->l3_id;
                ch->addr=bc->addr;
                
                start_bc_tones(ch);
                
-               chan_misdn_trace_call(ch->ast,1,"I->*: EVENT_CONNECT\n");
                
                ch->state = MISDN_CONNECTED;
                ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
        }
        break;
        case EVENT_DISCONNECT:
-       {
-               
+       /*we might not have an ch->ast ptr here anymore*/
+       if (ch) {
                struct chan_list *holded_ch=find_holded(cl_te, bc);
-               
-               
-               send_cause2ast(ch->ast,bc);
-
-               if (misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
+       
+               chan_misdn_log(3,bc->port," --> org:%d nt:%d, inbandavail:%d state:%d\n", ch->orginator, bc->nt, misdn_inband_avail(bc), ch->state);
+               if ( ch->orginator==ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
                        /* If there's inband information available (e.g. a
                           recorded message saying what was wrong with the
                           dialled number, or perhaps even giving an
                           alternative number, then play it instead of
                           immediately releasing the call */
+                       chan_misdn_log(1,bc->port, " --> Inband Info Avail, not sending RELEASE\n");
+               
+                       ch->state=MISDN_DISCONNECTED;
                        start_bc_tones(ch);
                        break;
                }
                
                /*Check for holded channel, to implement transfer*/
-               if (holded_ch ) {
+               if (holded_ch && ch->ast ) {
+                       cb_log(1,bc->port," --> found holded ch\n");
                        if  (ch->state == MISDN_CONNECTED ) {
                                misdn_transfer_bc(ch, holded_ch) ;
-                               misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
-                               break;
                        }
+                       hangup_chan(ch);
+                       release_chan(bc);
+                       break;
                }
                
                stop_bc_tones(ch);
-               bc->out_cause=16;
-               misdn_lib_send_event(bc,EVENT_RELEASE);
-               
+               hangup_chan(ch);
        }
+       bc->out_cause=-1;
+       if (bc->need_release) misdn_lib_send_event(bc,EVENT_RELEASE);
        break;
        
        case EVENT_RELEASE:
                {
-                       
-                       switch ( bc->cause) {
-                               
-                       case -1:
-                               /*
-                                 OK, it really sucks, this is a RELEASE from NT-Stack So we take
-                                 it and return easylie, It seems that we've send a DISCONNECT
-                                 before, so we should RELEASE_COMPLETE after that Disconnect
-                                 (looks like ALERTING State at misdn_hangup !!
-                               */
-                               return RESPONSE_OK;
-                               break;
-                       }
-                       
-                       
                        bc->out_cause=16;
                        
-                       stop_bc_tones(ch);
+                       hangup_chan(ch);
                        release_chan(bc);
+               
+                       if (bc->need_release_complete) 
+                               misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
                }
                break;
        case EVENT_RELEASE_COMPLETE:
        {
                stop_bc_tones(ch);
+               hangup_chan(ch);
                release_chan(bc);
+               if(ch)  
+                       ch->state=MISDN_CLEANING;
        }
        break;
+       case EVENT_CLEANUP:
+       {
+               stop_bc_tones(ch);
+               
+               switch(ch->state) {
+                       case MISDN_CALLING:
+                               bc->cause=27; /* Destination out of order */
+                       break;
+                       default:
+                       break;
+               }
+               
+               hangup_chan(ch);
+               release_chan(bc);
+       }
+       break;
+
+       case EVENT_TONE_GENERATE:
+       {
+               int tone_len=bc->tone_cnt;
+               struct ast_channel *ast=ch->ast;
+               void *tmp;
+               int res;
+               int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
+
+               chan_misdn_log(9,bc->port,"TONE_GEN: len:%d\n");
+
+               if (!ast) break;
+
+               if (!ast->generator) break;
+       
+               
        
+               tmp = ast->generatordata;
+               ast->generatordata = NULL;
+               generate = ast->generator->generate;
+
+               if (tone_len <0 || tone_len > 512 ) {
+                       ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n",tone_len);
+                       tone_len=128;
+               }
+
+               res = generate(ast, tmp, tone_len, tone_len);
+               ast->generatordata = tmp;
+               
+               if (res) {
+                       ast_log(LOG_WARNING, "Auto-deactivating generator\n");
+                       ast_deactivate_generator(ast);
+               } else {
+                       bc->tone_cnt=0;
+               }
+       }
+       break;
+               
        case EVENT_BCHAN_DATA:
        {
-               chan_misdn_trace_call(ch->ast,3,"I->*: EVENT_B_DATA len=%d\n",bc->bframe_len);
-               
-               if ( !misdn_cap_is_speech(ch->bc->capability) || bc->nojitter) {
-                       misdn_tx2ast_frm(ch, bc->bframe, bc->bframe_len );
+               if ( !misdn_cap_is_speech(ch->bc->capability) ) {
+                       struct ast_frame frame;
+                       /*In Data Modes we queue frames*/
+                       frame.frametype  = AST_FRAME_VOICE; /*we have no data frames yet*/
+                       frame.subclass = AST_FORMAT_ALAW;
+                       frame.datalen = bc->bframe_len;
+                       frame.samples = bc->bframe_len ;
+                       frame.mallocd =0 ;
+                       frame.offset= 0 ;
+                       frame.src = NULL;
+                       frame.data = bc->bframe ;
+                       
+                       ast_queue_frame(ch->ast,&frame);
                } else {
-                       int len=bc->bframe_len;
-                       int free=misdn_ibuf_freecount(bc->astbuf);
+                       fd_set wrfs;
+                       struct timeval tv;
+                       tv.tv_sec=0;
+                       tv.tv_usec=0;
+                       
                        
+                       FD_ZERO(&wrfs);
+                       FD_SET(ch->pipe[1],&wrfs);
                        
-                       if (bc->bframe_len > free) {
-                               ast_log(LOG_DEBUG, "sbuf overflow!\n");
-                               len=misdn_ibuf_freecount(bc->astbuf);
+                       int t=select(FD_SETSIZE,NULL,&wrfs,NULL,&tv);
 
-                               if (len == 0) {
-                                       ast_log(LOG_WARNING, "BCHAN_DATA: write buffer overflow port:%d channel:%d!\n",bc->port,bc->channel);
-                               }
+                       if (!t) {
+                               chan_misdn_log(9, bc->port, "Select Timed out\n");
+                               break;
                        }
                        
-                       misdn_ibuf_memcpy_w(bc->astbuf, bc->bframe, len);
+                       if (t<0) {
+                               chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n",strerror(errno));
+                               break;
+                       }
                        
-                       {
-                               char blah[1]="\0";
-#ifdef FLATTEN_JITTER
-                               {
-                                       struct timeval tv;
-                                       gettimeofday(&tv,NULL);
-                                       
-                                       if (tv.tv_usec % 10000 > 0 ) {
-                                               write(ch->pipe[1], blah,sizeof(blah));
-                                               bc->time_usec=tv.tv_usec;
-                                       }
-                               }
-#else
-                               write(ch->pipe[1], blah,sizeof(blah));
-#endif
-                               
+                       if (FD_ISSET(ch->pipe[1],&wrfs)) {
+                               chan_misdn_log(9, bc->port, "writing %d bytes 2 asterisk\n",bc->bframe_len);
+                               int ret=write(ch->pipe[1], bc->bframe, bc->bframe_len);
                                
+                               if (ret<=0) {
+                                       chan_misdn_log(-1, bc->port, "Write returned <=0 (err=%s)\n",strerror(errno));
+                               }
+                       } else {
+                               chan_misdn_log(1, bc->port, "Wripe Pipe full!\n");
                        }
                }
-               
        }
        break;
        case EVENT_TIMEOUT:
-               break; /* Ignore now .. */
                {
-                       switch (ch->state) {
+               if (ch && bc)
+                       chan_misdn_log(1,bc->port,"--> state: %s\n",misdn_get_ch_state(ch));
+
+               switch (ch->state) {
                        case MISDN_CALLING:
-                               chan_misdn_log(0, bc?bc->port:0, "GOT TIMOUT AT CALING pid:%d\n", bc?bc->pid:-1);
-                                       break;
                        case MISDN_DIALING:
                        case MISDN_PROGRESS:
-                               break;
+                       case MISDN_ALERTING:
+                       case MISDN_PROCEEDING:
+                       case MISDN_CALLING_ACKNOWLEDGE:
+                               if (bc->nt) {
+                                       bc->progress_indicator=8;
+                                       hanguptone_indicate(ch);
+                               }
+                               
+                               bc->out_cause=1;
+                               misdn_lib_send_event(bc,EVENT_DISCONNECT);
+                       break;
+
+                       case MISDN_WAITING4DIGS:
+                               if (bc->nt) {
+                                       bc->progress_indicator=8;
+                                       bc->out_cause=1;
+                                       hanguptone_indicate(ch);
+                                       misdn_lib_send_event(bc,EVENT_DISCONNECT);
+                               } else {
+                                       bc->out_cause=16;
+                                       misdn_lib_send_event(bc,EVENT_RELEASE);
+                               }
+                               
+                       break;
+
+
+                       case MISDN_CLEANING: 
+                               chan_misdn_log(1,bc->port," --> in state cleaning .. so ingoring, the stack should clean it for us\n");
+                       break;
+
                        default:
                                misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
                        }
                }
                break;
-       case EVENT_CLEANUP:
-       {
-               stop_bc_tones(ch);
-               release_chan(bc);
-       }
-       break;
+
     
        /***************************/
        /** Suplementary Services **/
        /***************************/
        case EVENT_RETRIEVE:
        {
+               ch=find_holded(cl_te, bc);
+               if (!ch) {
+                       ast_log(LOG_WARNING, "Found no Holded channel, cannot Retrieve\n");
+                       misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
+                       break;
+               }
                struct ast_channel *hold_ast=AST_BRIDGED_P(ch->ast);
                ch->state = MISDN_CONNECTED;
                
@@ -3297,34 +3936,77 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                misdn_cfg_get( bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
                
                if (!hold_allowed) {
-                       chan_misdn_log(0, bc->port, "Hold not allowed on port:%d\n", bc->port);
+
+                       chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
                        misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
                        break;
                }
 
+#if 0
                {
                        struct chan_list *holded_ch=find_holded(cl_te, bc);
                        if (holded_ch) {
                                misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
-                               chan_misdn_log(0, bc->port, "We can't use RETRIEVE at the moment due to mISDN bug!\n");
+
+                               chan_misdn_log(-1, bc->port, "We can't use RETRIEVE at the moment due to mISDN bug!\n");
                                break;
                        }
                }
+#endif
+               struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
                
-               if (AST_BRIDGED_P(ch->ast)){
+               if (bridged){
+                       struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged);
                        ch->state = MISDN_HOLDED;
                        ch->l3id = bc->l3_id;
                        
-                       ast_moh_start(AST_BRIDGED_P(ch->ast), NULL);
+                       bc->holded_bc=bridged_ch->bc;
                        misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
+
+                       ast_moh_start(bridged, NULL);
                } else {
                        misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
                        chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
                }
        } 
        break;
+       
+       case EVENT_FACILITY:
+               print_facility(bc);
+               
+               switch (bc->fac_type) {
+               case FACILITY_CALLDEFLECT:
+               {
+                       struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
+                       struct chan_list *ch;
+                       
+                       if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
+                               ch=MISDN_ASTERISK_TECH_PVT(bridged);
+                               /*ch->state=MISDN_FACILITY_DEFLECTED;*/
+                               if (ch->bc) {
+                                       /* todo */
+                               }
+                               
+                       }
+                       
+               } 
+               
+               break;
+               default:
+                       chan_misdn_log(1, bc->port," --> not yet handled\n");
+               }
+               
+               break;
+
+       case EVENT_RESTART:
+
+               stop_bc_tones(ch);
+               release_chan(bc);
+               
+               break;
+                               
        default:
-               ast_log(LOG_WARNING, "Got Unknown Event\n");
+               ast_log(LOG_NOTICE, "Got Unknown Event\n");
                break;
        }
        
@@ -3341,13 +4023,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
  *******************************************/
 
 
-int clearl3_true ( void ) {
-       int default_clearl3;
-       misdn_cfg_get( 0, MISDN_GEN_CLEAR_L3, &default_clearl3, sizeof(int));
-       return default_clearl3;
-}
-
-int g_config_initialized=0;
+static int g_config_initialized=0;
 
 int load_module(void)
 {
@@ -3359,7 +4035,7 @@ int load_module(void)
        
        if (max_ports<=0) {
                ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
-               return -1;
+               return 0;
        }
        
        
@@ -3374,16 +4050,17 @@ int load_module(void)
 
        
        {
-               char tempbuf[BUFFERSIZE];
+               char tempbuf[BUFFERSIZE+1];
                misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
                if (strlen(tempbuf))
                        tracing = 1;
        }
 
        ast_mutex_init(&cl_te_lock);
-       ast_mutex_init(&release_lock_mutex);
 
+       misdn_cfg_update_ptp();
        misdn_cfg_get_ports_string(ports);
+               
        if (strlen(ports))
                chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports);
        
@@ -3391,16 +4068,25 @@ int load_module(void)
                struct misdn_lib_iface iface = {
                        .cb_event = cb_events,
                        .cb_log = chan_misdn_log,
-                       .cb_clearl3_true = clearl3_true
+                       .cb_jb_empty = chan_misdn_jb_empty,
                };
                if (misdn_lib_init(ports, &iface, NULL))
                        chan_misdn_log(0, 0, "No te ports initialized\n");
+       
+               int ntflags=0;
+               char ntfile[BUFFERSIZE+1];
+
+               misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(int));
+               misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFILE, &ntfile, BUFFERSIZE);
+
+               misdn_lib_nt_debug_init(ntflags,ntfile);
+
        }
 
 
        {
                if (ast_channel_register(&misdn_tech)) {
-                       ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
+                       ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
                        unload_module();
                        return -1;
                }
@@ -3418,17 +4104,30 @@ int load_module(void)
        ast_cli_register(&cli_show_port);
        ast_cli_register(&cli_show_stacks);
 
+       ast_cli_register(&cli_port_block);
+       ast_cli_register(&cli_port_unblock);
        ast_cli_register(&cli_restart_port);
        ast_cli_register(&cli_port_up);
+       ast_cli_register(&cli_port_down);
        ast_cli_register(&cli_set_debug);
        ast_cli_register(&cli_set_crypt_debug);
        ast_cli_register(&cli_reload);
 
   
-       ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_flags",
+       ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
                                 "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
                                 "Sets mISDN opts. and optargs\n"
                                 "\n"
+                                "The available options are:\n"
+                                "    d - Send display text on called phone, text is the optparam\n"
+                                "    n - don't detect dtmf tones on called channel\n"
+                                "    h - make digital outgoing call\n" 
+                                "    c - make crypted outgoing call, param is keyindex\n"
+                                "    e - perform echo cancelation on this channel,\n"
+                                "        takes taps as arguments (32,64,128,256)\n"
+                                "    s - send Non Inband DTMF as inband\n"
+                                "   vr - rxgain control\n"
+                                "   vt - txgain control\n"
                );
 
        
@@ -3439,9 +4138,11 @@ int load_module(void)
                                 "Supported Facilities are:\n"
                                 "\n"
                                 "type=calldeflect args=Nr where to deflect\n"
-                                "\n"
                );
-  
+
+
+       misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
+
        chan_misdn_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
 
        return 0;
@@ -3469,8 +4170,11 @@ int unload_module(void)
        ast_cli_unregister(&cli_show_config);
        ast_cli_unregister(&cli_show_port);
        ast_cli_unregister(&cli_show_stacks);
+       ast_cli_unregister(&cli_port_block);
+       ast_cli_unregister(&cli_port_unblock);
        ast_cli_unregister(&cli_restart_port);
        ast_cli_unregister(&cli_port_up);
+       ast_cli_unregister(&cli_port_down);
        ast_cli_unregister(&cli_set_debug);
        ast_cli_unregister(&cli_set_crypt_debug);
        ast_cli_unregister(&cli_reload);
@@ -3480,6 +4184,7 @@ int unload_module(void)
   
        ast_channel_unregister(&misdn_tech);
 
+
        free_robin_list();
        misdn_cfg_destroy();
        misdn_lib_destroy();
@@ -3492,6 +4197,13 @@ int unload_module(void)
        return 0;
 }
 
+int reload(void)
+{
+       reload_config();
+
+       return 0;
+}
+
 int usecount(void)
 {
        int res;
@@ -3511,102 +4223,7 @@ char *key(void)
        return ASTERISK_GPL_KEY;
 }
 
-void chan_misdn_log(int level, int port, char *tmpl, ...)
-{
-       if (! ((0 <= port) && (port <= max_ports))) {
-               ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
-               return;
-       }
-               
-       va_list ap;
-       char buf[1024];
-  
-       va_start(ap, tmpl);
-       vsnprintf( buf, 1023, tmpl, ap );
-       va_end(ap);
-       
-       if (misdn_debug_only[port] ? (level==1 && misdn_debug[port]) || (level==misdn_debug[port]) : level <= misdn_debug[port]) {
-               ast_console_puts(buf);
-       }
-       
-       if (level <= misdn_debug[0] && tracing) {
-               time_t tm = time(NULL);
-               char *tmp=ctime(&tm),*p;
-               char file[BUFFERSIZE];
-               misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, file, BUFFERSIZE);
-               FILE *fp= fopen(file, "a+");
-
-               p=strchr(tmp,'\n');
-               if (p) *p=':';
-    
-               if (!fp) {
-                       ast_console_puts("Error opening Tracefile: ");
-                       ast_console_puts(strerror(errno));
-                       ast_console_puts("\n");
-                       return ;
-               }
-               
-               fputs(tmp,fp);
-               fputs(" ", fp);
-               fputs(buf, fp);
-
-               fclose(fp);
-       }
-}
-
-
-void chan_misdn_trace_call(struct ast_channel *chan, int debug, char *tmpl, ...)
-{
-       va_list ap;
-       char buf[1024];
-       char name[1024];
-
-       int trace;
-       misdn_cfg_get( 0, MISDN_GEN_TRACE_CALLS, &trace, sizeof(int));
-       if (!trace) return ;
-       
-       if (misdn_debug[0] < debug) return ; 
-       
-       char tracedir[BUFFERSIZE];
-       misdn_cfg_get( 0, MISDN_GEN_TRACE_DIR, tracedir, BUFFERSIZE);
-       sprintf(name,"%s/%s.%s",tracedir, chan->uniqueid, chan->cid.cid_num );
-       
-       va_start(ap, tmpl);
-       
-       vsprintf( buf, tmpl, ap );
-       
-       va_end(ap);
-       
-       time_t tm = time(NULL);
-       char *tmp=ctime(&tm),*p;
-       FILE *fp= fopen(name, "a");
-       int fd;
-       
-       if (!fp) {
-               ast_console_puts("Error opening Tracefile");
-               ast_console_puts(strerror(errno));
-               ast_console_puts("\n");
-               return ;
-       }
-       
-       fd=fileno(fp) ;
-       
-       flock(fd, LOCK_EX);
-       
-       p=strchr(tmp,'\n');
-       if (p) *p=':';
-       
-       
-       
-       fputs(tmp,fp);
-       fputs(" ", fp);
-       fputs(buf, fp);
 
-       flock(fd, LOCK_UN);
-       
-       fclose(fp);
-       
-}
 
 
 /*** SOME APPS ;)***/
@@ -3615,9 +4232,10 @@ static int misdn_facility_exec(struct ast_channel *chan, void *data)
 {
        struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
        char *tok, *tokb;
-       
 
-       if (strcasecmp(MISDN_ASTERISK_TYPE(chan),"mISDN")) {
+       chan_misdn_log(0,0,"TYPE: %s\n",chan->tech->type);
+       
+       if (strcasecmp(chan->tech->type,"mISDN")) {
                ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
                return -1;
        }
@@ -3659,8 +4277,9 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
        int  keyidx=0;
        int rxgain=0;
        int txgain=0;
-
-       if (strcasecmp(MISDN_ASTERISK_TYPE(chan),"mISDN")) {
+       int change_jitter=0;
+       
+       if (strcasecmp(chan->tech->type,"mISDN")) {
                ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
                return -1;
        }
@@ -3683,7 +4302,7 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
                switch(tok[0]) {
                        
                case 'd' :
-                       strncpy(ch->bc->display,++tok,84);
+                       ast_copy_string(ch->bc->display,++tok,84);
                        chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n",ch->bc->display);
                        break;
                        
@@ -3693,8 +4312,32 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
                        break;
 
                case 'j':
-                       chan_misdn_log(1, ch->bc->port, "SETOPT: No jitter\n");
-                       ch->bc->nojitter=1;
+                       chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
+                       tok++;
+                       change_jitter=1;
+                       
+                       switch ( tok[0] ) {
+                       case 'b' :
+                               ch->jb_len=atoi(++tok);
+                               chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n",ch->jb_len);
+                               break;
+                       case 't' :
+                               ch->jb_upper_threshold=atoi(++tok);
+                               chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n",ch->jb_upper_threshold);
+                               break;
+
+                       case 'n':
+                               ch->bc->nojitter=1;
+                               chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
+                               break;
+                               
+                       default:
+                               ch->jb_len=4000;
+                               ch->jb_upper_threshold=0;
+                               chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n",ch->jb_len);
+                               chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n",ch->jb_upper_threshold);
+                       }
+                       
                        break;
       
                case 'v':
@@ -3727,10 +4370,9 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
                        }
       
                        {
-                               int l = sizeof(ch->bc->crypt_key);
-                               strncpy(ch->bc->crypt_key, misdn_key_vector[keyidx], l);
-                               ch->bc->crypt_key[l-1] = 0;
+                               ast_copy_string(ch->bc->crypt_key,  misdn_key_vector[keyidx], sizeof(ch->bc->crypt_key));
                        }
+                       
                        chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n",misdn_key_vector[keyidx]);
                        break;
 
@@ -3738,7 +4380,9 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
                        chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
                        
                        if (neglect) {
+                               chan_misdn_log(1, ch->bc->port, " --> disabled\n");
                                ch->bc->ec_enable=0;
+
                        } else {
                                ch->bc->ec_enable=1;
                                ch->bc->orig=ch->orginator;
@@ -3752,18 +4396,12 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
       
                case 'h':
                        chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
+                       
                        if (strlen(tok) > 1 && tok[1]=='1') {
-                               chan_misdn_log(1, ch->bc->port, "SETOPT: Digital TRANS_DIGITAL\n");
-                               ch->bc->async=1;
-                               ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
-                               /*ch->bc->state=STATE_CONNECTED;
-                                 misdn_lib_setup_bc(ch->bc);*/
-                       } else {
-                               ch->bc->async=0;
-                               ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
-                               /*ch->bc->state=STATE_CONNECTED;
-                                 misdn_lib_setup_bc(ch->bc);*/
-                       }
+                               chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
+                               ch->bc->hdlc=1;
+                       }  
+                       ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
                        break;
             
                case 's':
@@ -3798,6 +4436,10 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
                        break;
                }
        }
+
+       if (change_jitter)
+               config_jitterbuffer(ch);
+       
        
        if (ch->faxdetect || ch->ast_dsp) {
                
@@ -3816,3 +4458,246 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
 }
 
 
+int chan_misdn_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;
+}
+
+
+
+/*******************************************************/
+/***************** JITTERBUFFER ************************/
+/*******************************************************/
+
+
+/* allocates the jb-structure and initialise the elements*/
+struct misdn_jb *misdn_jb_init(int size, int upper_threshold)
+{
+    int i;
+    struct misdn_jb *jb = (struct misdn_jb*) malloc(sizeof(struct misdn_jb));
+    jb->size = size;
+    jb->upper_threshold = upper_threshold;
+    jb->wp = 0;
+    jb->rp = 0;
+    jb->state_full = 0;
+    jb->state_empty = 0;
+    jb->bytes_wrote = 0;
+    jb->samples = (char *)malloc(size*sizeof(char));
+
+    if (!jb->samples) {
+           chan_misdn_log(-1,0,"No free Mem for jb->samples\n");
+           return NULL;
+    }
+    
+    jb->ok = (char *)malloc(size*sizeof(char));
+
+    if (!jb->ok) {
+           chan_misdn_log(-1,0,"No free Mem for jb->ok\n");
+           return NULL;
+    }
+
+    for(i=0; i<size; i++)
+       jb->ok[i]=0;
+
+    ast_mutex_init(&jb->mutexjb);
+
+    return jb;
+}
+
+/* frees the data and destroys the given jitterbuffer struct */
+void misdn_jb_destroy(struct misdn_jb *jb)
+{
+       ast_mutex_destroy(&jb->mutexjb);
+       
+       free(jb->samples);
+       free(jb);
+}
+
+/* fills the jitterbuffer with len data returns < 0 if there was an
+   error (bufferoverflow). */
+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->mutexjb);
+    
+    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;
+    chan_misdn_log(9,0,"misdn_jb_fill: written:%d | Bufferstatus:%d p:%x\n",len,jb->state_buffer,jb);
+    
+    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->mutexjb);
+       
+       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->mutexjb);
+    
+    return 0;
+}
+
+/* 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)
+{
+    int i, wp, rp, read=0;
+
+    ast_mutex_lock (&jb->mutexjb);
+
+    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->mutexjb);
+               
+               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;
+       chan_misdn_log(9,0,"misdn_jb_empty: read:%d | Bufferstatus:%d p:%x\n",len,jb->state_buffer,jb);
+       
+       jb->rp=rp;
+    }
+    else
+           chan_misdn_log(9,0,"misdn_jb_empty: Wait...requested:%d p:%x\n",len,jb);
+    
+    ast_mutex_unlock (&jb->mutexjb);
+
+    return read;
+}
+
+
+
+
+/*******************************************************/
+/*************** JITTERBUFFER  END *********************/
+/*******************************************************/
+
+
+
+
+void chan_misdn_log(int level, int port, char *tmpl, ...)
+{
+       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;
+       }
+               
+       va_list ap;
+       char buf[1024];
+       char port_buf[8];
+       sprintf(port_buf,"P[%2d] ",port);
+       
+       va_start(ap, tmpl);
+       vsnprintf( buf, 1023, 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(global_tracefile) ) {
+               time_t tm = time(NULL);
+               char *tmp=ctime(&tm),*p;
+               
+               FILE *fp= fopen(global_tracefile, "a+");
+               
+               p=strchr(tmp,'\n');
+               if (p) *p=':';
+               
+               if (!fp) {
+                       ast_console_puts("Error opening Tracefile: [ ");
+                       ast_console_puts(global_tracefile);
+                       ast_console_puts(" ] ");
+                       
+                       ast_console_puts(strerror(errno));
+                       ast_console_puts("\n");
+                       return ;
+               }
+               
+               fputs(tmp,fp);
+               fputs(" ", fp);
+               fputs(port_buf,fp);
+               fputs(" ", fp);
+               fputs(buf, fp);
+
+               fclose(fp);
+       }
+}
+
+
diff --git a/channels/chan_misdn_config.c b/channels/chan_misdn_config.c
deleted file mode 100644 (file)
index 2659871..0000000
+++ /dev/null
@@ -1,1083 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- * 
- * Copyright (C) 2005, Christian Richter
- *
- * Christian Richter <crich@beronet.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- *
- */
-
-/*!
- * \file
- *
- * \brief chan_misdn configuration management
- * \author Christian Richter <crich@beronet.com>
- *
- * \ingroup channel_drivers
- */
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "chan_misdn_config.h"
-
-#include <asterisk/config.h>
-#include <asterisk/channel.h>
-#include <asterisk/logger.h>
-#include <asterisk/lock.h>
-#include <asterisk/strings.h>
-
-#include <asterisk/utils.h>
-#define AST_LOAD_CFG ast_config_load
-#define AST_DESTROY_CFG ast_config_destroy
-
-#define DEF_ECHOCANCEL 128
-#define DEF_ECHOTRAINING 1
-
-struct msn_list {
-       char *msn;
-       struct msn_list *next;
-};
-
-struct port_config {
-       char *name;
-       int *rxgain;
-       int *txgain;
-       int *te_choose_channel;
-       char *context;
-       char *language;
-       char *callerid;
-       char *method;
-       int *dialplan;
-       int *localdialplan; 
-       char *nationalprefix;
-       char *internationalprefix;
-       int *pres;
-       int *always_immediate;
-       int *immediate;
-       int *hold_allowed;
-       int *early_bconnect;
-       int *use_callingpres;
-       int *echocancel;
-       int *echocancelwhenbridged;
-       int *echotraining;
-       struct msn_list *msn_list;
-       ast_group_t *callgroup;         /* Call group */
-       ast_group_t *pickupgroup;       /* Pickup group */
-};
-
-struct general_config {
-       int *debug;
-       char *tracefile;
-       int *trace_calls;
-       char *trace_dir;
-       int *bridging;
-       int *stop_tone_after_first_digit;
-       int *append_digits2exten;
-       int *l1_info_ok;
-       int *clear_l3;
-       int *dynamic_crypt;
-       char *crypt_prefix;
-       char *crypt_keys;
-};
-
-/* array of port configs, default is at position 0. */
-static struct port_config **port_cfg;
-/* max number of available ports, is set on init */
-static int max_ports;
-/* general config */
-static struct general_config *general_cfg;
-/* storing the ptp flag separated to save memory */
-static int *ptp;
-
-static ast_mutex_t config_mutex; 
-
-
-static inline void misdn_cfg_lock (void) {
-       ast_mutex_lock(&config_mutex);
-}
-
-static inline void misdn_cfg_unlock (void) {
-       ast_mutex_unlock(&config_mutex);
-}
-
-static void free_msn_list (struct msn_list* iter) {
-       if (iter->next)
-               free_msn_list(iter->next);
-       if (iter->msn)
-               free(iter->msn);
-       free(iter);
-}
-
-static void free_port_cfg (void) {
-
-       struct port_config **free_list = (struct port_config **)calloc(max_ports + 1, sizeof(struct port_config *));
-
-       int i, j;
-
-       for (i = 0; i < max_ports; i++) {
-               if (port_cfg[i]) {
-                       for (j = 0; j < max_ports && free_list[j]; j++) {
-                               if (free_list[j] && free_list[j] == port_cfg[i])
-                                       continue; /* already in list */
-                               free_list[j] = port_cfg[i];
-                       }
-               }
-       }
-
-#define FREE_ELEM(elem) ({ \
-               if (free_list[i]->elem) \
-                       free(free_list[i]->elem); \
-       })
-       
-       for (i = 0; i < max_ports; i++) {
-               if (free_list[i]) {
-                       FREE_ELEM(name);
-                       FREE_ELEM(rxgain);
-                       FREE_ELEM(txgain);
-                       FREE_ELEM(te_choose_channel);
-                       FREE_ELEM(context);
-                       FREE_ELEM(language);
-                       FREE_ELEM(callerid);
-                       FREE_ELEM(method);
-                       FREE_ELEM(dialplan);
-                       FREE_ELEM(localdialplan);
-                       FREE_ELEM(nationalprefix);
-                       FREE_ELEM(internationalprefix);
-                       FREE_ELEM(pres);
-                       FREE_ELEM(always_immediate);
-                       FREE_ELEM(immediate);
-                       FREE_ELEM(hold_allowed);
-                       FREE_ELEM(early_bconnect);
-                       FREE_ELEM(use_callingpres);
-                       FREE_ELEM(echocancel);
-                       FREE_ELEM(echocancelwhenbridged);
-                       FREE_ELEM(echotraining);
-                       if (free_list[i]->msn_list)
-                               free_msn_list(free_list[i]->msn_list);
-                       FREE_ELEM(callgroup);
-                       FREE_ELEM(pickupgroup);
-                       free(free_list[i]);
-               }
-       }
-       free(free_list);
-}
-
-static void free_general_cfg (void) {
-
-#define FREE_GEN_ELEM(elem) ({ \
-               if (general_cfg->elem) \
-                       free(general_cfg->elem); \
-       })
-       
-       FREE_GEN_ELEM(debug);
-       FREE_GEN_ELEM(tracefile);
-       FREE_GEN_ELEM(trace_calls);
-       FREE_GEN_ELEM(trace_dir);
-       FREE_GEN_ELEM(bridging);
-       FREE_GEN_ELEM(stop_tone_after_first_digit);
-       FREE_GEN_ELEM(append_digits2exten);
-       FREE_GEN_ELEM(l1_info_ok);
-       FREE_GEN_ELEM(clear_l3);
-       FREE_GEN_ELEM(dynamic_crypt);
-       FREE_GEN_ELEM(crypt_prefix);
-       FREE_GEN_ELEM(crypt_keys);
-}
-
-#define GET_PORTCFG_STRCPY(item) ({ \
-               char *temp; \
-               if (port_cfg[port] && port_cfg[port]->item) \
-                       temp = port_cfg[port]->item; \
-               else \
-                       temp = port_cfg[0]->item; \
-               if (!temp || !memccpy((void *)buf, (void *)temp, '\0', bufsize)) \
-                       memset(buf, 0, 1); \
-       })
-
-#define GET_GENCFG_STRCPY(item) ({ \
-               if (general_cfg && general_cfg->item) { \
-                       if (!memccpy((void *)buf, (void *)general_cfg->item, '\0', bufsize)) \
-                               memset(buf, 0, 1); \
-               } else \
-                       memset(buf, 0, 1); \
-       })
-
-#define GET_PORTCFG_MEMCPY(item) ({ \
-               typeof(port_cfg[0]->item) temp; \
-               if (port_cfg[port] && port_cfg[port]->item) \
-                       temp = port_cfg[port]->item; \
-               else \
-                       temp = port_cfg[0]->item; \
-               if (temp) { \
-                       int l = sizeof(*temp); \
-                       if (l > bufsize) \
-                               memset(buf, 0, bufsize); \
-                       else \
-                               memcpy(buf, temp, l); \
-               } else \
-                       memset(buf, 0, bufsize); \
-       })
-
-#define GET_GENCFG_MEMCPY(item) ({ \
-               if (general_cfg && general_cfg->item) { \
-                       typeof(general_cfg->item) temp = general_cfg->item; \
-                       int l = sizeof(*temp); \
-                       if (l > bufsize) \
-                               memset(buf, 0, bufsize); \
-                       else \
-                               memcpy(buf, temp, l); \
-               } else \
-                       memset(buf, 0, bufsize); \
-       })
-
-void misdn_cfg_get(int port, enum misdn_cfg_elements elem, void *buf, int bufsize) {
-       
-       if (!(elem > MISDN_GEN_FIRST) && !misdn_cfg_is_port_valid(port)) {
-               memset(buf, 0, bufsize);
-               ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Port number %d is not valid.\n", port);
-               return;
-       }
-
-       misdn_cfg_lock();
-       
-       switch (elem) {
-               
-               /* port config elements */
-                       
-               case MISDN_CFG_PTP:             if (sizeof(ptp[port]) <= bufsize)
-                                                       memcpy(buf, &ptp[port], sizeof(ptp[port]));
-                                               else
-                                                       buf = 0; /* error, should not happen */
-                                               break;
-               case MISDN_CFG_GROUPNAME:       GET_PORTCFG_STRCPY(name);
-                                               break;
-               case MISDN_CFG_RXGAIN:          GET_PORTCFG_MEMCPY(rxgain);
-                                               break;
-               case MISDN_CFG_TXGAIN:          GET_PORTCFG_MEMCPY(txgain);
-                                               break;
-               case MISDN_CFG_TE_CHOOSE_CHANNEL:
-                                               GET_PORTCFG_MEMCPY(te_choose_channel);
-                                               break;
-               case MISDN_CFG_CONTEXT:         GET_PORTCFG_STRCPY(context);
-                                               break;
-               case MISDN_CFG_LANGUAGE:        GET_PORTCFG_STRCPY(language);
-                                               break;
-               case MISDN_CFG_CALLERID:        GET_PORTCFG_STRCPY(callerid);
-                                               break;
-               case MISDN_CFG_METHOD:          GET_PORTCFG_STRCPY(method);
-                                               break;
-               case MISDN_CFG_DIALPLAN:        GET_PORTCFG_MEMCPY(dialplan);
-                                               break;
-       case MISDN_CFG_LOCALDIALPLAN:   GET_PORTCFG_MEMCPY(localdialplan);
-               break;
-               case MISDN_CFG_NATPREFIX:       GET_PORTCFG_STRCPY(nationalprefix);
-                                               break;
-               case MISDN_CFG_INTERNATPREFIX:
-                                               GET_PORTCFG_STRCPY(internationalprefix);
-                                               break;
-               case MISDN_CFG_PRES:            GET_PORTCFG_MEMCPY(pres);
-                                               break;
-               case MISDN_CFG_ALWAYS_IMMEDIATE:
-                                               GET_PORTCFG_MEMCPY(always_immediate);
-                                               break;
-               case MISDN_CFG_IMMEDIATE:       GET_PORTCFG_MEMCPY(immediate);
-                                               break;
-               case MISDN_CFG_HOLD_ALLOWED:
-                                               GET_PORTCFG_MEMCPY(hold_allowed);
-                                               break;
-               case MISDN_CFG_EARLY_BCONNECT:
-                                               GET_PORTCFG_MEMCPY(early_bconnect);
-                                               break;
-               case MISDN_CFG_USE_CALLINGPRES:
-                                               GET_PORTCFG_MEMCPY(use_callingpres);
-                                               break;
-               case MISDN_CFG_ECHOCANCEL:
-                                               GET_PORTCFG_MEMCPY(echocancel );
-                                               break;
-               case MISDN_CFG_ECHOCANCELWHENBRIDGED:
-                                               GET_PORTCFG_MEMCPY(echocancelwhenbridged);
-                                               break;
-               case MISDN_CFG_ECHOTRAINING:
-                                               GET_PORTCFG_MEMCPY(echotraining);
-                                               break;
-               case MISDN_CFG_CALLGROUP:       GET_PORTCFG_MEMCPY(callgroup);
-                                               break;
-               case MISDN_CFG_PICKUPGROUP:     GET_PORTCFG_MEMCPY(pickupgroup);
-                                               break;
-               
-               /* general config elements */
-                       
-               case MISDN_GEN_DEBUG:           GET_GENCFG_MEMCPY(debug);
-                                               break;
-               case MISDN_GEN_TRACEFILE:       GET_GENCFG_STRCPY(tracefile);
-                                               break;
-               case MISDN_GEN_TRACE_CALLS: GET_GENCFG_MEMCPY(trace_calls);
-                                               break;
-               case MISDN_GEN_TRACE_DIR:       GET_GENCFG_STRCPY(trace_dir);
-                                               break;
-               case MISDN_GEN_BRIDGING:        GET_GENCFG_MEMCPY(bridging);
-                                               break;
-               case MISDN_GEN_STOP_TONE:       GET_GENCFG_MEMCPY(stop_tone_after_first_digit);
-                                               break;
-               case MISDN_GEN_APPEND_DIGITS2EXTEN: 
-                                               GET_GENCFG_MEMCPY(append_digits2exten);
-                                               break;
-               case MISDN_GEN_L1_INFO_OK:      GET_GENCFG_MEMCPY(l1_info_ok);
-                                               break;
-               case MISDN_GEN_CLEAR_L3:        GET_GENCFG_MEMCPY(clear_l3);
-                                               break;
-               case MISDN_GEN_DYNAMIC_CRYPT:   GET_GENCFG_MEMCPY(dynamic_crypt);
-                                               break;
-               case MISDN_GEN_CRYPT_PREFIX:    GET_GENCFG_STRCPY(crypt_prefix);
-                                               break;
-               case MISDN_GEN_CRYPT_KEYS:      GET_GENCFG_STRCPY(crypt_keys);
-                                               break;
-               default:                        memset(buf, 0, bufsize);
-       }
-       
-       misdn_cfg_unlock();
-}
-
-int misdn_cfg_is_msn_valid (int port, char* msn) {
-       
-       if (!misdn_cfg_is_port_valid(port)) {
-               ast_log(LOG_WARNING, "Invalid call to misdn_cfg_is_msn_valid! Port number %d is not valid.\n", port);
-               return 0;
-       }
-       
-       struct msn_list *iter;
-       
-       misdn_cfg_lock();
-       
-       if (port_cfg[port]->msn_list)
-               iter = port_cfg[port]->msn_list;
-       else
-               iter = port_cfg[0]->msn_list;
-       for (; iter; iter = iter->next) 
-               if (*(iter->msn) == '*' || !strcasecmp(iter->msn, msn)) {
-                       misdn_cfg_unlock();
-                       return 1;
-               }
-       
-       misdn_cfg_unlock();
-       
-       return 0;
-}
-
-int misdn_cfg_is_port_valid (int port) {
-       
-       misdn_cfg_lock();
-       
-       if (port < 1 || port > max_ports) {
-               misdn_cfg_unlock();
-               return 0;
-       }
-
-       int valid = (port_cfg[port] != NULL);
-
-       misdn_cfg_unlock();
-
-       return valid;
-}
-
-int misdn_cfg_is_group_method (char *group, enum misdn_cfg_method meth) {
-
-       int i, re = 0;
-       char *method = NULL;
-
-       misdn_cfg_lock();
-       
-       for (i = 0; i < max_ports; i++) {
-               if (port_cfg[i]) {
-                       if (!strcasecmp(port_cfg[i]->name, group))
-                               method = port_cfg[i]->method ? port_cfg[i]->method : port_cfg[0]->method;
-               }
-       }
-
-       if (method) {
-               switch (meth) {
-               case METHOD_STANDARD:           re = !strcasecmp(method, "standard");
-                                                                       break;
-               case METHOD_ROUND_ROBIN:        re = !strcasecmp(method, "round_robin");
-                                                                       break;
-               }
-       }
-
-       misdn_cfg_unlock();
-
-       return re;
-}
-
-void misdn_cfg_get_ports_string (char *ports) {
-       *ports = 0;
-       char tmp[16];
-       int l;
-       
-       misdn_cfg_lock();
-
-       int i = 1;
-       for (; i <= max_ports; i++) {
-               if (port_cfg[i]) {
-                       if (ptp[i])
-                               sprintf(tmp, "%dptp,", i);
-                       else
-                               sprintf(tmp, "%d,", i);
-                       strcat(ports, tmp);
-               }
-       }
-       
-       misdn_cfg_unlock();
-
-       if ((l = strlen(ports)))
-               ports[l-1] = 0;
-}
-
-#define GET_CFG_STRING(typestr, type) ({ \
-               if (port_cfg[port] && port_cfg[port]->type) \
-                       snprintf(buf, bufsize, "%s " #typestr ": %s", begin, port_cfg[port]->type); \
-               else \
-                       snprintf(buf, bufsize, "%s " #typestr ": %s", begin, port_cfg[0]->type); \
-       }) \
-
-#define GET_GEN_STRING(typestr, type) ({ \
-               snprintf(buf, bufsize, "%s " #typestr ": %s", begin, general_cfg->type ? general_cfg->type : "not set"); \
-       }) \
-
-#define GET_CFG_INT(typestr, type) ({ \
-               if (port_cfg[port] && port_cfg[port]->type) \
-                       snprintf(buf, bufsize, "%s " #typestr ": %d", begin, *port_cfg[port]->type); \
-               else \
-                       snprintf(buf, bufsize, "%s " #typestr ": %d", begin, *port_cfg[0]->type); \
-       }) \
-
-#define GET_GEN_INT(typestr, type) ({ \
-               snprintf(buf, bufsize, "%s " #typestr ": %d", begin, general_cfg->type ? *general_cfg->type : 0); \
-       }) \
-
-#define GET_CFG_BOOL(typestr, type, yes, no) ({ \
-               int bool; \
-               if (port_cfg[port] && port_cfg[port]->type) \
-                       bool = *port_cfg[port]->type; \
-               else \
-                       bool = *port_cfg[0]->type; \
-               snprintf(buf, bufsize, "%s " #typestr ": %s", begin, bool ? #yes : #no); \
-       }) \
-
-#define GET_CFG_HYBRID(typestr, type, yes, no) ({ \
-               int bool; \
-               if (port_cfg[port] && port_cfg[port]->type) \
-                       bool = *port_cfg[port]->type; \
-               else \
-                       bool = *port_cfg[0]->type; \
-               if (bool == 1 || bool == 0) \
-                       snprintf(buf, bufsize, "%s " #typestr ": %s", begin, bool ? #yes : #no); \
-               else \
-                       snprintf(buf, bufsize, "%s " #typestr ": %d", begin, bool); \
-       }) \
-
-#define GET_GEN_BOOL(typestr, type, yes, no) ({ \
-               snprintf(buf, bufsize, "%s " #typestr ": %s", begin, general_cfg->type ? (*general_cfg->type ? #yes : #no) : "not set"); \
-       }) \
-
-#define GET_CFG_AST_GROUP_T(typestr, type) ({ \
-               ast_group_t *tmp; \
-               if (port_cfg[port] && port_cfg[port]->type) \
-                       tmp = port_cfg[port]->type; \
-               else \
-                       tmp = port_cfg[0]->type; \
-               if (tmp) { \
-                       char tmpbuf[256]; \
-                       snprintf(buf, bufsize, "%s " #typestr ": %s", begin, ast_print_group(tmpbuf, sizeof(tmpbuf), *tmp)); \
-               } else \
-                       snprintf(buf, bufsize, "%s " #typestr ": %s", begin, "none"); \
-       }) \
-
-void misdn_cfg_get_config_string(int port, enum misdn_cfg_elements elem, char* buf, int bufsize) {
-
-       if (!(elem > MISDN_GEN_FIRST) && !misdn_cfg_is_port_valid(port)) {
-               *buf = 0;
-               ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Port number %d is not valid.\n", port);
-               return;
-       }
-       
-       char begin[] = " -> ";
-       
-       misdn_cfg_lock();
-       
-       switch (elem) {
-               
-               case MISDN_CFG_PTP:             snprintf(buf, bufsize, "%s PTP: %s", begin, ptp[port] ? "yes" : "no");
-                                                                       break;
-               case MISDN_CFG_GROUPNAME:       GET_CFG_STRING(GROUPNAME, name);
-                                                                       break;
-               case MISDN_CFG_RXGAIN:          GET_CFG_INT(RXGAIN, rxgain);
-                                                                       break;
-               case MISDN_CFG_TXGAIN:          GET_CFG_INT(TXGAIN, txgain);
-                                                                       break;
-               case MISDN_CFG_TE_CHOOSE_CHANNEL:
-                                               GET_CFG_BOOL(TE_CHOOSE_CHANNEL, te_choose_channel, yes, no);
-                                                                       break;
-               case MISDN_CFG_CONTEXT:         GET_CFG_STRING(CONTEXT, context);
-                                                                       break;
-               case MISDN_CFG_LANGUAGE:        GET_CFG_STRING(LANGUAGE, language);
-                                                                       break;
-               case MISDN_CFG_CALLERID:        GET_CFG_STRING(CALLERID, callerid);
-                                                                       break;
-               case MISDN_CFG_METHOD:          GET_CFG_STRING(METHOD, method);
-                                                                       break;
-               case MISDN_CFG_DIALPLAN:        GET_CFG_INT(DIALPLAN, dialplan);
-                                                                       break;
-       case MISDN_CFG_LOCALDIALPLAN:   GET_CFG_INT(LOCALDIALPLAN, localdialplan);
-               break;
-               case MISDN_CFG_NATPREFIX:       GET_CFG_STRING(NATIONALPREFIX, nationalprefix);
-                                                                       break;
-               case MISDN_CFG_INTERNATPREFIX:
-                                               GET_CFG_STRING(INTERNATIONALPREFIX, internationalprefix);
-                                                                       break;
-               case MISDN_CFG_PRES:            GET_CFG_BOOL(PRESENTATION, pres, allowed, not_screened);
-                                                                       break;
-               case MISDN_CFG_ALWAYS_IMMEDIATE:
-                                               GET_CFG_BOOL(ALWAYS_IMMEDIATE, always_immediate, yes, no);
-                                                                       break;
-               case MISDN_CFG_IMMEDIATE:       GET_CFG_BOOL(IMMEDIATE, immediate, yes, no);
-                                                                       break;
-               case MISDN_CFG_HOLD_ALLOWED:
-                                               GET_CFG_BOOL(HOLD_ALLOWED, hold_allowed, yes, no);
-                                                                       break;
-               case MISDN_CFG_EARLY_BCONNECT:
-                                               GET_CFG_BOOL(EARLY_BCONNECT, early_bconnect, yes, no);
-                                                                       break;
-               case MISDN_CFG_USE_CALLINGPRES:
-                                               GET_CFG_BOOL(USE_CALLINGPRES, use_callingpres, yes, no);
-                                                                       break;
-               case MISDN_CFG_ECHOCANCEL:      GET_CFG_HYBRID(ECHOCANCEL, echocancel, yes, no);
-                                                                       break;
-               case MISDN_CFG_ECHOCANCELWHENBRIDGED:
-                                               GET_CFG_BOOL(ECHOCANCELWHENBRIDGED, echocancelwhenbridged, yes, no);
-                                                                       break;
-               case MISDN_CFG_ECHOTRAINING:
-                                               GET_CFG_HYBRID(ECHOTRAINING, echotraining, yes, no);
-                                                                       break;
-               case MISDN_CFG_CALLGROUP:       GET_CFG_AST_GROUP_T(CALLINGGROUP, callgroup);
-                                                                       break;
-               case MISDN_CFG_PICKUPGROUP:     GET_CFG_AST_GROUP_T(PICKUPGROUP, pickupgroup);
-                                                                       break;
-               case MISDN_CFG_MSNS:            {
-                                                       char tmpbuffer[BUFFERSIZE];
-                                                       tmpbuffer[0] = 0;
-                                                       struct msn_list *iter;
-                                                       if (port_cfg[port]->msn_list)
-                                                               iter = port_cfg[port]->msn_list;
-                                                       else
-                                                               iter = port_cfg[0]->msn_list;
-                                                       if (iter) {
-                                                               for (; iter; iter = iter->next)
-                                                                       sprintf(tmpbuffer, "%s%s, ", tmpbuffer, iter->msn);
-                                                               tmpbuffer[strlen(tmpbuffer)-2] = 0;
-                                                       }
-                                                       snprintf(buf, bufsize, "%s MSNs: %s", begin, *tmpbuffer ? tmpbuffer : "none"); \
-                                               }
-                                               break;
-               
-               /* general config elements */
-               
-               case MISDN_GEN_DEBUG:           GET_GEN_INT(DEBUG_LEVEL, debug);
-                                                                       break;
-               case MISDN_GEN_TRACEFILE:       GET_GEN_STRING(TRACEFILE, tracefile);
-                                                                       break;
-               case MISDN_GEN_TRACE_CALLS: GET_GEN_BOOL(TRACE_CALLS, trace_calls, true, false);
-                                                                       break;
-               case MISDN_GEN_TRACE_DIR:       GET_GEN_STRING(TRACE_DIR, trace_dir);
-                                                                       break;
-               case MISDN_GEN_BRIDGING:        GET_GEN_BOOL(BRIDGING, bridging, yes, no);
-                                                                       break;
-               case MISDN_GEN_STOP_TONE:       GET_GEN_BOOL(STOP_TONE_AFTER_FIRST_DIGIT, stop_tone_after_first_digit, yes, no);
-                                                                       break;
-               case MISDN_GEN_APPEND_DIGITS2EXTEN: 
-                                               GET_GEN_BOOL(APPEND_DIGITS2EXTEN, append_digits2exten, yes, no);
-                                                                       break;
-               case MISDN_GEN_L1_INFO_OK:      GET_GEN_BOOL(L1_INFO_OK, l1_info_ok, yes, no);
-                                                                       break;
-               case MISDN_GEN_CLEAR_L3:        GET_GEN_BOOL(CLEAR_L3, clear_l3, yes, no);
-                                                                       break;
-               case MISDN_GEN_DYNAMIC_CRYPT:
-                                               GET_GEN_BOOL(DYNAMIC_CRYPT,dynamic_crypt, yes, no);
-                                                                       break;
-               case MISDN_GEN_CRYPT_PREFIX:
-                                               GET_GEN_STRING(CRYPT_PREFIX, crypt_prefix);
-                                                                       break;
-               case MISDN_GEN_CRYPT_KEYS:      GET_GEN_STRING(CRYPT_KEYS, crypt_keys);
-                                                                       break;
-                                                                       
-               default:                        *buf = 0;
-                                                                       break;
-       }
-
-       misdn_cfg_unlock();
-}
-
-int misdn_cfg_get_next_port (int port) {
-       
-       misdn_cfg_lock();
-       
-       for (port++; port <= max_ports; port++) {
-               if (port_cfg[port]) {
-                       misdn_cfg_unlock();
-                       return port;
-               }
-       }
-       
-       misdn_cfg_unlock();
-       
-       return -1;
-}
-
-int misdn_cfg_get_next_port_spin (int port) {
-
-       int ret = misdn_cfg_get_next_port(port);
-
-       if (ret > 0)
-               return ret;
-
-       return misdn_cfg_get_next_port(0);
-}
-
-#define PARSE_GEN_INT(item) ({ \
-               if (!strcasecmp(v->name, #item)) { \
-                       int temp; \
-                       if (!sscanf(v->value, "%d", &temp)) { \
-                               ast_log(LOG_WARNING, "Value \"%s\" for \"" #item "\" (generals section) invalid or out of range! Please edit your misdn.conf and then do a \"misdn reload\".\n", v->value); \
-                       } else { \
-                               general_cfg->item = (int *)malloc(sizeof(int)); \
-                               memcpy(general_cfg->item, &temp, sizeof(int)); \
-                       } \
-                       continue; \
-               } \
-       }) \
-
-#define PARSE_GEN_BOOL(item) ({ \
-               if (!strcasecmp(v->name, #item)) { \
-                       general_cfg->item = (int *)malloc(sizeof(int)); \
-                       *(general_cfg->item) = ast_true(v->value)?1:0; \
-                       continue; \
-               } \
-       })
-
-#define PARSE_GEN_STR(item) ({ \
-               if (!strcasecmp(v->name, #item)) { \
-                       int l = strlen(v->value); \
-                       if (l) { \
-                               general_cfg->item = (char *)calloc(l+1, sizeof(char)); \
-                               strncpy(general_cfg->item,v->value, l); \
-                       } \
-                       continue; \
-               } \
-       })
-
-static void build_general_config(struct ast_variable *v) {
-
-       if (!v) 
-               return;
-
-       for (; v; v = v->next) {
-
-               PARSE_GEN_INT(debug);
-               PARSE_GEN_STR(tracefile);
-               PARSE_GEN_BOOL(trace_calls);
-               PARSE_GEN_STR(trace_dir);
-               PARSE_GEN_BOOL(bridging);
-               PARSE_GEN_BOOL(stop_tone_after_first_digit);
-               PARSE_GEN_BOOL(append_digits2exten);
-               PARSE_GEN_BOOL(l1_info_ok);
-               PARSE_GEN_BOOL(clear_l3);
-               PARSE_GEN_BOOL(dynamic_crypt);
-               PARSE_GEN_STR(crypt_prefix);
-               PARSE_GEN_STR(crypt_keys);
-               
-       }
-}
-
-#define PARSE_CFG_HYBRID(item, def) ({ \
-               if (!strcasecmp(v->name, #item)) { \
-                       new->item = (int *)malloc(sizeof(int)); \
-                       if (!sscanf(v->value, "%d", new->item)) { \
-                               if (ast_true(v->value)) \
-                                       *new->item = def; \
-                               else \
-                                       *new->item = 0; \
-                       } \
-                       continue; \
-               } \
-       }) \
-
-#define PARSE_CFG_INT(item) ({ \
-               if (!strcasecmp(v->name, #item)) { \
-                       new->item = (int *)malloc(sizeof(int)); \
-                       if (!sscanf(v->value, "%d", new->item)) { \
-                               ast_log(LOG_WARNING, "Value \"%s\" for \"" #item "\" of group \"%s\" invalid or out of range! Please edit your misdn.conf and then do a \"misdn reload\".\n", v->value, cat); \
-                               free(new->item); \
-                               new->item = NULL; \
-                       } \
-                       continue; \
-               } \
-       }) \
-
-#define PARSE_CFG_BOOL(item) ({ \
-               if (!strcasecmp(v->name, #item)) { \
-                       new->item = (int *)malloc(sizeof(int)); \
-                       *(new->item) = ast_true(v->value)?1:0; \
-                       continue; \
-               } \
-       })
-
-#define PARSE_CFG_STR(item) ({ \
-               if (!strcasecmp(v->name, #item)) { \
-                       int l = strlen(v->value); \
-                       if (l) { \
-                               new->item = (char *)calloc(l+1, sizeof(char)); \
-                               strncpy(new->item,v->value,l); \
-                       } \
-                       continue; \
-               } \
-       })
-
-static void build_port_config(struct ast_variable *v, char *cat) {
-       if (!v || !cat)
-               return;
-
-       int cfg_for_ports[max_ports + 1];
-       int i = 0;
-       for (; i < (max_ports + 1); i++) {
-               cfg_for_ports[i] = 0;
-       }
-       
-       /* we store the default config at position 0 */
-       if (!strcasecmp(cat, "default")) {
-               cfg_for_ports[0] = 1;
-       }
-
-       struct port_config* new = (struct port_config *)calloc(1, sizeof(struct port_config));
-       
-       {
-               int l = strlen(cat);
-               new->name = (char *)calloc(l+1, sizeof(char));
-               strncpy(new->name, cat, l);
-       }
-       
-       for (; v; v=v->next) {
-               if (!strcasecmp(v->name, "ports")) {
-                       /* TODO check for value not beeing set, like PORTS= */
-                       char *iter;
-                       char *value = v->value;
-                       while ((iter = strchr(value, ',')) != NULL) {
-                               *iter = 0;
-                               /* strip spaces */
-                               while (*value && *value == ' ') {
-                                       value++;
-                               }
-                               /* TODO check for char not 0-9 */
-
-                               if (*value){
-                                       int p = atoi(value);
-                                       if (p <= max_ports && p > 0) {
-                                               cfg_for_ports[p] = 1;
-                                               if (strstr(value, "ptp"))
-                                                       ptp[p] = 1;
-                                       } else
-                                               ast_log(LOG_WARNING, "Port value \"%s\" of group %s invalid or out of range! Please edit your misdn.conf and then do a \"misdn reload\".\n", value, cat);
-                                       value = ++iter;
-                               }
-                       }
-                       /* the remaining or the only one */
-                       /* strip spaces */
-                       while (*value && *value == ' ') {
-                               value++;
-                       }
-                       /* TODO check for char not 0-9 */
-                       if (*value) {
-                               int p = atoi(value);
-                               if (p <= max_ports && p > 0) {
-                                       cfg_for_ports[p] = 1;
-                                       if (strstr(value, "ptp"))
-                                               ptp[p] = 1;
-                               } else
-                                       ast_log(LOG_WARNING, "Port value \"%s\" of group %s invalid or out of range! Please edit your misdn.conf and then do a \"misdn reload\".\n", value, cat);
-                       }
-                       continue;
-               }
-               PARSE_CFG_STR(context);
-               PARSE_CFG_INT(dialplan);
-               PARSE_CFG_INT(localdialplan);
-               PARSE_CFG_STR(nationalprefix);
-               PARSE_CFG_STR(internationalprefix);
-               PARSE_CFG_STR(language);
-               if (!strcasecmp(v->name, "presentation")) {
-                       if (v->value && strlen(v->value)) {
-                               new->pres = (int *)malloc(sizeof(int));
-                               if (!strcasecmp(v->value, "allowed")) {
-                                       *(new->pres) = 1;
-                               }
-                               /* TODO: i assume if it is not "allowed", it is "not_screened" */
-                               else {
-                                       *(new->pres) = 0;
-                               }
-                       }
-                       continue;
-               }
-               PARSE_CFG_INT(rxgain);
-               PARSE_CFG_INT(txgain);
-               PARSE_CFG_BOOL(te_choose_channel);
-               PARSE_CFG_BOOL(immediate);
-               PARSE_CFG_BOOL(always_immediate);
-               PARSE_CFG_BOOL(hold_allowed);
-               PARSE_CFG_BOOL(early_bconnect);
-               PARSE_CFG_BOOL(use_callingpres);
-               PARSE_CFG_HYBRID(echocancel, DEF_ECHOCANCEL);
-               PARSE_CFG_BOOL(echocancelwhenbridged);
-               PARSE_CFG_HYBRID(echotraining, DEF_ECHOTRAINING);
-               PARSE_CFG_STR(callerid);
-               PARSE_CFG_STR(method);
-               if (!strcasecmp(v->name, "msns")) {
-                       /* TODO check for value not beeing set, like msns= */
-                       char *iter;
-                       char *value = v->value;
-
-                       while ((iter = strchr(value, ',')) != NULL) {
-                               *iter = 0;
-                               /* strip spaces */
-                               while (*value && *value == ' ') {
-                                       value++;
-                               }
-                               /* TODO check for char not 0-9 */
-                               if (*value){
-                                       int l = strlen(value);
-                                       if (l) {
-                                               struct msn_list *ml = (struct msn_list *)calloc(1, sizeof(struct msn_list));
-                                               ml->msn = (char *)calloc(l+1, sizeof(char));
-                                               strncpy(ml->msn,value,l);
-                                               ml->next = new->msn_list;
-                                               new->msn_list = ml;
-                                       }
-                                       value = ++iter;
-                               }
-                       }
-                       /* the remaining or the only one */
-                       /* strip spaces */
-                       while (*value && *value == ' ') {
-                               value++;
-                       }
-                       /* TODO check for char not 0-9 */
-                       if (*value) {
-                               int l = strlen(value);
-                               if (l) {
-                                       struct msn_list *ml = (struct msn_list *)calloc(1, sizeof(struct msn_list));
-                                       ml->msn = (char *)calloc(l+1, sizeof(char));
-                                       strncpy(ml->msn,value,l);
-                                       ml->next = new->msn_list;
-                                       new->msn_list = ml;
-                               }
-                       }
-                       continue;
-               }
-               if (!strcasecmp(v->name, "callgroup")) {
-                       new->callgroup = (ast_group_t *)malloc(sizeof(ast_group_t));
-                       *(new->callgroup)=ast_get_group(v->value);
-                       continue;
-               }
-               if (!strcasecmp(v->name, "pickupgroup")) {
-                       new->pickupgroup = (ast_group_t *)malloc(sizeof(ast_group_t));
-                       *(new->pickupgroup)=ast_get_group(v->value);
-                       continue;
-               }
-       }
-       /* store the new config in our array of port configs */
-       for (i = 0; i < (max_ports + 1); i++) {
-               if (cfg_for_ports[i])
-                       port_cfg[i] = new;
-       }
-}
-
-
-static void fill_defaults (void) {
-       
-       /* general defaults */
-       if (!general_cfg->debug)
-               general_cfg->debug = (int*)calloc(1, sizeof(int));
-       if (!general_cfg->trace_calls)
-               general_cfg->trace_calls = (int*)calloc(1, sizeof(int));
-       if (!general_cfg->trace_dir) {
-               general_cfg->trace_dir = (char *)malloc(10 * sizeof(char));
-               sprintf(general_cfg->trace_dir, "/var/log/");
-       }
-       if (!general_cfg->bridging) {
-               general_cfg->bridging = (int*)malloc(sizeof(int));
-               *general_cfg->bridging = 1;
-       }
-       if (!general_cfg->stop_tone_after_first_digit) {
-               general_cfg->stop_tone_after_first_digit = (int*)malloc(sizeof(int));
-               *general_cfg->stop_tone_after_first_digit = 1;
-       }
-       if (!general_cfg->append_digits2exten) {
-               general_cfg->append_digits2exten = (int*)malloc(sizeof(int));
-               *general_cfg->append_digits2exten = 1;
-       }
-       if (!general_cfg->l1_info_ok) {
-               general_cfg->l1_info_ok = (int*)malloc(sizeof(int));
-               *general_cfg->l1_info_ok = 1;
-       }
-       if (!general_cfg->clear_l3)
-               general_cfg->clear_l3 =(int*)calloc(1, sizeof(int));
-       if (!general_cfg->dynamic_crypt)
-               general_cfg->dynamic_crypt = (int*)calloc(1, sizeof(int));
-
-       /* defaults for default port config */
-       if (!port_cfg[0])
-               port_cfg[0] = (struct port_config*)calloc(1, sizeof(struct port_config));
-       if (!port_cfg[0]->name) {
-               port_cfg[0]->name = (char *)malloc(8 * sizeof(char));
-               sprintf(port_cfg[0]->name, "default");
-       }
-       if (!port_cfg[0]->rxgain)
-               port_cfg[0]->rxgain = (int *)calloc(1, sizeof(int));
-       if (!port_cfg[0]->txgain)
-               port_cfg[0]->txgain = (int *)calloc(1, sizeof(int));
-       if (!port_cfg[0]->te_choose_channel)
-               port_cfg[0]->te_choose_channel = (int *)calloc(1, sizeof(int));
-       if (!port_cfg[0]->context) {
-               port_cfg[0]->context = (char *)malloc(8 * sizeof(char));
-               sprintf(port_cfg[0]->context, "default");
-       }
-       if (!port_cfg[0]->language) {
-               port_cfg[0]->language = (char *)malloc(3 * sizeof(char));
-               sprintf(port_cfg[0]->language, "en");
-       }
-       if (!port_cfg[0]->callerid)
-               port_cfg[0]->callerid = (char *)calloc(1, sizeof(char));
-       if (!port_cfg[0]->method) {
-               port_cfg[0]->method = (char *)malloc(9 * sizeof(char));
-               sprintf(port_cfg[0]->method, "standard");
-       }
-       if (!port_cfg[0]->dialplan)
-               port_cfg[0]->dialplan = (int *)calloc(1, sizeof(int));
-       if (!port_cfg[0]->localdialplan)
-               port_cfg[0]->localdialplan = (int *)calloc(1, sizeof(int));
-       if (!port_cfg[0]->nationalprefix) {
-               port_cfg[0]->nationalprefix = (char *)malloc(2 * sizeof(char));
-               sprintf(port_cfg[0]->nationalprefix, "0");
-       }
-       if (!port_cfg[0]->internationalprefix) {
-               port_cfg[0]->internationalprefix = (char *)malloc(3 * sizeof(char));
-               sprintf(port_cfg[0]->internationalprefix, "00");
-       }
-       if (!port_cfg[0]->pres) {
-               port_cfg[0]->pres = (int *)malloc(sizeof(int));
-               *port_cfg[0]->pres = 1;
-       }
-       if (!port_cfg[0]->always_immediate)
-               port_cfg[0]->always_immediate = (int *)calloc(1, sizeof(int));
-       if (!port_cfg[0]->immediate)
-               port_cfg[0]->immediate = (int *)calloc(1, sizeof(int));
-       if (!port_cfg[0]->hold_allowed)
-               port_cfg[0]->hold_allowed = (int *)calloc(1, sizeof(int));
-       if (!port_cfg[0]->early_bconnect) {
-               port_cfg[0]->early_bconnect = (int *)malloc(sizeof(int));
-               *port_cfg[0]->early_bconnect = 1;
-       }
-       if (!port_cfg[0]->echocancel)
-               port_cfg[0]->echocancel=(int *)calloc(1, sizeof(int));
-       if (!port_cfg[0]->echocancelwhenbridged)
-               port_cfg[0]->echocancelwhenbridged=(int *)calloc(1, sizeof(int));
-       if (!port_cfg[0]->echotraining) {
-               port_cfg[0]->echotraining=(int *)malloc(sizeof(int));
-               *port_cfg[0]->echotraining = 1;
-       }
-       if (!port_cfg[0]->use_callingpres) {
-               port_cfg[0]->use_callingpres = (int *)malloc(sizeof(int));
-               *port_cfg[0]->use_callingpres = 1;
-       }
-       if (!port_cfg[0]->msn_list) {
-               port_cfg[0]->msn_list = (struct msn_list *)malloc(sizeof(struct msn_list));
-               port_cfg[0]->msn_list->next = NULL;
-               port_cfg[0]->msn_list->msn = (char *)calloc(2, sizeof(char));
-               *(port_cfg[0]->msn_list->msn) = '*';
-       }
-}
-
-void misdn_cfg_reload (void) {
-       misdn_cfg_init (0);
-}
-
-void misdn_cfg_destroy (void) {
-
-       misdn_cfg_lock();
-       
-       free_port_cfg();
-       free_general_cfg();
-       
-       free(port_cfg);
-       free(general_cfg);
-       free(ptp);
-
-       misdn_cfg_unlock();
-       ast_mutex_destroy(&config_mutex);
-}
-
-void misdn_cfg_init (int this_max_ports)
-{
-       char config[]="misdn.conf";
-       
-       struct ast_config *cfg;
-       cfg = AST_LOAD_CFG(config);
-       if (!cfg) {
-               ast_log(LOG_WARNING,"no misdn.conf ?\n");
-               return;
-       }
-
-       misdn_cfg_lock();
-       
-       if (this_max_ports) {
-               /* this is the first run */
-               max_ports = this_max_ports;
-               port_cfg = (struct port_config **)calloc(max_ports + 1, sizeof(struct port_config *));
-               general_cfg = (struct general_config*)calloc(1, sizeof(struct general_config));
-               ptp = (int *)calloc(max_ports + 1, sizeof(int));
-       }
-       else {
-               free_port_cfg();
-               free_general_cfg();
-               port_cfg = memset(port_cfg, 0, sizeof(struct port_config *) * (max_ports + 1));
-               general_cfg = memset(general_cfg, 0, sizeof(struct general_config));
-               ptp = memset(ptp, 0, sizeof(int) * (max_ports + 1));
-       }
-       
-       char *cat;
-       cat = ast_category_browse(cfg, NULL);
-
-       while(cat) {
-               struct ast_variable *v=ast_variable_browse(cfg,cat);
-               if (!strcasecmp(cat,"general")) {
-                       build_general_config (v);
-               } else {
-                       build_port_config (v, cat);
-               }
-               cat=ast_category_browse(cfg,cat);
-       }
-
-       fill_defaults();
-       
-       misdn_cfg_unlock();
-       
-       AST_DESTROY_CFG(cfg);
-}
index e0e18cf8559c2768508290be49a8e7634b1634c0..1374e75e36636154da3a5e3591d19b98b986c07e 100644 (file)
@@ -5,10 +5,13 @@
 #
 
 # Verify those options with main Makefile
-CFLAGS         += -pipe -c -DMISDNUSER_JOLLY
+CFLAGS         = -pipe -c -Wall -ggdb
+ifeq ($(shell uname -m),x86_64)
+CFLAGS         += -fPIC
+endif
 SOURCES                = isdn_lib.c isdn_msg_parser.c 
 OBJDIR         = .
-OBJS           = isdn_lib.o isdn_msg_parser.o
+OBJS           = isdn_lib.o isdn_msg_parser.o fac.o
 
 
 all: chan_misdn_lib.a 
@@ -16,57 +19,24 @@ all: chan_misdn_lib.a
 
 %.o: %.c
        $(CC) $(CFLAGS) -o $@ $<
-
+       
 
 chan_misdn_lib.a:      $(OBJS)
        ar crv $@ $(OBJS)
 
-misdn: test_preempt
-       if [ ! -d lib ] ; then \
-               mkdir lib; \
-               cd lib ; \
-               wget http://isdn.jolly.de/download/v3.1/mISDN_for_PBX4Linux-3.0.tar.gz ;\
-               tar xzf mISDN_for_PBX4Linux-3.0.tar.gz; \
-               wget http://isdn.jolly.de/download/v3.1/mISDNuser_for_PBX4Linux-3.0.tar.gz ;\
-               tar xzf mISDNuser_for_PBX4Linux-3.0.tar.gz ;\
-               cd mISDN; patch -p1 <../../mISDN.patch; \
-               cd ../mISDNuser ; patch -p1 <../../mISDNuser.patch; \
-       fi
+misdn:
+       @mkdir -p lib
+       cd lib ; cvs -d:pserver:anonymous:readonly@cvs.isdn4linux.de:/i4ldev co  mISDN mISDNuser ; 
        cd lib/mISDN ; make install
        cd lib/mISDNuser ; make install
 
-LINUX=/lib/modules/$(uname -r)/build
-GCCVERSION=$(shell $(CC) --version  | grep GCC  | cut -d " " -f 3  | cut -d "." -f 1)
-
-test_preempt:
-       @if  grep 'CONFIG_DEBUG_SPINLOCK=y' $(LINUX)/.config   ; then \
-               echo -e "\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!\nDisable the DEBUG_SPINLOCK Setting in your Kernel Config.\n with this option set, mISDN will not work! \n\n" ;\
-               read ; \
-               exit 1 ; \
-       fi
-       @if  grep 'CONFIG_DEBUG_SPINLOCK_SLEEP=y' $(LINUX)/.config   ; then \
-               echo -e "\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!\nDisable the DEBUG_SPINLOCK_SLEEP Setting in your Kernel Config.\n with this option set, mISDN will not work! \n\n" ;\
-               read ; \
-               exit 1 ; \
-       fi
-       @if  grep 'CONFIG_SMP=y' $(LINUX)/.config   ; then \
-               echo -e "\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!\nDisable the SMP Setting in your Kernel Config.\n\n" ; \
-               read ; \
-               exit 1 ; \
-       fi
-       @if test "$(GCCVERSION)" -gt 3 ; then \
-               echo -e "\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!\nYou're using GCC 4! Please downgrade to gcc-3.x and type:\nexport CC=gcc-3.x\nbefore issuing make again.\nyou won't have success with gcc-4!\n\n" ; \
-               read ; \
-               exit 1 ; \
-       fi
-
-
-
+portinfo: portinfo.o
+       $(CC) -L/usr/lib -o $@ $^ -lisdnnet -lmISDN -lpthread
+       
+       
 FORCE:
 
 clean: 
        rm -rf *.a *.o *.so
-
-misdn_clean:
        rm -rf lib
-
+       rm -rf portinfo
index 250a74e5434ab24517d91749992324927cf3abf3..58fca2c8b3affc23e50e24fdc3a7475cdef0e98c 100644 (file)
@@ -22,47 +22,58 @@ enum misdn_cfg_elements {
 
        /* port config items */
        MISDN_CFG_FIRST = 0,
-       MISDN_CFG_PTP,                 /* int (bool) */
        MISDN_CFG_GROUPNAME,           /* char[] */
+       MISDN_CFG_ALLOWED_BEARERS,           /* char[] */
+       MISDN_CFG_FAR_ALERTING,        /* int (bool) */
        MISDN_CFG_RXGAIN,              /* int */
        MISDN_CFG_TXGAIN,              /* int */
        MISDN_CFG_TE_CHOOSE_CHANNEL,   /* int (bool) */
+       MISDN_CFG_PMP_L1_CHECK,        /* int (bool) */
+       MISDN_CFG_ALARM_BLOCK,        /* int (bool) */
+       MISDN_CFG_HDLC,                /* int (bool) */
        MISDN_CFG_CONTEXT,             /* char[] */
        MISDN_CFG_LANGUAGE,            /* char[] */
+       MISDN_CFG_MUSICCLASS,            /* char[] */
        MISDN_CFG_CALLERID,            /* char[] */
        MISDN_CFG_METHOD,              /* char[] */
        MISDN_CFG_DIALPLAN,            /* int */
        MISDN_CFG_LOCALDIALPLAN,       /* int */
+       MISDN_CFG_CPNDIALPLAN,       /* int */
        MISDN_CFG_NATPREFIX,           /* char[] */
        MISDN_CFG_INTERNATPREFIX,      /* char[] */
-       MISDN_CFG_PRES,                /* int (bool) */
+       MISDN_CFG_PRES,                /* int */
+       MISDN_CFG_SCREEN,              /* int */
        MISDN_CFG_ALWAYS_IMMEDIATE,    /* int (bool) */
+       MISDN_CFG_NODIALTONE,    /* int (bool) */
        MISDN_CFG_IMMEDIATE,           /* int (bool) */
+       MISDN_CFG_SENDDTMF,           /* int (bool) */
        MISDN_CFG_HOLD_ALLOWED,        /* int (bool) */
        MISDN_CFG_EARLY_BCONNECT,      /* int (bool) */
-       MISDN_CFG_USE_CALLINGPRES,     /* int (bool) */
+       MISDN_CFG_INCOMING_EARLY_AUDIO,      /* int (bool) */
        MISDN_CFG_ECHOCANCEL,          /* int */
        MISDN_CFG_ECHOCANCELWHENBRIDGED,  /* int (bool) */
-       MISDN_CFG_ECHOTRAINING,        /* int (bool) */
+       MISDN_CFG_NEED_MORE_INFOS,     /* bool */
+       MISDN_CFG_JITTERBUFFER,              /* int */
+       MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD,              /* int */
        MISDN_CFG_CALLGROUP,           /* ast_group_t */
        MISDN_CFG_PICKUPGROUP,         /* ast_group_t */
        MISDN_CFG_MSNS,                /* char[] */
+       MISDN_CFG_PTP,                 /* int (bool) */
        MISDN_CFG_LAST,
        
        /* general config items */
        MISDN_GEN_FIRST,
+       MISDN_GEN_MISDN_INIT,           /* char[] */
        MISDN_GEN_DEBUG,               /* int */
        MISDN_GEN_TRACEFILE,           /* char[] */
-       MISDN_GEN_TRACE_CALLS,         /* int (bool) */
-       MISDN_GEN_TRACE_DIR,           /* char[] */
        MISDN_GEN_BRIDGING,            /* int (bool) */
        MISDN_GEN_STOP_TONE,           /* int (bool) */
        MISDN_GEN_APPEND_DIGITS2EXTEN, /* int (bool) */
-       MISDN_GEN_L1_INFO_OK,          /* int (bool) */
-       MISDN_GEN_CLEAR_L3,            /* int (bool) */
        MISDN_GEN_DYNAMIC_CRYPT,       /* int (bool) */
        MISDN_GEN_CRYPT_PREFIX,        /* char[] */
        MISDN_GEN_CRYPT_KEYS,          /* char[] */
+       MISDN_GEN_NTDEBUGFLAGS,          /* int */
+       MISDN_GEN_NTDEBUGFILE,          /* char[] */
        MISDN_GEN_LAST
 };
 
@@ -76,6 +87,8 @@ void misdn_cfg_init(int max_ports);
 void misdn_cfg_reload(void);
 void misdn_cfg_destroy(void);
 
+void misdn_cfg_update_ptp( void );
+
 /* if you requst a general config element, the port value is ignored. if the requested 
  * value is not available, or the buffer is too small, the buffer will be nulled (in 
  * case of a char* only its first byte will be nulled). */
diff --git a/channels/misdn/fac.c b/channels/misdn/fac.c
new file mode 100644 (file)
index 0000000..383a60f
--- /dev/null
@@ -0,0 +1,313 @@
+
+#include "isdn_lib_intern.h"
+#include "isdn_lib.h"
+
+#include "string.h"
+
+
+
+
+#define CENTREX_ID      0xa1
+#define CALLDEFLECT_ID      0xa1
+
+/**
+   This file covers the encoding and decoding of facility messages and
+   facility information elements.
+
+   There will be 2 Functions as Interface:
+   
+   fac_enc( char **ntmsg, msg_t * msg, enum facility_type type,  union facility fac, struct misdn_bchannel *bc)
+   fac_dec( unsigned char *p, Q931_info_t *qi, enum facility_type *type,  union facility *fac, struct misdn_bchannel *bc);
+
+   Those will either read the union facility or fill it.
+
+   internally, we will have deconding and encoding functions for each facility
+   IE.
+   
+**/
+
+
+/* support stuff */
+static void strnncpy(unsigned char *dest, unsigned char *src, int len, int dst_len)
+{
+       if (len > dst_len-1)
+               len = dst_len-1;
+       strncpy((char *)dest, (char *)src, len);
+       dest[len] = '\0';
+}
+
+
+
+
+/**********************/
+/*** FACILITY STUFF ***/
+/**********************/
+
+
+/* IE_FACILITY */
+void enc_ie_facility(unsigned char **ntmode, msg_t *msg, unsigned char *facility, int facility_len, int nt, struct misdn_bchannel *bc)
+{
+       unsigned char *p;
+       Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
+       int l;
+
+
+       if (!facility || facility_len<=0)
+       {
+               return;
+       }
+
+       
+       l = facility_len;
+       p = msg_put(msg, l+2);
+       if (nt)
+               *ntmode = p+1;
+       else
+               qi->QI_ELEMENT(facility) = p - (unsigned char *)qi - sizeof(Q931_info_t);
+       p[0] = IE_FACILITY;
+       p[1] = l;
+       memcpy(p+2, facility, facility_len);
+}
+
+
+/* facility for siemens CENTEX (known parts implemented only) */
+void enc_ie_facility_centrex(unsigned char **ntmode, msg_t *msg, unsigned char *cnip, int setup, int nt, struct misdn_bchannel *bc)
+{
+       unsigned char centrex[256];
+       int i = 0;
+
+       if (!cnip)
+               return;
+
+       /* centrex facility */
+       centrex[i++] = FACILITY_CENTREX;
+       centrex[i++] = CENTREX_ID;
+
+       /* cnip */
+       if (strlen((char *)cnip) > 15)
+       {
+/*             if (options.deb & DEBUG_PORT) */
+               cb_log(1,0,"%s: CNIP/CONP text too long (max 13 chars), cutting.\n", __FUNCTION__);
+               cnip[15] = '\0';
+       }
+       /*  dunno what the 8 bytes mean */
+       if (setup)
+       {
+               centrex[i++] = 0x17;
+               centrex[i++] = 0x02;
+               centrex[i++] = 0x02;
+               centrex[i++] = 0x44;
+               centrex[i++] = 0x18;
+               centrex[i++] = 0x02;
+               centrex[i++] = 0x01;
+               centrex[i++] = 0x09;
+       } else
+       {
+               centrex[i++] = 0x18;
+               centrex[i++] = 0x02;
+               centrex[i++] = 0x02;
+               centrex[i++] = 0x81;
+               centrex[i++] = 0x09;
+               centrex[i++] = 0x02;
+               centrex[i++] = 0x01;
+               centrex[i++] = 0x0a;
+       }
+
+       centrex[i++] = 0x80;
+       centrex[i++] = strlen((char *)cnip);
+       strcpy((char *)(&centrex[i]), (char *)cnip);
+       i += strlen((char *)cnip);
+       cb_log(4,0,"    cnip='%s'\n", cnip);
+
+       /* encode facility */
+       enc_ie_facility(ntmode, msg, centrex, i, nt , bc);
+}
+
+void dec_ie_facility_centrex(unsigned char *p, Q931_info_t *qi, unsigned char *centrex, int facility_len, unsigned char *cnip, int cnip_len, int nt, struct misdn_bchannel *bc)
+{
+
+       int i = 0;
+       *cnip = '\0';
+       
+       if (facility_len >= 2)
+       {
+               if (centrex[i++] != FACILITY_CENTREX)
+                       return;
+               if (centrex[i++] != CENTREX_ID)
+                       return;
+       }
+
+       /* loop sub IEs of facility */
+       while(facility_len > i+1)
+       {
+               if (centrex[i+1]+i+1 > facility_len)
+               {
+                       printf("%s: ERROR: short read of centrex facility.\n", __FUNCTION__);
+                       return;
+               }
+               switch(centrex[i])
+               {
+               case 0x80:
+                       strnncpy(cnip, &centrex[i+2], centrex[i+1], cnip_len);
+                       cb_log(4,0,"    CENTREX cnip='%s'\n", cnip);
+                       break;
+               }
+               i += 1+centrex[i+1];
+       }
+}
+
+
+
+
+/* facility for CALL Deflect (known parts implemented only) */
+void enc_ie_facility_calldeflect(unsigned char **ntmode, msg_t *msg, unsigned char *nr, int nt, struct misdn_bchannel *bc)
+{
+       unsigned char fac[256];
+       
+       if (!nr)
+               return;
+
+       int len = strlen(nr);
+       /* calldeflect facility */
+       
+       /* cnip */
+       if (strlen((char *)nr) > 15)
+       {
+/*             if (options.deb & DEBUG_PORT) */
+               cb_log(1,0,"%s: NR text too long (max 13 chars), cutting.\n", __FUNCTION__);
+               nr[15] = '\0';
+       }
+       
+       fac[0]=FACILITY_CALLDEFLECT;    // ..
+       fac[1]=CALLDEFLECT_ID;
+       fac[2]=0x0f + len;      // strlen destination + 15 = 26
+       fac[3]=0x02;
+       fac[4]=0x01;
+       //fac[5]=0x70;
+       fac[5]=0x09;
+       fac[6]=0x02;
+       fac[7]=0x01;
+       fac[8]=0x0d;
+       fac[9]=0x30;
+       fac[10]=0x07 + len;     // strlen destination + 7 = 18
+       fac[11]=0x30;   // ...hm 0x30
+       fac[12]=0x02+ len;      // strlen destination + 2       
+       fac[13]=0x80;   // CLIP
+       fac[14]= len;   //  strlen destination 
+       
+       memcpy((unsigned char *)fac+15,nr,len);
+       fac[15+len]=0x01; //sending complete
+       fac[16+len]=0x01;
+       fac[17+len]=0x80;
+       
+       enc_ie_facility(ntmode, msg, fac, 17+len +1 , nt , bc);
+}
+
+
+void dec_ie_facility_calldeflect(unsigned char *p, Q931_info_t *qi, unsigned char *fac, int fac_len, unsigned char *cd_nr,  int nt, struct misdn_bchannel *bc)
+{
+       *cd_nr = '\0';
+       
+       if (fac_len >= 15)
+       {
+               if (fac[0] != FACILITY_CALLDEFLECT)
+                       return;
+               if (fac[1] != CALLDEFLECT_ID)
+                       return;
+       } else {
+               cb_log(1,bc->port, "IE too short: FAC_CALLDEFLECT\n");
+               return ;
+       }
+       
+       
+       
+       {
+               int dest_len=fac[2]-0x0f;
+               
+               if (dest_len <0 || dest_len > 15) {
+                       cb_log(1,bc->port, "IE is garbage: FAC_CALLDEFLECT\n");
+                       return ;
+               }
+               
+               if (fac_len < 15+dest_len) {
+                       cb_log(1,bc->port, "IE too short: FAC_CALLDEFLECT\n");
+                       return ;
+               }
+               
+               memcpy(cd_nr, &fac[15],dest_len);
+               cd_nr[dest_len]=0;
+               
+               cb_log(5,bc->port, "--> IE CALLDEFLECT NR: %s\n",cd_nr);
+       }
+}
+
+
+
+void fac_enc( unsigned char **ntmsg, msg_t * msg, enum facility_type type,  union facility fac, struct misdn_bchannel *bc)
+{
+       switch (type) {
+       case FACILITY_CENTREX:
+       {
+               int setup=0;
+               enc_ie_facility_centrex(ntmsg, msg, fac.cnip, setup, bc->nt, bc);
+       }
+               break;
+       case FACILITY_CALLDEFLECT:
+               enc_ie_facility_calldeflect(ntmsg, msg, fac.calldeflect_nr, bc->nt, bc);
+               break;
+       default:
+               cb_log(1,0,"Don't know how handle this facility: %d\n", type);
+       }
+}
+
+void fac_dec( unsigned char *p, Q931_info_t *qi, enum facility_type *type,  union facility *fac, struct misdn_bchannel *bc)
+{
+       int i, fac_len=0;
+       unsigned char facility[256];
+
+       if (!bc->nt)
+       {
+               p = NULL;
+               if (qi->QI_ELEMENT(facility))
+                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1;
+       }
+       if (!p)
+               return;
+       
+       fac_len = p[0] & 0xff;
+
+       memcpy(facility, p+1, fac_len);
+       
+       switch(facility[0]) {
+       case FACILITY_CENTREX:
+       {
+               int cnip_len=15;
+               
+               dec_ie_facility_centrex(p, qi,facility, fac_len, fac->cnip, cnip_len, bc->nt, bc);
+               
+               *type=FACILITY_CENTREX;
+       }
+       break;
+       case FACILITY_CALLDEFLECT:
+               dec_ie_facility_calldeflect(p, qi,facility, fac_len, fac->calldeflect_nr,  bc->nt, bc);
+               
+               *type=FACILITY_CALLDEFLECT;
+               break;
+       default:
+               cb_log(3, bc->port, "Unknown Facility received: ");
+               i = 0;
+               while(i < fac_len)
+               {
+                       cb_log(3, bc->port, " %02x", facility[i]);
+                       i++;
+               }
+               cb_log(3, bc->port, "    facility\n");
+               
+               *type=FACILITY_NONE;
+       }
+       
+       
+}
+
+/*** FACILITY END **/
+
diff --git a/channels/misdn/fac.h b/channels/misdn/fac.h
new file mode 100644 (file)
index 0000000..acc41f1
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef FAC_H
+#define FAC_H
+
+void fac_enc( unsigned char **ntmsg, msg_t * msg, enum facility_type type,  union facility fac, struct misdn_bchannel *bc);
+
+void fac_dec( unsigned char *p, Q931_info_t *qi, enum facility_type *type,  union facility *fac, struct misdn_bchannel *bc);
+
+#endif
index 4d1815f6523aef2299cea834ecfa292f22710692..a3eb255f86c92dd5998cba9384ad10f94e2fcd89 100644 (file)
 
 #include <string.h>
 
-
-#include "isdn_lib_intern.h"
-
 #include <mISDNuser/mISDNlib.h>
 #include <mISDNuser/isdn_net.h>
 #include <mISDNuser/l3dss1.h>
 #include <mISDNuser/net_l3.h>
 
 
-#define CENTREX_FAC     0x88
-#define CENTREX_ID      0xa1
 
 #define MISDN_IE_DEBG 0
 
@@ -69,7 +64,8 @@ void enc_ie_complete(unsigned char **ntmode, msg_t *msg, int complete, int nt, s
                {
                        *ntmode = p;
                } else
-                       qi->sending_complete = p - (unsigned char *)qi - sizeof(Q931_info_t);
+                       qi->QI_ELEMENT(sending_complete) = p - (unsigned char *)qi - sizeof(Q931_info_t);
+
                p[0] = IE_COMPLETE;
        }
 }
@@ -79,7 +75,7 @@ void dec_ie_complete(unsigned char *p, Q931_info_t *qi, int *complete, int nt, s
        *complete = 0;
        if (!nt)
        {
-               if (qi->sending_complete)
+               if (qi->QI_ELEMENT(sending_complete))
                        *complete = 1;
        } else
                if (p)
@@ -140,7 +136,7 @@ void enc_ie_bearer(unsigned char **ntmode, msg_t *msg, int coding, int capabilit
        if (nt)
                *ntmode = p+1;
        else
-               qi->bearer_capability = p - (unsigned char *)qi - sizeof(Q931_info_t);
+               qi->QI_ELEMENT(bearer_capability) = p - (unsigned char *)qi - sizeof(Q931_info_t);
        p[0] = IE_BEARER;
        p[1] = l;
        p[2] = 0x80 + (coding<<5) + capability;
@@ -166,23 +162,28 @@ void dec_ie_bearer(unsigned char *p, Q931_info_t *qi, int *coding, int *capabili
        *stopbits = -1;
        *dbits = -1;
        *parity = -1;
-
+       
        if (!nt)
        {
                p = NULL;
-               if (qi->llc)
-                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->llc + 1;
-               else if (qi->bearer_capability)
-                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->bearer_capability + 1;
+#ifdef LLC_SUPPORT
+               if (qi->QI_ELEMENT(llc)) {
+                       
+                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(llc) + 1;
+               }
+#endif
+               if (qi->QI_ELEMENT(bearer_capability))
+                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(bearer_capability) + 1;
        }
        if (!p)
                return;
+
        if (p[0] < 2)
        {
                printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
                return;
        }
-
+       
        *coding = (p[1]&0x60) >> 5;
        *capability = p[1] & 0x1f;
        octet = 2;
@@ -292,7 +293,7 @@ void enc_ie_call_id(unsigned char **ntmode, msg_t *msg, unsigned char *callid, i
        if (nt)
                *ntmode = p+1;
        else
-               qi->call_id = p - (unsigned char *)qi - sizeof(Q931_info_t);
+               qi->QI_ELEMENT(call_id) = p - (unsigned char *)qi - sizeof(Q931_info_t);
        p[0] = IE_CALL_ID;
        p[1] = l;
        memcpy(p+2, callid, callid_len);
@@ -308,8 +309,8 @@ void dec_ie_call_id(unsigned char *p, Q931_info_t *qi, unsigned char *callid, in
        if (!nt)
        {
                p = NULL;
-               if (qi->call_id)
-                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->call_id + 1;
+               if (qi->QI_ELEMENT(call_id))
+                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(call_id) + 1;
        }
        if (!p)
                return;
@@ -363,7 +364,7 @@ void enc_ie_called_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, un
        if (nt)
                *ntmode = p+1;
        else
-               qi->called_nr = p - (unsigned char *)qi - sizeof(Q931_info_t);
+               qi->QI_ELEMENT(called_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t);
        p[0] = IE_CALLED_PN;
        p[1] = l;
        p[2] = 0x80 + (type<<4) + plan;
@@ -379,8 +380,8 @@ void dec_ie_called_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, u
        if (!nt)
        {
                p = NULL;
-               if (qi->called_nr)
-                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->called_nr + 1;
+               if (qi->QI_ELEMENT(called_nr))
+                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(called_nr) + 1;
        }
        if (!p)
                return;
@@ -437,7 +438,7 @@ void enc_ie_calling_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, i
        if (nt)
                *ntmode = p+1;
        else
-               qi->calling_nr = p - (unsigned char *)qi - sizeof(Q931_info_t);
+               qi->QI_ELEMENT(calling_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t);
        p[0] = IE_CALLING_PN;
        p[1] = l;
        if (present >= 0)
@@ -465,8 +466,8 @@ void dec_ie_calling_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan,
        if (!nt)
        {
                p = NULL;
-               if (qi->calling_nr)
-                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->calling_nr + 1;
+               if (qi->QI_ELEMENT(calling_nr))
+                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(calling_nr) + 1;
        }
        if (!p)
                return;
@@ -539,7 +540,7 @@ void enc_ie_connected_pn(unsigned char **ntmode, msg_t *msg, int type, int plan,
        if (nt)
                *ntmode = p+1;
        else
-               qi->connected_nr = p - (unsigned char *)qi - sizeof(Q931_info_t);
+               qi->QI_ELEMENT(connected_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t);
        p[0] = IE_CONNECT_PN;
        p[1] = l;
        if (present >= 0)
@@ -567,8 +568,8 @@ void dec_ie_connected_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan
        if (!nt)
        {
                p = NULL;
-               if (qi->connected_nr)
-                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->connected_nr + 1;
+               if (qi->QI_ELEMENT(connected_nr))
+                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(connected_nr) + 1;
        }
        if (!p)
                return;
@@ -624,7 +625,7 @@ void enc_ie_cause(unsigned char **ntmode, msg_t *msg, int location, int cause, i
        if (nt)
                *ntmode = p+1;
        else
-               qi->cause = p - (unsigned char *)qi - sizeof(Q931_info_t);
+               qi->QI_ELEMENT(cause) = p - (unsigned char *)qi - sizeof(Q931_info_t);
        p[0] = IE_CAUSE;
        p[1] = l;
        p[2] = 0x80 + location;
@@ -637,7 +638,7 @@ void enc_ie_cause_standalone(unsigned char **ntmode, msg_t *msg, int location, i
        if (ntmode)
                *ntmode = p+1;
        else
-               qi->cause = p - (unsigned char *)qi - sizeof(Q931_info_t);
+               qi->QI_ELEMENT(cause) = p - (unsigned char *)qi - sizeof(Q931_info_t);
        p[0] = IE_CAUSE;
        p[1] = 2;
        p[2] = 0x80 + location;
@@ -653,8 +654,8 @@ void dec_ie_cause(unsigned char *p, Q931_info_t *qi, int *location, int *cause,
        if (!nt)
        {
                p = NULL;
-               if (qi->cause)
-                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->cause + 1;
+               if (qi->QI_ELEMENT(cause))
+                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(cause) + 1;
        }
        if (!p)
                return;
@@ -705,7 +706,7 @@ void enc_ie_channel_id(unsigned char **ntmode, msg_t *msg, int exclusive, int ch
                if (nt)
                        *ntmode = p+1;
                else
-                       qi->channel_id = p - (unsigned char *)qi - sizeof(Q931_info_t);
+                       qi->QI_ELEMENT(channel_id) = p - (unsigned char *)qi - sizeof(Q931_info_t);
                p[0] = IE_CHANNEL_ID;
                p[1] = l;
                if (channel == 0xff)
@@ -725,7 +726,7 @@ void enc_ie_channel_id(unsigned char **ntmode, msg_t *msg, int exclusive, int ch
                        if (nt)
                                *ntmode = p+1;
                        else
-                               qi->channel_id = p - (unsigned char *)qi - sizeof(Q931_info_t);
+                               qi->QI_ELEMENT(channel_id) = p - (unsigned char *)qi - sizeof(Q931_info_t);
                        p[0] = IE_CHANNEL_ID;
                        p[1] = l;
                        p[2] = 0x80 + 0x20 + 0x03;
@@ -737,7 +738,7 @@ void enc_ie_channel_id(unsigned char **ntmode, msg_t *msg, int exclusive, int ch
                if (nt)
                        *ntmode = p+1;
                else
-                       qi->channel_id = p - (unsigned char *)qi - sizeof(Q931_info_t);
+                       qi->QI_ELEMENT(channel_id) = p - (unsigned char *)qi - sizeof(Q931_info_t);
                p[0] = IE_CHANNEL_ID;
                p[1] = l;
                p[2] = 0x80 + 0x20 + (exclusive<<3) + 0x01;
@@ -758,8 +759,8 @@ void dec_ie_channel_id(unsigned char *p, Q931_info_t *qi, int *exclusive, int *c
        if (!nt)
        {
                p = NULL;
-               if (qi->channel_id)
-                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->channel_id + 1;
+               if (qi->QI_ELEMENT(channel_id))
+                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(channel_id) + 1;
        }
        if (!p)
                return;
@@ -863,7 +864,7 @@ void enc_ie_date(unsigned char **ntmode, msg_t *msg, time_t ti, int nt, struct m
        if (nt)
                *ntmode = p+1;
        else
-               qi->date = p - (unsigned char *)qi - sizeof(Q931_info_t);
+               qi->QI_ELEMENT(date) = p - (unsigned char *)qi - sizeof(Q931_info_t);
        p[0] = IE_DATE;
        p[1] = l;
        p[2] = tm->tm_year % 100;
@@ -900,7 +901,7 @@ void enc_ie_display(unsigned char **ntmode, msg_t *msg, unsigned char *display,
        if (nt)
                *ntmode = p+1;
        else
-               qi->display = p - (unsigned char *)qi - sizeof(Q931_info_t);
+               qi->QI_ELEMENT(display) = p - (unsigned char *)qi - sizeof(Q931_info_t);
        p[0] = IE_DISPLAY;
        p[1] = l;
        strncpy((char *)p+2, (char *)display, strlen((char *)display));
@@ -913,8 +914,8 @@ void dec_ie_display(unsigned char *p, Q931_info_t *qi, unsigned char *display, i
        if (!nt)
        {
                p = NULL;
-               if (qi->display)
-                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->display + 1;
+               if (qi->QI_ELEMENT(display))
+                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(display) + 1;
        }
        if (!p)
                return;
@@ -950,7 +951,7 @@ void enc_ie_keypad(unsigned char **ntmode, msg_t *msg, unsigned char *keypad, in
        if (nt)
                *ntmode = p+1;
        else
-               qi->keypad = p - (unsigned char *)qi - sizeof(Q931_info_t);
+               qi->QI_ELEMENT(keypad) = p - (unsigned char *)qi - sizeof(Q931_info_t);
        p[0] = IE_KEYPAD;
        p[1] = l;
        strncpy((char *)p+2, (char *)keypad, strlen((char *)keypad));
@@ -963,8 +964,8 @@ void dec_ie_keypad(unsigned char *p, Q931_info_t *qi, unsigned char *keypad, int
        if (!nt)
        {
                p = NULL;
-               if (qi->keypad)
-                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->keypad + 1;
+               if (qi->QI_ELEMENT(keypad))
+                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(keypad) + 1;
        }
        if (!p)
                return;
@@ -1000,7 +1001,7 @@ void enc_ie_notify(unsigned char **ntmode, msg_t *msg, int notify, int nt, struc
        if (nt)
                *ntmode = p+1;
        else
-               qi->notify = p - (unsigned char *)qi - sizeof(Q931_info_t);
+               qi->QI_ELEMENT(notify) = p - (unsigned char *)qi - sizeof(Q931_info_t);
        p[0] = IE_NOTIFY;
        p[1] = l;
        p[2] = 0x80 + notify;
@@ -1013,8 +1014,8 @@ void dec_ie_notify(unsigned char *p, Q931_info_t *qi, int *notify, int nt, struc
        if (!nt)
        {
                p = NULL;
-               if (qi->notify)
-                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->notify + 1;
+               if (qi->QI_ELEMENT(notify))
+                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(notify) + 1;
        }
        if (!p)
                return;
@@ -1060,7 +1061,7 @@ void enc_ie_progress(unsigned char **ntmode, msg_t *msg, int coding, int locatio
        if (nt)
                *ntmode = p+1;
        else
-               qi->progress = p - (unsigned char *)qi - sizeof(Q931_info_t);
+               qi->QI_ELEMENT(progress) = p - (unsigned char *)qi - sizeof(Q931_info_t);
        p[0] = IE_PROGRESS;
        p[1] = l;
        p[2] = 0x80 + (coding<<5) + location;
@@ -1077,8 +1078,8 @@ void dec_ie_progress(unsigned char *p, Q931_info_t *qi, int *coding, int *locati
        if (!nt)
        {
                p = NULL;
-               if (qi->progress)
-                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->progress + 1;
+               if (qi->QI_ELEMENT(progress))
+                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(progress) + 1;
        }
        if (!p)
                return;
@@ -1144,7 +1145,7 @@ void enc_ie_redir_nr(unsigned char **ntmode, msg_t *msg, int type, int plan, int
        if (nt)
                *ntmode = p+1;
        else
-               qi->redirect_nr = p - (unsigned char *)qi - sizeof(Q931_info_t);
+               qi->QI_ELEMENT(redirect_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t);
        p[0] = IE_REDIR_NR;
        p[1] = l;
        if (present >= 0)
@@ -1183,8 +1184,8 @@ void dec_ie_redir_nr(unsigned char *p, Q931_info_t *qi, int *type, int *plan, in
        if (!nt)
        {
                p = NULL;
-               if (qi->redirect_nr)
-                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->redirect_nr + 1;
+               if (qi->QI_ELEMENT(redirect_nr))
+                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(redirect_nr) + 1;
        }
        if (!p)
                return;
@@ -1252,7 +1253,7 @@ void enc_ie_redir_dn(unsigned char **ntmode, msg_t *msg, int type, int plan, int
                *ntmode = p+1;
        else
 /* #warning REINSERT redir_dn, when included in te-mode */
-               /*qi->redir_dn = p - (unsigned char *)qi - sizeof(Q931_info_t)*/;
+               /*qi->QI_ELEMENT(redir_dn) = p - (unsigned char *)qi - sizeof(Q931_info_t)*/;
        p[0] = IE_REDIR_DN;
        p[1] = l;
        if (present >= 0)
@@ -1280,8 +1281,8 @@ void dec_ie_redir_dn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, in
        {
                p = NULL;
 /* #warning REINSERT redir_dn, when included in te-mode */
-/*             if (qi->redir_dn) */
-/*                     p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->redir_dn + 1; */
+/*             if (qi->QI_ELEMENT(redir_dn)) */
+/*                     p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(redir_dn) + 1; */
        }
        if (!p)
                return;
@@ -1306,242 +1307,6 @@ void dec_ie_redir_dn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, in
 }
 
 
-/* IE_FACILITY */
-void enc_ie_facility(unsigned char **ntmode, msg_t *msg, unsigned char *facility, int facility_len, int nt, struct misdn_bchannel *bc)
-{
-       unsigned char *p;
-       Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
-       int l;
-
-       char debug[768];
-       int i;
-
-       if (!facility || facility_len<=0)
-       {
-               return;
-       }
-
-       i = 0;
-       while(i < facility_len)
-       {
-               if (MISDN_IE_DEBG) printf(debug+(i*3), " %02x", facility[i]);
-               i++;
-       }
-               
-       if (MISDN_IE_DEBG) printf("    facility%s\n", debug);
-
-       l = facility_len;
-       p = msg_put(msg, l+2);
-       if (nt)
-               *ntmode = p+1;
-       else
-               qi->facility = p - (unsigned char *)qi - sizeof(Q931_info_t);
-       p[0] = IE_FACILITY;
-       p[1] = l;
-       memcpy(p+2, facility, facility_len);
-}
-
-void dec_ie_facility(unsigned char *p, Q931_info_t *qi, unsigned char *facility, int *facility_len, int nt, struct misdn_bchannel *bc)
-{
-       int i;
-       struct misdn_stack *stack=get_stack_by_bc(bc);
-       
-       *facility_len = 0;
-
-       if (!nt)
-       {
-               p = NULL;
-               if (qi->facility)
-                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->facility + 1;
-       }
-       if (!p)
-               return;
-
-       *facility_len = p[0];
-       memcpy(facility, p+1, *facility_len);
-       
-       i = 0;
-       while(i < *facility_len)
-       {
-               cb_log(3, stack->port, " %02x", facility[i]);
-               i++;
-       }
-       cb_log(3, stack->port, "    facility\n");
-}
-
-
-/* facility for siemens CENTEX (known parts implemented only) */
-void enc_facility_centrex(unsigned char **ntmode, msg_t *msg, unsigned char *cnip, int setup, int nt, struct misdn_bchannel *bc)
-{
-       unsigned char centrex[256];
-       int i = 0;
-
-       if (!cnip)
-               return;
-
-       /* centrex facility */
-       centrex[i++] = CENTREX_FAC;
-       centrex[i++] = CENTREX_ID;
-
-       /* cnip */
-       if (strlen((char *)cnip) > 15)
-       {
-/*             if (options.deb & DEBUG_PORT) */
-               if (MISDN_IE_DEBG) printf("%s: CNIP/CONP text too long (max 13 chars), cutting.\n", __FUNCTION__);
-               cnip[15] = '\0';
-       }
-       /*  dunno what the 8 bytes mean */
-       if (setup)
-       {
-               centrex[i++] = 0x17;
-               centrex[i++] = 0x02;
-               centrex[i++] = 0x02;
-               centrex[i++] = 0x44;
-               centrex[i++] = 0x18;
-               centrex[i++] = 0x02;
-               centrex[i++] = 0x01;
-               centrex[i++] = 0x09;
-       } else
-       {
-               centrex[i++] = 0x18;
-               centrex[i++] = 0x02;
-               centrex[i++] = 0x02;
-               centrex[i++] = 0x81;
-               centrex[i++] = 0x09;
-               centrex[i++] = 0x02;
-               centrex[i++] = 0x01;
-               centrex[i++] = 0x0a;
-       }
-
-       centrex[i++] = 0x80;
-       centrex[i++] = strlen((char *)cnip);
-       strcpy((char *)(&centrex[i]), (char *)cnip);
-       i += strlen((char *)cnip);
-       if (MISDN_IE_DEBG) printf("    cnip='%s'\n", cnip);
-
-       /* encode facility */
-       enc_ie_facility(ntmode, msg, centrex, i, nt , bc);
-}
-
-void dec_facility_centrex(unsigned char *p, Q931_info_t *qi, unsigned char *cnip, int cnip_len, int nt, struct misdn_bchannel *bc)
-{
-       unsigned char centrex[256];
-       char debug[768];
-       int facility_len = 0;
-       int i = 0, j;
-       *cnip = '\0';
-
-       dec_ie_facility(p, qi, centrex, &facility_len,  nt, bc);
-       if (facility_len >= 2)
-       {
-               if (centrex[i++] != CENTREX_FAC)
-                       return;
-               if (centrex[i++] != CENTREX_ID)
-                       return;
-       }
-
-       /* loop sub IEs of facility */
-       while(facility_len > i+1)
-       {
-               if (centrex[i+1]+i+1 > facility_len)
-               {
-                       printf("%s: ERROR: short read of centrex facility.\n", __FUNCTION__);
-                       return;
-               }
-               switch(centrex[i])
-               {
-               case 0x80:
-                       strnncpy(cnip, &centrex[i+2], centrex[i+1], cnip_len);
-                       if (MISDN_IE_DEBG) printf("    CENTREX cnip='%s'\n", cnip);
-                       break;
-
-               default:
-                       j = 0;
-                       while(j < centrex[i+1])
-                       {
-                               if (MISDN_IE_DEBG) printf(debug+(j*3), " %02x", centrex[i+1+j]);
-                               i++;
-                       }
-                       if (MISDN_IE_DEBG) printf("    CENTREX unknown=0x%2x len=%d%s\n", centrex[i], centrex[i+1], debug);
-               }
-               i += 1+centrex[i+1];
-       }
-}
-
-
-
-
-/* facility for siemens CENTEX (known parts implemented only) */
-void enc_facility_calldeflect(unsigned char **ntmode, msg_t *msg, unsigned char *nr, int nt, struct misdn_bchannel *bc)
-{
-       unsigned char fac[256];
-       
-       if (!nr)
-               return;
-       
-       /* calldeflect facility */
-       
-       /* cnip */
-       if (strlen((char *)nr) > 15)
-       {
-/*             if (options.deb & DEBUG_PORT) */
-               if (MISDN_IE_DEBG) printf("%s: NR text too long (max 13 chars), cutting.\n", __FUNCTION__);
-               nr[15] = '\0';
-       }
-       
-       fac[0]=0; // len 
-       fac[1]=0; //len 
-       fac[2]=0x01; // Use D-Chan
-       fac[3]=0; // Keypad len
-       fac[4]=31;      // user user data? len = 31 = 29 + 2
-       fac[5]=0x1c;    // magic?
-       fac[6]=0x1d;    // strlen destination + 18 = 29
-       fac[7]=0x91;    // ..
-       fac[8]=0xA1;
-       fac[9]=0x1A;    // strlen destination + 15 = 26
-       fac[10]=0x02;
-       fac[11]=0x01;
-       fac[12]=0x70;
-       fac[13]=0x02;
-       fac[14]=0x01;
-       fac[15]=0x0d;
-       fac[16]=0x30;
-       fac[17]=0x12;   // strlen destination + 7 = 18
-       fac[18]=0x30;   // ...hm 0x30
-       fac[19]=0x0d;   // strlen destination + 2       
-       fac[20]=0x80;   // CLIP
-       fac[21]=0x0b;   //  strlen destination 
-       fac[22]=0x01;   //  destination start
-       fac[23]=0x01;   //  
-       fac[24]=0x01;   //  
-       fac[25]=0x01;   //  
-       fac[26]=0x01;   //  
-       fac[27]=0x01;   //  
-       fac[28]=0x01;   //  
-       fac[29]=0x01;   //  
-       fac[30]=0x01;   //  
-       fac[31]=0x01;   //  
-       fac[32]=0x01;   //  
-       fac[33]=0x01;   // 0x1 = sending complete
-       fac[34]=0x01;
-       fac[35]=0x01;
-                                  
-       memcpy((unsigned char *)fac+22,nr,strlen(nr));
-       fac[22+strlen( nr)]=0x01;       // fill with 0x01 if number is only 6 numbers (local call)
-       fac[23+strlen(nr)]=0x01;
-       fac[24+strlen(nr)]=0x01;
-       fac[25+strlen(nr)]=0x01;
-       fac[26+strlen(nr)]=0x01;
-       
-       fac[6]=18+strlen(nr);
-       fac[9]=15+strlen(nr);
-       fac[17]=7+strlen(nr);
-       fac[19]=2+strlen(nr);
-       fac[21]=strlen(nr);
-       
-       enc_ie_facility(ntmode, msg, &fac[4], 36-4, nt , bc);
-}
-
 
 /* IE_USERUSER */
 void enc_ie_useruser(unsigned char **ntmode, msg_t *msg, int protocol, unsigned char *user, int user_len, int nt, struct misdn_bchannel *bc)
@@ -1577,7 +1342,7 @@ void enc_ie_useruser(unsigned char **ntmode, msg_t *msg, int protocol, unsigned
        if (nt)
                *ntmode = p+1;
        else
-               qi->useruser = p - (unsigned char *)qi - sizeof(Q931_info_t);
+               qi->QI_ELEMENT(useruser) = p - (unsigned char *)qi - sizeof(Q931_info_t);
        p[0] = IE_USER_USER;
        p[1] = l;
        p[2] = 0x80 + protocol;
@@ -1595,8 +1360,8 @@ void dec_ie_useruser(unsigned char *p, Q931_info_t *qi, int *protocol, unsigned
        if (!nt)
        {
                p = NULL;
-               if (qi->useruser)
-                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->useruser + 1;
+               if (qi->QI_ELEMENT(useruser))
+                       p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(useruser) + 1;
        }
        if (!p)
                return;
@@ -1619,3 +1384,5 @@ void dec_ie_useruser(unsigned char *p, Q931_info_t *qi, int *protocol, unsigned
 }
 
 
+
+
index aa1d51cea58081fd12cde8748738d9f87f45b502..ea7c208492de1bdf2bba565ec8b3a19ab5cd2736 100644 (file)
  * the GNU General Public License
  */
 
+
+#include <syslog.h>
 #include "isdn_lib_intern.h"
+#include <mISDNuser/isdn_debug.h>
 
+void misdn_join_conf(struct misdn_bchannel *bc, int conf_id);
+void misdn_split_conf(struct misdn_bchannel *bc, int conf_id);
 
-int misdn_ibuf_freecount(void *buf)
-{
-       return ibuf_freecount( (ibuffer_t*)buf);
-}
+int queue_cleanup_bc(struct misdn_bchannel *bc) ;
 
-int misdn_ibuf_usedcount(void *buf)
-{
-       return ibuf_usedcount( (ibuffer_t*)buf);
-}
+int misdn_lib_get_l2_up(struct misdn_stack *stack);
+
+struct misdn_stack* get_misdn_stack( void );
 
-void misdn_ibuf_memcpy_r(char *to, void *buf, int len)
+int misdn_lib_port_block(int port)
 {
-       ibuf_memcpy_r( to, (ibuffer_t*)buf, len);
+       struct misdn_stack *stack=get_misdn_stack();
+       for ( ; stack; stack=stack->next) {
+               if (stack->port == port) {
+                       stack->blocked=1;
+                       return 0;
+               }
+       }
+       return -1;
+
 }
 
-void misdn_ibuf_memcpy_w(void *buf, char *from,  int len)
+int misdn_lib_port_unblock(int port)
 {
-       ibuf_memcpy_w((ibuffer_t*)buf, from, len);
-}
+       struct misdn_stack *stack=get_misdn_stack();
+       for ( ; stack; stack=stack->next) {
+               if (stack->port == port) {
+                       stack->blocked=0;
+                       return 0;
+               }
+       }
+       return -1;
 
-struct misdn_stack* get_misdn_stack( void );
+}
 
+int misdn_lib_is_port_blocked(int port)
+{      
+       struct misdn_stack *stack=get_misdn_stack();
+       for ( ; stack; stack=stack->next) {
+               if (stack->port == port) {
+                       return stack->blocked;
+               }
+       }
+       return -1;
+}
 
 int misdn_lib_is_ptp(int port)
 {
@@ -46,6 +71,20 @@ int misdn_lib_is_ptp(int port)
        return -1;
 }
 
+int misdn_lib_get_maxchans(int port) 
+{
+       struct misdn_stack *stack=get_misdn_stack();
+       for ( ; stack; stack=stack->next) {
+               if (stack->port == port) {
+                       if (stack->pri) 
+                               return 30;
+                       else
+                               return 2;
+               }
+       }
+       return -1;
+}
+
 
 struct misdn_stack* get_stack_by_bc(struct misdn_bchannel *bc)
 {
@@ -73,7 +112,8 @@ void get_show_stack_details(int port, char *buf)
        }
        
        if (stack) {
-               sprintf(buf, "* Stack Addr: Port %d Type %s Prot. %s L2Link %s L1Link:%s", stack->upper_id & IF_CONTRMASK, stack->mode==NT_MODE?"NT":"TE", stack->ptp?"PTP":"PMP", stack->l2link?"UP":"DOWN", stack->l1link?"UP":"DOWN");
+               sprintf(buf, "* Port %d Type %s Prot. %s L2Link %s L1Link:%s Blocked:%d", stack->port, stack->nt?"NT":"TE", stack->ptp?"PTP":"PMP", stack->l2link?"UP":"DOWN", stack->l1link?"UP":"DOWN",stack->blocked);
+
        } else {
                buf[0]=0;
        }
@@ -125,6 +165,8 @@ struct misdn_lib {
 
 #define MISDN_DEBUG 0
 
+void misdn_tx_jitter(struct misdn_bchannel *bc, int len);
+
 struct misdn_bchannel *find_bc_by_l3id(struct misdn_stack *stack, unsigned long l3id);
 
 int setup_bc(struct misdn_bchannel *bc);
@@ -165,14 +207,13 @@ struct misdn_bchannel *stack_holder_find(struct misdn_stack *stack, unsigned lon
 
 /* from isdn_lib.h */
 int init_bc(struct misdn_stack * stack,  struct misdn_bchannel *bc, int midev, int port, int bidx, char *msn, int firsttime);
-struct misdn_stack* stack_te_init(int midev,  int port, int ptp);
-void stack_te_destroy(struct misdn_stack* stack);
+struct misdn_stack* stack_init(int midev,  int port, int ptp);
+void stack_destroy(struct misdn_stack* stack);
        /* user iface */
 int te_lib_init( void ) ; /* returns midev */
 void te_lib_destroy(int midev) ;
 struct misdn_bchannel *manager_find_bc_by_pid(int pid);
 struct misdn_bchannel *manager_find_bc_holded(struct misdn_bchannel* bc);
-unsigned char * manager_flip_buf_bits ( unsigned char * buf , int len);
 void manager_ph_control_block(struct misdn_bchannel *bc, int c1, void *c2, int c2_len);
 void manager_clean_bc(struct misdn_bchannel *bc );
 void manager_bchannel_setup (struct misdn_bchannel *bc);
@@ -234,7 +275,7 @@ void init_flip_bits(void)
        }
 }
 
-static unsigned char * flip_buf_bits ( unsigned char * buf , int len)
+unsigned char * flip_buf_bits ( unsigned char * buf , int len)
 {
        int i;
        char * start = buf;
@@ -315,21 +356,27 @@ int send_msg (int midev, struct misdn_bchannel *bc, msg_t *dmsg)
        iframe_t *frm;
        frm = (iframe_t *)dmsg->data;
        struct misdn_stack *stack=get_stack_by_bc(bc);
+
+       if (!stack) {
+               cb_log(0,bc->port,"send_msg: IEK!! no stack\n ");
+               return -1;
+       }
        
-       frm->addr = (stack->upper_id &  IF_ADDRMASK) | IF_DOWN ;
+       frm->addr = (stack->upper_id | FLG_MSG_DOWN);
        frm->dinfo = bc->l3_id;
-  
        frm->len = (dmsg->len) - mISDN_HEADER_LEN;
-  
+                               
+       cb_log(4,stack->port,"Sending msg, prim:%x addr:%x dinfo:%x\n",frm->prim,frm->addr,frm->dinfo);
+
        mISDN_write(midev, dmsg->data, dmsg->len, TIMEOUT_1SEC);
-  
        free_msg(dmsg);
 
        return 0;
 }
 
 
-static int mypid=0;
+static int mypid=1;
+
 
 int misdn_cap_is_speech(int cap)
 /** Poor mans version **/
@@ -362,7 +409,7 @@ void dump_chan_list(struct misdn_stack *stack)
        int i;
 
        for (i=0; i <stack->b_num; i++) {
-               cb_log(3, stack->port, "Idx:%d stack->cchan:%d Chan:%d\n",i,stack->channels[i], i+1);
+               cb_log(6, stack->port, "Idx:%d stack->cchan:%d Chan:%d\n",i,stack->channels[i], i+1);
        }
 }
 
@@ -373,8 +420,10 @@ static int find_free_chan_in_stack(struct misdn_stack *stack, int channel)
 {
        int i;
 
+       cb_log(1,stack->port,"find_free_chan: req_chan:%d\n",channel);
+
        if (channel < 0 || channel > MAX_BCHANS) {
-               cb_log(4, stack->port, " !! out of bound call to find_free_chan_in_stack! (port:%d ch:%d)\n", stack->port, channel);
+               cb_log(4, stack->port, " !! out of bound call to find_free_chan_in_stack! (ch:%d)\n", channel);
                return 0;
        }
        
@@ -383,7 +432,7 @@ static int find_free_chan_in_stack(struct misdn_stack *stack, int channel)
        for (i = 0; i < stack->b_num; i++) {
                if (i != 15 && (channel < 0 || i == channel)) { /* skip E1 Dchannel ;) and work with chan preselection */
                        if (!stack->channels[i]) {
-                               cb_log (4, stack->port, " --> found chan%s: %d\n", channel>=0?" (preselected)":"", i+1);
+                               cb_log (1, stack->port, " --> found chan%s: %d\n", channel>=0?" (preselected)":"", i+1);
                                stack->channels[i] = 1;
                                return i+1;
                        }
@@ -398,24 +447,96 @@ static int find_free_chan_in_stack(struct misdn_stack *stack, int channel)
 
 int empty_chan_in_stack(struct misdn_stack *stack, int channel)
 {
-       cb_log (4, stack?stack->port:0, " --> empty chan %d\n",channel); 
+       if (channel<=0) {
+               cb_log(0,stack?stack->port:0, "empty_chan_inst_stack: cannot empty channel %d\n",channel);
+               return -1;
+       }
+       
+       cb_log (4, stack?stack->port:0, "empty_chan_in_stack: %d\n",channel); 
        stack->channels[channel-1] = 0;
        dump_chan_list(stack);
        return 0;
 }
 
+char *bc_state2str(enum bchannel_state state) {
+       int i;
+       
+       struct bchan_state_s {
+               char *n;
+               enum bchannel_state s;
+       } states[] = {
+               {"BCHAN_CLEANED", BCHAN_CLEANED },
+               {"BCHAN_EMPTY", BCHAN_EMPTY},
+               {"BCHAN_SETUP", BCHAN_SETUP},
+               {"BCHAN_SETUPED", BCHAN_SETUPED},
+               {"BCHAN_ACTIVE", BCHAN_ACTIVE},
+               {"BCHAN_ACTIVATED", BCHAN_ACTIVATED},
+               {"BCHAN_BRIDGE",  BCHAN_BRIDGE},
+               {"BCHAN_BRIDGED", BCHAN_BRIDGED},
+               {"BCHAN_RELEASE", BCHAN_RELEASE},
+               {"BCHAN_RELEASED", BCHAN_RELEASED},
+               {"BCHAN_CLEAN", BCHAN_CLEAN},
+               {"BCHAN_CLEAN_REQUEST", BCHAN_CLEAN_REQUEST},
+               {"BCHAN_ERROR", BCHAN_ERROR}
+       };
+       
+       for (i=0; i< sizeof(states)/sizeof(struct bchan_state_s); i++)
+               if ( states[i].s == state)
+                       return states[i].n;
+
+       return "UNKNOWN";
+}
+
+void bc_state_change(struct misdn_bchannel *bc, enum bchannel_state state)
+{
+       cb_log(5,bc->port,"BC_STATE_CHANGE: from:%s to:%s\n",
+              bc_state2str(bc->bc_state),
+              bc_state2str(state) );
+       
+       switch (state) {
+               case BCHAN_ACTIVATED:
+                       if (bc->next_bc_state ==  BCHAN_BRIDGED) {
+                               misdn_join_conf(bc, bc->conf_id);
+                               bc->next_bc_state = BCHAN_EMPTY;
+                               return;
+                       }
+               default:
+                       bc->bc_state=state;
+                       break;
+       }
+}
+
+void bc_next_state_change(struct misdn_bchannel *bc, enum bchannel_state state)
+{
+       cb_log(5,bc->port,"BC_NEXT_STATE_CHANGE: from:%s to:%s\n",
+              bc_state2str(bc->next_bc_state),
+              bc_state2str(state) );
+
+       bc->next_bc_state=state;
+}
+
 
 void empty_bc(struct misdn_bchannel *bc)
 {
-       bc->state=STATE_NOTHING;
+       bc->bframe_len=0;
        
+
+       bc->in_use= 0;
+
        bc->channel = 0;
-       bc->in_use = 0;
 
+       bc->sending_complete = 0;
+
+       bc->restart_channel=0;
+       
+       bc->conf_id = 0;
+
+       bc->need_more_infos = 0;
+       
        bc->send_dtmf=0;
        bc->nodsp=0;
        bc->nojitter=0;
-       
+
        bc->time_usec=0;
        
        bc->rxgain=0;
@@ -426,12 +547,13 @@ void empty_bc(struct misdn_bchannel *bc)
        
        bc->crypt_key[0] = 0;
        
-       bc->tone=TONE_NONE;
-       bc->tone_cnt2 = bc->tone_cnt=0;
+       bc->generate_tone=0;
+       bc->tone_cnt=0;
   
        bc->dnumplan=NUMPLAN_UNKNOWN;
        bc->onumplan=NUMPLAN_UNKNOWN;
        bc->rnumplan=NUMPLAN_UNKNOWN;
+       bc->cpnnumplan=NUMPLAN_UNKNOWN;
        
 
        bc->active = 0;
@@ -441,8 +563,10 @@ void empty_bc(struct misdn_bchannel *bc)
        bc->ec_enable = 0;
        bc->ec_deftaps = 128;
        bc->ec_whenbridged = 0;
+
+#ifdef EC_TRAIN
        bc->ec_training = 1;
-       
+#endif
        
        bc->orig=0;
   
@@ -460,24 +584,28 @@ void empty_bc(struct misdn_bchannel *bc)
        bc->capability=INFO_CAPABILITY_SPEECH;
        bc->law=INFO_CODEC_ALAW;
        bc->mode=0;
-       bc->rate=0;
+       bc->rate=0x10;
        bc->user1=0;
-       bc->async=0;
        bc->urate=0;
        
+       bc->hdlc=0;
        
        
        bc->info_dad[0] = 0;
        bc->display[0] = 0;
        bc->infos_pending[0] = 0;
+       bc->cad[0] = 0;
        bc->oad[0] = 0;
        bc->dad[0] = 0;
+       bc->rad[0] = 0;
        bc->orig_dad[0] = 0;
        
-       bc->facility=FACILITY_NONE;
-       bc->facility_calldeflect_nr[0]=0;
-
+       bc->fac_type=FACILITY_NONE;
+       bc->out_fac_type=FACILITY_NONE;
+       
        bc->te_choose_channel = 0;
+
+       bc->holded_bc=NULL;
 }
 
 
@@ -486,29 +614,38 @@ int clean_up_bc(struct misdn_bchannel *bc)
        int ret=0;
        unsigned char buff[32];
        struct misdn_stack * stack;
+
+       cb_log(3, bc?bc->port:0, "$$$ CLEANUP CALLED pid:%d\n", bc?bc->pid:-1);
        
        if (!bc  ) return -1;
        stack=get_stack_by_bc(bc);
+       
        if (!stack) return -1;
        
-       if (!bc->upset) {
+       switch (bc->bc_state ) {
+       case BCHAN_CLEANED:
                cb_log(5, stack->port, "$$$ Already cleaned up bc with stid :%x\n", bc->b_stid);
                return -1;
+               
+       default:
+               break;
        }
-  
-       cb_log(5, stack->port, "$$$ Cleaning up bc with stid :%x\n", bc->b_stid);
        
+       cb_log(2, stack->port, "$$$ Cleaning up bc with stid :%x pid:%d\n", bc->b_stid, bc->pid);
        
-       if ( misdn_cap_is_speech(bc->capability) && bc->ec_enable) {
-               manager_ec_disable(bc);
-       }
-       
-       mISDN_write_frame(stack->midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
+       manager_bchannel_deactivate(bc);
+
+
+       manager_ec_disable(bc);
+
+
+       mISDN_write_frame(stack->midev, buff, bc->layer_id|FLG_MSG_TARGET|FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
        
+       /*mISDN_clear_stack(stack->midev, bc->b_stid);*/
+
        
        bc->b_stid = 0;
-       
-       bc->upset=0;
+       bc_state_change(bc, BCHAN_CLEANED);
        
        return ret;
 }
@@ -518,13 +655,13 @@ int clean_up_bc(struct misdn_bchannel *bc)
 void clear_l3(struct misdn_stack *stack)
 {
        int i;
+
        for (i=0; i<stack->b_num; i++) {
                if (global_state == MISDN_INITIALIZED)  {
-                       cb_event(EVENT_CLEANUP, &stack->bc[i], glob_mgr->user_data);
+                       cb_event(EVENT_CLEANUP, &stack->bc[i], NULL); 
                        empty_chan_in_stack(stack,i+1);
                        empty_bc(&stack->bc[i]);
                        clean_up_bc(&stack->bc[i]);
-                       
                }
                
        } 
@@ -532,7 +669,13 @@ void clear_l3(struct misdn_stack *stack)
 
 int set_chan_in_stack(struct misdn_stack *stack, int channel)
 {
-       stack->channels[channel-1] = 1;
+
+       cb_log(4,stack->port,"set_chan_in_stack: %d\n",channel);
+       if (channel >=1 ) {
+               stack->channels[channel-1] = 1;
+       } else {
+               cb_log(0,stack->port,"couldn't set channel %d in\n", channel );
+       }
   
        return 0;
 }
@@ -549,19 +692,59 @@ int chan_in_stack_free(struct misdn_stack *stack, int channel)
 
 static int newteid=0;
 
-#ifdef MISDNUSER_JOLLY
 #define MAXPROCS 0x100
-#else
-#define MAXPROCS 0x10
-#endif
+
+int misdn_lib_get_l1_down(struct misdn_stack *stack)
+{
+       /* Pull Up L1 */ 
+       iframe_t act;
+       act.prim = PH_DEACTIVATE | REQUEST; 
+       act.addr = (stack->upper_id | FLG_MSG_DOWN)  ;
+
+       
+       act.dinfo = 0;
+       act.len = 0;
+
+       return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
+
+
+}
+
+
+int misdn_lib_get_l2_down(struct misdn_stack *stack)
+{
+       
+       if (stack->ptp && (stack->nt) ) {
+               msg_t *dmsg;
+               /* L2 */
+               dmsg = create_l2msg(DL_RELEASE| REQUEST, 0, 0);
+               
+               if (stack->nst.manager_l3(&stack->nst, dmsg))
+                       free_msg(dmsg);
+               
+       } else {
+               iframe_t act;
+               
+               act.prim = DL_RELEASE| REQUEST;
+               act.addr = (stack->upper_id |FLG_MSG_DOWN)  ;
+               
+               act.dinfo = 0;
+               act.len = 0;
+               return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
+       }
+       
+       return 0;
+}
 
 
 int misdn_lib_get_l1_up(struct misdn_stack *stack)
 {
-       /* Pull Up L1 if we have JOLLY */ 
+       /* Pull Up L1 */ 
        iframe_t act;
        act.prim = PH_ACTIVATE | REQUEST; 
-       act.addr = (stack->upper_id & IF_ADDRMASK) | IF_DOWN ;
+       act.addr = (stack->upper_id | FLG_MSG_DOWN)  ;
+
+       
        act.dinfo = 0;
        act.len = 0;
 
@@ -572,7 +755,7 @@ int misdn_lib_get_l1_up(struct misdn_stack *stack)
 int misdn_lib_get_l2_up(struct misdn_stack *stack)
 {
        
-       if (stack->ptp && (stack->mode == NT_MODE) ) {
+       if (stack->ptp && (stack->nt) ) {
                msg_t *dmsg;
                /* L2 */
                dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
@@ -584,8 +767,8 @@ int misdn_lib_get_l2_up(struct misdn_stack *stack)
                iframe_t act;
                
                act.prim = DL_ESTABLISH | REQUEST;
-
-               act.addr = (stack->upper_id & IF_ADDRMASK) | IF_DOWN;
+               act.addr = (stack->upper_id |FLG_MSG_DOWN)  ;
+               
                act.dinfo = 0;
                act.len = 0;
                return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
@@ -594,23 +777,37 @@ int misdn_lib_get_l2_up(struct misdn_stack *stack)
        return 0;
 }
 
-
-int misdn_lib_get_l2_status(struct misdn_stack *stack)
+int misdn_lib_get_l2_te_ptp_up(struct misdn_stack *stack)
 {
        iframe_t act;
-       
-#ifdef DL_STATUS
-       act.prim = DL_STATUS | REQUEST; 
-#else
+               
        act.prim = DL_ESTABLISH | REQUEST;
-#endif
-       act.addr = (stack->upper_id & IF_ADDRMASK) | IF_DOWN;
+       act.addr = (stack->upper_id  & ~LAYER_ID_MASK) | 3 | FLG_MSG_DOWN;
+               
        act.dinfo = 0;
        act.len = 0;
        return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
+       return 0;
+}
+
+
+int misdn_lib_get_short_status(struct misdn_stack *stack)
+{
+       iframe_t act;
+       
+       
+       act.prim = MGR_SHORTSTATUS | REQUEST; 
+       
+       act.addr = (stack->upper_id | MSG_BROADCAST)  ;
+
+       act.dinfo = SSTATUS_BROADCAST_BIT | SSTATUS_ALL;
+       
+       act.len = 0;
+       return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
 }
 
 
+
 static int create_process (int midev, struct misdn_bchannel *bc) {
        iframe_t ncr;
        int l3_id;
@@ -618,35 +815,32 @@ static int create_process (int midev, struct misdn_bchannel *bc) {
        struct misdn_stack *stack=get_stack_by_bc(bc);
        int free_chan;
   
-       if (stack->mode == NT_MODE) {
+       if (stack->nt) {
                free_chan = find_free_chan_in_stack(stack, bc->channel_preselected?bc->channel:0);
                if (!free_chan) return -1;
                bc->channel=free_chan;
+               
+               cb_log(4,stack->port, " -->  found channel: %d\n",free_chan);
     
                for (i=0; i <= MAXPROCS; i++)
                        if (stack->procids[i]==0) break;
     
                if (i== MAXPROCS) {
-                       cb_log(0, stack->port, "Couldnt Create New ProcId Port:%d\n",stack->port);
+                       cb_log(0, stack->port, "Couldnt Create New ProcId.\n");
                        return -1;
                }
                stack->procids[i]=1;
 
-#ifdef MISDNUSER_JOLLY
                l3_id = 0xff00 | i;
-#else
-               l3_id = 0xfff0 | i;
-#endif
     
                ncr.prim = CC_NEW_CR | REQUEST; 
-               ncr.addr = (stack->upper_id & IF_ADDRMASK) | IF_DOWN ;
+
+               ncr.addr = (stack->upper_id | FLG_MSG_DOWN)  ;
+
                ncr.dinfo = l3_id;
                ncr.len = 0;
 
                bc->l3_id = l3_id;
-               if (mypid>5000) mypid=0;
-               bc->pid=mypid++;
-      
                cb_log(3, stack->port, " --> new_l3id %x\n",l3_id);
     
        } else { 
@@ -655,6 +849,7 @@ static int create_process (int midev, struct misdn_bchannel *bc) {
                        free_chan = find_free_chan_in_stack(stack, bc->channel_preselected?bc->channel:0);
                        if (!free_chan) return -1;
                        bc->channel=free_chan;
+                       cb_log(2,stack->port, " -->  found channel: %d\n",free_chan);
                } else {
                        /* other phones could have made a call also on this port (ptmp) */
                        bc->channel=0xff;
@@ -668,15 +863,14 @@ static int create_process (int midev, struct misdn_bchannel *bc) {
                l3_id = (entity<<16) | newteid;
                /* preparing message */
                ncr.prim = CC_NEW_CR | REQUEST; 
-               ncr.addr = (stack->upper_id & IF_ADDRMASK) | IF_DOWN ;
+
+               ncr.addr = (stack->upper_id | FLG_MSG_DOWN)  ;
+
                ncr.dinfo =l3_id;
                ncr.len = 0;
                /* send message */
 
                bc->l3_id = l3_id;
-               if (mypid>5000) mypid=0;
-               bc->pid=mypid++;
-    
                cb_log(3, stack->port, "--> new_l3id %x\n",l3_id);
     
                mISDN_write(midev, &ncr, mISDN_HEADER_LEN+ncr.len, TIMEOUT_1SEC);
@@ -698,34 +892,38 @@ int setup_bc(struct misdn_bchannel *bc)
   
        mISDN_pid_t pid;
        int ret;
+       
 
        struct misdn_stack *stack=get_stack_by_bc(bc);
+
+       if (!stack) {
+               cb_log(0, bc->port, "setup_bc: NO STACK FOUND!!\n");
+               return -1;
+       }
        
        int midev=stack->midev;
        int channel=bc->channel-1-(bc->channel>16);
        int b_stid=stack->b_stids[channel>=0?channel:0];
 
-       
-       if (bc->nodsp ) 
-               clean_up_bc(bc);
-       
-       if ( !misdn_cap_is_speech(bc->capability))
-               clean_up_bc(bc);
-       
-       
-       if (bc->upset) {
-               cb_log(4, stack->port, "$$$ bc already upsetted stid :%x\n", b_stid);
-               return -1;
+
+       switch (bc->bc_state) {
+               case BCHAN_CLEANED:
+                       break;
+               default:
+                       cb_log(4, stack->port, "$$$ bc already upsetted stid :%x (state:%s)\n", b_stid, bc_state2str(bc->bc_state) );
+                       return -1;
        }
        
        cb_log(5, stack->port, "$$$ Setting up bc with stid :%x\n", b_stid);
        
        if (b_stid <= 0) {
-               cb_log(0, stack->port," -- Stid <=0 at the moment on port:%d channel:%d\n",stack->port,channel);
+               cb_log(0, stack->port," -- Stid <=0 at the moment in channel:%d\n",channel);
+               
+               bc_state_change(bc,BCHAN_ERROR);
                return 1;
        }
        
-  
+       
        bc->b_stid = b_stid;
        
        {
@@ -738,78 +936,117 @@ int setup_bc(struct misdn_bchannel *bc)
                li.st = bc->b_stid; /*  given idx */
 
 
-               if ( misdn_cap_is_speech(bc->capability) && !bc->nodsp && bc->async != 1) {
-                       cb_log(4, stack->port,"setup_bc: with dsp\n");
+#define MISDN_DSP
+#ifndef MISDN_DSP
+               bc->nodsp=1;
+#endif
+               if ( bc->hdlc || bc->nodsp) {
+                       cb_log(4, stack->port,"setup_bc: without dsp\n");
                        { 
                                int l = sizeof(li.name);
-                               strncpy(li.name, "B L4", l);
+                               strncpy(li.name, "B L3", l);
                                li.name[l-1] = 0;
                        }
-                       li.pid.layermask = ISDN_LAYER((4));
-                       li.pid.protocol[4] = ISDN_PID_L4_B_USER;
+                       li.pid.layermask = ISDN_LAYER((3));
+                       li.pid.protocol[3] = ISDN_PID_L3_B_USER;
                        
+                       bc->layer=3;
                } else {
-                       cb_log(4, stack->port,"setup_bc: without dsp\n");
+                       cb_log(4, stack->port,"setup_bc: with dsp\n");
                        { 
                                int l = sizeof(li.name);
-                               strncpy(li.name, "B L3", l);
+                               strncpy(li.name, "B L4", l);
                                li.name[l-1] = 0;
                        }
-                       li.pid.layermask = ISDN_LAYER((3));
-                       li.pid.protocol[3] = ISDN_PID_L3_B_USER;
-               }
+                       li.pid.layermask = ISDN_LAYER((4));
+                       li.pid.protocol[4] = ISDN_PID_L4_B_USER
+;
+                       bc->layer=4;
+                       
+               }  
                
                ret = mISDN_new_layer(midev, &li);
-               if (ret <= 0) {
-                       cb_log(0, stack->port,"New Layer Err: %d %s port:%d\n",ret,strerror(errno), stack->port);
+               if (ret ) {
+                       cb_log(0, stack->port,"New Layer Err: %d %s\n",ret,strerror(errno));
+
+                       bc_state_change(bc,BCHAN_ERROR);
                        return(-EINVAL);
                }
-      
-               bc->layer_id = ret;
+               
+               bc->layer_id = li.id;
        }
        
        memset(&pid, 0, sizeof(pid));
        
-       bc->addr = ( bc->layer_id & IF_ADDRMASK) | IF_DOWN;
-       cb_log(4, stack->port," --> Got Adr %x\n", bc->addr);
-       cb_log(4, stack->port," --> Channel is %d\n", bc->channel);
        
        
-       if (bc->async == 1 || bc->nodsp) {
-               cb_log(4, stack->port," --> TRANSPARENT Mode (no DSP, no HDLC)\n");
+       cb_log(4, stack->port," --> Channel is %d\n", bc->channel);
+       
+       if (bc->nodsp) {
+               cb_log(2, stack->port," --> TRANSPARENT Mode (no DSP, no HDLC)\n");
                pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
                pid.protocol[2] = ISDN_PID_L2_B_TRANS;
                pid.protocol[3] = ISDN_PID_L3_B_USER;
                pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3));
                
-       } else if ( misdn_cap_is_speech(bc->capability)) {
-               cb_log(4, stack->port," --> TRANSPARENT Mode\n");
+       } else if ( bc->hdlc ) {
+               cb_log(2, stack->port," --> HDLC Mode\n");
+#ifdef ACK_HDLC
+               bc->ack_hdlc=(sem_t*)malloc(sizeof(sem_t));
+               if ( sem_init((sem_t*)bc->ack_hdlc, 1, 0)<0 )
+                       sem_init((sem_t*)bc->ack_hdlc, 0, 0);
+#endif
+               
+               pid.protocol[1] = ISDN_PID_L1_B_64HDLC ;
+               pid.protocol[2] = ISDN_PID_L2_B_TRANS  ;
+               pid.protocol[3] = ISDN_PID_L3_B_USER;
+               pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) ;
+       } else {
+               cb_log(2, stack->port," --> TRANSPARENT Mode\n");
                pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
                pid.protocol[2] = ISDN_PID_L2_B_TRANS;
                pid.protocol[3] = ISDN_PID_L3_B_DSP;
                pid.protocol[4] = ISDN_PID_L4_B_USER;
                pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4));
                
-       } else {
-               cb_log(4, stack->port," --> HDLC Mode\n");
-               pid.protocol[1] = ISDN_PID_L1_B_64HDLC ;
-               pid.protocol[2] = ISDN_PID_L2_B_TRANS  ;
-               pid.protocol[3] = ISDN_PID_L3_B_USER;
-               pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) ;
-       }
-       
+       } 
+
        ret = mISDN_set_stack(midev, bc->b_stid, &pid);
-       
-       
+
        if (ret){
-               cb_log(5, stack->port,"$$$ Set Stack Err: %d %s\n",ret,strerror(errno));
-    
-               mISDN_write_frame(midev, buff, bc->addr, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
+               cb_log(0, stack->port,"$$$ Set Stack Err: %d %s\n",ret,strerror(errno));
+               
+               mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
+               
+               bc_state_change(bc,BCHAN_ERROR);
                return(-EINVAL);
        }
-  
-       bc->upset=1;
-  
+
+       ret = mISDN_get_setstack_ind(midev, bc->layer_id);
+
+       if (ret) {
+               cb_log(0, stack->port,"$$$ Set StackIND Err: %d %s\n",ret,strerror(errno));
+               mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
+               
+               bc_state_change(bc,BCHAN_ERROR);
+               return(-EINVAL);
+       }
+
+       ret = mISDN_get_layerid(midev, bc->b_stid, bc->layer) ;
+
+       bc->addr = ret>0? ret : 0;
+
+       if (!bc->addr) {
+               cb_log(0, stack->port,"$$$ Get Layerid Err: %d %s\n",ret,strerror(errno));
+               mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
+               
+               bc_state_change(bc,BCHAN_ERROR);
+       }
+
+       manager_bchannel_activate(bc);
+       
+       bc_state_change(bc,BCHAN_ACTIVATED);
+
        return 0;
 }
 
@@ -824,7 +1061,7 @@ int init_bc(struct misdn_stack *stack,  struct misdn_bchannel *bc, int midev, in
   
        if (!bc) return -1;
   
-       cb_log(4, port, "Init.BC %d on port:%d\n",bidx, port);
+       cb_log(8, port, "Init.BC %d.\n",bidx);
        
        memset(bc, 0,sizeof(struct misdn_bchannel));
        
@@ -836,30 +1073,24 @@ int init_bc(struct misdn_stack *stack,  struct misdn_bchannel *bc, int midev, in
        
        
        empty_bc(bc);
-       bc->upset=0;
+       bc_state_change(bc, BCHAN_CLEANED);
+       
        bc->port=stack->port;
-       bc->nt=stack->mode==NT_MODE?1:0;
+       bc->nt=stack->nt?1:0;
        
        {
                ibuffer_t* ibuf= init_ibuffer(MISDN_IBUF_SIZE);
-               ibuffer_t* mbuf= init_ibuffer(MISDN_IBUF_SIZE);
 
                if (!ibuf) return -1;
-               if (!mbuf) return -1;
                
                clear_ibuffer( ibuf);
-               clear_ibuffer( mbuf);
                
                ibuf->rsem=malloc(sizeof(sem_t));
-               mbuf->rsem=malloc(sizeof(sem_t));
                
                bc->astbuf=ibuf;
-               bc->misdnbuf=mbuf;
 
                if (sem_init(ibuf->rsem,1,0)<0)
                        sem_init(ibuf->rsem,0,0);
-               if (sem_init(mbuf->rsem,1,0)< 0)
-                       sem_init(mbuf->rsem,0,0);
                
        }
        
@@ -870,13 +1101,13 @@ int init_bc(struct misdn_stack *stack,  struct misdn_bchannel *bc, int midev, in
                stack_info_t *stinf;
                ret = mISDN_get_stack_info(midev, stack->port, buff, sizeof(buff));
                if (ret < 0) {
-                       cb_log(0, port, "%s: Cannot get stack info for port:%d (ret=%d)\n", __FUNCTION__, port, ret);
+                       cb_log(0, port, "%s: Cannot get stack info for this port. (ret=%d)\n", __FUNCTION__, ret);
                        return -1;
                }
     
                stinf = (stack_info_t *)&frm->data.p;
     
-               cb_log(4, port, " --> Child %x\n",stinf->child[bidx]);
+               cb_log(8, port, " --> Child %x\n",stinf->child[bidx]);
        }
   
        return 0;
@@ -884,98 +1115,7 @@ int init_bc(struct misdn_stack *stack,  struct misdn_bchannel *bc, int midev, in
 
 
 
-struct misdn_stack * stack_nt_init(struct misdn_stack *stack, int midev, int port)
-{
-       int ret;
-       layer_info_t li;
-       interface_info_t ii;
-  
-  
-       cb_log(4, port, "Init. Stack on port:%d\n",port);
-       stack->mode = NT_MODE;
-  
-       stack->lower_id = mISDN_get_layerid(midev, stack->d_stid, 1); 
-       if (stack->lower_id <= 0) {
-               cb_log(0, port, "%s: Cannot get layer(%d) id of port:%d\n", __FUNCTION__, 1, port);
-               return(NULL);
-       }
-  
-  
-       memset(&li, 0, sizeof(li));
-       {
-               int l = sizeof(li.name);
-               strncpy(li.name,"net l2", l);
-               li.name[l-1] = 0;
-       }
-       li.object_id = -1;
-       li.extentions = 0;
-       li.pid.protocol[2] = ISDN_PID_L2_LAPD_NET;
-       li.pid.layermask = ISDN_LAYER((2));
-       li.st = stack->d_stid;
-  
-  
-       stack->upper_id = mISDN_new_layer(midev, &li);
-       if (stack->upper_id <= 0) {
-               cb_log(0, port, "%s: Cannot add layer %d of port:%d\n", __FUNCTION__, 2, port);
-               return(NULL);
-       }
-
-       cb_log(4, port, "NT Stacks upper_id %x\n",stack->upper_id);
-   
-       memset(&ii, 0, sizeof(ii));
-       ii.extentions = EXT_IF_EXCLUSIV;
-       ii.owner = stack->upper_id;
-       ii.peer = stack->lower_id;
-       ii.stat = IF_DOWN;
-       ret = mISDN_connect(midev, &ii);
-       if (ret) {
-               cb_log(0, port, "%s: Cannot connect layer %d of port:%d exclusively.\n", __FUNCTION__, 2, port);
-               return(NULL);
-       }
-
-       /* create nst (nt-mode only) */
-       {
-               memset(&stack->nst, 0, sizeof(net_stack_t));
-               memset(&stack->mgr, 0, sizeof(manager_t));
-    
-               stack->mgr.nst = &stack->nst;
-               stack->nst.manager = &stack->mgr;
-    
-               stack->nst.l3_manager = handle_event_nt;
-               stack->nst.device = midev;
-               stack->nst.cardnr = port;
-               stack->nst.d_stid = stack->d_stid;
-    
-#ifdef MISDNUSER_JOLLY
-               stack->nst.feature = FEATURE_NET_HOLD;
-               if (stack->ptp)
-                       stack->nst.feature |= FEATURE_NET_PTP;
-               if (stack->pri)
-                       stack->nst.feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
-#endif
-    
-               stack->nst.l1_id = stack->lower_id;
-               stack->nst.l2_id = stack->upper_id;
-    
-               msg_queue_init(&stack->nst.down_queue);
-    
-               Isdnl2Init(&stack->nst);
-               Isdnl3Init(&stack->nst);
-       }
-
-       misdn_lib_get_l1_up(stack);
-
-       if (stack->ptp) {
-               misdn_lib_get_l2_up(stack);
-               stack->l2link=0;
-       }
-       
-       
-       return stack;
-}
-
-
-struct misdn_stack* stack_te_init( int midev, int port, int ptp )
+struct misdn_stack* stack_init( int midev, int port, int ptp )
 {
        int ret;
        unsigned char buff[1025];
@@ -983,18 +1123,16 @@ struct misdn_stack* stack_te_init( int midev, int port, int ptp )
        stack_info_t *stinf;
        int i; 
        layer_info_t li;
-       interface_info_t ii;
+
        struct misdn_stack *stack = malloc(sizeof(struct misdn_stack));
        if (!stack ) return NULL;
 
-
-       //cb_log(2, "Init. Stack on port:%d\n",port);
-       cb_log(4, port, "Init. Stack on port:%d\n",port);
+       cb_log(8, port, "Init. Stack.\n");
   
        memset(stack,0,sizeof(struct misdn_stack));
   
        for (i=0; i<MAX_BCHANS + 1; i++ ) stack->channels[i]=0;
-  
+       
        stack->port=port;
        stack->midev=midev;
        stack->ptp=ptp;
@@ -1003,11 +1141,12 @@ struct misdn_stack* stack_te_init( int midev, int port, int ptp )
        stack->pri=0;
   
        msg_queue_init(&stack->downqueue);
+       msg_queue_init(&stack->upqueue);
   
        /* query port's requirements */
        ret = mISDN_get_stack_info(midev, port, buff, sizeof(buff));
        if (ret < 0) {
-               cb_log(0, port, "%s: Cannot get stack info for port:%d (ret=%d)\n", __FUNCTION__, port, ret);
+               cb_log(0, port, "%s: Cannot get stack info for this port. (ret=%d)\n", __FUNCTION__, ret);
                return(NULL);
        }
   
@@ -1021,13 +1160,12 @@ struct misdn_stack* stack_te_init( int midev, int port, int ptp )
   
        switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK) {
        case ISDN_PID_L0_TE_S0:
-               //cb_log(2, "TE Stack\n");
-               stack->mode = TE_MODE;
+               stack->nt=0;
                break;
        case ISDN_PID_L0_NT_S0:
-               cb_log(4, port, "NT Stack\n");
+               cb_log(8, port, "NT Stack\n");
 
-               return stack_nt_init(stack,midev,port); 
+               stack->nt=1;
                break;
 
        case ISDN_PID_L0_TE_U:
@@ -1039,82 +1177,138 @@ struct misdn_stack* stack_te_init( int midev, int port, int ptp )
        case ISDN_PID_L0_NT_UP2:
                break;
        case ISDN_PID_L0_TE_E1:
-               cb_log(4, port, "TE S2M Stack\n");
-               stack->mode = TE_MODE;
+               cb_log(8, port, "TE S2M Stack\n");
+               stack->nt=0;
                stack->pri=1;
                break;
        case ISDN_PID_L0_NT_E1:
-               cb_log(4, port, "TE S2M Stack\n");
-               stack->mode = NT_MODE;
+               cb_log(8, port, "TE S2M Stack\n");
+               stack->nt=1;
                stack->pri=1;
-    
-               return stack_nt_init(stack,midev,port); 
+               
                break;
        default:
-               cb_log(0, port, "unknown port(%d) type 0x%08x\n", port, stinf->pid.protocol[0]);
+               cb_log(0, port, "this is a unknown port type 0x%08x\n", stinf->pid.protocol[0]);
 
        }
-  
-       if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP ) { /* || (nt&&ptp) || pri */
-               stack->ptp = 1;
-       } else {
-               stack->ptp = 0;
-       }
 
-       stack->lower_id = mISDN_get_layerid(midev, stack->d_stid, 3); 
-       if (stack->lower_id <= 0) {
-               cb_log(0, stack->port, "No lower Id port:%d\n", stack->port);
-               return(NULL);
+       if (!stack->nt) {
+               if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP ) { 
+                       stack->ptp = 1;
+               } else {
+                       stack->ptp = 0;
+               }
        }
-  
-       memset(&li, 0, sizeof(li));
+       
        {
-               int l = sizeof(li.name);
-               strncpy(li.name, "user L4", l);
-               li.name[l-1] = 0;
-       }
-       li.object_id = -1;
-       li.extentions = 0;
-  
-       li.pid.protocol[4] = ISDN_PID_L4_CAPI20;
-  
-       li.pid.layermask = ISDN_LAYER((4));
-       li.st = stack->d_stid;
-       stack->upper_id = mISDN_new_layer(midev, &li);
-  
-       if (stack->upper_id <= 0)       {
-               cb_log(0, stack->port, "No Upper ID port:%d\n",stack->port);
-               return(NULL);
-       } 
-  
-       memset(&ii, 0, sizeof(ii));
-       ii.extentions = EXT_IF_EXCLUSIV | EXT_IF_CREATE;
-       ii.owner = stack->upper_id;
-       ii.peer = stack->lower_id;
-       ii.stat = IF_DOWN;
-       ret = mISDN_connect(midev, &ii);
-       if (ret) {
-               cb_log(0, stack->port, "No Connect port:%d\n", stack->port);
-               return NULL;
+               int ret;
+               int nt=stack->nt;
+
+               cb_log(8, port, "Init. Stack.\n");
+               
+               memset(&li, 0, sizeof(li));
+               {
+                       int l = sizeof(li.name);
+                       strncpy(li.name,nt?"net l2":"user l4", l);
+                       li.name[l-1] = 0;
+               }
+               li.object_id = -1;
+               li.extentions = 0;
+               li.pid.protocol[nt?2:4] = nt?ISDN_PID_L2_LAPD_NET:ISDN_PID_L4_CAPI20;
+               li.pid.layermask = ISDN_LAYER((nt?2:4));
+               li.st = stack->d_stid;
+               
+               
+               ret = mISDN_new_layer(midev, &li);
+               if (ret) {
+                       cb_log(0, port, "%s: Cannot add layer %d to this port.\n", __FUNCTION__, nt?2:4);
+                       return(NULL);
+               }
+               
+               
+               stack->upper_id = li.id;
+               ret = mISDN_register_layer(midev, stack->d_stid, stack->upper_id);
+               if (ret)
+               {
+                       cb_log(0,port,"Cannot register layer %d of this port.\n", nt?2:4);
+                       return(NULL);
+               }
+               
+               stack->lower_id = mISDN_get_layerid(midev, stack->d_stid, nt?1:3); 
+               if (stack->lower_id < 0) {
+                       cb_log(0, port, "%s: Cannot get layer(%d) id of this port.\n", __FUNCTION__, nt?1:3);
+                       return(NULL);
+               }
+               
+               stack->upper_id = mISDN_get_layerid(midev, stack->d_stid, nt?2:4);
+               if (stack->upper_id < 0) {
+                       cb_log(0, port, "%s: Cannot get layer(%d) id of this port.\n", __FUNCTION__, 2);
+                       return(NULL);
+               }
+               
+               cb_log(8, port, "NT Stacks upper_id %x\n",stack->upper_id);
+               
+               
+               /* create nst (nt-mode only) */
+               if (nt) {
+                       
+                       memset(&stack->nst, 0, sizeof(net_stack_t));
+                       memset(&stack->mgr, 0, sizeof(manager_t));
+    
+                       stack->mgr.nst = &stack->nst;
+                       stack->nst.manager = &stack->mgr;
+    
+                       stack->nst.l3_manager = handle_event_nt;
+                       stack->nst.device = midev;
+                       stack->nst.cardnr = port;
+                       stack->nst.d_stid = stack->d_stid;
+    
+                       stack->nst.feature = FEATURE_NET_HOLD;
+                       if (stack->ptp)
+                               stack->nst.feature |= FEATURE_NET_PTP;
+                       if (stack->pri)
+                               stack->nst.feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
+                       
+                       stack->nst.l1_id = stack->lower_id;
+                       stack->nst.l2_id = stack->upper_id;
+                       
+                       msg_queue_init(&stack->nst.down_queue);
+                       
+                       Isdnl2Init(&stack->nst);
+                       Isdnl3Init(&stack->nst);
+               } 
+               
+               stack->l1link=0;
+               stack->l2link=0;
+#if 0  
+               if (!stack->nt) {
+                       misdn_lib_get_short_status(stack);
+               } else {
+                       misdn_lib_get_l1_up(stack);
+                       if (!stack->ptp) misdn_lib_get_l1_up(stack);
+                       misdn_lib_get_l2_up(stack);
+               }
+#endif
+               misdn_lib_get_short_status(stack);
+               misdn_lib_get_l1_up(stack);
+               misdn_lib_get_l2_up(stack);
        }
-  
-       misdn_lib_get_l1_up(stack);
-       misdn_lib_get_l2_status(stack);
+
+       cb_log(8,0,"stack_init: port:%d lowerId:%x  upperId:%x\n",stack->port,stack->lower_id, stack->upper_id);
        
-       /*  initially, we assume that the link is NOT up */
-       stack->l2link = 0;
-       stack->l1link = 0;
-  
-       stack->next=NULL;
-  
        return stack;
-  
 }
 
-void stack_te_destroy(struct misdn_stack* stack)
+
+void stack_destroy(struct misdn_stack* stack)
 {
        char buf[1024];
        if (!stack) return;
+
+       if (stack->nt) {
+               cleanup_Isdnl2(&stack->nst);
+               cleanup_Isdnl3(&stack->nst);
+       }
   
        if (stack->lower_id) 
                mISDN_write_frame(stack->midev, buf, stack->lower_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
@@ -1127,11 +1321,12 @@ void stack_te_destroy(struct misdn_stack* stack)
 struct misdn_stack * find_stack_by_addr(int  addr)
 {
        struct misdn_stack *stack;
-  
+       
        for (stack=glob_mgr->stack_list;
             stack;
             stack=stack->next) {
-               if ( stack->upper_id == addr) return stack;
+               if ( (stack->upper_id&STACK_ID_MASK) == (addr&STACK_ID_MASK)) return stack;
+
        }
   
        return NULL;
@@ -1193,72 +1388,113 @@ struct misdn_bchannel *find_bc_holded(struct misdn_stack *stack)
 
 struct misdn_bchannel *find_bc_by_addr(unsigned long addr)
 {
-       int port = addr & IF_CONTRMASK;
        struct misdn_stack* stack;
        int i;
 
-
+       
        for (stack=glob_mgr->stack_list;
             stack;
             stack=stack->next) {
-    
-               if (stack->port == port) {
-                       for (i=0; i< stack->b_num; i++) {
-                               if (stack->bc[i].addr==addr) {
-                                       return &stack->bc[i];
-                               }
+               
+               for (i=0; i< stack->b_num; i++) {
+
+                       if ( (stack->bc[i].addr&STACK_ID_MASK)==(addr&STACK_ID_MASK) ||  stack->bc[i].layer_id== addr ) {
+                               return &stack->bc[i];
                        }
                }
+               
        }
-  
+
+       
+       return NULL;
+}
+
+
+struct misdn_bchannel *find_bc_by_channel(int port, int channel)
+{
+       struct misdn_stack* stack=find_stack_by_port(port);
+       int i;
+
+       if (!stack) return NULL;        
+       
+       for (i=0; i< stack->b_num; i++) {
+               if ( stack->bc[i].channel== channel ) {
+                       return &stack->bc[i];
+               }
+       }
+               
        return NULL;
 }
 
 
 
 
+
 int handle_event ( struct misdn_bchannel *bc, enum event_e event, iframe_t *frm)
 {
        struct misdn_stack *stack=get_stack_by_bc(bc);
-       if (stack->mode == TE_MODE) {
+       
+       if (!stack->nt) {
+               
                switch (event) {
 
                case EVENT_CONNECT_ACKNOWLEDGE:
-                       manager_bchannel_activate(bc);
+#if 0
+                       if ( !misdn_cap_is_speech(bc->capability)) {
+                               int ret=setup_bc(bc);
+                               if (ret == -EINVAL){
+                                       cb_log(0,bc->port,"send_event: setup_bc failed\n");
+                               }
+                       }
+#endif 
                        break;
                case EVENT_CONNECT:
-                       
+
                        if ( *bc->crypt_key ) {
-                               cb_log(4, stack->port, "ENABLING BLOWFISH port:%d channel:%d oad%d:%s dad%d:%s\n", stack->port, bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
-                               
+                               cb_log(4, stack->port, "ENABLING BLOWFISH channel:%d oad%d:%s dad%d:%s\n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
                                manager_ph_control_block(bc,  BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) );
                        }
-               case EVENT_SETUP:
-                       if (bc->channel>0 && bc->channel<255)
-                               set_chan_in_stack(stack, bc->channel);
-                       break;
                case EVENT_ALERTING:
                case EVENT_PROGRESS:
                case EVENT_PROCEEDING:
                case EVENT_SETUP_ACKNOWLEDGE:
+
+               setup_bc(bc);
+               
+               case EVENT_SETUP:
                        
                {
-                       struct misdn_stack *stack=find_stack_by_port(frm->addr&IF_CONTRMASK);
-                       if (!stack) return -1;
-                       
                        if (bc->channel == 0xff) {
                                bc->channel=find_free_chan_in_stack(stack, 0);
                                if (!bc->channel) {
                                        cb_log(0, stack->port, "Any Channel Requested, but we have no more!!\n");
                                        break;
                                }
-                       } 
-                       
-                       if (stack->mode == TE_MODE) {
-                               setup_bc(bc);
+                       }  
+
+                       if (bc->channel >0 && bc->channel<255) {
+                               set_chan_in_stack(stack ,bc->channel);
+                       }
+
+#if 0
+                       int ret=setup_bc(bc);
+                       if (ret == -EINVAL){
+                               cb_log(0,bc->port,"handle_event: setup_bc failed\n");
+                               misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
                        }
+#endif
                }
-               
+               break;
+
+               case EVENT_RELEASE_COMPLETE:
+               case EVENT_RELEASE:
+                       if (bc->channel>0)
+                               empty_chan_in_stack(stack,bc->channel);
+                       int tmpcause=bc->cause; 
+                       empty_bc(bc);
+                       bc->cause=tmpcause;
+                       clean_up_bc(bc);
+                       break;
                default:
                        break;
                }
@@ -1271,31 +1507,28 @@ int handle_event ( struct misdn_bchannel *bc, enum event_e event, iframe_t *frm)
 int handle_new_process(struct misdn_stack *stack, iframe_t *frm)
 {
   
-       struct misdn_bchannel* bc=misdn_lib_get_free_bc(frm->addr&IF_CONTRMASK, 0);
+       struct misdn_bchannel* bc=misdn_lib_get_free_bc(stack->port, 0);
+       
        
        if (!bc) {
-               cb_log(0, 0, " --> !! lib: No free channel!\n");
+               cb_log(0, stack->port, " --> !! lib: No free channel!\n");
                return -1;
        }
   
-       cb_log(4, stack->port, " --> new_process: New L3Id: %x\n",frm->dinfo);
+       cb_log(7, stack->port, " --> new_process: New L3Id: %x\n",frm->dinfo);
        bc->l3_id=frm->dinfo;
-       
-       if (mypid>5000) mypid=0;
-       bc->pid=mypid++;
        return 0;
 }
 
-int handle_cr ( iframe_t *frm)
+int handle_cr ( struct misdn_stack *stack, iframe_t *frm)
 {
-       struct misdn_stack *stack=find_stack_by_port(frm->addr&IF_CONTRMASK);
-
        if (!stack) return -1;
   
        switch (frm->prim) {
        case CC_NEW_CR|INDICATION:
-               cb_log(4, stack->port, " --> lib: NEW_CR Ind with l3id:%x port:%d\n",frm->dinfo, stack->port);
-               handle_new_process(stack, frm); 
+               cb_log(7, stack->port, " --> lib: NEW_CR Ind with l3id:%x on this port.\n",frm->dinfo);
+               if (handle_new_process(stack, frm) <0) 
+                       return -1;
                return 1;
        case CC_NEW_CR|CONFIRM:
                return 1;
@@ -1312,22 +1545,29 @@ int handle_cr ( iframe_t *frm)
                        struct misdn_bchannel dummybc;
       
                        if (!bc) {
-                               cb_log(4, stack->port, " --> Didn't found BC so temporarly creating dummy BC (l3id:%x) on port:%d\n", frm->dinfo, stack->port);
+                               cb_log(4, stack->port, " --> Didn't found BC so temporarly creating dummy BC (l3id:%x) on this port.\n", frm->dinfo);
                                memset (&dummybc,0,sizeof(dummybc));
                                dummybc.port=stack->port;
                                dummybc.l3_id=frm->dinfo;
+                               dummybc.nt=stack->nt;
                                bc=&dummybc; 
                        }
       
                        if (bc) {
                                cb_log(4, stack->port, " --> lib: CLEANING UP l3id: %x\n",frm->dinfo);
-                               empty_chan_in_stack(stack,bc->channel);
+                               if (bc->channel>0)
+                                       empty_chan_in_stack(stack,bc->channel);
                                empty_bc(bc);
+                               
                                clean_up_bc(bc);
+                               
                                dump_chan_list(stack);
-                               bc->pid = 0;
-                               cb_event(EVENT_CLEANUP, bc, glob_mgr->user_data);
+                               /*bc->pid = 0;*/
+                               bc->need_disconnect=0;
+                               bc->need_release=0;
+                               bc->need_release_complete=0;
                                
+                               cb_event(EVENT_CLEANUP, bc, glob_mgr->user_data);
                                if (bc->stack_holder) {
                                        cb_log(4,stack->port, "REMOVEING Holder\n");
                                        stack_holder_remove( stack, bc);
@@ -1335,7 +1575,7 @@ int handle_cr ( iframe_t *frm)
                                }
                        }
                        else {
-                               if (stack->mode == NT_MODE
+                               if (stack->nt
                                        cb_log(4, stack->port, "BC with dinfo: %x  not found.. (prim was %x and addr %x)\n",frm->dinfo, frm->prim, frm->addr);
                        }
       
@@ -1358,10 +1598,10 @@ void misdn_lib_release(struct misdn_bchannel *bc)
                return;
        }
        
-       if (bc->channel>=0) {
+       if (bc->channel>0) {
                empty_chan_in_stack(stack,bc->channel);
-               empty_bc(bc);
        }
+       empty_bc(bc);
        clean_up_bc(bc);
 }
 
@@ -1369,7 +1609,7 @@ void misdn_lib_release(struct misdn_bchannel *bc)
 
 
 int misdn_lib_get_port_up (int port) 
-{ /* Pull Up L1 if we have JOLLY */ 
+{ /* Pull Up L1 */ 
        struct misdn_stack *stack;
        
        for (stack=glob_mgr->stack_list;
@@ -1390,37 +1630,75 @@ int misdn_lib_get_port_up (int port)
 }
 
 
+int misdn_lib_get_port_down (int port) 
+{ /* Pull Down L1 */ 
+       struct misdn_stack *stack;
+       for (stack=glob_mgr->stack_list;
+            stack;
+            stack=stack->next) {
+               if (stack->port == port) {
+                               if (stack->l2link)
+                                       misdn_lib_get_l2_down(stack);
+                               misdn_lib_get_l1_down(stack);
+                       return 0;
+               }
+       }
+       return 0;
+}
+
 int misdn_lib_send_facility(struct misdn_bchannel *bc, enum facility_type fac, void *data)
 {
-       bc->facility=fac;
-       strcpy(bc->facility_calldeflect_nr,(char*)data);
+       switch (fac) {
+       case FACILITY_CALLDEFLECT:
+               strcpy(bc->out_fac.calldeflect_nr,(char*)data);
+               break;
+       default:
+               cb_log(1,bc?bc->port:0,"We don't handle this facility yet: %d\n",fac);
+               return 0;
+       }
+       
+       bc->out_fac_type=fac;
        
        misdn_lib_send_event(bc,EVENT_FACILITY);
        return 0;
 }
 
 
-int misdn_lib_port_up(int port)
+int misdn_lib_port_up(int port, int check)
 {
        struct misdn_stack *stack;
-       
+
+
        for (stack=glob_mgr->stack_list;
             stack;
             stack=stack->next) {
                
+               if ( !stack->ptp && !check) return 1;
+               
                if (stack->port == port) {
-                       if (stack->mode == NT_MODE) {
-                               if (stack->l1link)
+
+                       if (stack->blocked) {
+                               cb_log(0,port, "Port Blocked:%d L2:%d L1:%d\n", stack->blocked, stack->l2link, stack->l1link);
+                               return -1;
+                       }
+
+                       if (stack->ptp ) {
+
+                               if (stack->l1link && stack->l2link) {
                                        return 1;
-                               else
+                               } else {
+                                       cb_log(0,port, "Port Down L2:%d L1:%d\n",
+                                               stack->l2link, stack->l1link);
                                        return 0;
+                               }
                        } else {
-                               if (stack->l1link)
+                               if ( stack->l1link)
                                        return 1;
-                               else
+                               else {
+                                       cb_log(0,port, "Port down PMP\n");
                                        return 0;
+                               }
                        }
-
                }
        }
   
@@ -1433,38 +1711,31 @@ handle_event_nt(void *dat, void *arg)
 {
        manager_t *mgr = (manager_t *)dat;
        msg_t *msg = (msg_t *)arg;
-#ifdef MISDNUSER_JOLLY
        mISDNuser_head_t *hh;
-#else
-       mISDN_head_t *hh;
-#endif
+       int reject=0;
+
        struct misdn_stack *stack=find_stack_by_mgr(mgr);
        int port;
 
        if (!msg || !mgr)
                return(-EINVAL);
 
-#ifdef MISDNUSER_JOLLY
        hh=(mISDNuser_head_t*)msg->data;
-#else
-       hh=(mISDN_head_t*)msg->data;
-#endif
-  
-       port=hh->dinfo & IF_CONTRMASK;
-  
-       cb_log(4, stack->port, " --> lib: prim %x dinfo %x port: %d\n",hh->prim, hh->dinfo ,stack->port);
-  
+       port=stack->port;
+       
+       cb_log(5, stack->port, " --> lib: prim %x dinfo %x\n",hh->prim, hh->dinfo);
        {
                switch(hh->prim){
-                       
                case CC_RETRIEVE|INDICATION:
                {
                        iframe_t frm; /* fake te frm to add callref to global callreflist */
                        frm.dinfo = hh->dinfo;
-                       frm.addr=stack->upper_id;
+
+                       frm.addr=stack->upper_id | FLG_MSG_DOWN;
+
                        frm.prim = CC_NEW_CR|INDICATION;
                        
-                       if (handle_cr(&frm)< 0) {
+                       if (handle_cr( stack, &frm)< 0) {
                                msg_t *dmsg;
                                cb_log(4, stack->port, "Patch from MEIDANIS:Sending RELEASE_COMPLETE %x (No free Chan for you..)\n", hh->dinfo);
                                dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST,MT_RELEASE_COMPLETE, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1);
@@ -1474,11 +1745,16 @@ handle_event_nt(void *dat, void *arg)
                        }
                        
                        struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
-                       cb_event(EVENT_NEW_BC, bc, glob_mgr->user_data);
                        struct misdn_bchannel *hold_bc=stack_holder_find(stack,bc->l3_id);
+
                        if (hold_bc) {
+
                                cb_log(4, stack->port, "REMOVEING Holder\n");
                                stack_holder_remove(stack, hold_bc);
+
+                               memcpy(bc,hold_bc,sizeof(struct misdn_bchannel));
+                               cb_event(EVENT_NEW_BC, hold_bc, bc);
+
                                free(hold_bc);
                        }
                        
@@ -1486,16 +1762,14 @@ handle_event_nt(void *dat, void *arg)
                        
                        break;
                        
-                       
                case CC_SETUP|CONFIRM:
                {
                        struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
                        int l3id = *((int *)(((u_char *)msg->data)+ mISDNUSER_HEAD_SIZE));
-                       
-                       cb_log(4, bc?stack->port:0, " --> lib: Event_ind:SETUP CONFIRM [NT] : new L3ID  is %x\n",l3id );
-       
-                       if (!bc) { cb_log(4, 0, "Bc Not found (after SETUP CONFIRM)\n"); return 0; }
+                       cb_log(4, stack->port, " --> lib: Event_ind:SETUP CONFIRM [NT] : new L3ID  is %x\n",l3id );
        
+                       if (!bc) { cb_log(4, stack->port, "Bc Not found (after SETUP CONFIRM)\n"); return 0; }
+                       cb_log (2,bc->port,"I IND :CC_SETUP|CONFIRM: old l3id:%x new l3id:%x\n", bc->l3_id, l3id);
                        bc->l3_id=l3id;
                        cb_event(EVENT_NEW_L3ID, bc, glob_mgr->user_data);
                }
@@ -1509,7 +1783,7 @@ handle_event_nt(void *dat, void *arg)
                        frm.addr=stack->upper_id;
                        frm.prim = CC_NEW_CR|INDICATION;
                        
-                       if (handle_cr(&frm)< 0) {
+                       if (handle_cr(stack, &frm)< 0) {
                                msg_t *dmsg;
                                cb_log(4, stack->port, "Patch from MEIDANIS:Sending RELEASE_COMPLETE %x (No free Chan for you..)\n", hh->dinfo);
                                dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST,MT_RELEASE_COMPLETE, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1);
@@ -1520,17 +1794,35 @@ handle_event_nt(void *dat, void *arg)
                }
                break;
 
-
-               case CC_CONNECT|INDICATION:
+               case CC_CONNECT_ACKNOWLEDGE|INDICATION:
+#if 0
+               {
+                       struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
+                       if (bc) {
+                               if ( !misdn_cap_is_speech(bc->capability)) {
+                                       int ret=setup_bc(bc);
+                                       if (ret == -EINVAL){
+                                               cb_log(0,bc->port,"send_event: setup_bc failed\n");
+                                               
+                                       }
+                               }
+                       }
+               }
+#endif
+               break;
+               
                case CC_ALERTING|INDICATION:
                case CC_PROCEEDING|INDICATION:
-
+               case CC_SETUP_ACKNOWLEDGE|INDICATION:
+                       if(!stack->ptp) break;  
+               case CC_CONNECT|INDICATION:
                {
+#if 0
                        struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
                        
                        if (!bc) {
                                msg_t *dmsg;
-                               cb_log(0, stack->port,"!!!! We didn't found our bc, dinfo:%x port:%d\n",hh->dinfo, stack->port);
+                               cb_log(0, stack->port,"!!!! We didn't found our bc, dinfo:%x on this port.\n",hh->dinfo);
                                
                                cb_log(0, stack->port, "Releaseing call %x (No free Chan for you..)\n", hh->dinfo);
                                dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST,MT_RELEASE_COMPLETE, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1);
@@ -1539,8 +1831,12 @@ handle_event_nt(void *dat, void *arg)
                                return 0;
                                
                        }
-                       
-                       setup_bc(bc);
+                       int ret=setup_bc(bc);
+                       if (ret == -EINVAL){
+                               cb_log(0,bc->port,"handle_event_nt: setup_bc failed\n");
+                               misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
+                       }
+#endif
                }
                break;
                case CC_DISCONNECT|INDICATION:
@@ -1548,16 +1844,31 @@ handle_event_nt(void *dat, void *arg)
                        struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
                        if (!bc) {
                                bc=find_bc_by_masked_l3id(stack, hh->dinfo, 0xffff0000);
-                               if (bc) { //repair reject bug
+                               if (bc) { /*repair reject bug*/
                                        int myprocid=bc->l3_id&0x0000ffff;
                                        hh->dinfo=(hh->dinfo&0xffff0000)|myprocid;
-                                       cb_log(4,stack->port,"Repaired reject Bug, new dinfo: %x\n",hh->dinfo);
+                                       cb_log(3,stack->port,"Reject dinfo: %x cause:%d\n",hh->dinfo,bc->cause);
+                                       reject=1;               
                                }
                        }
                }
                break;
-
-               case CC_RELEASE_COMPLETE|INDICATION:
+               
+               case CC_FACILITY|INDICATION:
+               {
+                       struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
+                       if (!bc) {
+                               bc=find_bc_by_masked_l3id(stack, hh->dinfo, 0xffff0000);
+                               if (bc) { 
+                                       int myprocid=bc->l3_id&0x0000ffff;
+                                       hh->dinfo=(hh->dinfo&0xffff0000)|myprocid;
+                                       cb_log(4,bc->port,"Repaired reject Bug, new dinfo: %x\n",hh->dinfo);
+                               }
+                       }
+               }
+               break;
+               
+               case CC_RELEASE_COMPLETE|INDICATION:
                        break;
 
                case CC_SUSPEND|INDICATION:
@@ -1574,13 +1885,8 @@ handle_event_nt(void *dat, void *arg)
                        break;
 
                case CC_RELEASE|CONFIRM:
-               {
-                       struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
-                       cb_log(4, stack->port, " --> RELEASE CONFIRM, sending RELEASE_COMPLETE\n");
-                       if (bc) misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
-               }
-               hh->prim=CC_RELEASE|INDICATION;
-               break;  
+                       break;
+                       
                case CC_RELEASE|INDICATION:
                        break;
 
@@ -1590,42 +1896,35 @@ handle_event_nt(void *dat, void *arg)
                        struct misdn_bchannel dummybc;
                        iframe_t frm; /* fake te frm to remove callref from global callreflist */
                        frm.dinfo = hh->dinfo;
-                       frm.addr=stack->upper_id;
+
+                       frm.addr=stack->upper_id | FLG_MSG_DOWN;
+
                        frm.prim = CC_RELEASE_CR|INDICATION;
                        cb_log(4, stack->port, " --> Faking Realease_cr for %x\n",frm.addr);
                        /** removing procid **/
-
                        if (!bc) {
-                               cb_log(4, stack->port, " --> Didn't found BC so temporarly creating dummy BC (l3id:%x) on port:%d\n", hh->dinfo, stack->port);
+                               cb_log(4, stack->port, " --> Didn't found BC so temporarly creating dummy BC (l3id:%x) on this port.\n", hh->dinfo);
                                memset (&dummybc,0,sizeof(dummybc));
                                dummybc.port=stack->port;
                                dummybc.l3_id=hh->dinfo;
+                               dummybc.nt=stack->nt;
                                bc=&dummybc; 
                        }
        
                        if (bc) {
-#ifdef MISDNUSER_JOLLY
                                if ( (bc->l3_id & 0xff00) == 0xff00) {
-                                       cb_log(4, stack->port, " --> Removing Process Id:%x on port:%d\n", bc->l3_id&0xff, stack->port);
+                                       cb_log(4, stack->port, " --> Removing Process Id:%x on this port.\n", bc->l3_id&0xff);
                                        stack->procids[bc->l3_id&0xff] = 0 ;
                                }
-#else
-                               if ( (bc->l3_id & 0xfff0) == 0xfff0) {
-                                       cb_log(4, stack->port, " --> Removing Process Id:%x on port:%d\n", bc->l3_id&0xf, stack->port);
-                                       stack->procids[bc->l3_id&0xf] = 0 ;
-           
-                               }
-         
-#endif
-
                        }
-                       else cb_log(0, stack->port, "Couldnt find BC so I couldnt remove the Process!!!! this is bad Port:%d\n", stack->port );
+                       else cb_log(0, stack->port, "Couldnt find BC so I couldnt remove the Process!!!! this is a bad port.\n");
        
-                       handle_cr(&frm);
+                       if (handle_cr(stack, &frm)<0) {
+                       }
+
                        free_msg(msg);
                        return 0 ;
                }
-      
                break;
       
                case CC_NEW_CR|INDICATION:
@@ -1634,25 +1933,16 @@ handle_event_nt(void *dat, void *arg)
                {
                        struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
                        int l3id = *((int *)(((u_char *)msg->data)+ mISDNUSER_HEAD_SIZE));
-                       if (!bc) { cb_log(0, 0, " --> In NEW_CR: didn't found bc ??\n"); return -1;};
-#ifdef MISDNUSER_JOLLY
+                       if (!bc) { cb_log(0, stack->port, " --> In NEW_CR: didn't found bc ??\n"); return -1;};
                        if (((l3id&0xff00)!=0xff00) && ((bc->l3_id&0xff00)==0xff00)) {
-                               cb_log(4, stack->port, " --> Removing Process Id:%x on port:%d\n", 0xff&bc->l3_id, stack->port);
+                               cb_log(4, stack->port, " --> Removing Process Id:%x on this port.\n", 0xff&bc->l3_id);
                                stack->procids[bc->l3_id&0xff] = 0 ;
                        }
-#else
-                       if (((l3id&0xfff0)!=0xfff0) && ((bc->l3_id&0xfff0)==0xfff0)) {
-                               cb_log(4, stack->port, "Removing Process Id:%x on port:%d\n", 0xf&bc->l3_id, stack->port);
-                               stack->procids[bc->l3_id&0xf] = 0 ;
-                       }
-
-#endif
                        cb_log(4, stack->port, "lib: Event_ind:CC_NEW_CR : very new L3ID  is %x\n",l3id );
        
                        bc->l3_id =l3id;
                        cb_event(EVENT_NEW_L3ID, bc, glob_mgr->user_data);
        
-       
                        free_msg(msg);
                        return 0;
                }
@@ -1660,24 +1950,44 @@ handle_event_nt(void *dat, void *arg)
                case DL_ESTABLISH | INDICATION:
                case DL_ESTABLISH | CONFIRM:
                {
-                       cb_log(4, stack->port, "%% GOT L2 Activate Info port:%d\n",stack->port);
+                       cb_log(3, stack->port, "%% GOT L2 Activate Info.\n");
+                       
+                       if (stack->ptp && stack->l2link) {
+                               cb_log(0, stack->port, "%% GOT L2 Activate Info. but we're activated already.. this l2 is faulty, blocking port\n");
+                               cb_event(EVENT_PORT_ALARM, &stack->bc[0], glob_mgr->user_data);
+                       }
+                       
                        stack->l2link = 1;
-       
+                       stack->l2upcnt=0;
+                       
                        free_msg(msg);
                        return 0;
                }
                break;
 
+
                case DL_RELEASE | INDICATION:
                case DL_RELEASE | CONFIRM:
                {
-                       cb_log(4, stack->port, "%% GOT L2 DeActivate Info port:%d\n",stack->port);
-                       stack->l2link = 0;
-                       
-                       /** Clean the L3 here **/
-                       if (cb_clearl3_true())
-                               clear_l3(stack);
+                       if (stack->ptp) {
+                               cb_log(3 , stack->port, "%% GOT L2 DeActivate Info.\n");
+
+                               if (stack->l2upcnt>3) {
+                                       cb_log(0 , stack->port, "!!! Could not Get the L2 up after 3 Attemps!!!\n");
+                               }  else {
+#if 0
+                                       if (stack->nt) misdn_lib_reinit_nt_stack(stack->port);
+#endif
+                                       if (stack->l1link) {
+                                               misdn_lib_get_l2_up(stack);
+                                               stack->l2upcnt++;
+                                       }
+                               }
+                               
+                       } else 
+                               cb_log(3, stack->port, "%% GOT L2 DeActivate Info.\n");
                        
+                       stack->l2link = 0;
                        free_msg(msg);
                        return 0;
                }
@@ -1685,8 +1995,6 @@ handle_event_nt(void *dat, void *arg)
                }
        }
        
-  
-
        {
                /*  Parse Events and fire_up to App. */
                struct misdn_bchannel *bc;
@@ -1698,21 +2006,75 @@ handle_event_nt(void *dat, void *arg)
     
                if (!bc) {
       
-                       cb_log(4, stack->port, " --> Didn't found BC so temporarly creating dummy BC (l3id:%x) on port:%d\n", hh->dinfo, stack->port);
+                       cb_log(4, stack->port, " --> Didn't found BC so temporarly creating dummy BC (l3id:%x).\n", hh->dinfo);
                        memset (&dummybc,0,sizeof(dummybc));
                        dummybc.port=stack->port;
                        dummybc.l3_id=hh->dinfo;
+                       dummybc.nt=stack->nt;
                        bc=&dummybc; 
                }
                if (bc ) {
                        isdn_msg_parse_event(msgs_g,msg,bc, 1);
+
+                       switch (event) {
+                               case EVENT_SETUP:
+                                       if (bc->channel>0 && bc->channel<255) {
+
+                                               if (stack->ptp) 
+                                                       set_chan_in_stack(stack, bc->channel);
+                                               else 
+                                                       cb_log(0,stack->port," --> PTMP but channel requested\n");
+
+                                       } else {
+
+                                               bc->channel = find_free_chan_in_stack(stack, 0);
+                                               if (!bc->channel) {
+                                                       cb_log(0, stack->port, " No free channel at the moment\n");
+                                       
+                                                       msg_t *dmsg;
+                               
+                                                       cb_log(0, stack->port, "Releaseing call %x (No free Chan for you..)\n", hh->dinfo);
+                                                               dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST,MT_RELEASE_COMPLETE, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1);
+                                                       stack->nst.manager_l3(&stack->nst, dmsg);
+                                                       free_msg(msg);
+                                                       return 0;
+                                               }
+                                               
+                                       }
+#if 0
+                                       setup_bc(bc);
+#endif
+
+                                       break;
+                               case EVENT_RELEASE:
+                               case EVENT_RELEASE_COMPLETE:
+                                       if (bc->channel>0)
+                                               empty_chan_in_stack(stack, bc->channel);
+                                       int tmpcause=bc->cause; 
+                                       empty_bc(bc);
+                                       bc->cause=tmpcause;
+                                       clean_up_bc(bc);
+                                       break;
+
+                               default:
+                               break;
+                       }
                        
                        if(!isdn_get_info(msgs_g,event,1)) {
                                cb_log(4, stack->port, "Unknown Event Ind: prim %x dinfo %x\n",hh->prim, hh->dinfo);
                        } else {
+                               if (reject) {
+                                       switch(bc->cause){
+                                               case 17:
+                                                       cb_log(1, stack->port, "Siemens Busy reject..\n");
+
+                                                       break;
+                                               default:
+                                                       break;
+                                       }
+                               }
                                cb_event(event, bc, glob_mgr->user_data);
                        }
-
       
                } else {
                        cb_log(4, stack->port, "No BC found with l3id: prim %x dinfo %x\n",hh->prim, hh->dinfo);
@@ -1749,7 +2111,7 @@ int handle_timers(msg_t* msg)
                     stack = stack->next) {
                        itimer_t *it;
       
-                       if (stack->mode != NT_MODE) continue;
+                       if (!stack->nt) continue;
       
                        it = stack->nst.tlist;
                        /* find timer */
@@ -1780,129 +2142,221 @@ int handle_timers(msg_t* msg)
 
 
 
+void misdn_lib_tone_generator_start(struct misdn_bchannel *bc)
+{
+       bc->generate_tone=1;
+}
+
+void misdn_lib_tone_generator_stop(struct misdn_bchannel *bc)
+{
+       bc->generate_tone=0;
+}
+
 
 static int do_tone(struct misdn_bchannel *bc, int len)
 {
-       char buf[4096 + mISDN_HEADER_LEN];
-       iframe_t *frm= (iframe_t*)buf;
-       int  r;
-       struct misdn_stack *stack=get_stack_by_bc(bc);
+       bc->tone_cnt=len;
+       
+       if (bc->generate_tone) {
+               cb_event(EVENT_TONE_GENERATE, bc, glob_mgr->user_data);
+               
+               if ( !bc->nojitter ) {
+                       misdn_tx_jitter(bc,len);
+               }
+               
+               return 1;
+       }
        
-       if (bc->tone == TONE_NONE) return 0;
+       return 0;
+}
 
-       frm->prim = DL_DATA|REQUEST;
-       frm->dinfo = 0;
-       frm->addr = bc->addr | IF_DOWN;
-  
-       bc->tone_cnt+=len;
 
-       if (bc->tone_cnt < TONE_425_SIZE) return 1;
 
-       switch(bc->tone) {
-       case TONE_DIAL:
-       {
-               frm->len = TONE_425_SIZE;
-               memcpy(&buf[mISDN_HEADER_LEN], tone_425_flip,TONE_425_SIZE);
-      
-               r=mISDN_write(stack->midev, buf, frm->len + mISDN_HEADER_LEN, TIMEOUT_1SEC);
-               if (r<frm->len) {
-                       perror("Error written less than told bytes :(\n");
+void misdn_tx_jitter(struct misdn_bchannel *bc, int len)
+{
+       char buf[4096 + mISDN_HEADER_LEN];
+       char *data=&buf[mISDN_HEADER_LEN];
+       iframe_t *txfrm= (iframe_t*)buf;
+       int jlen, r;
+       
+       jlen=cb_jb_empty(bc,data,len);
+       
+       if (jlen) {
+               flip_buf_bits( data, jlen);
+               
+               if (jlen < len) {
+                       cb_log(7,bc->port,"Jitterbuffer Underrun.\n");
                }
-       }
-       break;
 
-       case TONE_ALERTING:
-               bc->tone_cnt2++;
-    
-               if (bc->tone_cnt2 <= TONE_ALERT_CNT) {
-                       frm->len = TONE_425_SIZE;
-                       memcpy(&buf[mISDN_HEADER_LEN], tone_425_flip,TONE_425_SIZE);
-                       r=mISDN_write(stack->midev, buf, frm->len + mISDN_HEADER_LEN, TIMEOUT_1SEC);
-                       if (r<frm->len) {
-                               perror("Error written less than told bytes :(\n");
-                       }
-               } else if (bc->tone_cnt2 <= (TONE_ALERT_SILENCE_CNT)) {
-                       frm->len = TONE_SILENCE_SIZE;
-                       memcpy(&buf[mISDN_HEADER_LEN], tone_silence_flip ,TONE_SILENCE_SIZE);
-                       r=mISDN_write(stack->midev, buf, frm->len + mISDN_HEADER_LEN, TIMEOUT_1SEC);
-               } else {
-                       bc->tone_cnt2=-1;
+               txfrm->prim = DL_DATA|REQUEST;
+               
+               txfrm->dinfo = 0;
+               
+               txfrm->addr = bc->addr|FLG_MSG_DOWN; /*  | IF_DOWN; */
+               
+               txfrm->len =jlen;
+               cb_log(9, bc->port, "Transmitting %d samples 2 misdn\n", txfrm->len);
+               
+               r=mISDN_write( glob_mgr->midev, buf, txfrm->len + mISDN_HEADER_LEN, 8000 );
+       } else {
+#define MISDN_GEN_SILENCE
+#ifdef MISDN_GEN_SILENCE
+               int cnt=len/TONE_SILENCE_SIZE;
+               int rest=len%TONE_SILENCE_SIZE;
+               int i;
+               
+               for (i=0; i<cnt; i++) {
+                       memcpy(data, tone_silence_flip, TONE_SILENCE_SIZE );
+                       data +=TONE_SILENCE_SIZE;
                }
-               break;
-       case TONE_BUSY:
-               bc->tone_cnt2++;
-    
-               if (bc->tone_cnt2 <= TONE_BUSY_CNT) {
-                       frm->len = TONE_425_SIZE;
-                       memcpy(&buf[mISDN_HEADER_LEN], tone_425_flip,TONE_425_SIZE);
-                       r=mISDN_write(stack->midev, buf, frm->len + mISDN_HEADER_LEN, TIMEOUT_1SEC);
-                       if (r<frm->len) {
-                               perror("Error written less than told bytes :(\n");
-                       }
-               } else if (bc->tone_cnt2 <= (TONE_BUSY_SILENCE_CNT)) {
-                       frm->len = TONE_SILENCE_SIZE;
-                       memcpy(&buf[mISDN_HEADER_LEN], tone_silence_flip ,TONE_SILENCE_SIZE);
-                       r=mISDN_write(stack->midev, buf, frm->len + mISDN_HEADER_LEN, TIMEOUT_1SEC);
-               } else {
-                       bc->tone_cnt2=-1;
+               
+               if (rest) {
+                       memcpy(data, tone_silence_flip, rest);
                }
-               break;
-       case TONE_FILE:
-               break;
-       case TONE_NONE:
-               return 0;
+               
+               txfrm->prim = DL_DATA|REQUEST;
+               
+               txfrm->dinfo = 0;
+               
+               txfrm->addr = bc->addr|FLG_MSG_DOWN; /*  | IF_DOWN; */
+               
+               txfrm->len =len;
+               cb_log(9, bc->port, "Transmitting %d samples 2 misdn\n", txfrm->len);
+               
+               r=mISDN_write( glob_mgr->midev, buf, txfrm->len + mISDN_HEADER_LEN, 8000 );
+#endif
        }
-  
-       bc->tone_cnt -= TONE_425_SIZE ;
-       return 1;
 }
 
-
-
 int handle_bchan(msg_t *msg)
 {
        iframe_t *frm= (iframe_t*)msg->data;
-       struct misdn_bchannel *bc;
+
+
+       struct misdn_bchannel *bc=find_bc_by_addr(frm->addr);
        
-       bc=find_bc_by_addr(frm->addr);
+       if (!bc) {
+               cb_log(1,0,"handle_bchan: BC not found for prim:%x with addr:%x dinfo:%x\n", frm->prim, frm->addr, frm->dinfo);
+               return 0 ;
+       }
        
-       if (!bc) return 0 ;
-
        struct misdn_stack *stack=get_stack_by_bc(bc);
-
-       if (!stack) return 0;
+       
+       if (!stack) {
+               cb_log(0, bc->port,"handle_bchan: STACK not found for prim:%x with addr:%x dinfo:%x\n", frm->prim, frm->addr, frm->dinfo);
+               return 0;
+       }
        
        switch (frm->prim) {
+
+       case MGR_SETSTACK| CONFIRM:
+               cb_log(3, stack->port, "BCHAN: MGR_SETSTACK|CONFIRM pid:%d\n",bc->pid);
+               break;
+               
+       case MGR_SETSTACK| INDICATION:
+               cb_log(3, stack->port, "BCHAN: MGR_SETSTACK|IND pid:%d\n",bc->pid);
+       break;
+#if 0
+       AGAIN:
+               bc->addr = mISDN_get_layerid(stack->midev, bc->b_stid, bc->layer);
+               if (!bc->addr) {
+
+                       if (errno == EAGAIN) {
+                               usleep(1000);
+                               goto AGAIN;
+                       }
+                       
+                       cb_log(0,stack->port,"$$$ Get Layer (%d) Id Error: %s\n",bc->layer,strerror(errno));
+                       
+                       /* we kill the channel later, when we received some
+                          data. */
+                       bc->addr= frm->addr;
+               } else if ( bc->addr < 0) {
+                       cb_log(0, stack->port,"$$$ bc->addr <0 Error:%s\n",strerror(errno));
+                       bc->addr=0;
+               }
+               
+               cb_log(4, stack->port," --> Got Adr %x\n", bc->addr);
+
+               free_msg(msg);
+       
+               
+               switch(bc->bc_state) {
+               case BCHAN_SETUP:
+                       bc_state_change(bc,BCHAN_SETUPED);
+               break;
+
+               case BCHAN_CLEAN_REQUEST:
+               default:
+                       cb_log(0, stack->port," --> STATE WASN'T SETUP (but %s) in SETSTACK|IND pid:%d\n",bc_state2str(bc->bc_state), bc->pid);
+                       clean_up_bc(bc);
+               }
+               return 1;
+#endif
+
+       case MGR_DELLAYER| INDICATION:
+               cb_log(3, stack->port, "BCHAN: MGR_DELLAYER|IND pid:%d\n",bc->pid);
+               break;
+               
+       case MGR_DELLAYER| CONFIRM:
+               cb_log(3, stack->port, "BCHAN: MGR_DELLAYER|CNF pid:%d\n",bc->pid);
+               
+               bc->pid=0;
+               bc->addr=0;
+               
+               free_msg(msg);
+               return 1;
+               
        case PH_ACTIVATE | INDICATION:
        case DL_ESTABLISH | INDICATION:
-               cb_log(4, stack->port, "BCHAN: ACT Ind\n");
+               cb_log(3, stack->port, "BCHAN: ACT Ind pid:%d\n", bc->pid);
+
                free_msg(msg);
                return 1;    
 
        case PH_ACTIVATE | CONFIRM:
        case DL_ESTABLISH | CONFIRM:
-               cb_log(4, stack->port, "BCHAN: bchan ACT Confirm\n");
+               
+               cb_log(3, stack->port, "BCHAN: bchan ACT Confirm pid:%d\n",bc->pid);
                free_msg(msg);
-
+               
                return 1;    
+
+       case DL_ESTABLISH | REQUEST:
+               {
+                       char buf[128];
+                       mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_TARGET | FLG_MSG_DOWN,  DL_ESTABLISH | CONFIRM, 0,0, NULL, TIMEOUT_1SEC);
+               }
+               free_msg(msg);
+               return 1;
+
+       case DL_RELEASE|REQUEST:
+               {
+                       char buf[128];
+                       mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_TARGET | FLG_MSG_DOWN,  DL_RELEASE| CONFIRM, 0,0, NULL, TIMEOUT_1SEC);
+               }
+               free_msg(msg);
+               return 1;
                
        case PH_DEACTIVATE | INDICATION:
        case DL_RELEASE | INDICATION:
-               cb_log (4, stack->port, "BCHAN: DeACT Ind\n");
+               cb_log (3, stack->port, "BCHAN: DeACT Ind pid:%d\n",bc->pid);
+               
                free_msg(msg);
                return 1;
     
        case PH_DEACTIVATE | CONFIRM:
        case DL_RELEASE | CONFIRM:
-               cb_log(4, stack->port, "BCHAN: DeACT Conf\n");
+               cb_log(3, stack->port, "BCHAN: DeACT Conf pid:%d\n",bc->pid);
+               
                free_msg(msg);
                return 1;
     
        case PH_CONTROL|INDICATION:
        {
-               unsigned long cont = *((unsigned long *)&frm->data.p);
+               unsigned int cont = *((unsigned int *)&frm->data.p);
                
-               cb_log(4, stack->port, "PH_CONTROL: port:%d channel:%d oad%d:%s dad%d:%s \n", stack->port, bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
+               cb_log(4, stack->port, "PH_CONTROL: channel:%d oad%d:%s dad%d:%s \n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
 
                if ((cont&~DTMF_TONE_MASK) == DTMF_TONE_VAL) {
                        int dtmf = cont & DTMF_TONE_MASK;
@@ -1925,7 +2379,16 @@ int handle_bchan(msg_t *msg)
                }
        }
        break;
-    
+
+       case PH_DATA|REQUEST:
+       case DL_DATA|REQUEST:
+               cb_log(0, stack->port, "DL_DATA REQUEST \n");
+               do_tone(bc, 64);
+               
+               free_msg(msg);
+               return 1;
+       
+       
        case PH_DATA|INDICATION:
        case DL_DATA|INDICATION:
        {
@@ -1935,44 +2398,63 @@ int handle_bchan(msg_t *msg)
                /** Anyway flip the bufbits **/
                if ( misdn_cap_is_speech(bc->capability) ) 
                        flip_buf_bits(bc->bframe, bc->bframe_len);
-               
+       
+
+               if (!bc->bframe_len) {
+                       cb_log(2, stack->port, "DL_DATA INDICATION bc->addr:%x frm->addr:%x\n", bc->addr, frm->addr);
+                       free_msg(msg);
+                       return 1;
+               }
+
+               if ( (bc->addr&STACK_ID_MASK) != (frm->addr&STACK_ID_MASK) ) {
+                       cb_log(2, stack->port, "DL_DATA INDICATION bc->addr:%x frm->addr:%x\n", bc->addr, frm->addr);
+                       free_msg(msg);
+                       return 1;
+               }
                
 #if MISDN_DEBUG
                cb_log(0, stack->port, "DL_DATA INDICATION Len %d\n", frm->len);
+
 #endif
                
-               if (bc->active && frm->len > 0) {
-                       if (  !do_tone(bc, frm->len)   ) {
+               if ( (bc->bc_state == BCHAN_ACTIVATED) && frm->len > 0) {
+                       int t;
+
+#ifdef MISDN_B_DEBUG
+                       cb_log(0,bc->port,"do_tone START\n");
+#endif
+                       t=do_tone(bc,frm->len);
+
+#ifdef MISDN_B_DEBUG
+                       cb_log(0,bc->port,"do_tone STOP (%d)\n",t);
+#endif
+                       if (  !t ) {
                                
                                if ( misdn_cap_is_speech(bc->capability)) {
                                        if ( !bc->nojitter ) {
-                                               char buf[4096 + mISDN_HEADER_LEN];
-                                               iframe_t *txfrm= (iframe_t*)buf;
-                                               int len, r;
-                                               
-                                               len = ibuf_usedcount(bc->misdnbuf);
-                                               
-                                               if (len < frm->len) {
-                                                       /** send nothing 
-                                                        * till we are synced
-                                                        **/
-                                               } else {
-                                                       
-                                                       txfrm->prim = DL_DATA|REQUEST;
-                                                       txfrm->dinfo = 0;
-                                                       txfrm->addr = bc->addr; /*  | IF_DOWN; */
-                                                       txfrm->len = frm->len;
-                                                       ibuf_memcpy_r(&buf[mISDN_HEADER_LEN], bc->misdnbuf,frm->len);
-                                                       cb_log(9, stack->port, "Transmitting %d samples 2 misdn\n", txfrm->len);
-                                                       
-                                                       r=mISDN_write(stack->midev, buf, txfrm->len + mISDN_HEADER_LEN, 8000 );
-                                                       
-                                               }
-                                               
+#ifdef MISDN_B_DEBUG
+                                               cb_log(0,bc->port,"tx_jitter START\n");
+#endif
+                                               misdn_tx_jitter(bc,frm->len);
+#ifdef MISDN_B_DEBUG
+                                               cb_log(0,bc->port,"tx_jitter STOP\n");
+#endif
                                        }
                                }
+
+#ifdef MISDN_B_DEBUG   
+                               cb_log(0,bc->port,"EVENT_B_DATA START\n");
+#endif
+                               
+                               int i=cb_event( EVENT_BCHAN_DATA, bc, glob_mgr->user_data);
+#ifdef MISDN_B_DEBUG   
+                               cb_log(0,bc->port,"EVENT_B_DATA STOP\n");
+#endif
                                
-                               cb_event( EVENT_BCHAN_DATA, bc, glob_mgr->user_data);
+                               if (i<0) {
+                                       cb_log(10,stack->port,"cb_event returned <0\n");
+                                       /*clean_up_bc(bc);*/
+                               }
                        }
                }
                free_msg(msg);
@@ -1980,22 +2462,27 @@ int handle_bchan(msg_t *msg)
        }
 
 
+       case PH_CONTROL | CONFIRM:
+               cb_log(4, stack->port, "PH_CONTROL|CNF bc->addr:%x\n", frm->addr);
+               free_msg(msg);
+               return 1;
+
        case PH_DATA | CONFIRM:
        case DL_DATA|CONFIRM:
 #if MISDN_DEBUG
+
                cb_log(0, stack->port, "Data confirmed\n");
+
 #endif
                free_msg(msg);
+               
                return 1;
-               break;
        case DL_DATA|RESPONSE:
 #if MISDN_DEBUG
                cb_log(0, stack->port, "Data response\n");
+
 #endif
                break;
-    
-       case DL_DATA | REQUEST:
-               break;
        }
   
        return 0;
@@ -2008,30 +2495,32 @@ int handle_frm_nt(msg_t *msg)
        iframe_t *frm= (iframe_t*)msg->data;
        struct misdn_stack *stack;
        int err=0;
+
+       stack=find_stack_by_addr( frm->addr );
+
+       
   
-       stack=find_stack_by_addr((frm->addr & IF_ADDRMASK ) );
-  
-       if (!stack || stack->mode != NT_MODE) {
+       if (!stack || !stack->nt) {
                return 0;
        }
-  
 
+       
        if ((err=stack->nst.l1_l2(&stack->nst,msg))) {
     
                if (nt_err_cnt > 0 ) {
                        if (nt_err_cnt < 100) {
                                nt_err_cnt++; 
-                               cb_log(0, stack->port, "NT Stack sends us error: %d port:%d\n", err,stack->port);
+                               cb_log(0, stack->port, "NT Stack sends us error: %d \n", err);
                        } else if (nt_err_cnt < 105){
-                               cb_log(0, stack->port, "NT Stack sends us error: %d port:%d over 100 times, so I'll stop this message\n", err,stack->port);
+                               cb_log(0, stack->port, "NT Stack sends us error: %d over 100 times, so I'll stop this message\n", err);
                                nt_err_cnt = - 1; 
                        }
                }
                free_msg(msg);
                return 1;
-    
+               
        }
-  
+       
        return 1;
 }
 
@@ -2039,16 +2528,24 @@ int handle_frm_nt(msg_t *msg)
 int handle_frm(msg_t *msg)
 {
        iframe_t *frm = (iframe_t*) msg->data;
-       struct misdn_stack *stack=find_stack_by_addr(frm->addr & IF_ADDRMASK);
-  
-       if (!stack || stack->mode != TE_MODE) {
+       
+       struct misdn_stack *stack=find_stack_by_addr(frm->addr);
+
+       if (!stack || stack->nt) {
                return 0;
        }
+       
+       cb_log(4,stack?stack->port:0,"handle_frm: frm->addr:%x frm->prim:%x\n",frm->addr,frm->prim);
 
        {
                struct misdn_bchannel *bc;
+               int ret=handle_cr(stack, frm);
+
+               if (ret<0) {
+                       cb_log(3,stack?stack->port:0,"handle_frm: handle_cr <0 prim:%x addr:%x\n", frm->prim, frm->addr);
+               }
 
-               if(handle_cr(frm)) {
+               if(ret) {
                        free_msg(msg);
                        return 1;
                }
@@ -2060,7 +2557,7 @@ int handle_frm(msg_t *msg)
                        enum event_response_e response=RESPONSE_OK;
       
                        isdn_msg_parse_event(msgs_g,msg,bc, 0);
-
+                       
                        /** Preprocess some Events **/
                        handle_event(bc, event, frm);
                        /*  shoot up event to App: */
@@ -2074,35 +2571,47 @@ int handle_frm(msg_t *msg)
                        if (event == EVENT_SETUP) {
                                switch (response) {
                                case RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE:
-                                       cb_log(0, stack->port, "TOTALY IGNORING SETUP: port:%d\n", frm->addr&IF_CONTRMASK);
+
+                                       cb_log(0, stack->port, "TOTALY IGNORING SETUP \n");                                     
+                                       
                                        break;
                                case RESPONSE_IGNORE_SETUP:
                                        /* I think we should send CC_RELEASE_CR, but am not sure*/
-                                       empty_chan_in_stack(stack, bc->channel);
+
+                                       bc->out_cause=16;
+                                       misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
+                                       if (bc->channel>0)
+                                               empty_chan_in_stack(stack, bc->channel);
                                        empty_bc(bc);
-         
-                                       cb_log(0, stack->port, "GOT IGNORE SETUP: port:%d\n", frm->addr&IF_CONTRMASK);
+                                       bc_state_change(bc,BCHAN_CLEANED);
+
+                                       cb_log(0, stack->port, "GOT IGNORE SETUP\n");
+
+                                       
                                        break;
                                case RESPONSE_OK:
-                                       cb_log(4, stack->port, "GOT SETUP OK: port:%d\n", frm->addr&IF_CONTRMASK);
+                                       cb_log(4, stack->port, "GOT SETUP OK\n");
+
+                                       
                                        break;
                                default:
                                        break;
                                }
                        }
-      
-                       cb_log(5, stack->port, "Freeing Msg on prim:%x port:%d\n",frm->prim, frm->addr&IF_CONTRMASK);
+
+                       cb_log(5, stack->port, "Freeing Msg on prim:%x \n",frm->prim);
+
+                       
                        free_msg(msg);
                        return 1;
 #endif
       
                } else {
-                       cb_log(0, stack->port, "NO BC FOR STACK: port:%d\n", frm->addr&IF_CONTRMASK);
+                       cb_log(0, stack->port, "NO BC FOR STACK\n");            
                }
-
        }
-       cb_log(4, stack->port, "TE_FRM_HANDLER: Returning 0 on prim:%x port:%d\n",frm->prim, frm->addr&IF_CONTRMASK);
-  
+
+       cb_log(4, stack->port, "TE_FRM_HANDLER: Returning 0 on prim:%x \n",frm->prim);
        return 0;
 }
 
@@ -2110,21 +2619,24 @@ int handle_frm(msg_t *msg)
 int handle_l1(msg_t *msg)
 {
        iframe_t *frm = (iframe_t*) msg->data;
-       struct misdn_stack *stack = find_stack_by_port(frm->addr & IF_CONTRMASK);
+       struct misdn_stack *stack = find_stack_by_addr(frm->addr);
        int i ;
        
        if (!stack) return 0 ;
-  
+
        switch (frm->prim) {
        case PH_ACTIVATE | CONFIRM:
        case PH_ACTIVATE | INDICATION:
-               cb_log (1, stack->port, "L1: PH L1Link Up! port:%d\n",stack->port);
+               cb_log (3, stack->port, "L1: PH L1Link Up!\n");
                stack->l1link=1;
                
-               if (stack->mode==NT_MODE) {
+               if (stack->nt) {
                        
                        if (stack->nst.l1_l2(&stack->nst, msg))
                                free_msg(msg);
+
+                       if (stack->ptp)
+                               misdn_lib_get_l2_up(stack);
                } else {
                        free_msg(msg);
                }
@@ -2137,30 +2649,37 @@ int handle_l1(msg_t *msg)
                        }
                        
                }
+               return 1;
+
+       case PH_ACTIVATE | REQUEST:
+               free_msg(msg);
+               cb_log(3,stack->port,"L1: PH_ACTIVATE|REQUEST \n");
+               return 1;
                
+       case PH_DEACTIVATE | REQUEST:
+               free_msg(msg);
+               cb_log(3,stack->port,"L1: PH_DEACTIVATE|REQUEST \n");
                return 1;
+               
        case PH_DEACTIVATE | CONFIRM:
        case PH_DEACTIVATE | INDICATION:
-               cb_log (1, stack->port, "L1: PH L1Link Down! port:%d\n",stack->port);
+               cb_log (3, stack->port, "L1: PH L1Link Down! \n");
                
                for (i=0; i<stack->b_num; i++) {
                        if (global_state == MISDN_INITIALIZED)  {
                                cb_event(EVENT_CLEANUP, &stack->bc[i], glob_mgr->user_data);
                        }
-                       
                }
                
-               if (stack->mode==NT_MODE) {
+               if (stack->nt) {
                        if (stack->nst.l1_l2(&stack->nst, msg))
                                free_msg(msg);
-                       
                } else {
                        free_msg(msg);
                }
                
                stack->l1link=0;
                stack->l2link=0;
-               
                return 1;
        }
   
@@ -2170,39 +2689,30 @@ int handle_l1(msg_t *msg)
 int handle_l2(msg_t *msg)
 {
        iframe_t *frm = (iframe_t*) msg->data;
-       struct misdn_stack *stack = find_stack_by_addr(frm->addr & IF_ADDRMASK);
 
-       if (!stack) return 0 ;
-  
+       struct misdn_stack *stack = find_stack_by_addr(frm->addr);
+       
+       if (!stack) {
+               return 0 ;
+       }
+       
        switch(frm->prim) {
 
-#ifdef DL_STATUS
-       case DL_STATUS | INDICATION:
-       case DL_STATUS | CONFIRM:
-               cb_log (3, stack->port, "L2: DL_STATUS! port:%d\n", stack->port);
-               
-               switch (frm->dinfo) {
-               case SDL_ESTAB:
-                       cb_log (4, stack->port, " --> SDL_ESTAB port:%d\n", stack->port);
-                       stack->l1link=1;
-                       goto dl_estab;
-               case SDL_REL:
-                       cb_log (4, stack->port, " --> SDL_REL port:%d\n", stack->port);
-                       stack->l1link=0;
-                       misdn_lib_get_l2_up(stack);
-                       goto dl_rel;
-               }
-               break;
-#endif
-    
-    
+       case DL_ESTABLISH | REQUEST:
+               cb_log(1,stack->port,"DL_ESTABLISH|REQUEST \n");
+               return 1;
+       case DL_RELEASE | REQUEST:
+               cb_log(1,stack->port,"DL_RELEASE|REQUEST \n");
+               return 1;
+               
        case DL_ESTABLISH | INDICATION:
        case DL_ESTABLISH | CONFIRM:
-#ifdef DL_STATUS
-       dl_estab:
-#endif
        {
-               cb_log (3, stack->port, "L2: L2Link Up! port:%d\n", stack->port);
+               cb_log (3, stack->port, "L2: L2Link Up! \n");
+               if (stack->ptp && stack->l2link) {
+                       cb_log (-1, stack->port, "L2: L2Link Up! but it's already UP.. must be faulty, blocking port\n"); 
+                       cb_event(EVENT_PORT_ALARM, &stack->bc[0], glob_mgr->user_data);
+               }
                stack->l2link=1;
                free_msg(msg);
                return 1;
@@ -2211,11 +2721,8 @@ int handle_l2(msg_t *msg)
     
        case DL_RELEASE | INDICATION:
        case DL_RELEASE | CONFIRM:
-#ifdef DL_STATUS
-       dl_rel:
-#endif
        {
-               cb_log (3, stack->port, "L2: L2Link Down! port:%d\n", stack->port);
+               cb_log (3, stack->port, "L2: L2Link Down! \n");
                stack->l2link=0;
                
                free_msg(msg);
@@ -2226,16 +2733,84 @@ int handle_l2(msg_t *msg)
        return 0;
 }
 
-
 int handle_mgmt(msg_t *msg)
 {
        iframe_t *frm = (iframe_t*) msg->data;
-  
-       if ( (frm->prim & 0x0f0000) ==  0x0f0000) {
-               cb_log(5, 0, "$$$ MGMT FRAME: prim %x addr %x dinfo %x\n",frm->prim, frm->addr, frm->dinfo) ;
+
+       if ( (frm->addr == 0) && (frm->prim == (MGR_DELLAYER|CONFIRM)) ) {
+               cb_log(2, 0, "MGMT: DELLAYER|CONFIRM Addr: 0 !\n") ;
+               free_msg(msg);
+               return 1;
+       }
+       
+       struct misdn_stack * stack=find_stack_by_addr(frm->addr);
+       
+       if (!stack) {
+               if (frm->prim == (MGR_DELLAYER|CONFIRM)) {
+                       cb_log(2, 0, "MGMT: DELLAYER|CONFIRM Addr: %x !\n",
+                                       frm->addr) ;
+                       free_msg(msg);
+                       return 1;
+               }
+               
+               return 0;
+       }
+       
+       switch(frm->prim) {
+       case MGR_SHORTSTATUS | INDICATION:
+       case MGR_SHORTSTATUS | CONFIRM:
+               cb_log(5, stack->port, "MGMT: Short status dinfo %x\n",frm->dinfo);
+               switch (frm->dinfo) {
+               case SSTATUS_L1_ACTIVATED:
+                       cb_log(3, stack->port, "MGMT: SSTATUS: L1_ACTIVATED \n");
+                       stack->l1link=1;
+                       break;
+
+               case SSTATUS_L1_DEACTIVATED:
+                       cb_log(3, stack->port, "MGMT: SSTATUS: L1_DEACTIVATED \n");
+                       /*reopen L1 if down*/
+                       if (stack->l1link==2)
+                               stack->l1link--;
+                       else                    
+                               stack->l1link=0;
+
+                       clear_l3(stack);
+                       
+                       break;
+
+               case SSTATUS_L2_ESTABLISHED:
+                       cb_log(3, stack->port, "MGMT: SSTATUS: L2_ESTABLISH \n");
+                       stack->l2link=1;
+                       if ( !stack->ptp && !stack->nt )
+                               stack->l1link=2;
+                       break;
+                       
+               case SSTATUS_L2_RELEASED:
+                       cb_log(3, stack->port, "MGMT: SSTATUS: L2_RELEASED \n");
+                       stack->l2link=0;
+                       break;
+               }
+               
+               free_msg(msg);
+               return 1;
+               
+       case MGR_SETSTACK | INDICATION:
+               cb_log(4, stack->port, "MGMT: SETSTACK|IND dinfo %x\n",frm->dinfo);
+               free_msg(msg);
+               return 1;
+       case MGR_DELLAYER | CONFIRM:
+               cb_log(4, stack->port, "MGMT: DELLAYER|CNF dinfo %x\n",frm->dinfo) ;
                free_msg(msg);
                return 1;
+               
        }
+       
+       /*
+       if ( (frm->prim & 0x0f0000) ==  0x0f0000) {
+       cb_log(5, 0, "$$$ MGMT FRAME: prim %x addr %x dinfo %x\n",frm->prim, frm->addr, frm->dinfo) ;
+       free_msg(msg);
+       return 1;
+       } */
     
        return 0;
 }
@@ -2245,33 +2820,51 @@ msg_t *fetch_msg(int midev)
 {
        msg_t *msg=alloc_msg(MAX_MSG_SIZE);
        int r;
-       fd_set rdfs;
+/*     fd_set rdfs; */
 
        if (!msg) {
                cb_log(0, 0, "fetch_msg: alloc msg failed !!");
                return NULL;
        }
-       
+
+#if 0
        FD_ZERO(&rdfs);
        FD_SET(midev,&rdfs);
   
        mISDN_select(FD_SETSIZE, &rdfs, NULL, NULL, NULL);
+       //select(FD_SETSIZE, &rdfs, NULL, NULL, NULL);
   
        if (FD_ISSET(midev, &rdfs)) {
-    
-               r=mISDN_read(midev,msg->data,MAX_MSG_SIZE,0);
+#endif
+
+       AGAIN:
+               r=mISDN_read(midev,msg->data,MAX_MSG_SIZE, TIMEOUT_10SEC);
                msg->len=r;
     
                if (r==0) {
                        free_msg(msg); /* danger, cauz usualy freeing in main_loop */
-                       printf ("Got empty Msg?\n");
+                       cb_log(6,0,"Got empty Msg..\n");
                        return NULL;
                }
 
+               if (r<0) {
+                       if (errno == EAGAIN) {
+                               /*we wait for mISDN here*/
+                               cb_log(4,0,"mISDN_read wants us to wait\n");
+                               usleep(5000);
+                               goto AGAIN;
+                       }
+                       
+                       cb_log(0,0,"mISDN_read returned :%d error:%s (%d)\n",r,strerror(errno),errno); 
+               }
+
                return msg;
+
+#if 0
        } else {
                printf ("Select timeout\n");
        }
+#endif
   
        return NULL;
 }
@@ -2282,9 +2875,7 @@ static void misdn_lib_isdn_event_catcher(void *arg)
        struct misdn_lib *mgr = arg;
        int zero_frm=0 , fff_frm=0 ;
        int midev= mgr->midev;
-       int port;
-       
-       //cb_log(5, 0, "In event_catcher thread\n");
+       int port=0;
        
        while (1) {
                msg_t *msg = fetch_msg(midev); 
@@ -2294,7 +2885,6 @@ static void misdn_lib_isdn_event_catcher(void *arg)
                if (!msg) continue;
                
                frm = (iframe_t*) msg->data;
-               port = frm->addr&IF_CONTRMASK;
                
                /** When we make a call from NT2Ast we get this frames **/
                if (frm->len == 0 && frm->addr == 0 && frm->dinfo == 0 && frm->prim == 0 ) {
@@ -2397,41 +2987,92 @@ struct misdn_bchannel *manager_find_bc_holded(struct misdn_bchannel* bc)
 
 
 
+void prepare_bc(struct misdn_bchannel*bc, int channel)
+{
+       bc->channel = channel;
+       bc->channel_preselected = channel?1:0;
+       bc->in_use = 1;
+       bc->need_disconnect=1;
+       bc->need_release=1;
+       bc->need_release_complete=1;
+       bc->cause=16;
+
+       if (++mypid>5000) mypid=1;
+       bc->pid=mypid;
+
+#if 0
+       bc->addr=0;
+       bc->b_stid=0;
+       bc->layer_id=0;
+#endif
+}
+
 struct misdn_bchannel* misdn_lib_get_free_bc(int port, int channel)
 {
        struct misdn_stack *stack;
        int i;
        
-       if (channel < 0 || channel > MAX_BCHANS)
+       if (channel < 0 || channel > MAX_BCHANS) {
+               cb_log(0,port,"Requested channel out of bounds (%d)\n",channel);
                return NULL;
+       }
 
        for (stack=glob_mgr->stack_list; stack; stack=stack->next) {
     
                if (stack->port == port) {
+                       if (stack->blocked) {
+                               cb_log(0,port,"Port is blocked\n");
+                               return NULL;
+                       }
+               
                        if (channel > 0) {
                                if (channel <= stack->b_num) {
                                        for (i = 0; i < stack->b_num; i++) {
                                                if (stack->bc[i].in_use && stack->bc[i].channel == channel) {
+                                                       cb_log(0,port,"Requested channel:%d on port:%d is already in use\n",channel, port);
                                                        return NULL;
                                                }
                                        }
-                               } else
+                               } else {
+                                       cb_log(0,port,"Requested channel:%d is out of bounds on port:%d\n",channel, port);
                                        return NULL;
+                               }
                        }
                        for (i = 0; i < stack->b_num; i++) {
                                if (!stack->bc[i].in_use) {
-                                       stack->bc[i].channel = channel;
-                                       stack->bc[i].channel_preselected = channel?1:0;
-                                       stack->bc[i].in_use = 1;
+                                       prepare_bc(&stack->bc[i], channel);
                                        return &stack->bc[i];
                                }
                        }
+
+                       cb_log(1,port,"There is no free channel on port (%d)\n",port);
                        return NULL;
                }
        }
+
+       cb_log(0,port,"Port is not configured (%d)\n",port);
        return NULL;
 }
 
+
+char *fac2str (enum facility_type type) {
+       struct arr_el { 
+               enum facility_type p; 
+               char *s ; 
+       } arr[] = {
+               { FACILITY_NONE, "FAC_NONE" },
+               { FACILITY_CALLDEFLECT, "FAC_CALLDEFLECT"},
+               { FACILITY_CENTREX, "FAC_CENTREX"}
+       };
+       
+       int i;
+       
+       for (i=0; i < sizeof(arr)/sizeof( struct arr_el) ; i ++)
+               if ( arr[i].p==type) return arr[i].s;
+       
+       return "FAC_UNKNOWN";
+}
+
 void misdn_lib_log_ies(struct misdn_bchannel *bc)
 {
        if (!bc) return;
@@ -2439,96 +3080,120 @@ void misdn_lib_log_ies(struct misdn_bchannel *bc)
        struct misdn_stack *stack=get_stack_by_bc(bc);
 
        if (!stack) return;
-       
-       cb_log(2, stack->port, " --> mode:%s cause:%d ocause:%d rad:%s\n", stack->mode==NT_MODE?"NT":"TE", bc->cause, bc->out_cause, bc->rad);
+
+       cb_log(2, stack->port, " --> channel:%d mode:%s cause:%d ocause:%d rad:%s cad:%s\n", bc->channel, stack->nt?"NT":"TE", bc->cause, bc->out_cause, bc->rad, bc->cad);
        
        cb_log(2, stack->port,
-              " --> info_dad:%s onumplan:%c dnumplan:%c rnumplan:%c\n",
+              " --> info_dad:%s onumplan:%c dnumplan:%c rnumplan:%c cpnnumplan:%c\n",
               bc->info_dad,
               bc->onumplan>=0?'0'+bc->onumplan:' ',
               bc->dnumplan>=0?'0'+bc->dnumplan:' ',
-              bc->rnumplan>=0?'0'+bc->rnumplan:' '
+              bc->rnumplan>=0?'0'+bc->rnumplan:' ',
+              bc->cpnnumplan>=0?'0'+bc->cpnnumplan:' '
                );
        
-       cb_log(2, stack->port, " --> channel:%d caps:%s pi:%x keypad:%s\n", bc->channel, bearer2str(bc->capability),bc->progress_indicator, bc->keypad);
-
-       cb_log(3, stack->port, " --> urate:%d rate:%d mode:%d user1:%d\n", bc->urate, bc->rate, bc->mode,bc->user1);
+       cb_log(3, stack->port, " --> caps:%s pi:%x keypad:%s sending_complete:%d\n", bearer2str(bc->capability),bc->progress_indicator, bc->keypad, bc->sending_complete);
+       cb_log(4, stack->port, " --> screen:%d --> pres:%d\n",
+                       bc->screen, bc->pres);
+       
+       cb_log(4, stack->port, " --> addr:%x l3id:%x b_stid:%x layer_id:%x\n", bc->addr, bc->l3_id, bc->b_stid, bc->layer_id);
        
-       cb_log(3, stack->port, " --> pid:%d addr:%x l3id:%x\n", bc->pid, bc->addr, bc->l3_id);
+       cb_log(4, stack->port, " --> facility:%s out_facility:%s\n",fac2str(bc->fac_type),fac2str(bc->out_fac_type));
 
-       cb_log(4, stack->port, " --> bc:%x h:%d sh:%d\n", bc, bc->holded, bc->stack_holder);
+       cb_log(5, stack->port, " --> urate:%d rate:%d mode:%d user1:%d\n", bc->urate, bc->rate, bc->mode,bc->user1);
+       
+       cb_log(5, stack->port, " --> bc:%x h:%d sh:%d\n", bc, bc->holded, bc->stack_holder);
 }
 
 int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
 {
        msg_t *msg; 
        int err = -1 ;
+       int ret=0;
   
        if (!bc) goto ERR; 
        
        struct misdn_stack *stack=get_stack_by_bc(bc);
        
-       if ( stack->mode == NT_MODE && !stack->l1link) {
+       if (!stack) {
+               cb_log(0,bc->port,"SENDEVENT: no Stack for event:%s oad:%s dad:%s \n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad);
+               return -1;
+       }
+       
+       cb_log(6,stack->port,"SENDEVENT: stack->nt:%d stack->uperid:%x\n",stack->nt, stack->upper_id);
+
+       if ( stack->nt && !stack->l1link) {
                /** Queue Event **/
                bc->evq=event;
                cb_log(1, stack->port, "Queueing Event %s because L1 is down (btw. Activating L1)\n", isdn_get_info(msgs_g, event, 0));
-               { /* Pull Up L1 */ 
-                       iframe_t act;
-                       act.prim = PH_ACTIVATE | REQUEST; 
-                       act.addr = (stack->upper_id & IF_ADDRMASK) | IF_DOWN ;
-                       act.dinfo = 0;
-                       act.len = 0;
-                       mISDN_write(glob_mgr->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
-               }
-               
+               misdn_lib_get_l1_up(stack);
                return 0;
        }
        
-       cb_log(1, stack->port, "I SEND:%s oad:%s dad:%s port:%d\n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad, stack->port);
+       cb_log(1, stack->port, "I SEND:%s oad:%s dad:%s pid:%d\n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad, bc->pid);
+       cb_log(1, stack->port, " --> bc_state:%s\n",bc_state2str(bc->bc_state));
        misdn_lib_log_ies(bc);
        
        switch (event) {
        case EVENT_SETUP:
                if (create_process(glob_mgr->midev, bc)<0) {
                        cb_log(0,  stack->port, " No free channel at the moment @ send_event\n");
+
                        err=-ENOCHAN;
                        goto ERR;
                }
+#if 0
+       if (stack->nt) {
+               ret=setup_bc(bc);
+               if (ret == -EINVAL) {
+                       cb_log(0,bc->port,"send_event: setup_bc failed\n");
+               }
+       }
+#endif
                break;
 
-       case EVENT_CONNECT:
        case EVENT_PROGRESS:
        case EVENT_ALERTING:
        case EVENT_PROCEEDING:
        case EVENT_SETUP_ACKNOWLEDGE:
+               if (!bc->nt && !stack->ptp) break;
+
+       case EVENT_CONNECT:
        case EVENT_RETRIEVE_ACKNOWLEDGE:
+
+               bc->holded=0;
                
-               if (stack->mode == NT_MODE) {
+               if (stack->nt) {
                        if (bc->channel <=0 ) { /*  else we have the channel already */
                                bc->channel = find_free_chan_in_stack(stack, 0);
                                if (!bc->channel) {
                                        cb_log(0, stack->port, " No free channel at the moment\n");
+                                       
                                        err=-ENOCHAN;
                                        goto ERR;
                                }
                        }
                        /* Its that i generate channels */
                }
+
+               ret=setup_bc(bc);
+               if (ret == -EINVAL) {
+                       cb_log(0,bc->port,"send_event: setup_bc failed\n");
+               }
+
+               cb_log(0,bc->port,"After SETUP BC\n");
+
                
-               setup_bc(bc);
-               
-               
-               if ( event == EVENT_CONNECT ) {
-                       if ( *bc->crypt_key ) {
-                               cb_log(4, stack->port,  " --> ENABLING BLOWFISH port:%d channel:%d oad%d:%s dad%d:%s \n", stack->port, bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
+               if (misdn_cap_is_speech(bc->capability)) {
+                       if ((event==EVENT_CONNECT)||(event==EVENT_RETRIEVE_ACKNOWLEDGE)) {
+                               if ( *bc->crypt_key ) {
+                                       cb_log(4, stack->port,  " --> ENABLING BLOWFISH channel:%d oad%d:%s dad%d:%s \n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
+                                       
+                                       manager_ph_control_block(bc,  BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) );
+                               }
                                
-                               manager_ph_control_block(bc,  BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) );
-                       }
-                       
-                       if ( misdn_cap_is_speech(bc->capability)) {
                                if (!bc->nodsp) manager_ph_control(bc,  DTMF_TONE_START, 0);
-                               
-                               if (bc->ec_enable) manager_ec_enable(bc);
+                               manager_ec_enable(bc);
                                
                                if (bc->txgain != 0) {
                                        cb_log(4, stack->port,  "--> Changing txgain to %d\n", bc->txgain);
@@ -2541,50 +3206,78 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
                                }
                        }
                }
-               
-               if (event == EVENT_RETRIEVE_ACKNOWLEDGE) {
-                       manager_bchannel_activate(bc);
-               }
-               
                break;
-    
+
        case EVENT_HOLD_ACKNOWLEDGE:
        {
                struct misdn_bchannel *holded_bc=malloc(sizeof(struct misdn_bchannel));
-               
                memcpy(holded_bc,bc,sizeof(struct misdn_bchannel));
-               
                holded_bc->holded=1;
                stack_holder_add(stack,holded_bc);
                
-               if (stack->mode == NT_MODE) {
-                       empty_chan_in_stack(stack,bc->channel);
+               if (stack->nt) {
+                       if (bc->bc_state == BCHAN_BRIDGED) {
+                               misdn_split_conf(bc,bc->conf_id);
+                               misdn_split_conf(bc->holded_bc,bc->holded_bc->conf_id);
+                       }
+
+                       if (bc->channel>0)
+                               empty_chan_in_stack(stack,bc->channel);
                        empty_bc(bc);
                        clean_up_bc(bc);
                }
                
                /** we set it up later at RETRIEVE_ACK again.**/
-               holded_bc->upset=0;
-               holded_bc->active=0;
+               /*holded_bc->upset=0;
+                 holded_bc->active=0;*/
+               bc_state_change(holded_bc,BCHAN_CLEANED);
                
-               cb_event( EVENT_NEW_BC, holded_bc, glob_mgr->user_data);
+               cb_event( EVENT_NEW_BC, bc,  holded_bc);
        }
        break;
-       
+
+       /* finishing the channel eh ? */
+       case EVENT_DISCONNECT:
+               if (!bc->need_disconnect) {
+                       cb_log(0,bc->port," --> we have already send Disconnect\n");
+                       return -1;
+               }
+               
+               bc->need_disconnect=0;
+               break;
        case EVENT_RELEASE:
+               if (!bc->need_release) {
+                       cb_log(0,bc->port," --> we have already send Release\n");
+                       return -1;
+               }
+               bc->need_disconnect=0;
+               bc->need_release=0;
                break;
-               
        case EVENT_RELEASE_COMPLETE:
-               empty_chan_in_stack(stack,bc->channel);
-               empty_bc(bc);
-               clean_up_bc(bc);
+               if (!bc->need_release_complete) {
+                       cb_log(0,bc->port," --> we have already send Release_complete\n");
+                       return -1;
+               }
+               bc->need_disconnect=0;
+               bc->need_release=0;
+               bc->need_release_complete=0;
                break;
     
        case EVENT_CONNECT_ACKNOWLEDGE:
+
+               if ( bc->nt || misdn_cap_is_speech(bc->capability)) {
+                       int ret=setup_bc(bc);
+                       if (ret == -EINVAL){
+                               cb_log(0,bc->port,"send_event: setup_bc failed\n");
+                               
+                       }
+               }
+       
                
                if (misdn_cap_is_speech(bc->capability)) {
                        if (  !bc->nodsp) manager_ph_control(bc,  DTMF_TONE_START, 0);
-                       if (bc->ec_enable) manager_ec_enable(bc);
+                       manager_ec_enable(bc);
+
                        if ( bc->txgain != 0 ) {
                                cb_log(4, stack->port, "--> Changing txgain to %d\n", bc->txgain);
                                manager_ph_control(bc, VOL_CHANGE_TX, bc->txgain);
@@ -2601,7 +3294,7 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
        }
   
        /* Later we should think about sending bchannel data directly to misdn. */
-       msg = isdn_msg_build_event(msgs_g, bc, event, stack->mode==NT_MODE?1:0);
+       msg = isdn_msg_build_event(msgs_g, bc, event, stack->nt);
        msg_queue_tail(&stack->downqueue, msg);
        sem_post(&glob_mgr->new_msg);
   
@@ -2612,40 +3305,151 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
 }
 
 
+int handle_err(msg_t *msg)
+{
+       iframe_t *frm = (iframe_t*) msg->data;
+
+
+       if (!frm->addr) {
+               static int cnt=0;
+               if (!cnt)
+                       cb_log(0,0,"mISDN Msg without Address pr:%x dinfo:%x\n",frm->prim,frm->dinfo);
+               cnt++;
+               if (cnt>100) {
+                       cb_log(0,0,"mISDN Msg without Address pr:%x dinfo:%x (already more than 100 of them)\n",frm->prim,frm->dinfo);
+                       cnt=0;
+               }
+               
+               free_msg(msg);
+               return 1;
+               
+       }
+       
+       switch (frm->prim) {
+               case MGR_SETSTACK|INDICATION:
+                       return handle_bchan(msg);
+               break;
+
+               case MGR_SETSTACK|CONFIRM:
+               case MGR_CLEARSTACK|CONFIRM:
+                       free_msg(msg) ; 
+                       return 1;
+               break;
+
+               case DL_DATA|CONFIRM:
+                       cb_log(4,0,"DL_DATA|CONFIRM\n");
+                       free_msg(msg);
+                       return 1;
+
+               case PH_CONTROL|CONFIRM:
+                       cb_log(4,0,"PH_CONTROL|CONFIRM\n");
+                       free_msg(msg);
+                       return 1;
+
+               case DL_DATA|INDICATION:
+               {
+                       int port=(frm->addr&MASTER_ID_MASK) >> 8;
+                       int channel=(frm->addr&CHILD_ID_MASK) >> 16;
+
+                       /*we flush the read buffer here*/
+                       
+                       cb_log(9,0,"BCHAN DATA without BC: addr:%x port:%d channel:%d\n",frm->addr, port,channel);
+                       
+                       free_msg(msg) ; 
+                       return 1;
+                       
+                       
+                       struct misdn_bchannel *bc=find_bc_by_channel( port , channel);
+
+                       if (!bc) {
+                               struct misdn_stack *stack=find_stack_by_port( port );
+
+                               if (!stack) {
+                                       cb_log(0,0," --> stack not found\n");
+                                       free_msg(msg);
+                                       return 1;
+                               }
+                               
+                               cb_log(0,0," --> bc not found by channel\n");
+                               if (stack->l2link)
+                                       misdn_lib_get_l2_down(stack);
+
+                               if (stack->l1link)
+                                       misdn_lib_get_l1_down(stack);
+
+                               free_msg(msg);
+                               return 1;
+                       }
+                       
+                       cb_log(3,port," --> BC in state:%s\n", bc_state2str(bc->bc_state));
+               }
+       }
+
+       return 0;
+}
+
+
+int queue_l2l3(msg_t *msg) {
+       iframe_t *frm= (iframe_t*)msg->data;
+       struct misdn_stack *stack;
+       stack=find_stack_by_addr( frm->addr );
+
+       
+       if (!stack) {
+               return 0;
+       }
+
+       msg_queue_tail(&stack->upqueue, msg);
+       sem_post(&glob_mgr->new_msg);
+       return 1;
+}
 
 int manager_isdn_handler(iframe_t *frm ,msg_t *msg)
 {  
 
        if (frm->dinfo==(signed long)0xffffffff && frm->prim==(PH_DATA|CONFIRM)) {
-               printf("SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");
+               cb_log(0,0,"SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");
        }
 
+       if ( ((frm->addr | ISDN_PID_BCHANNEL_BIT )>> 28 ) == 0x5) {
+               if (handle_bchan(msg)) {
+                       return 0 ;
+               }
+       }       
+
+#ifdef RECV_FRM_SYSLOG_DEBUG
+       syslog(LOG_NOTICE,"mISDN recv: P(%02d): ADDR:%x PRIM:%x DINFO:%x\n",stack->port, frm->addr, frm->prim, frm->dinfo);
+#endif
+
        if (handle_timers(msg)) 
                return 0 ;
-    
-       if (handle_mgmt(msg)) 
-               return 0 ;
 
+       
+       if (handle_mgmt(msg)) 
+               return 0 ; 
+       
        if (handle_l2(msg)) 
                return 0 ;
 
        /* Its important to handle l1 AFTER l2  */
        if (handle_l1(msg)) 
                return 0 ;
+       
+       if (handle_frm_nt(msg)) {
+               return 0;
+       }
 
-       if (handle_bchan(msg)) 
-               return 0 ;
+       if (handle_frm(msg)) {
+               return 0;
+       }
 
-       /** Handle L2/3 Signalling after bchans **/ 
-       if (handle_frm_nt(msg)) 
-               return 0 ;
-    
-       if (handle_frm(msg)) 
+       if (handle_err(msg)) {
                return 0 ;
+       }
 
-       cb_log(0, frm->addr&IF_CONTRMASK, "Unhandled Message: prim %x len %d from addr %x, dinfo %x on port: %d\n",frm->prim, frm->len, frm->addr, frm->dinfo, frm->addr&IF_CONTRMASK);
-   
+       cb_log(0, 0, "Unhandled Message: prim %x len %d from addr %x, dinfo %x on this port.\n",frm->prim, frm->len, frm->addr, frm->dinfo);            
        free_msg(msg);
+       
 
        return 0;
 }
@@ -2653,107 +3457,94 @@ int manager_isdn_handler(iframe_t *frm ,msg_t *msg)
 
 
 
-int misdn_lib_get_port_info(int port)
+int misdn_lib_get_port_info(int port)
+{
+       msg_t *msg=alloc_msg(MAX_MSG_SIZE);
+       iframe_t *frm;
+       struct misdn_stack *stack=find_stack_by_port(port);
+       if (!msg) {
+               cb_log(0, port, "misgn_lib_get_port: alloc_msg failed!\n");
+               return -1;
+       }
+       frm=(iframe_t*)msg->data;
+       if (!stack ) {
+               cb_log(0, port, "There is no Stack for this port.\n");
+               return -1;
+       }
+       /* activate bchannel */
+       frm->prim = CC_STATUS_ENQUIRY | REQUEST;
+
+       frm->addr = stack->upper_id| FLG_MSG_DOWN;
+
+       frm->dinfo = 0;
+       frm->len = 0;
+  
+       msg_queue_tail(&glob_mgr->activatequeue, msg);
+       sem_post(&glob_mgr->new_msg);
+
+  
+       return 0; 
+}
+
+
+int queue_cleanup_bc(struct misdn_bchannel *bc) 
 {
        msg_t *msg=alloc_msg(MAX_MSG_SIZE);
        iframe_t *frm;
-       struct misdn_stack *stack=find_stack_by_port(port);
        if (!msg) {
-               cb_log(0, port, "misgn_lib_get_port: alloc_msg failed!\n");
+               cb_log(0, bc->port, "misgn_lib_get_port: alloc_msg failed!\n");
                return -1;
        }
        frm=(iframe_t*)msg->data;
-       if (!stack ) {
-               cb_log(0, port, "There is no Stack on Port:%d\n",port);
-               return -1;
-       }
+
        /* activate bchannel */
-       frm->prim = CC_STATUS_ENQUIRY | REQUEST;
-       frm->addr = stack->upper_id;
-       frm->dinfo = 0;
+       frm->prim = MGR_CLEARSTACK| REQUEST;
+
+       frm->addr = bc->l3_id;
+
+       frm->dinfo = bc->port;
        frm->len = 0;
   
        msg_queue_tail(&glob_mgr->activatequeue, msg);
        sem_post(&glob_mgr->new_msg);
 
-  
        return 0; 
+
 }
 
 int misdn_lib_port_restart(int port)
 {
        struct misdn_stack *stack=find_stack_by_port(port);
  
-       cb_log(0, port, "Restarting Port:%d\n",port);
+       cb_log(0, port, "Restarting this port.\n");
        if (stack) {
                cb_log(0, port, "Stack:%p\n",stack);
-
-               
+                       
                clear_l3(stack);
-               
                {
                        msg_t *msg=alloc_msg(MAX_MSG_SIZE);
                        iframe_t *frm;
 
                        if (!msg) {
-                               cb_log(0, port, "port_restart: alloc_msg fialed\n");
+                               cb_log(0, port, "port_restart: alloc_msg failed\n");
                                return -1;
                        }
                        
                        frm=(iframe_t*)msg->data;
                        /* we must activate if we are deactivated */
                        /* activate bchannel */
-       
                        frm->prim = DL_RELEASE | REQUEST;
-       
-                       frm->addr = stack->upper_id ;
+                       frm->addr = stack->upper_id | FLG_MSG_DOWN;
+
                        frm->dinfo = 0;
                        frm->len = 0;
                        msg_queue_tail(&glob_mgr->activatequeue, msg);
                        sem_post(&glob_mgr->new_msg);
                }
-               return 0;
-    
-               stack_te_destroy(stack);
-      
-               {
-                       struct misdn_stack *tmpstack;
-                       struct misdn_stack *newstack=stack_te_init(stack->midev ,port, stack->ptp);
-      
-      
-                       if (stack == glob_mgr->stack_list) {
-                               struct misdn_stack *n=glob_mgr->stack_list->next;
-                               glob_mgr->stack_list = newstack ;
-                               glob_mgr->stack_list->next = n;
-                       } else {
-                               for (tmpstack=glob_mgr->stack_list;
-                                    tmpstack->next;
-                                    tmpstack=tmpstack->next) 
-                                       if (tmpstack->next == stack) break;
 
-                               if (!tmpstack->next) {
-                                       cb_log(0, port, "Stack to restart not found\n");
-                                       return 0;
-                               }  else {
-                                       struct misdn_stack *n=tmpstack->next->next;
-                                       tmpstack->next=newstack;
-                                       newstack->next=n;
-                               }
-                       }
-      
-                       {
-                               int i;
-                               for(i=0;i<newstack->b_num; i++) {
-                                       int r;
-                                       if ((r=init_bc(newstack, &newstack->bc[i], newstack->midev,port,i, "", 1))<0) {
-                                               cb_log(0, port, "Got Err @ init_bc :%d\n",r);
-                                               return 0;
-                                       }
-                               }
-                       }
-      
-                       free(stack);
-               }
+               if (stack->nt)
+                       misdn_lib_reinit_nt_stack(stack->port);
+    
        }
 
        return 0;
@@ -2782,6 +3573,27 @@ void manager_event_handler(void *arg)
                        iframe_t *frm =  (iframe_t*) msg->data ;
 
                        switch ( frm->prim) {
+
+                       case MGR_CLEARSTACK | REQUEST:
+                               /*a queued bchannel cleanup*/
+                               {
+                                       struct misdn_stack *stack=find_stack_by_port(frm->dinfo);
+                                       if (!stack) {
+                                               cb_log(0,0,"no stack found with port [%d]!! so we cannot cleanup the bc\n",frm->dinfo);
+                                               free_msg(msg);
+                                               break;
+                                       }
+                                       
+                                       struct misdn_bchannel *bc=find_bc_by_l3id(stack,frm->addr);
+                                       if (bc) {
+                                               cb_log(1,bc->port,"CLEARSTACK queued, cleaning up\n");
+                                               clean_up_bc(bc);
+                                       } else {
+                                               cb_log(0,stack->port,"bc could not be cleaned correctly !! addr [%x]\n",frm->addr);
+                                       }
+                               }
+                               free_msg(msg);  
+                               break;
                        case MGR_SETSTACK | REQUEST :
                                break;
                        default:
@@ -2793,20 +3605,32 @@ void manager_event_handler(void *arg)
                for (stack=glob_mgr->stack_list;
                     stack;
                     stack=stack->next ) { 
+
+                       while ( (msg=msg_dequeue(&stack->upqueue)) ) {
+                               /** Handle L2/3 Signalling after bchans **/ 
+                               if (!handle_frm_nt(msg)) {
+                                       /* Maybe it's TE */
+                                       if (!handle_frm(msg)) {
+                                               /* wow none! */
+                                               cb_log(0,stack->port,"Wow we've got a strange issue while dequeueing a Frame\n");
+                                       }
+                               }
+                       }
+
+                       /* Here we should check if we really want to 
+                               send all the messages we've queued, lets 
+                               assume we've queued a Disconnect, but 
+                               received it already from the other side!*/
+                    
                        while ( (msg=msg_dequeue(&stack->downqueue)) ) {
-       
-                               if (stack->mode == NT_MODE ){
-         
+                               if (stack->nt ) {
                                        if (stack->nst.manager_l3(&stack->nst, msg))
                                                cb_log(0, stack->port, "Error@ Sending Message in NT-Stack.\n");
          
                                } else {
-                                       if (msg) {
-                                               iframe_t *frm = (iframe_t *)msg->data;
-                                               struct misdn_bchannel *bc = find_bc_by_l3id(stack, frm->dinfo);
-           
-                                               if (bc) send_msg(glob_mgr->midev, bc, msg);
-                                       }
+                                       iframe_t *frm = (iframe_t *)msg->data;
+                                       struct misdn_bchannel *bc = find_bc_by_l3id(stack, frm->dinfo);
+                                       if (bc) send_msg(glob_mgr->midev, bc, msg);
                                }
                        }
                }
@@ -2829,6 +3653,27 @@ int misdn_lib_maxports_get() { /** BE AWARE WE HAVE NO CB_LOG HERE! **/
        return max;
 }
 
+
+void misdn_lib_nt_debug_init( int flags, char *file ) 
+{
+       int static init=0;
+       char *f;
+       
+       if (!flags) 
+               f=NULL;
+       else
+               f=file;
+
+       if (!init) {
+               debug_init( flags , f, f, f);
+               init=1;
+       } else {
+               debug_close();
+               debug_init( flags , f, f, f);
+       }
+}
+
+
 int misdn_lib_init(char *portlist, struct misdn_lib_iface *iface, void *user_data)
 {
        struct misdn_lib *mgr=calloc(1, sizeof(struct misdn_lib));
@@ -2839,12 +3684,13 @@ int misdn_lib_init(char *portlist, struct misdn_lib_iface *iface, void *user_dat
  
        cb_log = iface->cb_log;
        cb_event = iface->cb_event;
-       cb_clearl3_true = iface->cb_clearl3_true;
+       cb_jb_empty = iface->cb_jb_empty;
        
        glob_mgr = mgr;
   
        msg_init();
-       debug_init(0 , NULL, NULL, NULL);
+
+       misdn_lib_nt_debug_init(0,NULL);
        
        if (!portlist || (*portlist == 0) ) return 1;
        
@@ -2883,12 +3729,10 @@ int misdn_lib_init(char *portlist, struct misdn_lib_iface *iface, void *user_dat
                        ptp=1;
 
                if (port > port_count) {
-                       cb_log(0, port, "Couldn't Initialize Port:%d since we have only %d ports\n",port, port_count);
+                       cb_log(0, port, "Couldn't Initialize this port since we have only %d ports\n", port_count);
                        exit(1);
                }
-               stack=stack_te_init(midev, port, ptp);
-    
-    
+               stack=stack_init(midev, port, ptp);
     
                if (!stack) {
                        perror("init_stack");
@@ -2937,22 +3781,20 @@ int misdn_lib_init(char *portlist, struct misdn_lib_iface *iface, void *user_dat
        if (sem_init(&handler_started, 1, 0)<0)
                sem_init(&handler_started, 0, 0);
   
-       cb_log(4, 0, "Starting Event Handler\n");
+       cb_log(8, 0, "Starting Event Handler\n");
        pthread_create( &mgr->event_handler_thread, NULL,(void*)manager_event_handler, mgr);
   
        sem_wait(&handler_started) ;
-       cb_log(4, 0, "Starting Event Catcher\n");
+       cb_log(8, 0, "Starting Event Catcher\n");
        pthread_create( &mgr->event_thread, NULL, (void*)misdn_lib_isdn_event_catcher, mgr);
   
-       cb_log(4, 0, "Event Catcher started\n");
+       cb_log(8, 0, "Event Catcher started\n");
   
        global_state= MISDN_INITIALIZED; 
   
        return (mgr == NULL);
 }
 
-
-
 void misdn_lib_destroy()
 {
        struct misdn_stack *help;
@@ -2961,14 +3803,11 @@ void misdn_lib_destroy()
        for ( help=glob_mgr->stack_list; help; help=help->next ) {
                for(i=0;i<help->b_num; i++) {
                        char buf[1024];
-      
                        mISDN_write_frame(help->midev, buf, help->bc[i].addr, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
                        help->bc[i].addr = 0;
                }
-
-
-               cb_log (1, help->port, "Destroying port:%d\n", help->port);
-               stack_te_destroy(help);
+               cb_log (1, help->port, "Destroying this port.\n");
+               stack_destroy(help);
        }
        
        if (global_state == MISDN_INITIALIZED) {
@@ -2978,7 +3817,6 @@ void misdn_lib_destroy()
                        pthread_join(glob_mgr->event_handler_thread, NULL);
                }
          
-         
                cb_log(4, 0, "Killing Main Thread\n");
                if ( pthread_cancel(glob_mgr->event_thread) == 0 ) {
                        cb_log(4, 0, "Joining Main Thread\n");
@@ -2990,48 +3828,42 @@ void misdn_lib_destroy()
        te_lib_destroy(glob_mgr->midev);
 }
 
-
 char *manager_isdn_get_info(enum event_e event)
 {
        return isdn_get_info(msgs_g , event, 0);
 }
 
-
-
-
 void manager_bchannel_activate(struct misdn_bchannel *bc)
 {
-       msg_t *msg=alloc_msg(MAX_MSG_SIZE);
-       iframe_t *frm;
+       char buf[128];
+       iframe_t *ifrm;
+       int ret;
 
        struct misdn_stack *stack=get_stack_by_bc(bc);
-       
-       if (!msg) {
-               cb_log(0, stack->port, "bchannel_activate: alloc_msg failed !");
+
+       if (!stack) {
+               cb_log(0, bc->port, "bchannel_activate: Stack not found !");
                return ;
        }
        
-       frm=(iframe_t*)msg->data;
        /* we must activate if we are deactivated */
-       clear_ibuffer(bc->misdnbuf);
        clear_ibuffer(bc->astbuf);
        
-       
-       if (bc->active) return;
-  
        cb_log(5, stack->port, "$$$ Bchan Activated addr %x\n", bc->addr);
-
-       /* activate bchannel */
-       frm->prim = DL_ESTABLISH | REQUEST;
-       frm->addr = bc->addr ;
-       frm->dinfo = 0;
-       frm->len = 0;
        
-       msg_queue_tail(&glob_mgr->activatequeue, msg);
-       sem_post(&glob_mgr->new_msg);
+       mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_DOWN,  DL_ESTABLISH | REQUEST, 0,0, NULL, TIMEOUT_1SEC);
 
-       bc->active=1;
-  
+       ret=mISDN_read(stack->midev,buf,128,TIMEOUT_10SEC);
+
+       ifrm=(iframe_t*)buf;
+       
+       if (ret>0) {
+               if (ifrm->prim== (DL_ESTABLISH|CONFIRM)) {
+                       cb_log(2,stack->port,"bchan: DL_ESTABLISH|CNF\n");
+               }
+       }
+       
+       
        return ;
   
 }
@@ -3039,96 +3871,106 @@ void manager_bchannel_activate(struct misdn_bchannel *bc)
 
 void manager_bchannel_deactivate(struct misdn_bchannel * bc)
 {
-       iframe_t dact;
 
        struct misdn_stack *stack=get_stack_by_bc(bc);
-       if (!bc->active) return;
-  
-       cb_log(5, stack->port, "$$$ Bchan deActivated addr %x\n", bc->addr);
-  
-       bc->tone=TONE_NONE;
 
+
+       switch (bc->bc_state) {
+               case BCHAN_ACTIVATED:
+                       break;
+               case BCHAN_BRIDGED:
+                       misdn_split_conf(bc,bc->conf_id);
+                       break;
+               default:
+                       cb_log( 4, bc->port,"bchan_deactivate: called but not activated\n");
+                       return ;
+
+       }
+       
+       cb_log(5, stack->port, "$$$ Bchan deActivated addr %x\n", bc->addr);
+       
+       bc->generate_tone=0;
+       
+       iframe_t dact;
        dact.prim = DL_RELEASE | REQUEST;
-       dact.addr = bc->addr;
+       dact.addr = bc->addr | FLG_MSG_DOWN;
        dact.dinfo = 0;
        dact.len = 0;
-  
-       mISDN_write(stack->midev, &dact, mISDN_HEADER_LEN+dact.len, TIMEOUT_1SEC);
-       clear_ibuffer(bc->misdnbuf);
+       char buf[128];  
+       mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_DOWN, DL_RELEASE|REQUEST,0,0,NULL, TIMEOUT_1SEC);
+
+       mISDN_read(stack->midev, buf, 128, TIMEOUT_1SEC);
+
        clear_ibuffer(bc->astbuf);
-       bc->active=0;
+       
+       bc_state_change(bc,BCHAN_RELEASE);
   
        return;
 }
 
 
-int manager_tx2misdn_frm(struct misdn_bchannel *bc, void *data, int len)
+int misdn_lib_tx2misdn_frm(struct misdn_bchannel *bc, void *data, int len)
 {
-
        struct misdn_stack *stack=get_stack_by_bc(bc);
-       if (!bc->active) return -1;   
 
-       if ( misdn_cap_is_speech(bc->capability) )
-               flip_buf_bits(data,len);
+       switch (bc->bc_state) {
+               case BCHAN_ACTIVATED:
+               case BCHAN_BRIDGED:
+                       break;
+               default:
+                       cb_log(3, bc->port, "BC not yet activated (state:%s)\n",bc_state2str(bc->bc_state));
+                       return -1;
+       }
        
-       if ( !bc->nojitter && misdn_cap_is_speech(bc->capability) ) {
-               if (len > ibuf_freecount(bc->misdnbuf)) {
-                       len=ibuf_freecount(bc->misdnbuf);
-               }
-               ibuf_memcpy_w(bc->misdnbuf, (unsigned char*)data, len);
-       } else {
-               char buf[4096 + mISDN_HEADER_LEN];
-               iframe_t *frm= (iframe_t*)buf;
-               int  r;
-               
-               frm->prim = DL_DATA|REQUEST;
-               frm->dinfo = 0;
-               frm->addr = bc->addr | IF_DOWN;
-               frm->len = len;
-               memcpy(&buf[mISDN_HEADER_LEN], data,len);
-
-               
-               
-               if ( misdn_cap_is_speech(bc->capability))
-                       cb_log(4, stack->port, "Writing %d bytes\n",len);
+       char buf[4096 + mISDN_HEADER_LEN];
+       iframe_t *frm= (iframe_t*)buf;
+       int  r;
+       
+       frm->prim = DL_DATA|REQUEST;
+       frm->dinfo = 0;
+       frm->addr = bc->addr | FLG_MSG_DOWN ;
+       
+       frm->len = len;
+       memcpy(&buf[mISDN_HEADER_LEN], data,len);
                
-               cb_log(9, stack->port, "Wrinting %d bytes 2 mISDN\n",len);
-               r=mISDN_write(stack->midev, buf, frm->len + mISDN_HEADER_LEN, TIMEOUT_INFINIT);
+       if ( misdn_cap_is_speech(bc->capability) ) 
+               flip_buf_bits( &buf[mISDN_HEADER_LEN], len);
+       else
+               cb_log(6, stack->port, "Writing %d data bytes\n",len);
+       
+       cb_log(9, stack->port, "Writing %d bytes 2 mISDN\n",len);
+       r=mISDN_write(stack->midev, buf, frm->len + mISDN_HEADER_LEN, TIMEOUT_INFINIT);
+#ifdef ACK_HDLC
+       if (bc->hdlc && bc->ack_hdlc) {
+               cb_log(4,stack->port,"Awaiting Acknowledge [%d]\n",len);
+               sem_wait((sem_t*)bc->ack_hdlc);
+               cb_log(4,stack->port,"Acknowledged\n");
        }
-
+#endif 
        return 0;
 }
 
 
 
-
-void manager_send_tone (struct misdn_bchannel *bc, enum tone_e tone)
-{
-       if (tone != TONE_NONE) manager_bchannel_activate(bc);
-       bc->tone=tone;
-       bc->tone_cnt2=-1;
-       bc->tone_cnt=0;
-}
-
-
-
 /*
  * send control information to the channel (dsp-module)
  */
 void manager_ph_control(struct misdn_bchannel *bc, int c1, int c2)
 {
-       unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
+       unsigned char buffer[mISDN_HEADER_LEN+ 2*sizeof(int)];
        iframe_t *ctrl = (iframe_t *)buffer; /* preload data */
-       unsigned long *d = (unsigned long *)&ctrl->data.p;
-       struct misdn_stack *stack=get_stack_by_bc(bc);
+       unsigned int *d = (unsigned int*)&ctrl->data.p;
+       /*struct misdn_stack *stack=get_stack_by_bc(bc);*/
+       
+       cb_log(4,bc->port,"ph_control: c1:%x c2:%x\n",c1,c2);
        
        ctrl->prim = PH_CONTROL | REQUEST;
-       ctrl->addr = bc->addr;
+       ctrl->addr = bc->addr | FLG_MSG_DOWN;
        ctrl->dinfo = 0;
-       ctrl->len = sizeof(unsigned long)*2;
+       ctrl->len = sizeof(unsigned int)*2;
        *d++ = c1;
        *d++ = c2;
-       mISDN_write(stack->midev, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
+       mISDN_write(glob_mgr->midev, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
 }
 
 /*
@@ -3138,16 +3980,16 @@ void manager_ph_control_block(struct misdn_bchannel *bc, int c1, void *c2, int c
 {
        unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+c2_len];
        iframe_t *ctrl = (iframe_t *)buffer;
-       unsigned long *d = (unsigned long *)&ctrl->data.p;
-       struct misdn_stack *stack=get_stack_by_bc(bc);
+       unsigned int *d = (unsigned int *)&ctrl->data.p;
+       /*struct misdn_stack *stack=get_stack_by_bc(bc);*/
        
        ctrl->prim = PH_CONTROL | REQUEST;
-       ctrl->addr = bc->addr;
+       ctrl->addr = bc->addr | FLG_MSG_DOWN;
        ctrl->dinfo = 0;
-       ctrl->len = sizeof(unsigned long) + c2_len;
+       ctrl->len = sizeof(unsigned int) + c2_len;
        *d++ = c1;
        memcpy(d, c2, c2_len);
-       mISDN_write(stack->midev, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
+       mISDN_write(glob_mgr->midev, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
 }
 
 
@@ -3157,10 +3999,8 @@ void manager_clean_bc(struct misdn_bchannel *bc )
 {
        struct misdn_stack *stack=get_stack_by_bc(bc);
        
-       if (bc->state == STATE_CONNECTED)
-               misdn_lib_send_event(bc,EVENT_DISCONNECT);
-
-       empty_chan_in_stack(stack, bc->channel);
+       if (bc->channel>0)
+               empty_chan_in_stack(stack, bc->channel);
        empty_bc(bc);
   
        misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
@@ -3188,6 +4028,7 @@ void stack_holder_add(struct misdn_stack *stack, struct misdn_bchannel *holder)
             help=help->next) {
                if (!help->next) {
                        help->next=holder;
+                       break;
                }
        }
   
@@ -3199,6 +4040,8 @@ void stack_holder_remove(struct misdn_stack *stack, struct misdn_bchannel *holde
 
        if (!holder->stack_holder) return;
        
+       holder->stack_holder=0;
+       
        cb_log(4,stack->port, "*HOLDER: remove %x\n",holder->l3_id);
        if (!stack || ! stack->holding) return;
   
@@ -3241,35 +4084,78 @@ struct misdn_bchannel *stack_holder_find(struct misdn_stack *stack, unsigned lon
 
 
 
+void misdn_lib_send_tone(struct misdn_bchannel *bc, enum tone_e tone) 
+{
+
+       switch(tone) {
+       case TONE_DIAL:
+               manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_DIALTONE);     
+       break;
+       
+       case TONE_ALERTING:
+               manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_RINGING);      
+       break;
+       
+       case TONE_HANGUP:
+               manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_HANGUP);       
+       break;
+
+       case TONE_NONE:
+       default:
+               manager_ph_control(bc, TONE_PATT_OFF, TONE_GERMAN_HANGUP);      
+       }
+
+       char buf[mISDN_HEADER_LEN+128];
+       iframe_t *frm=(iframe_t*)buf;
+       memset(buf,0,mISDN_HEADER_LEN+128);
+
+       frm->prim=DL_DATA|REQUEST;
+       frm->addr=bc->addr|FLG_MSG_DOWN;
+       frm->dinfo=0;
+       frm->len=128;
+       
+       mISDN_write(glob_mgr->midev, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
+}
+
+
 void manager_ec_enable(struct misdn_bchannel *bc)
 {
        int ec_arr[2];
 
        struct misdn_stack *stack=get_stack_by_bc(bc);
        
-       cb_log(1, stack?stack->port:0,"Sending Control ECHOCAN_ON taps:%d training:%d\n",bc->ec_deftaps, bc->ec_training);
-       
-       switch (bc->ec_deftaps) {
-       case 4:
-       case 8:
-       case 16:
-       case 32:
-       case 64:
-       case 128:
-       case 256:
-       case 512:
-       case 1024:
-               cb_log(4, stack->port, "Taps is %d\n",bc->ec_deftaps);
-               break;
-       default:
-               cb_log(0, stack->port, "Taps should be power of 2\n");
-               bc->ec_deftaps=128;
+       cb_log(1, stack?stack->port:0,"ec_enable\n");
+
+       if (!misdn_cap_is_speech(bc->capability)) {
+               cb_log(1, stack?stack->port:0, " --> no speech? cannot enable EC\n");
+               return;
        }
 
-       ec_arr[0]=bc->ec_deftaps;
-       ec_arr[1]=bc->ec_training;
+       if (bc->ec_enable) {
+               cb_log(1, stack?stack->port:0,"Sending Control ECHOCAN_ON taps:%d training:%d\n",bc->ec_deftaps, bc->ec_training);
+       
+               switch (bc->ec_deftaps) {
+               case 4:
+               case 8:
+               case 16:
+               case 32:
+               case 64:
+               case 128:
+               case 256:
+               case 512:
+               case 1024:
+                       cb_log(4, stack->port, "Taps is %d\n",bc->ec_deftaps);
+                       break;
+               default:
+                       cb_log(0, stack->port, "Taps should be power of 2\n");
+                       bc->ec_deftaps=128;
+               }
        
-       manager_ph_control_block(bc,  ECHOCAN_ON,  ec_arr, sizeof(ec_arr));
+               ec_arr[0]=bc->ec_deftaps;
+               ec_arr[1]=0;
+               
+               manager_ph_control_block(bc,  ECHOCAN_ON,  ec_arr, sizeof(ec_arr));
+       }
 }
 
 
@@ -3278,8 +4164,17 @@ void manager_ec_disable(struct misdn_bchannel *bc)
 {
        struct misdn_stack *stack=get_stack_by_bc(bc);
        
-       cb_log(1, stack?stack->port:0, "Sending Control ECHOCAN_OFF\n");
-       manager_ph_control(bc,  ECHOCAN_OFF, 0);
+       cb_log(1, stack?stack->port:0,"ec_disable\n");
+
+       if (!misdn_cap_is_speech(bc->capability)) {
+               cb_log(1, stack?stack->port:0, " --> no speech? cannot disable EC\n");
+               return;
+       }
+
+       if ( bc->ec_enable) {
+               cb_log(1, stack?stack->port:0, "Sending Control ECHOCAN_OFF\n");
+               manager_ph_control(bc,  ECHOCAN_OFF, 0);
+       }
 }
 
 struct misdn_stack* get_misdn_stack() {
@@ -3288,21 +4183,127 @@ struct misdn_stack* get_misdn_stack() {
 
 
 
+void misdn_join_conf(struct misdn_bchannel *bc, int conf_id)
+{
+       bc_state_change(bc,BCHAN_BRIDGED);
+       manager_ph_control(bc, CMX_RECEIVE_OFF, 0);
+       manager_ph_control(bc, CMX_CONF_JOIN, conf_id);
+
+       cb_log(1,bc->port, "Joining bc:%x in conf:%d\n",bc->addr,conf_id);
+
+       char data[16];
+       int len=15;
+
+       memset(data,0,15);
+       
+       misdn_lib_tx2misdn_frm(bc, data, len);
+
+}
+
+
+void misdn_split_conf(struct misdn_bchannel *bc, int conf_id)
+{
+       bc_state_change(bc,BCHAN_ACTIVATED);
+       manager_ph_control(bc, CMX_RECEIVE_ON, 0);
+       manager_ph_control(bc, CMX_CONF_SPLIT, conf_id);
+
+       cb_log(1,bc->port, "Splitting bc:%x in conf:%d\n",bc->addr,conf_id);
+}
+
 void misdn_lib_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2) {
-       manager_ph_control(bc1, CMX_RECEIVE_OFF, 0);
-       manager_ph_control(bc2, CMX_RECEIVE_OFF, 0);
+       int conf_id=bc1->pid +1;
+
+       cb_log(1, bc1->port, "I Send: BRIDGE from:%d to:%d\n",bc1->port,bc2->port);
+       
+       struct misdn_bchannel *bc_list[]={
+               bc1,bc2,NULL
+       };
+       struct misdn_bchannel **bc;
+               
+       for (bc=bc_list; *bc;  *bc++) { 
+               (*bc)->conf_id=conf_id;
+               cb_log(1, (*bc)->port, " --> bc_addr:%x\n",(*bc)->addr);
        
-       manager_ph_control(bc1, CMX_CONF_JOIN, (bc1->pid<<1) +1);
-       manager_ph_control(bc2, CMX_CONF_JOIN, (bc1->pid<<1) +1);
+               switch((*bc)->bc_state) {
+                       case BCHAN_ACTIVATED:
+                               misdn_join_conf(*bc,conf_id);
+                               break;
+                       default:
+                               bc_next_state_change(*bc,BCHAN_BRIDGED);
+                               break;
+               }
+       }
 }
 
 void misdn_lib_split_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2)
 {
+
+       struct misdn_bchannel *bc_list[]={
+               bc1,bc2,NULL
+       };
+       struct misdn_bchannel **bc;
+               
+       for (bc=bc_list; *bc;  *bc++) { 
+               if ( (*bc)->bc_state == BCHAN_BRIDGED){
+                       misdn_split_conf( *bc, (*bc)->conf_id);
+               } else {
+                       cb_log( 2, (*bc)->port, "BC not bridged (state:%s) so not splitting it\n",bc_state2str((*bc)->bc_state));
+               }
+       }
+       
+}
+
+
+
+void misdn_lib_echo(struct misdn_bchannel *bc, int onoff)
+{
+       cb_log(1,bc->port, " --> ECHO %s\n", onoff?"ON":"OFF");
+       manager_ph_control(bc, onoff?CMX_ECHO_ON:CMX_ECHO_OFF, 0);
+}
+
+
+
+void misdn_lib_reinit_nt_stack(int port)
+{
+       struct misdn_stack *stack=find_stack_by_port(port);
        
-       manager_ph_control(bc1, CMX_RECEIVE_ON, 0) ;
-       manager_ph_control(bc2, CMX_RECEIVE_ON, 0);
+       if (stack) {
+               stack->l2link=0;
+               stack->blocked=0;
        
-       manager_ph_control(bc1, CMX_CONF_SPLIT, (bc1->pid<<1) +1);
-       manager_ph_control(bc2, CMX_CONF_SPLIT, (bc1->pid<<1) +1);
+               cleanup_Isdnl3(&stack->nst);
+               cleanup_Isdnl2(&stack->nst);
+
+
+               memset(&stack->nst, 0, sizeof(net_stack_t));
+               memset(&stack->mgr, 0, sizeof(manager_t));
+   
+               stack->mgr.nst = &stack->nst;
+               stack->nst.manager = &stack->mgr;
+    
+               stack->nst.l3_manager = handle_event_nt;
+               stack->nst.device = glob_mgr->midev;
+               stack->nst.cardnr = port;
+               stack->nst.d_stid = stack->d_stid;
+   
+               stack->nst.feature = FEATURE_NET_HOLD;
+               if (stack->ptp)
+                       stack->nst.feature |= FEATURE_NET_PTP;
+               if (stack->pri)
+                       stack->nst.feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
+               
+               stack->nst.l1_id = stack->lower_id;
+               stack->nst.l2_id = stack->upper_id;
+               
+               msg_queue_init(&stack->nst.down_queue);
        
+               Isdnl2Init(&stack->nst);
+               Isdnl3Init(&stack->nst);
+
+               if (!stack->ptp)
+                       misdn_lib_get_l1_up(stack);
+               misdn_lib_get_l2_up(stack);
+       }
 }
+
+
index 28a4fe7b6f261714c5e3a657c18fd10834dfd6c9..f79bc2ad059ff9396d736d9e38370ebf89706992 100644 (file)
 #ifndef TE_LIB
 #define TE_LIB
 
+
 /** For initialization usage **/
 /* typedef int ie_nothing_t ;*/
 /** end of init usage **/
 
+#ifdef WITH_BEROEC
+typedef int beroec_t;
 
-#define MAX_BCHANS 30
 
-enum bc_state_e {
-       STATE_NOTHING=0,
-       STATE_NULL,
-       STATE_CALL_INIT,
-       STATE_CONNECTED,
-       STATE_HOLD_ACKNOWLEDGE
+enum beroec_type {
+       BEROEC_FULLBAND=0,
+       BEROEC_SUBBAND,
+       BEROEC_FASTSUBBAND
 };
 
+void beroec_init(void);
+void beroec_exit(void);
+beroec_t *beroec_new(int tail, enum beroec_type type, int anti_howl,
+                    int tonedisable, int zerocoeff, int adapt, int nlp);
+
+void beroec_destroy(beroec_t *ec);
+int beroec_cancel_alaw_chunk(beroec_t *ec, 
+       char *send, 
+       char *receive , 
+       int len);
+
+int beroec_version(void);
+#endif
+
+
 
 enum tone_e {
        TONE_NONE=0,
        TONE_DIAL,
        TONE_ALERTING,
+       TONE_FAR_ALERTING,
        TONE_BUSY,
+       TONE_HANGUP,
+       TONE_CUSTOM,
        TONE_FILE
 };
 
+
+
+#define MAX_BCHANS 30
+
+enum bchannel_state {
+       BCHAN_CLEANED=0,
+       BCHAN_EMPTY,
+       BCHAN_SETUP,
+       BCHAN_SETUPED,
+       BCHAN_ACTIVE,
+       BCHAN_ACTIVATED,
+       BCHAN_BRIDGE,
+       BCHAN_BRIDGED,
+       BCHAN_RELEASE,
+       BCHAN_RELEASED,
+       BCHAN_CLEAN,
+       BCHAN_CLEAN_REQUEST,
+       BCHAN_ERROR
+};
+
+
 enum misdn_err_e {
        ENOCHAN=1
 };
 
 
-
 enum mISDN_NUMBER_PLAN {
        NUMPLAN_UNINITIALIZED=-1,
        NUMPLAN_INTERNATIONAL=0x1,
@@ -61,10 +99,11 @@ enum event_response_e {
 };
 
 
-
 enum event_e {
        EVENT_NOTHING,
+       EVENT_TONE_GENERATE,
        EVENT_BCHAN_DATA,
+       EVENT_BCHAN_ACTIVATED,
        EVENT_CLEANUP,
        EVENT_PROCEEDING,
        EVENT_PROGRESS,
@@ -99,6 +138,7 @@ enum event_e {
        EVENT_DTMF_TONE,
        EVENT_NEW_L3ID,
        EVENT_NEW_BC,
+       EVENT_PORT_ALARM,
        EVENT_UNKNOWN
 }; 
 
@@ -144,9 +184,19 @@ enum layer_e {
        UNKNOWN
 }; 
 
+
+
+/** FACILITY STUFF **/
+
 enum facility_type {
        FACILITY_NONE,
-       FACILITY_CALLDEFLECT
+       FACILITY_CALLDEFLECT=0x91,
+       FACILITY_CENTREX=0x88
+};
+
+union facility {
+       char calldeflect_nr[15];
+       char cnip[256];
 };
 
 
@@ -161,13 +211,21 @@ struct misdn_bchannel {
        /* int b_addr; */
        int layer_id;
 
-
+       void *ack_hdlc;
+       
+       int layer;
        
+       /*state stuff*/
+       int need_disconnect;
+       int need_release;
+       int need_release_complete;
+
        /** var stuff**/
        int l3_id;
        int pid;
        int ces;
-  
+
+       int restart_channel;
        int channel;
        int channel_preselected;
        
@@ -180,8 +238,8 @@ struct misdn_bchannel {
        
        
        void *astbuf;
+
        void *misdnbuf;
-       
 
        int te_choose_channel;
        int early_bconnect;
@@ -190,6 +248,13 @@ struct misdn_bchannel {
        int dtmf;
        int send_dtmf;
 
+       /* get setup ack */
+       int need_more_infos;
+
+       /* may there be more infos ?*/
+       int sending_complete;
+
+
        /* wether we should use jollys dsp or not */
        int nodsp;
        
@@ -199,13 +264,17 @@ struct misdn_bchannel {
        enum mISDN_NUMBER_PLAN dnumplan;
        enum mISDN_NUMBER_PLAN rnumplan;
        enum mISDN_NUMBER_PLAN onumplan;
+       enum mISDN_NUMBER_PLAN cpnnumplan;
 
        int progress_coding;
        int progress_location;
        int progress_indicator;
        
-       enum facility_type facility;
-       char facility_calldeflect_nr[15];
+       enum facility_type fac_type;
+       union facility fac;
+       
+       enum facility_type out_fac_type;
+       union facility out_fac;
        
        enum event_e evq;
        
@@ -226,14 +295,18 @@ struct misdn_bchannel {
        int active;
        int upset;
 
-       enum tone_e tone;
+       int generate_tone;
        int tone_cnt;
-       int tone_cnt2;
-  
-       enum bc_state_e state;
+       enum bchannel_state bc_state;
+       enum bchannel_state next_bc_state;
 
+       int conf_id;
+       
        int holded;
        int stack_holder;
+
+       struct misdn_bchannel *holded_bc;
        
        int pres;
        int screen;
@@ -246,7 +319,7 @@ struct misdn_bchannel {
 
        int user1;
        int urate;
-       int async;
+       int hdlc;
        /* V110 */
   
        unsigned char display[84];
@@ -254,16 +327,17 @@ struct misdn_bchannel {
        unsigned char oad[32];
        unsigned char rad[32];
        unsigned char dad[32];
+       unsigned char cad[32];
        unsigned char orig_dad[32];
        unsigned char keypad[32];
-  
+
        unsigned char info_dad[64];
        unsigned char infos_pending[64];
-       unsigned char info_keypad[32];
-       unsigned char clisub[24];
-       unsigned char cldsub[24];
-       unsigned char fac[132];
-       unsigned char uu[256];
+
+/*     unsigned char info_keypad[32]; */
+/*     unsigned char clisub[24]; */
+/*     unsigned char cldsub[24]; */
+/*     unsigned char uu[256]; */
   
        int cause;
        int out_cause;
@@ -276,6 +350,16 @@ struct misdn_bchannel {
        int ec_deftaps;
        int ec_whenbridged;
        int ec_training;
+
+#ifdef WITH_BEROEC
+       beroec_t *ec;
+       int bnec_tail;
+       int bnec_ah;
+       int bnec_nlp;
+       int bnec_td;
+       int bnec_adapt;
+       int bnec_zero;
+#endif
        
        int orig;
 
@@ -288,17 +372,19 @@ struct misdn_bchannel {
 
 enum event_response_e (*cb_event) (enum event_e event, struct misdn_bchannel *bc, void *user_data);
 void (*cb_log) (int level, int port, char *tmpl, ...);
-int (*cb_clearl3_true)(void);
+int (*cb_jb_empty)(struct misdn_bchannel *bc, char *buffer, int len);
 
 struct misdn_lib_iface {
        
        enum event_response_e (*cb_event)(enum event_e event, struct misdn_bchannel *bc, void *user_data);
        void (*cb_log)(int level, int port, char *tmpl, ...);
-       int (*cb_clearl3_true)(void);
+       int (*cb_jb_empty)(struct misdn_bchannel *bc, char *buffer, int len);
 };
 
 /***** USER IFACE **********/
 
+void misdn_lib_nt_debug_init( int flags, char *file );
+
 int misdn_lib_init(char *portlist, struct misdn_lib_iface* iface, void *user_data);
 int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event );
 void misdn_lib_destroy(void);
@@ -313,8 +399,8 @@ struct misdn_bchannel* misdn_lib_get_free_bc(int port, int channel);
 
 void manager_bchannel_activate(struct misdn_bchannel *bc);
 void manager_bchannel_deactivate(struct misdn_bchannel * bc);
-int manager_tx2misdn_frm(struct misdn_bchannel *bc, void *data, int len);
-void manager_send_tone (struct misdn_bchannel *bc, enum tone_e tone);
+
+int misdn_lib_tx2misdn_frm(struct misdn_bchannel *bc, void *data, int len);
 
 void manager_ph_control(struct misdn_bchannel *bc, int c1, int c2);
 
@@ -322,7 +408,13 @@ void manager_ph_control(struct misdn_bchannel *bc, int c1, int c2);
 int misdn_lib_port_restart(int port);
 int misdn_lib_get_port_info(int port);
 
-int misdn_lib_port_up(int port);
+int misdn_lib_is_port_blocked(int port);
+int misdn_lib_port_block(int port);
+int misdn_lib_port_unblock(int port);
+
+int misdn_lib_port_up(int port, int notcheck);
+
+int misdn_lib_get_port_down(int port);
 
 int misdn_lib_get_port_up (int port) ;
      
@@ -339,24 +431,26 @@ int misdn_lib_send_facility(struct misdn_bchannel *bc, enum facility_type fac, v
 void manager_ec_enable(struct misdn_bchannel *bc);
 void manager_ec_disable(struct misdn_bchannel *bc);
 
+void misdn_lib_send_tone(struct misdn_bchannel *bc, enum tone_e tone);
+
 void get_show_stack_details(int port, char *buf);
 
 
-/** Ibuf interface **/
-int misdn_ibuf_usedcount(void *buf);
-int misdn_ibuf_freecount(void *buf);
-void misdn_ibuf_memcpy_r(char *to, void *from, int len);
-void misdn_ibuf_memcpy_w(void *buf, char *from, int len);
+void misdn_lib_tone_generator_start(struct misdn_bchannel *bc);
+void misdn_lib_tone_generator_stop(struct misdn_bchannel *bc);
 
-/** Ibuf interface End **/
 
 void misdn_lib_setup_bc(struct misdn_bchannel *bc);
 
 void misdn_lib_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2);
 void misdn_lib_split_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2);
 
+void misdn_lib_echo(struct misdn_bchannel *bc, int onoff);
 
 int misdn_lib_is_ptp(int port);
+int misdn_lib_get_maxchans(int port);
+
+void misdn_lib_reinit_nt_stack(int port);
 
 #define PRI_TRANS_CAP_SPEECH                                    0x0
 #define PRI_TRANS_CAP_DIGITAL                                   0x08
@@ -364,4 +458,11 @@ int misdn_lib_is_ptp(int port);
 #define PRI_TRANS_CAP_3_1K_AUDIO                                0x10
 #define PRI_TRANS_CAP_7K_AUDIO                                  0x11
 
+
+
+char *bc_state2str(enum bchannel_state state);
+void bc_state_change(struct misdn_bchannel *bc, enum bchannel_state state);
+
+
+
 #endif
index 0305a2dad3b393570fe9f0f2922dddaa75338a23..ff63339bcd34e81b3d0a17d4aa1111a291cf0b87 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef ISDN_LIB_INTERN
-#define ISDN_LIB_INTER
+#define ISDN_LIB_INTERN
 
 
 #include <mISDNuser/mISDNlib.h>
 
 #include "isdn_lib.h"
 
-
-
+#define QI_ELEMENT(a) a.off
 
 
 #ifndef mISDNUSER_HEAD_SIZE
 
-#ifdef MISDNUSER_JOLLY
 #define mISDNUSER_HEAD_SIZE (sizeof(mISDNuser_head_t))
-#else
-#define mISDNUSER_HEAD_SIZE (sizeof(mISDN_head_t))
-#endif
+/*#define mISDNUSER_HEAD_SIZE (sizeof(mISDN_head_t))*/
 #endif
 
 
@@ -37,8 +33,6 @@ struct isdn_msg {
   
        void (*msg_parser)(struct isdn_msg *msgs, msg_t *msg, struct misdn_bchannel *bc, int nt);
        msg_t *(*msg_builder)(struct isdn_msg *msgs, struct misdn_bchannel *bc, int nt);
-       void (*msg_printer)(struct isdn_msg *msgs);
-  
        char *info;
   
 } ; 
@@ -60,9 +54,16 @@ struct misdn_stack {
        int b_stids[MAX_BCHANS + 1];
   
        int ptp;
+
+       int l2upcnt;
+
+       int l2_id;
        int lower_id;
        int upper_id;
   
+
+       int blocked;
+
        int l2link;
   
        time_t l2establish;
@@ -70,7 +71,7 @@ struct misdn_stack {
        int l1link;
        int midev;
   
-       enum mode_e {NT_MODE, TE_MODE} mode;
+       int nt;
        
        int pri;
   
@@ -78,6 +79,7 @@ struct misdn_stack {
        int procids[0x100+1];
 
        msg_queue_t downqueue;
+       msg_queue_t upqueue;
        int busy;
   
        int port;
@@ -96,4 +98,6 @@ struct misdn_stack {
 
 struct misdn_stack* get_stack_by_bc(struct misdn_bchannel *bc);
 
+
+
 #endif
index 9b59f8685767cf9b08031be149ad05a1d0831998..d23031ecb3ff614fd184a0d4e267e5651b5d0bae 100644 (file)
  */
 
 
+#include "isdn_lib_intern.h"
+
+
 #include "isdn_lib.h"
+
 #include "ie.c"
 
+#include "fac.h"
+
+
+void set_channel(struct misdn_bchannel *bc, int channel) {
+
+       cb_log(3,bc->port,"set_channel: bc->channel:%d channel:%d\n", bc->channel, channel);
+       
+       
+       if (channel==0xff) {
+               /* any channel */
+               channel=-1;
+       }
+       
+       /*  ALERT: is that everytime true ?  */
+       if (channel > 0 && bc->nt ) {
+               
+               if (bc->channel && ( bc->channel != 0xff) ) {
+                       cb_log(0,bc->port,"We already have a channel (%d)\n", bc->channel);
+               } else {
+                       bc->channel = channel;
+               }
+       }
+       
+       if (channel > 0 && !bc->nt ) 
+               bc->channel = channel;
+}
 
 void parse_proceeding (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
        int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
        CALL_PROCEEDING_t *proceeding=(CALL_PROCEEDING_t*)((unsigned long)msg->data+ HEADER_LEN);
-       struct misdn_stack *stack=get_stack_by_bc(bc);
+       //struct misdn_stack *stack=get_stack_by_bc(bc);
        
        {
                int  exclusive, channel;
                dec_ie_channel_id(proceeding->CHANNEL_ID, (Q931_info_t *)proceeding, &exclusive, &channel, nt,bc);
+
+               set_channel(bc,channel);
                
-               if (channel==0xff) /* any channel */
-                       channel=-1;
-    
-               /*  ALERT: is that everytime true ?  */
-               if (channel > 0 && stack->mode == NT_MODE) 
-                       bc->channel = channel;
        }
        
        dec_ie_progress(proceeding->PROGRESS, (Q931_info_t *)proceeding, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
        
+       
 #if DEBUG 
        printf("Parsing PROCEEDING Msg\n"); 
 #endif
@@ -59,9 +86,6 @@ msg_t *build_proceeding (struct isdn_msg msgs[], struct misdn_bchannel *bc, int
 #endif
        return msg; 
 }
-void print_proceeding (struct isdn_msg msgs[]) 
-{
-}
 
 void parse_alerting (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -94,9 +118,6 @@ msg_t *build_alerting (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt
 #endif
        return msg; 
 }
-void print_alerting (struct isdn_msg msgs[]) 
-{
-}
 
 
 void parse_progress (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
@@ -125,10 +146,6 @@ msg_t *build_progress (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt
 #endif
        return msg; 
 }
-void print_progress (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 { 
@@ -142,87 +159,76 @@ void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc,
        {
                int type,plan,present, screen;
                char id[32];
-               dec_ie_calling_pn(setup->CALLING_PN, qi, &type, &plan, &present, &screen, (unsigned char *)id, sizeof(id), nt,bc);
+               dec_ie_calling_pn(setup->CALLING_PN, qi, &type, &plan, &present, &screen, (unsigned char *)id, sizeof(id)-1, nt,bc);
 
                bc->onumplan=type; 
                strcpy(bc->oad, id);
                switch (present) {
                case 0:
-//                     cb_log(3, bc->stack->port, " --> Pres:0\n");
                        bc->pres=0; /* screened */
                        break;
                case 1:
-//                     cb_log(3, bc->stack->port, " --> Pres:1\n");
                        bc->pres=1; /* not screened */
                        break;
                default:
-//                     cb_log(3, bc->stack->port, " --> Pres:%d\n",present);
                        bc->pres=0;
                }
                switch (screen) {
                case 0:
-//                     cb_log(4, bc->stack->port, " --> Screen:0\n");
                        break;
                default:
-//                     cb_log(4, bc->stack->port, " --> Screen:%d\n",screen);
                        ;
                } 
        }
        {
                int  type, plan;
                char number[32]; 
-               dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *)setup, &type, &plan, (unsigned char *)number, sizeof(number), nt,bc);
+               dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *)setup, &type, &plan, (unsigned char *)number, sizeof(number)-1, nt,bc);
                strcpy(bc->dad, number);
                bc->dnumplan=type; 
        }
        {
                char keypad[32];
-               dec_ie_keypad(setup->KEYPAD, (Q931_info_t *)setup, (unsigned char *)keypad, sizeof(keypad), nt,bc);
+               dec_ie_keypad(setup->KEYPAD, (Q931_info_t *)setup, (unsigned char *)keypad, sizeof(keypad)-1, nt,bc);
                strcpy(bc->keypad, keypad);
        }
 
        {
-               int  sending_complete;
-               dec_ie_complete(setup->COMPLETE, (Q931_info_t *)setup, &sending_complete, nt,bc);
+               dec_ie_complete(setup->COMPLETE, (Q931_info_t *)setup, &bc->sending_complete, nt,bc);
+               
        }
   
        {
                int  type, plan, present, screen, reason;
                char id[32]; 
-               dec_ie_redir_nr(setup->REDIR_NR, (Q931_info_t *)setup, &type, &plan, &present, &screen, &reason, (unsigned char *)id, sizeof(id), nt,bc);
+               dec_ie_redir_nr(setup->REDIR_NR, (Q931_info_t *)setup, &type, &plan, &present, &screen, &reason, (unsigned char *)id, sizeof(id)-1, nt,bc);
     
                strcpy(bc->rad, id);
                bc->rnumplan=type; 
-//             cb_log(3, bc->stack->port, " --> Redirecting number (REDIR_NR): '%s'\n", id);
        }
        {
                int  coding, capability, mode, rate, multi, user, async, urate, stopbits, dbits, parity;
                dec_ie_bearer(setup->BEARER, (Q931_info_t *)setup, &coding, &capability, &mode, &rate, &multi, &user, &async, &urate, &stopbits, &dbits, &parity, nt,bc);
                switch (capability) {
                case -1: bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED; 
-//                     cb_log(2, bc->stack->port, " --> cap -1 -> digital\n");
                        break;
                case 0: bc->capability=INFO_CAPABILITY_SPEECH;
-//                     cb_log(2, bc->stack->port, " --> cap speech\n");
+                       break;
+               case 18: bc->capability=INFO_CAPABILITY_VIDEO;
                        break;
                case 8: bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
                        bc->user1 = user;
-                       bc->async = async;
                        bc->urate = urate;
                        
                        bc->rate = rate;
                        bc->mode = mode;
-                       
-//                     cb_log(2, bc->stack->port, " --> cap unres Digital (user l1 %d, async %d, user rate %d\n", user, async, urate);
                        break;
                case 9: bc->capability=INFO_CAPABILITY_DIGITAL_RESTRICTED;
-//                     cb_log(2, bc->stack->port, " --> cap res Digital\n");
                        break;
                default:
-//                     cb_log(2, bc->stack->port, " --> cap Else\n");
                        break;
                }
-
+               
                switch(user) {
                case 2:
                        bc->law=INFO_CODEC_ULAW;
@@ -240,11 +246,8 @@ void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc,
        {
                int  exclusive, channel;
                dec_ie_channel_id(setup->CHANNEL_ID, (Q931_info_t *)setup, &exclusive, &channel, nt,bc);
-               if (channel==0xff) /* any channel */
-                       channel=-1;
-
-               if (channel > 0) 
-                       bc->channel = channel;
+               
+               set_channel(bc,channel);
        }
        
        dec_ie_progress(setup->PROGRESS, (Q931_info_t *)setup, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
@@ -260,12 +263,12 @@ msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
   
        setup=(SETUP_t*)((msg->data+HEADER_LEN)); 
   
-//     cb_log(2, bc->stack->port, " --> oad %s dad %s channel %d\n",bc->oad, bc->dad,bc->channel);
        if (bc->channel == 0 || bc->channel == ANY_CHANNEL || bc->channel==-1)
                enc_ie_channel_id(&setup->CHANNEL_ID, msg, 0, bc->channel, nt,bc);
-       else
+       else 
                enc_ie_channel_id(&setup->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
-  
+       
+       
        {
                int type=bc->onumplan,plan=1,present=bc->pres,screen=bc->screen;
                enc_ie_calling_pn(&setup->CALLING_PN, msg, type, plan, present,
@@ -276,6 +279,13 @@ msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
                if (bc->dad[0])
                        enc_ie_called_pn(&setup->CALLED_PN, msg, bc->dnumplan, 1, bc->dad, nt,bc);
        }
+
+       {
+               if (bc->rad[0])
+                       enc_ie_redir_nr(&setup->REDIR_NR, msg, 1, 1,  bc->pres, bc->screen, 0, bc->rad, nt,bc);
+       }
+
+       
   
        if (*bc->display) {
                enc_ie_display(&setup->DISPLAY, msg, bc->display, nt,bc);
@@ -299,6 +309,8 @@ msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
                        break;
                case INFO_CAPABILITY_DIGITAL_UNRESTRICTED: capability = 8;
                        user=-1;
+                       mode=bc->mode;
+                       rate=bc->rate;
                        break;
                case INFO_CAPABILITY_DIGITAL_RESTRICTED: capability = 9;
                        user=-1;
@@ -318,19 +330,23 @@ msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
        return msg; 
 }
 
-void print_setup (struct isdn_msg msgs[]) 
-{
-}
-
 void parse_connect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
        int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
        CONNECT_t *connect=(CONNECT_t*)((unsigned long)(msg->data+HEADER_LEN));
   
+       int plan,pres,screen;
+       
        bc->ces = connect->ces;
        bc->ces = connect->ces;
 
        dec_ie_progress(connect->PROGRESS, (Q931_info_t *)connect, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
+
+       dec_ie_connected_pn(connect->CONNECT_PN,(Q931_info_t *)connect, &bc->cpnnumplan, &plan, &pres, &screen, bc->cad, 31, nt, bc);
+
+       /*
+               cb_log(1,bc->port,"CONNETED PN: %s cpn_dialplan:%d\n", connected_pn, type);
+       */
        
 #if DEBUG 
        printf("Parsing CONNECT Msg\n"); 
@@ -341,7 +357,9 @@ msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
        int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
        CONNECT_t *connect;
        msg_t *msg =(msg_t*)create_l3msg(CC_CONNECT | REQUEST, MT_CONNECT,  bc?bc->l3_id:-1, sizeof(CONNECT_t) ,nt); 
-  
+       
+       cb_log(6,bc->port,"BUILD_CONNECT: bc:%p bc->l3id:%d, nt:%d\n",bc,bc->l3_id,nt);
+
        connect=(CONNECT_t*)((msg->data+HEADER_LEN)); 
 
        if (nt) {
@@ -351,8 +369,8 @@ msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
        }
   
        {
-               int type=0, plan=1, present=2, screen=0;
-               enc_ie_connected_pn(&connect->CONNECT_PN, msg, type,plan, present, screen, (unsigned char*) bc->dad , nt , bc);
+               int type=bc->cpnnumplan, plan=1, present=2, screen=0;
+               enc_ie_connected_pn(&connect->CONNECT_PN, msg, type,plan, present, screen, (unsigned char*) bc->cad, nt , bc);
        }
 
 #if DEBUG 
@@ -360,10 +378,6 @@ msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
 #endif
        return msg; 
 }
-void print_connect (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_setup_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -374,11 +388,8 @@ void parse_setup_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_b
                int  exclusive, channel;
                dec_ie_channel_id(setup_acknowledge->CHANNEL_ID, (Q931_info_t *)setup_acknowledge, &exclusive, &channel, nt,bc);
 
-               if (channel==0xff) /* any channel */
-                       channel=-1;
 
-               if (channel > 0) 
-                       bc->channel = channel;
+               set_channel(bc, channel);
        }
        
        dec_ie_progress(setup_acknowledge->PROGRESS, (Q931_info_t *)setup_acknowledge, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
@@ -407,10 +418,6 @@ msg_t *build_setup_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *b
        return msg; 
 }
 
-void print_setup_acknowledge (struct isdn_msg msgs[]) 
-{
-}
-
 void parse_connect_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
 #if DEBUG 
@@ -434,10 +441,6 @@ msg_t *build_connect_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel
 #endif
        return msg; 
 }
-void print_connect_acknowledge (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_user_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -460,10 +463,6 @@ msg_t *build_user_information (struct isdn_msg msgs[], struct misdn_bchannel *bc
 #endif
        return msg; 
 }
-void print_user_information (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_suspend_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -486,10 +485,6 @@ msg_t *build_suspend_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc,
 #endif
        return msg; 
 }
-void print_suspend_reject (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_resume_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -512,10 +507,6 @@ msg_t *build_resume_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, i
 #endif
        return msg; 
 }
-void print_resume_reject (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_hold (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -538,10 +529,6 @@ msg_t *build_hold (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
 #endif
        return msg; 
 }
-void print_hold (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_suspend (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -564,10 +551,6 @@ msg_t *build_suspend (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
 #endif
        return msg; 
 }
-void print_suspend (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_resume (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -590,10 +573,6 @@ msg_t *build_resume (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
 #endif
        return msg; 
 }
-void print_resume (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_hold_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -616,10 +595,6 @@ msg_t *build_hold_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc
 #endif
        return msg; 
 }
-void print_hold_acknowledge (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_suspend_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -642,10 +617,6 @@ msg_t *build_suspend_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel
 #endif
        return msg; 
 }
-void print_suspend_acknowledge (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_resume_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -668,10 +639,6 @@ msg_t *build_resume_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *
 #endif
        return msg; 
 }
-void print_resume_acknowledge (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_hold_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -694,10 +661,6 @@ msg_t *build_hold_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int
 #endif
        return msg; 
 }
-void print_hold_reject (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_retrieve (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -720,10 +683,6 @@ msg_t *build_retrieve (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt
 #endif
        return msg; 
 }
-void print_retrieve (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_retrieve_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -747,10 +706,6 @@ msg_t *build_retrieve_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel
 #endif
        return msg; 
 }
-void print_retrieve_acknowledge (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_retrieve_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -773,10 +728,6 @@ msg_t *build_retrieve_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc,
 #endif
        return msg; 
 }
-void print_retrieve_reject (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_disconnect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -809,10 +760,6 @@ msg_t *build_disconnect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int
 #endif
        return msg; 
 }
-void print_disconnect (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_restart (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -827,10 +774,10 @@ void parse_restart (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *b
   
        {
                int  exclusive, channel;
-               dec_ie_channel_id(restart->CHANNEL_ID, (Q931_info_t *)restart, &exclusive, &channel, nt,bc);
+               dec_ie_channel_id(restart->CHANNEL_ID, (Q931_info_t *)restart, &exclusive, &bc->restart_channel, nt,bc);
                if (channel==0xff) /* any channel */
                        channel=-1;
-               cb_log(0, stack->port, "CC_RESTART Request on channel:%d on port:%d\n",stack->port);
+               cb_log(3, stack->port, "CC_RESTART Request on channel:%d on this port.\n");
        }
   
  
@@ -848,10 +795,6 @@ msg_t *build_restart (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
 #endif
        return msg; 
 }
-void print_restart (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_release (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -874,18 +817,14 @@ msg_t *build_release (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
  
        release=(RELEASE_t*)((msg->data+HEADER_LEN)); 
   
-  
-       enc_ie_cause(&release->CAUSE, msg, nt?1:0, bc->out_cause, nt,bc);
+       if (bc->out_cause>= 0)
+               enc_ie_cause(&release->CAUSE, msg, nt?1:0, bc->out_cause, nt,bc);
   
 #if DEBUG 
        printf("Building RELEASE Msg\n"); 
 #endif
        return msg; 
 }
-void print_release (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_release_complete (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -895,35 +834,30 @@ void parse_release_complete (struct isdn_msg msgs[], msg_t *msg, struct misdn_bc
        iframe_t *frm = (iframe_t*) msg->data;
 
        struct misdn_stack *stack=get_stack_by_bc(bc);
-       
-#ifdef MISDNUSER_JOLLY
        mISDNuser_head_t *hh;
        hh=(mISDNuser_head_t*)msg->data;
-#else
-       mISDN_head_t *hh;
-       hh=(mISDN_head_t*)msg->data;
-#endif
-  
+
+       /*hh=(mISDN_head_t*)msg->data;
+       mISDN_head_t *hh;*/
+
        if (nt) {
                if (hh->prim == (CC_RELEASE_COMPLETE|CONFIRM)) {
-                       cb_log(0, stack->port, "CC_RELEASE_COMPLETE|CONFIRM [NT] port:%d\n",stack->port);
+                       cb_log(0, stack->port, "CC_RELEASE_COMPLETE|CONFIRM [NT] \n");
                        return;
                }
        } else {
                if (frm->prim == (CC_RELEASE_COMPLETE|CONFIRM)) {
-                       cb_log(0, stack->port, "CC_RELEASE_COMPLETE|CONFIRM [TE] port:%d\n",stack->port);
+                       cb_log(0, stack->port, "CC_RELEASE_COMPLETE|CONFIRM [TE] \n");
                        return;
                }
        }
        dec_ie_cause(release_complete->CAUSE, (Q931_info_t *)(release_complete), &location, &bc->cause, nt,bc);
 
-  
 #if DEBUG 
        printf("Parsing RELEASE_COMPLETE Msg\n"); 
 #endif
-
 }
+
 msg_t *build_release_complete (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) 
 {
        int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
@@ -939,31 +873,26 @@ msg_t *build_release_complete (struct isdn_msg msgs[], struct misdn_bchannel *bc
 #endif
        return msg; 
 }
-void print_release_complete (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_facility (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
+//#define FACILITY_DECODE
+#ifdef FACILITY_DECODE
        int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
        FACILITY_t *facility=(FACILITY_t*)((unsigned long)(msg->data+HEADER_LEN)); 
        Q931_info_t *qi=(Q931_info_t*)(msg->data+HEADER_LEN);  
 
-
 #if DEBUG 
        printf("Parsing FACILITY Msg\n"); 
 #endif
 
        {
-               char fac[128];
-               int facility_len;
-               
-               dec_ie_facility(facility->FACILITY, qi, fac, &facility_len,  nt, bc);
+               fac_dec(facility->FACILITY, qi, &bc->fac_type, &bc->fac, bc);
        }
-               
+#endif 
+
 }
+
 msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) 
 {
        int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
@@ -977,17 +906,9 @@ msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt
                        printf("Sending %s as Display\n", bc->display);
                        enc_ie_display(&facility->DISPLAY, msg, bc->display, nt,bc);
                }
-
                
                
-               switch ( bc->facility ) {
-               case FACILITY_CALLDEFLECT:
-                       enc_facility_calldeflect(&facility->FACILITY, msg, bc->facility_calldeflect_nr, nt, bc);
-                       
-                       break;
-               case FACILITY_NONE:
-                       break;
-               }
+               fac_enc(&facility->FACILITY, msg, bc->out_fac_type, bc->out_fac,  bc);
                
        }
        
@@ -996,19 +917,14 @@ msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt
 #endif
        return msg; 
 }
-void print_facility (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_notify (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
 #if DEBUG 
        printf("Parsing NOTIFY Msg\n"); 
 #endif
-
 }
+
 msg_t *build_notify (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) 
 {
        int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
@@ -1022,19 +938,14 @@ msg_t *build_notify (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
 #endif
        return msg; 
 }
-void print_notify (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_status_enquiry (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
 #if DEBUG 
        printf("Parsing STATUS_ENQUIRY Msg\n"); 
 #endif
-
 }
+
 msg_t *build_status_enquiry (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) 
 {
        int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
@@ -1048,32 +959,25 @@ msg_t *build_status_enquiry (struct isdn_msg msgs[], struct misdn_bchannel *bc,
 #endif
        return msg; 
 }
-void print_status_enquiry (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
        int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
        INFORMATION_t *information=(INFORMATION_t*)((unsigned long)(msg->data+HEADER_LEN));
-
        {
                int  type, plan;
                char number[32];
                char keypad[32];
-               dec_ie_called_pn(information->CALLED_PN, (Q931_info_t *)information, &type, &plan, (unsigned char *)number, sizeof(number), nt,bc);
-               dec_ie_keypad(information->KEYPAD, (Q931_info_t *)information, (unsigned char *)keypad, sizeof(keypad), nt,bc);
+               dec_ie_called_pn(information->CALLED_PN, (Q931_info_t *)information, &type, &plan, (unsigned char *)number, sizeof(number)-1, nt, bc);
+               dec_ie_keypad(information->KEYPAD, (Q931_info_t *)information, (unsigned char *)keypad, sizeof(keypad)-1, nt, bc);
                strcpy(bc->info_dad, number);
                strcpy(bc->keypad,keypad);
-    
        }
 #if DEBUG 
        printf("Parsing INFORMATION Msg\n"); 
 #endif
-
 }
+
 msg_t *build_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) 
 {
        int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
@@ -1098,10 +1002,6 @@ msg_t *build_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int
 #endif
        return msg; 
 }
-void print_information (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_status (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
@@ -1115,9 +1015,8 @@ void parse_status (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc
 #if DEBUG 
        printf("Parsing STATUS Msg\n"); 
 #endif
-
 }
+
 msg_t *build_status (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) 
 {
        int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
@@ -1131,19 +1030,14 @@ msg_t *build_status (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
 #endif
        return msg; 
 }
-void print_status (struct isdn_msg msgs[]) 
-{
-}
-
 
 void parse_timeout (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) 
 {
 #if DEBUG 
        printf("Parsing STATUS Msg\n"); 
-#endif
-
+#endif 
 }
+
 msg_t *build_timeout (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) 
 {
        int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
@@ -1157,9 +1051,6 @@ msg_t *build_timeout (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
 #endif
        return msg; 
 }
-void print_timeout (struct isdn_msg msgs[]) 
-{
-}
 
 
 /************************************/
@@ -1171,96 +1062,96 @@ void print_timeout (struct isdn_msg msgs[])
 
 struct isdn_msg msgs_g[] = {
        {CC_PROCEEDING,L3,EVENT_PROCEEDING,
-        parse_proceeding,build_proceeding,print_proceeding,
+        parse_proceeding,build_proceeding,
         "PROCEEDING"},
        {CC_ALERTING,L3,EVENT_ALERTING,
-        parse_alerting,build_alerting,print_alerting,
+        parse_alerting,build_alerting,
         "ALERTING"},
        {CC_PROGRESS,L3,EVENT_PROGRESS,
-        parse_progress,build_progress,print_progress,
+        parse_progress,build_progress,
         "PROGRESS"},
        {CC_SETUP,L3,EVENT_SETUP,
-        parse_setup,build_setup,print_setup,
+        parse_setup,build_setup,
         "SETUP"},
        {CC_CONNECT,L3,EVENT_CONNECT,
-        parse_connect,build_connect,print_connect,
+        parse_connect,build_connect,
         "CONNECT"},
        {CC_SETUP_ACKNOWLEDGE,L3,EVENT_SETUP_ACKNOWLEDGE,
-        parse_setup_acknowledge,build_setup_acknowledge,print_setup_acknowledge,
+        parse_setup_acknowledge,build_setup_acknowledge,
         "SETUP_ACKNOWLEDGE"},
        {CC_CONNECT_ACKNOWLEDGE ,L3,EVENT_CONNECT_ACKNOWLEDGE ,
-        parse_connect_acknowledge ,build_connect_acknowledge ,print_connect_acknowledge ,
+        parse_connect_acknowledge ,build_connect_acknowledge,
         "CONNECT_ACKNOWLEDGE "},
        {CC_USER_INFORMATION,L3,EVENT_USER_INFORMATION,
-        parse_user_information,build_user_information,print_user_information,
+        parse_user_information,build_user_information,
         "USER_INFORMATION"},
        {CC_SUSPEND_REJECT,L3,EVENT_SUSPEND_REJECT,
-        parse_suspend_reject,build_suspend_reject,print_suspend_reject,
+        parse_suspend_reject,build_suspend_reject,
         "SUSPEND_REJECT"},
        {CC_RESUME_REJECT,L3,EVENT_RESUME_REJECT,
-        parse_resume_reject,build_resume_reject,print_resume_reject,
+        parse_resume_reject,build_resume_reject,
         "RESUME_REJECT"},
        {CC_HOLD,L3,EVENT_HOLD,
-        parse_hold,build_hold,print_hold,
+        parse_hold,build_hold,
         "HOLD"},
        {CC_SUSPEND,L3,EVENT_SUSPEND,
-        parse_suspend,build_suspend,print_suspend,
+        parse_suspend,build_suspend,
         "SUSPEND"},
        {CC_RESUME,L3,EVENT_RESUME,
-        parse_resume,build_resume,print_resume,
+        parse_resume,build_resume,
         "RESUME"},
        {CC_HOLD_ACKNOWLEDGE,L3,EVENT_HOLD_ACKNOWLEDGE,
-        parse_hold_acknowledge,build_hold_acknowledge,print_hold_acknowledge,
+        parse_hold_acknowledge,build_hold_acknowledge,
         "HOLD_ACKNOWLEDGE"},
        {CC_SUSPEND_ACKNOWLEDGE,L3,EVENT_SUSPEND_ACKNOWLEDGE,
-        parse_suspend_acknowledge,build_suspend_acknowledge,print_suspend_acknowledge,
+        parse_suspend_acknowledge,build_suspend_acknowledge,
         "SUSPEND_ACKNOWLEDGE"},
        {CC_RESUME_ACKNOWLEDGE,L3,EVENT_RESUME_ACKNOWLEDGE,
-        parse_resume_acknowledge,build_resume_acknowledge,print_resume_acknowledge,
+        parse_resume_acknowledge,build_resume_acknowledge,
         "RESUME_ACKNOWLEDGE"},
        {CC_HOLD_REJECT,L3,EVENT_HOLD_REJECT,
-        parse_hold_reject,build_hold_reject,print_hold_reject,
+        parse_hold_reject,build_hold_reject,
         "HOLD_REJECT"},
        {CC_RETRIEVE,L3,EVENT_RETRIEVE,
-        parse_retrieve,build_retrieve,print_retrieve,
+        parse_retrieve,build_retrieve,
         "RETRIEVE"},
        {CC_RETRIEVE_ACKNOWLEDGE,L3,EVENT_RETRIEVE_ACKNOWLEDGE,
-        parse_retrieve_acknowledge,build_retrieve_acknowledge,print_retrieve_acknowledge,
+        parse_retrieve_acknowledge,build_retrieve_acknowledge,
         "RETRIEVE_ACKNOWLEDGE"},
        {CC_RETRIEVE_REJECT,L3,EVENT_RETRIEVE_REJECT,
-        parse_retrieve_reject,build_retrieve_reject,print_retrieve_reject,
+        parse_retrieve_reject,build_retrieve_reject,
         "RETRIEVE_REJECT"},
        {CC_DISCONNECT,L3,EVENT_DISCONNECT,
-        parse_disconnect,build_disconnect,print_disconnect,
+        parse_disconnect,build_disconnect,
         "DISCONNECT"},
        {CC_RESTART,L3,EVENT_RESTART,
-        parse_restart,build_restart,print_restart,
+        parse_restart,build_restart,
         "RESTART"},
        {CC_RELEASE,L3,EVENT_RELEASE,
-        parse_release,build_release,print_release,
+        parse_release,build_release,
         "RELEASE"},
        {CC_RELEASE_COMPLETE,L3,EVENT_RELEASE_COMPLETE,
-        parse_release_complete,build_release_complete,print_release_complete,
+        parse_release_complete,build_release_complete,
         "RELEASE_COMPLETE"},
        {CC_FACILITY,L3,EVENT_FACILITY,
-        parse_facility,build_facility,print_facility,
+        parse_facility,build_facility,
         "FACILITY"},
        {CC_NOTIFY,L3,EVENT_NOTIFY,
-        parse_notify,build_notify,print_notify,
+        parse_notify,build_notify,
         "NOTIFY"},
        {CC_STATUS_ENQUIRY,L3,EVENT_STATUS_ENQUIRY,
-        parse_status_enquiry,build_status_enquiry,print_status_enquiry,
+        parse_status_enquiry,build_status_enquiry,
         "STATUS_ENQUIRY"},
        {CC_INFORMATION,L3,EVENT_INFORMATION,
-        parse_information,build_information,print_information,
+        parse_information,build_information,
         "INFORMATION"},
        {CC_STATUS,L3,EVENT_STATUS,
-        parse_status,build_status,print_status,
+        parse_status,build_status,
         "STATUS"},
        {CC_TIMEOUT,L3,EVENT_TIMEOUT,
-        parse_timeout,build_timeout,print_timeout,
+        parse_timeout,build_timeout,
         "TIMEOUT"},
-       {0,0,0,NULL,NULL,NULL,NULL}
+       {0,0,0,NULL,NULL,NULL}
 };
 
 #define msgs_max (sizeof(msgs_g)/sizeof(struct isdn_msg))
@@ -1271,15 +1162,12 @@ int isdn_msg_get_index(struct isdn_msg msgs[], msg_t *msg, int nt)
        int i;
 
        if (nt){
-#ifdef MISDNUSER_JOLLY
                mISDNuser_head_t *hh = (mISDNuser_head_t*)msg->data;
-#else
-               mISDN_head_t *hh = (mISDN_head_t*)msg->data;
-#endif
-    
-               for (i=0; i< msgs_max -1; i++) 
+               
+               for (i=0; i< msgs_max -1; i++) {
                        if ( (hh->prim&COMMAND_MASK)==(msgs[i].misdn_msg&COMMAND_MASK)) return i;
-    
+               }
+               
        } else {
                iframe_t *frm = (iframe_t*)msg->data;
     
@@ -1296,7 +1184,7 @@ int isdn_msg_get_index_by_event(struct isdn_msg msgs[], enum event_e event, int
        for (i=0; i< msgs_max; i++) 
                if ( event == msgs[i].event) return i;
 
-       cb_log(4,0, "get_index: EVENT NOT FOUND!!\n");
+       cb_log(10,0, "get_index: event not found!\n");
        
        return -1;
 }
@@ -1320,7 +1208,10 @@ char EVENT_CLEAN_INFO[] = "CLEAN_UP";
 char EVENT_DTMF_TONE_INFO[] = "DTMF_TONE";
 char EVENT_NEW_L3ID_INFO[] = "NEW_L3ID";
 char EVENT_NEW_BC_INFO[] = "NEW_BC";
+char EVENT_PORT_ALARM_INFO[] = "ALARM";
 char EVENT_BCHAN_DATA_INFO[] = "BCHAN_DATA";
+char EVENT_BCHAN_ACTIVATED_INFO[] = "BCHAN_ACTIVATED";
+char EVENT_TONE_GENERATE_INFO[] = "TONE_GENERATE";
 
 char * isdn_get_info(struct isdn_msg msgs[], enum event_e event, int nt)
 {
@@ -1333,6 +1224,9 @@ char * isdn_get_info(struct isdn_msg msgs[], enum event_e event, int nt)
        if (event == EVENT_NEW_L3ID) return EVENT_NEW_L3ID_INFO;
        if (event == EVENT_NEW_BC) return EVENT_NEW_BC_INFO;
        if (event == EVENT_BCHAN_DATA) return EVENT_BCHAN_DATA_INFO;
+       if (event == EVENT_BCHAN_ACTIVATED) return EVENT_BCHAN_ACTIVATED_INFO;
+       if (event == EVENT_TONE_GENERATE) return EVENT_TONE_GENERATE_INFO;
+       if (event == EVENT_PORT_ALARM) return EVENT_PORT_ALARM_INFO;
        
        return NULL;
 }
diff --git a/channels/misdn/mISDN.patch b/channels/misdn/mISDN.patch
deleted file mode 100644 (file)
index ccc8ae4..0000000
+++ /dev/null
@@ -1,2500 +0,0 @@
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/arith.h mISDN/drivers/isdn/hardware/mISDN/arith.h
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/arith.h     1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/arith.h  2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,347 @@
-+#ifndef _ZAPTEL_ARITH_H
-+#define _ZAPTEL_ARITH_H
-+/*
-+ * Handy add/subtract functions to operate on chunks of shorts.
-+ * Feel free to add customizations for additional architectures
-+ *
-+ */
-+
-+#ifdef CONFIG_ZAPTEL_MMX
-+#ifdef ZT_CHUNKSIZE
-+static inline void __ACSS(volatile short *dst, const short *src)
-+{
-+      __asm__ __volatile__ (
-+              "movq 0(%0), %%mm0;\n"
-+              "movq 0(%1), %%mm1;\n"
-+                "movq 8(%0), %%mm2;\n"
-+              "movq 8(%1), %%mm3;\n"
-+              "paddsw %%mm1, %%mm0;\n"
-+              "paddsw %%mm3, %%mm2;\n"
-+                "movq %%mm0, 0(%0);\n"
-+                "movq %%mm2, 8(%0);\n"
-+          : "=r" (dst)
-+          : "r" (src), "0" (dst)
-+          : "memory"
-+#if CLOBBERMMX
-+          , "%mm0", "%mm1", "%mm2", "%mm3"
-+#endif
-+      );
-+
-+}
-+static inline void __SCSS(volatile short *dst, const short *src)
-+{
-+      __asm__ __volatile__ (
-+              "movq 0(%0), %%mm0;\n"
-+              "movq 0(%1), %%mm1;\n"
-+                "movq 8(%0), %%mm2;\n"
-+              "movq 8(%1), %%mm3;\n"
-+              "psubsw %%mm1, %%mm0;\n"
-+              "psubsw %%mm3, %%mm2;\n"
-+                "movq %%mm0, 0(%0);\n"
-+                "movq %%mm2, 8(%0);\n"
-+          : "=r" (dst)
-+          : "r" (src), "0" (dst)
-+          : "memory"
-+#if CLOBBERMMX
-+          , "%mm0", "%mm1", "%mm2", "%mm3"
-+#endif
-+      );
-+
-+}
-+
-+#if (ZT_CHUNKSIZE == 8)
-+#define ACSS(a,b) __ACSS(a,b)
-+#define SCSS(a,b) __SCSS(a,b)
-+#elif (ZT_CHUNKSIZE > 8)
-+static inline void ACSS(volatile short *dst, const short *src)
-+{
-+      int x;
-+      for (x=0;x<ZT_CHUNKSIZE;x+=8)
-+              __ACSS(dst + x, src + x);
-+}
-+static inline void SCSS(volatile short *dst, const short *src)
-+{
-+      int x;
-+      for (x=0;x<ZT_CHUNKSIZE;x+=8)
-+              __SCSS(dst + x, src + x);
-+}
-+#else
-+#error No MMX for ZT_CHUNKSIZE < 8
-+#endif
-+#endif
-+static inline int CONVOLVE(const int *coeffs, const short *hist, int len)
-+{
-+      int sum;
-+      /* Divide length by 16 */
-+      len >>= 4;
-+      
-+      /* Clear our accumulator, mm4 */
-+      
-+      /* 
-+      
-+         For every set of eight...
-+      
-+         Load 16 coefficients into four registers...
-+         Shift each word right 16 to make them shorts...
-+         Pack the resulting shorts into two registers...
-+         With the coefficients now in mm0 and mm2, load the 
-+              history into mm1 and mm3...
-+         Multiply/add mm1 into mm0, and mm3 into mm2...
-+         Add mm2 into mm0 (without saturation, alas).  Now we have two half-results.
-+         Accumulate in mm4 (again, without saturation, alas)
-+      */
-+      __asm__ (
-+              "pxor %%mm4, %%mm4;\n"
-+              "mov %1, %%edi;\n"
-+              "mov %2, %%esi;\n"
-+              "mov %3, %%ecx;\n"
-+              "1:"
-+                      "movq  0(%%edi), %%mm0;\n"
-+                      "movq  8(%%edi), %%mm1;\n"
-+                      "movq 16(%%edi), %%mm2;\n"
-+                      "movq 24(%%edi), %%mm3;\n"
-+                      /* can't use 4/5 since 4 is the accumulator for us */
-+                      "movq 32(%%edi), %%mm6;\n"
-+                      "movq 40(%%edi), %%mm7;\n"
-+                      "psrad $16, %%mm0;\n"
-+                      "psrad $16, %%mm1;\n"
-+                      "psrad $16, %%mm2;\n"
-+                      "psrad $16, %%mm3;\n"
-+                      "psrad $16, %%mm6;\n"
-+                      "psrad $16, %%mm7;\n"
-+                      "packssdw %%mm1, %%mm0;\n"
-+                      "packssdw %%mm3, %%mm2;\n"
-+                      "packssdw %%mm7, %%mm6;\n"
-+                      "movq 0(%%esi), %%mm1;\n"
-+                      "movq 8(%%esi), %%mm3;\n"
-+                      "movq 16(%%esi), %%mm7;\n"
-+                      "pmaddwd %%mm1, %%mm0;\n"
-+                      "pmaddwd %%mm3, %%mm2;\n"
-+                      "pmaddwd %%mm7, %%mm6;\n"
-+                      "paddd %%mm6, %%mm4;\n"
-+                      "paddd %%mm2, %%mm4;\n"
-+                      "paddd %%mm0, %%mm4;\n"
-+                      /* Come back and do for the last few bytes */
-+                      "movq 48(%%edi), %%mm6;\n"
-+                      "movq 56(%%edi), %%mm7;\n"
-+                      "psrad $16, %%mm6;\n"
-+                      "psrad $16, %%mm7;\n"
-+                      "packssdw %%mm7, %%mm6;\n"
-+                      "movq 24(%%esi), %%mm7;\n"
-+                      "pmaddwd %%mm7, %%mm6;\n"
-+                      "paddd %%mm6, %%mm4;\n"
-+                      "add $64, %%edi;\n"
-+                      "add $32, %%esi;\n"
-+                      "dec %%ecx;\n"
-+              "jnz 1b;\n"
-+              "movq %%mm4, %%mm0;\n"
-+              "psrlq $32, %%mm0;\n"
-+              "paddd %%mm0, %%mm4;\n"
-+              "movd %%mm4, %0;\n"
-+              : "=r" (sum)
-+              : "r" (coeffs), "r" (hist), "r" (len)
-+              : "%ecx", "%edi", "%esi"
-+      );
-+              
-+      return sum;
-+}
-+
-+static inline void UPDATE(volatile int *taps, const short *history, const int nsuppr, const int ntaps)
-+{
-+      int i;
-+      int correction;
-+      for (i=0;i<ntaps;i++) {
-+              correction = history[i] * nsuppr;
-+              taps[i] += correction;
-+      }
-+}
-+
-+static inline void UPDATE2(volatile int *taps, volatile short *taps_short, const short *history, const int nsuppr, const int ntaps)
-+{
-+      int i;
-+      int correction;
-+#if 0
-+      ntaps >>= 4;
-+      /* First, load up taps, */
-+      __asm__ (
-+              "pxor %%mm4, %%mm4;\n"
-+              "mov %0, %%edi;\n"
-+              "mov %1, %%esi;\n"
-+              "mov %3, %%ecx;\n"
-+              "1:"
-+              "jnz 1b;\n"
-+              "movq %%mm4, %%mm0;\n"
-+              "psrlq $32, %%mm0;\n"
-+              "paddd %%mm0, %%mm4;\n"
-+              "movd %%mm4, %0;\n"
-+              : "=r" (taps), "=r" (taps_short)
-+              : "r" (history), "r" (nsuppr), "r" (ntaps), "0" (taps)
-+              : "%ecx", "%edi", "%esi"
-+      );
-+#endif
-+#if 1
-+      for (i=0;i<ntaps;i++) {
-+              correction = history[i] * nsuppr;
-+              taps[i] += correction;
-+              taps_short[i] = taps[i] >> 16;
-+      }
-+#endif        
-+}
-+
-+static inline int CONVOLVE2(const short *coeffs, const short *hist, int len)
-+{
-+      int sum;
-+      /* Divide length by 16 */
-+      len >>= 4;
-+      
-+      /* Clear our accumulator, mm4 */
-+      
-+      /* 
-+      
-+         For every set of eight...
-+         Load in eight coefficients and eight historic samples, multliply add and
-+         accumulate the result
-+      */
-+      __asm__ (
-+              "pxor %%mm4, %%mm4;\n"
-+              "mov %1, %%edi;\n"
-+              "mov %2, %%esi;\n"
-+              "mov %3, %%ecx;\n"
-+              "1:"
-+                      "movq  0(%%edi), %%mm0;\n"
-+                      "movq  8(%%edi), %%mm2;\n"
-+                      "movq 0(%%esi), %%mm1;\n"
-+                      "movq 8(%%esi), %%mm3;\n"
-+                      "pmaddwd %%mm1, %%mm0;\n"
-+                      "pmaddwd %%mm3, %%mm2;\n"
-+                      "paddd %%mm2, %%mm4;\n"
-+                      "paddd %%mm0, %%mm4;\n"
-+                      "movq  16(%%edi), %%mm0;\n"
-+                      "movq  24(%%edi), %%mm2;\n"
-+                      "movq 16(%%esi), %%mm1;\n"
-+                      "movq 24(%%esi), %%mm3;\n"
-+                      "pmaddwd %%mm1, %%mm0;\n"
-+                      "pmaddwd %%mm3, %%mm2;\n"
-+                      "paddd %%mm2, %%mm4;\n"
-+                      "paddd %%mm0, %%mm4;\n"
-+                      "add $32, %%edi;\n"
-+                      "add $32, %%esi;\n"
-+                      "dec %%ecx;\n"
-+              "jnz 1b;\n"
-+              "movq %%mm4, %%mm0;\n"
-+              "psrlq $32, %%mm0;\n"
-+              "paddd %%mm0, %%mm4;\n"
-+              "movd %%mm4, %0;\n"
-+              : "=r" (sum)
-+              : "r" (coeffs), "r" (hist), "r" (len)
-+              : "%ecx", "%edi", "%esi"
-+      );
-+              
-+      return sum;
-+}
-+static inline short MAX16(const short *y, int len, int *pos)
-+{
-+      int k;
-+      short max = 0;
-+      int bestpos = 0;
-+      for (k=0;k<len;k++) {
-+              if (max < y[k]) {
-+                      bestpos = k;
-+                      max = y[k];
-+              }
-+      }
-+      *pos = (len - 1 - bestpos);
-+      return max;
-+}
-+
-+
-+
-+#else
-+
-+#ifdef ZT_CHUNKSIZE
-+static inline void ACSS(short *dst, short *src)
-+{
-+      int x,sum;
-+      /* Add src to dst with saturation, storing in dst */
-+      for (x=0;x<ZT_CHUNKSIZE;x++) {
-+              sum = dst[x]+src[x];
-+              if (sum > 32767)
-+                      sum = 32767;
-+              else if (sum < -32768)
-+                      sum = -32768;
-+              dst[x] = sum;
-+      }
-+}
-+
-+static inline void SCSS(short *dst, short *src)
-+{
-+      int x,sum;
-+      /* Add src to dst with saturation, storing in dst */
-+      for (x=0;x<ZT_CHUNKSIZE;x++) {
-+              sum = dst[x]-src[x];
-+              if (sum > 32767)
-+                      sum = 32767;
-+              else if (sum < -32768)
-+                      sum = -32768;
-+              dst[x] = sum;
-+      }
-+}
-+
-+#endif        /* ZT_CHUNKSIZE */
-+
-+static inline int CONVOLVE(const int *coeffs, const short *hist, int len)
-+{
-+      int x;
-+      int sum = 0;
-+      for (x=0;x<len;x++)
-+              sum += (coeffs[x] >> 16) * hist[x];
-+      return sum;
-+}
-+
-+static inline int CONVOLVE2(const short *coeffs, const short *hist, int len)
-+{
-+      int x;
-+      int sum = 0;
-+      for (x=0;x<len;x++)
-+              sum += coeffs[x] * hist[x];
-+      return sum;
-+}
-+
-+static inline void UPDATE(int *taps, const short *history, const int nsuppr, const int ntaps)
-+{
-+      int i;
-+      int correction;
-+      for (i=0;i<ntaps;i++) {
-+              correction = history[i] * nsuppr;
-+              taps[i] += correction;
-+      }
-+}
-+
-+static inline void UPDATE2(int *taps, short *taps_short, const short *history, const int nsuppr, const int ntaps)
-+{
-+      int i;
-+      int correction;
-+      for (i=0;i<ntaps;i++) {
-+              correction = history[i] * nsuppr;
-+              taps[i] += correction;
-+              taps_short[i] = taps[i] >> 16;
-+      }
-+}
-+
-+static inline short MAX16(const short *y, int len, int *pos)
-+{
-+      int k;
-+      short max = 0;
-+      int bestpos = 0;
-+      for (k=0;k<len;k++) {
-+              if (max < y[k]) {
-+                      bestpos = k;
-+                      max = y[k];
-+              }
-+      }
-+      *pos = (len - 1 - bestpos);
-+      return max;
-+}
-+
-+#endif        /* MMX */
-+#endif        /* _ZAPTEL_ARITH_H */
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/biquad.h mISDN/drivers/isdn/hardware/mISDN/biquad.h
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/biquad.h    1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/biquad.h 2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,73 @@
-+/*
-+ * SpanDSP - a series of DSP components for telephony
-+ *
-+ * biquad.h - General telephony bi-quad section routines (currently this just
-+ *            handles canonic/type 2 form)
-+ *
-+ * Written by Steve Underwood <steveu@coppice.org>
-+ *
-+ * Copyright (C) 2001 Steve Underwood
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+typedef struct
-+{
-+    int32_t gain;
-+    int32_t a1;
-+    int32_t a2;
-+    int32_t b1;
-+    int32_t b2;
-+
-+    int32_t z1;
-+    int32_t z2;
-+} biquad2_state_t;
-+
-+static inline void biquad2_init (biquad2_state_t *bq,
-+                               int32_t gain,
-+                               int32_t a1,
-+                               int32_t a2,
-+                               int32_t b1,
-+                               int32_t b2)
-+{
-+    bq->gain = gain;
-+    bq->a1 = a1;
-+    bq->a2 = a2;
-+    bq->b1 = b1;
-+    bq->b2 = b2;
-+    
-+    bq->z1 = 0;
-+    bq->z2 = 0;    
-+}
-+/*- End of function --------------------------------------------------------*/
-+    
-+static inline int16_t biquad2 (biquad2_state_t *bq, int16_t sample)
-+{
-+    int32_t y;
-+    int32_t z0;
-+    
-+    z0 = sample*bq->gain + bq->z1*bq->a1 + bq->z2*bq->a2;
-+    y = z0 + bq->z1*bq->b1 + bq->z2*bq->b2;
-+
-+    bq->z2 = bq->z1;
-+    bq->z1 = z0 >> 15;
-+    y >>= 15;
-+    return  y;
-+}
-+/*- End of function --------------------------------------------------------*/
-+/*- End of file ------------------------------------------------------------*/
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/dsp_cancel.c mISDN/drivers/isdn/hardware/mISDN/dsp_cancel.c
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/dsp_cancel.c        1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/dsp_cancel.c     2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,390 @@
-+/* $Id$
-+ *
-+ * Simple but fast Echo cancellation for mISDN_dsp.
-+ *
-+ * Copyright Andreas Eversberg (jolly@jolly.de)
-+ *
-+ * This software may be used and distributed according to the terms
-+ * of the GNU General Public License, incorporated herein by reference.
-+ *
-+ */
-+
-+#include "layer1.h"
-+#include "helper.h"
-+#include "debug.h"
-+#include "dsp.h"
-+
-+
-+/*
-+ * how this works:
-+ *
-+ * 
-+ * 
-+ */
-+void bchdev_echocancel_chunk(dsp_t* dev, uint8_t *rxchunk, uint8_t *txchunk, uint16_t size);
-+int bchdev_echocancel_activate(dsp_t* dev, int deftaps, int train);
-+void bchdev_echocancel_deactivate(dsp_t* dev);
-+
-+
-+
-+
-+
-+
-+static char flip_table[256];
-+
-+void dsp_cancel_init_flip_bits()
-+{
-+      int i,k;
-+      
-+      for (i = 0 ; i < 256 ; i++) {
-+              unsigned char sample = 0 ;
-+              for (k = 0; k<8; k++) {
-+                      if ( i & 1 << k ) sample |= 0x80 >>  k;
-+              }
-+              flip_table[i] = sample;
-+      }
-+}
-+
-+static unsigned char * flip_buf_bits ( unsigned char * buf , int len)
-+{
-+      int i;
-+      char * start = buf;
-+      
-+      for (i = 0 ; i < len; i++) {
-+              buf[i] = flip_table[buf[i]];
-+      }
-+      
-+      return start;
-+}
-+
-+
-+
-+void
-+dsp_cancel_tx(dsp_t *dsp, u8 *data, int len)
-+{
-+      if (!dsp ) return ;
-+      if (!data) return;
-+      
-+      if (dsp->txbuflen + len < ECHOCAN_BUFLEN) {
-+              memcpy(&dsp->txbuf[dsp->txbuflen],data,len);
-+              dsp->txbuflen+=len;
-+      } else {
-+              printk("ECHOCAN: TXBUF Overflow len:%d newlen:%d\n",dsp->txbuflen,len);
-+              dsp->txbuflen=0;
-+      }
-+      
-+}
-+
-+void
-+dsp_cancel_rx(dsp_t *dsp, u8 *data, int len)
-+{
-+      if (!dsp ) return ;
-+      if (!data) return;
-+      
-+      if (len <= dsp->txbuflen) {
-+              char tmp[ECHOCAN_BUFLEN];
-+              
-+              int delta=dsp->txbuflen-len;
-+              
-+              memcpy(tmp,&dsp->txbuf[len],delta);
-+              
-+              flip_buf_bits(data,len);
-+              flip_buf_bits(dsp->txbuf,len);
-+              bchdev_echocancel_chunk(dsp, data, dsp->txbuf, len);
-+              flip_buf_bits(data,len);
-+              
-+              memcpy(dsp->txbuf,tmp,delta);
-+              dsp->txbuflen=delta;
-+              //dsp->txbuflen=0;
-+              
-+              //bchdev_echocancel_chunk(dsp,  dsp->txbuf, data, len);
-+      } else {
-+              printk("ECHOCAN: TXBUF Underrun len:%d newlen:%d\n",dsp->txbuflen,len);
-+      }
-+      
-+}
-+
-+int
-+dsp_cancel_init(dsp_t *dsp, int deftaps, int training, int delay)
-+{
-+      
-+      if (!dsp) return -1;
-+      
-+      printk("DSP_CANCEL_INIT called\n");
-+      
-+      if (delay < 0)
-+      {
-+              printk("Disabling EC\n");
-+              dsp->cancel_enable = 0;
-+              
-+              dsp->txbuflen=0;
-+              
-+              bchdev_echocancel_deactivate(dsp);
-+              
-+              return(0);
-+      }
-+      
-+      dsp->txbuflen=0;
-+      dsp->rxbuflen=0;
-+      
-+      
-+      bchdev_echocancel_activate(dsp,deftaps, training);
-+      
-+      printk("Enabling EC\n");
-+      dsp->cancel_enable = 1;
-+      return(0);
-+}
-+
-+
-+
-+
-+
-+/*****************************************************/
-+#define __ECHO_STATE_MUTE                       (1 << 8)
-+#define ECHO_STATE_IDLE                         (0)
-+#define ECHO_STATE_PRETRAINING          (1 | (__ECHO_STATE_MUTE))
-+#define ECHO_STATE_STARTTRAINING        (2 | (__ECHO_STATE_MUTE))
-+#define ECHO_STATE_AWAITINGECHO         (3 | (__ECHO_STATE_MUTE))
-+#define ECHO_STATE_TRAINING                     (4 | (__ECHO_STATE_MUTE))
-+#define ECHO_STATE_ACTIVE                       (5)
-+
-+#define AMI_MASK 0x55
-+
-+
-+static unsigned char linear2alaw (short linear)
-+{
-+      int mask;
-+      int seg;
-+      int pcm_val;
-+      static int seg_end[8] =
-+              {
-+                      0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
-+              };
-+    
-+      pcm_val = linear;
-+      if (pcm_val >= 0)
-+      {
-+              /* Sign (7th) bit = 1 */
-+              mask = AMI_MASK | 0x80;
-+      }
-+      else
-+      {
-+              /* Sign bit = 0 */
-+              mask = AMI_MASK;
-+              pcm_val = -pcm_val;
-+      }
-+
-+      /* Convert the scaled magnitude to segment number. */
-+      for (seg = 0;  seg < 8;  seg++)
-+      {
-+              if (pcm_val <= seg_end[seg])
-+                      break;
-+      }
-+      /* Combine the sign, segment, and quantization bits. */
-+      return  ((seg << 4) | ((pcm_val >> ((seg)  ?  (seg + 3)  :  4)) & 0x0F)) ^ mask;
-+}
-+
-+/*- End of function --------------------------------------------------------*/
-+
-+static short int alaw2linear (uint8_t alaw)
-+{
-+      int i;
-+      int seg;
-+
-+      alaw ^= AMI_MASK;
-+      i = ((alaw & 0x0F) << 4);
-+      seg = (((int) alaw & 0x70) >> 4);
-+      if (seg)
-+              i = (i + 0x100) << (seg - 1);
-+      return (short int) ((alaw & 0x80)  ?  i  :  -i);
-+}
-+
-+
-+/** @return string of given echo cancellation state */
-+char* bchdev_echocancel_statestr(uint16_t state)
-+{
-+  switch(state) {
-+  case ECHO_STATE_IDLE:
-+    return "idle";
-+    break;
-+  case ECHO_STATE_PRETRAINING:
-+    return "pre-training";
-+    break;
-+  case ECHO_STATE_STARTTRAINING:
-+    return "transmit impulse";
-+    break;
-+  case ECHO_STATE_AWAITINGECHO:
-+    return "awaiting echo";
-+    break;
-+  case ECHO_STATE_TRAINING:
-+    return "training start";
-+    break;
-+  case ECHO_STATE_ACTIVE:
-+    return "training finished";
-+    break;
-+  default:
-+    return "unknown";
-+  }
-+}
-+
-+/** Changes state of echo cancellation to given state */
-+void bchdev_echocancel_setstate(dsp_t* dev, uint16_t state)
-+{
-+  char* statestr = bchdev_echocancel_statestr(state);
-+  
-+  printk("bchdev: echo cancel state %d (%s)\n", state & 0xff, statestr);
-+  if (state == ECHO_STATE_ACTIVE)
-+        printk("bchdev: %d taps trained\n", dev->echolastupdate);
-+  dev->echostate = state;
-+}
-+
-+static int buf_size=0;
-+static int ec_timer=2000;
-+//static int ec_timer=1000;
-+
-+
-+/** Activates echo cancellation for the given bch_dev, device must have been locked before! */
-+int bchdev_echocancel_activate(dsp_t* dev, int deftaps, int training)
-+{
-+  int taps;
-+  
-+  if (! dev) return -EINVAL;
-+  
-+  if (dev->ec && dev->ecdis_rd && dev->ecdis_wr) {
-+        // already active
-+    return 0;
-+  }
-+  
-+  if (deftaps>0) {
-+        taps=deftaps;
-+  } else {
-+        taps=128;
-+  }
-+  
-+  
-+  switch (buf_size) {
-+  case  0: taps +=    0; break;
-+  case  1: taps +=  256-128; break;
-+  case  2: taps +=  512-128; break;
-+  default: taps += 1024-128;
-+  }
-+  
-+  if (!dev->ec) dev->ec = echo_can_create(taps, 0);
-+  if (!dev->ec) {
-+        return -ENOMEM;
-+  }
-+  
-+  dev->echolastupdate = 0;
-+
-+  if (!training) {
-+        dev->echotimer=0;
-+        bchdev_echocancel_setstate(dev, ECHO_STATE_IDLE);
-+  } else {
-+        if (training<10) 
-+                training= ec_timer;
-+        
-+        dev->echotimer      = training;
-+        bchdev_echocancel_setstate(dev, ECHO_STATE_PRETRAINING);
-+
-+  }
-+  
-+  if (!dev->ecdis_rd) dev->ecdis_rd = kmalloc(sizeof(echo_can_disable_detector_state_t), GFP_KERNEL);
-+  if (!dev->ecdis_rd) {
-+        kfree(dev->ec); dev->ec = NULL;
-+        return -ENOMEM;
-+  }
-+  echo_can_disable_detector_init(dev->ecdis_rd);
-+  
-+  if (!dev->ecdis_wr) dev->ecdis_wr = kmalloc(sizeof(echo_can_disable_detector_state_t), GFP_KERNEL);
-+  if (!dev->ecdis_wr) {
-+        kfree(dev->ec); dev->ec = NULL;
-+        kfree(dev->ecdis_rd); dev->ecdis_rd = NULL;
-+    return -ENOMEM;
-+  }
-+  echo_can_disable_detector_init(dev->ecdis_wr);
-+
-+  return 0;
-+}
-+
-+/** Deactivates echo cancellation for the given bch_dev, device must have been locked before! */
-+void bchdev_echocancel_deactivate(dsp_t* dev)
-+{
-+  if (! dev) return;
-+
-+  //chan_misdn_log("bchdev: deactivating echo cancellation on port=%04x, chan=%02x\n", dev->stack->port, dev->channel);
-+  
-+  if (dev->ec) echo_can_free(dev->ec);
-+  dev->ec = NULL;
-+  
-+  dev->echolastupdate = 0;
-+  dev->echotimer      = 0;
-+  bchdev_echocancel_setstate(dev, ECHO_STATE_IDLE);
-+
-+  if (dev->ecdis_rd) kfree(dev->ecdis_rd);
-+  dev->ecdis_rd = NULL;
-+  
-+  if (dev->ecdis_wr) kfree(dev->ecdis_wr);
-+  dev->ecdis_wr = NULL;
-+}
-+
-+/** Processes one TX- and one RX-packet with echocancellation */
-+void bchdev_echocancel_chunk(dsp_t* dev, uint8_t *rxchunk, uint8_t *txchunk, uint16_t size)
-+{
-+  int16_t rxlin, txlin;
-+  uint16_t pos;
-+
-+  /* Perform echo cancellation on a chunk if requested */
-+  if (dev->ec) {
-+    if (dev->echostate & __ECHO_STATE_MUTE) {
-+      if (dev->echostate == ECHO_STATE_STARTTRAINING) {
-+      // Transmit impulse now
-+      txchunk[0] = linear2alaw(16384);
-+      memset(txchunk+1, 0, size-1);
-+      bchdev_echocancel_setstate(dev, ECHO_STATE_TRAINING); //AWAITINGECHO);
-+      } else {
-+      // train the echo cancellation
-+      for (pos = 0; pos < size; pos++) {
-+        rxlin = alaw2linear(rxchunk[pos]);
-+        txlin = alaw2linear(txchunk[pos]);
-+        if (dev->echostate == ECHO_STATE_PRETRAINING) {
-+          if (dev->echotimer <= 0) {
-+            dev->echotimer = 0;
-+            bchdev_echocancel_setstate(dev, ECHO_STATE_STARTTRAINING);
-+          } else {
-+            dev->echotimer--;
-+          }
-+        }
-+        if ((dev->echostate == ECHO_STATE_AWAITINGECHO) && (txlin > 8000)) {
-+          dev->echolastupdate = 0;
-+          bchdev_echocancel_setstate(dev, ECHO_STATE_TRAINING);
-+        }
-+        if (dev->echostate == ECHO_STATE_TRAINING) {
-+          if (echo_can_traintap(dev->ec, dev->echolastupdate++, rxlin)) {
-+            bchdev_echocancel_setstate(dev, ECHO_STATE_ACTIVE);
-+          }
-+        }
-+
-+        rxchunk[pos] = linear2alaw(0);
-+        txchunk[pos] = linear2alaw(0);
-+      }
-+      }
-+    } else {
-+      for (pos = 0; pos < size; pos++) {
-+      rxlin = alaw2linear(rxchunk[pos]);
-+      txlin = alaw2linear(txchunk[pos]);
-+
-+      if (echo_can_disable_detector_update(dev->ecdis_rd, rxlin) || 
-+          echo_can_disable_detector_update(dev->ecdis_wr, txlin)) {
-+        bchdev_echocancel_deactivate(dev);
-+        printk("EC: Fax detected, EC disabled\n");
-+        return ;
-+      } else  {
-+        rxlin = echo_can_update(dev->ec, txlin, rxlin);
-+        rxchunk[pos] = linear2alaw(rxlin);
-+      }
-+      }
-+    }
-+  }
-+}
-+
-+/******************************************************/
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/dsp_core.c mISDN/drivers/isdn/hardware/mISDN/dsp_core.c
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/dsp_core.c  2005-01-29 17:15:21.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/dsp_core.c       2005-12-02 09:57:08.000000000 +0100
-@@ -42,17 +42,11 @@
-  *             v             |
-  *       +-----+-------------+-----+
-  *       |(3)(4)                   |
-- *       |                         |
-- *       |                         |
-  *       |           CMX           |
-  *       |                         |
-- *       |                         |
-- *       |                         |
-- *       |                         |
-  *       |           +-------------+
-  *       |           |       ^
-  *       |           |       |
-- *       |           |       |
-  *       |+---------+|  +----+----+
-  *       ||(1)      ||  |(5)      |
-  *       ||         ||  |         |
-@@ -62,7 +56,6 @@
-  *       |+----+----+|  +----+----+
-  *       +-----+-----+       ^
-  *             |             | 
-- *             |             |
-  *             v             |
-  *        +----+----+   +----+----+
-  *        |(5)      |   |(2)      |
-@@ -74,8 +67,18 @@
-  *             |             ^ 
-  *             |             |
-  *             v             |
-+ *        +----+-------------+----+
-+ *        |(7)                    |
-+ *        |                       |
-+ *        |   Echo Cancellation   |
-+ *        |                       |
-+ *        |                       |
-+ *        +----+-------------+----+
-+ *             |             ^ 
-+ *             |             |
-+ *             v             |
-  *        +----+----+   +----+----+
-- *        |(7)      |   |(7)      |
-+ *        |(8)      |   |(8)      |
-  *        |         |   |         |
-  *        | Encrypt |   | Decrypt |
-  *        |         |   |         |
-@@ -115,6 +118,13 @@
-  * data to/form upper layer may be swithed on/off individually without loosing
-  * features of CMX, Tones and DTMF.
-  *
-+ * Echo Cancellation: Sometimes we like to cancel echo from the interface.
-+ * Note that a VoIP call may not have echo caused by the IP phone. The echo
-+ * is generated by the telephone line connected to it. Because the delay
-+ * is high, it becomes an echo. RESULT: Echo Cachelation is required if
-+ * both echo AND delay is applied to an interface.
-+ * Remember that software CMX always generates a more or less delay.
-+ *
-  * If all used features can be realized in hardware, and if transmit and/or
-  * receive data ist disabled, the card may not send/receive any data at all.
-  * Not receiving is usefull if only announcements are played. Not sending is
-@@ -215,6 +225,9 @@
-                       printk(KERN_ERR "%s: failed to create tx packet\n", __FUNCTION__);
-                       return;
-               }
-+              /* if echo cancellation is enabled */
-+              if (dsp->cancel_enable)
-+                      dsp_cancel_tx(dsp, nskb->data, nskb->len);
-               /* crypt if enabled */
-               if (dsp->bf_enable)
-                       dsp_bf_encrypt(dsp, nskb->data, nskb->len);
-@@ -380,6 +393,34 @@
-                       if (dsp_debug & DEBUG_DSP_CMX)
-                               dsp_cmx_debug(dsp);
-                       break;
-+              case ECHOCAN_ON: /* turn echo calcellation on */
-+                      
-+                      if (len<4) {
-+                              ret = -EINVAL;
-+                              break;
-+                      }
-+                      int ec_arr[2];
-+                      
-+                      memcpy(&ec_arr,data,sizeof(ec_arr));
-+                      
-+                      
-+                      printk("data[0]: %d data[1]: %d, len :%d\n",ec_arr[0],
-+                             ec_arr[1] ,len);
-+                      
-+                      if (dsp_debug & DEBUG_DSP_CORE)
-+                              printk(KERN_DEBUG "%s: turn echo cancelation on (delay=%d attenuation-shift=%d\n", __FUNCTION__, ec_arr[0], ec_arr[1]);
-+                      
-+                      ret = dsp_cancel_init(dsp, ec_arr[0], ec_arr[1] ,1);
-+                      
-+                      dsp_cmx_hardware(dsp->conf, dsp);
-+                      break;
-+              case ECHOCAN_OFF: /* turn echo calcellation off */
-+                      if (dsp_debug & DEBUG_DSP_CORE)
-+                              printk(KERN_DEBUG "%s: turn echo cancelation off\n", __FUNCTION__);
-+                      
-+                      ret = dsp_cancel_init(dsp, 0,0,-1);
-+                      dsp_cmx_hardware(dsp->conf, dsp);
-+                      break;
-               case BF_ENABLE_KEY: /* turn blowfish on */
-                       if (len<4 || len>56) {
-                               ret = -EINVAL;
-@@ -522,6 +563,9 @@
-                       /* decrypt if enabled */
-                       if (dsp->bf_enable)
-                               dsp_bf_decrypt(dsp, skb->data, skb->len);
-+                      /* if echo cancellation is enabled */
-+                      if (dsp->cancel_enable)
-+                              dsp_cancel_rx(dsp, skb->data, skb->len);
-                       /* check if dtmf soft decoding is turned on */
-                       if (dsp->dtmf.software) {
-                               digits = dsp_dtmf_goertzel_decode(dsp, skb->data, skb->len, (dsp_options&DSP_OPT_ULAW)?1:0);
-@@ -919,6 +963,9 @@
-               dsp_audio_generate_ulaw_samples();
-       dsp_audio_generate_volume_changes();
-+
-+      dsp_cancel_init_flip_bits();
-+      
-       /* init global lock */
-       lock_HW_init(&dsp_lock);
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/dsp.h mISDN/drivers/isdn/hardware/mISDN/dsp.h
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/dsp.h       2005-01-29 17:15:31.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/dsp.h    2005-12-02 09:57:08.000000000 +0100
-@@ -40,6 +40,13 @@
- #include "memdbg.h"
- #endif
-+#include "ecdis.h"
-+#include "mec2.h"
-+
-+//#include "mec.h"
-+//#include "mec3.h"
-+
-+
- extern int dsp_options;
- extern int dsp_debug;
-@@ -109,6 +116,8 @@
- #define DSP_DTMF_NPOINTS 102
-+#define ECHOCAN_BUFLEN 4*128
-+
- typedef struct _dtmf_t {
-       int             software; /* dtmf uses software decoding */
-       int             hardware; /* dtmf uses hardware decoding */
-@@ -120,6 +129,13 @@
- } dtmf_t;
-+/**************
-+ *Cancel Stuff*
-+ ***************/
-+
-+void dsp_cancel_init_flip_bits(void);
-+
-+
- /***************
-  * tones stuff *
-  ***************/
-@@ -200,6 +216,25 @@
-       u8              bf_crypt_inring[16];
-       u8              bf_data_out[9];
-       int             bf_sync;
-+
-+      /* echo cancellation stuff */
-+      int             cancel_enable;
-+      echo_can_state_t* ec;      /**< == NULL: echo cancellation disabled;
-+                                    != NULL: echo cancellation enabled */
-+      
-+      echo_can_disable_detector_state_t* ecdis_rd;
-+      echo_can_disable_detector_state_t* ecdis_wr;
-+      
-+      uint16_t echotimer;
-+      uint16_t echostate;
-+      uint16_t echolastupdate;
-+      
-+      char txbuf[ECHOCAN_BUFLEN];
-+      int txbuflen;
-+      
-+      char rxbuf[ECHOCAN_BUFLEN];
-+      int rxbuflen;
-+      
- } dsp_t;
- /* functions */
-@@ -228,4 +263,8 @@
- extern int dsp_bf_init(dsp_t *dsp, const u8 *key, unsigned int keylen);
- extern void dsp_bf_cleanup(dsp_t *dsp);
-+extern void dsp_cancel_tx(dsp_t *dsp, u8 *data, int len);
-+extern void dsp_cancel_rx(dsp_t *dsp, u8 *data, int len);
-+extern int dsp_cancel_init(dsp_t *dsp, int taps, int training, int delay);
-+
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/ec.c mISDN/drivers/isdn/hardware/mISDN/ec.c
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/ec.c        1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/ec.c     2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,105 @@
-+#include "mec2.h"
-+#include "ec.h"
-+
-+
-+
-+#define __ECHO_STATE_MUTE                     (1 << 8)
-+#define ECHO_STATE_IDLE                               (0)
-+#define ECHO_STATE_PRETRAINING                (1 | (__ECHO_STATE_MUTE))
-+#define ECHO_STATE_STARTTRAINING      (2 | (__ECHO_STATE_MUTE))
-+#define ECHO_STATE_AWAITINGECHO               (3 | (__ECHO_STATE_MUTE))
-+#define ECHO_STATE_TRAINING                   (4 | (__ECHO_STATE_MUTE))
-+#define ECHO_STATE_ACTIVE                     (5)
-+
-+#define AMI_MASK 0x55
-+
-+static unsigned char linear2alaw (short linear)
-+{
-+    int mask;
-+    int seg;
-+    int pcm_val;
-+    static int seg_end[8] =
-+    {
-+         0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
-+    };
-+    
-+    pcm_val = linear;
-+    if (pcm_val >= 0)
-+    {
-+        /* Sign (7th) bit = 1 */
-+      mask = AMI_MASK | 0x80;
-+    }
-+    else
-+    {
-+        /* Sign bit = 0 */
-+        mask = AMI_MASK;
-+        pcm_val = -pcm_val;
-+    }
-+
-+    /* Convert the scaled magnitude to segment number. */
-+    for (seg = 0;  seg < 8;  seg++)
-+    {
-+        if (pcm_val <= seg_end[seg])
-+          break;
-+    }
-+    /* Combine the sign, segment, and quantization bits. */
-+    return  ((seg << 4) | ((pcm_val >> ((seg)  ?  (seg + 3)  :  4)) & 0x0F)) ^ mask;
-+}
-+/*- End of function --------------------------------------------------------*/
-+
-+static short int alaw2linear (uint8_t alaw)
-+{
-+    int i;
-+    int seg;
-+
-+    alaw ^= AMI_MASK;
-+    i = ((alaw & 0x0F) << 4);
-+    seg = (((int) alaw & 0x70) >> 4);
-+    if (seg)
-+        i = (i + 0x100) << (seg - 1);
-+    return (short int) ((alaw & 0x80)  ?  i  :  -i);
-+}
-+
-+
-+void ec_chunk(struct echo_can_s *echo_can, unsigned char *rxchunk, const unsigned char *txchunk, int chunk_size)
-+{
-+  short rxlin, txlin;
-+  int x;
-+  //unsigned long flags;
-+  /* Perform echo cancellation on a chunk if necessary */
-+  if (echo_can->ec) {
-+    if (echo_can->echostate & __ECHO_STATE_MUTE) {
-+      /* Special stuff for training the echo can */
-+      for (x=0;x< chunk_size;x++) {
-+      rxlin = alaw2linear(rxchunk[x]);
-+      txlin = alaw2linear(txchunk[x]);
-+      if (echo_can->echostate == ECHO_STATE_PRETRAINING) {
-+        if (--echo_can->echotimer <= 0) {
-+          echo_can->echotimer = 0;
-+          echo_can->echostate = ECHO_STATE_STARTTRAINING;
-+        }
-+      }
-+      if ((echo_can->echostate == ECHO_STATE_AWAITINGECHO) && (txlin > 8000)) {
-+        echo_can->echolastupdate = 0;
-+        echo_can->echostate = ECHO_STATE_TRAINING;
-+      }
-+      if (echo_can->echostate == ECHO_STATE_TRAINING) {
-+        if (echo_can_traintap(echo_can->ec, echo_can->echolastupdate++, rxlin)) {
-+#if 0
-+          printf("Finished training (%d taps trained)!\n", echo_can->echolastupdate);
-+#endif                                                
-+          echo_can->echostate = ECHO_STATE_ACTIVE;
-+        }
-+      }
-+      rxlin = 0;
-+      rxchunk[x] = linear2alaw((int)rxlin);
-+      }
-+    } else {
-+      for (x=0;x<chunk_size;x++) {
-+      rxlin = alaw2linear(rxchunk[x]);
-+      rxlin = echo_can_update(echo_can->ec,  alaw2linear(txchunk[x]), rxlin);
-+      rxchunk[x] = linear2alaw((int)rxlin);
-+      }
-+    }
-+  }
-+}
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/ecdis.h mISDN/drivers/isdn/hardware/mISDN/ecdis.h
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/ecdis.h     1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/ecdis.h  2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,118 @@
-+/*
-+ * SpanDSP - a series of DSP components for telephony
-+ *
-+ * ec_disable_detector.h - A detector which should eventually meet the
-+ *                         G.164/G.165 requirements for detecting the
-+ *                         2100Hz echo cancellor disable tone.
-+ *
-+ * Written by Steve Underwood <steveu@coppice.org>
-+ *
-+ * Copyright (C) 2001 Steve Underwood
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+#include "biquad.h"
-+
-+typedef struct
-+{
-+    biquad2_state_t notch;
-+    int notch_level;
-+    int channel_level;
-+    int tone_present;
-+    int tone_cycle_duration;
-+    int good_cycles;
-+    int hit;
-+} echo_can_disable_detector_state_t;
-+
-+
-+#define FALSE 0
-+#define TRUE (!FALSE)
-+
-+static inline void echo_can_disable_detector_init (echo_can_disable_detector_state_t *det)
-+{
-+    /* Elliptic notch */
-+    /* This is actually centred at 2095Hz, but gets the balance we want, due
-+       to the asymmetric walls of the notch */
-+    biquad2_init (&det->notch,
-+                (int32_t) (-0.7600000*32768.0),
-+                (int32_t) (-0.1183852*32768.0),
-+                (int32_t) (-0.5104039*32768.0),
-+                (int32_t) ( 0.1567596*32768.0),
-+                (int32_t) ( 1.0000000*32768.0));
-+
-+    det->channel_level = 0;
-+    det->notch_level = 0;    
-+    det->tone_present = FALSE;
-+    det->tone_cycle_duration = 0;
-+    det->good_cycles = 0;
-+    det->hit = 0;
-+}
-+/*- End of function --------------------------------------------------------*/
-+
-+static inline int echo_can_disable_detector_update (echo_can_disable_detector_state_t *det,
-+                                      int16_t amp)
-+{
-+    int16_t notched;
-+    
-+      notched = biquad2 (&det->notch, amp);
-+      /* Estimate the overall energy in the channel, and the energy in
-+         the notch (i.e. overall channel energy - tone energy => noise).
-+         Use abs instead of multiply for speed (is it really faster?).
-+         Damp the overall energy a little more for a stable result.
-+         Damp the notch energy a little less, so we don't damp out the
-+         blip every time the phase reverses */
-+        det->channel_level += ((abs(amp) - det->channel_level) >> 5);
-+      det->notch_level += ((abs(notched) - det->notch_level) >> 4);
-+      if (det->channel_level > 280)
-+      {
-+          /* There is adequate energy in the channel. Is it mostly at 2100Hz? */
-+          if (det->notch_level*6 < det->channel_level)
-+          {
-+                /* The notch says yes, so we have the tone. */
-+              if (!det->tone_present)
-+              {
-+                    /* Do we get a kick every 450+-25ms? */
-+                  if (det->tone_cycle_duration >= 425*8
-+                      &&
-+                      det->tone_cycle_duration <= 475*8)
-+                  {
-+                      det->good_cycles++;
-+                      if (det->good_cycles > 2)
-+                          det->hit = TRUE;
-+                  }
-+                  det->tone_cycle_duration = 0;
-+              }
-+              det->tone_present = TRUE;
-+          }
-+          else
-+          {
-+              det->tone_present = FALSE;
-+          }
-+          det->tone_cycle_duration++;
-+      }
-+      else
-+      {
-+          det->tone_present = FALSE;
-+          det->tone_cycle_duration = 0;
-+          det->good_cycles = 0;
-+      }
-+    return  det->hit;
-+}
-+/*- End of function --------------------------------------------------------*/
-+/*- End of file ------------------------------------------------------------*/
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/ec.h mISDN/drivers/isdn/hardware/mISDN/ec.h
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/ec.h        1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/ec.h     2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,12 @@
-+
-+
-+
-+struct echo_can_s {
-+  int echostate;
-+  int echotimer;
-+  int echolastupdate;
-+  echo_can_state_t  *ec;
-+}; 
-+
-+
-+
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c 2005-01-31 18:24:03.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c      2005-12-02 09:57:08.000000000 +0100
-@@ -136,7 +136,7 @@
- static int nt_t1_count[] = { 480, 240, 120, 60, 30, 15, 8, 4 };
- #define CLKDEL_TE     0x0f    /* CLKDEL in TE mode */
- #define CLKDEL_NT     0x0c    /* CLKDEL in NT mode (0x60 MUST not be included!) */
--static u_char silence =       0xff;   /* silence by LAW */
-+static u_char mysilence =     0xff;   /* silence by LAW */
- /* enable 32 bit fifo access (PC usage) */
- #define FIFO_32BIT_ACCESS
-@@ -903,11 +903,11 @@
-               bch->tx_idx = bch->tx_len = 0;
-       }
-       /* now we have no more data, so in case of transparent,
--       * we set the last byte in fifo to 'silence' in case we will get
-+       * we set the last byte in fifo to 'mysilence' in case we will get
-        * no more data at all. this prevents sending an undefined value.
-        */
-       if (!hdlc)
--              HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence);
-+              HFC_outb_(hc, A_FIFO_DATA0_NOINC, mysilence);
- }
-@@ -1551,7 +1551,7 @@
-               HFC_outb(hc, A_IRQ_MSK, 0);
-               HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
-               HFC_wait(hc);
--              HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence); /* tx silence */
-+              HFC_outb_(hc, A_FIFO_DATA0_NOINC, mysilence); /* tx silence */
-               /* enable RX fifo */
-               HFC_outb(hc, R_FIFO, (ch<<1)|1);
-               HFC_wait(hc);
-@@ -1692,7 +1692,7 @@
-       /* if off */
-       if (len <= 0) {
--              HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence);
-+              HFC_outb_(hc, A_FIFO_DATA0_NOINC, mysilence);
-               if (hc->chan[ch].slot_tx>=0) {
-                       if (debug & DEBUG_HFCMULTI_MODE)
-                               printk(KERN_DEBUG "%s: connecting PCM due to no more TONE: channel %d slot_tx %d\n", __FUNCTION__, ch, hc->chan[ch].slot_tx);
-@@ -2183,7 +2183,7 @@
-                       ret = 0;
-                       break;
--                      /* set silence */
-+                      /* set mysilence */
-                       case HW_SPL_LOOP_OFF:
-                       if (debug & DEBUG_HFCMULTI_MSG)
-                               printk(KERN_DEBUG "%s: HW_SPL_LOOP_OFF\n", __FUNCTION__);
-@@ -2799,7 +2799,13 @@
-               if (debug & DEBUG_HFCMULTI_INIT)
-                       printk(KERN_DEBUG "setup_pci(): investigating card entry %d (looking for type %d)\n", i, hc->type);
-               inuse:
-+
-+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
-+              tmp_dev = pci_get_subsys(id_list[i].vendor_id, id_list[i].device_id, id_list[i].vendor_sub, id_list[i].device_sub, tmp_dev);
-+#else
-               tmp_dev = pci_find_subsys(id_list[i].vendor_id, id_list[i].device_id, id_list[i].vendor_sub, id_list[i].device_sub, tmp_dev);
-+#endif
-+              
-               if (tmp_dev) {
-                       /* skip if already in use */
-                       list_for_each_entry_safe(hc_tmp, next, &HFCM_obj.ilist, list) {
-@@ -3318,9 +3324,9 @@
-               hc->type = type[HFC_cnt] & 0xff;
-               if (type[HFC_cnt] & 0x100) {
-                       test_and_set_bit(HFC_CHIP_ULAW, &hc->chip);
--                      silence = 0xff; /* ulaw silence */
-+                      mysilence = 0xff; /* ulaw silence */
-               } else
--                      silence = 0x2a; /* alaw silence */
-+                      mysilence = 0x2a; /* alaw silence */
-               if (type[HFC_cnt] & 0x200)
-                       test_and_set_bit(HFC_CHIP_DTMF, &hc->chip);
- //            if ((type[HFC_cnt]&0x400) && hc->type==4)
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/l3_udss1.c mISDN/drivers/isdn/hardware/mISDN/l3_udss1.c
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/l3_udss1.c  2005-03-26 11:21:39.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/l3_udss1.c       2005-12-02 09:57:08.000000000 +0100
-@@ -1202,6 +1202,14 @@
-       err = check_infoelements(pc, skb, ie_PROGRESS);
-       if (err)
-               l3dss1_std_ie_err(pc, err);
-+      /* START: patch by steinwej - http://www.beronet.com/bugs/bug_view_page.php?bug_id=0000095 */
-+      /* clear T310 if running */
-+      L3DelTimer(&pc->timer);
-+      if (pc->t303skb) {
-+              dev_kfree_skb(pc->t303skb);
-+              pc->t303skb = NULL;
-+      }
-+      /* END */
-       if (ERR_IE_COMPREHENSION != err) {
-               if (mISDN_l3up(pc, CC_PROGRESS | INDICATION, skb))
-                       dev_kfree_skb(skb);
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/Makefile mISDN/drivers/isdn/hardware/mISDN/Makefile
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/Makefile    2005-06-05 14:44:10.000000000 +0200
-+++ mISDN/drivers/isdn/hardware/mISDN/Makefile 2005-12-05 19:03:11.000000000 +0100
-@@ -30,6 +30,7 @@
- ifdef CONFIG_MISDN_SPEEDFAX
- obj-$(CONFIG_MISDN_DRV) += sedlfax.o
-+obj-$(CONFIG_MISDN_DRV) += faxl3.o
- endif
- ifdef CONFIG_MISDN_W6692
-@@ -70,8 +71,6 @@
-                    asn1_basic_service.o asn1_address.o asn1_enc.o capi_enc.o \
-                    supp_serv.o
- mISDN_dtmf-objs := dtmf.o
--mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o
-+mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o dsp_cancel.o
- mISDN_x25dte-objs := x25_dte.o x25_l3.o
- I4LmISDN-objs := i4l_mISDN.o
--
--include Rules.mISDN
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/Makefile.v2.6 mISDN/drivers/isdn/hardware/mISDN/Makefile.v2.6
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/Makefile.v2.6       2005-06-05 14:44:10.000000000 +0200
-+++ mISDN/drivers/isdn/hardware/mISDN/Makefile.v2.6    2005-12-02 09:57:08.000000000 +0100
-@@ -71,6 +71,6 @@
-                    asn1_basic_service.o asn1_address.o asn1_enc.o capi_enc.o \
-                    supp_serv.o
- mISDN_dtmf-objs := dtmf.o
--mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o
-+mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o dsp_cancel.o
- mISDN_x25dte-objs := x25_dte.o x25_l3.o
- I4LmISDN-objs := i4l_mISDN.o
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/mec2_const.h mISDN/drivers/isdn/hardware/mISDN/mec2_const.h
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/mec2_const.h        1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/mec2_const.h     2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,25 @@
-+/* 
-+   Important constants for tuning mec2 echo can
-+ */
-+#ifndef _MEC2_CONST_H
-+#define _MEC2_CONST_H
-+
-+
-+/* Convergence speed -- higher means slower */
-+#define DEFAULT_BETA1_I 2048
-+#define DEFAULT_SIGMA_LY_I 7
-+#define DEFAULT_SIGMA_LU_I 7
-+#define DEFAULT_ALPHA_ST_I 5
-+#define DEFAULT_ALPHA_YT_I 5
-+#define DEFAULT_CUTOFF_I 128
-+#define DEFAULT_HANGT 600
-+#define DEFAULT_SUPPR_I 16
-+#define MIN_UPDATE_THRESH_I 4096
-+#define DEFAULT_M 16
-+#define SUPPR_FLOOR -64
-+#define SUPPR_CEIL -24
-+#define RES_SUPR_FACTOR -20
-+#define AGGRESSIVE_HCNTR 160  /* 20ms */
-+
-+#endif /* _MEC2_CONST_H */
-+
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/mec2.h mISDN/drivers/isdn/hardware/mISDN/mec2.h
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/mec2.h      1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/mec2.h   2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,409 @@
-+/*
-+ * Mark's Second Echo Canceller
-+ * 
-+ * Copyright (C) 2002, Digium, Inc.
-+ *
-+ * This program is free software and may be used and
-+ * distributed according to the terms of the GNU
-+ * General Public License, incorporated herein by
-+ * reference.
-+ *
-+ */
-+#ifndef _MARK2_ECHO_H
-+#define _MARK2_ECHO_H
-+
-+#ifdef __KERNEL__
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#define MALLOC(a) kmalloc((a), GFP_KERNEL)
-+#define FREE(a) kfree(a)
-+#else
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <stdint.h>
-+#include <string.h>
-+#include <math.h>
-+#define MALLOC(a) malloc(a)
-+#define FREE(a) free(a)
-+#endif
-+
-+/* Get optimized routines for math */
-+#include "arith.h"
-+
-+#ifndef NULL
-+#define NULL 0
-+#endif
-+#ifndef FALSE
-+#define FALSE 0
-+#endif
-+#ifndef TRUE
-+#define TRUE (!FALSE)
-+#endif
-+
-+#include "mec2_const.h"
-+
-+/* Circular buffer definition */
-+typedef struct {
-+  int idx_d;
-+  int size_d;
-+  short *buf_d;       /* Twice as large as we need */
-+} echo_can_cb_s;
-+
-+// class definition
-+//
-+typedef struct  {
-+  /* Echo canceller definition */
-+
-+  /* absolute time */
-+  int i_d;
-+  
-+  /* pre-computed constants */
-+
-+  int N_d;
-+  int beta2_i;
-+
-+  // declare accumulators for power computations
-+  //
-+  int Ly_i;
-+  int Lu_i;
-+
-+  // declare an accumulator for the near-end signal detector
-+  //
-+  int s_tilde_i;
-+  int HCNTR_d;
-+
-+  // circular buffers and coefficients
-+  //
-+  int *a_i;
-+  short *a_s;
-+  echo_can_cb_s y_s;
-+  echo_can_cb_s s_s;
-+  echo_can_cb_s u_s;
-+  echo_can_cb_s y_tilde_s;
-+  int y_tilde_i;
-+
-+  /* Max memory */
-+  short max_y_tilde;
-+  int max_y_tilde_pos;
-+
-+} echo_can_state_t;
-+
-+static inline void init_cb_s(echo_can_cb_s *cb, int len, void *where)
-+{
-+      cb->buf_d = (short *)where;
-+      cb->idx_d = 0;
-+      cb->size_d = len;
-+}
-+
-+static inline void add_cc_s(echo_can_cb_s *cb, short newval)
-+{
-+    /* Can't use modulus because N+M isn't a power of two (generally) */
-+    cb->idx_d--;
-+    if (cb->idx_d < (int)0)
-+     {cb->idx_d += cb->size_d;}
-+      /* Load two copies into memory */
-+      cb->buf_d[cb->idx_d] = newval;
-+      cb->buf_d[cb->idx_d + cb->size_d] = newval;
-+}
-+
-+static inline short get_cc_s(echo_can_cb_s *cb, int pos)
-+{
-+      /* Load two copies into memory */
-+      return cb->buf_d[cb->idx_d + pos];
-+}
-+
-+static inline void init_cc(echo_can_state_t *ec, int N, int maxy, int maxu) {
-+
-+  void *ptr = ec;
-+  unsigned long tmp;
-+  /* double-word align past end of state */
-+  ptr += sizeof(echo_can_state_t);
-+  tmp = (unsigned long)ptr;
-+  tmp += 3;
-+  tmp &= ~3L;
-+  ptr = (void *)tmp;
-+  
-+  // reset parameters
-+  //
-+  ec->N_d = N;
-+  ec->beta2_i = DEFAULT_BETA1_I;
-+  
-+  // allocate coefficient memory
-+  //
-+  ec->a_i = ptr;
-+  ptr += (sizeof(int) * ec->N_d);
-+  ec->a_s = ptr;
-+  ptr += (sizeof(short) * ec->N_d);
-+
-+  /* Reset Y circular buffer (short version) */
-+  init_cb_s(&ec->y_s, maxy, ptr);
-+  ptr += (sizeof(short) * (maxy) * 2);
-+  
-+  /* Reset Sig circular buffer (short version for FIR filter) */
-+  init_cb_s(&ec->s_s, (1 << DEFAULT_ALPHA_ST_I), ptr);
-+  ptr += (sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) * 2);
-+
-+  init_cb_s(&ec->u_s, maxu, ptr);
-+  ptr += (sizeof(short) * maxu * 2);
-+
-+  // allocate a buffer for the reference signal power computation
-+  //
-+  init_cb_s(&ec->y_tilde_s, ec->N_d, ptr);
-+
-+
-+  // reset absolute time
-+  //
-+  ec->i_d = (int)0;
-+  
-+  // reset the power computations (for y and u)
-+  //
-+  ec->Ly_i = DEFAULT_CUTOFF_I;
-+  ec->Lu_i = DEFAULT_CUTOFF_I;
-+
-+  // reset the near-end speech detector
-+  //
-+  ec->s_tilde_i = 0;
-+  ec->HCNTR_d = (int)0;
-+
-+  // exit gracefully
-+  //
-+}
-+
-+static inline void echo_can_free(echo_can_state_t *ec)
-+{
-+      FREE(ec);
-+}
-+
-+static inline short echo_can_update(echo_can_state_t *ec, short iref, short isig) {
-+
-+  /* declare local variables that are used more than once
-+  */
-+  int k;
-+  int rs;
-+  short u;
-+  int Py_i;
-+  int two_beta_i;
-+  
-+  /***************************************************************************
-+  //
-+  // flow A on pg. 428
-+  //
-+   ***************************************************************************/
-+
-+  /* eq. (16): high-pass filter the input to generate the next value;
-+  //           push the current value into the circular buffer
-+  //
-+  // sdc_im1_d = sdc_d;
-+  // sdc_d = sig;
-+  //  s_i_d = sdc_d;
-+  //  s_d = s_i_d;
-+  //  s_i_d = (float)(1.0 - gamma_d) * s_i_d
-+     + (float)(0.5 * (1.0 - gamma_d)) * (sdc_d - sdc_im1_d); */
-+  
-+  
-+  /* Delete last sample from power estimate */
-+  ec->y_tilde_i -= abs(get_cc_s(&ec->y_s, (1 << DEFAULT_ALPHA_YT_I) - 1 )) >> DEFAULT_ALPHA_YT_I;
-+  /* push the reference data onto the circular buffer */
-+  add_cc_s(&ec->y_s, iref);
-+ 
-+  /* eq. (2): compute r in fixed-point */
-+  rs = CONVOLVE2(ec->a_s, ec->y_s.buf_d + ec->y_s.idx_d, ec->N_d);
-+  rs >>= 15;
-+
-+  /* eq. (3): compute the output value (see figure 3) and the error
-+  // note: the error is the same as the output signal when near-end
-+  // speech is not present
-+  */
-+  u = isig - rs;  
-+  
-+  add_cc_s(&ec->u_s, u);
-+  
-+
-+
-+  /* Delete oldest part of received s_tilde */
-+  ec->s_tilde_i -= abs(get_cc_s(&ec->s_s, (1 << DEFAULT_ALPHA_ST_I) - 1 ));
-+
-+  /* push the signal on the circular buffer, too */
-+  add_cc_s(&ec->s_s, isig);
-+  ec->s_tilde_i += abs(isig);
-+  ec->y_tilde_i += abs(iref) >> DEFAULT_ALPHA_YT_I;
-+
-+  /* Add to our list of recent y_tilde's */
-+  add_cc_s(&ec->y_tilde_s, ec->y_tilde_i);            
-+
-+  /****************************************************************************
-+  //
-+  // flow B on pg. 428
-+  // 
-+   ****************************************************************************/
-+  
-+  /* compute the new convergence factor
-+  */
-+  Py_i = (ec->Ly_i >> DEFAULT_SIGMA_LY_I) * (ec->Ly_i >> DEFAULT_SIGMA_LY_I);
-+  Py_i >>= 15;
-+  if (ec->HCNTR_d > 0) {
-+      Py_i = (1 << 15);
-+  }
-+  
-+#if 0
-+  printf("Py: %e, Py_i: %e\n", Py, Py_i * AMPL_SCALE_1);
-+#endif  
-+
-+  /* Vary rate of adaptation depending on position in the file
-+  // Do not do this for the first (DEFAULT_UPDATE_TIME) secs after speech
-+  // has begun of the file to allow the echo cancellor to estimate the
-+  // channel accurately
-+  */
-+#if 0
-+  if (ec->start_speech_d != 0 ){
-+    if ( ec->i_d > (DEFAULT_T0 + ec->start_speech_d)*(SAMPLE_FREQ) ){
-+      ec->beta2_d = max_cc_float(MIN_BETA,
-+                     DEFAULT_BETA1 * exp((-1/DEFAULT_TAU)*((ec->i_d/(float)SAMPLE_FREQ) -
-+                                               DEFAULT_T0 -
-+                                               ec->start_speech_d)));
-+    }
-+  }
-+  else {ec->beta2_d = DEFAULT_BETA1;}
-+#endif
-+  
-+  ec->beta2_i = DEFAULT_BETA1_I;      /* Fixed point, inverted */
-+  
-+  two_beta_i = (ec->beta2_i * Py_i) >> 15;    /* Fixed point version, inverted */
-+  if (!two_beta_i)
-+      two_beta_i++;
-+
-+  /* Update Lu_i (Suppressed power estimate) */
-+  ec->Lu_i -= abs(get_cc_s(&ec->u_s, (1 << DEFAULT_SIGMA_LU_I) - 1 )) ;
-+  ec->Lu_i += abs(u);
-+
-+  /* eq. (10): update power estimate of the reference
-+  */
-+  ec->Ly_i -= abs(get_cc_s(&ec->y_s, (1 << DEFAULT_SIGMA_LY_I) - 1)) ;
-+  ec->Ly_i += abs(iref);
-+
-+  if (ec->Ly_i < DEFAULT_CUTOFF_I)
-+      ec->Ly_i = DEFAULT_CUTOFF_I;
-+
-+#if 0
-+  printf("Float: %e, Int: %e\n", ec->Ly_d, (ec->Ly_i >> DEFAULT_SIGMA_LY_I) * AMPL_SCALE_1);
-+#endif
-+  
-+  if (ec->y_tilde_i > ec->max_y_tilde) {
-+      /* New highest y_tilde with full life */
-+      ec->max_y_tilde = ec->y_tilde_i;
-+      ec->max_y_tilde_pos = ec->N_d - 1;
-+  } else if (--ec->max_y_tilde_pos < 0) {
-+    /* Time to find new max y tilde... */
-+      ec->max_y_tilde = MAX16(ec->y_tilde_s.buf_d + ec->y_tilde_s.idx_d, ec->N_d, &ec->max_y_tilde_pos);
-+  }
-+
-+  if ((ec->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)) > ec->max_y_tilde)
-+    {
-+      ec->HCNTR_d = DEFAULT_HANGT;
-+    }
-+  else if (ec->HCNTR_d > (int)0)
-+    {
-+      ec->HCNTR_d--;
-+    }
-+
-+  /* update coefficients if no near-end speech and we have enough signal
-+   * to bother trying to update.
-+  */
-+  if (!ec->HCNTR_d && !(ec->i_d % DEFAULT_M) && 
-+      (ec->Lu_i > MIN_UPDATE_THRESH_I)) {
-+          // loop over all filter coefficients
-+          //
-+          for (k=0; k<ec->N_d; k++) {
-+            
-+            // eq. (7): compute an expectation over M_d samples 
-+            //
-+                int grad2;
-+            grad2 = CONVOLVE2(ec->u_s.buf_d + ec->u_s.idx_d,
-+                                                      ec->y_s.buf_d + ec->y_s.idx_d + k, DEFAULT_M);
-+            // eq. (7): update the coefficient
-+            //
-+            ec->a_i[k] += grad2 / two_beta_i;
-+                ec->a_s[k] = ec->a_i[k] >> 16;
-+          }
-+  }
-+
-+  /* paragraph below eq. (15): if no near-end speech,
-+  // check for residual error suppression
-+  */
-+#ifndef NO_ECHO_SUPPRESSOR
-+#ifdef AGGRESSIVE_SUPPRESSOR
-+  if ((ec->HCNTR_d < AGGRESSIVE_HCNTR) && (ec->Ly_i > (ec->Lu_i << 1))) {
-+      u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I)) + 1);
-+      u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I)) + 1);
-+  }
-+#else 
-+  if ((ec->HCNTR_d == 0) && ((ec->Ly_i/(ec->Lu_i + 1)) > DEFAULT_SUPPR_I)) {
-+      u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I + 2)) + 1);
-+  }
-+#endif        
-+#endif  
-+
-+#if 0
-+  if ((ec->HCNTR_d == 0) && ((ec->Lu_d/ec->Ly_d) < DEFAULT_SUPPR) &&
-+      (ec->Lu_d/ec->Ly_d > EC_MIN_DB_VALUE)) { 
-+    suppr_factor = (10/(float)(SUPPR_FLOOR-SUPPR_CEIL))*log(ec->Lu_d/ec->Ly_d)
-+      - SUPPR_CEIL/(float)(SUPPR_FLOOR - SUPPR_CEIL);
-+
-+    u_suppr = pow(10.0,(suppr_factor)*RES_SUPR_FACTOR/10.0)*u_suppr;
-+    
-+  }
-+#endif  
-+  ec->i_d++;
-+  return u;
-+}
-+
-+static inline echo_can_state_t *echo_can_create(int len, int adaption_mode)
-+{
-+      echo_can_state_t *ec;
-+      int maxy;
-+      int maxu;
-+      maxy = len + DEFAULT_M;
-+      maxu = DEFAULT_M;
-+      if (maxy < (1 << DEFAULT_ALPHA_YT_I))
-+              maxy = (1 << DEFAULT_ALPHA_YT_I);
-+      if (maxy < (1 << DEFAULT_SIGMA_LY_I))
-+              maxy = (1 << DEFAULT_SIGMA_LY_I);
-+      if (maxu < (1 << DEFAULT_SIGMA_LU_I))
-+              maxu = (1 << DEFAULT_SIGMA_LU_I);
-+      ec = (echo_can_state_t *)MALLOC(sizeof(echo_can_state_t) +
-+                                                                      4 +                                             /* align */
-+                                                                      sizeof(int) * len +                     /* a_i */
-+                                                                      sizeof(short) * len +           /* a_s */
-+                                                                      2 * sizeof(short) * (maxy) +    /* y_s */
-+                                                                      2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */
-+                                                                      2 * sizeof(short) * (maxu) +            /* u_s */
-+                                                                      2 * sizeof(short) * len);                       /* y_tilde_s */
-+      if (ec) {
-+              memset(ec, 0, sizeof(echo_can_state_t) +
-+                                                                      4 +                                             /* align */
-+                                                                      sizeof(int) * len +                     /* a_i */
-+                                                                      sizeof(short) * len +           /* a_s */
-+                                                                      2 * sizeof(short) * (maxy) +    /* y_s */
-+                                                                      2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */
-+                                                                      2 * sizeof(short) * (maxu) +            /* u_s */
-+                                                                      2 * sizeof(short) * len);                       /* y_tilde_s */
-+        init_cc(ec, len, maxy, maxu);
-+      }
-+      return ec;
-+}
-+
-+static inline int echo_can_traintap(echo_can_state_t *ec, int pos, short val)
-+{
-+      /* Reset hang counter to avoid adjustments after
-+         initial forced training */
-+      ec->HCNTR_d = ec->N_d << 1;
-+      if (pos >= ec->N_d)
-+              return 1;
-+      ec->a_i[pos] = val << 17;
-+      ec->a_s[pos] = val << 1;
-+      if (++pos >= ec->N_d)
-+              return 1;
-+      return 0;
-+}
-+
-+#endif
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/mec3.h mISDN/drivers/isdn/hardware/mISDN/mec3.h
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/mec3.h      1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/mec3.h   2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,243 @@
-+/*
-+ * Mark's Third Echo Canceller
-+ *
-+ * Copyright (C) 2003, Digium, Inc.
-+ *
-+ * This program is free software and may be used
-+ * and distributed under the terms of the GNU General Public 
-+ * License, incorporated herein by reference.  
-+ *
-+ * Dedicated to the crew of the Columbia, STS-107 for their
-+ * bravery and courageous sacrifice for science.
-+ *
-+ */
-+
-+#ifndef _MARK3_ECHO_H
-+#define _MARK3_ECHO_H
-+
-+
-+
-+#ifdef __KERNEL__
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#define MALLOC(a) kmalloc((a), GFP_KERNEL)
-+#define FREE(a) kfree(a)
-+#else
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <stdint.h>
-+#include <string.h>
-+#include <math.h>
-+#define MALLOC(a) malloc(a)
-+#define FREE(a) free(a)
-+#endif
-+
-+/* Features */
-+
-+/*
-+ * DO_BACKUP -- Backup coefficients, and revert in the presense of double talk to try to prevent
-+ * them from diverging during the ramp-up before the DTD kicks in
-+ */
-+/* #define DO_BACKUP */
-+
-+#define STEP_SHIFT                    2               /* Convergence rate higher = slower / better (as a shift) */
-+
-+#define SIGMA_REF_PWR         655             /* Keep denominator from being 0 */
-+
-+#define MIN_TX_ENERGY         256             /* Must have at least this much reference */
-+#define MIN_RX_ENERGY          32             /* Must have at least this much receive energy */
-+
-+#define MAX_ATTENUATION_SHIFT 6               /* Maximum amount of loss we care about */
-+#define MAX_BETA                      1024
-+
-+#define SUPPR_SHIFT                     4                             /* Amount of loss at which we suppress audio */
-+
-+#define HANG_TIME                     600             /* Hangover time */
-+
-+#define NTAPS                        2048                     /* Maximum number of echo can taps */
-+
-+#define BACKUP                                256                     /* Backup every this number of samples */
-+
-+#define POWER_OFFSET          5                       /* Shift power by this amount to be sure we don't overflow the
-+                                                                                 reference power.  Higher = less likely to overflow, lower = more accurage */
-+
-+#include "arith.h"
-+
-+typedef struct {
-+      short buf[NTAPS * 2];
-+      short max;
-+      int maxexp;
-+} cbuf_s;
-+
-+typedef struct {
-+      short   a_s[NTAPS];                             /* Coefficients in shorts */
-+      int     a_i[NTAPS];                             /* Coefficients in ints*/
-+#ifdef DO_BACKUP
-+      int     b_i[NTAPS];                             /* Coefficients (backup1) */
-+      int     c_i[NTAPS];                             /* Coefficients (backup2) */
-+#endif        
-+      cbuf_s  ref;                                    /* Reference excitation */
-+      cbuf_s  sig;                                    /* Signal (echo + near end + noise) */
-+      cbuf_s  e;                                              /* Error */
-+      int             refpwr;                                 /* Reference power */
-+      int             taps;                                   /* Number of taps */
-+      int             tappwr;                                 /* Power of taps */
-+      int             hcntr;                                  /* Hangtime counter */
-+      int pos;                                                /* Position in curcular buffers */
-+      int backup;                                             /* Backup timer */
-+} echo_can_state_t;
-+
-+static inline void echo_can_free(echo_can_state_t *ec)
-+{
-+      FREE(ec);
-+}
-+
-+static inline void buf_add(cbuf_s *b, short sample, int pos, int taps)
-+{
-+      /* Store and keep track of maxima */
-+      int x;
-+      b->buf[pos] = sample;
-+      b->buf[pos + taps] = sample;
-+      if (sample > b->max) {
-+              b->max = sample;
-+              b->maxexp = taps;
-+      } else {
-+              b->maxexp--;
-+              if (!b->maxexp) {
-+                      b->max = 0;
-+                      for (x=0;x<taps;x++)
-+                              if (b->max < abs(b->buf[pos + x])) {
-+                                      b->max = abs(b->buf[pos + x]);
-+                                      b->maxexp = x + 1;
-+                              }
-+              }
-+      }
-+}
-+
-+static inline short echo_can_update(echo_can_state_t *ec, short ref, short sig)
-+{
-+      int x;
-+      short u;
-+      int refpwr;
-+      int beta;                       /* Factor */
-+      int se;                 /* Simulated echo */
-+#ifdef DO_BACKUP
-+      if (!ec->backup) {
-+              /* Backup coefficients periodically */
-+              ec->backup = BACKUP;
-+              memcpy(ec->c_i,ec->b_i,sizeof(ec->c_i));
-+              memcpy(ec->b_i,ec->a_i,sizeof(ec->b_i));
-+      } else
-+              ec->backup--;
-+#endif                
-+      /* Remove old samples from reference power calculation */
-+      ec->refpwr -= ((ec->ref.buf[ec->pos] * ec->ref.buf[ec->pos]) >> POWER_OFFSET);
-+
-+      /* Store signal and reference */
-+      buf_add(&ec->ref, ref, ec->pos, ec->taps);
-+      buf_add(&ec->sig, sig, ec->pos, ec->taps);
-+
-+      /* Add new reference power */   
-+      ec->refpwr += ((ec->ref.buf[ec->pos] * ec->ref.buf[ec->pos]) >> POWER_OFFSET);
-+
-+
-+      /* Calculate simulated echo */
-+      se = CONVOLVE2(ec->a_s, ec->ref.buf + ec->pos, ec->taps);               
-+      se >>= 15;
-+      
-+      u = sig - se;
-+      if (ec->hcntr)
-+              ec->hcntr--;
-+
-+      /* Store error */
-+      buf_add(&ec->e, sig, ec->pos, ec->taps);
-+      if ((ec->ref.max > MIN_TX_ENERGY) && 
-+          (ec->sig.max > MIN_RX_ENERGY) &&
-+              (ec->e.max > (ec->ref.max >> MAX_ATTENUATION_SHIFT))) {
-+              /* We have sufficient energy */
-+              if (ec->sig.max < (ec->ref.max >> 1))  {
-+                      /* No double talk */
-+                      if (!ec->hcntr) {
-+                              refpwr = ec->refpwr >> (16 - POWER_OFFSET);
-+                              if (refpwr < SIGMA_REF_PWR)
-+                                      refpwr = SIGMA_REF_PWR;
-+                              beta = (u << 16) / refpwr;
-+                              beta >>= STEP_SHIFT;
-+                              if (beta > MAX_BETA)    
-+                                      beta = 0;
-+                              if (beta < -MAX_BETA)
-+                                      beta = 0;
-+                              /* Update coefficients */
-+                              for (x=0;x<ec->taps;x++) {
-+                                      ec->a_i[x] += beta * ec->ref.buf[ec->pos + x];
-+                                      ec->a_s[x] = ec->a_i[x] >> 16;
-+                              }
-+                      }
-+              } else {
-+#ifdef DO_BACKUP
-+                      if (!ec->hcntr) {
-+                              /* Our double talk detector is turning on for the first time.  Revert
-+                                 our coefficients, since we're probably well into the double talk by now */
-+                              memcpy(ec->a_i, ec->c_i, sizeof(ec->a_i));
-+                              for (x=0;x<ec->taps;x++) {
-+                                      ec->a_s[x] = ec->a_i[x] >> 16;
-+                              }
-+                      }
-+#endif                        
-+                      /* Reset hang-time counter, and prevent backups */
-+                      ec->hcntr = HANG_TIME;
-+#ifdef DO_BACKUP
-+                      ec->backup = BACKUP;
-+#endif                        
-+              }
-+      }
-+#ifndef NO_ECHO__SUPPRESSOR   
-+      if (ec->e.max < (ec->ref.max >> SUPPR_SHIFT)) {
-+              /* Suppress residual echo */
-+              u *= u;
-+              u >>= 16;
-+      } 
-+#endif        
-+      ec->pos--;
-+      if (ec->pos < 0)
-+              ec->pos = ec->taps-1;
-+      return u;
-+}
-+
-+static inline echo_can_state_t *echo_can_create(int taps, int adaption_mode)
-+{
-+      echo_can_state_t *ec;
-+      int x;
-+
-+      //taps = NTAPS;
-+      ec = MALLOC(sizeof(echo_can_state_t));
-+      if (ec) {
-+              memset(ec, 0, sizeof(echo_can_state_t));
-+              ec->taps = taps;
-+              ec->pos = ec->taps-1;
-+              for (x=0;x<31;x++) {
-+                      if ((1 << x) >= ec->taps) {
-+                              ec->tappwr = x;
-+                              break;
-+                      }
-+              }
-+      }
-+      return ec;
-+}
-+
-+static inline int echo_can_traintap(echo_can_state_t *ec, int pos, short val)
-+{
-+      /* Reset hang counter to avoid adjustments after
-+         initial forced training */
-+      ec->hcntr = ec->taps << 1;
-+      if (pos >= ec->taps)
-+              return 1;
-+      ec->a_i[pos] = val << 17;
-+      ec->a_s[pos] = val << 1;
-+      if (++pos >= ec->taps)
-+              return 1;
-+      return 0;
-+}
-+
-+
-+#endif
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/mec.h mISDN/drivers/isdn/hardware/mISDN/mec.h
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/mec.h       1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/drivers/isdn/hardware/mISDN/mec.h    2005-12-02 09:57:08.000000000 +0100
-@@ -0,0 +1,308 @@
-+/*
-+ * Mark's Echo Canceller
-+ *
-+ * Mark Spencer <markster@linux-support.net>
-+ *
-+ * Simple, LMS Echo Canceller with double talk detection.  
-+ * Partly based on the TI App note:
-+ *     "Digital Voice Echo Canceller with a TMS 32020"
-+ *
-+ * Special additional thanks to:
-+ *            Jim Dixon         (Lambda Telecommunications)
-+ *            Iman Ghobrial (Adtran, Inc.)
-+ *
-+ * Copyright (C) 2001, Linux Support Services, Inc.
-+ *
-+ * This program is free software and may be used and
-+ * distributed according to the terms of the GNU
-+ * General Public License, incorporated herein by
-+ * reference.
-+ *
-+ */
-+
-+#ifndef _MEC_H
-+#define _MEC_H 
-+
-+/* You have to express the size of the echo canceller in taps as
-+   a power of 2 (6 = 64 taps, 7 = 128 taps, 8 = 256 taps) */
-+#define       NUM_TAPS_POW2   6       /* Size of echo canceller in power of 2 (taps) */
-+#define NUM_TAPS (1 << NUM_TAPS_POW2) /* Actual number of taps */
-+#define TAP_MASK (NUM_TAPS-1)
-+
-+
-+#define SIGMA_LU_POW NUM_TAPS_POW2
-+#define SIGMA_LY_POW NUM_TAPS_POW2
-+#define SIGMA_YT_POW (NUM_TAPS_POW2 - 1)
-+#define SIGMA_ST_POW (NUM_TAPS_POW2 - 1)
-+
-+#define BETA_POW        8
-+
-+#define CUTOFF_S 4
-+
-+/* The higher you make this, the better the quality, but the more CPU time required */
-+#define MIN_QUALITY 100
-+
-+/* This optimization saves a lot of processor but may degrade quality */
-+#define OPTIMIZEDIV
-+
-+#if 0
-+/* This converges much more slowly but saves processor */
-+#define MIN_UPDATE 256
-+#define MIN_SKIP   8
-+#endif
-+
-+#define HANG_T        600                                     /* 600 samples, or 75ms */
-+
-+typedef struct mark_ec {
-+      /* Circular position */
-+      int cpos;
-+      short y[NUM_TAPS];              /* Last N samples (relative to cpos) transmitted */
-+      short y_abs[NUM_TAPS];          /* Last N samples (relative to cpos) transmitted (abs value) */
-+      short s[NUM_TAPS];              /* Last N samples (relative to cpos) received */
-+      short s_abs[NUM_TAPS];          /* Last N samples (relative to cpos) received (abs value) */
-+      short u[NUM_TAPS];              /* Last N samples (relative to cpos) with echo removed */
-+      short u_abs[NUM_TAPS];          /* Last N samples (relative to cpos) with echo removed */
-+      
-+      int Ly;                         /* tx power */
-+      int Lu;                         /* Power of echo-cancelled output */
-+
-+      int Ty[NUM_TAPS];               /* Short term power estimate of transmit */
-+      int Ts;                         /* Short term power estimate of received signal */
-+
-+      int a[NUM_TAPS];                /* Tap weight coefficients (not relative) */
-+      
-+      short sdc[NUM_TAPS];            /* Near end signal before High Pass Filter */
-+
-+      int samples;                    /* Sample count */
-+      int pass;                               /* Number of passes we've made */
-+
-+      int hangt;
-+
-+      int lastmax;                    /* Optimize maximum search */
-+      int maxTy;                      /* Maximum Ty */
-+} echo_can_state_t;
-+
-+#define INLINE inline
-+
-+#ifdef __KERNEL__
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#define MALLOC(a) kmalloc((a), GFP_KERNEL)
-+#define FREE(a) kfree((a))
-+#else
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <stdint.h>
-+#include <string.h>
-+#define MALLOC(a) malloc(a)
-+#define FREE(a) free(a)
-+#endif
-+
-+static INLINE echo_can_state_t *echo_can_create(int len, int adaption_mode)
-+{
-+      echo_can_state_t *ec;
-+      /* Uhm, we're only one length, sorry.  */
-+      ec = MALLOC(sizeof(echo_can_state_t));
-+      if (ec)
-+              memset(ec, 0, sizeof(*ec));
-+      return ec;
-+}
-+
-+#define PASSPOS 32000
-+#undef PASSPOS
-+
-+static INLINE void echo_can_free(echo_can_state_t *ec)
-+{
-+      FREE(ec);
-+}
-+
-+static INLINE int16_t echo_can_update(echo_can_state_t *ec, int16_t tx, int16_t rx)
-+{
-+      /* Process a sample, where tx is the near end and rx is the far end + echo */
-+
-+      int suppr;
-+      int nsuppr;
-+      short rxabs, txabs;
-+      register int Lu;
-+      register int x;
-+      register int pos;
-+      register int r_hat;             /* Estimated echo */
-+      int oldrxabs;
-+      int oldtxabs;
-+      int oldsupprabs;
-+      int supprabs;
-+#ifdef MIN_UPDATE
-+      int totalupd;
-+#endif
-+
-+      txabs = abs(tx);
-+      rxabs = abs(rx);
-+
-+      ec->pass++;
-+
-+      r_hat = 0;
-+
-+      /* Load next value */
-+      ec->y[ec->cpos] = tx;
-+
-+      /* Load next abs value */
-+      oldtxabs = ec->y_abs[ec->cpos];
-+      ec->y_abs[ec->cpos] = txabs;
-+
-+      /* Bring in receive value (near-end signal) */
-+      ec->sdc[ec->cpos] = rx;
-+      
-+      /* Bring in receive value absolute value */
-+      oldrxabs = ec->s_abs[ec->cpos];
-+      ec->s_abs[ec->cpos] = rxabs;
-+
-+      Lu = ec->Lu | 1;
-+
-+#if 0
-+      /* Apply first order high pass filter (3 dB @ 160 Hz) */
-+      tx = ec->s[ec->cpos] = (1.0-DEFGAMMA) * ec->s[(ec->cpos - 1) & TAP_MASK] +
-+                                                      0.5 * (1.0-DEFGAMMA) * ( ec->sdc[(ec->cpos - 1) & TAP_MASK] - ec->sdc[(ec->cpos - 2) & TAP_MASK]);
-+#endif
-+
-+      /* Estimate echo */
-+      pos = ec->cpos;
-+      for (x=0;x<NUM_TAPS;x++) {
-+              r_hat += ec->a[x] * ec->y[pos];
-+              /* Go backwards in time and loop around circular buffer */
-+              pos = (pos - 1) & TAP_MASK;
-+      }
-+      
-+      r_hat >>= 16;
-+      
-+      if (ec->hangt > 0)
-+              ec->hangt--;
-+
-+      /* printf("rx: %F, rhat: %F\n", rx, r_hat); */
-+      /* Calculate suppressed amount */
-+      suppr = rx - r_hat;
-+
-+      if (ec->pass > NUM_TAPS) {
-+              /* Have to have enough taps to start with */
-+              if (ec->maxTy > ec->Ts) {
-+                      /* There is no near-end speech detected */
-+                      if (!ec->hangt) {
-+                              /* We're not in the hang-time from the end of near-end speech */
-+                              if ((ec->Ly > 1024) && ((ec->Ly / Lu) < MIN_QUALITY)) {
-+#ifdef OPTIMIZEDIV
-+                                      /* We both have enough signal on the transmit   */
-+                                      nsuppr = (suppr << 18) / ec->Ly;
-+                              
-+                                      if (nsuppr > 32767)
-+                                              nsuppr = 32767;
-+                                      if (nsuppr < -32768)
-+                                              nsuppr =  -32768;
-+                      
-+                                      nsuppr /= ec->Ly;
-+#else                                 
-+                                      /* We both have enough signal on the transmit   */
-+                                      nsuppr = (suppr << 16) / ec->Ly;
-+                              
-+                                      if (nsuppr > 32767)
-+                                              nsuppr = 32767;
-+                                      if (nsuppr < -32768)
-+                                              nsuppr =  -32768;
-+                      
-+#endif                                        
-+                      
-+                                      /* Update coefficients */
-+                                      pos = ec->cpos;
-+#ifdef MIN_UPDATE
-+                                      totalupd =0;
-+#endif                                        
-+                                      for (x=0;x<NUM_TAPS;x++) {
-+                                              register int adj;
-+                                              adj = ec->y[pos] * nsuppr;
-+#ifndef OPTIMIZEDIV
-+                                              adj /= ec->Ly;
-+                                              adj >>= BETA_POW;
-+#else                                         
-+                                              adj >>= BETA_POW + 2;
-+#endif                                                
-+#ifdef PASSPOS
-+                                              if (ec->pass > PASSPOS)
-+                                                      printf("tx: %d, old %d: %d, adj %d, nsuppr: %d, power: %d\n", tx, x, ec->a[x], adj, nsuppr, ec->Ly);
-+#endif                                                        
-+                                              ec->a[x] += adj;
-+#ifdef MIN_UPDATE
-+                                              totalupd += abs(adj);
-+#endif                                                
-+                                              /* Go backwards in time and loop around circular buffer */
-+                                              pos = (pos - 1) & TAP_MASK;
-+                                      }
-+#ifdef MIN_UPDATE
-+                                      /* If we didn't update at least this much, delay for many more taps */
-+                                      if (totalupd < MIN_UPDATE) {
-+                                              ec->hangt += MIN_SKIP;
-+                                      }
-+#endif                                                
-+                              } 
-+                                      
-+                      }
-+              } else
-+                      /* Near end speech detected */
-+                      ec->hangt = HANG_T;
-+      } 
-+
-+      /* Save supression and absolute values */
-+      supprabs = abs(suppr);
-+      oldsupprabs = ec->u_abs[ec->cpos];
-+      ec->u[ec->cpos] = suppr;
-+      ec->u_abs[ec->cpos] = supprabs;
-+
-+      /* Update tx power */
-+      ec->Ly += (txabs >> SIGMA_LY_POW) - (oldtxabs >> SIGMA_LY_POW);
-+
-+      /* Update rx power */
-+      ec->Lu += (supprabs  >> SIGMA_LU_POW) - (oldsupprabs >> SIGMA_LU_POW);
-+
-+      /* Short term power of tx */
-+      ec->Ty[ec->cpos] = ec->Ty[(ec->cpos - 1) & TAP_MASK] + 
-+              ((txabs >> SIGMA_YT_POW ) - (oldtxabs >> SIGMA_YT_POW));
-+      
-+      /* Keep track of highest */
-+      if (ec->lastmax == ec->cpos) {
-+              register int maxTy = 0;
-+              /* Have to loop through and find the new highest since our old highest expired */
-+              /* Estimate echo */
-+              pos = ec->cpos;
-+              for (x=0;x<NUM_TAPS;x++) {
-+                      if (ec->Ty[pos] > maxTy)
-+                              maxTy = ec->Ty[pos];
-+                      /* Go backwards in time and loop around circular buffer */
-+                      pos = (pos - 1) & TAP_MASK;
-+              }
-+              ec->maxTy = maxTy;
-+      } else {
-+              /* Just keep the highest */
-+              if (ec->Ty[ec->cpos] > ec->maxTy) {
-+                      ec->maxTy = ec->Ty[ec->cpos];
-+                      ec->lastmax = ec->cpos;
-+              }
-+      }
-+      ec->Ts += (rxabs >> SIGMA_ST_POW) - (oldrxabs >> SIGMA_ST_POW) ;
-+
-+      /* Increment position memory */
-+      ec->cpos = (ec->cpos + 1 ) & TAP_MASK;
-+      
-+      return suppr;
-+}
-+
-+static inline int echo_can_traintap(echo_can_state_t *ec, int pos, short val)
-+{
-+      /* Reset hang counter to avoid adjustments after
-+         initial forced training */
-+      ec->hangt = NUM_TAPS << 1;
-+      if (pos >= NUM_TAPS)
-+              return 1;
-+      ec->a[pos] = val << 17;
-+      if (++pos >= NUM_TAPS)
-+              return 1;
-+      return 0;
-+}
-+
-+#endif
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/sedl_fax.c mISDN/drivers/isdn/hardware/mISDN/sedl_fax.c
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/sedl_fax.c  2004-08-27 21:27:40.000000000 +0200
-+++ mISDN/drivers/isdn/hardware/mISDN/sedl_fax.c       2005-12-02 09:57:08.000000000 +0100
-@@ -811,8 +811,8 @@
-               return(err);
-       }
--      printk(KERN_INFO "mISDN: sedlpci found adapter %s at %s\n",
--             (char *) ent->driver_data, pdev->slot_name);
-+/*    printk(KERN_INFO "mISDN: sedlpci found adapter %s at %s\n",
-+             (char *) ent->driver_data, pdev->slot_name); */
-       card->cfg = pci_resource_start(pdev, 0);
-       card->irq = pdev->irq;
-diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/w6692.c mISDN/drivers/isdn/hardware/mISDN/w6692.c
---- /tmp/mISDN/drivers/isdn/hardware/mISDN/w6692.c     2004-08-27 21:27:40.000000000 +0200
-+++ mISDN/drivers/isdn/hardware/mISDN/w6692.c  2005-12-02 09:57:08.000000000 +0100
-@@ -1502,8 +1502,8 @@
-               return(err);
-       }
--      printk(KERN_INFO "mISDN_w6692: found adapter %s at %s\n",
--             (char *) ent->driver_data, pdev->slot_name);
-+/*    printk(KERN_INFO "mISDN_w6692: found adapter %s at %s\n",
-+             (char *) ent->driver_data, pdev->slot_name); */
-       card->addr = pci_resource_start(pdev, 1);
-       card->irq = pdev->irq;
-diff -u -r -P /tmp/mISDN/include/linux/mISDNif.h mISDN/include/linux/mISDNif.h
---- /tmp/mISDN/include/linux/mISDNif.h 2005-02-05 11:18:17.000000000 +0100
-+++ mISDN/include/linux/mISDNif.h      2005-12-02 09:57:08.000000000 +0100
-@@ -173,6 +173,8 @@
- #define BF_DISABLE    0x2315
- #define BF_ACCEPT     0x2316
- #define BF_REJECT     0x2317
-+#define ECHOCAN_ON    0x2318
-+#define ECHOCAN_OFF   0x2319
- #define HW_POTS_ON            0x1001
- #define HW_POTS_OFF           0x1002
- #define HW_POTS_SETMICVOL     0x1100
-diff -u -r -P /tmp/mISDN/Makefile mISDN/Makefile
---- /tmp/mISDN/Makefile        1970-01-01 01:00:00.000000000 +0100
-+++ mISDN/Makefile     2005-12-05 19:08:57.000000000 +0100
-@@ -0,0 +1,54 @@
-+BASEDIR=$(shell pwd)
-+
-+
-+INSTALL_PREFIX := /
-+export INSTALL_PREFIX
-+
-+#PATH to linux source/headers
-+#LINUX=/usr/src/linux
-+LINUX=/lib/modules/$(shell uname -r)/build
-+
-+MISDNDIR=$(BASEDIR)
-+MISDN_SRC=$(MISDNDIR)/drivers/isdn/hardware/mISDN
-+
-+########################################
-+# USER CONFIGS END
-+########################################
-+
-+CONFIGS+=CONFIG_MISDN_DRV=m CONFIG_MISDN_DSP=m 
-+CONFIGS+=CONFIG_MISDN_HFCMULTI=m 
-+CONFIGS+=CONFIG_MISDN_HFCPCI=m
-+CONFIGS+=CONFIG_MISDN_HFCUSB=m
-+#CONFIGS+=CONFIG_MISDN_AVM_FRITZ=m
-+
-+
-+MINCLUDES+=-I$(MISDNDIR)/include
-+
-+all: 
-+      @echo
-+      @echo "Makeing mISDN"
-+      @echo "============="
-+      @echo
-+      cp $(MISDNDIR)/drivers/isdn/hardware/mISDN/Makefile.v2.6 $(MISDNDIR)/drivers/isdn/hardware/mISDN/Makefile
-+
-+      cd $(LINUX) ; make SUBDIRS=$(MISDN_SRC) modules $(CONFIGS) LINUXINCLUDE="$(MINCLUDES) -I$(LINUX)/include"
-+
-+
-+
-+install: all
-+      cd $(LINUX) ; make SUBDIRS=$(MISDN_SRC) modules_install 
-+      cp $(MISDNDIR)/include/linux/*.h $(INSTALL_PREFIX)/usr/include/linux/
-+      depmod
-+
-+.PHONY: install all clean 
-+
-+clean:
-+      rm -rf drivers/isdn/hardware/mISDN/*.o
-+      rm -rf drivers/isdn/hardware/mISDN/*.ko
-+      rm -rf *~
-+      find . -iname ".*.cmd" -exec rm -rf {} \;
-+      find . -iname ".*.d" -exec rm -rf {} \;
-+      find . -iname "*.mod.c" -exec rm -rf {} \;
-+      find . -iname "*.mod" -exec rm -rf {} \;
-+
-+
diff --git a/channels/misdn/portinfo.c b/channels/misdn/portinfo.c
deleted file mode 100644 (file)
index c7add95..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-
-
-#include "isdn_lib.h"
-
-
-/*
- * global function to show all available isdn ports
- */
-void isdn_port_info(void)
-{
-       int err;
-       int i, ii, p;
-       int useable, nt, pri;
-       unsigned char buff[1025];
-       iframe_t *frm = (iframe_t *)buff;
-       stack_info_t *stinf;
-       int device;
-
-       /* open mISDN */
-       if ((device = mISDN_open()) < 0)
-       {
-               fprintf(stderr, "mISDN_open() failed: ret=%d errno=%d (%s) Check for mISDN modules and device.\n", device, errno, strerror(errno));
-               exit(-1);
-       }
-
-       /* get number of stacks */
-       i = 1;
-       ii = mISDN_get_stack_count(device);
-       printf("\n");
-       if (ii <= 0)
-       {
-               printf("Found no card. Please be sure to load card drivers.\n");
-       }
-
-       /* loop the number of cards and get their info */
-       while(i <= ii)
-       {
-               err = mISDN_get_stack_info(device, i, buff, sizeof(buff));
-               if (err <= 0)
-               {
-                       fprintf(stderr, "mISDN_get_stack_info() failed: port=%d err=%d\n", i, err);
-                       break;
-               }
-               stinf = (stack_info_t *)&frm->data.p;
-
-               nt = pri = 0;
-               useable = 1;
-
-               /* output the port info */
-               printf("Port %2d: ", i);
-               switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
-               {
-                       case ISDN_PID_L0_TE_S0:
-                       printf("TE-mode BRI S/T interface line (for phone lines)");
-#if 0
-                       if (stinf->pid.protocol[0] & ISDN_PID_L0_TE_S0_HFC & ISDN_PID_FEATURE_MASK)
-                               printf(" HFC multiport card");
-#endif
-                       break;
-                       case ISDN_PID_L0_NT_S0:
-                       nt = 1;
-                       printf("NT-mode BRI S/T interface port (for phones)");
-#if 0
-                       if (stinf->pid.protocol[0] & ISDN_PID_L0_NT_S0_HFC & ISDN_PID_FEATURE_MASK)
-                               printf(" HFC multiport card");
-#endif
-                       break;
-                       case ISDN_PID_L0_TE_U:
-                       printf("TE-mode BRI U   interface line");
-                       break;
-                       case ISDN_PID_L0_NT_U:
-                       nt = 1;
-                       printf("NT-mode BRI U   interface port");
-                       break;
-                       case ISDN_PID_L0_TE_UP2:
-                       printf("TE-mode BRI Up2 interface line");
-                       break;
-                       case ISDN_PID_L0_NT_UP2:
-                       nt = 1;
-                       printf("NT-mode BRI Up2 interface port");
-                       break;
-                       case ISDN_PID_L0_TE_E1:
-                       pri = 1;
-                       printf("TE-mode PRI E1  interface line (for phone lines)");
-#if 0
-                       if (stinf->pid.protocol[0] & ISDN_PID_L0_TE_E1_HFC & ISDN_PID_FEATURE_MASK)
-                               printf(" HFC-E1 card");
-#endif
-                       break;
-                       case ISDN_PID_L0_NT_E1:
-                       nt = 1;
-                       pri = 1;
-                       printf("NT-mode PRI E1  interface port (for phones)");
-#if 0
-                       if (stinf->pid.protocol[0] & ISDN_PID_L0_NT_E1_HFC & ISDN_PID_FEATURE_MASK)
-                               printf(" HFC-E1 card");
-#endif
-                       break;
-                       default:
-                       useable = 0;
-                       printf("unknown type 0x%08x",stinf->pid.protocol[0]);
-               }
-               printf("\n");
-
-               if (nt)
-               {
-                       if (stinf->pid.protocol[1] == 0)
-                       {
-                               useable = 0;
-                               printf(" -> Missing layer 1 NT-mode protocol.\n");
-                       }
-                       p = 2;
-                       while(p <= MAX_LAYER_NR) {
-                               if (stinf->pid.protocol[p])
-                               {
-                                       useable = 0;
-                                       printf(" -> Layer %d protocol 0x%08x is detected, but not allowed for NT lib.\n", p, stinf->pid.protocol[p]);
-                               }
-                               p++;
-                       }
-                       if (useable)
-                       {
-                               if (pri)
-                                       printf(" -> Interface is Point-To-Point (PRI).\n");
-                               else
-                                       printf(" -> Interface can be Poin-To-Point/Multipoint.\n");
-                       }
-               } else
-               {
-                       if (stinf->pid.protocol[1] == 0)
-                       {
-                               useable = 0;
-                               printf(" -> Missing layer 1 protocol.\n");
-                       }
-                       if (stinf->pid.protocol[2] == 0)
-                       {
-                               useable = 0;
-                               printf(" -> Missing layer 2 protocol.\n");
-                       }
-                       if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP)
-                       {
-                               printf(" -> Interface is Poin-To-Point.\n");
-                       }
-                       if (stinf->pid.protocol[3] == 0)
-                       {
-                               useable = 0;
-                               printf(" -> Missing layer 3 protocol.\n");
-                       } else
-                       {
-                               printf(" -> Protocol: ");
-                               switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
-                               {
-                                       case ISDN_PID_L3_DSS1USER:
-                                       printf("DSS1 (Euro ISDN)");
-                                       break;
-
-                                       default:
-                                       useable = 0;
-                                       printf("unknown protocol 0x%08x",stinf->pid.protocol[3]);
-                               }
-                               printf("\n");
-                       }
-                       p = 4;
-                       while(p <= MAX_LAYER_NR) {
-                               if (stinf->pid.protocol[p])
-                               {
-                                       useable = 0;
-                                       printf(" -> Layer %d protocol 0x%08x is detected, but not allowed for TE lib.\n", p, stinf->pid.protocol[p]);
-                               }
-                               p++;
-                       }
-                       printf(" -> childcnt: %d\n",stinf->childcnt);
-               }
-
-               if (!useable)
-                       printf(" * Port NOT useable for PBX\n");
-
-               printf("--------\n");
-
-               i++;
-       }
-       printf("\n");
-
-       /* close mISDN */
-       if ((err = mISDN_close(device)))
-       {
-               fprintf(stderr, "mISDN_close() failed: err=%d '%s'\n", err, strerror(err));
-               exit(-1);
-       }
-}
-
-
-int main()
-{
-  isdn_port_info();
-  return 0;
-}
diff --git a/channels/misdn_config.c b/channels/misdn_config.c
new file mode 100644 (file)
index 0000000..7c019dc
--- /dev/null
@@ -0,0 +1,784 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ * 
+ * Copyright (C) 2005, Christian Richter
+ *
+ * Christian Richter <crich@beronet.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ *
+ */
+
+/*!
+ * \file
+ *
+ * \brief chan_misdn configuration management
+ * \author Christian Richter <crich@beronet.com>
+ *
+ * \ingroup channel_drivers
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "chan_misdn_config.h"
+
+#include <asterisk/config.h>
+#include <asterisk/channel.h>
+#include <asterisk/logger.h>
+#include <asterisk/lock.h>
+#include <asterisk/pbx.h>
+#include <asterisk/strings.h>
+#include <asterisk/utils.h>
+
+#define AST_LOAD_CFG ast_config_load
+#define AST_DESTROY_CFG ast_config_destroy
+
+#define NO_DEFAULT "<>"
+#define NONE 0
+
+#define GEN_CFG 1
+#define PORT_CFG 2
+#define NUM_GEN_ELEMENTS (sizeof(gen_spec) / sizeof(struct misdn_cfg_spec))
+#define NUM_PORT_ELEMENTS (sizeof(port_spec) / sizeof(struct misdn_cfg_spec))
+
+enum misdn_cfg_type {
+       MISDN_CTYPE_STR,
+       MISDN_CTYPE_INT,
+       MISDN_CTYPE_BOOL,
+       MISDN_CTYPE_BOOLINT,
+       MISDN_CTYPE_MSNLIST,
+       MISDN_CTYPE_ASTGROUP
+};
+
+struct msn_list {
+       char *msn;
+       struct msn_list *next;
+};
+
+union misdn_cfg_pt {
+       char *str;
+       int *num;
+       struct msn_list *ml;
+       ast_group_t *grp;
+       void *any;
+};
+
+struct misdn_cfg_spec {
+       char name[BUFFERSIZE];
+       enum misdn_cfg_elements elem;
+       enum misdn_cfg_type type;
+       char def[BUFFERSIZE];
+       int boolint_def;
+};
+
+static const struct misdn_cfg_spec port_spec[] = {
+       { "name", MISDN_CFG_GROUPNAME, MISDN_CTYPE_STR, "default", NONE },
+       { "allowed_bearers", MISDN_CFG_ALLOWED_BEARERS, MISDN_CTYPE_STR, "all", NONE },
+       { "rxgain", MISDN_CFG_RXGAIN, MISDN_CTYPE_INT, "0", NONE },
+       { "txgain", MISDN_CFG_TXGAIN, MISDN_CTYPE_INT, "0", NONE },
+       { "te_choose_channel", MISDN_CFG_TE_CHOOSE_CHANNEL, MISDN_CTYPE_BOOL, "no", NONE },
+       { "far_alerting", MISDN_CFG_FAR_ALERTING, MISDN_CTYPE_BOOL, "no", NONE },
+       { "pmp_l1_check", MISDN_CFG_PMP_L1_CHECK, MISDN_CTYPE_BOOL, "yes", NONE },
+       { "block_on_alarm", MISDN_CFG_ALARM_BLOCK, MISDN_CTYPE_BOOL, "yes", NONE },
+       { "hdlc", MISDN_CFG_HDLC, MISDN_CTYPE_BOOL, "no", NONE },
+       { "context", MISDN_CFG_CONTEXT, MISDN_CTYPE_STR, "default", NONE },
+       { "language", MISDN_CFG_LANGUAGE, MISDN_CTYPE_STR, "en", NONE },
+       { "musicclass", MISDN_CFG_MUSICCLASS, MISDN_CTYPE_STR, "default", NONE },
+       { "callerid", MISDN_CFG_CALLERID, MISDN_CTYPE_STR, "", NONE },
+       { "method", MISDN_CFG_METHOD, MISDN_CTYPE_STR, "standard", NONE },
+       { "dialplan", MISDN_CFG_DIALPLAN, MISDN_CTYPE_INT, "0", NONE },
+       { "localdialplan", MISDN_CFG_LOCALDIALPLAN, MISDN_CTYPE_INT, "0", NONE },
+       { "cpndialplan", MISDN_CFG_CPNDIALPLAN, MISDN_CTYPE_INT, "0", NONE },
+       { "nationalprefix", MISDN_CFG_NATPREFIX, MISDN_CTYPE_STR, "0", NONE },
+       { "internationalprefix", MISDN_CFG_INTERNATPREFIX, MISDN_CTYPE_STR, "00", NONE },
+       { "presentation", MISDN_CFG_PRES, MISDN_CTYPE_INT, "-1", NONE },
+       { "screen", MISDN_CFG_SCREEN, MISDN_CTYPE_INT, "-1", NONE },
+       { "always_immediate", MISDN_CFG_ALWAYS_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE },
+       { "nodialtone", MISDN_CFG_NODIALTONE, MISDN_CTYPE_BOOL, "no", NONE },
+       { "immediate", MISDN_CFG_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE },
+       { "senddtmf", MISDN_CFG_SENDDTMF, MISDN_CTYPE_BOOL, "no", NONE },
+       { "hold_allowed", MISDN_CFG_HOLD_ALLOWED, MISDN_CTYPE_BOOL, "no", NONE },
+       { "early_bconnect", MISDN_CFG_EARLY_BCONNECT, MISDN_CTYPE_BOOL, "yes", NONE },
+       { "incoming_early_audio", MISDN_CFG_INCOMING_EARLY_AUDIO, MISDN_CTYPE_BOOL, "no", NONE },
+       { "echocancel", MISDN_CFG_ECHOCANCEL, MISDN_CTYPE_BOOLINT, "0", 128 },
+       { "need_more_infos", MISDN_CFG_NEED_MORE_INFOS, MISDN_CTYPE_BOOL, "0", NONE },
+       { "jitterbuffer", MISDN_CFG_JITTERBUFFER, MISDN_CTYPE_INT, "4000", NONE },
+       { "jitterbuffer_upper_threshold", MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, MISDN_CTYPE_INT, "0", NONE },
+       { "callgroup", MISDN_CFG_CALLGROUP, MISDN_CTYPE_ASTGROUP, NO_DEFAULT, NONE },
+       { "pickupgroup", MISDN_CFG_PICKUPGROUP, MISDN_CTYPE_ASTGROUP, NO_DEFAULT, NONE },
+       { "msns", MISDN_CFG_MSNS, MISDN_CTYPE_MSNLIST, NO_DEFAULT, NONE }
+};
+
+static const struct misdn_cfg_spec gen_spec[] = {
+       { "debug", MISDN_GEN_DEBUG, MISDN_CTYPE_INT, "0", NONE },
+       { "misdn_init", MISDN_GEN_MISDN_INIT, MISDN_CTYPE_STR, "/etc/misdn-init.conf", NONE },
+       { "tracefile", MISDN_GEN_TRACEFILE, MISDN_CTYPE_STR, "/var/log/asterisk/misdn.log", NONE },
+       { "bridging", MISDN_GEN_BRIDGING, MISDN_CTYPE_BOOL, "yes", NONE },
+       { "stop_tone_after_first_digit", MISDN_GEN_STOP_TONE, MISDN_CTYPE_BOOL, "yes", NONE },
+       { "append_digits2exten", MISDN_GEN_APPEND_DIGITS2EXTEN, MISDN_CTYPE_BOOL, "yes", NONE },
+       { "dynamic_crypt", MISDN_GEN_DYNAMIC_CRYPT, MISDN_CTYPE_BOOL, "no", NONE },
+       { "crypt_prefix", MISDN_GEN_CRYPT_PREFIX, MISDN_CTYPE_STR, NO_DEFAULT, NONE },
+       { "crypt_keys", MISDN_GEN_CRYPT_KEYS, MISDN_CTYPE_STR, NO_DEFAULT, NONE },
+       { "ntdebugflags", MISDN_GEN_NTDEBUGFLAGS, MISDN_CTYPE_INT, "0", NONE },
+       { "ntdebugfile", MISDN_GEN_NTDEBUGFILE, MISDN_CTYPE_STR, "/var/log/misdn-nt.log", NONE }
+};
+
+/* array of port configs, default is at position 0. */
+static union misdn_cfg_pt **port_cfg;
+/* max number of available ports, is set on init */
+static int max_ports;
+/* general config */
+static union misdn_cfg_pt *general_cfg;
+/* storing the ptp flag separated to save memory */
+static int *ptp;
+/* maps enum config elements to array positions */
+static int *map;
+
+static ast_mutex_t config_mutex; 
+
+#define CLI_ERROR(name, value, section) ({ \
+       ast_log(LOG_WARNING, "misdn.conf: \"%s=%s\" (section: %s) invalid or out of range. " \
+               "Please edit your misdn.conf and then do a \"misdn reload\".\n", name, value, section); \
+})
+
+static void _enum_array_map (void)
+{
+       int i, j;
+
+       for (i = MISDN_CFG_FIRST + 1; i < MISDN_CFG_LAST; ++i) {
+               if (i == MISDN_CFG_PTP)
+                       continue;
+               for (j = 0; j < NUM_PORT_ELEMENTS; ++j) {
+                       if (port_spec[j].elem == i) {
+                               map[i] = j;
+                               break;
+                       }
+               }
+       }
+       for (i = MISDN_GEN_FIRST + 1; i < MISDN_GEN_LAST; ++i) {
+               for (j = 0; j < NUM_GEN_ELEMENTS; ++j) {
+                       if (gen_spec[j].elem == i) {
+                               map[i] = j;
+                               break;
+                       }
+               }
+       }
+}
+
+static int get_cfg_position (char *name, int type)
+{
+       int i;
+
+       switch (type) {
+       case PORT_CFG:
+               for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
+                       if (!strcasecmp(name, port_spec[i].name))
+                               return i;
+               }
+               break;
+       case GEN_CFG:
+               for (i = 0; i < NUM_GEN_ELEMENTS; ++i) {
+                       if (!strcasecmp(name, gen_spec[i].name))
+                               return i;
+               }
+       }
+
+       return -1;
+}
+
+static inline void misdn_cfg_lock (void)
+{
+       ast_mutex_lock(&config_mutex);
+}
+
+static inline void misdn_cfg_unlock (void)
+{
+       ast_mutex_unlock(&config_mutex);
+}
+
+static void _free_msn_list (struct msn_list* iter)
+{
+       if (iter->next)
+               _free_msn_list(iter->next);
+       if (iter->msn)
+               free(iter->msn);
+       free(iter);
+}
+
+static void _free_port_cfg (void)
+{
+       int i, j;
+       int gn = map[MISDN_CFG_GROUPNAME];
+       union misdn_cfg_pt* free_list[max_ports + 2];
+       
+       memset(free_list, 0, sizeof(free_list));
+       free_list[0] = port_cfg[0];
+       for (i = 1; i <= max_ports; ++i) {
+               if (port_cfg[i][gn].str) {
+                       /* we always have a groupname in the non-default case, so this is fine */
+                       for (j = 1; j <= max_ports; ++j) {
+                               if (free_list[j] && free_list[j][gn].str == port_cfg[i][gn].str)
+                                       break;
+                               else if (!free_list[j]) {
+                                       free_list[j] = port_cfg[i];
+                                       break;
+                               }
+                       }
+               }
+       }
+       for (j = 0; free_list[j]; ++j) {
+               for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
+                       if (free_list[j][i].any) {
+                               if (port_spec[i].type == MISDN_CTYPE_MSNLIST)
+                                       _free_msn_list(free_list[j][i].ml);
+                               else
+                                       free(free_list[j][i].any);
+                       }
+               }
+       }
+}
+
+static void _free_general_cfg (void)
+{
+       int i;
+
+       for (i = 0; i < NUM_GEN_ELEMENTS; i++) 
+               if (general_cfg[i].any)
+                       free(general_cfg[i].any);
+}
+
+void misdn_cfg_get (int port, enum misdn_cfg_elements elem, void *buf, int bufsize)
+{
+       int place;
+
+       if ((elem < MISDN_CFG_LAST) && !misdn_cfg_is_port_valid(port)) {
+               memset(buf, 0, bufsize);
+               ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Port number %d is not valid.\n", port);
+               return;
+       }
+
+       misdn_cfg_lock();
+       if (elem == MISDN_CFG_PTP) {
+               if (!memcpy(buf, &ptp[port], (bufsize > ptp[port]) ? sizeof(ptp[port]) : bufsize))
+                       memset(buf, 0, bufsize);
+       } else {
+               if ((place = map[elem]) < 0) {
+                       memset (buf, 0, bufsize);
+                       ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Invalid element (%d) requested.\n", elem);
+               } else {
+                       if (elem < MISDN_CFG_LAST) {
+                               switch (port_spec[place].type) {
+                               case MISDN_CTYPE_STR:
+                                       if (port_cfg[port][place].str) {
+                                               if (!memccpy(buf, port_cfg[port][place].str, 0, bufsize))
+                                                       memset(buf, 0, 1);
+                                       } else if (port_cfg[0][place].str) {
+                                               if (!memccpy(buf, port_cfg[0][place].str, 0, bufsize))
+                                                       memset(buf, 0, 1);
+                                       }
+                                       break;
+                               default:
+                                       if (port_cfg[port][place].any)
+                                               memcpy(buf, port_cfg[port][place].any, bufsize);
+                                       else if (port_cfg[0][place].any)
+                                               memcpy(buf, port_cfg[0][place].any, bufsize);
+                                       else
+                                               memset(buf, 0, bufsize);
+                               }
+                       } else {
+                               switch (gen_spec[place].type) {
+                               case MISDN_CTYPE_STR:
+                                       if (!general_cfg[place].str || !memccpy(buf, general_cfg[place].str, 0, bufsize))
+                                               memset(buf, 0, 1);
+                                       break;
+                               default:
+                                       if (general_cfg[place].any)
+                                               memcpy(buf, general_cfg[place].any, bufsize);
+                                       else
+                                               memset(buf, 0, bufsize);
+                               }
+                       }
+               }
+       }
+       misdn_cfg_unlock();
+}
+
+int misdn_cfg_is_msn_valid (int port, char* msn)
+{
+       int re = 0;
+       struct msn_list *iter;
+
+       if (!misdn_cfg_is_port_valid(port)) {
+               ast_log(LOG_WARNING, "Invalid call to misdn_cfg_is_msn_valid! Port number %d is not valid.\n", port);
+               return 0;
+       }
+
+       misdn_cfg_lock();
+       if (port_cfg[port][map[MISDN_CFG_MSNS]].ml)
+               iter = port_cfg[port][map[MISDN_CFG_MSNS]].ml;
+       else
+               iter = port_cfg[0][map[MISDN_CFG_MSNS]].ml;
+       for (; iter; iter = iter->next) 
+               if (*(iter->msn) == '*' || ast_extension_match(iter->msn, msn)) {
+                       re = 1;
+                       break;
+               }
+       misdn_cfg_unlock();
+
+       return re;
+}
+
+int misdn_cfg_is_port_valid (int port)
+{
+       return (port >= 1 && port <= max_ports);
+}
+
+int misdn_cfg_is_group_method (char *group, enum misdn_cfg_method meth)
+{
+       int i, re = 0;
+       char *method = NULL;
+
+       misdn_cfg_lock();
+       for (i = 1; i <= max_ports; i++) {
+               if (port_cfg[i] && port_cfg[i][map[MISDN_CFG_GROUPNAME]].str) {
+                       if (!strcasecmp(port_cfg[i][map[MISDN_CFG_GROUPNAME]].str, group))
+                               method = (port_cfg[i][map[MISDN_CFG_METHOD]].str ? 
+                                                 port_cfg[i][map[MISDN_CFG_METHOD]].str : port_cfg[0][map[MISDN_CFG_METHOD]].str);
+               }
+       }
+       if (method) {
+               switch (meth) {
+               case METHOD_STANDARD:           re = !strcasecmp(method, "standard");
+                                                                       break;
+               case METHOD_ROUND_ROBIN:        re = !strcasecmp(method, "round_robin");
+                                                                       break;
+               }
+       }
+       misdn_cfg_unlock();
+
+       return re;
+}
+
+void misdn_cfg_get_ports_string (char *ports)
+{
+       char tmp[16];
+       int l, i;
+       int gn = map[MISDN_CFG_GROUPNAME];
+
+       *ports = 0;
+
+       misdn_cfg_lock();
+       for (i = 1; i <= max_ports; i++) {
+               if (port_cfg[i][gn].str) {
+                       if (ptp[i])
+                               sprintf(tmp, "%dptp,", i);
+                       else
+                               sprintf(tmp, "%d,", i);
+                       strcat(ports, tmp);
+               }
+       }
+       misdn_cfg_unlock();
+
+       if ((l = strlen(ports)))
+               ports[l-1] = 0;
+}
+
+void misdn_cfg_get_config_string (int port, enum misdn_cfg_elements elem, char* buf, int bufsize)
+{
+       int place;
+       char tempbuf[BUFFERSIZE] = "";
+       struct msn_list *iter;
+
+       if ((elem < MISDN_CFG_LAST) && !misdn_cfg_is_port_valid(port)) {
+               *buf = 0;
+               ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Port number %d is not valid.\n", port);
+               return;
+       }
+
+       place = map[elem];
+
+       misdn_cfg_lock();
+       if (elem == MISDN_CFG_PTP) {
+               snprintf(buf, bufsize, " -> ptp: %s", ptp[port] ? "yes" : "no");
+       }
+       else if (elem > MISDN_CFG_FIRST && elem < MISDN_CFG_LAST) {
+               switch (port_spec[place].type) {
+               case MISDN_CTYPE_INT:
+               case MISDN_CTYPE_BOOLINT:
+                       if (port_cfg[port][place].num)
+                               snprintf(buf, bufsize, " -> %s: %d", port_spec[place].name, *port_cfg[port][place].num);
+                       else if (port_cfg[0][place].num)
+                               snprintf(buf, bufsize, " -> %s: %d", port_spec[place].name, *port_cfg[0][place].num);
+                       else
+                               snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
+                       break;
+               case MISDN_CTYPE_BOOL:
+                       if (port_cfg[port][place].num)
+                               snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, *port_cfg[port][place].num ? "yes" : "no");
+                       else if (port_cfg[0][place].num)
+                               snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, *port_cfg[0][place].num ? "yes" : "no");
+                       else
+                               snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
+                       break;
+               case MISDN_CTYPE_ASTGROUP:
+                       if (port_cfg[port][place].grp)
+                               snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, 
+                                                ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[port][place].grp));
+                       else if (port_cfg[0][place].grp)
+                               snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, 
+                                                ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[0][place].grp));
+                       else
+                               snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
+                       break;
+               case MISDN_CTYPE_MSNLIST:
+                       if (port_cfg[port][place].ml)
+                               iter = port_cfg[port][place].ml;
+                       else
+                               iter = port_cfg[0][place].ml;
+                       if (iter) {
+                               for (; iter; iter = iter->next)
+                                       sprintf(tempbuf, "%s%s, ", tempbuf, iter->msn);
+                               tempbuf[strlen(tempbuf)-2] = 0;
+                       }
+                       snprintf(buf, bufsize, " -> msns: %s", *tempbuf ? tempbuf : "none");
+                       break;
+               case MISDN_CTYPE_STR:
+                       if ( port_cfg[port][place].str) {
+                               snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, port_cfg[port][place].str);
+                       } else if (port_cfg[0][place].str) {
+                               snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, port_cfg[0][place].str);
+                       } else {
+                               snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
+                       }
+                       break;
+               }
+       } else if (elem > MISDN_GEN_FIRST && elem < MISDN_GEN_LAST) {
+               switch (gen_spec[place].type) {
+               case MISDN_CTYPE_INT:
+               case MISDN_CTYPE_BOOLINT:
+                       if (general_cfg[place].num)
+                               snprintf(buf, bufsize, " -> %s: %d", gen_spec[place].name, *general_cfg[place].num);
+                       else
+                               snprintf(buf, bufsize, " -> %s:", gen_spec[place].name);
+                       break;
+               case MISDN_CTYPE_BOOL:
+                       if (general_cfg[place].num)
+                               snprintf(buf, bufsize, " -> %s: %s", gen_spec[place].name, *general_cfg[place].num ? "yes" : "no");
+                       else
+                               snprintf(buf, bufsize, " -> %s:", gen_spec[place].name);
+                       break;
+               case MISDN_CTYPE_STR:
+                       if ( general_cfg[place].str) {
+                               snprintf(buf, bufsize, " -> %s: %s", gen_spec[place].name, general_cfg[place].str);
+                       } else {
+                               snprintf(buf, bufsize, " -> %s:", gen_spec[place].name);
+                       }
+                       break;
+               default:
+                       snprintf(buf, bufsize, " -> type of %s not handled yet", gen_spec[place].name);
+                       break;
+               }
+       } else {
+               *buf = 0;
+               ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Invalid config element (%d) requested.\n", elem);
+       }
+       misdn_cfg_unlock();
+}
+
+int misdn_cfg_get_next_port (int port)
+{
+       int p = -1;
+       int gn = map[MISDN_CFG_GROUPNAME];
+       
+       misdn_cfg_lock();
+       for (port++; port <= max_ports; port++) {
+               if (port_cfg[port][gn].str) {
+                       p = port;
+                       break;
+               }
+       }
+       misdn_cfg_unlock();
+
+       return p;
+}
+
+int misdn_cfg_get_next_port_spin (int port)
+{
+       int p = misdn_cfg_get_next_port(port);
+       return (p > 0) ? p : misdn_cfg_get_next_port(0);
+}
+
+static int _parse (union misdn_cfg_pt *dest, char *value, enum misdn_cfg_type type, int boolint_def)
+{
+       int re = 0;
+       int len, tmp;
+       char *valtmp;
+
+       switch (type) {
+       case MISDN_CTYPE_STR:
+               if ((len = strlen(value))) {
+                       dest->str = (char *)malloc((len + 1) * sizeof(char));
+                       strncpy(dest->str, value, len);
+                       dest->str[len] = 0;
+               } else {
+                       dest->str = (char *)malloc( sizeof(char));
+                       dest->str[0] = 0;
+               }
+               break;
+       case MISDN_CTYPE_INT:
+       {
+               char *pat;
+               if (strchr(value,'x')) 
+                       pat="%x";
+               else
+                       pat="%d";
+               if (sscanf(value, pat, &tmp)) {
+                       dest->num = (int *)malloc(sizeof(int));
+                       memcpy(dest->num, &tmp, sizeof(int));
+               } else
+                       re = -1;
+       }
+               break;
+       case MISDN_CTYPE_BOOL:
+               dest->num = (int *)malloc(sizeof(int));
+               *(dest->num) = (ast_true(value) ? 1 : 0);
+               break;
+       case MISDN_CTYPE_BOOLINT:
+               dest->num = (int *)malloc(sizeof(int));
+               if (sscanf(value, "%d", &tmp)) {
+                       memcpy(dest->num, &tmp, sizeof(int));
+               } else {
+                       *(dest->num) = (ast_true(value) ? boolint_def : 0);
+               }
+               break;
+       case MISDN_CTYPE_MSNLIST:
+               for (valtmp = strsep(&value, ","); valtmp; valtmp = strsep(&value, ",")) {
+                       if ((len = strlen(valtmp))) {
+                               struct msn_list *ml = (struct msn_list *)malloc(sizeof(struct msn_list));
+                               ml->msn = (char *)calloc(len+1, sizeof(char));
+                               strncpy(ml->msn, valtmp, len);
+                               ml->next = dest->ml;
+                               dest->ml = ml;
+                       }
+               }
+               break;
+       case MISDN_CTYPE_ASTGROUP:
+               dest->grp = (ast_group_t *)malloc(sizeof(ast_group_t));
+               *(dest->grp) = ast_get_group(value);
+               break;
+       }
+
+       return re;
+}
+
+static void _build_general_config (struct ast_variable *v)
+{
+       int pos;
+
+       for (; v; v = v->next) {
+               if (((pos = get_cfg_position(v->name, GEN_CFG)) < 0) || 
+                       (_parse(&general_cfg[pos], v->value, gen_spec[pos].type, gen_spec[pos].boolint_def) < 0))
+                       CLI_ERROR(v->name, v->value, "general");
+       }
+}
+
+static void _build_port_config (struct ast_variable *v, char *cat)
+{
+       int pos, i;
+       union misdn_cfg_pt cfg_tmp[NUM_PORT_ELEMENTS];
+       int cfg_for_ports[max_ports + 1];
+
+       if (!v || !cat)
+               return;
+
+       memset(cfg_tmp, 0, sizeof(cfg_tmp));
+       memset(cfg_for_ports, 0, sizeof(cfg_for_ports));
+
+       if (!strcasecmp(cat, "default")) {
+               cfg_for_ports[0] = 1;
+       }
+
+       if (((pos = get_cfg_position("name", PORT_CFG)) < 0) || 
+               (_parse(&cfg_tmp[pos], cat, port_spec[pos].type, port_spec[pos].boolint_def) < 0)) {
+               CLI_ERROR(v->name, v->value, cat);
+               return;
+       }
+
+       for (; v; v = v->next) {
+               if (!strcasecmp(v->name, "ports")) {
+                       char *token;
+                       char ptpbuf[BUFFERSIZE] = "";
+                       int start, end;
+                       for (token = strsep(&v->value, ","); token; token = strsep(&v->value, ","), *ptpbuf = 0) { 
+                               if (!*token)
+                                       continue;
+                               if (sscanf(token, "%d-%d%s", &start, &end, ptpbuf) >= 2) {
+                                       for (; start <= end; start++) {
+                                               if (start <= max_ports && start > 0) {
+                                                       cfg_for_ports[start] = 1;
+                                                       ptp[start] = (strstr(ptpbuf, "ptp")) ? 1 : 0;
+                                               } else
+                                                       CLI_ERROR(v->name, v->value, cat);
+                                       }
+                               } else {
+                                       if (sscanf(token, "%d%s", &start, ptpbuf)) {
+                                               if (start <= max_ports && start > 0) {
+                                                       cfg_for_ports[start] = 1;
+                                                       ptp[start] = (strstr(ptpbuf, "ptp")) ? 1 : 0;
+                                               } else
+                                                       CLI_ERROR(v->name, v->value, cat);
+                                       } else
+                                               CLI_ERROR(v->name, v->value, cat);
+                               }
+                       }
+               } else {
+                       if (((pos = get_cfg_position(v->name, PORT_CFG)) < 0) || 
+                               (_parse(&cfg_tmp[pos], v->value, port_spec[pos].type, port_spec[pos].boolint_def) < 0))
+                               CLI_ERROR(v->name, v->value, cat);
+               }
+       }
+
+       for (i = 0; i < (max_ports + 1); ++i) {
+               if (cfg_for_ports[i]) {
+                       memcpy(port_cfg[i], cfg_tmp, sizeof(cfg_tmp));
+               }
+       }
+}
+
+void misdn_cfg_update_ptp (void)
+{
+       char misdn_init[BUFFERSIZE];
+       char line[BUFFERSIZE];
+       FILE *fp;
+       char *tok, *p, *end;
+       int port;
+
+       misdn_cfg_get(0, MISDN_GEN_MISDN_INIT, &misdn_init, sizeof(misdn_init));
+
+       if (misdn_init) {
+               fp = fopen(misdn_init, "r");
+               if (fp) {
+                       while(fgets(line, sizeof(line), fp)) {
+                               if (!strncmp(line, "nt_ptp", 6)) {
+                                       for (tok = strtok_r(line,",=", &p);
+                                                tok;
+                                                tok = strtok_r(NULL,",=", &p)) {
+                                               port = strtol(tok, &end, 10);
+                                               if (end != tok && misdn_cfg_is_port_valid(port)) {
+                                                       misdn_cfg_lock();
+                                                       ptp[port] = 1;
+                                                       misdn_cfg_unlock();
+                                               }
+                                       }
+                               }
+                       }
+                       fclose(fp);
+               } else {
+                       ast_log(LOG_WARNING,"Couldn't open %s: %s\n", misdn_init, strerror(errno));
+               }
+       }
+}
+
+static void _fill_defaults (void)
+{
+       int i;
+
+       for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
+               if (!port_cfg[0][i].any && strcasecmp(port_spec[i].def, NO_DEFAULT))
+                       _parse(&(port_cfg[0][i]), (char *)port_spec[i].def, port_spec[i].type, port_spec[i].boolint_def);
+       }
+       for (i = 0; i < NUM_GEN_ELEMENTS; ++i) {
+               if (!general_cfg[i].any && strcasecmp(gen_spec[i].def, NO_DEFAULT))
+                       _parse(&(general_cfg[i]), (char *)gen_spec[i].def, gen_spec[i].type, gen_spec[i].boolint_def);
+       }
+}
+
+void misdn_cfg_reload (void)
+{
+       misdn_cfg_init (0);
+}
+
+void misdn_cfg_destroy (void)
+{
+       misdn_cfg_lock();
+
+       _free_port_cfg();
+       _free_general_cfg();
+
+       free(port_cfg);
+       free(general_cfg);
+       free(ptp);
+       free(map);
+
+       misdn_cfg_unlock();
+       ast_mutex_destroy(&config_mutex);
+}
+
+void misdn_cfg_init (int this_max_ports)
+{
+       char config[] = "misdn.conf";
+       char *cat, *p;
+       int i;
+       struct ast_config *cfg;
+       struct ast_variable *v;
+
+       if (!(cfg = AST_LOAD_CFG(config))) {
+               ast_log(LOG_WARNING,"no misdn.conf ?\n");
+               return;
+       }
+
+       misdn_cfg_lock();
+
+       if (this_max_ports) {
+               /* this is the first run */
+               max_ports = this_max_ports;
+               p = (char *)calloc(1, (max_ports + 1) * sizeof(union misdn_cfg_pt *)
+                                                  + (max_ports + 1) * NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt));
+               port_cfg = (union misdn_cfg_pt **)p;
+               p += (max_ports + 1) * sizeof(union misdn_cfg_pt *);
+               for (i = 0; i <= max_ports; ++i) {
+                       port_cfg[i] = (union misdn_cfg_pt *)p;
+                       p += NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt);
+               }
+               general_cfg = (union misdn_cfg_pt *)calloc(1, sizeof(union misdn_cfg_pt *) * NUM_GEN_ELEMENTS);
+               ptp = (int *)calloc(max_ports + 1, sizeof(int));
+               map = (int *)calloc(MISDN_GEN_LAST + 1, sizeof(int));
+               _enum_array_map();
+       }
+       else {
+               /* misdn reload */
+               _free_port_cfg();
+               _free_general_cfg();
+               memset(port_cfg[0], 0, NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt) * (max_ports + 1));
+               memset(general_cfg, 0, sizeof(union misdn_cfg_pt *) * NUM_GEN_ELEMENTS);
+               memset(ptp, 0, sizeof(int) * (max_ports + 1));
+       }
+
+       cat = ast_category_browse(cfg, NULL);
+
+       while(cat) {
+               v = ast_variable_browse(cfg, cat);
+               if (!strcasecmp(cat,"general")) {
+                       _build_general_config(v);
+               } else {
+                       _build_port_config(v, cat);
+               }
+               cat = ast_category_browse(cfg,cat);
+       }
+
+       _fill_defaults();
+
+       misdn_cfg_unlock();
+       AST_DESTROY_CFG(cfg);
+}
index 8957e2fa62438c1e174d5ba635a06596fce2f297..a5840e37fcaa0f589e9acd39d990fe7bafc8b964 100644 (file)
@@ -8,6 +8,10 @@
 ;
 
 [general] 
+;
+; Sets the Path to the misdn-init.conf (for nt_ptp mode checking)
+;
+misdn_init=/etc/misdn-init.conf
 
 ; set debugging flag: 
 ;   0 - No Debug
 ;
 debug=0
 
+
+
+; set debugging file and flags for mISDNuser (NT-Stack) 
+; 
+; flags can be or'ed with the following values:
+;
+; DBGM_NET        0x00000001
+; DBGM_MSG        0x00000002
+; DBGM_FSM        0x00000004
+; DBGM_TEI        0x00000010
+; DBGM_L2         0x00000020
+; DBGM_L3         0x00000040
+; DBGM_L3DATA     0x00000080
+; DBGM_BC         0x00000100
+; DBGM_TONE       0x00000200
+; DBGM_BCDATA     0x00000400
+; DBGM_MAN        0x00001000
+; DBGM_APPL       0x00002000
+; DBGM_ISDN       0x00004000
+; DBGM_SOCK       0x00010000
+; DBGM_CONN       0x00020000
+; DBGM_CDATA      0x00040000
+; DBGM_DDATA      0x00080000
+; DBGM_SOUND      0x00100000
+; DBGM_SDATA      0x00200000
+; DBGM_TOPLEVEL   0x40000000
+; DBGM_ALL        0xffffffff
+;
+
+ntdebugflags=0
+ntdebugfile=/var/log/misdn-nt.log
+
 ; the big trace
 ;
 ; default value: [not set]
 ;
-;tracefile=/var/log/misdn.trace
-
-; single call trace files
-; set to true if you want to have them
-; they depend on debug level
-;
-; default values: trace_calls : false
-;                 trace_dir   : /var/log/
-;
-trace_calls=false
-trace_dir=/var/log/
+;tracefile=/var/log/asterisk/misdn.log
 
 ; set to yes if you want mISDN_dsp to bridge the calls in HW
 ;
 ; default value: yes
 ;
-bridging=yes
+bridging=no
 
 ; stops dialtone after getting first digit on nt Port
 ;
@@ -54,29 +80,6 @@ stop_tone_after_first_digit=yes
 ;
 append_digits2exten=yes
 
-; set this to yes if you have jollys mISDN which sends correct L1 Infos
-;
-; default value: yes
-;
-l1_info_ok=yes
-
-; set this to yes if you want to clear the l3 in case the l2 deactivates
-; some environments have a flickering l2 which causes this option to 
-; damage active calls .. highly experimental
-; 
-; default value: no
-;
-clear_l3=no
-
-; set the method to use for channel selection:
-;   standard    - always choose the first free channel with the lowest number
-;   round_robin - use the round robin algorithm to select a channel. use this
-;                 if you want to balance your load.
-;
-; default value: standard
-;
-method=standard
-
 ;;; CRYPTION STUFF
 
 ; Wether to look for dynamic crypting attempt
@@ -125,6 +128,27 @@ context=misdn
 ;
 language=en
 
+;
+; sets the musiconhold class
+;
+musicclass=default
+
+;
+; Either if we should produce DTMF Tones ourselve
+; 
+senddtmf=yes
+
+;
+; If we should generate Ringing for chan_sip and others
+;
+far_alerting=no
+
+
+;
+; here you can define which bearers should be allowed
+;
+allowed_bearers=all
+
 ; Prefixes for national and international, those are put before the 
 ; oad if an according dialplan is set by the other end. 
 ;
@@ -149,11 +173,52 @@ txgain=0
 ;
 te_choose_channel=no
 
+
+
+;
+; This option defines, if chan_misdn should check the L1 on  a PMP 
+; before makeing a group call on it. The L1 may go down for PMP Ports
+; so we might need this.
+; But be aware! a broken or plugged off cable might be used for a group call
+; as well, since chan_misdn has no chance to distinguish if the L1 is down
+; because of a lost Link or because the Provider shut it down...
+;
+; default: yes
+;
+pmp_l1_check=yes
+
+;
+; Send Setup_Acknowledge on incoming calls anyway (instead of PROCEEDING), 
+; this requests additional Infos, so we can waitfordigits 
+; without much issues. This works only for PTP Ports
+; 
+; default value: no
+;
+need_more_infos=no
+
+; set the method to use for channel selection:
+;   standard    - always choose the first free channel with the lowest number
+;   round_robin - use the round robin algorithm to select a channel. use this
+;                 if you want to balance your load.
+;
+; default value: standard
+;
+method=standard
+
+;
+; dialplan means Type Of Number in ISDN Terms (for outgoing calls)
+;
+; there are different types of the dialplan:
+;
+; dialplan -> outgoing Number
+; localdialplan -> callerid
+; cpndialplan -> connected party number
+;
 ; dialplan options: 
 ;
 ; 0 - unknown
-; 1 - National
-; 2 - International
+; 1 - International
+; 2 - National
 ; 4 - Subscriber
 ;
 ; This setting is used for outgoing calls
@@ -161,14 +226,26 @@ te_choose_channel=no
 ; default value: 0
 ;
 dialplan=0
+localdialplan=0
+cpndialplan=0
+
+
 
-; This is only for asterisk head and will result in only considering 
-; misdn.confs and misdn_set_opts callingpresentation informations if set to no.
-; Otherwise asterisks callingpresentation overwrites misdn.confs settings.
 ;
-; default value: yes
+; turn this to no if you don't mind correct handling of Progress Indicators  
 ;
-use_callingpres=yes
+early_bconnect=yes
+
+
+;
+; turn this on if you like to send Tone Indications to a Incoming
+; isdn channel on a TE Port. Rarely used, only if the Telco allows
+; you to send indications by yourself, normally the Telco sends the 
+; indications to the remote party.
+; 
+; default: no
+;
+incoming_early_audio=no
 
 ; uncomment the following to get into s extension at extension conf
 ; there you can use DigitTimeout if you can't or don't want to use
@@ -179,6 +256,15 @@ use_callingpres=yes
 ;
 ;always_immediate=no
 
+;
+; set this to yes if you want to generate your own dialtone 
+; with always_immediate=yes, else chan_misdn generates the dialtone
+;
+; default value: no
+;
+nodialtone=no
+
+
 ; uncomment the following if you want callers which called exactly the 
 ; base number (so no extension is set) jump to the s extension.
 ; if the user dials something more it jumps to the correct extension 
@@ -201,17 +287,17 @@ use_callingpres=yes
 ;callgroup=1
 ;pickupgroup=1
 
-; Allows/Screens Callerid
-;
-; possible values: allowed,not_screened
-;
-; be aware, if you set to allowed you need to set a correct 
-; callerid in the dialplan or set it here in the misdn.conf
-; Some Telcos don't care about wrong callerids, others do !
-;
-; default value: allowed
+
 ;
-;presentation=not_screened
+; these are the exact isdn screening and presentation indicators
+; if -1 is given for both values the presentation indicators are used
+; from asterisks SetCallerPres application.
+; s=0, p=0 -> callerid presented not screened
+; s=1, p=1 -> callerid presented but screened (the remote end does not see it!)
+; 
+; defaule values s=-1, p=-1
+presentation=-1
+screen=-1
 
 ; this enables echocancellation, with the given number of taps
 ; be aware, move this setting only to outgoing portgroups!
@@ -223,18 +309,22 @@ use_callingpres=yes
 ;
 ;echocancel=no
 
-; this disables echocancellation when the call is bridged between 
-; mISDN channels
 ;
-; default value: no
+; chan_misdns jitterbuffer, default 4000
+; 
+jitterbuffer=4000
+
 ;
-echocancelwhenbridged=no
+; change this threshold to enable dejitter functionality
+;
+jitterbuffer_upper_threshold=0
+
 
-; Set this to no to disable echotraining
 ;
-; default value: yes
+; change this to yes, if you want to bridge a mISDN data channel to 
+; another channel type or to an application.
 ;
-echotraining=yes
+hdlc=no
 
 [intern]
 ; define your ports, e.g. 1,2 (depends on mISDN-driver loading order) 
@@ -243,10 +333,12 @@ ports=1,2
 context=Intern
 
 [internPP]
-; if you want to have pp Protocol on one nt Port, you need 
-; to add a ptp directly after the portnumber, you can still add 
-; more ports and multiple ptp adds in your config.
-ports=3ptp
+;
+; adding the postfix 'ptp' to a port number is obsolete now, chan_misdn
+; parses /etc/misdn-init.conf and sets the ptp mode to the corresponding
+; configs. For backwards compatibility you can still set ptp here.
+;
+ports=3
        
 [first_extern]
 ; again port defs
index 652ba70cd85accaa620db8ebe1f3e0786edb53b3..ab029e4d13c4de9705fdbbfd76884fc085a3c561 100644 (file)
@@ -11,6 +11,7 @@ Features:
 * NT and TE mode
 * PP and PMP mode
 * BRI and PRI (with BNE1 and BN2E1 Cards)
+* Hardware Bridging
 * DTMF Detection in HW+mISDNdsp (much better than asterisks internal!)
 * Display Messages to Phones (which support display msg)
 * HOLD/RETRIEVE/TRANSFER on ISDN Phones : )
@@ -21,6 +22,7 @@ Features:
 * Data (HDLC) callthrough 
 * Data Calling (with app_ptyfork +pppd)
 * Echo cancellation
+* CallDeflection
 * Some other
 
 Supported Hardware:
@@ -54,8 +56,7 @@ channels/misdn. You just need to type:
 cd channels/misdn 
 make misdn
 
-Then all the necessary files are fetched from jollys homepage and are patched
-with the Echocanellor.
+Then all the necessary files are fetched from isdn4linux.de.
 
 
 Pre-Requisites
@@ -64,7 +65,7 @@ Pre-Requisites
 To compile and install this driver, you'll need at least one mISDN Driver and
 the mISDNuser package. Chan_misdn works with both, the current release version
 and the development (svn trunk) version of Asterisk. mISDNuser and mISDN must
-be fetched from jollys homepage and must be patched with the Echocancellor.
+be fetched from cvs.isdn4linux.de.
 
 Please Note that mISDN works good for the linux-2.6.x kernels. Some of the
 mISDN drivers do not compile against the 2.4.x or older kernels, you can patch
@@ -140,10 +141,6 @@ should insert here the msns which you'll like to give the Asterisk).  Finally
 a context variable resides in the user sections, which tells chan_misdn where
 to send incoming calls to in the Asterisk dial plan (extension.conf).
 
-In NT-Mode Ports there is a new option, directly after the port number you can
-write ptp, this enables PP Mode for this port, please look at misdn.conf.sample for
-an example.
-
 
 Dial and Options String
 -----------------------
@@ -283,31 +280,6 @@ the pci_find_subgsys funktion, so hfc_multi from mISDN doesn't compile against
 it, you can just change pci_find_subsys to pci_get_subsys, this works.
 
 
-- chan_misdn-0.0.3-rc1:        
-       * linux-kernel >= 2.6.3 (but at least 2.6) 
-       * asterisk >= v1-0 
-       * mISDN/mISDNuser since September/04
-
-- chan_misdn-0.0.3-rc3:        
-       * linux-kernel >= 2.6.3 (but at least 2.6) 
-       * asterisk >= v1-0.2 
-       * mISDN/mISDNuser since December/04
-
-- chan_misdn-0.0.3-rc4:        
-       * linux-kernel >= 2.6.8 (but at least 2.6) 
-       * asterisk >= v1-0.2 
-       * mISDN/mISDNuser head on cvs.isdn4linux.de
-
-- chan_misdn-0.0.3-rc6:        
-       * linux-kernel >= 2.6.8 (but at least 2.6) 
-       * asterisk >= v1-0.2 
-       * mISDN/mISDNuser head on cvs.isdn4linux.de
-
-- chan_misdn-0.1.0
-       * linux-kernel >= 2.6.8 (but at least 2.6) 
-       * asterisk >= v1-0.2 , also CVS Head
-       * mISDN/mISDNuser (3.0-beta) from isdn.jolly.de
-
 - chan_misdn-0.2.1
        * linux-kernel >= 2.6.8 (but at least 2.6) 
        * asterisk >= v1.2 , also CVS Head