Merge the cli_cleanup branch.
[asterisk/asterisk.git] / channels / chan_misdn.c
index 3fa6331..3d3da0c 100644 (file)
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include <stdio.h>
 #include <pthread.h>
-#include <string.h>
 #include <sys/socket.h>
 #include <sys/time.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
 #include <arpa/inet.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
@@ -55,18 +50,14 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #include "asterisk/channel.h"
 #include "asterisk/config.h"
-#include "asterisk/logger.h"
 #include "asterisk/module.h"
 #include "asterisk/pbx.h"
-#include "asterisk/options.h"
 #include "asterisk/io.h"
 #include "asterisk/frame.h"
 #include "asterisk/translate.h"
 #include "asterisk/cli.h"
 #include "asterisk/musiconhold.h"
 #include "asterisk/dsp.h"
-#include "asterisk/translate.h"
-#include "asterisk/config.h"
 #include "asterisk/file.h"
 #include "asterisk/callerid.h"
 #include "asterisk/indications.h"
@@ -75,13 +66,15 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/term.h"
 #include "asterisk/sched.h"
 #include "asterisk/stringfields.h"
+#include "asterisk/abstract_jb.h"
+#include "asterisk/causes.h"
 
 #include "chan_misdn_config.h"
 #include "isdn_lib.h"
 
-char global_tracefile[BUFFERSIZE+1];
+char global_tracefile[BUFFERSIZE + 1];
 
-static int g_config_initialized=0;
+static int g_config_initialized = 0;
 
 struct misdn_jb{
        int size;
@@ -97,14 +90,14 @@ struct misdn_jb{
 
 
 
-/*! \brief allocates the jb-structure and initialise the elements*/
+/*! \brief allocates the jb-structure and initialize the elements */
 struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
 
 /*! \brief frees the data and destroys the given jitterbuffer struct */
 void misdn_jb_destroy(struct misdn_jb *jb);
 
 /*! \brief fills the jitterbuffer with len data returns < 0 if there was an
-error (bufferoverun). */
+error (buffer overrun). */
 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
 
 /*! \brief gets len bytes out of the jitterbuffer if available, else only the
@@ -112,11 +105,18 @@ 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);
 
+static char *complete_ch(struct ast_cli_args *a);
+static char *complete_debug_port(struct ast_cli_args *a);
+static char *complete_show_config(struct ast_cli_args *a);
+
+/* BEGIN: chan_misdn.h */
+
+ast_mutex_t release_lock;
 
 enum misdn_chan_state {
        MISDN_NOTHING=0,        /*!< at beginning */
        MISDN_WAITING4DIGS, /*!<  when waiting for infos */
-       MISDN_EXTCANTMATCH, /*!<  when asterisk couldnt match our ext */
+       MISDN_EXTCANTMATCH, /*!<  when asterisk couldn't match our ext */
        MISDN_INCOMING_SETUP, /*!<  for incoming setups*/
        MISDN_DIALING, /*!<  when pbx_start */
        MISDN_PROGRESS, /*!<  we got a progress */
@@ -131,9 +131,8 @@ enum misdn_chan_state {
        MISDN_RELEASED, /*!<  when connected */
        MISDN_BRIDGED, /*!<  when bridged */
        MISDN_CLEANING, /*!< when hangup from * but we were connected before */
-       MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
-       MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of */
-       /* misdn_hangup */
+       MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP  came from misdn */
+       MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of misdn_hangup */
        MISDN_HOLDED, /*!< if this chan is holded */
        MISDN_HOLD_DISCONNECT, /*!< if this chan is holded */
   
@@ -149,7 +148,7 @@ struct hold_info {
 
 struct chan_list {
   
-       char allowed_bearers[BUFFERSIZE+1];
+       char allowed_bearers[BUFFERSIZE + 1];
        
        enum misdn_chan_state state;
        int need_queue_hangup;
@@ -244,11 +243,13 @@ static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_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)
+                       ast_free(r->group);
+               ast_free(r);
+       }
 }
 
 static void free_robin_list ( void )
@@ -259,12 +260,13 @@ static void free_robin_list ( void )
 
 static struct robin_list* get_robin_position (char *group) 
 {
+       struct robin_list *new;
        struct robin_list *iter = robin;
        for (; iter; iter = iter->next) {
                if (!strcasecmp(iter->group, group))
                        return iter;
        }
-       struct robin_list *new = (struct robin_list *)calloc(1, sizeof(struct robin_list));
+       new = ast_calloc(1, sizeof(*new));
        new->group = strndup(group, strlen(group));
        new->channel = 1;
        if (robin) {
@@ -282,7 +284,8 @@ static pthread_t misdn_tasks_thread;
 
 static int *misdn_ports;
 
-static void chan_misdn_log(int level, int port, char *tmpl, ...);
+static void chan_misdn_log(int level, int port, char *tmpl, ...)
+       __attribute__ ((format (printf, 3, 4)));
 
 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 );
@@ -293,7 +296,7 @@ static int pbx_start_chan(struct chan_list *ch);
 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
 #define MISDN_ASTERISK_PVT(ast) 1
 
-#include <asterisk/strings.h>
+#include "asterisk/strings.h"
 
 /* #define MISDN_DEBUG 1 */
 
@@ -337,6 +340,7 @@ static int start_bc_tones(struct chan_list *cl);
 static int stop_bc_tones(struct chan_list *cl);
 static void release_chan(struct misdn_bchannel *bc);
 
+static int misdn_check_l2l1(struct ast_channel *chan, void *data);
 static int misdn_set_opt_exec(struct ast_channel *chan, void *data);
 static int misdn_facility_exec(struct ast_channel *chan, void *data);
 
@@ -358,11 +362,6 @@ static int update_ec_config(struct misdn_bchannel *bc);
 
 
 
-
-/*protos*/ 
-
-int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len); 
-
 /*************** Helpers *****************/
 
 static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
@@ -390,87 +389,85 @@ static struct chan_list * get_chan_by_ast_name(char *name)
 
 
 struct allowed_bearers {
-       int cap;
-       int val;
-       char *name;
+       char *name;                     /*!< Bearer capability name string used in /etc/misdn.conf allowed_bearers */
+       char *display;          /*!< Bearer capability displayable name */
+       int cap;                        /*!< SETUP message bearer capability field code value */
+       int deprecated;         /*!< TRUE if this entry is deprecated. (Misspelled or bad name to use) */
 };
 
-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"}
+/* *INDENT-OFF* */
+static const struct allowed_bearers allowed_bearers_array[]= {
+       /* Name,                      Displayable Name       Bearer Capability,                    Deprecated */
+       { "speech",                  "Speech",               INFO_CAPABILITY_SPEECH,               0 },
+       { "3_1khz",                  "3.1KHz Audio",         INFO_CAPABILITY_AUDIO_3_1K,           0 },
+       { "digital_unrestricted",    "Unrestricted Digital", INFO_CAPABILITY_DIGITAL_UNRESTRICTED, 0 },
+       { "digital_restricted",      "Restricted Digital",   INFO_CAPABILITY_DIGITAL_RESTRICTED,   0 },
+       { "digital_restriced",       "Restricted Digital",   INFO_CAPABILITY_DIGITAL_RESTRICTED,   1 }, /* Allow misspelling for backwards compatibility */
+       { "video",                   "Video",                INFO_CAPABILITY_VIDEO,                0 }
 };
+/* *INDENT-ON* */
 
-static char *bearer2str(int cap) {
-       static char *bearers[]={
-               "Speech",
-               "Audio 3.1k",
-               "Unres Digital",
-               "Res Digital",
-               "Video",
-               "Unknown Bearer"
-       };
-       
-       switch (cap) {
-       case INFO_CAPABILITY_SPEECH:
-               return bearers[0];
-               break;
-       case INFO_CAPABILITY_AUDIO_3_1K:
-               return bearers[1];
-               break;
-       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
-               return bearers[2];
-               break;
-       case INFO_CAPABILITY_DIGITAL_RESTRICTED:
-               return bearers[3];
-               break;
-       case INFO_CAPABILITY_VIDEO:
-               return bearers[4];
-               break;
-       default:
-               return bearers[5];
-               break;
-       }
+static const char *bearer2str(int cap)
+{
+       unsigned index;
+
+       for (index = 0; index < ARRAY_LEN(allowed_bearers_array); ++index) {
+               if (allowed_bearers_array[index].cap == cap) {
+                       return allowed_bearers_array[index].display;
+               }
+       }       /* end for */
+
+       return "Unknown Bearer";
 }
 
 
 static void print_facility(struct FacParm *fac, struct misdn_bchannel *bc)
 {
        switch (fac->Function) {
-       case Fac_CD:
-               chan_misdn_log(1,bc->port," --> calldeflect to: %s, screened: %s\n", fac->u.CDeflection.DeflectedToNumber,
-                                          fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
-               break;
-       case Fac_AOCDCurrency:
-               if (fac->u.AOCDcur.chargeNotAvailable)
-                       chan_misdn_log(1,bc->port," --> AOCD currency: charge not available\n");
-               else if (fac->u.AOCDcur.freeOfCharge)
-                       chan_misdn_log(1,bc->port," --> AOCD currency: free of charge\n");
-               else if (fac->u.AOCDchu.billingId >= 0)
-                       chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d billingId:%d\n",
-                                                  fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
-                                                  (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
-               else
-                       chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d\n",
-                                                  fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
-                                                  (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
-               break;
-       case Fac_AOCDChargingUnit:
-               if (fac->u.AOCDchu.chargeNotAvailable)
-                       chan_misdn_log(1,bc->port," --> AOCD charging unit: charge not available\n");
-               else if (fac->u.AOCDchu.freeOfCharge)
-                       chan_misdn_log(1,bc->port," --> AOCD charging unit: free of charge\n");
-               else if (fac->u.AOCDchu.billingId >= 0)
-                       chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
-                                                  fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
-               else
-                       chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
-                                                  fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
-               break;
-       default:
-               chan_misdn_log(1,bc->port," --> unknown\n");
+#ifdef HAVE_MISDN_FAC_RESULT
+               case Fac_RESULT:
+                       chan_misdn_log(0, bc->port," --> Received RESULT Operation\n");
+                       break;
+#endif
+#ifdef HAVE_MISDN_FAC_ERROR
+               case Fac_ERROR:
+                       chan_misdn_log(0, bc->port," --> Received Error Operation\n");
+                       chan_misdn_log(0, bc->port," --> Value:%d Error:%s\n",fac->u.ERROR.errorValue, fac->u.ERROR.error);
+                       break;
+#endif
+               case Fac_CD:
+                       chan_misdn_log(1,bc->port," --> calldeflect to: %s, screened: %s\n", fac->u.CDeflection.DeflectedToNumber,
+                                       fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
+                       break;
+               case Fac_AOCDCurrency:
+                       if (fac->u.AOCDcur.chargeNotAvailable)
+                               chan_misdn_log(1,bc->port," --> AOCD currency: charge not available\n");
+                       else if (fac->u.AOCDcur.freeOfCharge)
+                               chan_misdn_log(1,bc->port," --> AOCD currency: free of charge\n");
+                       else if (fac->u.AOCDchu.billingId >= 0)
+                               chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s billingId:%d\n",
+                                               fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
+                                               (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
+                       else
+                               chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s\n",
+                                               fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
+                                               (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
+                       break;
+               case Fac_AOCDChargingUnit:
+                       if (fac->u.AOCDchu.chargeNotAvailable)
+                               chan_misdn_log(1,bc->port," --> AOCD charging unit: charge not available\n");
+                       else if (fac->u.AOCDchu.freeOfCharge)
+                               chan_misdn_log(1,bc->port," --> AOCD charging unit: free of charge\n");
+                       else if (fac->u.AOCDchu.billingId >= 0)
+                               chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
+                                               fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
+                       else
+                               chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
+                                               fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
+                       break;
+               case Fac_None:
+               default:
+                       chan_misdn_log(1,bc->port," --> unknown facility\n");
        }
 }
 
@@ -611,7 +608,7 @@ static inline void misdn_tasks_wakeup (void)
        pthread_kill(misdn_tasks_thread, SIGUSR1);
 }
 
-static inline int _misdn_tasks_add_variable (int timeout, ast_sched_cb callback, void *data, int variable)
+static inline int _misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data, int variable)
 {
        int task_id;
 
@@ -624,29 +621,29 @@ static inline int _misdn_tasks_add_variable (int timeout, ast_sched_cb callback,
        return task_id;
 }
 
-static int misdn_tasks_add (int timeout, ast_sched_cb callback, void *data)
+static int misdn_tasks_add (int timeout, ast_sched_cb callback, const void *data)
 {
        return _misdn_tasks_add_variable(timeout, callback, data, 0);
 }
 
-static int misdn_tasks_add_variable (int timeout, ast_sched_cb callback, void *data)
+static int misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data)
 {
        return _misdn_tasks_add_variable(timeout, callback, data, 1);
 }
 
 static void misdn_tasks_remove (int task_id)
 {
-       ast_sched_del(misdn_tasks, task_id);
+       AST_SCHED_DEL(misdn_tasks, task_id);
 }
 
-static int misdn_l1_task (void *data)
+static int misdn_l1_task (const void *data)
 {
        misdn_lib_isdn_l1watcher(*(int *)data);
        chan_misdn_log(5, *(int *)data, "L1watcher timeout\n");
        return 1;
 }
 
-static int misdn_overlap_dial_task (void *data)
+static int misdn_overlap_dial_task (const void *data)
 {
        struct timeval tv_end, tv_now;
        int diff;
@@ -669,9 +666,16 @@ static int misdn_overlap_dial_task (void *data)
        diff = ast_tvdiff_ms(tv_end, tv_now);
 
        if (diff <= 100) {
+               char *dad=ch->bc->dad, sexten[]="s";
                /* if we are 100ms near the timeout, we are satisfied.. */
                stop_indicate(ch);
-               if (ast_exists_extension(ch->ast, ch->context, ch->bc->dad, 1, ch->bc->oad)) {
+               
+               if (ast_strlen_zero(ch->bc->dad)) {
+                       dad=sexten;
+                       strcpy(ch->ast->exten, sexten);
+               }
+
+               if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->oad)) {
                        ch->state=MISDN_DIALING;
                        if (pbx_start_chan(ch) < 0) {
                                chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
@@ -680,10 +684,9 @@ static int misdn_overlap_dial_task (void *data)
                } else {
 misdn_overlap_dial_task_disconnect:
                        hanguptone_indicate(ch);
-                       if (ch->bc->nt)
-                               misdn_lib_send_event(ch->bc, EVENT_RELEASE_COMPLETE );
-                       else
-                               misdn_lib_send_event(ch->bc, EVENT_RELEASE);
+                       ch->bc->out_cause = AST_CAUSE_UNALLOCATED;
+                       ch->state=MISDN_CLEANING;
+                       misdn_lib_send_event(ch->bc, EVENT_DISCONNECT);
                }
                ch->overlap_dial_task = -1;
                return 0;
@@ -722,162 +725,240 @@ static void send_digit_to_chan(struct chan_list *cl, char digit )
                ast_playtones_start(chan,0,dtmf_tones[15], 0);
        else {
                /* not handled */
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
+               ast_debug(1, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
        }
 }
+
 /*** CLI HANDLING ***/
-static int misdn_set_debug(int fd, int argc, char *argv[])
+static char *handle_cli_misdn_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       if (argc != 4 && argc != 5 && argc != 6 && argc != 7)
-               return RESULT_SHOWUSAGE; 
-
-       int level = atoi(argv[3]);
-
-       switch (argc) {
-               case 4: 
-               case 5: {
-                                       int only = 0;
-                                       if (argc == 5) {
-                                               if (strncasecmp(argv[4], "only", strlen(argv[4])))
-                                                       return RESULT_SHOWUSAGE;
-                                               else
-                                                       only = 1;
-                                       }
-                                       int i;
-                                       for (i=0; i<=max_ports; i++) {
-                                               misdn_debug[i] = level;
-                                               misdn_debug_only[i] = only;
-                                       }
-                                       ast_cli(fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
-                               }
-                               break;
-               case 6: 
-               case 7: {
-                                       if (strncasecmp(argv[4], "port", strlen(argv[4])))
-                                               return RESULT_SHOWUSAGE;
-                                       int port = atoi(argv[5]);
-                                       if (port <= 0 || port > max_ports) {
-                                               switch (max_ports) {
-                                                       case 0:
-                                                               ast_cli(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
-                                                               break;
-                                                       case 1:
-                                                               ast_cli(fd, "port number not valid! only port 1 is availble.\n");
-                                                               break;
-                                                       default:
-                                                               ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
-                                                       }
-                                                       return 0;
-                                       }
-                                       if (argc == 7) {
-                                               if (strncasecmp(argv[6], "only", strlen(argv[6])))
-                                                       return RESULT_SHOWUSAGE;
-                                               else
-                                                       misdn_debug_only[port] = 1;
-                                       } else
-                                               misdn_debug_only[port] = 0;
-                                       misdn_debug[port] = level;
-                                       ast_cli(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
+       int level;
+
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn set debug {on|off|<level>}";
+               e->usage =
+                       "Usage: misdn set debug {on|off|<level>} [only] | [port <port> [only]]\n"
+                       "       Set the debug level of the mISDN channel.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return complete_debug_port(a);
+       }
+
+       if (a->argc < 4 || a->argc > 7)
+               return CLI_SHOWUSAGE;
+       
+       if (!strcasecmp(a->argv[3], "on")) {
+               level = 1;
+       } else if (!strcasecmp(a->argv[3], "off")) {
+               level = 0;
+       } else {
+               level = atoi(a->argv[3]);
+       }
+
+       switch (a->argc) {
+       case 4: 
+       case 5:
+               {
+                       int only = 0, i;
+                       if (a->argc == 5) {
+                               if (strncasecmp(a->argv[4], "only", strlen(a->argv[4])))
+                                       return CLI_SHOWUSAGE;
+                               else
+                                       only = 1;
+                       }
+       
+                       for (i = 0; i <= max_ports; i++) {
+                               misdn_debug[i] = level;
+                               misdn_debug_only[i] = only;
+                       }
+                       ast_cli(a->fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
+               }
+               break;
+       case 6: 
+       case 7:
+               {
+                       int port;
+                       if (strncasecmp(a->argv[4], "port", strlen(a->argv[4])))
+                               return CLI_SHOWUSAGE;
+                       port = atoi(a->argv[5]);
+                       if (port <= 0 || port > max_ports) {
+                               switch (max_ports) {
+                               case 0:
+                                       ast_cli(a->fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
+                                       break;
+                               case 1:
+                                       ast_cli(a->fd, "port number not valid! only port 1 is available.\n");
+                                       break;
+                               default:
+                                       ast_cli(a->fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
                                }
+                               return 0;
+                       }
+                       if (a->argc == 7) {
+                               if (strncasecmp(a->argv[6], "only", strlen(a->argv[6])))
+                                       return CLI_SHOWUSAGE;
+                               else
+                                       misdn_debug_only[port] = 1;
+                       } else
+                               misdn_debug_only[port] = 0;
+                       misdn_debug[port] = level;
+                       ast_cli(a->fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
+               }
        }
-       return 0;
+
+       return CLI_SUCCESS;
 }
 
-static int misdn_set_crypt_debug(int fd, int argc, char *argv[])
+static char *handle_cli_misdn_set_crypt_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       if (argc != 5) return RESULT_SHOWUSAGE; 
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn set crypt debug";
+               e->usage =
+                       "Usage: misdn set crypt debug <level>\n"
+                       "       Set the crypt debug level of the mISDN channel. Level\n"
+                       "       must be 1 or 2.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
 
-       return 0;
-}
+       if (a->argc != 5)
+               return CLI_SHOWUSAGE;
 
+       /* Is this supposed to not do anything? */
+
+       return CLI_SUCCESS;
+}
 
-static int misdn_port_block(int fd, int argc, char *argv[])
+static char *handle_cli_misdn_port_block(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       int port;
-  
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
-  
-       port = atoi(argv[3]);
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn port block";
+               e->usage =
+                       "Usage: misdn port block <port>\n"
+                       "       Block the specified port by <port>.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
 
-       misdn_lib_port_block(port);
+       if (a->argc != 4)
+               return CLI_SHOWUSAGE;
 
-       return 0;
+       misdn_lib_port_block(atoi(a->argv[3]));
+
+       return CLI_SUCCESS;
 }
 
-static int misdn_port_unblock(int fd, int argc, char *argv[])
+static char *handle_cli_misdn_port_unblock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       int port;
-  
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
-  
-       port = atoi(argv[3]);
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn port unblock";
+               e->usage =
+                       "Usage: misdn port unblock <port>\n"
+                       "       Unblock the port specified by <port>.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
 
-       misdn_lib_port_unblock(port);
+       if (a->argc != 4)
+               return CLI_SHOWUSAGE;
 
-       return 0;
-}
+       misdn_lib_port_unblock(atoi(a->argv[3]));
 
+       return CLI_SUCCESS;
+}
 
-static int misdn_restart_port (int fd, int argc, char *argv[])
+static char *handle_cli_misdn_restart_port(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       int port;
-  
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
-  
-       port = atoi(argv[3]);
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn restart port";
+               e->usage =
+                       "Usage: misdn restart port <port>\n"
+                       "       Restart the given port.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
 
-       misdn_lib_port_restart(port);
+       if (a->argc != 4)
+               return CLI_SHOWUSAGE;
 
-       return 0;
+       misdn_lib_port_restart(atoi(a->argv[3]));
+
+       return CLI_SUCCESS;
 }
 
-static int misdn_restart_pid (int fd, int argc, char *argv[])
+static char *handle_cli_misdn_restart_pid(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       int pid;
-  
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
-  
-       pid = atoi(argv[3]);
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn restart pid";
+               e->usage =
+                       "Usage: misdn restart pid <pid>\n"
+                       "       Restart the given pid\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
 
-       misdn_lib_pid_restart(pid);
+       if (a->argc != 4)
+               return CLI_SHOWUSAGE;
 
-       return 0;
+       misdn_lib_pid_restart(atoi(a->argv[3]));
+
+       return CLI_SUCCESS;
 }
 
-static int misdn_port_up (int fd, int argc, char *argv[])
+static char *handle_cli_misdn_port_up(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       int port;
-       
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
-       
-       port = atoi(argv[3]);
-       
-       misdn_lib_get_port_up(port);
-  
-       return 0;
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn port up";
+               e->usage =
+                       "Usage: misdn port up <port>\n"
+                       "       Try to establish L1 on the given port.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+
+       if (a->argc != 4)
+               return CLI_SHOWUSAGE;
+
+       misdn_lib_get_port_up(atoi(a->argv[3]));
+
+       return CLI_SUCCESS;
 }
 
-static int misdn_port_down (int fd, int argc, char *argv[])
+static char *handle_cli_misdn_port_down(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       int port;
-       
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
-       
-       port = atoi(argv[3]);
-       
-       misdn_lib_get_port_down(port);
-  
-       return 0;
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn port down";
+               e->usage =
+                       "Usage: misdn port down <port>\n"
+                       "       Try to deactivate the L1 on the given port.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+
+       if (a->argc != 4)
+               return CLI_SHOWUSAGE;
+
+       misdn_lib_get_port_down(atoi(a->argv[3]));
+
+       return CLI_SUCCESS;
 }
 
-static inline void show_config_description (int fd, enum misdn_cfg_elements elem)
+static inline void show_config_description(int fd, enum misdn_cfg_elements elem)
 {
        char section[BUFFERSIZE];
        char name[BUFFERSIZE];
@@ -898,9 +979,11 @@ static inline void show_config_description (int fd, enum misdn_cfg_elements elem
                ast_cli(fd, "[%s] %s   (Default: %s)\n\t%s\n", section, name, def, desc);
        else
                ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);
+
+       return;
 }
 
-static int misdn_show_config (int fd, int argc, char *argv[])
+static char *handle_cli_misdn_show_config(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        char buffer[BUFFERSIZE];
        enum misdn_cfg_elements elem;
@@ -908,86 +991,94 @@ static int misdn_show_config (int fd, int argc, char *argv[])
        int onlyport = -1;
        int ok = 0;
 
-       if (argc >= 4) {
-               if (!strcmp(argv[3], "description")) {
-                       if (argc == 5) {
-                               enum misdn_cfg_elements elem = misdn_cfg_get_elem (argv[4]);
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn show config";
+               e->usage =
+                       "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
+               "       Use 0 for <port> to only print the general config.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return complete_show_config(a);
+       }
+
+       if (a->argc >= 4) {
+               if (!strcmp(a->argv[3], "description")) {
+                       if (a->argc == 5) {
+                               enum misdn_cfg_elements elem = misdn_cfg_get_elem(a->argv[4]);
                                if (elem == MISDN_CFG_FIRST)
-                                       ast_cli(fd, "Unknown element: %s\n", argv[4]);
+                                       ast_cli(a->fd, "Unknown element: %s\n", a->argv[4]);
                                else
-                                       show_config_description(fd, elem);
-                               return 0;
+                                       show_config_description(a->fd, elem);
+                               return CLI_SUCCESS;
                        }
-                       return RESULT_SHOWUSAGE;
-               }
-               if (!strcmp(argv[3], "descriptions")) {
-                       if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "general"))) {
+                       return CLI_SHOWUSAGE;
+               } else if (!strcmp(a->argv[3], "descriptions")) {
+                       if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "general"))) {
                                for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
-                                       show_config_description(fd, elem);
-                                       ast_cli(fd, "\n");
+                                       show_config_description(a->fd, elem);
+                                       ast_cli(a->fd, "\n");
                                }
                                ok = 1;
                        }
-                       if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "ports"))) {
+                       if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "ports"))) {
                                for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem) {
-                                       show_config_description(fd, elem);
-                                       ast_cli(fd, "\n");
+                                       show_config_description(a->fd, elem);
+                                       ast_cli(a->fd, "\n");
                                }
                                ok = 1;
                        }
-                       return ok ? 0 : RESULT_SHOWUSAGE;
+                       return ok ? CLI_SUCCESS : CLI_SHOWUSAGE;
+               } else if (!sscanf(a->argv[3], "%d", &onlyport) || onlyport < 0) {
+                       ast_cli(a->fd, "Unknown option: %s\n", a->argv[3]);
+                       return CLI_SHOWUSAGE;
                }
-               if (!sscanf(argv[3], "%d", &onlyport) || onlyport < 0) {
-                       ast_cli(fd, "Unknown option: %s\n", argv[3]);
-                       return RESULT_SHOWUSAGE;
-               }
-       }
-       
-       if (argc == 3 || onlyport == 0) {
-               ast_cli(fd,"Misdn General-Config: \n"); 
+       } else if (a->argc == 3 || onlyport == 0) {
+               ast_cli(a->fd, "mISDN General-Config:\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" : "");
+                       misdn_cfg_get_config_string(0, elem, buffer, sizeof(buffer));
+                       ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
                }
-               ast_cli(fd, "\n");
+               ast_cli(a->fd, "\n");
        }
 
        if (onlyport < 0) {
                int port = misdn_cfg_get_next_port(0);
                for (; port > 0; port = misdn_cfg_get_next_port(port)) {
-                       ast_cli(fd, "\n[PORT %d]\n", port);
+                       ast_cli(a->fd, "\n[PORT %d]\n", port);
                        for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
-                               misdn_cfg_get_config_string( port, elem, buffer, BUFFERSIZE);
-                               ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
+                               misdn_cfg_get_config_string(port, elem, buffer, sizeof(buffer));
+                               ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
                        }       
-                       ast_cli(fd, "\n");
+                       ast_cli(a->fd, "\n");
                }
        }
        
        if (onlyport > 0) {
                if (misdn_cfg_is_port_valid(onlyport)) {
-                       ast_cli(fd, "[PORT %d]\n", onlyport);
+                       ast_cli(a->fd, "[PORT %d]\n", onlyport);
                        for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
-                               misdn_cfg_get_config_string(onlyport, elem, buffer, BUFFERSIZE);
-                               ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
+                               misdn_cfg_get_config_string(onlyport, elem, buffer, sizeof(buffer));
+                               ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
                        }       
-                       ast_cli(fd, "\n");
+                       ast_cli(a->fd, "\n");
                } else {
-                       ast_cli(fd, "Port %d is not active!\n", onlyport);
+                       ast_cli(a->fd, "Port %d is not active!\n", onlyport);
                }
        }
-       return 0;
+
+       return CLI_SUCCESS;
 }
 
 struct state_struct {
        enum misdn_chan_state state;
-       char txt[255] ;
-} ;
+       char txt[255];
+};
 
 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_EXTCANTMATCH,"EXTCANTMATCH"}, /*  when asterisk couldn't match our ext */
        {MISDN_INCOMING_SETUP,"INCOMING SETUP"}, /*  when pbx_start */
        {MISDN_DIALING,"DIALING"}, /*  when pbx_start */
        {MISDN_PROGRESS,"PROGRESS"}, /*  when pbx_start */
@@ -1002,25 +1093,25 @@ static struct state_struct state_array[] = {
        {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 */
-       {MISDN_HOLDED,"HOLDED"}, /* when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
-       {MISDN_HOLD_DISCONNECT,"HOLD_DISCONNECT"}, /* when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
-       {MISDN_HUNGUP_FROM_AST,"HUNGUP_FROM_AST"} /* when DISCONNECT/RELEASE/REL_COMP came out of */
-       /* misdn_hangup */
+       {MISDN_HUNGUP_FROM_MISDN,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP  came from misdn */
+       {MISDN_HOLDED,"HOLDED"}, /* when DISCONNECT/RELEASE/REL_COMP  came from misdn */
+       {MISDN_HOLD_DISCONNECT,"HOLD_DISCONNECT"}, /* when DISCONNECT/RELEASE/REL_COMP  came from misdn */
+       {MISDN_HUNGUP_FROM_AST,"HUNGUP_FROM_AST"} /* when DISCONNECT/RELEASE/REL_COMP came out of misdn_hangup */
 };
 
-static char *misdn_get_ch_state(struct chan_list *p) 
+static const 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; 
+       for (i = 0; i < sizeof(state_array) / sizeof(struct state_struct); i++) {
+               if (state_array[i].state == p->state)
+                       return state_array[i].txt; 
        }
 
-       sprintf(state,"%d",p->state) ;
+       snprintf(state, sizeof(state), "%d", p->state) ;
 
        return state;
 }
@@ -1039,8 +1130,8 @@ static void reload_config(void)
        free_robin_list();
        misdn_cfg_reload();
        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));
+       misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
+       misdn_cfg_get(0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(cfg_debug));
 
        for (i = 0;  i <= max_ports; i++) {
                misdn_debug[i] = cfg_debug;
@@ -1048,26 +1139,41 @@ static void reload_config(void)
        }
 }
 
-static int misdn_reload (int fd, int argc, char *argv[])
+static char *handle_cli_misdn_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       ast_cli(fd, "Reloading mISDN Config\n");
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn reload";
+               e->usage =
+                       "Usage: misdn reload\n"
+                       "       Reload internal mISDN config, read from the config\n"
+                       "       file.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+
+       if (a->argc != 2)
+               return CLI_SHOWUSAGE;
+
+       ast_cli(a->fd, "Reloading mISDN configuration\n");
        reload_config();
-       return 0;
+       return CLI_SUCCESS;
 }
 
-static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel* bc)
+static void print_bc_info (int fd, struct chan_list *help, struct misdn_bchannel *bc)
 {
-       struct ast_channel *ast=help->ast;
+       struct ast_channel *ast = help->ast;
        ast_cli(fd,
                "* 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->originator == ORG_AST?"*":"I",
-               ast?ast->exten:NULL,
-               ast?ast->cid.cid_num:NULL,
+               bc->nt ? "NT" : "TE",
+               help->originator == ORG_AST ? "*" : "I",
+               ast ? ast->exten : NULL,
+               ast ? ast->cid.cid_num : NULL,
                bc->rad,
-               ast?ast->context:NULL,
+               ast ? ast->context : NULL,
                misdn_get_ch_state(help)
                );
        if (misdn_debug[bc->port] > 0)
@@ -1092,7 +1198,7 @@ static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel
                        help->l3id,
                        help->addr,
                        bc->addr,
-                       bc?bc->l3_id:-1,
+                       bc ? bc->l3_id : -1,
                        bc->display,
                        
                        bc->active,
@@ -1104,545 +1210,673 @@ static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel
                        bc->ec_enable,
 #endif
 
-                       help->norxtone,help->notxtone,
+                       help->norxtone, help->notxtone,
                        bc->holded
                        );
-  
+
 }
 
-static int misdn_show_cls (int fd, int argc, char *argv[])
+static char *handle_cli_misdn_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       struct chan_list *help=cl_te;
-  
-       ast_cli(fd,"Chan List: %p\n",cl_te); 
+       struct chan_list *help = NULL;
+
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn show channels";
+               e->usage =
+                       "Usage: misdn show channels\n"
+                       "       Show the internal mISDN channel list\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+
+       if (a->argc != 3)
+               return CLI_SHOWUSAGE;
+
+       help = cl_te;
   
-       for (;help; help=help->next) {
-               struct misdn_bchannel *bc=help->bc;   
-               struct ast_channel *ast=help->ast;
-               if (misdn_debug[0] > 2) ast_cli(fd, "Bc:%p Ast:%p\n", bc, ast);
+       ast_cli(a->fd, "Channel List: %p\n", cl_te); 
+
+       for (; help; help = help->next) {
+               struct misdn_bchannel *bc = help->bc;   
+               struct ast_channel *ast = help->ast;
+               if (!ast) {
+                       if (!bc) {
+                               ast_cli(a->fd, "chan_list obj. with l3id:%x has no bc and no ast Leg\n", help->l3id);
+                               continue;
+                       }
+                       ast_cli(a->fd, "bc with pid:%d has no Ast Leg\n", bc->pid);
+                       continue;
+               }
+
+               if (misdn_debug[0] > 2)
+                       ast_cli(a->fd, "Bc:%p Ast:%p\n", bc, ast);
                if (bc) {
-                       print_bc_info(fd, help, bc);
+                       print_bc_info(a->fd, help, bc);
                } else {
                        if (help->state == MISDN_HOLDED) {
-                               ast_cli(fd, "ITS A HOLDED BC:\n");
-                               ast_cli(fd, " --> l3_id: %x\n"
+                               ast_cli(a->fd, "ITS A HOLDED BC:\n");
+                               ast_cli(a->fd, " --> l3_id: %x\n"
                                                " --> dad:%s oad:%s\n"
                                                " --> hold_port: %d\n"
-                                               " --> hold_channel: %d\n"
-                               
-                                               ,help->l3id
-                                               ,ast->exten
-                                               ,ast->cid.cid_num
-                                               ,help->hold_info.port
-                                               ,help->hold_info.channel
+                                               " --> hold_channel: %d\n",
+                                               help->l3id,
+                                               ast->exten,
+                                               ast->cid.cid_num,
+                                               help->hold_info.port,
+                                               help->hold_info.channel
                                                );
                        } else {
-                               ast_cli(fd,"* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, ast->cid.cid_num);
+                               ast_cli(a->fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, ast->cid.cid_num);
                        }
                }
        }
-  
-  
-       return 0;
+
+       misdn_dump_chanlist();
+
+       return CLI_SUCCESS;
 }
 
-static int misdn_show_cl (int fd, int argc, char *argv[])
+static char *handle_cli_misdn_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       struct chan_list *help=cl_te;
+       struct chan_list *help = NULL;
+
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn show channel";
+               e->usage =
+                       "Usage: misdn show channel <channel>\n"
+                       "       Show an internal mISDN channel\n.";
+               return NULL;
+       case CLI_GENERATE:
+               return complete_ch(a);
+       }
 
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
-  
-       for (;help; help=help->next) {
-               struct misdn_bchannel *bc=help->bc;   
-               struct ast_channel *ast=help->ast;
+       if (a->argc != 4)
+               return CLI_SHOWUSAGE;
+
+       help = cl_te;
+
+       for (; help; help = help->next) {
+               struct misdn_bchannel *bc = help->bc;   
+               struct ast_channel *ast = help->ast;
     
                if (bc && ast) {
-                       if (!strcasecmp(ast->name,argv[3])) {
-                               print_bc_info(fd, help, bc);
+                       if (!strcasecmp(ast->name, a->argv[3])) {
+                               print_bc_info(a->fd, help, bc);
                                break; 
                        }
                } 
        }
-  
-  
-       return 0;
+
+       return CLI_SUCCESS;
 }
 
 ast_mutex_t lock;
-int MAXTICS=8;
+int MAXTICS = 8;
 
-static int misdn_set_tics (int fd, int argc, char *argv[])
+static char *handle_cli_misdn_set_tics(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
-  
-       MAXTICS=atoi(argv[3]);
-  
-       return 0;
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn set tics";
+               e->usage =
+                       "Usage: misdn set tics <value>\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+
+       if (a->argc != 4)
+               return CLI_SHOWUSAGE;
+
+       MAXTICS = atoi(a->argv[3]);
+
+       return CLI_SUCCESS;
 }
 
-static int misdn_show_stacks (int fd, int argc, char *argv[])
+static char *handle_cli_misdn_show_stacks(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int port;
 
-       ast_cli(fd, "BEGIN STACK_LIST:\n");
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn show stacks";
+               e->usage =
+                       "Usage: misdn show stacks\n"
+                       "       Show internal mISDN stack_list.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+
+       if (a->argc != 3)
+               return CLI_SHOWUSAGE;
 
-       for (port=misdn_cfg_get_next_port(0); port > 0;
-            port=misdn_cfg_get_next_port(port)) {
+       ast_cli(a->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];
-               get_show_stack_details(port,buf);
-               ast_cli(fd,"  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
+               get_show_stack_details(port, buf);
+               ast_cli(a->fd,"  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
        }
-               
-       return 0;
-}
 
+       return CLI_SUCCESS;
+}
 
-static int misdn_show_ports_stats (int fd, int argc, char *argv[])
+static char *handle_cli_misdn_show_ports_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int port;
 
-       ast_cli(fd, "Port\tin_calls\tout_calls\n");
-       
-       for (port=misdn_cfg_get_next_port(0); port > 0;
-            port=misdn_cfg_get_next_port(port)) {
-               ast_cli(fd,"%d\t%d\t\t%d\n",port,misdn_in_calls[port],misdn_out_calls[port]);
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn show ports stats";
+               e->usage =
+                       "Usage: misdn show ports stats\n"
+                       "       Show mISDNs channel's call statistics per port.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
        }
-       ast_cli(fd,"\n");
-       
-       return 0;
 
-}
+       if (a->argc != 4)
+               return CLI_SHOWUSAGE;
 
+       ast_cli(a->fd, "Port\tin_calls\tout_calls\n");
+       for (port = misdn_cfg_get_next_port(0); port > 0;
+            port = misdn_cfg_get_next_port(port)) {
+               ast_cli(a->fd, "%d\t%d\t\t%d\n", port, misdn_in_calls[port], misdn_out_calls[port]);
+       }
+       ast_cli(a->fd, "\n");
+
+       return CLI_SUCCESS;
+}
 
-static int misdn_show_port (int fd, int argc, char *argv[])
+static char *handle_cli_misdn_show_port(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int port;
-       
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
-  
-       port = atoi(argv[3]);
-  
-       ast_cli(fd, "BEGIN STACK_LIST:\n");
-
        char buf[128];
-       get_show_stack_details(port,buf);
-       ast_cli(fd,"  %s  Debug:%d%s\n",buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
 
-       
-       return 0;
-}
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn show port";
+               e->usage =
+                       "Usage: misdn show port <port>\n"
+                       "       Show detailed information for given port.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
 
-static int misdn_send_cd (int fd, int argc, char *argv[])
-{
-       char *channame; 
-       char *nr; 
-  
-       if (argc != 5)
-               return RESULT_SHOWUSAGE;
-  
-       channame = argv[3];
-       nr = argv[4];
+       if (a->argc != 4)
+               return CLI_SHOWUSAGE;
 
-       ast_cli(fd, "Sending Calldeflection (%s) to %s\n",nr, channame);
-       
-       {
-               struct chan_list *tmp=get_chan_by_ast_name(channame);
-               
-               if (!tmp) {
-                       ast_cli(fd, "Sending CD with nr %s to %s failed: Channel does not exist.\n",nr, channame);
-                       return 0; 
-               } else {
-                       if (strlen(nr) >= 15) {
-                               ast_cli(fd, "Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n",nr, channame);
-                               return 0; 
-                       }
-                       tmp->bc->fac_out.Function = Fac_CD;
-                       strncpy((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
-                       misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
-               }
-       }
+       port = atoi(a->argv[3]);
   
-       return 0; 
+       ast_cli(a->fd, "BEGIN STACK_LIST:\n");
+       get_show_stack_details(port, buf);
+       ast_cli(a->fd, "  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
+
+       return CLI_SUCCESS;
 }
 
-static int misdn_send_digit (int fd, int argc, char *argv[])
+static char *handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        char *channame; 
-       char *msg; 
-  
-       if (argc != 5)
-               return RESULT_SHOWUSAGE;
-  
-       channame = argv[3];
-       msg = argv[4];
+       char *nr;
+       struct chan_list *tmp;
+       int port; 
+       char *served_nr;
+       struct misdn_bchannel dummy, *bc=&dummy;
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn send facility";
+               e->usage = "Usage: misdn send facility <type> <channel|port> \"<args>\" \n"
+               "\t type is one of:\n"
+               "\t - calldeflect\n"
+               "\t - CFActivate\n"
+               "\t - CFDeactivate\n";
 
-       ast_cli(fd, "Sending %s to %s\n",msg, channame);
-  
-       {
-               struct chan_list *tmp=get_chan_by_ast_name(channame);
-    
+               return NULL;
+       case CLI_GENERATE:
+               return complete_ch(a);
+       }
+
+       if (a->argc < 5)
+               return CLI_SHOWUSAGE;
+       if (strstr(a->argv[3], "calldeflect")) {
+               if (a->argc < 6) {
+                       ast_verbose("calldeflect requires 1 arg: ToNumber\n\n");
+                       return 0;
+               }
+               channame = a->argv[4];
+               nr = a->argv[5];
+
+               ast_verbose("Sending Calldeflection (%s) to %s\n", nr, channame);
+               tmp = get_chan_by_ast_name(channame);
                if (!tmp) {
-                       ast_cli(fd, "Sending %s to %s failed Channel does not exist\n",msg, channame);
+                       ast_verbose("Sending CD with nr %s to %s failed: Channel does not exist.\n",nr, channame);
                        return 0; 
-               } else {
-#if 1
-                       int i;
-                       int msglen = strlen(msg);
-                       for (i=0; i<msglen; i++) {
-                               ast_cli(fd, "Sending: %c\n",msg[i]);
-                               send_digit_to_chan(tmp, msg[i]);
-                               /* res = ast_safe_sleep(tmp->ast, 250); */
-                               usleep(250000);
-                               /* res = ast_waitfor(tmp->ast,100); */
-                       }
-#else
-                       int res;
-                       res = ast_dtmf_stream(tmp->ast,NULL,msg,250);
-#endif
                }
+
+               if (strlen(nr) >= 15) {
+                       ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n",nr, channame);
+                       return 0; 
+               }
+               tmp->bc->fac_out.Function = Fac_CD;
+               ast_copy_string((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
+               misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
+       } else if (strstr(a->argv[3],"CFActivate")) {
+               if (a->argc < 7) {
+                       ast_verbose("CFActivate requires 2 args: 1.FromNumber, 2.ToNumber\n\n");
+                       return 0;
+               }
+               port = atoi(a->argv[4]);
+               served_nr = a->argv[5];
+               nr = a->argv[6];
+
+               misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
+
+               ast_verbose("Sending CFActivate  Port:(%d) FromNr. (%s) to Nr. (%s)\n", port, served_nr, nr);
+
+               bc->fac_out.Function = Fac_CFActivate;
+               bc->fac_out.u.CFActivate.BasicService = 0; //All Services
+               bc->fac_out.u.CFActivate.Procedure = 0; //Unconditional
+               ast_copy_string((char *)bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
+               ast_copy_string((char *)bc->fac_out.u.CFActivate.ForwardedToNumber, nr, sizeof(bc->fac_out.u.CFActivate.ForwardedToNumber));
+
+               misdn_lib_send_event(bc, EVENT_FACILITY);
+       } else if (strstr(a->argv[3],"CFDeactivate")) {
+
+               if (a->argc < 6) {
+                       ast_verbose("CFActivate requires 1 arg: FromNumber\n\n");
+                       return 0;
+               }
+               port = atoi(a->argv[4]);
+               served_nr = a->argv[5];
+               
+               misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
+               ast_verbose("Sending CFDeactivate  Port:(%d) FromNr. (%s)\n", port, served_nr);
+
+               bc->fac_out.Function = Fac_CFDeactivate;
+               bc->fac_out.u.CFDeactivate.BasicService = 0; //All Services
+               bc->fac_out.u.CFDeactivate.Procedure = 0; //Unconditional
+               
+               ast_copy_string((char *)bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
+               misdn_lib_send_event(bc, EVENT_FACILITY);
        }
-  
-       return 0; 
+
+       return CLI_SUCCESS;
+}
+
+static char *handle_cli_misdn_send_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn send restart";
+               e->usage =
+                       "Usage: misdn send restart [port [channel]]\n"
+                       "       Send a restart for every bchannel on the given port.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+
+       if (a->argc < 4 || a->argc > 5)
+               return CLI_SHOWUSAGE;
+
+       if (a->argc == 5)
+               misdn_lib_send_restart(atoi(a->argv[3]), atoi(a->argv[4]));
+       else
+               misdn_lib_send_restart(atoi(a->argv[3]), -1);
+
+       return CLI_SUCCESS;
 }
 
-static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
+static char *handle_cli_misdn_send_digit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        char *channame; 
+       char *msg; 
+       struct chan_list *tmp;
+       int i, msglen;
+
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn send digit";
+               e->usage =
+                       "Usage: misdn send digit <channel> \"<msg>\" \n"
+                       "       Send <digit> to <channel> as DTMF Tone\n"
+                       "       when channel is a mISDN channel\n";
+               return NULL;
+       case CLI_GENERATE:
+               return complete_ch(a);
+       }
 
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
-       
-       channame = argv[3];
-  
-       ast_cli(fd, "Toggling EchoCancel on %s\n", channame);
-  
-       {
-               struct chan_list *tmp=get_chan_by_ast_name(channame);
-    
-               if (!tmp) {
-                       ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
-                       return 0; 
-               } else {
-                       
-                       tmp->toggle_ec=tmp->toggle_ec?0:1;
+       if (a->argc != 5)
+               return CLI_SHOWUSAGE;
 
-                       if (tmp->toggle_ec) {
-#ifdef MISDN_1_2
-                               update_pipeline_config(tmp->bc);
+       channame = a->argv[3];
+       msg = a->argv[4];
+       msglen = strlen(msg);
+
+       ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
+
+       tmp = get_chan_by_ast_name(channame);
+       if (!tmp) {
+               ast_cli(a->fd, "Sending %s to %s failed Channel does not exist\n", msg, channame);
+               return CLI_SUCCESS; 
+       }
+#if 1
+       for (i = 0; i < msglen; i++) {
+               ast_cli(a->fd, "Sending: %c\n", msg[i]);
+               send_digit_to_chan(tmp, msg[i]);
+               /* res = ast_safe_sleep(tmp->ast, 250); */
+               usleep(250000);
+               /* res = ast_waitfor(tmp->ast,100); */
+       }
 #else
-                               update_ec_config(tmp->bc);
+       ast_dtmf_stream(tmp->ast, NULL, msg, 250);
 #endif
-                               manager_ec_enable(tmp->bc);
-                       } else {
-                               manager_ec_disable(tmp->bc);
-                       }
-               }
-       }
-  
-       return 0; 
+
+       return CLI_SUCCESS;
 }
 
-static int misdn_send_display (int fd, int argc, char *argv[])
+static char *handle_cli_misdn_toggle_echocancel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       char *channame; 
-       char *msg; 
+       char *channame;
+       struct chan_list *tmp;
+
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn toggle echocancel";
+               e->usage =
+                       "Usage: misdn toggle echocancel <channel>\n"
+                       "       Toggle EchoCancel on mISDN Channel.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return complete_ch(a);
+       }
+
+       if (a->argc != 4)
+               return CLI_SHOWUSAGE;
+
+       channame = a->argv[3];
   
-       if (argc != 5)
-               return RESULT_SHOWUSAGE;
+       ast_cli(a->fd, "Toggling EchoCancel on %s\n", channame);
   
-       channame = argv[3];
-       msg = argv[4];
+       tmp = get_chan_by_ast_name(channame);
+       if (!tmp) {
+               ast_cli(a->fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
+               return CLI_SUCCESS;
+       }
 
-       ast_cli(fd, "Sending %s to %s\n",msg, channame);
-       {
-               struct chan_list *tmp;
-               tmp=get_chan_by_ast_name(channame);
-    
-               if (tmp && tmp->bc) {
-                       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);
-                       return RESULT_FAILURE;
-               }
+       tmp->toggle_ec = tmp->toggle_ec?0:1;
+
+       if (tmp->toggle_ec) {
+#ifdef MISDN_1_2
+               update_pipeline_config(tmp->bc);
+#else
+               update_ec_config(tmp->bc);
+#endif
+               manager_ec_enable(tmp->bc);
+       } else {
+               manager_ec_disable(tmp->bc);
        }
 
-       return RESULT_SUCCESS ;
+       return CLI_SUCCESS;
 }
 
-static char *complete_ch_helper(const char *line, const char *word, int pos, int state, int rpos)
+static char *handle_cli_misdn_send_display(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       struct ast_channel *c;
-       int which=0;
-       char *ret;
-       if (pos != rpos)
+       char *channame;
+       char *msg;
+       struct chan_list *tmp;
+
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "misdn send display";
+               e->usage =
+                       "Usage: misdn send display <channel> \"<msg>\" \n"
+                       "       Send <msg> to <channel> as Display Message\n"
+                       "       when channel is a mISDN channel\n";
                return NULL;
-       c = ast_channel_walk_locked(NULL);
-       while(c) {
-               if (!strncasecmp(word, c->name, strlen(word))) {
-                       if (++which > state)
-                               break;
-               }
-               ast_mutex_unlock(&c->lock);
-               c = ast_channel_walk_locked(c);
+       case CLI_GENERATE:
+               return complete_ch(a);
        }
-       if (c) {
-               ret = strdup(c->name);
-               ast_mutex_unlock(&c->lock);
-       } else
-               ret = NULL;
-       return ret;
+
+       if (a->argc != 5)
+               return CLI_SHOWUSAGE;
+
+       channame = a->argv[3];
+       msg = a->argv[4];
+
+       ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
+       tmp = get_chan_by_ast_name(channame);
+    
+       if (tmp && tmp->bc) {
+               ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
+               misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
+       } else {
+               ast_cli(a->fd, "No such channel %s\n", channame);
+               return CLI_SUCCESS;
+       }
+
+       return CLI_SUCCESS;
 }
 
-static char *complete_ch(const char *line, const char *word, int pos, int state)
+static char *complete_ch(struct ast_cli_args *a)
 {
-       return complete_ch_helper(line, word, pos, state, 3);
+       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
 }
 
-static char *complete_debug_port (const char *line, const char *word, int pos, int state)
+static char *complete_debug_port (struct ast_cli_args *a)
 {
-       if (state)
+       if (a->n)
                return NULL;
 
-       switch (pos) {
-       case 4: if (*word == 'p')
-                               return strdup("port");
-                       else if (*word == 'o')
-                               return strdup("only");
-                       break;
-       case 6: if (*word == 'o')
-                               return strdup("only");
-                       break;
+       switch (a->pos) {
+       case 4:
+               if (a->word[0] == 'p')
+                       return ast_strdup("port");
+               else if (a->word[0] == 'o')
+                       return ast_strdup("only");
+               break;
+       case 6:
+               if (a->word[0] == 'o')
+                       return ast_strdup("only");
+               break;
        }
        return NULL;
 }
 
-static char *complete_show_config (const char *line, const char *word, int pos, int state)
+static char *complete_show_config(struct ast_cli_args *a)
 {
        char buffer[BUFFERSIZE];
        enum misdn_cfg_elements elem;
-       int wordlen = strlen(word);
+       int wordlen = strlen(a->word);
        int which = 0;
        int port = 0;
 
-       switch (pos) {
-       case 3: if ((!strncmp(word, "description", wordlen)) && (++which > state))
-                               return strdup("description");
-                       if ((!strncmp(word, "descriptions", wordlen)) && (++which > state))
-                               return strdup("descriptions");
-                       if ((!strncmp(word, "0", wordlen)) && (++which > state))
-                               return strdup("0");
-                       while ((port = misdn_cfg_get_next_port(port)) != -1) {
-                               snprintf(buffer, sizeof(buffer), "%d", port);
-                               if ((!strncmp(word, buffer, wordlen)) && (++which > state)) {
-                                       return strdup(buffer);
-                               }
+       switch (a->pos) {
+       case 3:
+               if ((!strncmp(a->word, "description", wordlen)) && (++which > a->n))
+                       return ast_strdup("description");
+               if ((!strncmp(a->word, "descriptions", wordlen)) && (++which > a->n))
+                       return ast_strdup("descriptions");
+               if ((!strncmp(a->word, "0", wordlen)) && (++which > a->n))
+                       return ast_strdup("0");
+               while ((port = misdn_cfg_get_next_port(port)) != -1) {
+                       snprintf(buffer, sizeof(buffer), "%d", port);
+                       if ((!strncmp(a->word, buffer, wordlen)) && (++which > a->n)) {
+                               return ast_strdup(buffer);
                        }
-                       break;
+               }
+               break;
        case 4:
-                       if (strstr(line, "description ")) {
-                               for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
-                                       if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST))
-                                               continue;
-                                       misdn_cfg_get_name(elem, buffer, BUFFERSIZE);
-                                       if (!wordlen || !strncmp(word, buffer, wordlen)) {
-                                               if (++which > state)
-                                                       return strdup(buffer);
-                                       }
+               if (strstr(a->line, "description ")) {
+                       for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
+                               if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST))
+                                       continue;
+                               misdn_cfg_get_name(elem, buffer, sizeof(buffer));
+                               if (!wordlen || !strncmp(a->word, buffer, wordlen)) {
+                                       if (++which > a->n)
+                                               return ast_strdup(buffer);
                                }
-                       } else if (strstr(line, "descriptions ")) {
-                               if ((!wordlen || !strncmp(word, "general", wordlen)) && (++which > state))
-                                       return strdup("general");
-                               if ((!wordlen || !strncmp(word, "ports", wordlen)) && (++which > state))
-                                       return strdup("ports");
                        }
-                       break;
+               } else if (strstr(a->line, "descriptions ")) {
+                       if ((!wordlen || !strncmp(a->word, "general", wordlen)) && (++which > a->n))
+                               return ast_strdup("general");
+                       if ((!wordlen || !strncmp(a->word, "ports", wordlen)) && (++which > a->n))
+                               return ast_strdup("ports");
+               }
+               break;
        }
        return NULL;
 }
 
 static struct ast_cli_entry chan_misdn_clis[] = {
-       { {"misdn","send","calldeflect", NULL}, misdn_send_cd, "Sends CallDeflection to mISDN Channel",
-               "Usage: misdn send calldeflect <channel> \"<nr>\" \n", complete_ch },
-       { {"misdn","send","digit", NULL}, misdn_send_digit,     "Sends DTMF Digit to mISDN Channel",
-               "Usage: misdn send digit <channel> \"<msg>\" \n"
-               "       Send <digit> to <channel> as DTMF Tone\n"
-               "       when channel is a mISDN channel\n", complete_ch },
-       { {"misdn","toggle","echocancel", NULL}, misdn_toggle_echocancel, "Toggles EchoCancel on mISDN Channel",
-               "Usage: misdn toggle echocancel <channel>\n", complete_ch },
-       { {"misdn","send","display", NULL}, misdn_send_display, "Sends Text to mISDN Channel", 
-               "Usage: misdn send display <channel> \"<msg>\" \n"
-               "       Send <msg> to <channel> as Display Message\n"
-               "       when channel is a mISDN channel\n", complete_ch },
-       { {"misdn","show","config", NULL}, misdn_show_config, "Shows internal mISDN config, read from cfg-file",
-               "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
-               "       Use 0 for <port> to only print the general config.\n", complete_show_config },
-       { {"misdn","reload", NULL}, misdn_reload, "Reloads internal mISDN config, read from cfg-file",
-               "Usage: misdn reload\n" },
-       { {"misdn","set","tics", NULL}, misdn_set_tics, "", 
-               "\n" },
-       { {"misdn","show","channels", NULL}, misdn_show_cls, "Shows internal mISDN chan_list",
-               "Usage: misdn show channels\n" },
-       { {"misdn","show","channel", NULL}, misdn_show_cl, "Shows internal mISDN chan_list",
-               "Usage: misdn show channels\n", complete_ch },
-       { {"misdn","port","block", NULL}, misdn_port_block, "Blocks the given port",
-               "Usage: misdn port block\n" },
-       { {"misdn","port","unblock", NULL}, misdn_port_unblock, "Unblocks the given port",
-               "Usage: misdn port unblock\n" },
-       { {"misdn","restart","port", NULL}, misdn_restart_port, "Restarts the given port",
-               "Usage: misdn restart port\n" },
-       { {"misdn","restart","pid", NULL}, misdn_restart_pid, "Restarts the given pid",
-               "Usage: misdn restart pid\n" },
-       { {"misdn","port","up", NULL}, misdn_port_up, "Tries to establish L1 on the given port",
-               "Usage: misdn port up <port>\n" },
-       { {"misdn","port","down", NULL}, misdn_port_down, "Tries to deacivate the L1 on the given port",
-               "Usage: misdn port down <port>\n" },
-       { {"misdn","show","stacks", NULL}, misdn_show_stacks, "Shows internal mISDN stack_list",
-               "Usage: misdn show stacks\n" },
-       { {"misdn","show","ports","stats", NULL}, misdn_show_ports_stats, "Shows chan_misdns call statistics per port",
-               "Usage: misdn show port stats\n" },
-       { {"misdn","show","port", NULL}, misdn_show_port, "Shows detailed information for given port",
-               "Usage: misdn show port <port>\n" },
-       { {"misdn","set","debug", NULL}, misdn_set_debug, "Sets Debuglevel of chan_misdn",
-               "Usage: misdn set debug <level> [only] | [port <port> [only]]\n", complete_debug_port },
-       { {"misdn","set","crypt","debug", NULL}, misdn_set_crypt_debug, "Sets CryptDebuglevel of chan_misdn, at the moment, level={1,2}",
-               "Usage: misdn set crypt debug <level>\n" }
+       AST_CLI_DEFINE(handle_cli_misdn_port_block,        "Block the given port"),
+       AST_CLI_DEFINE(handle_cli_misdn_port_down,         "Try to deactivate the L1 on the given port"),
+       AST_CLI_DEFINE(handle_cli_misdn_port_unblock,      "Unblock the given port"),
+       AST_CLI_DEFINE(handle_cli_misdn_port_up,           "Try to establish L1 on the given port"),
+       AST_CLI_DEFINE(handle_cli_misdn_reload,            "Reload internal mISDN config, read from the config file"),
+       AST_CLI_DEFINE(handle_cli_misdn_restart_pid,       "Restart the given pid"),
+       AST_CLI_DEFINE(handle_cli_misdn_restart_port,      "Restart the given port"),
+       AST_CLI_DEFINE(handle_cli_misdn_show_channel,      "Show an internal mISDN channel"),
+       AST_CLI_DEFINE(handle_cli_misdn_show_channels,     "Show the internal mISDN channel list"),
+       AST_CLI_DEFINE(handle_cli_misdn_show_config,       "Show internal mISDN config, read from the config file"),
+       AST_CLI_DEFINE(handle_cli_misdn_show_port,         "Show detailed information for given port"),
+       AST_CLI_DEFINE(handle_cli_misdn_show_ports_stats,  "Show mISDNs channel's call statistics per port"),
+       AST_CLI_DEFINE(handle_cli_misdn_show_stacks,       "Show internal mISDN stack_list"),
+       AST_CLI_DEFINE(handle_cli_misdn_send_facility,     "Sends a Facility Message to the mISDN Channel"),
+       AST_CLI_DEFINE(handle_cli_misdn_send_digit,        "Send DTMF digit to mISDN Channel"),
+       AST_CLI_DEFINE(handle_cli_misdn_send_display,      "Send Text to mISDN Channel"),
+       AST_CLI_DEFINE(handle_cli_misdn_send_restart,      "Send a restart for every bchannel on the given port"),
+       AST_CLI_DEFINE(handle_cli_misdn_set_crypt_debug,   "Set CryptDebuglevel of chan_misdn, at the moment, level={1,2}"),
+       AST_CLI_DEFINE(handle_cli_misdn_set_debug,         "Set Debuglevel of chan_misdn"),
+       AST_CLI_DEFINE(handle_cli_misdn_set_tics,          "???"),
+       AST_CLI_DEFINE(handle_cli_misdn_toggle_echocancel, "Toggle EchoCancel on mISDN Channel"),
 };
 
-static int update_config (struct chan_list *ch, int orig) 
+static int update_config(struct chan_list *ch, int orig) 
 {
+       struct ast_channel *ast;
+       struct misdn_bchannel *bc;
+       int port, hdlc = 0;
+       int pres, screen;
+
        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 = ch->ast;
+       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(7,port,"update_config: Getting Config\n");
 
-       int hdlc=0;
-       misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
+       port = bc->port;
+
+       chan_misdn_log(7, port, "update_config: Getting Config\n");
+
+       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;
+                       chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
+                       bc->hdlc = 1;
                        break;
                }
-               
        }
-       
-       
-       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 ) {
 
-               chan_misdn_log(2,port," --> pres: %x\n", ast->cid.cid_pres);
+
+       misdn_cfg_get(port, MISDN_CFG_PRES, &pres, sizeof(pres));
+       misdn_cfg_get(port, MISDN_CFG_SCREEN, &screen, sizeof(screen));
+       chan_misdn_log(2, port, " --> pres: %d screen: %d\n", pres, screen);
+               
+       if (pres < 0 || screen < 0) {
+               chan_misdn_log(2, port, " --> pres: %x\n", ast->cid.cid_pres);
                        
-               switch (ast->cid.cid_pres & 0x60){
-                               
+               switch (ast->cid.cid_pres & 0x60) {
                case AST_PRES_RESTRICTED:
-                       bc->pres=1;
-                       chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
+                       bc->pres = 1;
+                       chan_misdn_log(2, port, " --> PRES: Restricted (1)\n");
                        break;
-                               
-                               
                case AST_PRES_UNAVAILABLE:
-                       bc->pres=2;
-                       chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
+                       bc->pres = 2;
+                       chan_misdn_log(2, port, " --> PRES: Unavailable (2)\n");
                        break;
-                               
                default:
-                       bc->pres=0;
-                       chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
+                       bc->pres = 0;
+                       chan_misdn_log(2, port, " --> PRES: Allowed (0)\n");
+                       break;
                }
-                       
-               switch (ast->cid.cid_pres & 0x3){
-                               
+
+               switch (ast->cid.cid_pres & 0x3) {
+               default:
                case AST_PRES_USER_NUMBER_UNSCREENED:
-                       bc->screen=0;
-                       chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
+                       bc->screen = 0;
+                       chan_misdn_log(2, port, " --> SCREEN: Unscreened (0)\n");
                        break;
-
                case AST_PRES_USER_NUMBER_PASSED_SCREEN:
-                       bc->screen=1;
-                       chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
+                       bc->screen = 1;
+                       chan_misdn_log(2, port, " --> SCREEN: Passed Screen (1)\n");
                        break;
                case AST_PRES_USER_NUMBER_FAILED_SCREEN:
-                       bc->screen=2;
-                       chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
+                       bc->screen = 2;
+                       chan_misdn_log(2, port, " --> SCREEN: Failed Screen (2)\n");
                        break;
-                               
                case AST_PRES_NETWORK_NUMBER:
-                       bc->screen=3;
-                       chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
+                       bc->screen = 3;
+                       chan_misdn_log(2, port, " --> SCREEN: Network Nr. (3)\n");
                        break;
-                               
-               default:
-                       bc->screen=0;
-                       chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
                }
-
-                       
        } else {
-               bc->screen=screen;
-               bc->pres=pres;
+               bc->screen = screen;
+               bc->pres = pres;
        }
 
        return 0;
-       
 }
 
 
-
-
 static void config_jitterbuffer(struct chan_list *ch)
 {
-       struct misdn_bchannel *bc=ch->bc;
-       int len=ch->jb_len, threshold=ch->jb_upper_threshold;
+       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");
+       chan_misdn_log(5, bc->port, "config_jb: Called\n");
        
-       if ( ! len ) {
-               chan_misdn_log(1,bc->port, "config_jb: Deactivating Jitterbuffer\n");
+       if (! len) {
+               chan_misdn_log(1, bc->port, "config_jb: Deactivating Jitterbuffer\n");
                bc->nojitter=1;
        } else {
-               
-               if (len <=100 || len > 8000) {
-                       chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
-                       len=1000;
+               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");
+                       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");
+                       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 = NULL;
                }
-               
+
                ch->jb=misdn_jb_init(len, threshold);
 
                if (!ch->jb ) 
-                       bc->nojitter=1;
+                       bc->nojitter = 1;
        }
 }
 
@@ -1651,16 +1885,16 @@ void debug_numplan(int port, int numplan, char *type)
 {
        switch (numplan) {
        case NUMPLAN_INTERNATIONAL:
-               chan_misdn_log(2, port, " --> %s: International\n",type);
+               chan_misdn_log(2, port, " --> %s: International\n", type);
                break;
        case NUMPLAN_NATIONAL:
-               chan_misdn_log(2, port, " --> %s: National\n",type);
+               chan_misdn_log(2, port, " --> %s: National\n", type);
                break;
        case NUMPLAN_SUBSCRIBER:
-               chan_misdn_log(2, port, " --> %s: Subscriber\n",type);
+               chan_misdn_log(2, port, " --> %s: Subscriber\n", type);
                break;
        case NUMPLAN_UNKNOWN:
-               chan_misdn_log(2, port, " --> %s: Unknown\n",type);
+               chan_misdn_log(2, port, " --> %s: Unknown\n", type);
                break;
                /* Maybe we should cut off the prefix if present ? */
        default:
@@ -1670,8 +1904,6 @@ void debug_numplan(int port, int numplan, char *type)
 }
 
 
-
-
 #ifdef MISDN_1_2
 static int update_pipeline_config(struct misdn_bchannel *bc)
 {
@@ -1682,11 +1914,11 @@ static int update_pipeline_config(struct misdn_bchannel *bc)
        if (*bc->pipeline)
                return 0;
 
-       misdn_cfg_get(bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
+       misdn_cfg_get(bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(ec));
        if (ec == 1)
-               snprintf(bc->pipeline, sizeof(bc->pipeline) - 1, "mg2ec");
+               ast_copy_string(bc->pipeline, "mg2ec", sizeof(bc->pipeline));
        else if (ec > 1)
-               snprintf(bc->pipeline, sizeof(bc->pipeline) - 1, "mg2ec(deftaps=%d)", ec);
+               snprintf(bc->pipeline, sizeof(bc->pipeline), "mg2ec(deftaps=%d)", ec);
 
        return 0;
 }
@@ -1694,15 +1926,15 @@ static int update_pipeline_config(struct misdn_bchannel *bc)
 static int update_ec_config(struct misdn_bchannel *bc)
 {
        int ec;
-       int port=bc->port;
-               
-       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;
+       int port = bc->port;
+
+       misdn_cfg_get(port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(ec));
+
+       if (ec == 1) {
+               bc->ec_enable = 1;
+       } else if (ec > 1) {
+               bc->ec_enable = 1;
+               bc->ec_deftaps = ec;
        }
 
        return 0;
@@ -1710,79 +1942,81 @@ static int update_ec_config(struct misdn_bchannel *bc)
 #endif
 
 
-static int read_config(struct chan_list *ch, int orig) {
+static int read_config(struct chan_list *ch, int orig)
+{
+       struct ast_channel *ast;
+       struct misdn_bchannel *bc;
+       int port, hdlc = 0;
+       char lang[BUFFERSIZE + 1], localmusicclass[BUFFERSIZE + 1], faxdetect[BUFFERSIZE + 1];
+       char buf[256], buf2[256];
+       ast_group_t pg, cg;
 
        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 = ch->ast;
+       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(1,port,"read_config: Getting Config\n");
-
-       char lang[BUFFERSIZE+1];
-       
+       port = bc->port;
+       chan_misdn_log(1, port, "read_config: Getting Config\n");
 
-       misdn_cfg_get( port, MISDN_CFG_LANGUAGE, lang, BUFFERSIZE);
+       misdn_cfg_get(port, MISDN_CFG_LANGUAGE, lang, sizeof(lang));
        ast_string_field_set(ast, language, lang);
 
-       char localmusicclass[BUFFERSIZE+1];
-       
-       misdn_cfg_get( port, MISDN_CFG_MUSICCLASS, localmusicclass, BUFFERSIZE);
+       misdn_cfg_get(port, MISDN_CFG_MUSICCLASS, localmusicclass, sizeof(localmusicclass));
        ast_string_field_set(ast, musicclass, localmusicclass);
-       
-       
-       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_NTTIMEOUT, &ch->nttimeout, sizeof(int));
-       
-       misdn_cfg_get( port, MISDN_CFG_NOAUTORESPOND_ON_SETUP, &ch->noautorespond_on_setup, sizeof(int));
-       
-       misdn_cfg_get( port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(int));
+       misdn_cfg_get(port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(bc->txgain));
+       misdn_cfg_get(port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(bc->rxgain));
 
-       misdn_cfg_get( port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, BUFFERSIZE);
-       
-       char faxdetect[BUFFERSIZE+1];
-       misdn_cfg_get( port, MISDN_CFG_FAXDETECT, faxdetect, BUFFERSIZE);
-       
-       int hdlc=0;
-       misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
+       misdn_cfg_get(port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(ch->incoming_early_audio));
+
+       misdn_cfg_get(port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(bc->send_dtmf));
        
+       misdn_cfg_get( port, MISDN_CFG_ASTDTMF, &ch->ast_dsp, sizeof(int));
+
+       if (ch->ast_dsp) {
+               ch->ignore_dtmf=1;
+       }
+
+       misdn_cfg_get(port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(bc->need_more_infos));
+       misdn_cfg_get(port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(ch->nttimeout));
+
+       misdn_cfg_get(port, MISDN_CFG_NOAUTORESPOND_ON_SETUP, &ch->noautorespond_on_setup, sizeof(ch->noautorespond_on_setup));
+
+       misdn_cfg_get(port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(ch->far_alerting));
+
+       misdn_cfg_get(port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, sizeof(ch->allowed_bearers));
+
+       misdn_cfg_get(port, MISDN_CFG_FAXDETECT, faxdetect, sizeof(faxdetect));
+
+       misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(hdlc));
+
        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;
+                       chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
+                       bc->hdlc = 1;
                        break;
                }
                
        }
        /*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));        
+       misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(ch->jb_len));
+       misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(ch->jb_upper_threshold));
+
+       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));
 
 #ifdef MISDN_1_2
        update_pipeline_config(bc);
@@ -1790,131 +2024,103 @@ static int read_config(struct chan_list *ch, int orig) {
        update_ec_config(bc);
 #endif
 
-       {
-               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;
-       }
+       misdn_cfg_get(bc->port, MISDN_CFG_EARLY_BCONNECT, &bc->early_bconnect, sizeof(bc->early_bconnect));
+
+       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(buf2, sizeof(buf2), 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));
-               
+       if (orig == ORG_AST) {
+               char callerid[BUFFERSIZE + 1];
+
+               misdn_cfg_get(port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(bc->te_choose_channel));
+
                if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) {
                        if (strstr(faxdetect, "nojump"))
-                               ch->faxdetect=2;
+                               ch->faxdetect = 2;
                        else
-                               ch->faxdetect=1;
+                               ch->faxdetect = 1;
                }
 
-               {
-                       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;
-                               }
-
-                       }
-
-                       
-                       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");
+               misdn_cfg_get(port, MISDN_CFG_CALLERID, callerid, sizeof(callerid));
+               if ( ! ast_strlen_zero(callerid) ) {
+                       chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
+                       ast_copy_string(bc->oad, callerid, sizeof(bc->oad));
                }
 
+               misdn_cfg_get(port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(bc->dnumplan));
+               misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(bc->onumplan));
+               misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(bc->cpnnumplan));
+               debug_numplan(port, bc->dnumplan, "TON");
+               debug_numplan(port, bc->onumplan, "LTON");
+               debug_numplan(port, bc->cpnnumplan, "CTON");
+
                ch->overlap_dial = 0;
        } else { /** ORIGINATOR MISDN **/
+               char prefix[BUFFERSIZE + 1] = "";
+
                if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
                        if (strstr(faxdetect, "nojump"))
-                               ch->faxdetect=2;
+                               ch->faxdetect = 2;
                        else
-                               ch->faxdetect=1;
+                               ch->faxdetect = 1;
                }
-       
-               misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
-               debug_numplan(port, bc->cpnnumplan,"CTON");
-               
-               char prefix[BUFFERSIZE+1]="";
-               switch( bc->onumplan ) {
+
+               misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(bc->cpnnumplan));
+               debug_numplan(port, bc->cpnnumplan, "CTON");
+
+               switch (bc->onumplan) {
                case NUMPLAN_INTERNATIONAL:
-                       misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
+                       misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, sizeof(prefix));
                        break;
-                       
+
                case NUMPLAN_NATIONAL:
-                       misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
+                       misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, sizeof(prefix));
                        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);
-               }
-               
+
+               ast_copy_string(buf, bc->oad, sizeof(buf));
+               snprintf(bc->oad, sizeof(bc->oad), "%s%s", prefix, buf);
+
                if (!ast_strlen_zero(bc->dad)) {
-                       ast_copy_string(bc->orig_dad,bc->dad, sizeof(bc->orig_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));
+                       ast_copy_string(bc->dad, bc->keypad, sizeof(bc->dad));
                }
 
                prefix[0] = 0;
-               
-               switch( bc->dnumplan ) {
+
+               switch (bc->dnumplan) {
                case NUMPLAN_INTERNATIONAL:
-                       misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
+                       misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, sizeof(prefix));
                        break;
                case NUMPLAN_NATIONAL:
-                       misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
+                       misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, sizeof(prefix));
                        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);
-               }
-               
-               if ( strcmp(bc->dad,ast->exten)) {
+
+               ast_copy_string(buf, bc->dad, sizeof(buf));
+               snprintf(bc->dad, sizeof(bc->dad), "%s%s", prefix, buf);
+
+               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) ) {
                        if (ast->cid.cid_rdnis)
-                               free(ast->cid.cid_rdnis);
-                       ast->cid.cid_rdnis = strdup(bc->rad);
+                               ast_free(ast->cid.cid_rdnis);
+                       ast->cid.cid_rdnis = ast_strdup(bc->rad);
                }
        
                misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
@@ -1923,14 +2129,18 @@ static int read_config(struct chan_list *ch, int orig) {
 
        ch->overlap_dial_task = -1;
        
-       if (ch->faxdetect) {
-               misdn_cfg_get( port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
+       if (ch->faxdetect  || ch->ast_dsp) {
+               misdn_cfg_get(port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
                if (!ch->dsp)
                        ch->dsp = ast_dsp_new();
-               if (ch->dsp)
-                       ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT | DSP_FEATURE_FAX_DETECT);
+               if (ch->dsp) {
+                       if (ch->faxdetect) 
+                               ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_FAX_DETECT);
+                       else 
+                               ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT );
+               }
                if (!ch->trans)
-                       ch->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
+                       ch->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
        }
 
        /* AOCD initialization */
@@ -1946,27 +2156,24 @@ static int read_config(struct chan_list *ch, int orig) {
 
 static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
 {
-       int port=0;
+       int port = 0;
        int r;
-       struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
+       int exceed;
+       int bridging;
+       struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(ast);
        struct misdn_bchannel *newbc;
-       char *opts=NULL, *ext,*tokb;
-       char dest_cp[256];
+       char *opts = NULL, *ext, *tokb;
+       char *dest_cp = ast_strdupa(dest);
 
-       {
-               strncpy(dest_cp,dest,sizeof(dest_cp)-1);
-               dest_cp[sizeof(dest_cp)]=0;
-               
-               ext=strtok_r(dest_cp,"/",&tokb);
-               
+       ext = strtok_r(dest_cp, "/", &tokb);
+
+       if (ext) {
+               ext = strtok_r(NULL, "/", &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;
-                       }
+                       opts = strtok_r(NULL, "/", &tokb);
+               } else {
+                       chan_misdn_log(0, 0, "misdn_call: No Extension given!\n");
+                       return -1;
                }
        }
 
@@ -1977,125 +2184,107 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
 
        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->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
                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->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
                ast_setstate(ast, AST_STATE_DOWN);
                return -1;
        }
        
-       newbc=ch->bc;
+       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->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
                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));
+       port = newbc->port;
 
-       int exceed;
-       if ((exceed=add_out_calls(port))) {
+       if ((exceed = add_out_calls(port))) {
                char tmp[16];
-               sprintf(tmp,"%d",exceed);
-               pbx_builtin_setvar_helper(ast,"MAX_OVERFLOW",tmp);
+               snprintf(tmp, sizeof(tmp), "%d", exceed);
+               pbx_builtin_setvar_helper(ast, "MAX_OVERFLOW", tmp);
                return -1;
        }
        
-       chan_misdn_log(1, port, "* CALL: %s\n",dest);
+       chan_misdn_log(1, port, "* CALL: %s\n", dest);
        
-       chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
+       chan_misdn_log(2, 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);
+       chan_misdn_log(3, port, " --> * adding2newbc ext %s\n", ast->exten);
        if (ast->exten) {
-               int l = sizeof(newbc->dad);
-               strncpy(newbc->dad,ast->exten, l);
-               newbc->dad[l-1] = 0;
+               ast_copy_string(ast->exten, ext, sizeof(ast->exten));
+               ast_copy_string(newbc->dad, ext, sizeof(newbc->dad));
        }
 
-       if (ast->cid.cid_rdnis)  
-               strcpy(newbc->rad, ast->cid.cid_rdnis);
-       else 
-               newbc->rad[0]=0;
+       ast_copy_string(newbc->rad, S_OR(ast->cid.cid_rdnis, ""), sizeof(newbc->rad));
 
-       chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",ast->cid.cid_num);
-       if (ast_strlen_zero(newbc->oad) && ast->cid.cid_num ) {
+       chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n", ast->cid.cid_num);
+       if (ast_strlen_zero(newbc->oad) && !ast_strlen_zero(ast->cid.cid_num)) {
+               ast_copy_string(newbc->oad, ast->cid.cid_num, sizeof(newbc->oad));
+       }
 
-               if (ast->cid.cid_num) {
-                       int l = sizeof(newbc->oad);
-                       strncpy(newbc->oad,ast->cid.cid_num, l);
-                       newbc->oad[l-1] = 0;
-               }
+       newbc->capability = ast->transfercapability;
+       pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc->capability));
+       if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
+               chan_misdn_log(2, port, " --> * Call with flag Digital\n");
        }
-       
-       {
-               struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
-               if (!ch) { ast_verbose("No chan_list in misdn_call\n"); return -1;}
-               
-               newbc->capability=ast->transfercapability;
-               pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability));
-               if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
-                       chan_misdn_log(2, port, " --> * Call with flag Digital\n");
-               }
-               
 
-               /* update screening and presentation */ 
-               update_config(ch,ORG_AST);
-               
-               /* fill in some ies from channel vary*/
-               import_ch(ast, newbc, ch);
+       /* update screening and presentation */ 
+       update_config(ch, ORG_AST);
                
-               /* Finally The Options Override Everything */
-               if (opts)
-                       misdn_set_opt_exec(ast,opts);
-               else
-                       chan_misdn_log(2,port,"NO OPTS GIVEN\n");
+       /* 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(2, port, "NO OPTS GIVEN\n");
 
-               /*check for bridging*/
-               int bridging;
-               misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
-               if (bridging && ch->other_ch) {
+       /*check for bridging*/
+       misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
+       if (bridging && ch->other_ch) {
 #ifdef MISDN_1_2
-                       chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n");
-                       *ch->bc->pipeline=0;
-                       *ch->other_ch->bc->pipeline=0;
+               chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n");
+               *ch->bc->pipeline = 0;
+               *ch->other_ch->bc->pipeline = 0;
 #else
-                       chan_misdn_log(1, port, "Disabling EC on both Sides\n");
-                       ch->bc->ec_enable=0;
-                       ch->other_ch->bc->ec_enable=0;
+               chan_misdn_log(1, port, "Disabling EC on both Sides\n");
+               ch->bc->ec_enable = 0;
+               ch->other_ch->bc->ec_enable = 0;
 #endif
-               }
-               
-               r=misdn_lib_send_event( newbc, EVENT_SETUP );
-               
-               /** we should have l3id after sending setup **/
-               ch->l3id=newbc->l3_id;
        }
-       
+
+       r = misdn_lib_send_event( newbc, EVENT_SETUP );
+
+       /** we should have l3id after sending setup **/
+       ch->l3id = newbc->l3_id;
+
        if ( r == -ENOCHAN  ) {
                chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
-               chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n",newbc?newbc->pid:-1);
-               ast->hangupcause=34;
+               chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n", newbc ? newbc->pid : -1);
+               ast->hangupcause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
                ast_setstate(ast, AST_STATE_DOWN);
                return -1;
        }
        
-       chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
+       chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n", newbc ? newbc->pid : 1);
 
        ast_setstate(ast, AST_STATE_DIALING);
-       ast->hangupcause=16;
+       ast->hangupcause = AST_CAUSE_NORMAL_CLEARING;
        
-       if (newbc->nt) stop_bc_tones(ch);
+       if (newbc->nt)
+               stop_bc_tones(ch);
 
-       ch->state=MISDN_CALLING;
+       ch->state = MISDN_CALLING;
        
        return 0; 
 }
@@ -2104,60 +2293,51 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
 static int misdn_answer(struct ast_channel *ast)
 {
        struct chan_list *p;
+       const char *tmp;
 
+       if (!ast || ! (p = MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
        
-       if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
-       
-       chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n");
+       chan_misdn_log(1, p ? (p->bc ? p->bc->port : 0) : 0, "* ANSWER:\n");
        
        if (!p) {
                ast_log(LOG_WARNING, " --> Channel not connected ??\n");
-               ast_queue_hangup(ast);
+               ast_queue_hangup_with_cause(ast, AST_CAUSE_NETWORK_OUT_OF_ORDER);
        }
 
        if (!p->bc) {
                chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
 
-               ast_queue_hangup(ast);
+               ast_queue_hangup_with_cause(ast, AST_CAUSE_PROTOCOL_ERROR);
        }
 
-       {
-               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");
-                       {
-                               int l = sizeof(p->bc->crypt_key);
-                               strncpy(p->bc->crypt_key,tmp_key, l);
-                               p->bc->crypt_key[l-1] = 0;
-                       }
-               } else {
-                       chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
-               }
-    
+       tmp = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
+
+       if (!ast_strlen_zero(tmp)) {
+               chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
+               ast_copy_string(p->bc->crypt_key, tmp, sizeof(p->bc->crypt_key));
+       } else {
+               chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
        }
 
-       {
-               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->nodsp=1;
-                       p->bc->hdlc=0;
-                       p->bc->nojitter=1;
-               }
+       tmp = pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
+       if (!ast_strlen_zero(tmp) && ast_true(tmp)) {
+               chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
+               p->bc->nodsp = 1;
+               p->bc->hdlc = 0;
+               p->bc->nojitter = 1;
        }
-       
+
        p->state = MISDN_CONNECTED;
        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));
+               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;
 }
 
@@ -2170,57 +2350,42 @@ static int misdn_digit_begin(struct ast_channel *chan, char digit)
 static int misdn_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
 {
        struct chan_list *p;
+       struct misdn_bchannel *bc;
+       char buf[2] = { digit, 0 };
        
        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);
+       bc = p->bc;
+       chan_misdn_log(1, bc ? bc->port : 0, "* IND : Digit %c\n", digit);
        
        if (!bc) {
-               ast_log(LOG_WARNING, " --> !! Got Digit Event withut having bchannel Object\n");
+               ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n");
                return -1;
        }
        
        switch (p->state ) {
-               case MISDN_CALLING:
-               {
-                       
-                       char buf[8];
-                       buf[0]=digit;
-                       buf[1]=0;
-                       
-                       int l = sizeof(bc->infos_pending);
-                       strncat(bc->infos_pending,buf,l);
-                       bc->infos_pending[l-1] = 0;
-               }
+       case MISDN_CALLING:
+               if (strlen(bc->infos_pending) < sizeof(bc->infos_pending) - 1)
+                       strncat(bc->infos_pending, buf, sizeof(bc->infos_pending) - strlen(bc->infos_pending) - 1);
                break;
-               case MISDN_CALLING_ACKNOWLEDGE:
-               {
-                       bc->info_dad[0]=digit;
-                       bc->info_dad[1]=0;
-                       
-                       {
-                               int l = sizeof(bc->dad);
-                               strncat(bc->dad,bc->info_dad, l - strlen(bc->dad));
-                               bc->dad[l-1] = 0;
-               }
-                       {
-                               int l = sizeof(p->ast->exten);
-                               strncpy(p->ast->exten, bc->dad, l);
-                               p->ast->exten[l-1] = 0;
-                       }
-                       
-                       misdn_lib_send_event( bc, EVENT_INFORMATION);
-               }
+       case MISDN_CALLING_ACKNOWLEDGE:
+               ast_copy_string(bc->info_dad, buf, sizeof(bc->info_dad));
+               if (strlen(bc->dad) < sizeof(bc->dad) - 1)
+                       strncat(bc->dad, buf, sizeof(bc->dad) - strlen(bc->dad) - 1);
+               ast_copy_string(p->ast->exten, bc->dad, sizeof(p->ast->exten));
+               misdn_lib_send_event( bc, EVENT_INFORMATION);
                break;
-               
-               default:
-                       if ( bc->send_dtmf ) {
+       default:        
+                       /* Do not send Digits in CONNECTED State, when
+                        * the other side is too mISDN. */
+                       if (p->other_ch ) 
+                               return 0;
+
+                       if ( bc->send_dtmf ) 
                                send_digit_to_chan(p,digit);
-                       }
                break;
-       }
-       
+}
+
        return 0;
 }
 
@@ -2228,13 +2393,13 @@ static int misdn_digit_end(struct ast_channel *ast, char digit, unsigned int dur
 static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
 {
        struct chan_list *p;
-       
+
        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 L3id:%x\n", misdn_get_ch_state(p), p->l3id);
-       
-       p->ast = ast ;
-  
+
+       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;
+
        return 0;
 }
 
@@ -2244,26 +2409,25 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
 {
        struct chan_list *p;
 
-  
        if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
-               ast_log(LOG_WARNING, "Returnded -1 in misdn_indication\n");
+               ast_log(LOG_WARNING, "Returned -1 in misdn_indication\n");
                return -1;
        }
        
        if (!p->bc ) {
-               chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten);
+               chan_misdn_log(1, 0, "* IND : Indication from %s\n", ast->exten);
                ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
                return -1;
        }
        
-       chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] from %s\n",cond, ast->exten);
+       chan_misdn_log(5, 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 pid:%d\n",p->bc?p->bc->pid:-1);
-               ast_setstate(ast,AST_STATE_BUSY);
+               chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc ? p->bc->pid : -1);
+               ast_setstate(ast, AST_STATE_BUSY);
 
-               p->bc->out_cause=17;
+               p->bc->out_cause = AST_CAUSE_USER_BUSY;
                if (p->state != MISDN_CONNECTED) {
                        start_bc_tones(p);
                        misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
@@ -2271,75 +2435,69 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
                        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);
+               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:
-               chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
+               chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
                switch (p->state) {
-                       case MISDN_ALERTING:
-                               chan_misdn_log(2, 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(2, 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(2, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
-                               misdn_lib_send_event( p->bc, EVENT_ALERTING);
+               case MISDN_ALERTING:
+                       chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n", p->bc ? p->bc->pid : -1);
+                       break;
+               case MISDN_CONNECTED:
+                       chan_misdn_log(2, 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;
+               default:
+                       p->state = MISDN_ALERTING;
+                       chan_misdn_log(2, 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(2,p->bc->port, " --> other End is mISDN and has inband info available\n");
-                                               break;
-                                       }
+                       if (p->other_ch && p->other_ch->bc) {
+                               if (misdn_inband_avail(p->other_ch->bc)) {
+                                       chan_misdn_log(2, p->bc->port, " --> other End is mISDN and has inband info available\n");
+                                       break;
+                               }
 
-                                       if (!p->other_ch->bc->nt) {
-                                               chan_misdn_log(2,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
-                                               break;
-                                       }
+                               if (!p->other_ch->bc->nt) {
+                                       chan_misdn_log(2, p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
+                                       break;
                                }
+                       }
 
-                               chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
-                               ast_setstate(ast,AST_STATE_RINGING);
+                       chan_misdn_log(3, 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->originator==ORG_MISDN) && !p->incoming_early_audio ) 
-                                       chan_misdn_log(2,p->bc->port, " --> incoming_early_audio off\n");
-                               else 
-                                       return -1;
+                       if ( !p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio ) 
+                               chan_misdn_log(2, p->bc->port, " --> incoming_early_audio off\n");
+                       else 
+                               return -1;
                }
                break;
        case AST_CONTROL_ANSWER:
-               chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1);
+               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);
+               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);
+               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);
+               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);
+               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);
+               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);
+               chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc ? p->bc->pid : -1);
 
-               p->bc->out_cause=42;
+               p->bc->out_cause = AST_CAUSE_SWITCH_CONGESTION;
                start_bc_tones(p);
                misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
 
@@ -2348,23 +2506,23 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
                }
                break;
        case -1 :
-               chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) 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);
+               ast_moh_start(ast,data,ast->musicclass); 
+               chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
                break;
        case AST_CONTROL_UNHOLD:
-               chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
+               ast_moh_stop(ast);
+               chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
                break;
        default:
-               chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
+               chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc ? p->bc->pid : -1);
        }
   
        return 0;
@@ -2373,22 +2531,31 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
 static int misdn_hangup(struct ast_channel *ast)
 {
        struct chan_list *p;
-       struct misdn_bchannel *bc=NULL;
+       struct misdn_bchannel *bc = NULL;
+       const char *varcause = NULL;
+
+       ast_debug(1, "misdn_hangup(%s)\n", ast->name);
 
-       if (option_debug)
-               ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
-       
        if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
-       
+
        if (!p) {
                chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
                return 0 ;
        }
-       
-       bc=p->bc;
 
-       MISDN_ASTERISK_TECH_PVT(ast)=NULL;
-       p->ast=NULL;
+       bc = p->bc;
+
+       if (bc) {
+               const char *tmp=pbx_builtin_getvar_helper(ast,"MISDN_USERUSER");
+               if (tmp) {
+                       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
+                       strcpy(bc->uu, tmp);
+                       bc->uulen=strlen(bc->uu);
+               }
+       }
+
+       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
+       p->ast = NULL;
 
        if (ast->_state == AST_STATE_RESERVED || 
                p->state == MISDN_NOTHING || 
@@ -2397,14 +2564,15 @@ static int misdn_hangup(struct ast_channel *ast)
 
                CLEAN_CH:
                /* between request and call */
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "State Reserved (or nothing) => chanIsAvail\n");
-               MISDN_ASTERISK_TECH_PVT(ast)=NULL;
-               
+               ast_debug(1, "State Reserved (or nothing) => chanIsAvail\n");
+               MISDN_ASTERISK_TECH_PVT(ast) = NULL;
+       
+               ast_mutex_lock(&release_lock);
                cl_dequeue_chan(&cl_te, p);
                close(p->pipe[0]);
                close(p->pipe[1]);
-               free(p);
+               ast_free(p);
+               ast_mutex_unlock(&release_lock);
                
                if (bc)
                        misdn_lib_release(bc);
@@ -2413,122 +2581,124 @@ static int misdn_hangup(struct ast_channel *ast)
        }
 
        if (!bc) {
-               ast_log(LOG_WARNING,"Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id);
+               ast_log(LOG_WARNING, "Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id);
                goto CLEAN_CH;
        }
 
 
-       p->need_hangup=0;
-       p->need_queue_hangup=0;
-       p->need_busy=0;
+       p->need_hangup = 0;
+       p->need_queue_hangup = 0;
+       p->need_busy = 0;
 
 
        if (!p->bc->nt) 
                stop_bc_tones(p);
 
-       
-       {
-               const char *varcause=NULL;
-               bc->out_cause=ast->hangupcause?ast->hangupcause:16;
+       bc->out_cause = ast->hangupcause ? ast->hangupcause : AST_CAUSE_NORMAL_CLEARING;
                
-               if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
-                    (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
-                       int tmpcause=atoi(varcause);
-                       bc->out_cause=tmpcause?tmpcause:16;
-               }
+       if ( (varcause = pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
+            (varcause = pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
+               int tmpcause = atoi(varcause);
+               bc->out_cause = tmpcause ? tmpcause : AST_CAUSE_NORMAL_CLEARING;
+       }
     
-               chan_misdn_log(1, bc->port, "* IND : HANGUP\tpid:%d ctx:%s dad:%s oad:%s State:%s\n",p->bc?p->bc->pid:-1, ast->context, ast->exten, ast->cid.cid_num, misdn_get_ch_state(p));
-               chan_misdn_log(3, bc->port, " --> l3id:%x\n",p->l3id);
-               chan_misdn_log(3, bc->port, " --> cause:%d\n",bc->cause);
-               chan_misdn_log(2, bc->port, " --> out_cause:%d\n",bc->out_cause);
-               chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
-               
-               switch (p->state) {
-               case MISDN_INCOMING_SETUP:
-               case MISDN_CALLING:
-                       p->state=MISDN_CLEANING;
-                       misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
-                       break;
-               case MISDN_HOLDED:
-               case MISDN_DIALING:
-                       start_bc_tones(p);
-                       hanguptone_indicate(p);
+       chan_misdn_log(1, bc->port, "* IND : HANGUP\tpid:%d ctx:%s dad:%s oad:%s State:%s\n", p->bc ? p->bc->pid : -1, ast->context, ast->exten, ast->cid.cid_num, misdn_get_ch_state(p));
+       chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
+       chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
+       chan_misdn_log(2, bc->port, " --> out_cause:%d\n", bc->out_cause);
+       chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
+
+       switch (p->state) {
+       case MISDN_INCOMING_SETUP:
+       case MISDN_CALLING:
+               p->state = MISDN_CLEANING;
+               /* This is the only place in misdn_hangup, where we 
+                * can call release_chan, else it might create lot's of trouble
+                * */
+               ast_log(LOG_NOTICE, "release channel, in CALLING/INCOMING_SETUP state.. no other events happened\n");
+               release_chan(bc);
+               misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
+               break;
+       case MISDN_HOLDED:
+       case MISDN_DIALING:
+               start_bc_tones(p);
+               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);
+               p->state=MISDN_CLEANING;
+               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;
+               if (bc->need_disconnect)
+                       misdn_lib_send_event( bc, EVENT_DISCONNECT);
+               break;
       
-               case MISDN_ALERTING:
-               case MISDN_PROGRESS:
-               case MISDN_PROCEEDING:
-                       if (p->originator != ORG_AST) 
-                               hanguptone_indicate(p);
+       case MISDN_ALERTING:
+       case MISDN_PROGRESS:
+       case MISDN_PROCEEDING:
+               if (p->originator != ORG_AST) 
+                       hanguptone_indicate(p);
       
-                       /*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 */
-                       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;*/
+               if (bc->need_disconnect)
+                       misdn_lib_send_event( bc, EVENT_DISCONNECT);
+               break;
+       case MISDN_CONNECTED:
+       case MISDN_PRECONNECTED:
+               /*  Alerting or Disconnect */
+               if (p->bc->nt) {
+                       start_bc_tones(p);
+                       hanguptone_indicate(p);
+                       p->bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
+               }
+               if (bc->need_disconnect)
+                       misdn_lib_send_event( bc, EVENT_DISCONNECT);
 
-                       /*p->state=MISDN_CLEANING;*/
-                       break;
-               case MISDN_DISCONNECTED:
+               /*p->state=MISDN_CLEANING;*/
+               break;
+       case MISDN_DISCONNECTED:
+               if (bc->need_release)
                        misdn_lib_send_event( bc, EVENT_RELEASE);
-                       p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
-                       break;
+               p->state = MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
+               break;
 
-               case MISDN_RELEASED:
-               case MISDN_CLEANING:
-                       p->state=MISDN_CLEANING;
-                       break;
+       case MISDN_RELEASED:
+       case MISDN_CLEANING:
+               p->state = MISDN_CLEANING;
+               break;
 
-               case MISDN_BUSY:
-                       break;
+       case MISDN_BUSY:
+               break;
       
-               case MISDN_HOLD_DISCONNECT:
-                       /* need to send release here */
-                       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:
-                       if (bc->nt) {
-                               bc->out_cause=-1;
+       case MISDN_HOLD_DISCONNECT:
+               /* need to send release here */
+               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;
+               if (bc->need_release)
+                       misdn_lib_send_event(bc, EVENT_RELEASE);
+               p->state = MISDN_CLEANING;
+               break;
+       default:
+               if (bc->nt) {
+                       bc->out_cause = -1;
+                       if (bc->need_release)
                                misdn_lib_send_event(bc, EVENT_RELEASE);
-                               p->state=MISDN_CLEANING; 
-                       } else {
-                               if (bc->need_disconnect)
-                                       misdn_lib_send_event(bc, EVENT_DISCONNECT);
-                       }
+                       p->state = MISDN_CLEANING; 
+               } else {
+                       if (bc->need_disconnect)
+                               misdn_lib_send_event(bc, EVENT_DISCONNECT);
                }
+       }
 
-               p->state=MISDN_CLEANING;
+       p->state = MISDN_CLEANING;
     
-       }
-       
+       chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n", ast->name, misdn_get_ch_state(p));
 
-       chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n",ast->name,misdn_get_ch_state(p));
-       
        return 0;
 }
 
@@ -2545,12 +2715,10 @@ static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame
                return NULL;
        }
 
        if (!f || (f->frametype != AST_FRAME_DTMF))
                return frame;
  
-       if (option_debug)
-               ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c\n", f->subclass);
+       ast_debug(1, "Detected inband DTMF digit: %c\n", f->subclass);
  
        if (tmp->faxdetect && (f->subclass == 'f')) {
                /* Fax tone -- Handle and return NULL */
@@ -2577,8 +2745,7 @@ static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame
                                        misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
                                        context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
                                        if (ast_exists_extension(ast, context, "fax", 1, ast->cid.cid_num)) {
-                                               if (option_verbose > 2)
-                                                       ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
+                                               ast_verb(3, "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
                                                /* 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, context, "fax", 1))
@@ -2586,17 +2753,15 @@ static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame
                                        } else
                                                ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
                                } else {
-                                       if (option_debug)
-                                               ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
+                                       ast_debug(1, "Already in a fax extension, not redirecting\n");
                                }
                                break;
                        case 2:
-                               ast_verbose(VERBOSE_PREFIX_3 "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
+                               ast_verb(3, "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
                                break;
                        }
                } else {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "Fax already handled\n");
+                       ast_debug(1, "Fax already handled\n");
                }
        }
        
@@ -2604,67 +2769,92 @@ static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame
                chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass);
        }
 
-       return frame;
+       return f;
 }
 
 
-static 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;
-       
+       fd_set rrfs;
+       struct timeval tv;
+       int len, t;
+
        if (!ast) {
-               chan_misdn_log(1,0,"misdn_read called without ast\n");
+               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=MISDN_ASTERISK_TECH_PVT(ast))) {
-               chan_misdn_log(1,0,"misdn_read called without ast->pvt\n");
+
+       if (!tmp->bc && !(tmp->state == MISDN_HOLDED)) {
+               chan_misdn_log(1, 0, "misdn_read called without bc\n");
                return NULL;
        }
 
-       if (!tmp->bc && !(tmp->state==MISDN_HOLDED)) {
-               chan_misdn_log(1,0,"misdn_read called without bc\n");
+       tv.tv_sec=0;
+       tv.tv_usec=20000;
+
+       FD_ZERO(&rrfs);
+       FD_SET(tmp->pipe[0],&rrfs);
+
+       t=select(FD_SETSIZE,&rrfs,NULL, NULL,&tv);
+
+       if (!t) {
+               chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n");
+               len=160;
+       }
+
+       if (t<0) {
+               chan_misdn_log(-1, tmp->bc->port, "Select Error (err=%s)\n",strerror(errno));
                return NULL;
        }
 
-       len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
+       if (FD_ISSET(tmp->pipe[0],&rrfs)) {
+               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;
+               }
 
-       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");
+       } else {
                return NULL;
        }
 
-       tmp->frame.frametype  = AST_FRAME_VOICE;
+       tmp->frame.frametype = AST_FRAME_VOICE;
        tmp->frame.subclass = AST_FORMAT_ALAW;
        tmp->frame.datalen = len;
        tmp->frame.samples = len;
        tmp->frame.mallocd = 0;
        tmp->frame.offset = 0;
-       tmp->frame.delivery= ast_tv(0,0) ;
+       tmp->frame.delivery = ast_tv(0,0);
        tmp->frame.src = NULL;
-       tmp->frame.data = tmp->ast_rd_buf;
+       tmp->frame.data.ptr = tmp->ast_rd_buf;
 
        if (tmp->faxdetect && !tmp->faxhandled) {
                if (tmp->faxdetect_timeout) {
                        if (ast_tvzero(tmp->faxdetect_tv)) {
                                tmp->faxdetect_tv = ast_tvnow();
-                               chan_misdn_log(2,tmp->bc->port,"faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
+                               chan_misdn_log(2, tmp->bc->port, "faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
                                return process_ast_dsp(tmp, &tmp->frame);
                        } else {
                                struct timeval tv_now = ast_tvnow();
                                int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
                                if (diff <= (tmp->faxdetect_timeout * 1000)) {
-                                       chan_misdn_log(5,tmp->bc->port,"faxdetect: detecting ...\n");
+                                       chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ...\n");
                                        return process_ast_dsp(tmp, &tmp->frame);
                                } else {
-                                       chan_misdn_log(2,tmp->bc->port,"faxdetect: stopping detection (time ran out) ...\n");
+                                       chan_misdn_log(2, tmp->bc->port, "faxdetect: stopping detection (time ran out) ...\n");
                                        tmp->faxdetect = 0;
                                        return &tmp->frame;
                                }
                        }
                } else {
-                       chan_misdn_log(5,tmp->bc->port,"faxdetect: detecting ... (no timeout)\n");
+                       chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ... (no timeout)\n");
                        return process_ast_dsp(tmp, &tmp->frame);
                }
        } else {
@@ -2681,7 +2871,7 @@ static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
        struct chan_list *ch;
        int i  = 0;
        
-       if (!ast || ! (ch=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
+       if (!ast || ! (ch = MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
 
        if (ch->state == MISDN_HOLDED) {
                chan_misdn_log(7, 0, "misdn_write: Returning because holded\n");
@@ -2694,26 +2884,37 @@ static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
        }
        
        if (ch->notxtone) {
-               chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxone\n");
+               chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
                return 0;
        }
 
 
-       if ( !frame->subclass) {
+       if (!frame->subclass) {
                chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
                return 0;
        }
        
-       if ( !(frame->subclass & prefformat)) {
+       if (!(frame->subclass & prefformat)) {
                
                chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
                return 0;
        }
        
 
-       if ( !frame->samples ) {
+       if (!frame->samples ) {
                chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
-               return 0;
+               
+               if (!strcmp(frame->src,"ast_prod")) {
+                       chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
+
+                       if (ch->ts) {
+                               chan_misdn_log(4, ch->bc->port, "Starting Playtones\n");
+                               misdn_lib_tone_generator_start(ch->bc);
+                       }
+                       return 0;
+               }
+
+               return -1;
        }
 
        if ( ! ch->bc->addr ) {
@@ -2723,49 +2924,45 @@ static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
        
 #ifdef MISDN_DEBUG
        {
-               int i, max=5>frame->samples?frame->samples:5;
-               
-               printf("write2mISDN %p %d bytes: ", p, frame->samples);
-               
-               for (i=0; i<  max ; i++) printf("%2.2x ",((char*) frame->data)[i]);
-               printf ("\n");
+               int i, max = 5 > frame->samples ? frame->samples : 5;
+
+               ast_debug(1, "write2mISDN %p %d bytes: ", p, frame->samples);
+
+               for (i = 0; i < max ; i++)
+                       ast_debug(1, "%2.2x ", ((char*) frame->data.ptr)[i]);
        }
 #endif
 
-
        switch (ch->bc->bc_state) {
-               case BCHAN_ACTIVATED:
-               case BCHAN_BRIDGED:
-                       break;
-               default:
+       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 l3id:%x\n",frame->samples,ch->bc->addr, ast->exten, ast->cid.cid_num,misdn_get_ch_state( ch), ch->bc->bc_state, ch->bc->l3_id);
+                       chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) dropping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n", frame->samples, ch->bc->addr, ast->exten, ast->cid.cid_num, misdn_get_ch_state( ch), ch->bc->bc_state, ch->bc->l3_id);
                
                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);
-
+                       ch->dropped_frame_cnt = 0;
+                       chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) dropping: %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);
+       chan_misdn_log(9, ch->bc->port, "Sending :%d bytes to 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) {
+               /* Buffered Transmit (triggered by read from isdn side)*/
+               if (misdn_jb_fill(ch->jb, frame->data.ptr, frame->samples) < 0) {
                        if (ch->bc->active)
-                               cb_log(0,ch->bc->port,"Misdn Jitterbuffer Overflow.\n");
+                               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);
+               i=misdn_lib_tx2misdn_frm(ch->bc, frame->data.ptr, frame->samples);
        }
 
-       
-       
        return 0;
 }
 
@@ -2779,69 +2976,75 @@ static enum ast_bridge_result  misdn_bridge (struct ast_channel *c0,
                                      int timeoutms)
 
 {
-       struct chan_list *ch1,*ch2;
+       struct chan_list *ch1, *ch2;
        struct ast_channel *carr[2], *who;
-       int to=-1;
+       int to = -1;
        struct ast_frame *f;
+       int p1_b, p2_b;
+       int bridging;
   
-       ch1=get_chan_by_ast(c0);
-       ch2=get_chan_by_ast(c1);
+       ch1 = get_chan_by_ast(c0);
+       ch2 = get_chan_by_ast(c1);
 
-       carr[0]=c0;
-       carr[1]=c1;
+       carr[0] = c0;
+       carr[1] = c1;
   
-       if (ch1 && ch2 ) ;
-       else
+       if (!(ch1 && ch2))
                return -1;
 
-       int bridging;
-       misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
+       misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(p1_b));
+       misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(p2_b));
+
+       if (! p1_b || ! p2_b) {
+               ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
+               return AST_BRIDGE_FAILED;
+       }
+
+       misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
        if (bridging) {
                /* trying to make a mISDN_dsp conference */
-               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, "I SEND: Making conference with Number:%d\n", ch1->bc->pid + 1);
+               misdn_lib_bridge(ch1->bc, ch2->bc);
        }
-       
-       if (option_verbose > 2) 
-               ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
+
+       ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
 
        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_0) )
+               ch1->ignore_dtmf = 1;
 
-       if (! (flags&AST_BRIDGE_DTMF_CHANNEL_1) )
-               ch2->ignore_dtmf=1;
+       if (! (flags & AST_BRIDGE_DTMF_CHANNEL_1) )
+               ch2->ignore_dtmf = 1;
 
-       while(1) {
-               to=-1;
+       for (;/*ever*/;) {
+               to = -1;
                who = ast_waitfor_n(carr, 2, &to);
 
                if (!who) {
-                       ast_log(LOG_NOTICE,"misdn_bridge: empty read, breaking out\n");
+                       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(4,ch1->bc->port,"Read Null Frame\n");
+                               chan_misdn_log(4, ch1->bc->port, "Read Null Frame\n");
                        else
-                               chan_misdn_log(4,ch1->bc->port,"Read Frame Controll class:%d\n",f->subclass);
-                       
-                       *fo=f;
-                       *rc=who;
-      
+                               chan_misdn_log(4, ch1->bc->port, "Read Frame Control 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);
+                       chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f->subclass, who->exten);
 
-                       *fo=f;
-                       *rc=who;
+                       *fo = f;
+                       *rc = who;
                        break;
                }
        
@@ -2854,19 +3057,17 @@ static enum ast_bridge_result  misdn_bridge (struct ast_channel *c0,
 #endif
 
                if (who == c0) {
-                       ast_write(c1,f);
+                       ast_write(c1, f);
                }
                else {
-                       ast_write(c0,f);
+                       ast_write(c0, f);
                }
-    
        }
-       
-       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);
-       
-       
+
+       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;
 }
 
@@ -2874,32 +3075,31 @@ static enum ast_bridge_result  misdn_bridge (struct ast_channel *c0,
 
 static int dialtone_indicate(struct chan_list *cl)
 {
-       const struct ind_tone_zone_sound *ts= NULL;
-       struct ast_channel *ast=cl->ast;
+       const struct ind_tone_zone_sound *ts = NULL;
+       struct ast_channel *ast = cl->ast;
+       int nd = 0;
 
        if (!ast) {
-               chan_misdn_log(0,cl->bc->port,"No Ast in dialtone_indicate\n");
+               chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
                return -1;
        }
 
-       int nd=0;
-       misdn_cfg_get( cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
+       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");
+               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;      
+       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);
+               cl->notxtone = 0;
+               cl->norxtone = 0;
+               /* This prods us in misdn_write */
+               ast_playtones_start(ast, 0, ts->data, 0);
        }
 
        return 0;
@@ -2907,24 +3107,26 @@ static int dialtone_indicate(struct chan_list *cl)
 
 static int hanguptone_indicate(struct chan_list *cl)
 {
-       misdn_lib_send_tone(cl->bc,TONE_HANGUP);
+       misdn_lib_send_tone(cl->bc, TONE_HANGUP);
        return 0;
 }
 
 static int stop_indicate(struct chan_list *cl)
 {
-       struct ast_channel *ast=cl->ast;
+       struct ast_channel *ast = cl->ast;
 
        if (!ast) {
-               chan_misdn_log(0,cl->bc->port,"No Ast in stop_indicate\n");
+               chan_misdn_log(0, cl->bc->port, "No Ast in stop_indicate\n");
                return -1;
        }
 
-       chan_misdn_log(3,cl->bc->port," --> None\n");
+       chan_misdn_log(3, cl->bc->port, " --> None\n");
        misdn_lib_tone_generator_stop(cl->bc);
        ast_playtones_stop(ast);
+
+       cl->ts = NULL;
        /*ast_deactivate_generator(ast);*/
-       
+
        return 0;
 }
 
@@ -2932,8 +3134,8 @@ static int stop_indicate(struct chan_list *cl)
 static int start_bc_tones(struct chan_list* cl)
 {
        misdn_lib_tone_generator_stop(cl->bc);
-       cl->notxtone=0;
-       cl->norxtone=0;
+       cl->notxtone = 0;
+       cl->norxtone = 0;
        return 0;
 }
 
@@ -2941,8 +3143,8 @@ static int stop_bc_tones(struct chan_list *cl)
 {
        if (!cl) return -1;
 
-       cl->notxtone=1;
-       cl->norxtone=1;
+       cl->notxtone = 1;
+       cl->norxtone = 1;
        
        return 0;
 }
@@ -2950,85 +3152,77 @@ static int stop_bc_tones(struct chan_list *cl)
 
 static struct chan_list *init_chan_list(int orig)
 {
-       struct chan_list *cl=malloc(sizeof(struct chan_list));
-       
+       struct chan_list *cl;
+
+       cl = ast_calloc(1, sizeof(*cl));
+
        if (!cl) {
                chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
                return NULL;
        }
        
-       memset(cl,0,sizeof(struct chan_list));
+       cl->originator = orig;
+       cl->need_queue_hangup = 1;
+       cl->need_hangup = 1;
+       cl->need_busy = 1;
+       cl->overlap_dial_task = -1;
 
-       cl->originator=orig;
-       cl->need_queue_hangup=1;
-       cl->need_hangup=1;
-       cl->need_busy=1;
-       cl->overlap_dial_task=-1;
-       
        return cl;
-       
 }
 
 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
-
 {
        struct ast_channel *tmp = NULL;
-       char group[BUFFERSIZE+1]="";
+       char group[BUFFERSIZE + 1] = "";
        char buf[128];
-       char buf2[128], *ext=NULL, *port_str;
-       char *tokb=NULL, *p=NULL;
-       int channel=0, port=0;
+       char *buf2 = ast_strdupa(data), *ext = NULL, *port_str;
+       char *tokb = NULL, *p = NULL;
+       int channel = 0, port = 0;
        struct misdn_bchannel *newbc = NULL;
-       int dec=0;
-       
-       struct chan_list *cl=init_chan_list(ORG_AST);
-       
-       sprintf(buf,"%s/%s",misdn_type,(char*)data);
-       ast_copy_string(buf2,data, 128);
-       
-       port_str=strtok_r(buf2,"/", &tokb);
+       int dec = 0;
+
+       struct chan_list *cl = init_chan_list(ORG_AST);
+
+       snprintf(buf, sizeof(buf), "%s/%s", misdn_type, (char*)data);
 
-       ext=strtok_r(NULL,"/", &tokb);
+       port_str = strtok_r(buf2, "/", &tokb);
+
+       ext = strtok_r(NULL, "/", &tokb);
 
        if (port_str) {
-               if (port_str[0]=='g' && port_str[1]==':' ) {
+               if (port_str[0] == 'g' && port_str[1] == ':' ) {
                        /* We make a group call lets checkout which ports are in my group */
                        port_str += 2;
-                       strncpy(group, port_str, BUFFERSIZE);
-                       group[127] = 0;
-                       chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
-               } 
-               else if ((p = strchr(port_str, ':'))) {
+                       ast_copy_string(group, port_str, sizeof(group));
+                       chan_misdn_log(2, 0, " --> Group Call group: %s\n", group);
+               } else if ((p = strchr(port_str, ':'))) {
                        /* we have a preselected channel */
                        *p = 0;
                        channel = atoi(++p);
                        port = atoi(port_str);
                        chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
-               }
-               else {
+               } else {
                        port = atoi(port_str);
                }
        } else {
-               ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext);
+               ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extensions.conf\n", ext);
                return NULL;
        }
 
        if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
-               chan_misdn_log(4, port, " --> STARTING STANDARDDEC...\n");
-               dec=1;
+               chan_misdn_log(4, port, " --> STARTING STANDARD DEC...\n");
+               dec = 1;
        }
 
        if (!ast_strlen_zero(group)) {
-       
-               char cfg_group[BUFFERSIZE+1];
+               char cfg_group[BUFFERSIZE + 1];
                struct robin_list *rr = NULL;
 
                if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
                        chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
                        rr = get_robin_position(group);
                }
-               
-                       
+
                if (rr) {
                        int robin_channel = rr->channel;
                        int port_start;
@@ -3053,24 +3247,23 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
                                                next_chan = 0;
                                        }
 
-                                       misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
-                                       
+                                       misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
+
                                        if (!strcasecmp(cfg_group, group)) {
                                                int port_up;
                                                int check;
-                                               misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
+                                               misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
                                                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");
+                                                       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 (check && port_up < 0) {
+                                                       ast_log(LOG_WARNING, "This port (%d) is blocked\n", port);
                                                }
-                                               
-                                               
-                                               if ( port_up>0 )        {
-                                                       newbc = misdn_lib_get_free_bc(port, robin_channel,0, 0);
+
+                                               if (port_up > 0)        {
+                                                       newbc = misdn_lib_get_free_bc(port, robin_channel, 0, 0);
                                                        if (newbc) {
                                                                chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
                                                                if (port_up)
@@ -3084,24 +3277,22 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
                                }
                        } while (!newbc && robin_channel != rr->channel);
                        
-                       if (!newbc)
-                               chan_misdn_log(-1, port, " Failed! No free channel in group %d!", group);
                } else {                
-                       for (port=misdn_cfg_get_next_port(0); port > 0;
-                                port=misdn_cfg_get_next_port(port)) {
-                               
-                               misdn_cfg_get( port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
+                       for (port = misdn_cfg_get_next_port(0); port > 0;
+                                port = misdn_cfg_get_next_port(port)) {
+
+                               misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
 
-                               chan_misdn_log(3,port, "Group [%s] Port [%d]\n", group, port);
+                               chan_misdn_log(3, port, "Group [%s] Port [%d]\n", group, port);
                                if (!strcasecmp(cfg_group, group)) {
                                        int port_up;
                                        int check;
-                                       misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
+                                       misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
                                        port_up = misdn_lib_port_up(port, check);
-                                       
+
                                        chan_misdn_log(4, port, "portup:%d\n", port_up);
-                                       
-                                       if ( port_up>0 ) {
+
+                                       if (port_up > 0) {
                                                newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
                                                if (newbc)
                                                        break;
@@ -3109,21 +3300,37 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
                                }
                        }
                }
-       } else {
+               
+               /* Group dial failed ?*/
+               if (!newbc) {
+                       ast_log(LOG_WARNING, 
+                                       "Could not Dial out on group '%s'.\n"
+                                       "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
+                                       "\tOr there was no free channel on none of the ports\n\n"
+                                       , group);
+                       return NULL;
+               }
+       } else { /* 'Normal' Port dial * Port dial */
                if (channel)
-                       chan_misdn_log(1, port," --> preselected_channel: %d\n",channel);
+                       chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
                newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
+
+               if (!newbc) {
+                       ast_log(LOG_WARNING, "Could not create channel on port:%d with extensions:%s\n", port, ext);
+                       return NULL;
+               }
        }
        
-       if (!newbc) {
-               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;
+       cl->bc = newbc;
        
        tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
+       if (!tmp) {
+               ast_log(LOG_ERROR,"Could not create Asterisk object\n");
+               return NULL;
+       }
+
        cl->ast=tmp;
        
        /* register chan in local list */
@@ -3133,18 +3340,18 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
        read_config(cl, ORG_AST);
 
        /* important */
-       cl->need_hangup=0;
+       cl->need_hangup = 0;
        
        return tmp;
 }
 
 
-static int misdn_send_text (struct ast_channel *chan, const char *text)
+static int misdn_send_text(struct ast_channel *chan, const char *text)
 {
-       struct chan_list *tmp=chan->tech_pvt;
+       struct chan_list *tmp = chan->tech_pvt;
        
        if (tmp && tmp->bc) {
-               ast_copy_string(tmp->bc->display,text,sizeof(tmp->bc->display));
+               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");
@@ -3155,84 +3362,91 @@ static int misdn_send_text (struct ast_channel *chan, const char *text)
 }
 
 static struct ast_channel_tech misdn_tech = {
-       .type="mISDN",
-       .description="Channel driver for mISDN Support (Bri/Pri)",
-       .capabilities= AST_FORMAT_ALAW ,
-       .requester=misdn_request,
-       .send_digit_begin=misdn_digit_begin,
-       .send_digit_end=misdn_digit_end,
-       .call=misdn_call,
-       .bridge=misdn_bridge, 
-       .hangup=misdn_hangup,
-       .answer=misdn_answer,
-       .read=misdn_read,
-       .write=misdn_write,
-       .indicate=misdn_indication,
-       .fixup=misdn_fixup,
-       .send_text=misdn_send_text,
-       .properties=0
+       .type = "mISDN",
+       .description = "Channel driver for mISDN Support (Bri/Pri)",
+       .capabilities = AST_FORMAT_ALAW ,
+       .requester = misdn_request,
+       .send_digit_begin = misdn_digit_begin,
+       .send_digit_end = misdn_digit_end,
+       .call = misdn_call,
+       .bridge = misdn_bridge, 
+       .hangup = misdn_hangup,
+       .answer = misdn_answer,
+       .read = misdn_read,
+       .write = misdn_write,
+       .indicate = misdn_indication,
+       .fixup = misdn_fixup,
+       .send_text = misdn_send_text,
+       .properties = 0
 };
 
 static struct ast_channel_tech misdn_tech_wo_bridge = {
-       .type="mISDN",
-       .description="Channel driver for mISDN Support (Bri/Pri)",
-       .capabilities=AST_FORMAT_ALAW ,
-       .requester=misdn_request,
-       .send_digit_begin=misdn_digit_begin,
-       .send_digit_end=misdn_digit_end,
-       .call=misdn_call,
-       .hangup=misdn_hangup,
-       .answer=misdn_answer,
-       .read=misdn_read,
-       .write=misdn_write,
-       .indicate=misdn_indication,
-       .fixup=misdn_fixup,
-       .send_text=misdn_send_text,
-       .properties=0
+       .type = "mISDN",
+       .description = "Channel driver for mISDN Support (Bri/Pri)",
+       .capabilities = AST_FORMAT_ALAW ,
+       .requester = misdn_request,
+       .send_digit_begin = misdn_digit_begin,
+       .send_digit_end = misdn_digit_end,
+       .call = misdn_call,
+       .hangup = misdn_hangup,
+       .answer = misdn_answer,
+       .read = misdn_read,
+       .write = misdn_write,
+       .indicate = misdn_indication,
+       .fixup = misdn_fixup,
+       .send_text = misdn_send_text,
+       .properties = 0
 };
 
 
-static int glob_channel=0;
+static int glob_channel = 0;
 
 static void update_name(struct ast_channel *tmp, int port, int c) 
 {
-       int chan_offset=0;
+       int chan_offset = 0;
        int tmp_port = misdn_cfg_get_next_port(0);
-       for (; tmp_port > 0; tmp_port=misdn_cfg_get_next_port(tmp_port)) {
-       if (tmp_port == port) break;
-               chan_offset+=misdn_lib_port_is_pri(tmp_port)?30:2;      
+       char newname[255];
+       for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
+               if (tmp_port == port)
+                       break;
+               chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;        
        }
-       if (c<0) c=0;
+       if (c < 0)
+               c = 0;
 
-       ast_string_field_build(tmp, name, "%s/%d-u%d",
-                                misdn_type, chan_offset+c, glob_channel++);
-
-       chan_misdn_log(3,port," --> updating channel name to [%s]\n",tmp->name);
-       
+       snprintf(newname, sizeof(newname), "%s/%d-", misdn_type, chan_offset + c);
+       if (strncmp(tmp->name, newname, strlen(newname))) {
+               snprintf(newname, sizeof(newname), "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
+               ast_change_name(tmp, newname);
+               chan_misdn_log(3, port, " --> updating channel name to [%s]\n", tmp->name);
+       }
 }
 
 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;
        char *cid_name = 0, *cid_num = 0;
-       int chan_offset=0;
+       int chan_offset = 0;
        int tmp_port = misdn_cfg_get_next_port(0);
+       int bridging;
 
-       for (; tmp_port > 0; tmp_port=misdn_cfg_get_next_port(tmp_port)) {
-       if (tmp_port == port) break;
-               chan_offset+=misdn_lib_port_is_pri(tmp_port)?30:2;      
+       for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
+               if (tmp_port == port)
+                       break;
+               chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
        }
-       if (c<0) c=0;
+       if (c < 0)
+               c = 0;
 
-       
-       if (callerid) 
+       if (callerid) {
                ast_callerid_parse(callerid, &cid_name, &cid_num);
+       }
+
+       tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/%s%d-u%d", misdn_type, c ? "" : "tmp", chan_offset + c, glob_channel++);
 
-       tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
-       
        if (tmp) {
-               chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten,callerid);
-               
+               chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n", exten, callerid);
+
                tmp->nativeformats = prefformat;
 
                tmp->readformat = format;
@@ -3241,50 +3455,41 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state,  char
                tmp->rawwriteformat = format;
     
                tmp->tech_pvt = chlist;
-               
-               int bridging;
-               misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
+
+               misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
+
                if (bridging)
                        tmp->tech = &misdn_tech;
                else
                        tmp->tech = &misdn_tech_wo_bridge;
-               
+
                tmp->writeformat = format;
                tmp->readformat = format;
                tmp->priority=1;
-               
+
                if (exten) 
-                       ast_copy_string(tmp->exten, exten,  sizeof(tmp->exten));
+                       ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
                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);
+                       chan_misdn_log(1, 0, "misdn_new: no exten given.\n");
+
+               if (callerid)
                        /* Don't use ast_set_callerid() here because it will
                         * generate a needless NewCallerID event */
-                       tmp->cid.cid_num = ast_strdup(cid_num);
                        tmp->cid.cid_ani = ast_strdup(cid_num);
-                       tmp->cid.cid_name = ast_strdup(cid_name);
-               }
 
-               {
-                       if (pipe(chlist->pipe)<0)
-                               perror("Pipe failed\n");
-                       
-                       tmp->fds[0]=chlist->pipe[0];
-                       
-               }
-               
+               if (pipe(chlist->pipe) < 0)
+                       ast_log(LOG_ERROR, "Pipe failed\n");
+
+               ast_channel_set_fd(tmp, 0, chlist->pipe[0]);
+
                if (state == AST_STATE_RING)
                        tmp->rings = 1;
                else
                        tmp->rings = 0;
                
-               
+               ast_jb_configure(tmp, misdn_get_global_jbconf());
        } else {
-               chan_misdn_log(-1,0,"Unable to allocate channel structure\n");
+               chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
        }
        
        return tmp;
@@ -3292,51 +3497,52 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state,  char
 
 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) {
+       struct chan_list *help = list;
+       for (; help; help = help->next) {
                if (help->bc == bc) return help;
        }
-  
-       chan_misdn_log(6, 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;
 }
 
 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid)
 {
-       struct chan_list *help=list;
-       for (;help; help=help->next) {
+       struct chan_list *help = list;
+       for (; help; help = help->next) {
                if ( help->bc && (help->bc->pid == pid) ) return help;
        }
-  
-       chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n",pid);
-  
+
+       chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid);
+
        return NULL;
 }
 
 static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
 {
-       struct chan_list *help=list;
-       
-       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->state==MISDN_HOLDED, help->hold_info.channel);
+       struct chan_list *help = list;
+
+       if (bc->pri) return NULL;
+
+       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->state==MISDN_HOLDED, help->hold_info.channel);
                if (    (help->state == MISDN_HOLDED) && 
                        (help->hold_info.port == bc->port) ) 
                        return help;
-       }       
-       chan_misdn_log(6, 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;
 }
 
 
 static struct chan_list *find_holded_l3(struct chan_list *list, unsigned long l3_id, int w) 
-
 {
-       struct chan_list *help=list;
+       struct chan_list *help = list;
 
-       for (;help; help=help->next) {
+       for (; help; help = help->next) {
                if ( (help->state == MISDN_HOLDED) &&
                         (help->l3id == l3_id)   
                        ) 
@@ -3348,29 +3554,29 @@ static struct chan_list *find_holded_l3(struct chan_list *list, unsigned long l3
 
 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);
+       chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
   
        ast_mutex_lock(&cl_te_lock);
        if (!*list) {
                *list = chan;
        } else {
-               struct chan_list *help=*list;
-               for (;help->next; help=help->next); 
-               help->next=chan;
+               struct chan_list *help = *list;
+               for (; help->next; help = help->next); 
+               help->next = chan;
        }
-       chan->next=NULL;
+       chan->next = NULL;
        ast_mutex_unlock(&cl_te_lock);
 }
 
 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan) 
 {
+       struct chan_list *help;
+
        if (chan->dsp) 
                ast_dsp_free(chan->dsp);
        if (chan->trans)
                ast_translator_free_path(chan->trans);
 
-       
-
        ast_mutex_lock(&cl_te_lock);
        if (!*list) {
                ast_mutex_unlock(&cl_te_lock);
@@ -3378,19 +3584,16 @@ static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
        }
   
        if (*list == chan) {
-               *list=(*list)->next;
+               *list = (*list)->next;
                ast_mutex_unlock(&cl_te_lock);
-               return ;
+               return;
        }
   
-       {
-               struct chan_list *help=*list;
-               for (;help->next; help=help->next) {
-                       if (help->next == chan) {
-                               help->next=help->next->next;
-                               ast_mutex_unlock(&cl_te_lock);
-                               return;
-                       }
+       for (help = *list; help->next; help = help->next) {
+               if (help->next == chan) {
+                       help->next = help->next->next;
+                       ast_mutex_unlock(&cl_te_lock);
+                       return;
                }
        }
        
@@ -3400,78 +3603,80 @@ static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
 /** Channel Queue End **/
 
 
-int pbx_start_chan(struct chan_list *ch)
+static int pbx_start_chan(struct chan_list *ch)
 {
-       int ret=ast_pbx_start(ch->ast); 
+       int ret = ast_pbx_start(ch->ast);       
 
-       if (ret>=0) 
-               ch->need_hangup=0;
+       if (ret >= 0) 
+               ch->need_hangup = 0;
        else
-               ch->need_hangup=1;
+               ch->need_hangup = 1;
 
        return ret;
 }
 
 static void hangup_chan(struct chan_list *ch)
 {
-       int port=ch?ch->bc?ch->bc->port:0:0;
+       int port = ch ? (ch->bc ? ch->bc->port : 0) : 0;
        if (!ch) {
-               cb_log(1,0,"Cannot hangup chan, no ch\n");
+               cb_log(1, 0, "Cannot hangup chan, no ch\n");
                return;
        }
 
-       cb_log(5,port,"hangup_chan called\n");
+       cb_log(5, port, "hangup_chan called\n");
 
-       if (ch->need_hangup) 
-       {
-               cb_log(2,port," --> hangup\n");
-               send_cause2ast(ch->ast,ch->bc,ch);
-               ch->need_hangup=0;
-               ch->need_queue_hangup=0;
+       if (ch->need_hangup) {
+               cb_log(2, 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(2,port," --> No need to queue hangup\n");
+               cb_log(2, port, " --> No need to queue hangup\n");
        }
 
-       ch->need_queue_hangup=0;
+       ch->need_queue_hangup = 0;
        if (ch->ast) {
-               send_cause2ast(ch->ast,ch->bc,ch);
+               send_cause2ast(ch->ast, ch->bc, ch);
 
                if (ch->ast)
-                       ast_queue_hangup(ch->ast);
-               cb_log(2,port," --> queue_hangup\n");
+                       ast_queue_hangup_with_cause(ch->ast, ch->bc->cause);
+               cb_log(2, port, " --> queue_hangup\n");
        } else {
-               cb_log(1,port,"Cannot hangup chan, no ast\n");
+               cb_log(1, 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;
+
+       ast_mutex_lock(&release_lock);
        {
                struct chan_list *ch=find_chan_by_bc(cl_te, bc);
                if (!ch)  {
                        chan_misdn_log(1, bc->port, "release_chan: Ch not found!\n");
+                       ast_mutex_unlock(&release_lock);
                        return;
                }
-               
+
                if (ch->ast) {
-                       ast=ch->ast;
+                       ast = ch->ast;
                } 
-               
-               chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n",bc->l3_id);
-               
-               /*releaseing jitterbuffer*/
+
+               chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n", bc->l3_id);
+
+               /*releasing jitterbuffer*/
                if (ch->jb ) {
                        misdn_jb_destroy(ch->jb);
-                       ch->jb=NULL;
+                       ch->jb = NULL;
                } else {
                        if (!bc->nojitter)
-                               chan_misdn_log(5,bc->port,"Jitterbuffer already destroyed.\n");
+                               chan_misdn_log(5, bc->port, "Jitterbuffer already destroyed.\n");
                }
 
                if (ch->overlap_dial) {
@@ -3487,60 +3692,57 @@ static void release_chan(struct misdn_bchannel *bc) {
                } else {
                        misdn_in_calls[bc->port]--;
                }
-               
+
                if (ch) {
-                       
                        close(ch->pipe[0]);
                        close(ch->pipe[1]);
 
-                       
                        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.cid_num,misdn_get_ch_state(ch));
+                               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.cid_num, misdn_get_ch_state(ch));
                                chan_misdn_log(3, bc->port, " --> * State Down\n");
-                               MISDN_ASTERISK_TECH_PVT(ast)=NULL;
-                               
-      
+                               MISDN_ASTERISK_TECH_PVT(ast) = NULL;
+
                                if (ast->_state != AST_STATE_RESERVED) {
                                        chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
                                        ast_setstate(ast, AST_STATE_DOWN);
                                }
                        }
-                               
-                       ch->state=MISDN_CLEANING;
+
+                       ch->state = MISDN_CLEANING;
                        cl_dequeue_chan(&cl_te, ch);
-                       
-                       free(ch);
+
+                       ast_free(ch);
                } else {
                        /* chan is already cleaned, so exiting  */
                }
+
+               ast_mutex_unlock(&release_lock);
        }
-}
 /*** release end **/
+}
 
 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);
-       
-       tmp_ch->state=MISDN_HOLD_DISCONNECT;
-  
+       chan_misdn_log(4, 0, "TRANSFERRING %s to %s\n", holded_chan->ast->name, tmp_ch->ast->name);
+
+       tmp_ch->state = MISDN_HOLD_DISCONNECT;
+
        ast_moh_stop(ast_bridged_channel(holded_chan->ast));
 
        holded_chan->state=MISDN_CONNECTED;
-       //misdn_lib_transfer(holded_chan->bc);
+       /* misdn_lib_transfer(holded_chan->bc); */
        ast_channel_masquerade(holded_chan->ast, ast_bridged_channel(tmp_ch->ast));
 }
 
 
-static 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;
-  
+       char *predial;
        struct ast_frame fr;
-  
-       strncpy(predial, ast->exten, sizeof(predial) -1 );
-  
-       ch->state=MISDN_DIALING;
+
+       predial = ast_strdupa(ast->exten);
+
+       ch->state = MISDN_DIALING;
 
        if (!ch->noautorespond_on_setup) {
                if (bc->nt) {
@@ -3558,17 +3760,12 @@ static void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch ,
                ch->state = MISDN_INCOMING_SETUP;
        }
 
-       if ( !bc->nt && (ch->originator==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.cid_num);
   
-       strncpy(ast->exten,"s", 2);
+       strncpy(ast->exten, "s", 2);
   
-       if (pbx_start_chan(ch)<0) {
-               ast=NULL;
+       if (pbx_start_chan(ch) < 0) {
+               ast = NULL;
                hangup_chan(ch);
                hanguptone_indicate(ch);
 
@@ -3579,145 +3776,146 @@ static void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch ,
        }
   
   
-       while (!ast_strlen_zero(p) ) {
+       while (!ast_strlen_zero(predial) ) {
                fr.frametype = AST_FRAME_DTMF;
-               fr.subclass = *p ;
-               fr.src=NULL;
-               fr.data = NULL ;
+               fr.subclass = *predial;
+               fr.src = NULL;
+               fr.data.ptr = NULL;
                fr.datalen = 0;
-               fr.samples = 0 ;
-               fr.mallocd =0 ;
-               fr.offset= 0 ;
-               fr.delivery= ast_tv(0,0) ;
+               fr.samples = 0;
+               fr.mallocd = 0;
+               fr.offset = 0;
+               fr.delivery = ast_tv(0,0);
 
                if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
                        ast_queue_frame(ch->ast, &fr);
                }
-               p++;
+               predial++;
        }
 }
 
 
 
-static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch) {
+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");
+               chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
                return;
        }
        if (!bc) {
-               chan_misdn_log(1,0,"send_cause2ast: No BC\n");
+               chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
                return;
        }
        if (!ch) {
-               chan_misdn_log(1,0,"send_cause2ast: No Ch\n");
+               chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
                return;
        }
-       
-       ast->hangupcause=bc->cause;
-       
-       switch ( bc->cause) {
-               
-       case 1: /** Congestion Cases **/
-       case 2:
-       case 3:
-       case 4:
-       case 22:
-       case 27:
+
+       ast->hangupcause = bc->cause;
+
+       switch (bc->cause) {
+
+       case AST_CAUSE_UNALLOCATED:
+       case AST_CAUSE_NO_ROUTE_TRANSIT_NET:
+       case AST_CAUSE_NO_ROUTE_DESTINATION:
+       case 4: /* Send special information tone */
+       case AST_CAUSE_NUMBER_CHANGED:
+       case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
+               /* Congestion Cases */
                /*
                 * 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;
+               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;
-                       
+
+       case AST_CAUSE_CALL_REJECTED:
+       case AST_CAUSE_USER_BUSY:
+               ch->state = MISDN_BUSY;
+
                if (!ch->need_busy) {
-                       chan_misdn_log(1,bc?bc->port:0, "Queued busy already\n");
+                       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);
+
+               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;
+               ch->need_busy = 0;
                
                break;
        }
 }
 
 
-
-
 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
 {
-       const char *tmp;
-       tmp=pbx_builtin_getvar_helper(chan,"MISDN_PID");
+       const char *tmp = pbx_builtin_getvar_helper(chan, "MISDN_PID");
        if (tmp) {
-               ch->other_pid=atoi(tmp);
-               chan_misdn_log(3,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;
+               ch->other_pid = atoi(tmp);
+               chan_misdn_log(3, 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;
                }
        }
 
-       tmp=pbx_builtin_getvar_helper(chan,"MISDN_ADDRESS_COMPLETE");
+       tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
        if (tmp && (atoi(tmp) == 1)) {
-               bc->sending_complete=1;
+               bc->sending_complete = 1;
        }
-       
-       ast_log(LOG_VERBOSE, "getting MISDN_USERUSER:\n");
-       tmp=pbx_builtin_getvar_helper(chan,"MISDN_USERUSER");
+
+       tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
        if (tmp) {
-               ast_log(LOG_VERBOSE, "MISDN_USERUSER: %s\n", tmp);
-               strcpy(bc->uu, tmp);
-               bc->uulen=strlen(bc->uu);
+               ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
+               ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
+               bc->uulen = strlen(bc->uu);
        }
 
+       tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
+       if (tmp)
+               ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
 }
 
 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
 {
        char tmp[32];
-       chan_misdn_log(3,bc->port," --> EXPORT_PID: pid:%d\n",bc->pid);
-       sprintf(tmp,"%d",bc->pid);
-       pbx_builtin_setvar_helper(chan,"_MISDN_PID",tmp);
+       chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
+       snprintf(tmp, sizeof(tmp), "%d", bc->pid);
+       pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
 
        if (bc->sending_complete) {
-               sprintf(tmp,"%d",bc->sending_complete);
-               pbx_builtin_setvar_helper(chan,"MISDN_ADDRESS_COMPLETE",tmp);
+               snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
+               pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
        }
 
        if (bc->urate) {
-               sprintf(tmp,"%d",bc->urate);
-               pbx_builtin_setvar_helper(chan,"MISDN_URATE",tmp);
+               snprintf(tmp, sizeof(tmp), "%d", bc->urate);
+               pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
        }
 
-       if (bc->uulen) {
-               pbx_builtin_setvar_helper(chan,"MISDN_USERUSER",bc->uu);
-       }
+       if (bc->uulen)
+               pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
+
+       if (!ast_strlen_zero(bc->keypad)) 
+               pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
 }
 
 int add_in_calls(int port)
 {
        int max_in_calls;
        
-       misdn_cfg_get( port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
-
+       misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
        misdn_in_calls[port]++;
 
-       if (max_in_calls >=0 && max_in_calls<misdn_in_calls[port]) {
-               ast_log(LOG_NOTICE,"Marking Incoming Call on port[%d]\n",port);
-               return misdn_in_calls[port]-max_in_calls;
+       if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
+               ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
+               return misdn_in_calls[port] - max_in_calls;
        }
        
        return 0;
@@ -3727,12 +3925,11 @@ int add_out_calls(int port)
 {
        int max_out_calls;
        
-       misdn_cfg_get( port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
-       
+       misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
 
-       if (max_out_calls >=0 && max_out_calls<=misdn_out_calls[port]) {
-               ast_log(LOG_NOTICE,"Rejecting Outgoing Call on port[%d]\n",port);
-               return (misdn_out_calls[port]+1)-max_out_calls;
+       if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
+               ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
+               return (misdn_out_calls[port] + 1) - max_out_calls;
        }
 
        misdn_out_calls[port]++;
@@ -3740,6 +3937,24 @@ int add_out_calls(int port)
        return 0;
 }
 
+static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
+       if (pbx_start_chan(ch) < 0) {
+               hangup_chan(ch);
+               chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
+               if (bc->nt) {
+                       hanguptone_indicate(ch);
+                       misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
+               } else
+                       misdn_lib_send_event(bc, EVENT_RELEASE);
+       }
+}
+
+static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
+       ch->state=MISDN_WAITING4DIGS;
+       misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
+       if (bc->nt && !bc->dad[0])
+               dialtone_indicate(ch);
+}
 
 
 /************************************************************/
@@ -3748,58 +3963,57 @@ int add_out_calls(int port)
 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);
+       struct chan_list *ch = find_chan_by_bc(cl_te, bc);
        
        if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /*  Debug Only Non-Bchan */
-               int debuglevel=1;
-               if ( event==EVENT_CLEANUP && !user_data)
-                       debuglevel=5;
+               int debuglevel = 1;
+               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) {
+               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));
+                       chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
                }
        }
        
        if (!ch) {
                switch(event) {
-                       case EVENT_SETUP:
-                       case EVENT_DISCONNECT:
-                       case EVENT_PORT_ALARM:
-                       case EVENT_RETRIEVE:
-                       case EVENT_NEW_BC:
-                       case EVENT_FACILITY:
-                               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;
+               case EVENT_SETUP:
+               case EVENT_DISCONNECT:
+               case EVENT_PORT_ALARM:
+               case EVENT_RETRIEVE:
+               case EVENT_NEW_BC:
+               case EVENT_FACILITY:
+                       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 ) {
+       if (ch) {
                switch (event) {
                case EVENT_TONE_GENERATE:
-               break;
+                       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));
+                               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)
+                       if (!ch->ast  || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
+                               if (event != EVENT_BCHAN_DATA)
                                        ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
                                return -1;
                        }
@@ -3810,14 +4024,14 @@ 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));
+                       int boa = 0;
+                       misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(boa));
                        if (boa) {
-                               cb_log(1,bc->port," --> blocking\n");
+                               cb_log(1, bc->port, " --> blocking\n");
                                misdn_lib_port_block(bc->port); 
                        }
                }
-       break;
+               break;
        case EVENT_BCHAN_ACTIVATED:
                break;
                
@@ -3832,102 +4046,95 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
 
        case EVENT_NEW_BC:
                if (!ch) {
-                       ch=find_holded(cl_te,bc);
+                       ch = find_holded(cl_te,bc);
                }
                
                if (!ch) {
-                       ast_log(LOG_WARNING,"NEW_BC without chan_list?\n");
+                       ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
                        break;
                }
 
                if (bc)
-                       ch->bc=(struct misdn_bchannel*)user_data;
+                       ch->bc = (struct misdn_bchannel *)user_data;
                break;
                
        case EVENT_DTMF_TONE:
        {
                /*  sending INFOS as DTMF-Frames :) */
-               struct ast_frame fr;
-               memset(&fr, 0 , sizeof(fr));
+               struct ast_frame fr = { 0, };
                fr.frametype = AST_FRAME_DTMF;
                fr.subclass = bc->dtmf ;
-               fr.src=NULL;
-               fr.data = NULL ;
+               fr.src = NULL;
+               fr.data.ptr = NULL;
                fr.datalen = 0;
-               fr.samples = 0 ;
-               fr.mallocd =0 ;
-               fr.offset= 0 ;
-               fr.delivery= ast_tv(0,0) ;
+               fr.samples = 0;
+               fr.mallocd = 0;
+               fr.offset = 0;
+               fr.delivery = ast_tv(0,0);
                
                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);
+                       chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
                }
        }
-       break;
+               break;
        case EVENT_STATUS:
                break;
     
        case EVENT_INFORMATION:
        {
-               int stop_tone;
-               misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
-               if ( stop_tone ) {
+               if ( ch->state != MISDN_CONNECTED ) 
                        stop_indicate(ch);
-               }
        
-               if (!ch->ast) break;
+               if (!ch->ast)
+                       break;
 
                if (ch->state == MISDN_WAITING4DIGS ) {
                        /*  Ok, incomplete Setup, waiting till extension exists */
-
                        if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
                                chan_misdn_log(1, bc->port, " --> using keypad as info\n");
-                               strcpy(bc->info_dad,bc->keypad);
+                               ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
                        }
 
-                       {
-                               int l = sizeof(bc->dad);
-                               strncat(bc->dad,bc->info_dad, l);
-                               bc->dad[l-1] = 0;
-                       }
-                       
-                       
-                       {
-                               int l = sizeof(ch->ast->exten);
-                               strncpy(ch->ast->exten, bc->dad, l);
-                               ch->ast->exten[l-1] = 0;
-                       }
-/*                     chan_misdn_log(5, bc->port, "Can Match Extension: dad:%s oad:%s\n",bc->dad,bc->oad);*/
-                       
+                       strncat(bc->dad,bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
+                       ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
+
                        /* 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;
+                                       struct ast_channel *chan = ch->ast;
                                        ch->state = MISDN_CALLING_ACKNOWLEDGE;
                                        ast_setstate(chan, AST_STATE_DOWN);
                                        hangup_chan(ch);
-                                       ch->ast=NULL;
+                                       ch->ast = NULL;
                                        break;
                                }
                        }
                        
-                       if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
+                       if (!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
+                               if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
+                                       ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n", bc->port);
+                                       strcpy(ch->ast->exten, "i");
+
+                                       ch->state = MISDN_DIALING;
+                                       start_pbx(ch, bc, ch->ast);
+                                       break;
+                               }
+
+                               ast_log(LOG_WARNING, "Extension can never match, so disconnecting on port(%d).\n"
+                                               "\tMaybe you want to add an 'i' extension to catch this case.\n",
+                                               bc->port);
 
-                               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;
-
-                               misdn_lib_send_event(bc, EVENT_DISCONNECT );
+                               ch->state = MISDN_EXTCANTMATCH;
+                               bc->out_cause = AST_CAUSE_UNALLOCATED;
 
+                               misdn_lib_send_event(bc, EVENT_DISCONNECT);
                                break;
                        }
 
@@ -3942,46 +4149,31 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                                break;
                        }
 
-                       if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
-                               ch->state=MISDN_DIALING;
-         
-                               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 );
-                               }
+                       if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad))  {
+                               
+                               ch->state = MISDN_DIALING;
+                               start_pbx(ch, bc, ch->ast);
                        }
-       
                } else {
                        /*  sending INFOS as DTMF-Frames :) */
                        struct ast_frame fr;
+                       int digits;
+                       memset(&fr, 0, sizeof(fr));
                        fr.frametype = AST_FRAME_DTMF;
                        fr.subclass = bc->info_dad[0] ;
-                       fr.src=NULL;
-                       fr.data = NULL ;
+                       fr.src = NULL;
+                       fr.data.ptr = NULL;
                        fr.datalen = 0;
-                       fr.samples = 0 ;
-                       fr.mallocd =0 ;
-                       fr.offset= 0 ;
-                       fr.delivery= ast_tv(0,0) ;
+                       fr.samples = 0;
+                       fr.mallocd = 0;
+                       fr.offset = 0;
+                       fr.delivery = ast_tv(0,0);
 
-                       
-                       int digits;
-                       misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
+                       misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(digits));
                        if (ch->state != MISDN_CONNECTED ) {
                                if (digits) {
-                                       int l = sizeof(bc->dad);
-                                       strncat(bc->dad,bc->info_dad, l);
-                                       bc->dad[l-1] = 0;
-                                       l = sizeof(ch->ast->exten);
-                                       strncpy(ch->ast->exten, bc->dad, l);
-                                       ch->ast->exten[l-1] = 0;
-
+                                       strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
+                                       ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
                                        ast_cdr_update(ch->ast);
                                }
                                
@@ -3989,132 +4181,171 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        }
                }
        }
-       break;
+               break;
        case EVENT_SETUP:
        {
-               struct chan_list *ch=find_chan_by_bc(cl_te, bc);
+               struct chan_list *ch = find_chan_by_bc(cl_te, bc);
+               int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
+               struct ast_channel *chan;
+               int exceed;
+               int pres,screen;
+               int ai;
+               int im;
+
                if (ch) {
                        switch (ch->state) {
-                               case MISDN_NOTHING:
-                               ch=NULL;
+                       case MISDN_NOTHING:
+                               ch = NULL;
                                break;
-                               default:
+                       default:
                                chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
                                return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /*  Ignore MSNs which are not in our List */
                        }
                }
-       }
-       
 
-       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");
-               return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
-       }
+               if (!bc->nt && ! msn_valid) {
+                       chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
+                       return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
+               }
 
-       
-       if (bc->cw) {
-               chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
-               int cause;
-               misdn_cfg_get( bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
-               bc->out_cause=cause?cause:16;
-               return RESPONSE_RELEASE_SETUP;
-       }
+               if (bc->cw) {
+                       int cause;
+                       chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
+                       misdn_cfg_get(bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
+                       bc->out_cause = cause ? cause : AST_CAUSE_NORMAL_CLEARING;
+                       return RESPONSE_RELEASE_SETUP;
+               }
 
-       print_bearer(bc);
+               print_bearer(bc);
     
-       {
-               struct chan_list *ch=init_chan_list(ORG_MISDN);
-               struct ast_channel *chan;
-               int exceed;
+               if (!bc->nt && ! msn_valid) {
+                       chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
+                       return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
+               }
+
+               if (bc->cw) {
+                       int cause;
+                       chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
+                       misdn_cfg_get(bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
+                       bc->out_cause = cause ? cause : AST_CAUSE_NORMAL_CLEARING;
+                       return RESPONSE_RELEASE_SETUP;
+               }
+
+               print_bearer(bc);
+
+               ch = init_chan_list(ORG_MISDN);
+
+               if (!ch) {
+                       chan_misdn_log(-1, 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->l3id = bc->l3_id;
+               ch->addr = bc->addr;
                ch->originator = ORG_MISDN;
 
-               chan=misdn_new(ch, AST_STATE_RESERVED,bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
+               chan = misdn_new(ch, AST_STATE_RESERVED, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
+
+               if (!chan) {
+                       misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
+                       ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n"); 
+                       return 0;
+               }
+
                ch->ast = chan;
 
-               if ((exceed=add_in_calls(bc->port))) {
+               if ((exceed = add_in_calls(bc->port))) {
                        char tmp[16];
-                       sprintf(tmp,"%d",exceed);
-                       pbx_builtin_setvar_helper(chan,"MAX_OVERFLOW",tmp);
+                       snprintf(tmp, sizeof(tmp), "%d", exceed);
+                       pbx_builtin_setvar_helper(chan, "MAX_OVERFLOW", tmp);
                }
 
                read_config(ch, ORG_MISDN);
-               
+
                export_ch(chan, bc, ch);
 
-               ch->ast->rings=1;
+               ch->ast->rings = 1;
                ast_setstate(ch->ast, AST_STATE_RINGING);
 
-               int pres,screen;
-
                switch (bc->pres) {
-                       case 1:
-                       pres=AST_PRES_RESTRICTED; chan_misdn_log(2,bc->port," --> PRES: Restricted (1)\n");
+               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");
+               case 2:
+                       pres = AST_PRES_UNAVAILABLE;
+                       chan_misdn_log(2, bc->port, " --> PRES: Unavailable (2)\n");
+                       break;
+               default:
+                       pres = AST_PRES_ALLOWED;
+                       chan_misdn_log(2, bc->port, " --> PRES: Allowed (%d)\n", bc->pres);
                        break;
-                       default:
-                       pres=AST_PRES_ALLOWED; chan_misdn_log(2,bc->port," --> PRES: Restricted (%d)\n", bc->pres);
                }
 
                switch (bc->screen) {
-                       case 0:
-                       screen=AST_PRES_USER_NUMBER_UNSCREENED;  chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (0)\n");
+               default:
+               case 0:
+                       screen = AST_PRES_USER_NUMBER_UNSCREENED;
+                       chan_misdn_log(2, bc->port, " --> SCREEN: Unscreened (%d)\n", bc->screen);
                        break;
-                       case 1:
-                       screen=AST_PRES_USER_NUMBER_PASSED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: Passed screen (1)\n");
+               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");
+               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");
+               case 3:
+                       screen = AST_PRES_NETWORK_NUMBER;
+                       chan_misdn_log(2, bc->port, " --> SCREEN: Network Number (3)\n");
                        break;
-                       default:
-                       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->cid.cid_pres = pres | screen;
 
                pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
-               chan->transfercapability=bc->capability;
-               
+               chan->transfercapability = bc->capability;
+
                switch (bc->capability) {
                case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
-                       pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL");
+                       pbx_builtin_setvar_helper(chan, "CALLTYPE", "DIGITAL");
                        break;
                default:
-                       pbx_builtin_setvar_helper(chan,"CALLTYPE","SPEECH");
+                       pbx_builtin_setvar_helper(chan, "CALLTYPE", "SPEECH");
                }
 
                /** queue new chan **/
-               cl_queue_chan(&cl_te, ch) ;
+               cl_queue_chan(&cl_te, ch);
 
-
-               if (!strstr(ch->allowed_bearers,"all")) {
+               if (!strstr(ch->allowed_bearers, "all")) {
                        int i;
-                       for (i=0; i< sizeof(allowed_bearers_array)/sizeof(struct allowed_bearers); i++) {
+
+                       for (i = 0; i < ARRAY_LEN(allowed_bearers_array); ++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 (strstr(ch->allowed_bearers, allowed_bearers_array[i].name)) {
+                                               /* The bearer capability is allowed */
+                                               if (allowed_bearers_array[i].deprecated) {
+                                                       chan_misdn_log(0, bc->port, "%s in allowed_bearers list is deprecated\n",
+                                                               allowed_bearers_array[i].name);
+                                               }
+                                               break;
                                        }
                                }
-                               
+                       }       /* end for */
+                       if (i == ARRAY_LEN(allowed_bearers_array)) {
+                               /* We did not find the bearer capability */
+                               chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
+                                       bearer2str(bc->capability), bc->capability);
+                               bc->out_cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
+
+                               ch->state = MISDN_EXTCANTMATCH;
+                               misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
+                               return RESPONSE_OK;
                        }
                }
-               
+
                /* Check for Pickup Request first */
                if (!strcmp(chan->exten, ast_pickup_ext())) {
                        if (!ch->noautorespond_on_setup) {
@@ -4129,134 +4360,122 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                                ch->state = MISDN_CALLING_ACKNOWLEDGE;
                                ast_setstate(chan, AST_STATE_DOWN);
                                hangup_chan(ch);
-                               ch->ast=NULL;
+                               ch->ast = NULL;
                                break;
                        }
                }
-               
+
                /*
-                 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;
-                       }
-                       
-                       
-                       
+                  added support for s extension hope it will help those poor cretains
+                  which haven't overlap dial.
+                  */
+               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;
-                       }
+               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;
                }
 
-               
-                       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");
+               chan_misdn_log(5, bc->port, "CONTEXT:%s\n", ch->context);
+               if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
+                       if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
+                               ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n", bc->port);
+                               strcpy(ch->ast->exten, "i");
+                               misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
+                               ch->state = MISDN_DIALING;
+                               start_pbx(ch, bc, chan);
+                               break;
+                       }
 
+                       ast_log(LOG_WARNING, "Extension can never match, so disconnecting on port(%d).\n"
+                                       "\tMaybe you want to add an 'i' extension to catch this case.\n",
+                                       bc->port);
                        if (bc->nt)
                                hanguptone_indicate(ch);
-                       ch->state=MISDN_EXTCANTMATCH;
-                       bc->out_cause=1;
+
+                       ch->state = MISDN_EXTCANTMATCH;
+                       bc->out_cause = AST_CAUSE_UNALLOCATED;
 
                        if (bc->nt)
                                misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
                        else
                                misdn_lib_send_event(bc, EVENT_RELEASE );
-                               
+
                        break;
                }
-               
-               if (!ch->overlap_dial && ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
-                       
+
+               /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely 
+                * jump into the dialplan, when the dialed extension does not exist, the 's' extension 
+                * will be used by Asterisk automatically. */
+               if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
                        if (!ch->noautorespond_on_setup) {
                                ch->state=MISDN_DIALING;
-
-                               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 {
-                                       int ret;
-                                       ret= misdn_lib_send_event(bc, EVENT_PROCEEDING );
-                               }
+                               misdn_lib_send_event(bc, EVENT_PROCEEDING );
                        } else {
                                ch->state = MISDN_INCOMING_SETUP;
                        }
-       
-                       if (pbx_start_chan(ch)<0) {
-                               hangup_chan(ch);
+                       start_pbx(ch, bc, chan);
+                       break;
+               }
 
-                               chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
-                               chan=NULL;
 
-                               if (bc->nt) {
-                                       hanguptone_indicate(ch);
-                                       misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
-                               } else
-                                       misdn_lib_send_event(bc, EVENT_RELEASE);
-                       }
-               } else {
+               /*
+                * When we are NT and overlapdial is set and if 
+                * the number is empty, we wait for the ISDN timeout
+                * instead of our own timer.
+                */
+               if (ch->overlap_dial && bc->nt && !bc->dad[0] ) {
+                       wait_for_digits(ch, bc, chan);
+                       break;
+               }
 
-                       if (bc->sending_complete) {
-                               ch->state=MISDN_EXTCANTMATCH;
-                               bc->out_cause=1;
+               /* 
+                * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more 
+                * Infos with a Interdigit Timeout.
+                * */
+               if (ch->overlap_dial) {
+                       ast_mutex_lock(&ch->overlap_tv_lock);
+                       ch->overlap_tv = ast_tvnow();
+                       ast_mutex_unlock(&ch->overlap_tv_lock);
 
-                               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);
-                               }
+                       wait_for_digits(ch, bc, chan);
+                       if (ch->overlap_dial_task == -1) 
+                               ch->overlap_dial_task = 
+                                       misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
 
-                       } 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, dad_len;
-                               misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
+                       break;
+               }
 
-                               dad_len = ast_strlen_zero(bc->dad);
-                               
-                               if ( !dad_len && stop_tone )
-                                       stop_indicate(ch);
-                               else
-                                       dialtone_indicate(ch);
-                               
-                               ch->state=MISDN_WAITING4DIGS;
-                               
-                               if (ch->overlap_dial && !dad_len) {
-                                       ast_mutex_lock(&ch->overlap_tv_lock);
-                                       ch->overlap_tv = ast_tvnow();
-                                       ast_mutex_unlock(&ch->overlap_tv_lock);
-                                       if (ch->overlap_dial_task == -1) {
-                                               ch->overlap_dial_task = 
-                                                       misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
-                                       }
-                               }
-                       }
+               /* If the extension does not exist and we're not TE_PTMP we wait for more digits 
+                * without interdigit timeout.
+                * */
+               if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad))  {
+                       wait_for_digits(ch, bc, chan);
+                       break;
+               }
+
+               /*
+                * If the extension exists let's just jump into it.
+                * */
+               if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
+                       if (bc->need_more_infos)
+                               misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
+                       else
+                               misdn_lib_send_event(bc, EVENT_PROCEEDING);
+
+                       ch->state = MISDN_DIALING;
+                       start_pbx(ch, bc, chan);
+                       break;
                }
-               
        }
        break;
+
        case EVENT_SETUP_ACKNOWLEDGE:
        {
                ch->state = MISDN_CALLING_ACKNOWLEDGE;
@@ -4266,25 +4485,13 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                
                if (!ast_strlen_zero(bc->infos_pending)) {
                        /* TX Pending Infos */
-                       
-                       {
-                               int l = sizeof(bc->dad);
-                               strncat(bc->dad,bc->infos_pending, l - strlen(bc->dad));
-                               bc->dad[l-1] = 0;
-                       }       
-               
-                       if (!ch->ast) break;
-                       {
-                               int l = sizeof(ch->ast->exten);
-                               strncpy(ch->ast->exten, bc->dad, l);
-                               ch->ast->exten[l-1] = 0;
-                       }
-                       {
-                               int l = sizeof(bc->info_dad);
-                               strncpy(bc->info_dad, bc->infos_pending, l);
-                               bc->info_dad[l-1] = 0;
-                       }
-                       strncpy(bc->infos_pending,"", 1);
+                       strncat(bc->dad, bc->infos_pending, sizeof(bc->dad) - strlen(bc->dad) - 1);
+
+                       if (!ch->ast)
+                               break;
+                       ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
+                       ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
+                       ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
 
                        misdn_lib_send_event(bc, EVENT_INFORMATION);
                }
@@ -4293,14 +4500,15 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
        case EVENT_PROCEEDING:
        {
                
-               if ( misdn_cap_is_speech(bc->capability) &&
+               if (misdn_cap_is_speech(bc->capability) &&
                     misdn_inband_avail(bc) ) {
                        start_bc_tones(ch);
                }
 
                ch->state = MISDN_PROCEEDING;
                
-               if (!ch->ast) break;
+               if (!ch->ast)
+                       break;
 
                ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
        }
@@ -4308,7 +4516,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
        case EVENT_PROGRESS:
 
                if (bc->channel) 
-                       update_name(ch->ast,bc->port,bc->channel);
+                       update_name(ch->ast, bc->port, bc->channel);
 
                if (!bc->nt ) {
                        if ( misdn_cap_is_speech(bc->capability) &&
@@ -4317,9 +4525,10 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                                start_bc_tones(ch);
                        }
                        
-                       ch->state=MISDN_PROGRESS;
+                       ch->state = MISDN_PROGRESS;
 
-                       if (!ch->ast) break;
+                       if (!ch->ast)
+                               break;
                        ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
                }
                break;
@@ -4329,20 +4538,21 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
        {
                ch->state = MISDN_ALERTING;
                
-               if (!ch->ast) break;
+               if (!ch->ast)
+                       break;
 
                ast_queue_control(ch->ast, AST_CONTROL_RINGING);
                ast_setstate(ch->ast, AST_STATE_RINGING);
                
-               cb_log(7,bc->port," --> Set State Ringing\n");
+               cb_log(7, bc->port, " --> Set State Ringing\n");
                
-               if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
-                       cb_log(1,bc->port,"Starting Tones, we have inband Data\n");
+               if (misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
+                       cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
                        start_bc_tones(ch);
                } else {
-                       cb_log(3,bc->port," --> We have no inband Data, the other end must create ringing\n");
+                       cb_log(3, 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..");
+                               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);*/
                        }
@@ -4351,113 +4561,117 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
        break;
        case EVENT_CONNECT:
        {
+               struct ast_channel *bridged;
+
                /*we answer when we've got our very new L3 ID from the NT stack */
-               misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE);
+               misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
 
-               if (!ch->ast) break;
+               if (!ch->ast)
+                       break;
 
-               struct ast_channel *bridged=ast_bridged_channel(ch->ast);
+               bridged = ast_bridged_channel(ch->ast);
                stop_indicate(ch);
 
-               if (bridged && !strcasecmp(bridged->tech->type,"mISDN")) {
-                       struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged);
+               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);
+                       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));
+                               bridged_ch->bc->cpnnumplan = bc->cpnnumplan;
+                               ast_copy_string(bridged_ch->bc->cad, bc->cad, sizeof(bridged_ch->bc->cad));
                        }
                }
        }
+       ch->l3id=bc->l3_id;
+       ch->addr=bc->addr;
+
+       start_bc_tones(ch);
+       
+       ch->state = MISDN_CONNECTED;
        
-       /* notice that we don't break here!*/
+       ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
+       break;
        case EVENT_CONNECT_ACKNOWLEDGE:
        {
-               ch->l3id=bc->l3_id;
-               ch->addr=bc->addr;
-               
+               ch->l3id = bc->l3_id;
+               ch->addr = bc->addr;
+
                start_bc_tones(ch);
-               
-               ch->state = MISDN_CONNECTED;
-               
-               if (!ch->ast) break;
 
-               ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
+               ch->state = MISDN_CONNECTED;
        }
        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);
-               
-               chan_misdn_log(3,bc->port," --> org:%d nt:%d, inbandavail:%d state:%d\n", ch->originator, bc->nt, misdn_inband_avail(bc), ch->state);
-               if ( ch->originator==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");
+               /*we might not have an ch->ast ptr here anymore*/
+               if (ch) {
+                       struct chan_list *holded_ch = find_holded(cl_te, bc);
+
+                       chan_misdn_log(3, bc->port, " --> org:%d nt:%d, inbandavail:%d state:%d\n", ch->originator, bc->nt, misdn_inband_avail(bc), ch->state);
+                       if (ch->originator == 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);
+                               ch->state = MISDN_DISCONNECTED;
+                               start_bc_tones(ch);
 
-                       if (ch->ast) {
-                               ch->ast->hangupcause=bc->cause;
-                               if (bc->cause == 17)
-                                       ast_queue_control(ch->ast, AST_CONTROL_BUSY);
+                               if (ch->ast) {
+                                       ch->ast->hangupcause = bc->cause;
+                                       if (bc->cause == AST_CAUSE_USER_BUSY)
+                                               ast_queue_control(ch->ast, AST_CONTROL_BUSY);
+                               }
+                               ch->need_busy = 0;
+                               break;
                        }
-                       ch->need_busy=0;
-                       break;
-               }
-               
-               /*Check for holded channel, to implement transfer*/
-               if (    holded_ch && 
-                       holded_ch != ch && 
-                       ch->ast && 
-                       ch->state == MISDN_CONNECTED    ) {
-                       cb_log(1,bc->port," --> found holded ch\n");
-                       misdn_transfer_bc(ch, holded_ch) ;
-               }
 
-               bc->need_disconnect=0;
-               
-               stop_bc_tones(ch);
-               hangup_chan(ch);
-       } else {
-       /*      ch=find_holded_l3(cl_te, bc->l3_id,1);
-               if (ch) {
+                       /*Check for holded channel, to implement transfer*/
+                       if (holded_ch && holded_ch != ch && ch->ast && ch->state == MISDN_CONNECTED) {
+                               cb_log(1, bc->port, " --> found holded ch\n");
+                               misdn_transfer_bc(ch, holded_ch) ;
+                       }
+
+                       bc->need_disconnect = 0;
+
+                       stop_bc_tones(ch);
                        hangup_chan(ch);
+#if 0
+               } else {
+                       ch = find_holded_l3(cl_te, bc->l3_id,1);
+                       if (ch) {
+                               hangup_chan(ch);
+                       }
+#endif
                }
-       */
-       }
-       bc->out_cause=-1;
-       if (bc->need_release) misdn_lib_send_event(bc,EVENT_RELEASE);
-       break;
+               bc->out_cause = -1;
+               if (bc->need_release)
+                       misdn_lib_send_event(bc, EVENT_RELEASE);
+               break;
        
        case EVENT_RELEASE:
                {
-                       bc->need_disconnect=0;
-                       bc->need_release=0;
+                       bc->need_disconnect = 0;
+                       bc->need_release = 0;
 
                        hangup_chan(ch);
                        release_chan(bc);
-               
-                       if (bc->need_release_complete) 
-                               misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
                }
                break;
        case EVENT_RELEASE_COMPLETE:
        {
-               bc->need_disconnect=0;
-               bc->need_release=0;
-               bc->need_release_complete=0;
+               bc->need_disconnect = 0;
+               bc->need_release = 0;
+               bc->need_release_complete = 0;
 
                stop_bc_tones(ch);
                hangup_chan(ch);
+
+               if (ch)
+                       ch->state = MISDN_CLEANING;
+
                release_chan(bc);
-               if(ch)  
-                       ch->state=MISDN_CLEANING;
        }
        break;
        case EVENT_BCHAN_ERROR:
@@ -4465,11 +4679,11 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
        {
                stop_bc_tones(ch);
                
-               switch(ch->state) {
-                       case MISDN_CALLING:
-                               bc->cause=27; /* Destination out of order */
+               switch (ch->state) {
+               case MISDN_CALLING:
+                       bc->cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
                        break;
-                       default:
+               default:
                        break;
                }
                
@@ -4480,27 +4694,27 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
 
        case EVENT_TONE_GENERATE:
        {
-               int tone_len=bc->tone_cnt;
-               struct ast_channel *ast=ch->ast;
+               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");
+               chan_misdn_log(9, bc->port, "TONE_GEN: len:%d\n", tone_len);
 
-               if (!ast) break;
+               if (!ast)
+                       break;
+
+               if (!ast->generator)
+                       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;
+               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);
@@ -4510,65 +4724,61 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        ast_log(LOG_WARNING, "Auto-deactivating generator\n");
                        ast_deactivate_generator(ast);
                } else {
-                       bc->tone_cnt=0;
+                       bc->tone_cnt = 0;
                }
        }
        break;
-               
+
        case EVENT_BCHAN_DATA:
        {
                if (ch->bc->AOCD_need_export)
                        export_aoc_vars(ch->originator, ch->ast, ch->bc);
-               if ( !misdn_cap_is_speech(ch->bc->capability) ) {
+               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.delivery= ast_tv(0,0) ;
+                       frame.samples = bc->bframe_len;
+                       frame.mallocd = 0;
+                       frame.offset = 0;
+                       frame.delivery = ast_tv(0,0);
                        frame.src = NULL;
-                       frame.data = bc->bframe ;
-                       
+                       frame.data.ptr = bc->bframe;
+
                        if (ch->ast) 
-                               ast_queue_frame(ch->ast,&frame);
+                               ast_queue_frame(ch->ast, &frame);
                } else {
                        fd_set wrfs;
-                       struct timeval tv;
-                       tv.tv_sec=0;
-                       tv.tv_usec=0;
-                       
-                       
+                       struct timeval tv = { 0, 0 };
+                       int t;
+
                        FD_ZERO(&wrfs);
-                       FD_SET(ch->pipe[1],&wrfs);
-                       
-                       int t=select(FD_SETSIZE,NULL,&wrfs,NULL,&tv);
+                       FD_SET(ch->pipe[1], &wrfs);
+
+                       t = select(FD_SETSIZE, NULL, &wrfs, NULL, &tv);
 
                        if (!t) {
                                chan_misdn_log(9, bc->port, "Select Timed out\n");
                                break;
                        }
                        
-                       if (t<0) {
-                               chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n",strerror(errno));
+                       if (t < 0) {
+                               chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n", strerror(errno));
                                break;
                        }
                        
-                       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) --> hanging up channel\n",strerror(errno));
+                       if (FD_ISSET(ch->pipe[1], &wrfs)) {
+                               chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
+                               if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
+                                       chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
 
                                        stop_bc_tones(ch);
                                        hangup_chan(ch);
                                        release_chan(bc);
                                }
                        } else {
-                               chan_misdn_log(1, bc->port, "Wripe Pipe full!\n");
+                               chan_misdn_log(1, bc->port, "Write Pipe full!\n");
                        }
                }
        }
@@ -4576,59 +4786,61 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
        case EVENT_TIMEOUT:
                {
                if (ch && bc)
-                       chan_misdn_log(1,bc->port,"--> state: %s\n",misdn_get_ch_state(ch));
+                       chan_misdn_log(1, bc->port, "--> state: %s\n", misdn_get_ch_state(ch));
 
                switch (ch->state) {
-                       case MISDN_DIALING:
-                       case MISDN_PROGRESS:
-                               if (bc->nt && !ch->nttimeout) break;
+               case MISDN_DIALING:
+               case MISDN_PROGRESS:
+                       if (bc->nt && !ch->nttimeout)
+                               break;
                        
-                       case MISDN_CALLING:
-                       case MISDN_ALERTING:
-                       case MISDN_PROCEEDING:
-                       case MISDN_CALLING_ACKNOWLEDGE:
-                               if (bc->nt) {
-                                       bc->progress_indicator=8;
-                                       hanguptone_indicate(ch);
-                               }
+               case MISDN_CALLING:
+               case MISDN_ALERTING:
+               case MISDN_PROCEEDING:
+               case MISDN_CALLING_ACKNOWLEDGE:
+                       if (bc->nt) {
+                               bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
+                               hanguptone_indicate(ch);
+                       }
                                
-                               bc->out_cause=1;
-                               misdn_lib_send_event(bc,EVENT_DISCONNECT);
+                       bc->out_cause = AST_CAUSE_UNALLOCATED;
+                       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);
-                               }
+               case MISDN_WAITING4DIGS:
+                       if (bc->nt) {
+                               bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
+                               bc->out_cause = AST_CAUSE_UNALLOCATED;
+                               hanguptone_indicate(ch);
+                               misdn_lib_send_event(bc, EVENT_DISCONNECT);
+                       } else {
+                               bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
+                               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");
+               case MISDN_CLEANING: 
+                       chan_misdn_log(1,bc->port," --> in state cleaning .. so ignoring, the stack should clean it for us\n");
                        break;
 
-                       default:
-                               misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
-                       }
+               default:
+                       misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
                }
-               break;
+       }
+       break;
 
     
-       /***************************/
-       /** Suplementary Services **/
-       /***************************/
+       /****************************/
+       /** Supplementary Services **/
+       /****************************/
        case EVENT_RETRIEVE:
        {
+               struct ast_channel *hold_ast;
+
                if (!ch) {
-                       chan_misdn_log(4, bc->port, " --> no CH, searching in holded");
-                       ch=find_holded_l3(cl_te, bc->l3_id,1);
+                       chan_misdn_log(4, bc->port, " --> no CH, searching in holded\n");
+                       ch = find_holded_l3(cl_te, bc->l3_id, 1);
                }
 
                if (!ch) {
@@ -4638,39 +4850,41 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                }
 
                /*remember the channel again*/
-               ch->bc=bc;
+               ch->bc = bc;
                ch->state = MISDN_CONNECTED;
 
-               ch->hold_info.port=0;
-               ch->hold_info.channel=0;
-               
-               struct ast_channel *hold_ast=ast_bridged_channel(ch->ast);
-               
+               ch->hold_info.port = 0;
+               ch->hold_info.channel = 0;
+
+               hold_ast = ast_bridged_channel(ch->ast);
+
                if (hold_ast) {
                        ast_moh_stop(hold_ast);
                }
        
-               if ( misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0)
+               if (misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
+                       chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
                        misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
+               }
        }
        break;
     
        case EVENT_HOLD:
        {
                int hold_allowed;
-               misdn_cfg_get( bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
-               
+               struct ast_channel *bridged = ast_bridged_channel(ch->ast);
+
+               misdn_cfg_get(bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(hold_allowed));
+
                if (!hold_allowed) {
 
                        chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
                        misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
                        break;
                }
-               
-               struct ast_channel *bridged=ast_bridged_channel(ch->ast);
 
                if (bridged) {
-                       chan_misdn_log(2,bc->port,"Bridge Partner is of type: %s\n",bridged->tech->type);
+                       chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", bridged->tech->type);
                        ch->state = MISDN_HOLDED;
                        ch->l3id = bc->l3_id;
                        
@@ -4681,9 +4895,9 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        ast_moh_start(bridged, NULL, NULL);
 
                        /*forget the channel now*/
-                       ch->bc=NULL;
-                       ch->hold_info.port=bc->port;
-                       ch->hold_info.channel=bc->channel;
+                       ch->bc = NULL;
+                       ch->hold_info.port = bc->port;
+                       ch->hold_info.channel = bc->channel;
 
                } else {
                        misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
@@ -4693,62 +4907,69 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
        break;
        
        case EVENT_FACILITY:
-               if (!ch) {
-                       /* This may come from a call we don't know nothing about, so we ignore it. */
-                       chan_misdn_log(-1, bc->port, "Got EVENT_FACILITY but we don't have a ch!\n");
-                       break;
-               }
-
                print_facility(&(bc->fac_in), bc);
                
                switch (bc->fac_in.Function) {
+#ifdef HAVE_MISDN_FAC_RESULT
+               case Fac_RESULT:
+               break;
+#endif
                case Fac_CD:
-                       {
-                               struct ast_channel *bridged=ast_bridged_channel(ch->ast);
+                       if (ch) {
+                               struct ast_channel *bridged = ast_bridged_channel(ch->ast);
                                struct chan_list *ch_br;
                                if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
-                                       ch_br=MISDN_ASTERISK_TECH_PVT(bridged);
-                                       /*ch->state=MISDN_FACILITY_DEFLECTED;*/
+                                       ch_br = MISDN_ASTERISK_TECH_PVT(bridged);
+                                       /*ch->state = MISDN_FACILITY_DEFLECTED;*/
                                        if (ch_br->bc) {
                                                if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
-                                                       ch_br->state=MISDN_DIALING;
+                                                       ch_br->state = MISDN_DIALING;
                                                        if (pbx_start_chan(ch_br) < 0) {
                                                                chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
                                                        }
                                                }
                                        }
-
                                }
                                misdn_lib_send_event(bc, EVENT_DISCONNECT);
                        } 
                        break;
                case Fac_AOCDCurrency:
-                       bc->AOCDtype = Fac_AOCDCurrency;
-                       memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(struct FacAOCDCurrency));
-                       bc->AOCD_need_export = 1;
-                       export_aoc_vars(ch->originator, ch->ast, bc);
+                       if (ch) {
+                               bc->AOCDtype = Fac_AOCDCurrency;
+                               memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(bc->AOCD.currency));
+                               bc->AOCD_need_export = 1;
+                               export_aoc_vars(ch->originator, ch->ast, bc);
+                       }
                        break;
                case Fac_AOCDChargingUnit:
-                       bc->AOCDtype = Fac_AOCDChargingUnit;
-                       memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(struct FacAOCDChargingUnit));
-                       bc->AOCD_need_export = 1;
-                       export_aoc_vars(ch->originator, ch->ast, bc);
+                       if (ch) {
+                               bc->AOCDtype = Fac_AOCDChargingUnit;
+                               memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(bc->AOCD.chargingUnit));
+                               bc->AOCD_need_export = 1;
+                               export_aoc_vars(ch->originator, ch->ast, bc);
+                       }
                        break;
+               case Fac_None:
+#ifdef HAVE_MISDN_FAC_ERROR
+               case Fac_ERROR:
+#endif
+               break;
                default:
-                       chan_misdn_log(0, bc->port," --> not yet handled: facility type:%p\n", bc->fac_in.Function);
+                       chan_misdn_log(0, bc->port," --> not yet handled: facility type:%d\n", bc->fac_in.Function);
                }
                
                break;
 
        case EVENT_RESTART:
 
-               stop_bc_tones(ch);
-               release_chan(bc);
-               
+               if (!bc->dummy) {
+                       stop_bc_tones(ch);
+                       release_chan(bc);
+               }
                break;
-                               
+
        default:
-               chan_misdn_log(1,0, "Got Unknown Event\n");
+               chan_misdn_log(1, 0, "Got Unknown Event\n");
                break;
        }
        
@@ -4773,26 +4994,27 @@ static int unload_module(void)
 
        misdn_tasks_destroy();
        
-       if (!g_config_initialized) return 0;
+       if (!g_config_initialized)
+               return 0;
        
        ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
        
        /* ast_unregister_application("misdn_crypt"); */
        ast_unregister_application("misdn_set_opt");
        ast_unregister_application("misdn_facility");
+       ast_unregister_application("misdn_check_l2l1");
   
        ast_channel_unregister(&misdn_tech);
 
-
        free_robin_list();
        misdn_cfg_destroy();
        misdn_lib_destroy();
   
        if (misdn_debug)
-               free(misdn_debug);
+               ast_free(misdn_debug);
        if (misdn_debug_only)
-               free(misdn_debug_only);
-       free(misdn_ports);
+               ast_free(misdn_debug_only);
+       ast_free(misdn_ports);
        
        return 0;
 }
@@ -4800,99 +5022,110 @@ static int unload_module(void)