Merge the cli_cleanup branch.
[asterisk/asterisk.git] / channels / chan_misdn.c
index 1eaa640..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"
@@ -99,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
@@ -114,6 +105,9 @@ 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 */
 
@@ -122,7 +116,7 @@ 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 */
@@ -137,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 */
   
@@ -291,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 );
@@ -368,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)
@@ -400,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");
        }
 }
 
@@ -646,7 +633,7 @@ static int misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const v
 
 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 (const void *data)
@@ -679,9 +666,16 @@ static int misdn_overlap_dial_task (const 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");
@@ -690,10 +684,9 @@ static int misdn_overlap_dial_task (const 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;
@@ -735,24 +728,42 @@ static void send_digit_to_chan(struct chan_list *cl, char digit )
                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)
 {
        int level;
 
-       if (argc != 4 && argc != 5 && argc != 6 && argc != 7)
-               return RESULT_SHOWUSAGE; 
+       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);
+       }
 
-       level = atoi(argv[3]);
+       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 (argc) {
+       switch (a->argc) {
        case 4: 
        case 5:
                {
                        int only = 0, i;
-                       if (argc == 5) {
-                               if (strncasecmp(argv[4], "only", strlen(argv[4])))
-                                       return RESULT_SHOWUSAGE;
+                       if (a->argc == 5) {
+                               if (strncasecmp(a->argv[4], "only", strlen(a->argv[4])))
+                                       return CLI_SHOWUSAGE;
                                else
                                        only = 1;
                        }
@@ -761,138 +772,193 @@ static int misdn_set_debug(int fd, int argc, char *argv[])
                                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)":"");
+                       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(argv[4], "port", strlen(argv[4])))
-                               return RESULT_SHOWUSAGE;
-                       port = atoi(argv[5]);
+                       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(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
+                                       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(fd, "port number not valid! only port 1 is availble.\n");
+                                       ast_cli(a->fd, "port number not valid! only port 1 is available.\n");
                                        break;
                                default:
-                                       ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
+                                       ast_cli(a->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;
+                       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(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
+                       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? */
 
-static int misdn_port_block(int fd, int argc, char *argv[])
+       return CLI_SUCCESS;
+}
+
+static char *handle_cli_misdn_port_block(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       int port;
+       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;
+       }
 
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
-  
-       port = atoi(argv[3]);
+       if (a->argc != 4)
+               return CLI_SHOWUSAGE;
 
-       misdn_lib_port_block(port);
+       misdn_lib_port_block(atoi(a->argv[3]));
 
-       return 0;
+       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];
@@ -913,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;
@@ -923,75 +991,83 @@ 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, sizeof(buffer));
-                       ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
+                       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, sizeof(buffer));
-                               ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
+                               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, sizeof(buffer));
-                               ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
+                               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 {
@@ -1002,7 +1078,7 @@ struct state_struct {
 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 */
@@ -1017,11 +1093,10 @@ 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 const char *misdn_get_ch_state(struct chan_list *p) 
@@ -1064,11 +1139,26 @@ 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)
@@ -1126,27 +1216,51 @@ static void print_bc_info (int fd, struct chan_list *help, struct misdn_bchannel
 
 }
 
-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;
   
+       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(fd, "Bc:%p Ast:%p\n", bc, ast);
+                       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,
@@ -1154,178 +1268,310 @@ static int misdn_show_cls(int fd, int argc, char *argv[])
                                                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);
                        }
                }
        }
 
        misdn_dump_chanlist();
-       return 0;
+
+       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 (a->argc != 4)
+               return CLI_SHOWUSAGE;
+
+       help = cl_te;
 
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
-  
        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;
 
-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;
 
+       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)" : "");
+               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");
-       
+       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;
+       }
+
+       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(fd, "%d\t%d\t\t%d\n", port, misdn_in_calls[port], misdn_out_calls[port]);
+               ast_cli(a->fd, "%d\t%d\t\t%d\n", port, misdn_in_calls[port], misdn_out_calls[port]);
        }
-       ast_cli(fd, "\n");
+       ast_cli(a->fd, "\n");
 
-       return 0;
+       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;
        char buf[128];
-       
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
-  
-       port = atoi(argv[3]);
-  
-       ast_cli(fd, "BEGIN STACK_LIST:\n");
 
+       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;
+       }
+
+       if (a->argc != 4)
+               return CLI_SHOWUSAGE;
+
+       port = atoi(a->argv[3]);
+  
+       ast_cli(a->fd, "BEGIN STACK_LIST:\n");
        get_show_stack_details(port, buf);
-       ast_cli(fd, "  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
+       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_send_cd(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 *nr;
        struct chan_list *tmp;
-  
-       if (argc != 5)
-               return RESULT_SHOWUSAGE;
-  
-       channame = argv[3];
-       nr = argv[4];
+       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 Calldeflection (%s) to %s\n", nr, channame);
-       
-       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; 
+               return NULL;
+       case CLI_GENERATE:
+               return complete_ch(a);
        }
 
-       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; 
+       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_verbose("Sending CD with nr %s to %s failed: Channel does not exist.\n",nr, channame);
+                       return 0; 
+               }
+
+               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);
        }
-       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);
 
-       return 0; 
+       return CLI_SUCCESS;
 }
 
-static int misdn_send_restart(int fd, int argc, char *argv[])
+static char *handle_cli_misdn_send_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       int port;
-       int channel;
-       
-       if ( (argc < 4) ||  (argc >  5) )
-               return RESULT_SHOWUSAGE;
-  
-       port = atoi(argv[3]);
+       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 (argc==5) {
-               channel = atoi(argv[4]);
-               misdn_lib_send_restart(port, channel);
-       } else
-               misdn_lib_send_restart(port, -1 );
-       
-       return 0;
+       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_send_digit(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;
 
-       if (argc != 5)
-               return RESULT_SHOWUSAGE;
+       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);
+       }
 
-       channame = argv[3];
-       msg = argv[4];
+       if (a->argc != 5)
+               return CLI_SHOWUSAGE;
+
+       channame = a->argv[3];
+       msg = a->argv[4];
        msglen = strlen(msg);
 
-       ast_cli(fd, "Sending %s to %s\n", msg, channame);
+       ast_cli(a->fd, "Sending %s to %s\n", msg, 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);
-               return 0; 
+               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(fd, "Sending: %c\n", msg[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);
@@ -1335,26 +1581,36 @@ static int misdn_send_digit(int fd, int argc, char *argv[])
        ast_dtmf_stream(tmp->ast, NULL, msg, 250);
 #endif
 
-       return 0; 
+       return CLI_SUCCESS;
 }
 
-static int misdn_toggle_echocancel(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;
        struct chan_list *tmp;
 
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
-       
-       channame = argv[3];
+       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];
   
-       ast_cli(fd, "Toggling EchoCancel on %s\n", channame);
+       ast_cli(a->fd, "Toggling EchoCancel on %s\n", channame);
   
        tmp = get_chan_by_ast_name(channame);
-    
        if (!tmp) {
-               ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
-               return 0; 
+               ast_cli(a->fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
+               return CLI_SUCCESS;
        }
 
        tmp->toggle_ec = tmp->toggle_ec?0:1;
@@ -1370,120 +1626,110 @@ static int misdn_toggle_echocancel(int fd, int argc, char *argv[])
                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_send_display(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       char *channame; 
-       char *msg; 
+       char *channame;
+       char *msg;
        struct chan_list *tmp;
 
-       if (argc != 5)
-               return RESULT_SHOWUSAGE;
+       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;
+       case CLI_GENERATE:
+               return complete_ch(a);
+       }
+
+       if (a->argc != 5)
+               return CLI_SHOWUSAGE;
 
-       channame = argv[3];
-       msg = argv[4];
+       channame = a->argv[3];
+       msg = a->argv[4];
 
-       ast_cli(fd, "Sending %s to %s\n", msg, channame);
+       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(fd, "No such channel %s\n", channame);
-               return RESULT_FAILURE;
+               ast_cli(a->fd, "No such channel %s\n", channame);
+               return CLI_SUCCESS;
        }
 
-       return RESULT_SUCCESS ;
-}
-
-static char *complete_ch_helper(const char *line, const char *word, int pos, int state, int rpos)
-{
-       struct ast_channel *c;
-       int which = 0;
-       char *ret;
-       if (pos != rpos)
-               return NULL;
-       for (c = ast_channel_walk_locked(NULL); c; c = ast_channel_walk_locked(c)) {
-               if (!strncasecmp(word, c->name, strlen(word))) {
-                       if (++which > state)
-                               break;
-               }
-               ast_mutex_unlock(&c->lock);
-       }
-       if (c) {
-               ret = ast_strdup(c->name);
-               ast_mutex_unlock(&c->lock);
-       } else
-               ret = NULL;
-       return ret;
+       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) {
+       switch (a->pos) {
        case 4:
-               if (*word == 'p')
+               if (a->word[0] == 'p')
                        return ast_strdup("port");
-               else if (*word == 'o')
+               else if (a->word[0] == 'o')
                        return ast_strdup("only");
                break;
        case 6:
-               if (*word == 'o')
+               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) {
+       switch (a->pos) {
        case 3:
-               if ((!strncmp(word, "description", wordlen)) && (++which > state))
+               if ((!strncmp(a->word, "description", wordlen)) && (++which > a->n))
                        return ast_strdup("description");
-               if ((!strncmp(word, "descriptions", wordlen)) && (++which > state))
+               if ((!strncmp(a->word, "descriptions", wordlen)) && (++which > a->n))
                        return ast_strdup("descriptions");
-               if ((!strncmp(word, "0", wordlen)) && (++which > state))
+               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(word, buffer, wordlen)) && (++which > state)) {
+                       if ((!strncmp(a->word, buffer, wordlen)) && (++which > a->n)) {
                                return ast_strdup(buffer);
                        }
                }
                break;
        case 4:
-               if (strstr(line, "description ")) {
+               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(word, buffer, wordlen)) {
-                                       if (++which > state)
+                               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))
+               } else if (strstr(a->line, "descriptions ")) {
+                       if ((!wordlen || !strncmp(a->word, "general", wordlen)) && (++which > a->n))
                                return ast_strdup("general");
-                       if ((!wordlen || !strncmp(word, "ports", wordlen)) && (++which > state))
+                       if ((!wordlen || !strncmp(a->word, "ports", wordlen)) && (++which > a->n))
                                return ast_strdup("ports");
                }
                break;
@@ -1492,54 +1738,27 @@ static char *complete_show_config (const char *line, const char *word, int pos,
 }
 
 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","send","restart", NULL},  misdn_send_restart, 
-         "Sends a restart for every bchannel on the given port", 
-         "Usage: misdn send 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) 
@@ -1582,46 +1801,42 @@ static int update_config(struct chan_list *ch, int orig)
        misdn_cfg_get(port, MISDN_CFG_SCREEN, &screen, sizeof(screen));
        chan_misdn_log(2, port, " --> pres: %d screen: %d\n", pres, screen);
                
-       if ( (pres + screen) < 0 ) {
-
+       if (pres < 0 || screen < 0) {
                chan_misdn_log(2, port, " --> pres: %x\n", ast->cid.cid_pres);
                        
                switch (ast->cid.cid_pres & 0x60) {
-                               
                case AST_PRES_RESTRICTED:
                        bc->pres = 1;
-                       chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
+                       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");
+                       chan_misdn_log(2, port, " --> PRES: Unavailable (2)\n");
                        break;
                default:
                        bc->pres = 0;
-                       chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
+                       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");
+                       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");
+                       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");
+                       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");
+                       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;
@@ -1920,9 +2135,9 @@ static int read_config(struct chan_list *ch, int orig)
                        ch->dsp = ast_dsp_new();
                if (ch->dsp) {
                        if (ch->faxdetect) 
-                               ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT | DSP_FEATURE_FAX_DETECT);
+                               ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_FAX_DETECT);
                        else 
-                               ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT );
+                               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);
@@ -2086,13 +2301,13 @@ static int misdn_answer(struct ast_channel *ast)
        
        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);
        }
 
        tmp = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
@@ -2144,19 +2359,19 @@ static int misdn_digit_end(struct ast_channel *ast, char digit, unsigned int dur
        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:
                if (strlen(bc->infos_pending) < sizeof(bc->infos_pending) - 1)
-                       strncat(bc->infos_pending, buf, sizeof(bc->infos_pending) - 1);
+                       strncat(bc->infos_pending, buf, sizeof(bc->infos_pending) - strlen(bc->infos_pending) - 1);
                break;
        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) - 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;
@@ -2227,7 +2442,7 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
                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);
+                       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);
@@ -2299,9 +2514,11 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
                        start_bc_tones(p);
                break;
        case AST_CONTROL_HOLD:
+               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:
+               ast_moh_stop(ast);
                chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
                break;
        default:
@@ -2407,6 +2624,7 @@ static int misdn_hangup(struct ast_channel *ast)
                start_bc_tones(p);
                hanguptone_indicate(p);
                
+               p->state=MISDN_CLEANING;
                if (bc->need_disconnect)
                        misdn_lib_send_event( bc, EVENT_DISCONNECT);
                break;
@@ -2430,11 +2648,11 @@ static int misdn_hangup(struct ast_channel *ast)
                break;
        case MISDN_CONNECTED:
        case MISDN_PRECONNECTED:
-               /*  Alerting or Disconect */
+               /*  Alerting or Disconnect */
                if (p->bc->nt) {
                        start_bc_tones(p);
                        hanguptone_indicate(p);
-                       p->bc->progress_indicator = 8;
+                       p->bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
                }
                if (bc->need_disconnect)
                        misdn_lib_send_event( bc, EVENT_DISCONNECT);
@@ -2442,7 +2660,8 @@ static int misdn_hangup(struct ast_channel *ast)
                /*p->state=MISDN_CLEANING;*/
                break;
        case MISDN_DISCONNECTED:
-               misdn_lib_send_event( bc, EVENT_RELEASE);
+               if (bc->need_release)
+                       misdn_lib_send_event( bc, EVENT_RELEASE);
                p->state = MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
                break;
 
@@ -2460,13 +2679,15 @@ static int misdn_hangup(struct ast_channel *ast)
                chan_misdn_log(1, bc->port, " --> out_cause %d\n", bc->out_cause);
 
                bc->out_cause = -1;
-               misdn_lib_send_event(bc, EVENT_RELEASE);
+               if (bc->need_release)
+                       misdn_lib_send_event(bc, EVENT_RELEASE);
                p->state = MISDN_CLEANING;
                break;
        default:
                if (bc->nt) {
                        bc->out_cause = -1;
-                       misdn_lib_send_event(bc, EVENT_RELEASE);
+                       if (bc->need_release)
+                               misdn_lib_send_event(bc, EVENT_RELEASE);
                        p->state = MISDN_CLEANING; 
                } else {
                        if (bc->need_disconnect)
@@ -2604,6 +2825,7 @@ static struct ast_frame *misdn_read(struct ast_channel *ast)
                return NULL;
        }
 
+       tmp->frame.frametype = AST_FRAME_VOICE;
        tmp->frame.subclass = AST_FORMAT_ALAW;
        tmp->frame.datalen = len;
        tmp->frame.samples = len;
@@ -2611,7 +2833,7 @@ static struct ast_frame *misdn_read(struct ast_channel *ast)
        tmp->frame.offset = 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) {
@@ -2662,7 +2884,7 @@ 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;
        }
 
@@ -2707,7 +2929,7 @@ static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
                ast_debug(1, "write2mISDN %p %d bytes: ", p, frame->samples);
 
                for (i = 0; i < max ; i++)
-                       ast_debug(1, "%2.2x ", ((char*) frame->data)[i]);
+                       ast_debug(1, "%2.2x ", ((char*) frame->data.ptr)[i]);
        }
 #endif
 
@@ -2717,29 +2939,28 @@ static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
                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);
-
+                       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");
                }
                
        } 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;
@@ -2812,11 +3033,10 @@ static enum ast_bridge_result  misdn_bridge (struct ast_channel *c0,
                        if (!f) 
                                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);
+                               chan_misdn_log(4, ch1->bc->port, "Read Frame Control class:%d\n", f->subclass);
 
                        *fo = f;
                        *rc = who;
-
                        break;
                }
                
@@ -2990,7 +3210,7 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
        }
 
        if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
-               chan_misdn_log(4, port, " --> STARTING STANDARDDEC...\n");
+               chan_misdn_log(4, port, " --> STARTING STANDARD DEC...\n");
                dec = 1;
        }
 
@@ -3185,6 +3405,7 @@ static void update_name(struct ast_channel *tmp, int port, int c)
 {
        int chan_offset = 0;
        int tmp_port = misdn_cfg_get_next_port(0);
+       char newname[255];
        for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
                if (tmp_port == port)
                        break;
@@ -3193,10 +3414,12 @@ static void update_name(struct ast_channel *tmp, int port, int c)
        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)
@@ -3210,15 +3433,16 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state,  char
        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;        
+               chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
        }
        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/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
+       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++);
 
        if (tmp) {
                chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n", exten, callerid);
@@ -3263,7 +3487,7 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state,  char
                else
                        tmp->rings = 0;
                
-               ast_jb_configure(tmp, misdn_get_global_jbconf());
+               ast_jb_configure(tmp, misdn_get_global_jbconf());
        } else {
                chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
        }
@@ -3379,7 +3603,7 @@ 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);       
 
@@ -3420,7 +3644,7 @@ static void hangup_chan(struct chan_list *ch)
                send_cause2ast(ch->ast, ch->bc, ch);
 
                if (ch->ast)
-                       ast_queue_hangup(ch->ast);
+                       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");
@@ -3446,7 +3670,7 @@ static void release_chan(struct misdn_bchannel *bc) {
 
                chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n", bc->l3_id);
 
-               /*releaseing jitterbuffer*/
+               /*releasing jitterbuffer*/
                if (ch->jb ) {
                        misdn_jb_destroy(ch->jb);
                        ch->jb = NULL;
@@ -3499,7 +3723,7 @@ static void release_chan(struct misdn_bchannel *bc) {
 
 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);
+       chan_misdn_log(4, 0, "TRANSFERRING %s to %s\n", holded_chan->ast->name, tmp_ch->ast->name);
 
        tmp_ch->state = MISDN_HOLD_DISCONNECT;
 
@@ -3556,7 +3780,7 @@ static void do_immediate_setup(struct misdn_bchannel *bc, struct chan_list *ch,
                fr.frametype = AST_FRAME_DTMF;
                fr.subclass = *predial;
                fr.src = NULL;
-               fr.data = NULL;
+               fr.data.ptr = NULL;
                fr.datalen = 0;
                fr.samples = 0;
                fr.mallocd = 0;
@@ -3590,12 +3814,13 @@ static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, s
 
        switch (bc->cause) {
 
-       case 1: /** Congestion Cases **/
-       case 2:
-       case 3:
-       case 4:
-       case 22:
-       case 27:
+       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
@@ -3607,9 +3832,8 @@ static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, s
                */
                break;
 
-       case 21:
-       case 17: /* user busy */
-
+       case AST_CAUSE_CALL_REJECTED:
+       case AST_CAUSE_USER_BUSY:
                ch->state = MISDN_BUSY;
 
                if (!ch->need_busy) {
@@ -3841,7 +4065,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                fr.frametype = AST_FRAME_DTMF;
                fr.subclass = bc->dtmf ;
                fr.src = NULL;
-               fr.data = NULL;
+               fr.data.ptr = NULL;
                fr.datalen = 0;
                fr.samples = 0;
                fr.mallocd = 0;
@@ -3852,7 +4076,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        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;
@@ -3874,7 +4098,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                                ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
                        }
 
-                       strncat(bc->dad,bc->info_dad, sizeof(bc->dad) - 1);
+                       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 */
@@ -3901,14 +4125,14 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                                        break;
                                }
 
-                               ast_log(LOG_WARNING, "Extension can never match, so disconnecting on port(%d)."
-                                               "maybe you want to add an 'i' extension to catch this case.\n",
+                               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;
+                               bc->out_cause = AST_CAUSE_UNALLOCATED;
 
                                misdn_lib_send_event(bc, EVENT_DISCONNECT);
                                break;
@@ -3934,10 +4158,11 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        /*  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.data.ptr = NULL;
                        fr.datalen = 0;
                        fr.samples = 0;
                        fr.mallocd = 0;
@@ -3947,7 +4172,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(digits));
                        if (ch->state != MISDN_CONNECTED ) {
                                if (digits) {
-                                       strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - 1);
+                                       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);
                                }
@@ -3987,7 +4212,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        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 : 16;
+                       bc->out_cause = cause ? cause : AST_CAUSE_NORMAL_CLEARING;
                        return RESPONSE_RELEASE_SETUP;
                }
 
@@ -4002,7 +4227,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        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 : 16;
+                       bc->out_cause = cause ? cause : AST_CAUSE_NORMAL_CLEARING;
                        return RESPONSE_RELEASE_SETUP;
                }
 
@@ -4050,17 +4275,19 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        break;
                case 2:
                        pres = AST_PRES_UNAVAILABLE;
-                       chan_misdn_log(2, bc->port, " --> PRES: Restricted (2)\n");
+                       chan_misdn_log(2, bc->port, " --> PRES: Unavailable (2)\n");
                        break;
                default:
                        pres = AST_PRES_ALLOWED;
-                       chan_misdn_log(2, bc->port, " --> PRES: Restricted (%d)\n", bc->pres);
+                       chan_misdn_log(2, bc->port, " --> PRES: Allowed (%d)\n", bc->pres);
+                       break;
                }
 
                switch (bc->screen) {
+               default:
                case 0:
                        screen = AST_PRES_USER_NUMBER_UNSCREENED;
-                       chan_misdn_log(2, bc->port, " --> SCREEN: Unscreened (0)\n");
+                       chan_misdn_log(2, bc->port, " --> SCREEN: Unscreened (%d)\n", bc->screen);
                        break;
                case 1:
                        screen = AST_PRES_USER_NUMBER_PASSED_SCREEN;
@@ -4074,12 +4301,9 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        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;
@@ -4097,18 +4321,28 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
 
                if (!strstr(ch->allowed_bearers, "all")) {
                        int i;
-                       for (i = 0; i < sizeof(allowed_bearers_array) / sizeof(struct allowed_bearers); i++) {
-                               if (allowed_bearers_array[i].cap == bc->capability) {
-                                       if (!strstr(ch->allowed_bearers, allowed_bearers_array[i].name)) {
-                                               chan_misdn_log(0, bc->port, "Bearer Not allowed\b");
-                                               bc->out_cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
 
-                                               ch->state = MISDN_EXTCANTMATCH;
-                                               misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
-                                               return RESPONSE_OK;
+                       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)) {
+                                               /* 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;
                        }
                }
 
@@ -4159,8 +4393,8 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                                break;
                        }
 
-                       ast_log(LOG_WARNING, "Extension can never match, so disconnecting on port(%d)."
-                                       "maybe you want to add an 'i' extension to catch this case.\n",
+                       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);
@@ -4190,6 +4424,17 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        break;
                }
 
+
+               /*
+                * 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 overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more 
                 * Infos with a Interdigit Timeout.
@@ -4199,15 +4444,15 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        ch->overlap_tv = ast_tvnow();
                        ast_mutex_unlock(&ch->overlap_tv_lock);
 
+                       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);
 
-                       wait_for_digits(ch, bc, chan);
                        break;
                }
 
-               /* If the extension does not exist and we're not TE_PTMP we wait for more digis 
+               /* 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))  {
@@ -4455,7 +4700,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                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;
@@ -4499,7 +4744,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        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);
@@ -4524,7 +4769,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        }
                        
                        if (FD_ISSET(ch->pipe[1], &wrfs)) {
-                               chan_misdn_log(9, bc->port, "writing %d bytes 2 asterisk\n", bc->bframe_len);
+                               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));
 
@@ -4554,7 +4799,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                case MISDN_PROCEEDING:
                case MISDN_CALLING_ACKNOWLEDGE:
                        if (bc->nt) {
-                               bc->progress_indicator = 8;
+                               bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
                                hanguptone_indicate(ch);
                        }
                                
@@ -4564,7 +4809,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
 
                case MISDN_WAITING4DIGS:
                        if (bc->nt) {
-                               bc->progress_indicator = 8;
+                               bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
                                bc->out_cause = AST_CAUSE_UNALLOCATED;
                                hanguptone_indicate(ch);
                                misdn_lib_send_event(bc, EVENT_DISCONNECT);
@@ -4576,7 +4821,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        break;
 
                case MISDN_CLEANING: 
-                       chan_misdn_log(1,bc->port," --> in state cleaning .. so ingoring, the stack should clean it for us\n");
+                       chan_misdn_log(1,bc->port," --> in state cleaning .. so ignoring, the stack should clean it for us\n");
                        break;
 
                default:
@@ -4586,9 +4831,9 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
        break;
 
     
-       /***************************/
-       /** Suplementary Services **/
-       /***************************/
+       /****************************/
+       /** Supplementary Services **/
+       /****************************/
        case EVENT_RETRIEVE:
        {
                struct ast_channel *hold_ast;
@@ -4662,17 +4907,15 @@ 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:
-                       {
+                       if (ch) {
                                struct ast_channel *bridged = ast_bridged_channel(ch->ast);
                                struct chan_list *ch_br;
                                if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
@@ -4691,19 +4934,28 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        } 
                        break;
                case Fac_AOCDCurrency:
-                       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);
+                       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(bc->AOCD.chargingUnit));
-                       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;
@@ -4770,7 +5022,7 @@ static int unload_module(void)
 static int load_module(void)
 {
        int i, port;
-       int ntflags = 0;
+       int ntflags = 0, ntkc = 0;
        char ports[256] = "";
        char tempbuf[BUFFERSIZE + 1];
        char ntfile[BUFFERSIZE + 1];
@@ -4831,13 +5083,14 @@ static int load_module(void)
 
        if (!ast_strlen_zero(ports))
                chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
-
        if (misdn_lib_init(ports, &iface, NULL))
                chan_misdn_log(0, 0, "No te ports initialized\n");
 
        misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(ntflags));
        misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, sizeof(ntfile));
+       misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(ntkc));
 
+       misdn_lib_nt_keepcalls(ntkc);
        misdn_lib_nt_debug_init(ntflags, ntfile);
 
        if (ast_channel_register(&misdn_tech)) {
@@ -4849,20 +5102,30 @@ static int load_module(void)
        ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
 
        ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
-                                "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
-                                "Sets mISDN opts. and optargs\n"
-                                "\n"
-                                "The available options are:\n"
-                                "    d - Send display text on called phone, text is the optparam\n"
-                                "    n - don't detect dtmf tones on called channel\n"
-                                "    h - make digital outgoing call\n" 
-                                "    c - make crypted outgoing call, param is keyindex\n"
-                                "    e - perform echo cancelation on this channel,\n"
-                                "        takes taps as arguments (32,64,128,256)\n"
-                                "    s - send Non Inband DTMF as inband\n"
-                                "   vr - rxgain control\n"
-                                "   vt - txgain control\n"
-                                "    i - Ignore detected dtmf tones, don't signal them to asterisk, they will be transported inband.\n"
+               "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
+               "Sets mISDN opts. and optargs\n"
+               "\n"
+               "The available options are:\n"
+               "    a - Have Asterisk detect DTMF tones on called channel\n"
+               "    c - Make crypted outgoing call, optarg is keyindex\n"
+               "    d - Send display text to called phone, text is the optarg\n"
+               "    e - Perform echo cancelation on this channel,\n"
+               "        takes taps as optarg (32,64,128,256)\n"
+               "   e! - Disable echo cancelation on this channel\n"
+               "    f - Enable fax detection\n"
+               "    h - Make digital outgoing call\n" 
+               "   h1 - Make HDLC mode digital outgoing call\n" 
+               "    i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
+               "        they will be transported inband.\n"
+               "   jb - Set jitter buffer length, optarg is length\n"
+               "   jt - Set jitter buffer upper threshold, optarg is threshold\n"
+               "   jn - Disable jitter buffer\n"
+               "    n - disable DSP on channel, disables: Echocancel, DTMF Detection and Volume Control.\n"
+               "    p - Caller ID presentation,\n"
+               "        optarg is either 'allowed' or 'restricted'\n"
+               "    s - Send Non-inband DTMF as inband\n"
+               "   vr - Rx gain control, optarg is gain\n"
+               "   vt - Tx gain control, optarg is gain\n"
                );
 
        
@@ -5213,7 +5476,10 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
                        /* CRICH: callingpres!!! */
                        if (strstr(tok,"allowed")) {
                                ch->bc->pres = 0;
+                       } else if (strstr(tok, "restricted")) {
+                               ch->bc->pres = 1;
                        } else if (strstr(tok, "not_screened")) {
+                               chan_misdn_log(0, ch->bc->port, "SETOPT: callerpres: not_screened is deprecated\n");
                                ch->bc->pres = 1;
                        }
                        break;
@@ -5233,7 +5499,7 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
                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);
+                       ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_FAX_DETECT);
                if (!ch->trans)
                        ch->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
        }
@@ -5266,7 +5532,7 @@ int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len)
 /*******************************************************/
 
 
-/* allocates the jb-structure and initialise the elements*/
+/* allocates the jb-structure and initialize the elements*/
 struct misdn_jb *misdn_jb_init(int size, int upper_threshold)
 {
        int i;
@@ -5319,7 +5585,7 @@ void misdn_jb_destroy(struct misdn_jb *jb)
 }
 
 /* fills the jitterbuffer with len data returns < 0 if there was an
-   error (bufferoverflow). */
+   error (buffer overflow). */
 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
 {
        int i, j, rp, wp;
@@ -5345,7 +5611,7 @@ int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
                jb->state_buffer = wp - rp;
        else
                jb->state_buffer = jb->size - rp + wp;
-       chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Bufferstatus:%d p:%x\n", len, jb->state_buffer, jb);
+       chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
 
        if (jb->state_full) {
                jb->wp = wp;
@@ -5411,11 +5677,11 @@ int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
                        jb->state_buffer = wp - rp;
                else
                        jb->state_buffer = jb->size - rp + wp;
-               chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Bufferstatus:%d p:%x\n", len, jb->state_buffer, jb);
+               chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
 
                jb->rp = rp;
        } else
-               chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%x\n", len, jb);
+               chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
 
        ast_mutex_unlock(&jb->mutexjb);
 
@@ -5432,7 +5698,7 @@ int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
 
 
 
-void chan_misdn_log(int level, int port, char *tmpl, ...)
+static void chan_misdn_log(int level, int port, char *tmpl, ...)
 {
        va_list ap;
        char buf[1024];
@@ -5451,7 +5717,7 @@ void chan_misdn_log(int level, int port, char *tmpl, ...)
        va_end(ap);
 
        if (level == -1)
-               ast_log(LOG_WARNING, buf);
+               ast_log(LOG_WARNING, "%s", buf);
 
        else if (misdn_debug_only[port] ? 
                        (level == 1 && misdn_debug[port]) || (level == misdn_debug[port])