WIP: chan_lcr support for Asterisk 11.5
[lcr.git] / chan_lcr.c
index b3c42cc..95972a9 100644 (file)
@@ -40,7 +40,7 @@ a new call reference (ref).
 The ref_was_assigned ist set to 1.
 Further dialing information is queued.
 After the new callref is received by special MESSAGE_NEWREF reply, new ref
 The ref_was_assigned ist set to 1.
 Further dialing information is queued.
 After the new callref is received by special MESSAGE_NEWREF reply, new ref
-is stored in the chan_call structure. 
+is stored in the chan_call structure.
 The setup information is sent to LCR using MESSAGE_SETUP.
 The state changes to CHAN_LCR_STATE_OUT_SETUP.
 
 The setup information is sent to LCR using MESSAGE_SETUP.
 The state changes to CHAN_LCR_STATE_OUT_SETUP.
 
@@ -129,11 +129,20 @@ it is called from ast_channel process which has already locked ast_channel.
 #define HAVE_ATTRIBUTE_always_inline 1
 #define HAVE_ARPA_INET_H 1
 #define HAVE_TIMERSUB 1
 #define HAVE_ATTRIBUTE_always_inline 1
 #define HAVE_ARPA_INET_H 1
 #define HAVE_TIMERSUB 1
+#define HAVE_STRTOQ 1
+#define HAVE_INET_ATON 1
 
 #include <asterisk/compiler.h>
 #ifdef LCR_FOR_ASTERISK
 #include <asterisk/buildopts.h>
 #endif
 
 #include <asterisk/compiler.h>
 #ifdef LCR_FOR_ASTERISK
 #include <asterisk/buildopts.h>
 #endif
+
+/*
+ * Fwd declare struct ast_channel to get rid of gcc warning about
+ * incompatible pointer type passed to ast_register_application2.
+ */
+struct ast_channel;
+
 #include <asterisk/module.h>
 #include <asterisk/channel.h>
 #include <asterisk/config.h>
 #include <asterisk/module.h>
 #include <asterisk/channel.h>
 #include <asterisk/config.h>
@@ -159,14 +168,14 @@ it is called from ast_channel process which has already locked ast_channel.
 #include <asterisk/app.h>
 #include <asterisk/features.h>
 #include <asterisk/sched.h>
 #include <asterisk/app.h>
 #include <asterisk/features.h>
 #include <asterisk/sched.h>
-
 #include "extension.h"
 #include "message.h"
 #include "callerid.h"
 #include "lcrsocket.h"
 #include "cause.h"
 #include "extension.h"
 #include "message.h"
 #include "callerid.h"
 #include "lcrsocket.h"
 #include "cause.h"
-#include "bchannel.h"
+#include "select.h"
 #include "options.h"
 #include "options.h"
+#include "config.h"
 #include "chan_lcr.h"
 
 CHAN_LCR_STATE // state description structure
 #include "chan_lcr.h"
 
 CHAN_LCR_STATE // state description structure
@@ -183,7 +192,6 @@ static struct ast_frame nullframe = { AST_FRAME_NULL, };
 #endif
 
 int lcr_debug=1;
 #endif
 
 int lcr_debug=1;
-int mISDN_created=1;
 
 char lcr_type[]="lcr";
 
 
 char lcr_type[]="lcr";
 
@@ -196,11 +204,20 @@ static char *desc = "Channel driver for mISDN/LCR Support (Bri/Pri)";
 pthread_t chan_tid;
 ast_mutex_t chan_lock; /* global lock */
 ast_mutex_t log_lock; /* logging log */
 pthread_t chan_tid;
 ast_mutex_t chan_lock; /* global lock */
 ast_mutex_t log_lock; /* logging log */
-int quit;
+/* global_change:
+ * used to indicate change in file descriptors, so select function's result may
+ * be obsolete.
+ */
+int global_change = 0;
+int wake_global = 0;
+int wake_pipe[2];
+struct lcr_fd wake_fd;
 
 int glob_channel = 0;
 
 int lcr_sock = -1;
 
 int glob_channel = 0;
 
 int lcr_sock = -1;
+struct lcr_fd socket_fd;
+struct lcr_timer socket_retry;
 
 struct admin_list {
        struct admin_list *next;
 
 struct admin_list {
        struct admin_list *next;
@@ -229,10 +246,15 @@ void chan_lcr_log(int type, const char *file, int line, const char *function, st
        if (call)
                sprintf(call_text, "%d", call->ref);
        if (ast)
        if (call)
                sprintf(call_text, "%d", call->ref);
        if (ast)
+#if ASTERISK_VERSION_NUM < 110000
                strncpy(ast_text, ast->name, sizeof(ast_text)-1);
                strncpy(ast_text, ast->name, sizeof(ast_text)-1);
+#else
+               strncpy(ast_text, ast_channel_name(ast), sizeof(ast_text)-1);
+#endif
        ast_text[sizeof(ast_text)-1] = '\0';
        ast_text[sizeof(ast_text)-1] = '\0';
-       
-       ast_log(type, file, line, function, "[call=%s ast=%s] %s", call_text, ast_text, buffer);
+
+//     ast_log(type, file, line, function, "[call=%s ast=%s] %s", call_text, ast_text, buffer);
+       printf("[call=%s ast=%s line=%d] %s", call_text, ast_text, line, buffer);
 
        ast_mutex_unlock(&log_lock);
 }
 
        ast_mutex_unlock(&log_lock);
 }
@@ -251,37 +273,27 @@ struct chan_call *find_call_ref(unsigned int ref)
 {
        struct chan_call *call = call_first;
        int assigned = (ref > 0);
 {
        struct chan_call *call = call_first;
        int assigned = (ref > 0);
-       
-       while(call)
-       {
+
+       while(call) {
                if (call->ref == ref && call->ref_was_assigned == assigned)
                        break;
                call = call->next;
        }
                if (call->ref == ref && call->ref_was_assigned == assigned)
                        break;
                call = call->next;
        }
-       return(call);
+       return call;
 }
 
 void free_call(struct chan_call *call)
 {
        struct chan_call **temp = &call_first;
 
 }
 
 void free_call(struct chan_call *call)
 {
        struct chan_call **temp = &call_first;
 
-       while(*temp)
-       {
-               if (*temp == call)
-               {
+       while(*temp) {
+               if (*temp == call) {
                        *temp = (*temp)->next;
                        if (call->pipe[0] > -1)
                                close(call->pipe[0]);
                        if (call->pipe[1] > -1)
                                close(call->pipe[1]);
                        *temp = (*temp)->next;
                        if (call->pipe[0] > -1)
                                close(call->pipe[0]);
                        if (call->pipe[1] > -1)
                                close(call->pipe[1]);
-                       if (call->bchannel)
-                       {
-                               if (call->bchannel->call != call)
-                                       CERROR(call, NULL, "Linked bchannel structure has no link to us.\n");
-                               call->bchannel->call = NULL;
-                       }
-                       if (call->bridge_call)
-                       {
+                       if (call->bridge_call) {
                                if (call->bridge_call->bridge_call != call)
                                        CERROR(call, NULL, "Linked call structure has no link to us.\n");
                                call->bridge_call->bridge_call = NULL;
                                if (call->bridge_call->bridge_call != call)
                                        CERROR(call, NULL, "Linked call structure has no link to us.\n");
                                call->bridge_call->bridge_call = NULL;
@@ -292,6 +304,7 @@ void free_call(struct chan_call *call)
                                ast_dsp_free(call->dsp);
                        CDEBUG(call, NULL, "Call instance freed.\n");
                        free(call);
                                ast_dsp_free(call->dsp);
                        CDEBUG(call, NULL, "Call instance freed.\n");
                        free(call);
+                       global_change = 1;
                        return;
                }
                temp = &((*temp)->next);
                        return;
                }
                temp = &((*temp)->next);
@@ -312,11 +325,15 @@ struct chan_call *alloc_call(void)
        if (pipe((*callp)->pipe) < 0) {
                CERROR(*callp, NULL, "Failed to create pipe.\n");
                free_call(*callp);
        if (pipe((*callp)->pipe) < 0) {
                CERROR(*callp, NULL, "Failed to create pipe.\n");
                free_call(*callp);
-               return(NULL);
+               return NULL;
        }
        fcntl((*callp)->pipe[0], F_SETFL, O_NONBLOCK);
        CDEBUG(*callp, NULL, "Call instance allocated.\n");
        }
        fcntl((*callp)->pipe[0], F_SETFL, O_NONBLOCK);
        CDEBUG(*callp, NULL, "Call instance allocated.\n");
-       return(*callp);
+
+       /* unset dtmf (default, use option 'd' to enable) */
+       (*callp)->dsp_dtmf = 0;
+
+       return *callp;
 }
 
 unsigned short new_bridge_id(void)
 }
 
 unsigned short new_bridge_id(void)
@@ -325,11 +342,9 @@ unsigned short new_bridge_id(void)
        unsigned short id = 1;
 
        /* search for lowest bridge id that is not in use and not 0 */
        unsigned short id = 1;
 
        /* search for lowest bridge id that is not in use and not 0 */
-       while(id)
-       {
+       while(id) {
                call = call_first;
                call = call_first;
-               while(call)
-               {
+               while(call) {
                        if (call->bridge_id == id)
                                break;
                        call = call->next;
                        if (call->bridge_id == id)
                                break;
                        call = call->next;
@@ -339,7 +354,7 @@ unsigned short new_bridge_id(void)
                id++;
        }
        CDEBUG(NULL, NULL, "New bridge ID %d.\n", id);
                id++;
        }
        CDEBUG(NULL, NULL, "New bridge ID %d.\n", id);
-       return(id);
+       return id;
 }
 
 /*
 }
 
 /*
@@ -353,7 +368,8 @@ int send_message(int message_type, unsigned int ref, union parameter *param)
                CDEBUG(NULL, NULL, "Ignoring message %d, because socket is closed.\n", message_type);
                return -1;
        }
                CDEBUG(NULL, NULL, "Ignoring message %d, because socket is closed.\n", message_type);
                return -1;
        }
-       CDEBUG(NULL, NULL, "Sending %s to socket.\n", messages_txt[message_type]);
+       if (message_type != MESSAGE_TRAFFIC)
+               CDEBUG(NULL, NULL, "Sending %s to socket. (ref=%d)\n", messages_txt[message_type], ref);
 
        adminp = &admin_first;
        while(*adminp)
 
        adminp = &admin_first;
        while(*adminp)
@@ -369,8 +385,15 @@ int send_message(int message_type, unsigned int ref, union parameter *param)
        admin->msg.u.msg.type = message_type;
        admin->msg.u.msg.ref = ref;
        memcpy(&admin->msg.u.msg.param, param, sizeof(union parameter));
        admin->msg.u.msg.type = message_type;
        admin->msg.u.msg.ref = ref;
        memcpy(&admin->msg.u.msg.param, param, sizeof(union parameter));
+       socket_fd.when |= LCR_FD_WRITE;
+       if (!wake_global) {
+               wake_global = 1;
+               char byte = 0;
+               int rc;
+               rc = write(wake_pipe[1], &byte, 1);
+       }
 
 
-       return(0);
+       return 0;
 }
 
 /*
 }
 
 /*
@@ -379,8 +402,8 @@ int send_message(int message_type, unsigned int ref, union parameter *param)
 void apply_opt(struct chan_call *call, char *data)
 {
        union parameter newparam;
 void apply_opt(struct chan_call *call, char *data)
 {
        union parameter newparam;
-       char string[1024], *p = string, *opt, *key;
-       int gain, i;
+       char string[1024], *p = string, *opt;//, *key;
+//     int gain, i;
 
        if (!data[0])
                return; // no opts
 
        if (!data[0])
                return; // no opts
@@ -389,8 +412,7 @@ void apply_opt(struct chan_call *call, char *data)
        string[sizeof(string)-1] = '\0';
 
        /* parse options */
        string[sizeof(string)-1] = '\0';
 
        /* parse options */
-       while((opt = strsep(&p, ":")))
-       {
+       while((opt = strsep(&p, ":"))) {
                switch(opt[0]) {
                case 'd':
                        if (opt[1] == '\0') {
                switch(opt[0]) {
                case 'd':
                        if (opt[1] == '\0') {
@@ -406,14 +428,15 @@ void apply_opt(struct chan_call *call, char *data)
                                send_message(MESSAGE_NOTIFY, call->ref, &newparam);
                        }
                        break;
                                send_message(MESSAGE_NOTIFY, call->ref, &newparam);
                        }
                        break;
-               case 'n':
+               case 'D':
                        if (opt[1] != '\0') {
                        if (opt[1] != '\0') {
-                               CERROR(call, call->ast, "Option 'n' (no DTMF) expects no parameter.\n", opt);
+                               CERROR(call, call->ast, "Option 'D' (DTMF) expects no parameter.\n", opt);
                                break;
                        }
                                break;
                        }
-                       CDEBUG(call, call->ast, "Option 'n' (no DTMF).\n");
-                       call->no_dtmf = 1;
+                       CDEBUG(call, call->ast, "Option 'D' (DTMF).\n");
+                       call->dsp_dtmf = 1;
                        break;
                        break;
+#if 0
                case 'c':
                        if (opt[1] == '\0') {
                                CERROR(call, call->ast, "Option 'c' (encrypt) expects key parameter.\n", opt);
                case 'c':
                        if (opt[1] == '\0') {
                                CERROR(call, call->ast, "Option 'c' (encrypt) expects key parameter.\n", opt);
@@ -431,8 +454,7 @@ void apply_opt(struct chan_call *call, char *data)
                                break;
                        }
                        i = 0;
                                break;
                        }
                        i = 0;
-                       while(*key)
-                       {
+                       while(*key) {
                                if (*key>='0' && *key<='9')
                                        call->bf_key[i] = (*key-'0') << 8;
                                else if (*key>='a' && *key<='f')
                                if (*key>='0' && *key<='9')
                                        call->bf_key[i] = (*key-'0') << 8;
                                else if (*key>='a' && *key<='f')
@@ -462,6 +484,7 @@ void apply_opt(struct chan_call *call, char *data)
                        if (call->bchannel)
                                bchannel_blowfish(call->bchannel, call->bf_key, call->bf_len);
                        break;
                        if (call->bchannel)
                                bchannel_blowfish(call->bchannel, call->bf_key, call->bf_len);
                        break;
+#endif
                case 'h':
                        if (opt[1] != '\0') {
                                CERROR(call, call->ast, "Option 'h' (HDLC) expects no parameter.\n", opt);
                case 'h':
                        if (opt[1] != '\0') {
                                CERROR(call, call->ast, "Option 'h' (HDLC) expects no parameter.\n", opt);
@@ -471,15 +494,15 @@ void apply_opt(struct chan_call *call, char *data)
                        if (!call->hdlc)
                                call->hdlc = 1;
                        break;
                        if (!call->hdlc)
                                call->hdlc = 1;
                        break;
-               case 't':
-                       if (opt[1] != '\0') {
-                               CERROR(call, call->ast, "Option 't' (no_dsp) expects no parameter.\n", opt);
+               case 'q':
+                       if (opt[1] == '\0') {
+                               CERROR(call, call->ast, "Option 'q' (queue) expects parameter.\n", opt);
                                break;
                        }
                                break;
                        }
-                       CDEBUG(call, call->ast, "Option 't' (no dsp).\n");
-                       if (!call->nodsp)
-                               call->nodsp = 1;
+                       CDEBUG(call, call->ast, "Option 'q' (queue).\n");
+                       call->tx_queue = atoi(opt+1);
                        break;
                        break;
+#if 0
                case 'e':
                        if (opt[1] == '\0') {
                                CERROR(call, call->ast, "Option 'e' (echo cancel) expects parameter.\n", opt);
                case 'e':
                        if (opt[1] == '\0') {
                                CERROR(call, call->ast, "Option 'e' (echo cancel) expects parameter.\n", opt);
@@ -490,30 +513,24 @@ void apply_opt(struct chan_call *call, char *data)
                        if (call->bchannel)
                                bchannel_pipeline(call->bchannel, call->pipeline);
                        break;
                        if (call->bchannel)
                                bchannel_pipeline(call->bchannel, call->pipeline);
                        break;
+#endif
                case 'f':
                case 'f':
-                       if (opt[1] == '\0') {
-                               CERROR(call, call->ast, "Option 'f' (faxdetect) expects parameter.\n", opt);
+                       if (opt[1] != '\0') {
+                               CERROR(call, call->ast, "Option 'f' (faxdetect) expects no parameter.\n", opt);
                                break;
                        }
                                break;
                        }
-                       call->faxdetect=atoi(opt+1);
-                       if (!call->dsp)
-                               call->dsp=ast_dsp_new();
-                       if (call->dsp) {
-                               #ifdef LCR_FOR_CALLWEAVER
-                               ast_dsp_set_features(call->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_CNG_DETECT);
-                               #endif
-                               #ifdef LCR_FOR_ASTERISK
-                               ast_dsp_set_features(call->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_DETECT);
-                               #endif
-                               if (!call->trans)
-                                       #ifdef LCR_FOR_CALLWEAVER
-                                       call->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, 8000, (options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW, 8000);
-                                       #endif
-                                       #ifdef LCR_FOR_ASTERISK
-                                       call->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, (options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW);
-                                       #endif
+                       call->faxdetect = 1;
+                       call->dsp_dtmf = 0;
+                       CDEBUG(call, call->ast, "Option 'f' (faxdetect).\n");
+                       break;
+               case 'a':
+                       if (opt[1] != '\0') {
+                               CERROR(call, call->ast, "Option 'a' (asterisk DTMF) expects no parameter.\n", opt);
+                               break;
                        }
                        }
-                       CDEBUG(call, call->ast, "Option 'f' (faxdetect) with config '%s'.\n", call->faxdetect);
+                       call->ast_dsp = 1;
+                       call->dsp_dtmf = 0;
+                       CDEBUG(call, call->ast, "Option 'a' (Asterisk DTMF detection).\n");
                        break;
                case 'r':
                        if (opt[1] != '\0') {
                        break;
                case 'r':
                        if (opt[1] != '\0') {
@@ -532,6 +549,7 @@ void apply_opt(struct chan_call *call, char *data)
                        CDEBUG(call, call->ast, "Option 's' (inband DTMF).\n");
                        call->inband_dtmf = 1;
                        break;
                        CDEBUG(call, call->ast, "Option 's' (inband DTMF).\n");
                        call->inband_dtmf = 1;
                        break;
+#if 0
                case 'v':
                        if (opt[1] != 'r' && opt[1] != 't') {
                                CERROR(call, call->ast, "Option 'v' (volume) expects parameter.\n", opt);
                case 'v':
                        if (opt[1] != 'r' && opt[1] != 't') {
                                CERROR(call, call->ast, "Option 'v' (volume) expects parameter.\n", opt);
@@ -553,16 +571,53 @@ void apply_opt(struct chan_call *call, char *data)
                                        bchannel_gain(call->bchannel, call->tx_gain, 1);
                        }
                        break;
                                        bchannel_gain(call->bchannel, call->tx_gain, 1);
                        }
                        break;
+#endif
+               case 'k':
+                       if (opt[1] != '\0') {
+                               CERROR(call, call->ast, "Option 'k' (keypad) expects no parameter.\n", opt);
+                               break;
+                       }
+                       CDEBUG(call, call->ast, "Option 'k' (keypad).\n");
+                       if (!call->keypad)
+                               call->keypad = 1;
+                       break;
                default:
                        CERROR(call, call->ast, "Option '%s' unknown.\n", opt);
                }
                default:
                        CERROR(call, call->ast, "Option '%s' unknown.\n", opt);
                }
-       }               
-       
-       /* re-open, if bchannel is created */
-       if (call->bchannel && call->bchannel->b_sock > -1) {
-               bchannel_destroy(call->bchannel);
-               if (bchannel_create(call->bchannel, ((call->nodsp || call->faxdetect > 0)?1:0) + ((call->hdlc)?2:0)))
-                       bchannel_activate(call->bchannel, 1);
+       }
+
+       if (call->faxdetect || call->ast_dsp) {
+               if (!call->dsp)
+                       call->dsp=ast_dsp_new();
+               if (call->dsp) {
+                       #ifdef LCR_FOR_CALLWEAVER
+                       ast_dsp_set_features(call->dsp, DSP_FEATURE_DTMF_DETECT | ((call->faxdetect) ? DSP_FEATURE_FAX_CNG_DETECT : 0));
+                       #endif
+                       #ifdef LCR_FOR_ASTERISK
+                       #ifdef DSP_FEATURE_DTMF_DETECT
+                       ast_dsp_set_features(call->dsp, DSP_FEATURE_DTMF_DETECT | ((call->faxdetect) ? DSP_FEATURE_FAX_DETECT : 0));
+                       #else
+                       ast_dsp_set_features(call->dsp, DSP_FEATURE_DIGIT_DETECT | ((call->faxdetect) ? DSP_FEATURE_FAX_DETECT : 0));
+                       #endif
+
+                       #endif
+                       if (!call->trans) {
+                               #ifdef LCR_FOR_CALLWEAVER
+                               call->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, 8000, (options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW, 8000);
+                               #endif
+                               #ifdef LCR_FOR_ASTERISK
+                               #if ASTERISK_VERSION_NUM < 100000
+                               call->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, (options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW);
+//                             #else
+//                             struct ast_format src;
+//                             struct ast_format dst;
+//                             ast_format_set(&dst, AST_FORMAT_SLINEAR, 0);
+//                             ast_format_set(&dst,(options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW , 0);
+//                             call->trans=ast_translator_build_path(&dst, &src);
+                               #endif
+                               #endif
+                       }
+               }
        }
 }
 
        }
 }
 
@@ -574,34 +629,45 @@ static void send_setup_to_lcr(struct chan_call *call)
 {
        union parameter newparam;
        struct ast_channel *ast = call->ast;
 {
        union parameter newparam;
        struct ast_channel *ast = call->ast;
+//     const char *tmp;
 
        if (!call->ast || !call->ref)
                return;
 
 
        if (!call->ast || !call->ref)
                return;
 
+#ifdef AST_1_8_OR_HIGHER
+       CDEBUG(call, call->ast, "Sending setup to LCR. (interface=%s dialstring=%s, cid=%s)\n", call->interface, call->dialstring, call->callerinfo.id);
+#else
        CDEBUG(call, call->ast, "Sending setup to LCR. (interface=%s dialstring=%s, cid=%s)\n", call->interface, call->dialstring, call->cid_num);
        CDEBUG(call, call->ast, "Sending setup to LCR. (interface=%s dialstring=%s, cid=%s)\n", call->interface, call->dialstring, call->cid_num);
+#endif
 
        /* send setup message to LCR */
        memset(&newparam, 0, sizeof(union parameter));
 
        /* send setup message to LCR */
        memset(&newparam, 0, sizeof(union parameter));
-               newparam.setup.dialinginfo.itype = INFO_ITYPE_ISDN;     
-               newparam.setup.dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
-       strncpy(newparam.setup.dialinginfo.id, call->dialstring, sizeof(newparam.setup.dialinginfo.id)-1);
-       strncpy(newparam.setup.dialinginfo.interfaces, call->interface, sizeof(newparam.setup.dialinginfo.interfaces)-1);
-               newparam.setup.callerinfo.itype = INFO_ITYPE_CHAN;      
-               newparam.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
+       newparam.setup.dialinginfo.itype = INFO_ITYPE_ISDN;
+       newparam.setup.dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
+       if (call->keypad)
+               strncpy(newparam.setup.dialinginfo.keypad, call->dialstring, sizeof(newparam.setup.dialinginfo.keypad)-1);
+       else
+               strncpy(newparam.setup.dialinginfo.id, call->dialstring, sizeof(newparam.setup.dialinginfo.id)-1);
+       newparam.setup.callerinfo.itype = INFO_ITYPE_CHAN;
+       newparam.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
        strncpy(newparam.setup.callerinfo.display, call->display, sizeof(newparam.setup.callerinfo.display)-1);
        call->display[0] = '\0';
        strncpy(newparam.setup.callerinfo.display, call->display, sizeof(newparam.setup.callerinfo.display)-1);
        call->display[0] = '\0';
+
+#ifdef AST_1_8_OR_HIGHER
+       /* set stored call information */
+       memcpy(&newparam.setup.callerinfo, &call->callerinfo, sizeof(struct caller_info));
+       memcpy(&newparam.setup.redirinfo, &call->redirinfo, sizeof(struct redir_info));
+#else
        if (call->cid_num[0])
                strncpy(newparam.setup.callerinfo.id, call->cid_num, sizeof(newparam.setup.callerinfo.id)-1);
        if (call->cid_name[0])
                strncpy(newparam.setup.callerinfo.name, call->cid_name, sizeof(newparam.setup.callerinfo.name)-1);
        if (call->cid_num[0])
                strncpy(newparam.setup.callerinfo.id, call->cid_num, sizeof(newparam.setup.callerinfo.id)-1);
        if (call->cid_name[0])
                strncpy(newparam.setup.callerinfo.name, call->cid_name, sizeof(newparam.setup.callerinfo.name)-1);
-       if (call->cid_rdnis[0])
-       {
+       if (call->cid_rdnis[0]) {
                strncpy(newparam.setup.redirinfo.id, call->cid_rdnis, sizeof(newparam.setup.redirinfo.id)-1);
                strncpy(newparam.setup.redirinfo.id, call->cid_rdnis, sizeof(newparam.setup.redirinfo.id)-1);
-                       newparam.setup.redirinfo.itype = INFO_ITYPE_CHAN;       
-               newparam.setup.redirinfo.ntype = INFO_NTYPE_UNKNOWN;    
+               newparam.setup.redirinfo.itype = INFO_ITYPE_CHAN;
+               newparam.setup.redirinfo.ntype = INFO_NTYPE_UNKNOWN;
        }
        }
-       switch(ast->cid.cid_pres & AST_PRES_RESTRICTION)
-       {
+       switch(ast->cid.cid_pres & AST_PRES_RESTRICTION) {
                case AST_PRES_RESTRICTED:
                newparam.setup.callerinfo.present = INFO_PRESENT_RESTRICTED;
                break;
                case AST_PRES_RESTRICTED:
                newparam.setup.callerinfo.present = INFO_PRESENT_RESTRICTED;
                break;
@@ -612,8 +678,7 @@ static void send_setup_to_lcr(struct chan_call *call)
                default:
                newparam.setup.callerinfo.present = INFO_PRESENT_ALLOWED;
        }
                default:
                newparam.setup.callerinfo.present = INFO_PRESENT_ALLOWED;
        }
-       switch(ast->cid.cid_ton)
-       {
+       switch(ast->cid.cid_ton) {
                case 4:
                newparam.setup.callerinfo.ntype = INFO_NTYPE_SUBSCRIBER;
                break;
                case 4:
                newparam.setup.callerinfo.ntype = INFO_NTYPE_SUBSCRIBER;
                break;
@@ -626,7 +691,17 @@ static void send_setup_to_lcr(struct chan_call *call)
                default:
                newparam.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
        }
                default:
                newparam.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
        }
+#endif
+#warning DISABLED DUE TO DOUBLE LOCKING PROBLEM
+//     tmp = pbx_builtin_getvar_helper(ast, "LCR_TRANSFERCAPABILITY");
+//     if (tmp && *tmp)
+#if ASTERISK_VERSION_NUM < 110000
+//             ast->transfercapability = atoi(tmp);
        newparam.setup.capainfo.bearer_capa = ast->transfercapability;
        newparam.setup.capainfo.bearer_capa = ast->transfercapability;
+#else
+//             ast_channel_transfercapability_set(ast, atoi(tmp));
+       newparam.setup.capainfo.bearer_capa = ast_channel_transfercapability(ast);
+#endif
        newparam.setup.capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
        if (call->hdlc)
                newparam.setup.capainfo.source_mode = B_MODE_HDLC;
        newparam.setup.capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
        if (call->hdlc)
                newparam.setup.capainfo.source_mode = B_MODE_HDLC;
@@ -637,6 +712,11 @@ static void send_setup_to_lcr(struct chan_call *call)
        newparam.setup.capainfo.hlc = INFO_HLC_NONE;
        newparam.setup.capainfo.exthlc = INFO_HLC_NONE;
        send_message(MESSAGE_SETUP, call->ref, &newparam);
        newparam.setup.capainfo.hlc = INFO_HLC_NONE;
        newparam.setup.capainfo.exthlc = INFO_HLC_NONE;
        send_message(MESSAGE_SETUP, call->ref, &newparam);
+       if (call->tx_queue) {
+               memset(&newparam, 0, sizeof(union parameter));
+               newparam.queue = call->tx_queue * 8;
+               send_message(MESSAGE_DISABLE_DEJITTER, call->ref, &newparam);
+       }
 
        /* change to outgoing setup state */
        call->state = CHAN_LCR_STATE_OUT_SETUP;
 
        /* change to outgoing setup state */
        call->state = CHAN_LCR_STATE_OUT_SETUP;
@@ -653,12 +733,15 @@ static void send_dialque_to_lcr(struct chan_call *call)
 
        if (!call->ast || !call->ref || !call->dialque[0])
                return;
 
        if (!call->ast || !call->ref || !call->dialque[0])
                return;
-       
+
        CDEBUG(call, call->ast, "Sending dial queue to LCR. (dialing=%s)\n", call->dialque);
 
        /* send setup message to LCR */
        memset(&newparam, 0, sizeof(union parameter));
        CDEBUG(call, call->ast, "Sending dial queue to LCR. (dialing=%s)\n", call->dialque);
 
        /* send setup message to LCR */
        memset(&newparam, 0, sizeof(union parameter));
-       strncpy(newparam.information.id, call->dialque, sizeof(newparam.information.id)-1);
+       if (call->keypad)
+               strncpy(newparam.information.keypad, call->dialque, sizeof(newparam.information.keypad)-1);
+       else
+               strncpy(newparam.information.id, call->dialque, sizeof(newparam.information.id)-1);
        call->dialque[0] = '\0';
        send_message(MESSAGE_INFORMATION, call->ref, &newparam);
 }
        call->dialque[0] = '\0';
        send_message(MESSAGE_INFORMATION, call->ref, &newparam);
 }
@@ -677,19 +760,12 @@ static void bridge_message_if_bridged(struct chan_call *call, int message_type,
 }
 
 /*
 }
 
 /*
- * send release message to LCR and import bchannel if exported
+ * send release message to LCR
  */
  */
-static void send_release_and_import(struct chan_call *call, int cause, int location)
+static void send_release(struct chan_call *call, int cause, int location)
 {
        union parameter newparam;
 
 {
        union parameter newparam;
 
-       /* importing channel */
-       if (call->bchannel) {
-               memset(&newparam, 0, sizeof(union parameter));
-               newparam.bchannel.type = BCHANNEL_RELEASE;
-               newparam.bchannel.handle = call->bchannel->handle;
-               send_message(MESSAGE_BCHANNEL, call->ref, &newparam);
-       }
        /* sending release */
        memset(&newparam, 0, sizeof(union parameter));
        newparam.disconnectinfo.cause = cause;
        /* sending release */
        memset(&newparam, 0, sizeof(union parameter));
        newparam.disconnectinfo.cause = cause;
@@ -706,24 +782,43 @@ static void lcr_start_pbx(struct chan_call *call, struct ast_channel *ast, int c
 {
        int cause, ret;
        union parameter newparam;
 {
        int cause, ret;
        union parameter newparam;
+#if ASTERISK_VERSION_NUM < 110000
        char *exten = ast->exten;
        char *exten = ast->exten;
-       if (!*exten)
+#else
+       char s_exten[AST_MAX_EXTENSION];
+       char *exten=s_exten;
+
+       strncpy(exten, ast_channel_exten(ast), AST_MAX_EXTENSION-1);
+#endif
+
+if (!*exten)
                exten = "s";
 
                exten = "s";
 
+#if ASTERISK_VERSION_NUM < 110000
        CDEBUG(call, ast, "Try to start pbx. (exten=%s context=%s complete=%s)\n", exten, ast->context, complete?"yes":"no");
        CDEBUG(call, ast, "Try to start pbx. (exten=%s context=%s complete=%s)\n", exten, ast->context, complete?"yes":"no");
-       
-       if (complete)
-       {
+#else
+       CDEBUG(call, ast, "Try to start pbx. (exten=%s context=%s complete=%s)\n", exten, ast_channel_context(ast), complete?"yes":"no");
+#endif
+
+       if (complete) {
                /* if not match */
                /* if not match */
-               if (!ast_canmatch_extension(ast, ast->context, exten, 1, call->oad))
-               {
-                       CDEBUG(call, ast, "Got 'sending complete', but extension '%s' will not match at context '%s' - releasing.\n", exten, ast->context);
+#if ASTERISK_VERSION_NUM < 110000
+               if (!ast_canmatch_extension(ast, ast->context, exten, 1, call->oad)) {
+CDEBUG(call, ast, "Got 'sending complete', but extension '%s' will not match at context '%s' - releasing.\n", exten, ast->context);
+#else
+               if (!ast_canmatch_extension(ast, ast_channel_context(ast), exten, 1, call->oad)) {
+CDEBUG(call, ast, "Got 'sending complete', but extension '%s' will not match at context '%s' - releasing.\n", exten, ast_channel_context(ast));
+#endif
                        cause = 1;
                        goto release;
                }
                        cause = 1;
                        goto release;
                }
-               if (!ast_exists_extension(ast, ast->context, exten, 1, call->oad))
-               {
+#if ASTERISK_VERSION_NUM < 110000
+               if (!ast_exists_extension(ast, ast->context, exten, 1, call->oad)) {
                        CDEBUG(call, ast, "Got 'sending complete', but extension '%s' would match at context '%s', if more digits would be dialed - releasing.\n", exten, ast->context);
                        CDEBUG(call, ast, "Got 'sending complete', but extension '%s' would match at context '%s', if more digits would be dialed - releasing.\n", exten, ast->context);
+#else
+               if (!ast_exists_extension(ast, ast_channel_context(ast), exten, 1, call->oad)) {
+                       CDEBUG(call, ast, "Got 'sending complete', but extension '%s' would match at context '%s', if more digits would be dialed - releasing.\n", exten, ast_channel_context(ast));
+#endif
                        cause = 28;
                        goto release;
                }
                        cause = 28;
                        goto release;
                }
@@ -738,8 +833,11 @@ static void lcr_start_pbx(struct chan_call *call, struct ast_channel *ast, int c
                goto start;
        }
 
                goto start;
        }
 
-       if (ast_canmatch_extension(ast, ast->context, exten, 1, call->oad))
-       {
+#if ASTERISK_VERSION_NUM < 110000
+       if (ast_canmatch_extension(ast, ast->context, exten, 1, call->oad)) {
+#else
+       if (ast_canmatch_extension(ast, ast_channel_context(ast), exten, 1, call->oad)) {
+#endif
                /* send setup acknowledge to lcr */
                if (call->state != CHAN_LCR_STATE_IN_DIALING) {
                        memset(&newparam, 0, sizeof(union parameter));
                /* send setup acknowledge to lcr */
                if (call->state != CHAN_LCR_STATE_IN_DIALING) {
                        memset(&newparam, 0, sizeof(union parameter));
@@ -750,17 +848,43 @@ static void lcr_start_pbx(struct chan_call *call, struct ast_channel *ast, int c
                call->state = CHAN_LCR_STATE_IN_DIALING;
 
                /* if match, start pbx */
                call->state = CHAN_LCR_STATE_IN_DIALING;
 
                /* if match, start pbx */
-               if (ast_exists_extension(ast, ast->context, exten, 1, call->oad)) {
+#if ASTERISK_VERSION_NUM < 110000
+       if (ast_exists_extension(ast, ast->context, exten, 1, call->oad)) {
+#else
+       if (ast_exists_extension(ast, ast_channel_context(ast), exten, 1, call->oad)) {
+#endif
                        CDEBUG(call, ast, "Extensions matches.\n");
                        goto start;
                }
 
                        CDEBUG(call, ast, "Extensions matches.\n");
                        goto start;
                }
 
+               /* send setup acknowledge to lcr */
+               if (call->state != CHAN_LCR_STATE_IN_DIALING) {
+                       memset(&newparam, 0, sizeof(union parameter));
+                       send_message(MESSAGE_OVERLAP, call->ref, &newparam);
+               }
+
+               /* change state */
+               call->state = CHAN_LCR_STATE_IN_DIALING;
+
                /* if can match */
                CDEBUG(call, ast, "Extensions may match, if more digits are dialed.\n");
                return;
        }
 
                /* if can match */
                CDEBUG(call, ast, "Extensions may match, if more digits are dialed.\n");
                return;
        }
 
+#if ASTERISK_VERSION_NUM < 110000
        if (!*ast->exten) {
        if (!*ast->exten) {
+#else
+       if (!*ast_channel_exten(ast)) {
+#endif
+               /* send setup acknowledge to lcr */
+               if (call->state != CHAN_LCR_STATE_IN_DIALING) {
+                       memset(&newparam, 0, sizeof(union parameter));
+                       send_message(MESSAGE_OVERLAP, call->ref, &newparam);
+               }
+
+               /* change state */
+               call->state = CHAN_LCR_STATE_IN_DIALING;
+
                /* if can match */
                CDEBUG(call, ast, "There is no 's' extension (and we tried to match it implicitly). Extensions may match, if more digits are dialed.\n");
                return;
                /* if can match */
                CDEBUG(call, ast, "There is no 's' extension (and we tried to match it implicitly). Extensions may match, if more digits are dialed.\n");
                return;
@@ -771,27 +895,30 @@ static void lcr_start_pbx(struct chan_call *call, struct ast_channel *ast, int c
        release:
        /* release lcr */
        CDEBUG(call, ast, "Releasing due to extension missmatch.\n");
        release:
        /* release lcr */
        CDEBUG(call, ast, "Releasing due to extension missmatch.\n");
-       send_release_and_import(call, cause, LOCATION_PRIVATE_LOCAL);
+       send_release(call, cause, LOCATION_PRIVATE_LOCAL);
        call->ref = 0;
        /* release asterisk */
        call->ref = 0;
        /* release asterisk */
+#if ASTERISK_VERSION_NUM < 110000
        ast->hangupcause = call->cause;
        ast->hangupcause = call->cause;
+#else
+       ast_channel_hangupcause_set(ast, call->cause);
+#endif
        /* change to release state */
        call->state = CHAN_LCR_STATE_RELEASE;
        ast_hangup(ast); // call will be destroyed here
        return;
        /* change to release state */
        call->state = CHAN_LCR_STATE_RELEASE;
        ast_hangup(ast); // call will be destroyed here
        return;
-       
+
        start:
        /* send setup to asterisk */
        CDEBUG(call, ast, "Starting call to Asterisk due to matching extension.\n");
 
        start:
        /* send setup to asterisk */
        CDEBUG(call, ast, "Starting call to Asterisk due to matching extension.\n");
 
-       #ifdef LCR_FOR_CALLWEAVER       
+       #ifdef LCR_FOR_CALLWEAVER
        ast->type = "LCR";
        ast->type = "LCR";
-       snprintf(ast->name, sizeof(ast->name), "LCR/%s-%04x",ast->cid.cid_num, ast_random() & 0xffff);
+       snprintf(ast->name, sizeof(ast->name), "%s/%s-%04x",lcr_type ,ast->cid.cid_num, ast_random() & 0xffff);
        #endif
        #endif
-       
+
        ret = ast_pbx_start(ast);
        ret = ast_pbx_start(ast);
-       if (ret < 0)
-       {
+       if (ret < 0) {
                cause = (ret==-2)?34:27;
                goto release;
        }
                cause = (ret==-2)?34:27;
                goto release;
        }
@@ -805,7 +932,18 @@ static void lcr_start_pbx(struct chan_call *call, struct ast_channel *ast, int c
 static void lcr_in_setup(struct chan_call *call, int message_type, union parameter *param)
 {
        struct ast_channel *ast;
 static void lcr_in_setup(struct chan_call *call, int message_type, union parameter *param)
 {
        struct ast_channel *ast;
-
+#ifdef AST_1_8_OR_HIGHER
+       struct ast_party_redirecting *ast_redir;
+       struct ast_party_caller *ast_caller;
+#else
+       struct ast_callerid *ast_caller;
+#endif
+#if ASTERISK_VERSION_NUM >= 110000
+       struct ast_party_redirecting s_ast_redir;
+       struct ast_party_caller s_ast_caller;
+       ast_party_redirecting_init(&s_ast_redir);
+       ast_party_caller_init(&s_ast_caller);
+#endif
        CDEBUG(call, NULL, "Incomming setup from LCR. (callerid %s, dialing %s)\n", param->setup.callerinfo.id, param->setup.dialinginfo.id);
 
        /* create asterisk channel instrance */
        CDEBUG(call, NULL, "Incomming setup from LCR. (callerid %s, dialing %s)\n", param->setup.callerinfo.id, param->setup.dialinginfo.id);
 
        /* create asterisk channel instrance */
@@ -815,39 +953,208 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet
        #endif
 
        #ifdef LCR_FOR_ASTERISK
        #endif
 
        #ifdef LCR_FOR_ASTERISK
+#ifdef AST_1_8_OR_HIGHER
+       ast = ast_channel_alloc(1, AST_STATE_RESERVED, NULL, NULL, "", NULL, "", "", 0, "%s/%d", lcr_type, ++glob_channel);
+#else
        ast = ast_channel_alloc(1, AST_STATE_RESERVED, NULL, NULL, "", NULL, "", 0, "%s/%d", lcr_type, ++glob_channel);
        ast = ast_channel_alloc(1, AST_STATE_RESERVED, NULL, NULL, "", NULL, "", 0, "%s/%d", lcr_type, ++glob_channel);
+#endif
        #endif
        #endif
-       
-       if (!ast)
-       {
+
+#if ASTERISK_VERSION_NUM < 110000
+#ifdef AST_1_8_OR_HIGHER
+       ast_redir = &ast->redirecting;
+       ast_caller = &ast->caller;
+#else
+       ast_caller = &ast->cid;
+#endif
+#else
+       ast_redir = &s_ast_redir;
+       ast_caller = &s_ast_caller;
+#endif
+
+       if (!ast) {
                /* release */
                CERROR(call, NULL, "Failed to create Asterisk channel - releasing.\n");
                /* release */
                CERROR(call, NULL, "Failed to create Asterisk channel - releasing.\n");
-               send_release_and_import(call, CAUSE_RESSOURCEUNAVAIL, LOCATION_PRIVATE_LOCAL);
+               send_release(call, CAUSE_RESSOURCEUNAVAIL, LOCATION_PRIVATE_LOCAL);
                /* remove call */
                free_call(call);
                return;
        }
        /* link together */
        call->ast = ast;
                /* remove call */
                free_call(call);
                return;
        }
        /* link together */
        call->ast = ast;
+#if ASTERISK_VERSION_NUM < 110000
        ast->tech_pvt = call;
        ast->tech = &lcr_tech;
        ast->fds[0] = call->pipe[0];
        ast->tech_pvt = call;
        ast->tech = &lcr_tech;
        ast->fds[0] = call->pipe[0];
-       
+#else
+       ast_channel_tech_pvt_set(ast, call);
+       ast_channel_tech_set(ast, &lcr_tech);
+       ast_channel_set_fd(ast, 0, call->pipe[0]);
+#endif
+
        /* fill setup information */
        if (param->setup.dialinginfo.id)
        /* fill setup information */
        if (param->setup.dialinginfo.id)
+#if ASTERISK_VERSION_NUM < 110000
                strncpy(ast->exten, param->setup.dialinginfo.id, AST_MAX_EXTENSION-1);
                strncpy(ast->exten, param->setup.dialinginfo.id, AST_MAX_EXTENSION-1);
-       if (param->setup.context[0])
-               strncpy(ast->context, param->setup.context, AST_MAX_CONTEXT-1);
+       if (param->setup.dialinginfo.context[0])
+               strncpy(ast->context, param->setup.dialinginfo.context, AST_MAX_CONTEXT-1);
        else
                strncpy(ast->context, param->setup.callerinfo.interface, AST_MAX_CONTEXT-1);
        else
                strncpy(ast->context, param->setup.callerinfo.interface, AST_MAX_CONTEXT-1);
+#else
+               ast_channel_exten_set(ast, param->setup.dialinginfo.id);
+       if (param->setup.dialinginfo.context[0])
+               ast_channel_context_set(ast, param->setup.dialinginfo.context);
+       else
+               ast_channel_context_set(ast, param->setup.callerinfo.interface);
+#endif
+
+
+#ifdef AST_1_8_OR_HIGHER
+       if (param->setup.callerinfo.id[0]) {
+               ast_caller->id.number.valid = 1;
+               ast_caller->id.number.str = strdup(param->setup.callerinfo.id);
+               if (!param->setup.callerinfo.id[0]) {
+                       ast_caller->id.number.presentation = AST_PRES_RESTRICTED;
+                       ast_caller->id.number.plan = (0 << 4) | 1;
+               }
+               switch (param->setup.callerinfo.present) {
+                       case INFO_PRESENT_ALLOWED:
+                               ast_caller->id.number.presentation = AST_PRES_ALLOWED;
+                       break;
+                       case INFO_PRESENT_RESTRICTED:
+                               ast_caller->id.number.presentation = AST_PRES_RESTRICTED;
+                       break;
+                       default:
+                               ast_caller->id.number.presentation = AST_PRES_UNAVAILABLE;
+               }
+               switch (param->setup.callerinfo.screen) {
+                       case INFO_SCREEN_USER:
+                               ast_caller->id.number.presentation |= AST_PRES_USER_NUMBER_UNSCREENED;
+                       break;
+                       case INFO_SCREEN_USER_VERIFIED_PASSED:
+                               ast_caller->id.number.presentation |= AST_PRES_USER_NUMBER_PASSED_SCREEN;
+                       break;
+                       case INFO_SCREEN_USER_VERIFIED_FAILED:
+                               ast_caller->id.number.presentation |= AST_PRES_USER_NUMBER_FAILED_SCREEN;
+                       break;
+                       default:
+                               ast_caller->id.number.presentation |= AST_PRES_NETWORK_NUMBER;
+               }
+               switch (param->setup.callerinfo.ntype) {
+                       case INFO_NTYPE_SUBSCRIBER:
+                               ast_caller->id.number.plan = (4 << 4) | 1;
+                       break;
+                       case INFO_NTYPE_NATIONAL:
+                               ast_caller->id.number.plan = (2 << 4) | 1;
+                       break;
+                       case INFO_NTYPE_INTERNATIONAL:
+                               ast_caller->id.number.plan = (1 << 4) | 1;
+                       break;
+                       default:
+                               ast_caller->id.number.plan = (0 << 4) | 1;
+               }
+       }
+       if (param->setup.callerinfo.id2[0]) {
+               ast_caller->ani.number.valid = 1;
+               ast_caller->ani.number.str = strdup(param->setup.callerinfo.id2);
+               switch (param->setup.callerinfo.present2) {
+                       case INFO_PRESENT_ALLOWED:
+                               ast_caller->ani.number.presentation = AST_PRES_ALLOWED;
+                       break;
+                       case INFO_PRESENT_RESTRICTED:
+                               ast_caller->ani.number.presentation = AST_PRES_RESTRICTED;
+                       break;
+                       default:
+                               ast_caller->ani.number.presentation = AST_PRES_UNAVAILABLE;
+               }
+               switch (param->setup.callerinfo.screen2) {
+                       case INFO_SCREEN_USER:
+                               ast_caller->ani.number.presentation |= AST_PRES_USER_NUMBER_UNSCREENED;
+                       break;
+                       case INFO_SCREEN_USER_VERIFIED_PASSED:
+                               ast_caller->ani.number.presentation |= AST_PRES_USER_NUMBER_PASSED_SCREEN;
+                       break;
+                       case INFO_SCREEN_USER_VERIFIED_FAILED:
+                               ast_caller->ani.number.presentation |= AST_PRES_USER_NUMBER_FAILED_SCREEN;
+                       break;
+                       default:
+                               ast_caller->ani.number.presentation |= AST_PRES_NETWORK_NUMBER;
+               }
+               switch (param->setup.callerinfo.ntype2) {
+                       case INFO_NTYPE_SUBSCRIBER:
+                               ast_caller->ani.number.plan = (4 << 4) | 1;
+                       break;
+                       case INFO_NTYPE_NATIONAL:
+                               ast_caller->ani.number.plan = (2 << 4) | 1;
+                       break;
+                       case INFO_NTYPE_INTERNATIONAL:
+                               ast_caller->ani.number.plan = (1 << 4) | 1;
+                       break;
+                       default:
+                               ast_caller->ani.number.plan = (0 << 4) | 1;
+               }
+       }
+       if (param->setup.callerinfo.name[0]) {
+               ast_caller->id.name.valid = 1;
+               ast_caller->id.name.str = strdup(param->setup.callerinfo.name);
+       }
+#if ASTERISK_VERSION_NUM >= 110000
+       ast_channel_caller_set(ast, ast_caller);
+#endif
+       if (param->setup.redirinfo.id[0]) {
+               ast_redir->from.number.valid = 1;
+               ast_redir->from.number.str = strdup(param->setup.redirinfo.id);
+               switch (param->setup.redirinfo.present) {
+                       case INFO_PRESENT_ALLOWED:
+                               ast_redir->from.number.presentation = AST_PRES_ALLOWED;
+                       break;
+                       case INFO_PRESENT_RESTRICTED:
+                               ast_redir->from.number.presentation = AST_PRES_RESTRICTED;
+                       break;
+                       default:
+                               ast_redir->from.number.presentation = AST_PRES_UNAVAILABLE;
+               }
+               switch (param->setup.redirinfo.screen) {
+                       case INFO_SCREEN_USER:
+                               ast_redir->from.number.presentation |= AST_PRES_USER_NUMBER_UNSCREENED;
+                       break;
+                       case INFO_SCREEN_USER_VERIFIED_PASSED:
+                               ast_redir->from.number.presentation |= AST_PRES_USER_NUMBER_PASSED_SCREEN;
+                       break;
+                       case INFO_SCREEN_USER_VERIFIED_FAILED:
+                               ast_redir->from.number.presentation |= AST_PRES_USER_NUMBER_FAILED_SCREEN;
+                       break;
+                       default:
+                               ast_redir->from.number.presentation |= AST_PRES_NETWORK_NUMBER;
+               }
+               switch (param->setup.redirinfo.ntype) {
+                       case INFO_NTYPE_SUBSCRIBER:
+                               ast_redir->from.number.plan = (4 << 4) | 1;
+                       break;
+                       case INFO_NTYPE_NATIONAL:
+                               ast_redir->from.number.plan = (2 << 4) | 1;
+                       break;
+                       case INFO_NTYPE_INTERNATIONAL:
+                               ast_redir->from.number.plan = (1 << 4) | 1;
+                       break;
+                       default:
+                               ast_redir->from.number.plan = (0 << 4) | 1;
+               }
+#if ASTERISK_VERSION_NUM >= 110000
+               ast_channel_redirecting_set(ast, ast_redir);
+#endif
+       }
+#else
+       memset(&ast->cid, 0, sizeof(ast->cid));
        if (param->setup.callerinfo.id[0])
                ast->cid.cid_num = strdup(param->setup.callerinfo.id);
        if (param->setup.callerinfo.id[0])
                ast->cid.cid_num = strdup(param->setup.callerinfo.id);
+       if (param->setup.callerinfo.id2[0])
+               ast->cid.cid_ani = strdup(param->setup.callerinfo.id2);
        if (param->setup.callerinfo.name[0])
                ast->cid.cid_name = strdup(param->setup.callerinfo.name);
        if (param->setup.redirinfo.id[0])
        if (param->setup.callerinfo.name[0])
                ast->cid.cid_name = strdup(param->setup.callerinfo.name);
        if (param->setup.redirinfo.id[0])
-               ast->cid.cid_name = strdup(numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
-       switch (param->setup.callerinfo.present)
-       {
+               ast->cid.cid_rdnis = strdup(numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype, options.national, options.international));
+       switch (param->setup.callerinfo.present) {
                case INFO_PRESENT_ALLOWED:
                        ast->cid.cid_pres = AST_PRES_ALLOWED;
                break;
                case INFO_PRESENT_ALLOWED:
                        ast->cid.cid_pres = AST_PRES_ALLOWED;
                break;
@@ -857,8 +1164,7 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet
                default:
                        ast->cid.cid_pres = AST_PRES_UNAVAILABLE;
        }
                default:
                        ast->cid.cid_pres = AST_PRES_UNAVAILABLE;
        }
-       switch (param->setup.callerinfo.ntype)
-       {
+       switch (param->setup.callerinfo.ntype) {
                case INFO_NTYPE_SUBSCRIBER:
                        ast->cid.cid_ton = 4;
                break;
                case INFO_NTYPE_SUBSCRIBER:
                        ast->cid.cid_ton = 4;
                break;
@@ -871,18 +1177,49 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet
                default:
                        ast->cid.cid_ton = 0;
        }
                default:
                        ast->cid.cid_ton = 0;
        }
+#endif
+
+#if ASTERISK_VERSION_NUM < 110000
        ast->transfercapability = param->setup.capainfo.bearer_capa;
        ast->transfercapability = param->setup.capainfo.bearer_capa;
+#else
+       ast_channel_transfercapability_set(ast, param->setup.capainfo.bearer_capa);
+#endif
        /* enable hdlc if transcap is data */
        if (param->setup.capainfo.source_mode == B_MODE_HDLC)
                call->hdlc = 1;
        strncpy(call->oad, numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international), sizeof(call->oad)-1);
 
        /* configure channel */
        /* enable hdlc if transcap is data */
        if (param->setup.capainfo.source_mode == B_MODE_HDLC)
                call->hdlc = 1;
        strncpy(call->oad, numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international), sizeof(call->oad)-1);
 
        /* configure channel */
+#if ASTERISK_VERSION_NUM < 100000
+       wat een onzin
+#endif
+
+#if ASTERISK_VERSION_NUM < 100000
        ast->nativeformats = (options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW;
        ast->readformat = ast->rawreadformat = ast->nativeformats;
        ast->writeformat = ast->rawwriteformat =  ast->nativeformats;
        ast->nativeformats = (options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW;
        ast->readformat = ast->rawreadformat = ast->nativeformats;
        ast->writeformat = ast->rawwriteformat =  ast->nativeformats;
+#else
+#if ASTERISK_VERSION_NUM < 110000
+       ast_format_set(&ast->rawwriteformat ,(options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW , 0);
+       ast_format_copy(&ast->rawreadformat, &ast->rawwriteformat);
+       ast_format_cap_set(ast->nativeformats, &ast->rawwriteformat);
+       ast_set_write_format(ast, &ast->rawwriteformat);
+       ast_set_read_format(ast, &ast->rawreadformat);
+#else
+       ast_format_set(ast_channel_rawwriteformat(ast) ,(options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW , 0);
+       ast_format_copy(ast_channel_rawreadformat(ast), ast_channel_rawwriteformat(ast));
+       ast_format_cap_set(ast_channel_nativeformats(ast), ast_channel_rawwriteformat(ast));
+       ast_set_write_format(ast, ast_channel_rawwriteformat(ast));
+       ast_set_read_format(ast, ast_channel_rawreadformat(ast));
+#endif
+#endif
+#if ASTERISK_VERSION_NUM < 110000
        ast->priority = 1;
        ast->hangupcause = 0;
        ast->priority = 1;
        ast->hangupcause = 0;
+#else
+       ast_channel_priority_set(ast, 1);
+       ast_channel_hangupcause_set(ast, 0);
+#endif
 
        /* change state */
        call->state = CHAN_LCR_STATE_IN_SETUP;
 
        /* change state */
        call->state = CHAN_LCR_STATE_IN_SETUP;
@@ -917,8 +1254,16 @@ static void lcr_in_proceeding(struct chan_call *call, int message_type, union pa
        /* change state */
        call->state = CHAN_LCR_STATE_OUT_PROCEEDING;
        /* queue event for asterisk */
        /* change state */
        call->state = CHAN_LCR_STATE_OUT_PROCEEDING;
        /* queue event for asterisk */
-       if (call->ast && call->pbx_started)
+       if (call->ast && call->pbx_started) {
+               if (!wake_global) {
+                       wake_global = 1;
+                       char byte = 0;
+                       int rc;
+                       rc = write(wake_pipe[1], &byte, 1);
+               }
                strncat(call->queue_string, "P", sizeof(call->queue_string)-1);
                strncat(call->queue_string, "P", sizeof(call->queue_string)-1);
+       }
+
 }
 
 /*
 }
 
 /*
@@ -931,8 +1276,15 @@ static void lcr_in_alerting(struct chan_call *call, int message_type, union para
        /* change state */
        call->state = CHAN_LCR_STATE_OUT_ALERTING;
        /* queue event to asterisk */
        /* change state */
        call->state = CHAN_LCR_STATE_OUT_ALERTING;
        /* queue event to asterisk */
-       if (call->ast && call->pbx_started)
+       if (call->ast && call->pbx_started) {
+               if (!wake_global) {
+                       wake_global = 1;
+                       char byte = 0;
+                       int rc;
+                       rc = write(wake_pipe[1], &byte, 1);
+               }
                strncat(call->queue_string, "R", sizeof(call->queue_string)-1);
                strncat(call->queue_string, "R", sizeof(call->queue_string)-1);
+       }
 }
 
 /*
 }
 
 /*
@@ -940,24 +1292,22 @@ static void lcr_in_alerting(struct chan_call *call, int message_type, union para
  */
 static void lcr_in_connect(struct chan_call *call, int message_type, union parameter *param)
 {
  */
 static void lcr_in_connect(struct chan_call *call, int message_type, union parameter *param)
 {
-       union parameter newparam;
-
        CDEBUG(call, call->ast, "Incomming connect (answer) from LCR.\n");
 
        /* change state */
        call->state = CHAN_LCR_STATE_CONNECT;
        CDEBUG(call, call->ast, "Incomming connect (answer) from LCR.\n");
 
        /* change state */
        call->state = CHAN_LCR_STATE_CONNECT;
-       /* request bchannel */
-       if (!call->bchannel) {
-               CDEBUG(call, call->ast, "Requesting B-channel.\n");
-               memset(&newparam, 0, sizeof(union parameter));
-               newparam.bchannel.type = BCHANNEL_REQUEST;
-               send_message(MESSAGE_BCHANNEL, call->ref, &newparam);
-       }
        /* copy connectinfo */
        memcpy(&call->connectinfo, &param->connectinfo, sizeof(struct connect_info));
        /* queue event to asterisk */
        /* copy connectinfo */
        memcpy(&call->connectinfo, &param->connectinfo, sizeof(struct connect_info));
        /* queue event to asterisk */
-       if (call->ast && call->pbx_started)
+       if (call->ast && call->pbx_started) {
+               if (!wake_global) {
+                       wake_global = 1;
+                       char byte = 0;
+                       int rc;
+                       rc = write(wake_pipe[1], &byte, 1);
+               }
                strncat(call->queue_string, "N", sizeof(call->queue_string)-1);
                strncat(call->queue_string, "N", sizeof(call->queue_string)-1);
+       }
 }
 
 /*
 }
 
 /*
@@ -977,25 +1327,33 @@ static void lcr_in_disconnect(struct chan_call *call, int message_type, union pa
        /* if bridge, forward disconnect and return */
 #ifdef TODO
        feature flag
        /* if bridge, forward disconnect and return */
 #ifdef TODO
        feature flag
-       if (call->bridge_call)
-       {
+       if (call->bridge_call) {
                CDEBUG(call, call->ast, "Only signal disconnect via bridge.\n");
                bridge_message_if_bridged(call, message_type, param);
                return;
        }
 #endif
        /* release lcr with same cause */
                CDEBUG(call, call->ast, "Only signal disconnect via bridge.\n");
                bridge_message_if_bridged(call, message_type, param);
                return;
        }
 #endif
        /* release lcr with same cause */
-       send_release_and_import(call, call->cause, call->location);
+       send_release(call, call->cause, call->location);
        call->ref = 0;
        /* change to release state */
        call->state = CHAN_LCR_STATE_RELEASE;
        /* queue release asterisk */
        call->ref = 0;
        /* change to release state */
        call->state = CHAN_LCR_STATE_RELEASE;
        /* queue release asterisk */
-       if (ast)
-       {
+       if (ast) {
+#if ASTERISK_VERSION_NUM < 110000
                ast->hangupcause = call->cause;
                ast->hangupcause = call->cause;
-               if (call->pbx_started)
+#else
+               ast_channel_hangupcause_set(ast, call->cause);
+#endif
+               if (call->pbx_started) {
+                       if (!wake_global) {
+                               wake_global = 1;
+                               char byte = 0;
+                               int rc;
+                               rc = write(wake_pipe[1], &byte, 1);
+                       }
                        strcpy(call->queue_string, "H"); // overwrite other indications
                        strcpy(call->queue_string, "H"); // overwrite other indications
-               else {
+               else {
                        ast_hangup(ast); // call will be destroyed here
                }
        }
                        ast_hangup(ast); // call will be destroyed here
                }
        }
@@ -1015,25 +1373,32 @@ static void lcr_in_release(struct chan_call *call, int message_type, union param
        /* change to release state */
        call->state = CHAN_LCR_STATE_RELEASE;
        /* copy release info */
        /* change to release state */
        call->state = CHAN_LCR_STATE_RELEASE;
        /* copy release info */
-       if (!call->cause)
-       {
-              call->cause = param->disconnectinfo.cause;
-              call->location = param->disconnectinfo.location;
+       if (!call->cause) {
+               call->cause = param->disconnectinfo.cause;
+               call->location = param->disconnectinfo.location;
        }
        /* if we have an asterisk instance, queue hangup, else we are done */
        }
        /* if we have an asterisk instance, queue hangup, else we are done */
-       if (ast)
-       {
+       if (ast) {
+#if ASTERISK_VERSION_NUM < 110000
                ast->hangupcause = call->cause;
                ast->hangupcause = call->cause;
-               if (call->pbx_started)
+#else
+               ast_channel_hangupcause_set(ast, call->cause);
+#endif
+               if (call->pbx_started) {
+                       if (!wake_global) {
+                               wake_global = 1;
+                               char byte = 0;
+                               int rc;
+                               rc = write(wake_pipe[1], &byte, 1);
+                       }
                        strcpy(call->queue_string, "H");
                        strcpy(call->queue_string, "H");
-               else {
+               else {
                        ast_hangup(ast); // call will be destroyed here
                }
                        ast_hangup(ast); // call will be destroyed here
                }
-       } else
-       {
+       } else {
                free_call(call);
        }
                free_call(call);
        }
-       
+
 }
 
 /*
 }
 
 /*
@@ -1044,33 +1409,58 @@ static void lcr_in_information(struct chan_call *call, int message_type, union p
        struct ast_channel *ast = call->ast;
 
        CDEBUG(call, call->ast, "Incoming information from LCR. (dialing=%s)\n", param->information.id);
        struct ast_channel *ast = call->ast;
 
        CDEBUG(call, call->ast, "Incoming information from LCR. (dialing=%s)\n", param->information.id);
-       
+
        if (!ast) return;
 
        /* pbx not started */
        if (!ast) return;
 
        /* pbx not started */
-       if (!call->pbx_started)
-       {
+       if (!call->pbx_started) {
                CDEBUG(call, call->ast, "Asterisk not started, adding digits to number.\n");
                CDEBUG(call, call->ast, "Asterisk not started, adding digits to number.\n");
+#if ASTERISK_VERSION_NUM < 110000
                strncat(ast->exten, param->information.id, AST_MAX_EXTENSION-1);
                strncat(ast->exten, param->information.id, AST_MAX_EXTENSION-1);
+#else
+               char *tmp[AST_MAX_EXTENSION];
+               snprintf(tmp,AST_MAX_EXTENSION,"%s%s",ast_channel_exten(ast),param->information.id);
+               ast_channel_exten_set(ast, tmp);
+#endif
                lcr_start_pbx(call, ast, param->information.sending_complete);
                return;
        }
                lcr_start_pbx(call, ast, param->information.sending_complete);
                return;
        }
-       
+
        /* change dailing state after setup */
        if (call->state == CHAN_LCR_STATE_IN_SETUP) {
                CDEBUG(call, call->ast, "Changing from SETUP to DIALING state.\n");
                call->state = CHAN_LCR_STATE_IN_DIALING;
 //             ast_setstate(ast, AST_STATE_DIALING);
        }
        /* change dailing state after setup */
        if (call->state == CHAN_LCR_STATE_IN_SETUP) {
                CDEBUG(call, call->ast, "Changing from SETUP to DIALING state.\n");
                call->state = CHAN_LCR_STATE_IN_DIALING;
 //             ast_setstate(ast, AST_STATE_DIALING);
        }
-       
+
        /* queue digits */
        /* queue digits */
-       if (call->state == CHAN_LCR_STATE_IN_DIALING && param->information.id[0])
+       if (call->state == CHAN_LCR_STATE_IN_DIALING && param->information.id[0]) {
+               if (!wake_global) {
+                       wake_global = 1;
+                       char byte = 0;
+                       int rc;
+                       rc = write(wake_pipe[1], &byte, 1);
+               }
                strncat(call->queue_string, param->information.id, sizeof(call->queue_string)-1);
                strncat(call->queue_string, param->information.id, sizeof(call->queue_string)-1);
+       }
 
        /* use bridge to forware message not supported by asterisk */
        if (call->state == CHAN_LCR_STATE_CONNECT) {
 
        /* use bridge to forware message not supported by asterisk */
        if (call->state == CHAN_LCR_STATE_CONNECT) {
-               CDEBUG(call, call->ast, "Call is connected, bridging.\n");
-               bridge_message_if_bridged(call, message_type, param);
+               if (call->bridge_call) {
+                       CDEBUG(call, call->ast, "Call is connected, bridging.\n");
+                       bridge_message_if_bridged(call, message_type, param);
+               } else {
+                       if (call->dsp_dtmf) {
+                               if (!wake_global) {
+                                       wake_global = 1;
+                                       char byte = 0;
+                                       int rc;
+                                       rc = write(wake_pipe[1], &byte, 1);
+                               }
+                               strncat(call->queue_string, param->information.id, sizeof(call->queue_string)-1);
+                       } else
+                               CDEBUG(call, call->ast, "LCR's DTMF detection is disabled.\n");
+               }
        }
 }
 
        }
 }
 
@@ -1079,18 +1469,8 @@ static void lcr_in_information(struct chan_call *call, int message_type, union p
  */
 static void lcr_in_notify(struct chan_call *call, int message_type, union parameter *param)
 {
  */
 static void lcr_in_notify(struct chan_call *call, int message_type, union parameter *param)
 {
-       union parameter newparam;
-
        CDEBUG(call, call->ast, "Incomming notify from LCR. (notify=%d)\n", param->notifyinfo.notify);
 
        CDEBUG(call, call->ast, "Incomming notify from LCR. (notify=%d)\n", param->notifyinfo.notify);
 
-       /* request bchannel, if call is resumed and we don't have it */
-       if (param->notifyinfo.notify == INFO_NOTIFY_USER_RESUMED && !call->bchannel && call->ref) {
-               CDEBUG(call, call->ast, "Reqesting bchannel at resume.\n");
-               memset(&newparam, 0, sizeof(union parameter));
-               newparam.bchannel.type = BCHANNEL_REQUEST;
-               send_message(MESSAGE_BCHANNEL, call->ref, &newparam);
-       }
-
        if (!call->ast) return;
 
        /* use bridge to forware message not supported by asterisk */
        if (!call->ast) return;
 
        /* use bridge to forware message not supported by asterisk */
@@ -1111,6 +1491,39 @@ static void lcr_in_facility(struct chan_call *call, int message_type, union para
 }
 
 /*
 }
 
 /*
+ * incoming pattern from LCR
+ */
+static void lcr_in_pattern(struct chan_call *call, int message_type, union parameter *param)
+{
+       union parameter newparam;
+
+       CDEBUG(call, call->ast, "Incomming pattern indication from LCR.\n");
+
+       if (!call->ast) return;
+
+       /* pattern are indicated only once */
+       if (call->has_pattern)
+               return;
+       call->has_pattern = 1;
+
+       /* request bchannel */
+       CDEBUG(call, call->ast, "Requesting audio path (ref=%d)\n", call->ref);
+       memset(&newparam, 0, sizeof(union parameter));
+       send_message(MESSAGE_AUDIOPATH, call->ref, &newparam);
+
+       /* queue PROGRESS, because tones are available */
+       if (call->ast && call->pbx_started) {
+               if (!wake_global) {
+                       wake_global = 1;
+                       char byte = 0;
+                       int rc;
+                       rc = write(wake_pipe[1], &byte, 1);
+               }
+               strncat(call->queue_string, "T", sizeof(call->queue_string)-1);
+       }
+}
+
+/*
  * got dtmf from bchannel (locked state)
  */
 void lcr_in_dtmf(struct chan_call *call, int val)
  * got dtmf from bchannel (locked state)
  */
 void lcr_in_dtmf(struct chan_call *call, int val)
@@ -1123,9 +1536,20 @@ void lcr_in_dtmf(struct chan_call *call, int val)
        if (!call->pbx_started)
                return;
 
        if (!call->pbx_started)
                return;
 
+       if (!call->dsp_dtmf) {
+               CDEBUG(call, call->ast, "Recognised DTMF digit '%c' by LCR, but ignoring. (disabled by option)\n", val);
+               return;
+       }
+
        CDEBUG(call, call->ast, "Recognised DTMF digit '%c'.\n", val);
        digit[0] = val;
        digit[1] = '\0';
        CDEBUG(call, call->ast, "Recognised DTMF digit '%c'.\n", val);
        digit[0] = val;
        digit[1] = '\0';
+       if (!wake_global) {
+               wake_global = 1;
+               char byte = 0;
+               int rc;
+               rc = write(wake_pipe[1], &byte, 1);
+       }
        strncat(call->queue_string, digit, sizeof(call->queue_string)-1);
 }
 
        strncat(call->queue_string, digit, sizeof(call->queue_string)-1);
 }
 
@@ -1134,118 +1558,20 @@ void lcr_in_dtmf(struct chan_call *call, int val)
  */
 int receive_message(int message_type, unsigned int ref, union parameter *param)
 {
  */
 int receive_message(int message_type, unsigned int ref, union parameter *param)
 {
-       struct bchannel *bchannel;
        struct chan_call *call;
        union parameter newparam;
        struct chan_call *call;
        union parameter newparam;
+       int rc = 0;
 
        memset(&newparam, 0, sizeof(union parameter));
 
 
        memset(&newparam, 0, sizeof(union parameter));
 
-       /* handle bchannel message*/
-       if (message_type == MESSAGE_BCHANNEL)
-       {
-               switch(param->bchannel.type)
-               {
-                       case BCHANNEL_ASSIGN:
-                       CDEBUG(NULL, NULL, "Received BCHANNEL_ASSIGN message. (handle=%08lx) for ref %d\n", param->bchannel.handle, ref);
-                       if ((bchannel = find_bchannel_handle(param->bchannel.handle)))
-                       {
-                               CERROR(NULL, NULL, "bchannel handle %x already assigned.\n", (int)param->bchannel.handle);
-                               return(-1);
-                       }
-                       /* create bchannel */
-                       bchannel = alloc_bchannel(param->bchannel.handle);
-                       if (!bchannel)
-                       {
-                               CERROR(NULL, NULL, "alloc bchannel handle %x failed.\n", (int)param->bchannel.handle);
-                               return(-1);
-                       }
-
-                       /* configure channel */
-                       bchannel->b_tx_gain = param->bchannel.tx_gain;
-                       bchannel->b_rx_gain = param->bchannel.rx_gain;
-                       strncpy(bchannel->b_pipeline, param->bchannel.pipeline, sizeof(bchannel->b_pipeline)-1);
-                       if (param->bchannel.crypt_len && param->bchannel.crypt_len <= sizeof(bchannel->b_bf_key))
-                       {
-                               bchannel->b_bf_len = param->bchannel.crypt_len;
-                               memcpy(bchannel->b_bf_key, param->bchannel.crypt, param->bchannel.crypt_len);
-                       }
-                       bchannel->b_txdata = 0;
-                       bchannel->b_dtmf = 1;
-                       bchannel->b_tx_dejitter = 1;
-
-                       /* in case, ref is not set, this bchannel instance must
-                        * be created until it is removed again by LCR */
-                       /* link to call */
-                       call = find_call_ref(ref);
-                       if (call)
-                       {
-                               bchannel->call = call;
-                               call->bchannel = bchannel;
-                               if (call->dtmf)
-                                       bchannel_dtmf(bchannel, 1);
-                               if (call->bf_len)
-                                       bchannel_blowfish(bchannel, call->bf_key, call->bf_len);
-                               if (call->pipeline[0])
-                                       bchannel_pipeline(bchannel, call->pipeline);
-                               if (call->rx_gain)
-                                       bchannel_gain(bchannel, call->rx_gain, 0);
-                               if (call->tx_gain)
-                                       bchannel_gain(bchannel, call->tx_gain, 1);
-                               if (call->bridge_id) {
-                                       CDEBUG(call, call->ast, "Join bchannel, because call is already bridged.\n");
-                                       bchannel_join(bchannel, call->bridge_id);
-                               }
-                               /* create only, if call exists, othewhise it bchannel is freed below... */
-                               if (bchannel_create(bchannel, ((call->nodsp || call->faxdetect > 0)?1:0) + ((call->hdlc)?2:0)))
-                                       bchannel_activate(bchannel, 1);
-                       }
-                       /* acknowledge */
-                       newparam.bchannel.type = BCHANNEL_ASSIGN_ACK;
-                       newparam.bchannel.handle = param->bchannel.handle;
-                       send_message(MESSAGE_BCHANNEL, 0, &newparam);
-                       /* if call has released before bchannel is assigned */
-                       if (!call) {
-                               newparam.bchannel.type = BCHANNEL_RELEASE;
-                               newparam.bchannel.handle = param->bchannel.handle;
-                               send_message(MESSAGE_BCHANNEL, 0, &newparam);
-                       }
-
-                       break;
-
-                       case BCHANNEL_REMOVE:
-                       CDEBUG(NULL, NULL, "Received BCHANNEL_REMOVE message. (handle=%08lx)\n", param->bchannel.handle);
-                       if (!(bchannel = find_bchannel_handle(param->bchannel.handle)))
-                       {
-                               CERROR(NULL, NULL, "Bchannel handle %x not assigned.\n", (int)param->bchannel.handle);
-                               return(-1);
-                       }
-                       /* unklink from call and destroy bchannel */
-                       free_bchannel(bchannel);
-
-                       /* acknowledge */
-                       newparam.bchannel.type = BCHANNEL_REMOVE_ACK;
-                       newparam.bchannel.handle = param->bchannel.handle;
-                       send_message(MESSAGE_BCHANNEL, 0, &newparam);
-                       
-                       break;
-
-                       default:
-                       CDEBUG(NULL, NULL, "Received unknown bchannel message %d.\n", param->bchannel.type);
-               }
-               return(0);
-       }
-
-       /* handle new ref */
-       if (message_type == MESSAGE_NEWREF)
-       {
-               if (param->direction)
-               {
-                       /* new ref from lcr */
-                       CDEBUG(NULL, NULL, "Received new ref by LCR, due to incomming call. (ref=%ld)\n", ref);
-                       if (!ref || find_call_ref(ref))
-                       {
-                               CERROR(NULL, NULL, "Illegal new ref %ld received.\n", ref);
-                               return(-1);
+       /* handle new ref */
+       if (message_type == MESSAGE_NEWREF) {
+               if (param->newref.direction) {
+                       /* new ref from lcr */
+                       CDEBUG(NULL, NULL, "Received new ref by LCR, due to incomming call. (ref=%ld)\n", ref);
+                       if (!ref || find_call_ref(ref)) {
+                               CERROR(NULL, NULL, "Illegal new ref %ld received.\n", ref);
+                               return -1;
                        }
                        /* allocate new call instance */
                        call = alloc_call();
                        }
                        /* allocate new call instance */
                        call = alloc_call();
@@ -1255,17 +1581,14 @@ int receive_message(int message_type, unsigned int ref, union parameter *param)
                        call->ref = ref;
                        call->ref_was_assigned = 1;
                        /* wait for setup (or release from asterisk) */
                        call->ref = ref;
                        call->ref_was_assigned = 1;
                        /* wait for setup (or release from asterisk) */
-               } else
-               {
+               } else {
                        /* new ref, as requested from this remote application */
                        CDEBUG(NULL, NULL, "Received new ref by LCR, as requested from chan_lcr. (ref=%ld)\n", ref);
                        call = find_call_ref(0);
                        /* new ref, as requested from this remote application */
                        CDEBUG(NULL, NULL, "Received new ref by LCR, as requested from chan_lcr. (ref=%ld)\n", ref);
                        call = find_call_ref(0);
-                       if (!call)
-                       {
+                       if (!call) {
                                /* send release, if ref does not exist */
                                /* send release, if ref does not exist */
-                               CDEBUG(NULL, NULL, "No call found, that requests a ref.\n");
-                               send_release_and_import(call, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL);
-                               return(0);
+                               CERROR(NULL, NULL, "No call found, that requests a ref.\n");
+                               return 0;
                        }
                        /* store new ref */
                        call->ref = ref;
                        }
                        /* store new ref */
                        call->ref = ref;
@@ -1274,38 +1597,35 @@ int receive_message(int message_type, unsigned int ref, union parameter *param)
                        if (call->state == CHAN_LCR_STATE_OUT_PREPARE)
                                send_setup_to_lcr(call);
                        /* release if asterisk has signed off */
                        if (call->state == CHAN_LCR_STATE_OUT_PREPARE)
                                send_setup_to_lcr(call);
                        /* release if asterisk has signed off */
-                       else if (call->state == CHAN_LCR_STATE_RELEASE)
-                       {
+                       else if (call->state == CHAN_LCR_STATE_RELEASE) {
                                /* send release */
                                if (call->cause)
                                /* send release */
                                if (call->cause)
-                                       send_release_and_import(call, call->cause, call->location);
+                                       send_release(call, call->cause, call->location);
                                else
                                else
-                                       send_release_and_import(call, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL);
+                                       send_release(call, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL);
                                /* free call */
                                free_call(call);
                                /* free call */
                                free_call(call);
-                               return(0);
+                               return 0;
                        }
                }
                        }
                }
-               return(0);
+               send_message(MESSAGE_ENABLEKEYPAD, call->ref, &newparam);
+               return 0;
        }
 
        /* check ref */
        }
 
        /* check ref */
-       if (!ref)
-       {
+       if (!ref) {
                CERROR(NULL, NULL, "Received message %d without ref.\n", message_type);
                CERROR(NULL, NULL, "Received message %d without ref.\n", message_type);
-               return(-1);
+               return -1;
        }
        call = find_call_ref(ref);
        }
        call = find_call_ref(ref);
-       if (!call)
-       {
+       if (!call) {
                /* ignore ref that is not used (anymore) */
                CDEBUG(NULL, NULL, "Message %d from LCR ignored, because no call instance found.\n", message_type);
                /* ignore ref that is not used (anymore) */
                CDEBUG(NULL, NULL, "Message %d from LCR ignored, because no call instance found.\n", message_type);
-               return(0);
+               return 0;
        }
 
        /* handle messages */
        }
 
        /* handle messages */
-       switch(message_type)
-       {
+       switch(message_type) {
                case MESSAGE_SETUP:
                lcr_in_setup(call, message_type, param);
                break;
                case MESSAGE_SETUP:
                lcr_in_setup(call, message_type, param);
                break;
@@ -1347,6 +1667,8 @@ int receive_message(int message_type, unsigned int ref, union parameter *param)
                break;
 
                case MESSAGE_PATTERN: // audio available from LCR
                break;
 
                case MESSAGE_PATTERN: // audio available from LCR
+               if (!call->has_pattern)
+                       lcr_in_pattern(call, message_type, param);
                break;
 
                case MESSAGE_NOPATTERN: // audio not available from LCR
                break;
 
                case MESSAGE_NOPATTERN: // audio not available from LCR
@@ -1356,11 +1678,25 @@ int receive_message(int message_type, unsigned int ref, union parameter *param)
                call->audiopath = param->audiopath;
                break;
 
                call->audiopath = param->audiopath;
                break;
 
+               case MESSAGE_TRAFFIC: // if remote audio connected or hold
+               {
+                       unsigned char *p = param->traffic.data;
+                       int i, len = param->traffic.len;
+                       for (i = 0; i < len; i++, p++)
+                               *p = flip_bits[*p];
+               }
+               rc = write(call->pipe[1], param->traffic.data, param->traffic.len);
+               break;
+
+               case MESSAGE_DTMF:
+               lcr_in_dtmf(call, param->dtmf);
+               break;
+
                default:
                CDEBUG(call, call->ast, "Message %d from LCR unhandled.\n", message_type);
                break;
        }
                default:
                CDEBUG(call, call->ast, "Message %d from LCR unhandled.\n", message_type);
                break;
        }
-       return(0);
+       return rc;
 }
 
 /*
 }
 
 /*
@@ -1393,89 +1729,85 @@ again:
                        goto again;
                }
                CDEBUG(call, call->ast, "Queue call release, because Asterisk channel is running.\n");
                        goto again;
                }
                CDEBUG(call, call->ast, "Queue call release, because Asterisk channel is running.\n");
+               if (!wake_global) {
+                       wake_global = 1;
+                       char byte = 0;
+                       int rc;
+                       rc = write(wake_pipe[1], &byte, 1);
+               }
                strcpy(call->queue_string, "H");
                call = call->next;
        }
                strcpy(call->queue_string, "H");
                call = call->next;
        }
-
-       /* release all bchannels */
-       while(bchannel_first)
-               free_bchannel(bchannel_first);
 }
 
 }
 
+void close_socket(void);
 
 /* asterisk handler
  * warning! not thread safe
  * returns -1 for socket error, 0 for no work, 1 for work
  */
 
 /* asterisk handler
  * warning! not thread safe
  * returns -1 for socket error, 0 for no work, 1 for work
  */
-int handle_socket(void)
+static int handle_socket(struct lcr_fd *fd, unsigned int what, void *instance, int index)
 {
 {
-       int work = 0;
        int len;
        struct admin_list *admin;
        struct admin_message msg;
 
        int len;
        struct admin_list *admin;
        struct admin_message msg;
 
-       /* read from socket */
-       len = read(lcr_sock, &msg, sizeof(msg));
-       if (len == 0)
-       {
-               CERROR(NULL, NULL, "Socket closed.\n");
-               return(-1); // socket closed
-       }
-       if (len > 0)
-       {
-               if (len != sizeof(msg))
-               {
-                       CERROR(NULL, NULL, "Socket short read. (len %d)\n", len);
-                       return(-1); // socket error
-               }
-               if (msg.message != ADMIN_MESSAGE)
-               {
-                       CERROR(NULL, NULL, "Socket received illegal message %d.\n", msg.message);
-                       return(-1);
+       if ((what & LCR_FD_READ)) {
+               /* read from socket */
+               len = read(lcr_sock, &msg, sizeof(msg));
+               if (len == 0) {
+                       CERROR(NULL, NULL, "Socket closed.(read)\n");
+                       error:
+                       CERROR(NULL, NULL, "Handling of socket failed - closing for some seconds.\n");
+                       close_socket();
+                       release_all_calls();
+                       schedule_timer(&socket_retry, SOCKET_RETRY_TIMER, 0);
+                       return 0;
                }
                }
-               receive_message(msg.u.msg.type, msg.u.msg.ref, &msg.u.msg.param);
-               work = 1;
-       } else
-       {
-               if (errno != EWOULDBLOCK)
-               {
+               if (len > 0) {
+                       if (len != sizeof(msg)) {
+                               CERROR(NULL, NULL, "Socket short read. (len %d)\n", len);
+                               goto error;
+                       }
+                       if (msg.message != ADMIN_MESSAGE) {
+                               CERROR(NULL, NULL, "Socket received illegal message %d.\n", msg.message);
+                               goto error;
+                       }
+                       receive_message(msg.u.msg.type, msg.u.msg.ref, &msg.u.msg.param);
+               } else {
                        CERROR(NULL, NULL, "Socket failed (errno %d).\n", errno);
                        CERROR(NULL, NULL, "Socket failed (errno %d).\n", errno);
-                       return(-1);
+                       goto error;
                }
        }
 
                }
        }
 
-       /* write to socket */
-       if (!admin_first)
-               return(work);
-       admin = admin_first;
-       len = write(lcr_sock, &admin->msg, sizeof(msg));
-       if (len == 0)
-       {
-               CERROR(NULL, NULL, "Socket closed.\n");
-               return(-1); // socket closed
-       }
-       if (len > 0)
-       {
-               if (len != sizeof(msg))
-               {
-                       CERROR(NULL, NULL, "Socket short write. (len %d)\n", len);
-                       return(-1); // socket error
+       if ((what & LCR_FD_WRITE)) {
+               /* write to socket */
+               if (!admin_first) {
+                       socket_fd.when &= ~LCR_FD_WRITE;
+                       return 0;
                }
                }
-               /* free head */
-               admin_first = admin->next;
-               free(admin);
-
-               work = 1;
-       } else
-       {
-               if (errno != EWOULDBLOCK)
-               {
+               admin = admin_first;
+               len = write(lcr_sock, &admin->msg, sizeof(msg));
+               if (len == 0) {
+                       CERROR(NULL, NULL, "Socket closed.(write)\n");
+                       goto error;
+               }
+               if (len > 0) {
+                       if (len != sizeof(msg)) {
+                               CERROR(NULL, NULL, "Socket short write. (len %d)\n", len);
+                               goto error;
+                       }
+                       /* free head */
+                       admin_first = admin->next;
+                       free(admin);
+                       global_change = 1;
+               } else {
                        CERROR(NULL, NULL, "Socket failed (errno %d).\n", errno);
                        CERROR(NULL, NULL, "Socket failed (errno %d).\n", errno);
-                       return(-1);
+                       goto error;
                }
        }
 
                }
        }
 
-       return(work);
+       return 0;
 }
 
 /*
 }
 
 /*
@@ -1483,17 +1815,14 @@ int handle_socket(void)
  */
 int open_socket(void)
 {
  */
 int open_socket(void)
 {
-       int ret;
        int conn;
        struct sockaddr_un sock_address;
        int conn;
        struct sockaddr_un sock_address;
-       unsigned int on = 1;
        union parameter param;
 
        /* open socket */
        union parameter param;
 
        /* open socket */
-       if ((lcr_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
-       {
+       if ((lcr_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
                CERROR(NULL, NULL, "Failed to create socket.\n");
                CERROR(NULL, NULL, "Failed to create socket.\n");
-               return(lcr_sock);
+               return lcr_sock;
        }
 
        /* set socket address and name */
        }
 
        /* set socket address and name */
@@ -1502,35 +1831,36 @@ int open_socket(void)
        sprintf(sock_address.sun_path, SOCKET_NAME, options.lock);
 
        /* connect socket */
        sprintf(sock_address.sun_path, SOCKET_NAME, options.lock);
 
        /* connect socket */
-       if ((conn = connect(lcr_sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
-       {
+       if ((conn = connect(lcr_sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0) {
                close(lcr_sock);
                lcr_sock = -1;
                CDEBUG(NULL, NULL, "Failed to connect to socket '%s'. Is LCR running?\n", sock_address.sun_path);
                close(lcr_sock);
                lcr_sock = -1;
                CDEBUG(NULL, NULL, "Failed to connect to socket '%s'. Is LCR running?\n", sock_address.sun_path);
-               return(conn);
+               return conn;
        }
 
        }
 
-       /* set non-blocking io */
-       if ((ret = ioctl(lcr_sock, FIONBIO, (unsigned char *)(&on))) < 0)
-       {
-               close(lcr_sock);
-               lcr_sock = -1;
-               CERROR(NULL, NULL, "Failed to set socket into non-blocking IO.\n");
-               return(ret);
-       }
+       /* register socket fd */
+       memset(&socket_fd, 0, sizeof(socket_fd));
+       socket_fd.fd = lcr_sock;
+       register_fd(&socket_fd, LCR_FD_READ | LCR_FD_EXCEPT, handle_socket, NULL, 0);
 
        /* enque hello message */
        memset(&param, 0, sizeof(param));
        strcpy(param.hello.application, "asterisk");
        send_message(MESSAGE_HELLO, 0, &param);
 
 
        /* enque hello message */
        memset(&param, 0, sizeof(param));
        strcpy(param.hello.application, "asterisk");
        send_message(MESSAGE_HELLO, 0, &param);
 
-       return(lcr_sock);
+       return lcr_sock;
 }
 
 void close_socket(void)
 {
        struct admin_list *admin, *temp;
 }
 
 void close_socket(void)
 {
        struct admin_list *admin, *temp;
-       
+
+       /* socket not created */
+       if (lcr_sock < 0)
+               return;
+
+       unregister_fd(&socket_fd);
+
        /* flush pending messages */
        admin = admin_first;
        while(admin) {
        /* flush pending messages */
        admin = admin_first;
        while(admin) {
@@ -1541,173 +1871,152 @@ void close_socket(void)
        admin_first = NULL;
 
        /* close socket */
        admin_first = NULL;
 
        /* close socket */
-       if (lcr_sock >= 0)      
-               close(lcr_sock);
+       close(lcr_sock);
        lcr_sock = -1;
        lcr_sock = -1;
+       global_change = 1;
 }
 
 
 /* sending queue to asterisk */
 }
 
 
 /* sending queue to asterisk */
-static int queue_send(void)
+static int wake_event(struct lcr_fd *fd, unsigned int what, void *instance, int index)
+{
+       char byte;
+       int rc;
+
+       rc = read(wake_pipe[0], &byte, 1);
+
+       wake_global = 0;
+
+       return 0;
+}
+
+static void handle_queue()
 {
 {
-       int work = 0;
        struct chan_call *call;
        struct ast_channel *ast;
        struct ast_frame fr;
        char *p;
 
        struct chan_call *call;
        struct ast_channel *ast;
        struct ast_frame fr;
        char *p;
 
+again:
        call = call_first;
        while(call) {
                p = call->queue_string;
                ast = call->ast;
                if (*p && ast) {
        call = call_first;
        while(call) {
                p = call->queue_string;
                ast = call->ast;
                if (*p && ast) {
-                       /* there is something to queue */
-                       if (!ast_channel_trylock(ast)) { /* succeed */
-                               while(*p) {
-                                       switch (*p) {
-                                       case 'P':
-                                               CDEBUG(call, ast, "Sending queued PROCEEDING to Asterisk.\n");
-                                               ast_queue_control(ast, AST_CONTROL_PROCEEDING);
-                                               break;
-                                       case 'R':
-                                               CDEBUG(call, ast, "Sending queued RINGING to Asterisk.\n");
-                                               ast_queue_control(ast, AST_CONTROL_RINGING);
-                                               ast_setstate(ast, AST_STATE_RINGING);
-                                               break;
-                                       case 'N':
-                                               CDEBUG(call, ast, "Sending queued ANSWER to Asterisk.\n");
-                                               ast_queue_control(ast, AST_CONTROL_ANSWER);
-                                               break;
-                                       case 'H':
-                                               CDEBUG(call, ast, "Sending queued HANGUP to Asterisk.\n");
-                                               ast_queue_hangup(ast);
-                                               break;
-                                       case '1': case '2': case '3': case 'A':
-                                       case '4': case '5': case '6': case 'B':
-                                       case '7': case '8': case '9': case 'C':
-                                       case '*': case '0': case '#': case 'D':
-                                               CDEBUG(call, ast, "Sending queued digit '%c' to Asterisk.\n", *p);
-                                               /* send digit to asterisk */
-                                               memset(&fr, 0, sizeof(fr));
-                                               
-                                               #ifdef LCR_FOR_ASTERISK
-                                               fr.frametype = AST_FRAME_DTMF_BEGIN;
-                                               #endif
-
-                                               #ifdef LCR_FOR_CALLWEAVER
-                                               fr.frametype = AST_FRAME_DTMF;
-                                               #endif
-                                               
-                                               fr.subclass = *p;
-                                               fr.delivery = ast_tv(0, 0);
-                                               ast_queue_frame(ast, &fr);
-                                               
-                                               #ifdef LCR_FOR_ASTERISK
-                                               fr.frametype = AST_FRAME_DTMF_END;
-                                               ast_queue_frame(ast, &fr);
-                                               #endif
-                                                                                               
-                                               break;
-                                       default:
-                                               CDEBUG(call, ast, "Ignoring queued digit 0x%02x.\n", *p);
-                                       }
-                                       p++;
+                       if (ast_channel_trylock(ast)) {
+                               ast_mutex_unlock(&chan_lock);
+                               usleep(1);
+                               ast_mutex_lock(&chan_lock);
+                               goto again;
+                       }
+                       while(*p) {
+                               switch (*p) {
+                               case 'T':
+                                       CDEBUG(call, ast, "Sending queued PROGRESS to Asterisk.\n");
+                                       ast_queue_control(ast, AST_CONTROL_PROGRESS);
+                                       break;
+                               case 'P':
+                                       CDEBUG(call, ast, "Sending queued PROCEEDING to Asterisk.\n");
+                                       ast_queue_control(ast, AST_CONTROL_PROCEEDING);
+                                       break;
+                               case 'R':
+                                       CDEBUG(call, ast, "Sending queued RINGING to Asterisk.\n");
+                                       ast_queue_control(ast, AST_CONTROL_RINGING);
+                                       ast_setstate(ast, AST_STATE_RINGING);
+                                       break;
+                               case 'N':
+                                       CDEBUG(call, ast, "Sending queued ANSWER to Asterisk.\n");
+                                       ast_queue_control(ast, AST_CONTROL_ANSWER);
+                                       break;
+                               case 'H':
+                                       CDEBUG(call, ast, "Sending queued HANGUP to Asterisk.\n");
+                                       ast_queue_hangup(ast);
+                                       break;
+                               case '1': case '2': case '3': case 'A':
+                               case '4': case '5': case '6': case 'B':
+                               case '7': case '8': case '9': case 'C':
+                               case '*': case '0': case '#': case 'D':
+                                       CDEBUG(call, ast, "Sending queued digit '%c' to Asterisk.\n", *p);
+                                       /* send digit to asterisk */
+                                       memset(&fr, 0, sizeof(fr));
+
+                                       #ifdef LCR_FOR_ASTERISK
+                                       fr.frametype = AST_FRAME_DTMF_BEGIN;
+                                       #endif
+
+                                       #ifdef LCR_FOR_CALLWEAVER
+                                       fr.frametype = AST_FRAME_DTMF;
+                                       #endif
+
+#ifdef AST_1_8_OR_HIGHER
+                                       fr.subclass.integer = *p;
+#else
+                                       fr.subclass = *p;
+#endif
+                                       fr.delivery = ast_tv(0, 0);
+                                       ast_queue_frame(ast, &fr);
+
+                                       #ifdef LCR_FOR_ASTERISK
+                                       fr.frametype = AST_FRAME_DTMF_END;
+                                       ast_queue_frame(ast, &fr);
+                                       #endif
+
+                                       break;
+                               default:
+                                       CDEBUG(call, ast, "Ignoring queued digit 0x%02x.\n", *p);
                                }
                                }
-                               call->queue_string[0] = '\0';
-                               ast_channel_unlock(ast);
-                               work = 1;
+                               p++;
                        }
                        }
+                       call->queue_string[0] = '\0';
+                       ast_channel_unlock(ast);
                }
                call = call->next;
        }
                }
                call = call->next;
        }
+}
+
+static int handle_retry(struct lcr_timer *timer, void *instance, int index)
+{
+       CDEBUG(NULL, NULL, "Retry to open socket.\n");
+       if (open_socket() < 0)
+               schedule_timer(&socket_retry, SOCKET_RETRY_TIMER, 0);
 
 
-       return work;
+       return 0;
+}
+
+void lock_chan(void)
+{
+       ast_mutex_lock(&chan_lock);
 }
 
 }
 
-/* signal handler */
-void sighandler(int sigset)
+void unlock_chan(void)
 {
 {
+       ast_mutex_unlock(&chan_lock);
 }
 
 /* chan_lcr thread */
 static void *chan_thread(void *arg)
 {
 }
 
 /* chan_lcr thread */
 static void *chan_thread(void *arg)
 {
-       int work;
-       int ret;
-       union parameter param;
-       time_t retry = 0, now;
+       if (pipe(wake_pipe) < 0) {
+               CERROR(NULL, NULL, "Failed to open pipe.\n");
+               return NULL;
+       }
+       memset(&wake_fd, 0, sizeof(wake_fd));
+       wake_fd.fd = wake_pipe[0];
+       register_fd(&wake_fd, LCR_FD_READ, wake_event, NULL, 0);
 
 
-       bchannel_pid = getpid();
+       memset(&socket_retry, 0, sizeof(socket_retry));
+       add_timer(&socket_retry, handle_retry, NULL, 0);
 
 
-//     signal(SIGPIPE, sighandler);
-       
-       memset(&param, 0, sizeof(union parameter));
-       if (lcr_sock < 0)
-               time(&retry);
+       /* open socket the first time */
+       handle_retry(NULL, NULL, 0);
 
        ast_mutex_lock(&chan_lock);
 
 
        ast_mutex_lock(&chan_lock);
 
-       while(!quit) {
-               work = 0;
-
-               if (lcr_sock > 0) {
-                       /* handle socket */
-                       ret = handle_socket();
-                       if (ret < 0) {
-                               CERROR(NULL, NULL, "Handling of socket failed - closing for some seconds.\n");
-                               close_socket();
-                               release_all_calls();
-                               time(&retry);
-                       }
-                       if (ret)
-                               work = 1;
-               } else {
-                       time(&now);
-                       if (retry && now-retry > 5) {
-                               CDEBUG(NULL, NULL, "Retry to open socket.\n");
-                               retry = 0;
-                               if (open_socket() < 0) {
-                                       time(&retry);
-                               }
-                               work = 1;
-                       }
-                                       
-               }
-
-               /* handle mISDN */
-               ret = bchannel_handle();
-               if (ret)
-                       work = 1;
-
-               /* handle messages to asterisk */
-               ret = queue_send();
-               if (ret)
-                       work = 1;
-
-               /* delay if no work done */
-               if (!work) {
-                       ast_mutex_unlock(&chan_lock);
-
-                       #ifdef LCR_FOR_ASTERISK                 
-                       usleep(30000);
-                       #endif
-                       
-                       #ifdef LCR_FOR_CALLWEAVER                       
-                       usleep(20000);
-                       #endif
-                       
-                       ast_mutex_lock(&chan_lock);
-               }
+       while(1) {
+               handle_queue();
+               select_main(0, &global_change, lock_chan, unlock_chan);
        }
 
        }
 
-       close_socket();
-
-       CERROR(NULL, NULL, "Thread exit.\n");
-       
-       ast_mutex_unlock(&chan_lock);
-
-//     signal(SIGPIPE, SIG_DFL);
-
        return NULL;
 }
 
        return NULL;
 }
 
@@ -1715,18 +2024,29 @@ static void *chan_thread(void *arg)
  * new asterisk instance
  */
 static
  * new asterisk instance
  */
 static
+#ifdef AST_1_8_OR_HIGHER
+#if ASTERISK_VERSION_NUM < 100000
+struct ast_channel *lcr_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
+#else
+struct ast_channel *lcr_request(const char *type, struct ast_format_cap *format, const struct ast_channel *requestor, void *data, int *cause)
+#endif
+#else
 struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
 struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
+#endif
 {
        char exten[256], *dial, *interface, *opt;
        struct ast_channel *ast;
 {
        char exten[256], *dial, *interface, *opt;
        struct ast_channel *ast;
-        struct chan_call *call;
+       struct chan_call *call;
+#ifdef AST_1_8_OR_HIGHER
+       const struct ast_party_redirecting *req_redir;
+       const struct ast_party_caller *req_caller;
+#endif
 
        ast_mutex_lock(&chan_lock);
        CDEBUG(NULL, NULL, "Received request from Asterisk. (data=%s)\n", (char *)data);
 
        /* if socket is closed */
 
        ast_mutex_lock(&chan_lock);
        CDEBUG(NULL, NULL, "Received request from Asterisk. (data=%s)\n", (char *)data);
 
        /* if socket is closed */
-       if (lcr_sock < 0)
-       {
+       if (lcr_sock < 0) {
                CERROR(NULL, NULL, "Rejecting call from Asterisk, because LCR not running.\n");
                ast_mutex_unlock(&chan_lock);
                return NULL;
                CERROR(NULL, NULL, "Rejecting call from Asterisk, because LCR not running.\n");
                ast_mutex_unlock(&chan_lock);
                return NULL;
@@ -1734,8 +2054,7 @@ struct ast_channel *lcr_request(const char *type, int format, void *data, int *c
 
        /* create call instance */
        call = alloc_call();
 
        /* create call instance */
        call = alloc_call();
-       if (!call)
-       {
+       if (!call) {
                /* failed to create instance */
                ast_mutex_unlock(&chan_lock);
                return NULL;
                /* failed to create instance */
                ast_mutex_unlock(&chan_lock);
                return NULL;
@@ -1744,34 +2063,80 @@ struct ast_channel *lcr_request(const char *type, int format, void *data, int *c
        /* create asterisk channel instrance */
 
        #ifdef LCR_FOR_ASTERISK
        /* create asterisk channel instrance */
 
        #ifdef LCR_FOR_ASTERISK
+#ifdef AST_1_8_OR_HIGHER
+       ast = ast_channel_alloc(1, AST_STATE_RESERVED, NULL, NULL, NULL, NULL, NULL, NULL, 0, "%s/%d", lcr_type, ++glob_channel);
+#else
        ast = ast_channel_alloc(1, AST_STATE_RESERVED, NULL, NULL, "", NULL, "", 0, "%s/%d", lcr_type, ++glob_channel);
        ast = ast_channel_alloc(1, AST_STATE_RESERVED, NULL, NULL, "", NULL, "", 0, "%s/%d", lcr_type, ++glob_channel);
+#endif
        #endif
        #endif
-       
+
        #ifdef LCR_FOR_CALLWEAVER
        ast = ast_channel_alloc(1);
        #endif
        #ifdef LCR_FOR_CALLWEAVER
        ast = ast_channel_alloc(1);
        #endif
-               
-       if (!ast)
-       {
+
+       if (!ast) {
                CERROR(NULL, NULL, "Failed to create Asterisk channel.\n");
                free_call(call);
                /* failed to create instance */
                ast_mutex_unlock(&chan_lock);
                return NULL;
        }
                CERROR(NULL, NULL, "Failed to create Asterisk channel.\n");
                free_call(call);
                /* failed to create instance */
                ast_mutex_unlock(&chan_lock);
                return NULL;
        }
+#if ASTERISK_VERSION_NUM < 110000
        ast->tech = &lcr_tech;
        ast->tech_pvt = (void *)1L; // set pointer or asterisk will not call
        ast->tech = &lcr_tech;
        ast->tech_pvt = (void *)1L; // set pointer or asterisk will not call
+#ifdef AST_1_8_OR_HIGHER
+       req_redir = &requestor->redirecting;
+       req_caller = &requestor->caller;
+#endif
+#else
+       ast_channel_tech_set(ast, &lcr_tech);
+       ast_channel_tech_pvt_set(ast, (void *)1L); // set pointer or asterisk will not call
+       req_redir = ast_channel_redirecting(requestor);
+       req_caller = ast_channel_caller(requestor);
+#endif
        /* configure channel */
        /* configure channel */
+#if ASTERISK_VERSION_NUM < 100000
+#if ASTERISK_VERSION_NUM < 110000
        ast->nativeformats = (options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW;
        ast->readformat = ast->rawreadformat = ast->nativeformats;
        ast->writeformat = ast->rawwriteformat =  ast->nativeformats;
        ast->nativeformats = (options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW;
        ast->readformat = ast->rawreadformat = ast->nativeformats;
        ast->writeformat = ast->rawwriteformat =  ast->nativeformats;
+#else
+       ast_channel_nativeformats_set(ast, (options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW);
+       ast->readformat = ast->rawreadformat = ast_channel_nativeformats(ast);
+       ast->writeformat = ast->rawwriteformat =  ast_channel_nativeformats(ast);
+#endif
+#else
+#if ASTERISK_VERSION_NUM < 110000
+       ast_format_set(&ast->rawwriteformat ,(options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW , 0);
+       ast_format_copy(&ast->rawreadformat, &ast->rawwriteformat);
+       ast_format_cap_set(ast->nativeformats, &ast->rawwriteformat);
+       ast_set_write_format(ast, &ast->rawwriteformat);
+       ast_set_read_format(ast, &ast->rawreadformat);
+#else
+       ast_format_set(ast_channel_rawwriteformat(ast) ,(options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW , 0);
+       ast_format_copy(ast_channel_rawreadformat(ast), ast_channel_rawwriteformat(ast));
+       ast_format_cap_set(ast_channel_nativeformats(ast), ast_channel_rawwriteformat(ast));
+       ast_set_write_format(ast, ast_channel_rawwriteformat(ast));
+       ast_set_read_format(ast, ast_channel_rawreadformat(ast));
+#endif
+#endif
+#if ASTERISK_VERSION_NUM < 110000
        ast->priority = 1;
        ast->hangupcause = 0;
        ast->priority = 1;
        ast->hangupcause = 0;
+#else
+       ast_channel_priority_set(ast, 1);
+       ast_channel_hangupcause_set(ast, 0);
+#endif
 
        /* link together */
        call->ast = ast;
 
        /* link together */
        call->ast = ast;
+#if ASTERISK_VERSION_NUM < 110000
        ast->tech_pvt = call;
        ast->fds[0] = call->pipe[0];
        ast->tech_pvt = call;
        ast->fds[0] = call->pipe[0];
+#else
+       ast_channel_tech_pvt_set(ast, call);
+       ast_channel_set_fd(ast, 0, call->pipe[0]);
+#endif
        call->pbx_started = 0;
        /* set state */
        call->state = CHAN_LCR_STATE_OUT_PREPARE;
        call->pbx_started = 0;
        /* set state */
        call->state = CHAN_LCR_STATE_OUT_PREPARE;
@@ -1801,6 +2166,227 @@ struct ast_channel *lcr_request(const char *type, int format, void *data, int *c
        strncpy(call->dialstring, dial, sizeof(call->dialstring)-1);
        apply_opt(call, (char *)opt);
 
        strncpy(call->dialstring, dial, sizeof(call->dialstring)-1);
        apply_opt(call, (char *)opt);
 
+#ifdef AST_1_8_OR_HIGHER
+//     clone_variables(requestor, ast);
+
+#if 0
+       ast->caller.ani.number.valid=                   req_caller->ani.number.valid;
+       if (req_caller->ani.number.valid)
+         if (req_caller->ani.number.str)
+           if (req_caller->ani.number.str[0])
+               ast->caller.ani.number.str=             strdup(req_caller->ani.number.str);
+       ast->caller.ani.number.plan=                    req_caller->ani.number.plan;
+       ast->caller.ani.number.presentation=            req_caller->ani.number.presentation;
+
+       ast->caller.ani.name.valid=                     req_caller->ani.name.valid;
+       if (req_caller->ani.name.valid)
+         if (req_caller->ani.name.str)
+           if (req_caller->ani.name.str[0])
+               ast->caller.ani.name.str=               strdup(req_caller->ani.name.str);
+       ast->caller.ani.name.presentation=              req_caller->ani.name.presentation;
+
+       ast->caller.ani.subaddress.valid=               req_caller->ani.subaddress.valid;
+       if (req_caller->ani.subaddress.valid)
+         if (req_caller->ani.subaddress.str)
+           if (req_caller->ani.subaddress.str[0])
+               ast->caller.ani.subaddress.str=         strdup(req_caller->ani.subaddress.str);
+       ast->caller.ani.subaddress.type=                req_caller->ani.subaddress.type;
+
+       ast->caller.id.number.valid=                    req_caller->id.number.valid;
+       if (req_caller->id.number.valid)
+         if (req_caller->id.number.str)
+           if (req_caller->id.number.str[0])
+               ast->caller.id.number.str=              strdup(req_caller->id.number.str);
+       ast->caller.id.number.plan=                     req_caller->id.number.plan;
+       ast->caller.id.number.presentation=             req_caller->id.number.presentation;
+
+       ast->caller.id.name.valid=                      req_caller->id.name.valid;
+       if (req_caller->id.name.valid)
+         if (req_caller->id.name.str)
+           if (req_caller->id.name.str[0])
+               ast->caller.id.name.str=                strdup(req_caller->id.name.str);
+       ast->caller.id.name.presentation=               req_caller->id.name.presentation;
+
+       ast->caller.id.subaddress.valid=                req_caller->id.subaddress.valid;
+       if (req_caller->id.subaddress.valid)
+         if (req_caller->id.subaddress.str)
+           if (req_caller->id.subaddress.str[0])
+               ast->caller.id.subaddress.str=          strdup(req_caller->id.subaddress.str);
+       ast->caller.id.subaddress.type=                 req_caller->id.subaddress.type;
+
+       if (requestor->dialed.number.str)
+         if (requestor->dialed.number.str[0])
+               ast->dialed.number.str=                 strdup(requestor->dialed.number.str);
+       ast->dialed.number.plan=                        requestor->dialed.number.plan;
+
+       ast->dialed.subaddress.valid=                   requestor->dialed.subaddress.valid;
+       if (requestor->dialed.subaddress.valid)
+         if (requestor->dialed.subaddress.str)
+           if (requestor->dialed.subaddress.str[0])
+               ast->dialed.subaddress.str=             strdup(requestor->dialed.subaddress.str);
+       ast->dialed.subaddress.type=                    requestor->dialed.subaddress.type;
+
+       ast->dialed.transit_network_select=             requestor->dialed.transit_network_select;
+       ast->redirecting.count=                         req_redir->count;
+       ast->redirecting.reason=                        req_redir->reason;
+
+       ast->redirecting.from.number.valid=             req_redir->from.number.valid;
+       if (req_redir->from.number.valid)
+         if (req_redir->from.number.str)
+           if (req_redir->from.number.str[0])
+               ast->redirecting.from.number.str=       strdup(req_redir->from.number.str);
+       ast->redirecting.from.number.plan=              req_redir->from.number.plan;
+       ast->redirecting.from.number.presentation=      req_redir->from.number.presentation;
+
+       ast->redirecting.to.number.valid=               req_redir->to.number.valid;
+       if (req_redir->to.number.valid)
+         if (req_redir->to.number.str)
+           if (req_redir->to.number.str[0])
+               ast->redirecting.to.number.str=         strdup(req_redir->to.number.str);
+       ast->redirecting.to.number.plan=                req_redir->to.number.plan;
+       ast->redirecting.to.number.presentation=        req_redir->to.number.presentation;
+#endif
+       /* store call information for setup */
+
+       /* caller ID */
+       if (requestor && req_caller->id.number.valid) {
+               if (req_caller->id.number.str)
+                       strncpy(call->callerinfo.id, req_caller->id.number.str, sizeof(call->callerinfo.id)-1);
+               switch(req_caller->id.number.presentation & AST_PRES_RESTRICTION) {
+                       case AST_PRES_RESTRICTED:
+                       call->callerinfo.present = INFO_PRESENT_RESTRICTED;
+                       break;
+                       case AST_PRES_UNAVAILABLE:
+                       call->callerinfo.present = INFO_PRESENT_NOTAVAIL;
+                       break;
+                       case AST_PRES_ALLOWED:
+                       default:
+                       call->callerinfo.present = INFO_PRESENT_ALLOWED;
+               }
+               switch(req_caller->id.number.presentation & AST_PRES_NUMBER_TYPE) {
+                       case AST_PRES_USER_NUMBER_UNSCREENED:
+                       call->callerinfo.screen = INFO_SCREEN_USER;
+                       break;
+                       case AST_PRES_USER_NUMBER_PASSED_SCREEN:
+                       call->callerinfo.screen = INFO_SCREEN_USER_VERIFIED_PASSED;
+                       break;
+                       case AST_PRES_USER_NUMBER_FAILED_SCREEN:
+                       call->callerinfo.screen = INFO_SCREEN_USER_VERIFIED_FAILED;
+                       break;
+                       default:
+                       call->callerinfo.screen = INFO_SCREEN_NETWORK;
+               }
+               switch((req_caller->id.number.plan >> 4) & 7) {
+                       case 4:
+                       call->callerinfo.ntype = INFO_NTYPE_SUBSCRIBER;
+                       break;
+                       case 2:
+                       call->callerinfo.ntype = INFO_NTYPE_NATIONAL;
+                       break;
+                       case 1:
+                       call->callerinfo.ntype = INFO_NTYPE_INTERNATIONAL;
+                       break;
+                       default:
+                       call->callerinfo.ntype = INFO_NTYPE_UNKNOWN;
+               }
+       } else
+               call->callerinfo.present = INFO_PRESENT_NOTAVAIL;
+
+       /* caller ID 2 */
+       if (requestor && req_caller->ani.number.valid) {
+               if (req_caller->ani.number.str)
+                       strncpy(call->callerinfo.id2, req_caller->ani.number.str, sizeof(call->callerinfo.id2)-1);
+               switch(req_caller->ani.number.presentation & AST_PRES_RESTRICTION) {
+                       case AST_PRES_RESTRICTED:
+                       call->callerinfo.present2 = INFO_PRESENT_RESTRICTED;
+                       break;
+                       case AST_PRES_UNAVAILABLE:
+                       call->callerinfo.present2 = INFO_PRESENT_NOTAVAIL;
+                       break;
+                       case AST_PRES_ALLOWED:
+                       default:
+                       call->callerinfo.present2 = INFO_PRESENT_ALLOWED;
+               }
+               switch(req_caller->ani.number.presentation & AST_PRES_NUMBER_TYPE) {
+                       case AST_PRES_USER_NUMBER_UNSCREENED:
+                       call->callerinfo.screen2 = INFO_SCREEN_USER;
+                       break;
+                       case AST_PRES_USER_NUMBER_PASSED_SCREEN:
+                       call->callerinfo.screen2 = INFO_SCREEN_USER_VERIFIED_PASSED;
+                       break;
+                       case AST_PRES_USER_NUMBER_FAILED_SCREEN:
+                       call->callerinfo.screen2 = INFO_SCREEN_USER_VERIFIED_FAILED;
+                       break;
+                       default:
+                       call->callerinfo.screen2 = INFO_SCREEN_NETWORK;
+               }
+               switch((req_caller->ani.number.plan >> 4) & 7) {
+                       case 4:
+                       call->callerinfo.ntype2 = INFO_NTYPE_SUBSCRIBER;
+                       break;
+                       case 2:
+                       call->callerinfo.ntype2 = INFO_NTYPE_NATIONAL;
+                       break;
+                       case 1:
+                       call->callerinfo.ntype2 = INFO_NTYPE_INTERNATIONAL;
+                       break;
+                       default:
+                       call->callerinfo.ntype2 = INFO_NTYPE_UNKNOWN;
+               }
+       } else
+               call->callerinfo.present2 = INFO_PRESENT_NOTAVAIL;
+
+       /* caller name */
+       if (requestor && req_caller->id.name.valid) {
+               if (req_caller->id.name.str)
+                       strncpy(call->callerinfo.name, req_caller->id.name.str, sizeof(call->callerinfo.name)-1);
+       }
+
+       /* redir number */
+       if (requestor && req_redir->from.number.valid) {
+               call->redirinfo.itype = INFO_ITYPE_CHAN;
+               if (req_redir->from.number.str)
+                       strncpy(call->redirinfo.id, req_redir->from.number.str, sizeof(call->redirinfo.id)-1);
+               switch(req_redir->from.number.presentation & AST_PRES_RESTRICTION) {
+                       case AST_PRES_RESTRICTED:
+                       call->redirinfo.present = INFO_PRESENT_RESTRICTED;
+                       break;
+                       case AST_PRES_UNAVAILABLE:
+                       call->redirinfo.present = INFO_PRESENT_NOTAVAIL;
+                       break;
+                       case AST_PRES_ALLOWED:
+                       default:
+                       call->redirinfo.present = INFO_PRESENT_ALLOWED;
+               }
+               switch(req_redir->from.number.presentation & AST_PRES_NUMBER_TYPE) {
+                       case AST_PRES_USER_NUMBER_UNSCREENED:
+                       call->redirinfo.screen = INFO_SCREEN_USER;
+                       break;
+                       case AST_PRES_USER_NUMBER_PASSED_SCREEN:
+                       call->redirinfo.screen = INFO_SCREEN_USER_VERIFIED_PASSED;
+                       break;
+                       case AST_PRES_USER_NUMBER_FAILED_SCREEN:
+                       call->redirinfo.screen = INFO_SCREEN_USER_VERIFIED_FAILED;
+                       break;
+                       default:
+                       call->redirinfo.screen = INFO_SCREEN_NETWORK;
+               }
+               switch((req_redir->from.number.plan >> 4) & 7) {
+                       case 4:
+                       call->redirinfo.ntype = INFO_NTYPE_SUBSCRIBER;
+                       break;
+                       case 2:
+                       call->redirinfo.ntype = INFO_NTYPE_NATIONAL;
+                       break;
+                       case 1:
+                       call->redirinfo.ntype = INFO_NTYPE_INTERNATIONAL;
+                       break;
+                       default:
+                       call->redirinfo.ntype = INFO_NTYPE_UNKNOWN;
+               }
+       }
+#endif
+
        ast_mutex_unlock(&chan_lock);
        return ast;
 }
        ast_mutex_unlock(&chan_lock);
        return ast;
 }
@@ -1811,16 +2397,23 @@ struct ast_channel *lcr_request(const char *type, int format, void *data, int *c
 static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
 {
        union parameter newparam;
 static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
 {
        union parameter newparam;
-        struct chan_call *call;
+       struct chan_call *call;
+#if ASTERISK_VERSION_NUM >= 110000
+       int transfercapability;
+#endif
 
        ast_mutex_lock(&chan_lock);
 
        ast_mutex_lock(&chan_lock);
-        call = ast->tech_pvt;
-        
-        #ifdef LCR_FOR_CALLWEAVER
-        ast->type = "LCR";
-        snprintf(ast->name, sizeof(ast->name), "LCR/%s-%04x",call->dialstring, ast_random() & 0xffff);
-        #endif
-        
+#if ASTERISK_VERSION_NUM < 110000
+       call = ast->tech_pvt;
+#else
+       call = ast_channel_tech_pvt(ast);
+#endif
+
+       #ifdef LCR_FOR_CALLWEAVER
+       ast->type = "LCR";
+       snprintf(ast->name, sizeof(ast->name), "%s/%s-%04x",lcr_type, call->dialstring, ast_random() & 0xffff);
+       #endif
+
        if (!call) {
                CERROR(NULL, ast, "Received call from Asterisk, but call instance does not exist.\n");
                ast_mutex_unlock(&chan_lock);
        if (!call) {
                CERROR(NULL, ast, "Received call from Asterisk, but call instance does not exist.\n");
                ast_mutex_unlock(&chan_lock);
@@ -1833,21 +2426,37 @@ static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
        call->pbx_started = 1;
        /* send MESSAGE_NEWREF */
        memset(&newparam, 0, sizeof(union parameter));
        call->pbx_started = 1;
        /* send MESSAGE_NEWREF */
        memset(&newparam, 0, sizeof(union parameter));
-       newparam.direction = 0; /* request from app */
+       newparam.newref.direction = 0; /* request from app */
+       strncpy(newparam.newref.interface, call->interface, sizeof(newparam.newref.interface) - 1);
        send_message(MESSAGE_NEWREF, 0, &newparam);
 
        /* set hdlc if capability requires hdlc */
        send_message(MESSAGE_NEWREF, 0, &newparam);
 
        /* set hdlc if capability requires hdlc */
+#if ASTERISK_VERSION_NUM < 110000
        if (ast->transfercapability == INFO_BC_DATAUNRESTRICTED
         || ast->transfercapability == INFO_BC_DATARESTRICTED
         || ast->transfercapability == INFO_BC_VIDEO)
        if (ast->transfercapability == INFO_BC_DATAUNRESTRICTED
         || ast->transfercapability == INFO_BC_DATARESTRICTED
         || ast->transfercapability == INFO_BC_VIDEO)
+#else
+       transfercapability=ast_channel_transfercapability(ast);
+       if (transfercapability == INFO_BC_DATAUNRESTRICTED
+        || transfercapability == INFO_BC_DATARESTRICTED
+        || transfercapability == INFO_BC_VIDEO)
+#endif
                call->hdlc = 1;
        /* if hdlc is forced by option, we change transcap to data */
        if (call->hdlc
                call->hdlc = 1;
        /* if hdlc is forced by option, we change transcap to data */
        if (call->hdlc
+#if ASTERISK_VERSION_NUM < 110000
         && ast->transfercapability != INFO_BC_DATAUNRESTRICTED
         && ast->transfercapability != INFO_BC_DATARESTRICTED
         && ast->transfercapability != INFO_BC_VIDEO)
                ast->transfercapability = INFO_BC_DATAUNRESTRICTED;
         && ast->transfercapability != INFO_BC_DATAUNRESTRICTED
         && ast->transfercapability != INFO_BC_DATARESTRICTED
         && ast->transfercapability != INFO_BC_VIDEO)
                ast->transfercapability = INFO_BC_DATAUNRESTRICTED;
+#else
+        && transfercapability != INFO_BC_DATAUNRESTRICTED
+        && transfercapability != INFO_BC_DATARESTRICTED
+        && transfercapability != INFO_BC_VIDEO)
+               transfercapability = INFO_BC_DATAUNRESTRICTED;
+#endif
 
 
+#ifndef AST_1_8_OR_HIGHER
        call->cid_num[0] = 0;
        call->cid_name[0] = 0;
        call->cid_rdnis[0] = 0;
        call->cid_num[0] = 0;
        call->cid_name[0] = 0;
        call->cid_rdnis[0] = 0;
@@ -1855,51 +2464,53 @@ static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
        if (ast->cid.cid_num) if (ast->cid.cid_num[0])
                strncpy(call->cid_num, ast->cid.cid_num,
                        sizeof(call->cid_num)-1);
        if (ast->cid.cid_num) if (ast->cid.cid_num[0])
                strncpy(call->cid_num, ast->cid.cid_num,
                        sizeof(call->cid_num)-1);
-
        if (ast->cid.cid_name) if (ast->cid.cid_name[0])
        if (ast->cid.cid_name) if (ast->cid.cid_name[0])
-               strncpy(call->cid_name, ast->cid.cid_name, 
+               strncpy(call->cid_name, ast->cid.cid_name,
                        sizeof(call->cid_name)-1);
        if (ast->cid.cid_rdnis) if (ast->cid.cid_rdnis[0])
                        sizeof(call->cid_name)-1);
        if (ast->cid.cid_rdnis) if (ast->cid.cid_rdnis[0])
-               strncpy(call->cid_rdnis, ast->cid.cid_rdnis, 
+               strncpy(call->cid_rdnis, ast->cid.cid_rdnis,
                        sizeof(call->cid_rdnis)-1);
                        sizeof(call->cid_rdnis)-1);
+#endif
 
        ast_mutex_unlock(&chan_lock);
 
        ast_mutex_unlock(&chan_lock);
-       return 0; 
+       return 0;
 }
 
 static void send_digit_to_chan(struct ast_channel * ast, char digit )
 {
 }
 
 static void send_digit_to_chan(struct ast_channel * ast, char digit )
 {
-        static const char* dtmf_tones[] = {
-                "!941+1336/100,!0/100", /* 0 */
-                "!697+1209/100,!0/100", /* 1 */
-                "!697+1336/100,!0/100", /* 2 */
-                "!697+1477/100,!0/100", /* 3 */
-                "!770+1209/100,!0/100", /* 4 */
-                "!770+1336/100,!0/100", /* 5 */
-                "!770+1477/100,!0/100", /* 6 */
-                "!852+1209/100,!0/100", /* 7 */
-                "!852+1336/100,!0/100", /* 8 */
-                "!852+1477/100,!0/100", /* 9 */
-                "!697+1633/100,!0/100", /* A */
-                "!770+1633/100,!0/100", /* B */
-                "!852+1633/100,!0/100", /* C */
-                "!941+1633/100,!0/100", /* D */
-                "!941+1209/100,!0/100", /* * */
-                "!941+1477/100,!0/100" };       /* # */
-
-        if (digit >= '0' && digit <='9')
-                ast_playtones_start(ast,0,dtmf_tones[digit-'0'], 0);
-        else if (digit >= 'A' && digit <= 'D')
-                ast_playtones_start(ast,0,dtmf_tones[digit-'A'+10], 0);
-        else if (digit == '*')
-                ast_playtones_start(ast,0,dtmf_tones[14], 0);
-        else if (digit == '#')
-                ast_playtones_start(ast,0,dtmf_tones[15], 0);
-        else {
-                /* not handled */
-                ast_log(LOG_DEBUG, "Unable to handle DTMF tone "
-                       "'%c' for '%s'\n", digit, ast->name);
-        }
+       static const char* dtmf_tones[] = {
+               "!941+1336/100,!0/100", /* 0 */
+               "!697+1209/100,!0/100", /* 1 */
+               "!697+1336/100,!0/100", /* 2 */
+               "!697+1477/100,!0/100", /* 3 */
+               "!770+1209/100,!0/100", /* 4 */
+               "!770+1336/100,!0/100", /* 5 */
+               "!770+1477/100,!0/100", /* 6 */
+               "!852+1209/100,!0/100", /* 7 */
+               "!852+1336/100,!0/100", /* 8 */
+               "!852+1477/100,!0/100", /* 9 */
+               "!697+1633/100,!0/100", /* A */
+               "!770+1633/100,!0/100", /* B */
+               "!852+1633/100,!0/100", /* C */
+               "!941+1633/100,!0/100", /* D */
+               "!941+1209/100,!0/100", /* * */
+               "!941+1477/100,!0/100" };       /* # */
+
+       if (digit >= '0' && digit <='9')
+               ast_playtones_start(ast,0,dtmf_tones[digit-'0'], 0);
+       else if (digit >= 'A' && digit <= 'D')
+               ast_playtones_start(ast,0,dtmf_tones[digit-'A'+10], 0);
+       else if (digit == '*')
+               ast_playtones_start(ast,0,dtmf_tones[14], 0);
+       else if (digit == '#')
+               ast_playtones_start(ast,0,dtmf_tones[15], 0);
+       else {
+#if ASTERISK_VERSION_NUM < 110000
+               CDEBUG(NULL, ast, "Unable to handle DTMF tone '%c' for '%s'\n", digit, ast->name);
+#else
+               CDEBUG(NULL, ast, "Unable to handle DTMF tone '%c' for '%s'\n", digit, ast_channel_name(ast));
+#endif
+       }
 }
 
 #ifdef LCR_FOR_ASTERISK
 }
 
 #ifdef LCR_FOR_ASTERISK
@@ -1909,7 +2520,7 @@ static int lcr_digit_begin(struct ast_channel *ast, char digit)
 static int lcr_digit(struct ast_channel *ast, char digit)
 #endif
 {
 static int lcr_digit(struct ast_channel *ast, char digit)
 #endif
 {
-        struct chan_call *call;
+       struct chan_call *call;
        union parameter newparam;
        char buf[]="x";
 
        union parameter newparam;
        char buf[]="x";
 
@@ -1922,7 +2533,11 @@ static int lcr_digit(struct ast_channel *ast, char digit)
                return 0;
 
        ast_mutex_lock(&chan_lock);
                return 0;
 
        ast_mutex_lock(&chan_lock);
-        call = ast->tech_pvt;
+#if ASTERISK_VERSION_NUM < 110000
+       call = ast->tech_pvt;
+#else
+       call = ast_channel_tech_pvt(ast);
+#endif
        if (!call) {
                CERROR(NULL, ast, "Received digit from Asterisk, but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
        if (!call) {
                CERROR(NULL, ast, "Received digit from Asterisk, but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
@@ -1932,17 +2547,20 @@ static int lcr_digit(struct ast_channel *ast, char digit)
        CDEBUG(call, ast, "Received digit '%c' from Asterisk.\n", digit);
 
        /* send information or queue them */
        CDEBUG(call, ast, "Received digit '%c' from Asterisk.\n", digit);
 
        /* send information or queue them */
-       if (call->ref && call->state == CHAN_LCR_STATE_OUT_DIALING)
-       {
+       if (call->ref && call->state == CHAN_LCR_STATE_OUT_DIALING) {
                CDEBUG(call, ast, "Sending digit to LCR, because we are in dialing state.\n");
                memset(&newparam, 0, sizeof(union parameter));
                CDEBUG(call, ast, "Sending digit to LCR, because we are in dialing state.\n");
                memset(&newparam, 0, sizeof(union parameter));
-               newparam.information.id[0] = digit;
-               newparam.information.id[1] = '\0';
+               if (call->keypad) {
+                       newparam.information.keypad[0] = digit;
+                       newparam.information.keypad[1] = '\0';
+               } else {
+                       newparam.information.id[0] = digit;
+                       newparam.information.id[1] = '\0';
+               }
                send_message(MESSAGE_INFORMATION, call->ref, &newparam);
        } else
        if (!call->ref
                send_message(MESSAGE_INFORMATION, call->ref, &newparam);
        } else
        if (!call->ref
-        && (call->state == CHAN_LCR_STATE_OUT_PREPARE || call->state == CHAN_LCR_STATE_OUT_SETUP))
-       {
+        && (call->state == CHAN_LCR_STATE_OUT_PREPARE || call->state == CHAN_LCR_STATE_OUT_SETUP)) {
                CDEBUG(call, ast, "Queue digits, because we are in setup/dialing state and have no ref yet.\n");
                *buf = digit;
                strncat(call->dialque, buf, strlen(call->dialque)-1);
                CDEBUG(call, ast, "Queue digits, because we are in setup/dialing state and have no ref yet.\n");
                *buf = digit;
                strncat(call->dialque, buf, strlen(call->dialque)-1);
@@ -1951,23 +2569,27 @@ static int lcr_digit(struct ast_channel *ast, char digit)
        ast_mutex_unlock(&chan_lock);
 
 #ifdef LCR_FOR_ASTERISK
        ast_mutex_unlock(&chan_lock);
 
 #ifdef LCR_FOR_ASTERISK
-       return(0);
+       return 0;
 }
 
 static int lcr_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
 {
        int inband_dtmf = 0;
 }
 
 static int lcr_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
 {
        int inband_dtmf = 0;
-        struct chan_call *call;
+       struct chan_call *call;
 #endif
 
        ast_mutex_lock(&chan_lock);
 
 #endif
 
        ast_mutex_lock(&chan_lock);
 
-        call = ast->tech_pvt;
+#if ASTERISK_VERSION_NUM < 110000
+       call = ast->tech_pvt;
+#else
+       call = ast_channel_tech_pvt(ast);
+#endif
 
        if (!call) {
 
        if (!call) {
-               CERROR(NULL, ast, 
-                      "Received digit from Asterisk, "
-                      "but no call instance exists.\n");
+               CERROR(NULL, ast,
+                       "Received digit from Asterisk, "
+                       "but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
                return -1;
        }
                ast_mutex_unlock(&chan_lock);
                return -1;
        }
@@ -1985,24 +2607,28 @@ static int lcr_digit_end(struct ast_channel *ast, char digit, unsigned int durat
                send_digit_to_chan(ast, digit);
        }
 
                send_digit_to_chan(ast, digit);
        }
 
-       return (0);
+       return 0;
 }
 
 static int lcr_answer(struct ast_channel *ast)
 {
        union parameter newparam;
 }
 
 static int lcr_answer(struct ast_channel *ast)
 {
        union parameter newparam;
-        struct chan_call *call;
+       struct chan_call *call;
 
        ast_mutex_lock(&chan_lock);
 
        ast_mutex_lock(&chan_lock);
-        call = ast->tech_pvt;
+#if ASTERISK_VERSION_NUM < 110000
+       call = ast->tech_pvt;
+#else
+       call = ast_channel_tech_pvt(ast);
+#endif
        if (!call) {
                CERROR(NULL, ast, "Received answer from Asterisk, but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
                return -1;
        }
        if (!call) {
                CERROR(NULL, ast, "Received answer from Asterisk, but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
                return -1;
        }
-       
+
        CDEBUG(call, ast, "Received answer from Asterisk (maybe during lcr_bridge).\n");
        CDEBUG(call, ast, "Received answer from Asterisk (maybe during lcr_bridge).\n");
-               
+
        /* copy connectinfo, if bridged */
        if (call->bridge_call)
                memcpy(&call->connectinfo, &call->bridge_call->connectinfo, sizeof(struct connect_info));
        /* copy connectinfo, if bridged */
        if (call->bridge_call)
                memcpy(&call->connectinfo, &call->bridge_call->connectinfo, sizeof(struct connect_info));
@@ -2014,38 +2640,32 @@ static int lcr_answer(struct ast_channel *ast)
                call->state = CHAN_LCR_STATE_CONNECT;
        }
        /* change state */
                call->state = CHAN_LCR_STATE_CONNECT;
        }
        /* change state */
-       /* request bchannel */
-       if (!call->bchannel) {
-               CDEBUG(call, ast, "Requesting B-channel.\n");
-               memset(&newparam, 0, sizeof(union parameter));
-               newparam.bchannel.type = BCHANNEL_REQUEST;
-               send_message(MESSAGE_BCHANNEL, call->ref, &newparam);
-       }
        /* enable keypad */
 //     memset(&newparam, 0, sizeof(union parameter));
 //     send_message(MESSAGE_ENABLEKEYPAD, call->ref, &newparam);
        /* enable keypad */
 //     memset(&newparam, 0, sizeof(union parameter));
 //     send_message(MESSAGE_ENABLEKEYPAD, call->ref, &newparam);
-       /* enable dtmf */
-       if (call->no_dtmf)
-               CDEBUG(call, ast, "DTMF is disabled by option.\n");
-       else
-               call->dtmf = 1;
-       
-       ast_mutex_unlock(&chan_lock);
-        return 0;
+
+       ast_mutex_unlock(&chan_lock);
+       return 0;
 }
 
 static int lcr_hangup(struct ast_channel *ast)
 {
 }
 
 static int lcr_hangup(struct ast_channel *ast)
 {
-        struct chan_call *call;
+       struct chan_call *call;
        pthread_t tid = pthread_self();
 
        pthread_t tid = pthread_self();
 
-       if (!pthread_equal(tid, chan_tid))
+       if (!pthread_equal(tid, chan_tid)) {
                ast_mutex_lock(&chan_lock);
                ast_mutex_lock(&chan_lock);
-        call = ast->tech_pvt;
+       }
+#if ASTERISK_VERSION_NUM < 110000
+       call = ast->tech_pvt;
+#else
+       call = ast_channel_tech_pvt(ast);
+#endif
        if (!call) {
                CERROR(NULL, ast, "Received hangup from Asterisk, but no call instance exists.\n");
        if (!call) {
                CERROR(NULL, ast, "Received hangup from Asterisk, but no call instance exists.\n");
-               if (!pthread_equal(tid, chan_tid))
+               if (!pthread_equal(tid, chan_tid)) {
                        ast_mutex_unlock(&chan_lock);
                        ast_mutex_unlock(&chan_lock);
+               }
                return -1;
        }
 
                return -1;
        }
 
@@ -2055,71 +2675,155 @@ static int lcr_hangup(struct ast_channel *ast)
                CDEBUG(call, ast, "Received hangup from LCR thread.\n");
 
        /* disconnect asterisk, maybe not required */
                CDEBUG(call, ast, "Received hangup from LCR thread.\n");
 
        /* disconnect asterisk, maybe not required */
+#if ASTERISK_VERSION_NUM < 110000
        ast->tech_pvt = NULL;
        ast->fds[0] = -1;
        ast->tech_pvt = NULL;
        ast->fds[0] = -1;
-       if (call->ref)
-       {
+#else
+       ast_channel_tech_pvt_set(ast, NULL);
+       ast_channel_set_fd(ast, 0, -1);
+#endif
+       if (call->ref) {
                /* release */
                CDEBUG(call, ast, "Releasing ref and freeing call instance.\n");
                /* release */
                CDEBUG(call, ast, "Releasing ref and freeing call instance.\n");
+#if ASTERISK_VERSION_NUM < 110000
                if (ast->hangupcause > 0)
                if (ast->hangupcause > 0)
-                       send_release_and_import(call, ast->hangupcause, LOCATION_PRIVATE_LOCAL);
+                       send_release(call, ast->hangupcause, LOCATION_PRIVATE_LOCAL);
+#else
+               if (ast_channel_hangupcause(ast) > 0)
+                       send_release(call, ast_channel_hangupcause(ast), LOCATION_PRIVATE_LOCAL);
+#endif
                else
                else
-                       send_release_and_import(call, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL);
+                       send_release(call, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL);
                /* remove call */
                free_call(call);
                /* remove call */
                free_call(call);
-               if (!pthread_equal(tid, chan_tid))
+               if (!pthread_equal(tid, chan_tid)) {
                        ast_mutex_unlock(&chan_lock);
                        ast_mutex_unlock(&chan_lock);
+               }
                return 0;
                return 0;
-       } else
-       {
+       } else {
                /* ref is not set, due to prepare setup or release */
                /* ref is not set, due to prepare setup or release */
-               if (call->state == CHAN_LCR_STATE_RELEASE)
-               {
+               if (call->state == CHAN_LCR_STATE_RELEASE) {
                        /* we get the response to our release */
                        CDEBUG(call, ast, "Freeing call instance, because we have no ref AND we are requesting no ref.\n");
                        free_call(call);
                        /* we get the response to our release */
                        CDEBUG(call, ast, "Freeing call instance, because we have no ref AND we are requesting no ref.\n");
                        free_call(call);
-               } else
-               {
+               } else {
                        /* during prepare, we change to release state */
                        CDEBUG(call, ast, "We must wait until we received our ref, until we can free call instance.\n");
                        call->state = CHAN_LCR_STATE_RELEASE;
                        call->ast = NULL;
                }
                        /* during prepare, we change to release state */
                        CDEBUG(call, ast, "We must wait until we received our ref, until we can free call instance.\n");
                        call->state = CHAN_LCR_STATE_RELEASE;
                        call->ast = NULL;
                }
-       } 
-       if (!pthread_equal(tid, chan_tid))
+       }
+       if (!pthread_equal(tid, chan_tid)) {
                ast_mutex_unlock(&chan_lock);
                ast_mutex_unlock(&chan_lock);
+       }
        return 0;
 }
 
        return 0;
 }
 
-static int lcr_write(struct ast_channel *ast, struct ast_frame *f)
+static int lcr_write(struct ast_channel *ast, struct ast_frame *fr)
 {
 {
-        struct chan_call *call;
-
+       union parameter newparam;
+       struct chan_call *call;
+       struct ast_frame * f = fr;
+       unsigned char *p, *q;
+       int len, l;
+
+#if ASTERISK_VERSION_NUM < 100000
+#ifdef AST_1_8_OR_HIGHER
+       if (!f->subclass.codec)
+#else
        if (!f->subclass)
        if (!f->subclass)
+#endif
                CDEBUG(NULL, ast, "No subclass\n");
                CDEBUG(NULL, ast, "No subclass\n");
-       if (!(f->subclass & ast->nativeformats))
-               CDEBUG(NULL, ast, "Unexpected format.\n");
-       
+#endif
+#ifdef AST_1_8_OR_HIGHER
+#if ASTERISK_VERSION_NUM < 100000
+#if ASTERISK_VERSION_NUM < 110000
+       if (!(f->subclass.codec & ast->nativeformats)) {
+#else
+       if (!(f->subclass.codec & ast_channel_nativeformats(ast))) {
+#endif
+#else
+#if ASTERISK_VERSION_NUM < 110000
+       if (!ast_format_cap_iscompatible(ast->nativeformats, &f->subclass.format)) {
+#else
+       if (!ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &f->subclass.format)) {
+#endif
+#endif
+#else
+#if ASTERISK_VERSION_NUM < 110000
+       if (!(f->subclass & ast->nativeformats)) {
+#else
+       if (!(f->subclass & ast_channel_nativeformats(ast))) {
+#endif
+#endif
+               CDEBUG(NULL, ast,
+                              "Unexpected format. "
+                      "Activating emergency conversion...\n");
+
+#ifdef AST_1_8_OR_HIGHER
+#if ASTERISK_VERSION_NUM < 100000
+               ast_set_write_format(ast, f->subclass.codec);
+#else
+               ast_set_write_format(ast, &f->subclass.format);
+#endif
+#else
+               ast_set_write_format(ast, f->subclass);
+#endif
+#if ASTERISK_VERSION_NUM < 110000
+               f = (ast->writetrans) ? ast_translate(
+                       ast->writetrans, fr, 0) : fr;
+#else
+               f = (ast_channel_writetrans(ast)) ? ast_translate(
+                       ast_channel_writetrans(ast), fr, 0) : fr;
+#endif
+       }
+
        ast_mutex_lock(&chan_lock);
        ast_mutex_lock(&chan_lock);
-        call = ast->tech_pvt;
-       if (!call) {
+#if ASTERISK_VERSION_NUM < 110000
+       call = ast->tech_pvt;
+#else
+       call = ast_channel_tech_pvt(ast);
+#endif
+       if (!call || !call->ref) {
+               /* drop the frame, if no ref exists, but return successfull delivery, or asterisk will abort connection */
                ast_mutex_unlock(&chan_lock);
                ast_mutex_unlock(&chan_lock);
-               return -1;
+               if (f != fr) {
+                       ast_frfree(f);
+               }
+               return 0;
+       }
+       len = f->samples;
+       p = *((unsigned char **)&(f->data));
+       q = newparam.traffic.data;
+       memset(&newparam, 0, sizeof(union parameter));
+       while (len) {
+               l = (len > sizeof(newparam.traffic.data)) ? sizeof(newparam.traffic.data) : len;
+               newparam.traffic.len = l;
+               len -= l;
+               for (; l; l--)
+                       *q++ = flip_bits[*p++];
+               send_message(MESSAGE_TRAFFIC, call->ref, &newparam);
        }
        }
-       if (call->bchannel && f->samples)
-               bchannel_transmit(call->bchannel, (unsigned char *)f->data, f->samples);
        ast_mutex_unlock(&chan_lock);
        ast_mutex_unlock(&chan_lock);
+       if (f != fr) {
+               ast_frfree(f);
+       }
        return 0;
 }
 
 
 static struct ast_frame *lcr_read(struct ast_channel *ast)
 {
        return 0;
 }
 
 
 static struct ast_frame *lcr_read(struct ast_channel *ast)
 {
-        struct chan_call *call;
-       int len;
+       struct chan_call *call;
+       int len = 0;
+       struct ast_frame *f = NULL;
 
        ast_mutex_lock(&chan_lock);
 
        ast_mutex_lock(&chan_lock);
-        call = ast->tech_pvt;
+#if ASTERISK_VERSION_NUM < 110000
+       call = ast->tech_pvt;
+#else
+       call = ast_channel_tech_pvt(ast);
+#endif
        if (!call) {
                ast_mutex_unlock(&chan_lock);
                return NULL;
        if (!call) {
                ast_mutex_unlock(&chan_lock);
                return NULL;
@@ -2140,15 +2844,16 @@ static struct ast_frame *lcr_read(struct ast_channel *ast)
                        #ifdef LCR_FOR_ASTERISK
                        return &ast_null_frame;
                        #endif
                        #ifdef LCR_FOR_ASTERISK
                        return &ast_null_frame;
                        #endif
-                       
+
                        #ifdef LCR_FOR_CALLWEAVER
                        return &nullframe;
                        #endif
                        #ifdef LCR_FOR_CALLWEAVER
                        return &nullframe;
                        #endif
-                       
+
                }
                if (len <= 0) {
                        close(call->pipe[0]);
                        call->pipe[0] = -1;
                }
                if (len <= 0) {
                        close(call->pipe[0]);
                        call->pipe[0] = -1;
+                       global_change = 1;
                        ast_mutex_unlock(&chan_lock);
                        return NULL;
                } else if (call->rebuffer && call->framepos < 160) {
                        ast_mutex_unlock(&chan_lock);
                        return NULL;
                } else if (call->rebuffer && call->framepos < 160) {
@@ -2159,7 +2864,28 @@ static struct ast_frame *lcr_read(struct ast_channel *ast)
        }
 
        call->read_fr.frametype = AST_FRAME_VOICE;
        }
 
        call->read_fr.frametype = AST_FRAME_VOICE;
+#ifdef AST_1_8_OR_HIGHER
+#if ASTERISK_VERSION_NUM < 100000
+#if ASTERISK_VERSION_NUM < 110000
+       call->read_fr.subclass.codec = ast->nativeformats;
+#else
+       call->read_fr.subclass.codec = ast_channel_nativeformats(ast);
+#endif
+#else
+#if ASTERISK_VERSION_NUM < 110000
+       ast_best_codec(ast->nativeformats, &call->read_fr.subclass.format);
+#else
+       ast_best_codec(ast_channel_nativeformats(ast), &call->read_fr.subclass.format);
+#endif
+       call->read_fr.subclass.integer = call->read_fr.subclass.format.id;
+#endif
+#else
+#if ASTERISK_VERSION_NUM < 110000
        call->read_fr.subclass = ast->nativeformats;
        call->read_fr.subclass = ast->nativeformats;
+#else
+       call->read_fr.subclass = ast_channel_nativeformats(ast);
+#endif
+#endif
        if (call->rebuffer) {
                call->read_fr.datalen = call->framepos;
                call->read_fr.samples = call->framepos;
        if (call->rebuffer) {
                call->read_fr.datalen = call->framepos;
                call->read_fr.samples = call->framepos;
@@ -2170,27 +2896,45 @@ static struct ast_frame *lcr_read(struct ast_channel *ast)
        }
        call->read_fr.delivery = ast_tv(0,0);
        *((unsigned char **)&(call->read_fr.data)) = call->read_buff;
        }
        call->read_fr.delivery = ast_tv(0,0);
        *((unsigned char **)&(call->read_fr.data)) = call->read_buff;
+
+       if (call->dsp)
+               f = ast_dsp_process(ast, call->dsp, &call->read_fr);
+       if (f && f->frametype == AST_FRAME_DTMF)
+#ifdef AST_1_8_OR_HIGHER
+               CDEBUG(call, ast, "Asterisk detected inband DTMF: %c.\n", f->subclass.integer);
+#else
+               CDEBUG(call, ast, "Asterisk detected inband DTMF: %c.\n", f->subclass);
+#endif
+
        ast_mutex_unlock(&chan_lock);
 
        ast_mutex_unlock(&chan_lock);
 
+       if (f && f->frametype == AST_FRAME_DTMF)
+               return f;
+
        return &call->read_fr;
 }
 
 static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, size_t datalen)
 {
        union parameter newparam;
        return &call->read_fr;
 }
 
 static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, size_t datalen)
 {
        union parameter newparam;
-        int res = 0;
-        struct chan_call *call;
+       int res = 0;
+       struct chan_call *call;
+       const struct ast_tone_zone_sound *ts = NULL;
 
        ast_mutex_lock(&chan_lock);
 
        ast_mutex_lock(&chan_lock);
-        call = ast->tech_pvt;
+#if ASTERISK_VERSION_NUM < 110000
+       call = ast->tech_pvt;
+#else
+       call = ast_channel_tech_pvt(ast);
+#endif
        if (!call) {
                CERROR(NULL, ast, "Received indicate from Asterisk, but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
                return -1;
        }
 
        if (!call) {
                CERROR(NULL, ast, "Received indicate from Asterisk, but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
                return -1;
        }
 
-        switch (cond) {
-                case AST_CONTROL_BUSY:
+       switch (cond) {
+               case AST_CONTROL_BUSY:
                        CDEBUG(call, ast, "Received indicate AST_CONTROL_BUSY from Asterisk.\n");
                        ast_setstate(ast, AST_STATE_BUSY);
                        if (call->state != CHAN_LCR_STATE_OUT_DISCONNECT) {
                        CDEBUG(call, ast, "Received indicate AST_CONTROL_BUSY from Asterisk.\n");
                        ast_setstate(ast, AST_STATE_BUSY);
                        if (call->state != CHAN_LCR_STATE_OUT_DISCONNECT) {
@@ -2201,21 +2945,43 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz
                                send_message(MESSAGE_DISCONNECT, call->ref, &newparam);
                                /* change state */
                                call->state = CHAN_LCR_STATE_OUT_DISCONNECT;
                                send_message(MESSAGE_DISCONNECT, call->ref, &newparam);
                                /* change state */
                                call->state = CHAN_LCR_STATE_OUT_DISCONNECT;
+                       } else {
+                               CDEBUG(call, ast, "Using Asterisk 'busy' indication\n");
+#if ASTERISK_VERSION_NUM < 110000
+                               ts = ast_get_indication_tone(ast->zone, "busy");
+#else
+                               ts = ast_get_indication_tone(ast_channel_zone(ast), "busy");
+#endif
                        }
                        break;
                        }
                        break;
-                case AST_CONTROL_CONGESTION:
+               case AST_CONTROL_CONGESTION:
+#if ASTERISK_VERSION_NUM < 110000
                        CDEBUG(call, ast, "Received indicate AST_CONTROL_CONGESTION from Asterisk. (cause %d)\n", ast->hangupcause);
                        CDEBUG(call, ast, "Received indicate AST_CONTROL_CONGESTION from Asterisk. (cause %d)\n", ast->hangupcause);
+#else
+                       CDEBUG(call, ast, "Received indicate AST_CONTROL_CONGESTION from Asterisk. (cause %d)\n", ast_channel_hangupcause(ast));
+#endif
                        if (call->state != CHAN_LCR_STATE_OUT_DISCONNECT) {
                                /* send message to lcr */
                                memset(&newparam, 0, sizeof(union parameter));
                        if (call->state != CHAN_LCR_STATE_OUT_DISCONNECT) {
                                /* send message to lcr */
                                memset(&newparam, 0, sizeof(union parameter));
+#if ASTERISK_VERSION_NUM < 110000
                                newparam.disconnectinfo.cause = ast->hangupcause;
                                newparam.disconnectinfo.cause = ast->hangupcause;
+#else
+                               newparam.disconnectinfo.cause = ast_channel_hangupcause(ast);
+#endif
                                newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                                send_message(MESSAGE_DISCONNECT, call->ref, &newparam);
                                /* change state */
                                call->state = CHAN_LCR_STATE_OUT_DISCONNECT;
                                newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                                send_message(MESSAGE_DISCONNECT, call->ref, &newparam);
                                /* change state */
                                call->state = CHAN_LCR_STATE_OUT_DISCONNECT;
+                       } else {
+                               CDEBUG(call, ast, "Using Asterisk 'congestion' indication\n");
+#if ASTERISK_VERSION_NUM < 110000
+                               ts = ast_get_indication_tone(ast->zone, "congestion");
+#else
+                               ts = ast_get_indication_tone(ast_channel_zone(ast), "congestion");
+#endif
                        }
                        break;
                        }
                        break;
-                case AST_CONTROL_PROCEEDING:
+               case AST_CONTROL_PROCEEDING:
                        CDEBUG(call, ast, "Received indicate AST_CONTROL_PROCEEDING from Asterisk.\n");
                        if (call->state == CHAN_LCR_STATE_IN_SETUP
                         || call->state == CHAN_LCR_STATE_IN_DIALING) {
                        CDEBUG(call, ast, "Received indicate AST_CONTROL_PROCEEDING from Asterisk.\n");
                        if (call->state == CHAN_LCR_STATE_IN_SETUP
                         || call->state == CHAN_LCR_STATE_IN_DIALING) {
@@ -2226,9 +2992,9 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz
                                call->state = CHAN_LCR_STATE_IN_PROCEEDING;
                        }
                        break;
                                call->state = CHAN_LCR_STATE_IN_PROCEEDING;
                        }
                        break;
-                case AST_CONTROL_RINGING:
+               case AST_CONTROL_RINGING:
                        CDEBUG(call, ast, "Received indicate AST_CONTROL_RINGING from Asterisk.\n");
                        CDEBUG(call, ast, "Received indicate AST_CONTROL_RINGING from Asterisk.\n");
-                       ast_setstate(ast, AST_STATE_RINGING);
+                       ast_setstate(ast, AST_STATE_RING);
                        if (call->state == CHAN_LCR_STATE_IN_SETUP
                         || call->state == CHAN_LCR_STATE_IN_DIALING
                         || call->state == CHAN_LCR_STATE_IN_PROCEEDING) {
                        if (call->state == CHAN_LCR_STATE_IN_SETUP
                         || call->state == CHAN_LCR_STATE_IN_DIALING
                         || call->state == CHAN_LCR_STATE_IN_PROCEEDING) {
@@ -2237,36 +3003,64 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz
                                send_message(MESSAGE_ALERTING, call->ref, &newparam);
                                /* change state */
                                call->state = CHAN_LCR_STATE_IN_ALERTING;
                                send_message(MESSAGE_ALERTING, call->ref, &newparam);
                                /* change state */
                                call->state = CHAN_LCR_STATE_IN_ALERTING;
+                       } else {
+                               CDEBUG(call, ast, "Using Asterisk 'ring' indication\n");
+#if ASTERISK_VERSION_NUM < 110000
+                               ts = ast_get_indication_tone(ast->zone, "ring");
+#else
+                               ts = ast_get_indication_tone(ast_channel_zone(ast), "ring");
+#endif
                        }
                        break;
                        }
                        break;
-                case -1:
+               case AST_CONTROL_PROGRESS:
+                       CDEBUG(call, ast, "Received indicate AST_CONTROL_PROGRESS from Asterisk.\n");
+                       if (call->state == CHAN_LCR_STATE_IN_SETUP
+                        || call->state == CHAN_LCR_STATE_IN_DIALING) {
+                               CDEBUG(call, ast, "Changing to proceeding state, because no more dialing possible.\n");
+                               /* send message to lcr */
+                               memset(&newparam, 0, sizeof(union parameter));
+                               send_message(MESSAGE_PROCEEDING, call->ref, &newparam);
+                               /* change state */
+                               call->state = CHAN_LCR_STATE_IN_PROCEEDING;
+                       }
+                       /* request bchannel */
+                       CDEBUG(call, ast, "Requesting audio path.\n");
+                       memset(&newparam, 0, sizeof(union parameter));
+                       send_message(MESSAGE_AUDIOPATH, call->ref, &newparam);
+                       break;
+               case -1:
                        CDEBUG(call, ast, "Received indicate -1.\n");
                        CDEBUG(call, ast, "Received indicate -1.\n");
-                        res = -1;
+                       ast_playtones_stop(ast);
+                       res = -1;
                        break;
 
                        break;
 
-                case AST_CONTROL_VIDUPDATE:
+               case AST_CONTROL_VIDUPDATE:
                        CDEBUG(call, ast, "Received indicate AST_CONTROL_VIDUPDATE.\n");
                        CDEBUG(call, ast, "Received indicate AST_CONTROL_VIDUPDATE.\n");
-                        res = -1;
-                        break;
-                case AST_CONTROL_HOLD:
+                       res = -1;
+                       break;
+               case AST_CONTROL_HOLD:
                        CDEBUG(call, ast, "Received indicate AST_CONTROL_HOLD from Asterisk.\n");
                        /* send message to lcr */
                        memset(&newparam, 0, sizeof(union parameter));
                        newparam.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD;
                        send_message(MESSAGE_NOTIFY, call->ref, &newparam);
                        CDEBUG(call, ast, "Received indicate AST_CONTROL_HOLD from Asterisk.\n");
                        /* send message to lcr */
                        memset(&newparam, 0, sizeof(union parameter));
                        newparam.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD;
                        send_message(MESSAGE_NOTIFY, call->ref, &newparam);
-                       
+
                        /*start music onhold*/
                        #ifdef LCR_FOR_ASTERISK
                        /*start music onhold*/
                        #ifdef LCR_FOR_ASTERISK
+                       #if ASTERISK_VERSION_NUM <110000
                        ast_moh_start(ast,data,ast->musicclass);
                        ast_moh_start(ast,data,ast->musicclass);
+                       #else
+                       ast_moh_start(ast,data,ast_channel_musicclass(ast));
                        #endif
                        #endif
-                       
+                       #endif
+
                        #ifdef LCR_FOR_CALLWEAVER
                        ast_moh_start(ast, NULL);
                        #endif
                        #ifdef LCR_FOR_CALLWEAVER
                        ast_moh_start(ast, NULL);
                        #endif
-                       
+
                        call->on_hold = 1;
                        call->on_hold = 1;
-                        break;
-                case AST_CONTROL_UNHOLD:
+                       break;
+               case AST_CONTROL_UNHOLD:
                        CDEBUG(call, ast, "Received indicate AST_CONTROL_UNHOLD from Asterisk.\n");
                        /* send message to lcr */
                        memset(&newparam, 0, sizeof(union parameter));
                        CDEBUG(call, ast, "Received indicate AST_CONTROL_UNHOLD from Asterisk.\n");
                        /* send message to lcr */
                        memset(&newparam, 0, sizeof(union parameter));
@@ -2274,23 +3068,29 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz
                        send_message(MESSAGE_NOTIFY, call->ref, &newparam);
 
                        /*stop moh*/
                        send_message(MESSAGE_NOTIFY, call->ref, &newparam);
 
                        /*stop moh*/
-                       ast_moh_stop(ast);
+                       ast_moh_stop(ast);
                        call->on_hold = 0;
                        call->on_hold = 0;
-                       break;
+                       break;
 #ifdef AST_CONTROL_SRCUPDATE
 #ifdef AST_CONTROL_SRCUPDATE
-               case AST_CONTROL_SRCUPDATE:
-                       CDEBUG(call, ast, "Received AST_CONTROL_SRCUPDATE from Asterisk.\n");
-                        break;
+               case AST_CONTROL_SRCUPDATE:
+#else
+               case 20:
 #endif
 #endif
-                default:
+                       CDEBUG(call, ast, "Received AST_CONTROL_SRCUPDATE from Asterisk.\n");
+                       break;
+               default:
                        CERROR(call, ast, "Received indicate from Asterisk with unknown condition %d.\n", cond);
                        CERROR(call, ast, "Received indicate from Asterisk with unknown condition %d.\n", cond);
-                        res = -1;
+                       res = -1;
                        break;
                        break;
-        }
+       }
+
+       if (ts && ts->data[0]) {
+               ast_playtones_start(ast, 0, ts->data, 1);
+       }
 
        /* return */
        ast_mutex_unlock(&chan_lock);
 
        /* return */
        ast_mutex_unlock(&chan_lock);
-        return res;
+       return res;
 }
 
 /*
 }
 
 /*
@@ -2298,14 +3098,18 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz
  */
 static int lcr_fixup(struct ast_channel *oldast, struct ast_channel *ast)
 {
  */
 static int lcr_fixup(struct ast_channel *oldast, struct ast_channel *ast)
 {
-        struct chan_call *call;
+       struct chan_call *call;
 
        if (!ast) {
                return -1;
        }
 
        ast_mutex_lock(&chan_lock);
 
        if (!ast) {
                return -1;
        }
 
        ast_mutex_lock(&chan_lock);
+#if ASTERISK_VERSION_NUM < 110000
        call = ast->tech_pvt;
        call = ast->tech_pvt;
+#else
+       call = ast_channel_tech_pvt(ast);
+#endif
        if (!call) {
                CERROR(NULL, ast, "Received fixup from Asterisk, but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
        if (!call) {
                CERROR(NULL, ast, "Received fixup from Asterisk, but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
@@ -2323,11 +3127,15 @@ static int lcr_fixup(struct ast_channel *oldast, struct ast_channel *ast)
  */
 static int lcr_send_text(struct ast_channel *ast, const char *text)
 {
  */
 static int lcr_send_text(struct ast_channel *ast, const char *text)
 {
-        struct chan_call *call;
+       struct chan_call *call;
        union parameter newparam;
 
        ast_mutex_lock(&chan_lock);
        union parameter newparam;
 
        ast_mutex_lock(&chan_lock);
+#if ASTERISK_VERSION_NUM < 110000
        call = ast->tech_pvt;
        call = ast->tech_pvt;
+#else
+       call = ast_channel_tech_pvt(ast);
+#endif
        if (!call) {
                CERROR(NULL, ast, "Received send_text from Asterisk, but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
        if (!call) {
                CERROR(NULL, ast, "Received send_text from Asterisk, but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
@@ -2338,7 +3146,7 @@ static int lcr_send_text(struct ast_channel *ast, const char *text)
        memset(&newparam, 0, sizeof(union parameter));
        strncpy(newparam.notifyinfo.display, text, sizeof(newparam.notifyinfo.display)-1);
        send_message(MESSAGE_NOTIFY, call->ref, &newparam);
        memset(&newparam, 0, sizeof(union parameter));
        strncpy(newparam.notifyinfo.display, text, sizeof(newparam.notifyinfo.display)-1);
        send_message(MESSAGE_NOTIFY, call->ref, &newparam);
-       ast_mutex_lock(&chan_lock);
+       ast_mutex_unlock(&chan_lock);
        return 0;
 }
 
        return 0;
 }
 
@@ -2357,6 +3165,9 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
        struct ast_frame        *f;
        int                     bridge_id;
 
        struct ast_frame        *f;
        int                     bridge_id;
 
+/* bridge is disabled, because there is currerntly no concept to bridge mISDN channels */
+return AST_BRIDGE_FAILED;
+
        CDEBUG(NULL, NULL, "Received bridging request from Asterisk.\n");
 
        carr[0] = ast1;
        CDEBUG(NULL, NULL, "Received bridging request from Asterisk.\n");
 
        carr[0] = ast1;
@@ -2364,35 +3175,33 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
 
        /* join via dsp (if the channels are currently open) */
        ast_mutex_lock(&chan_lock);
 
        /* join via dsp (if the channels are currently open) */
        ast_mutex_lock(&chan_lock);
+#if ASTERISK_VERSION_NUM < 110000
        call1 = ast1->tech_pvt;
        call2 = ast2->tech_pvt;
        call1 = ast1->tech_pvt;
        call2 = ast2->tech_pvt;
+#else
+       call1 = ast_channel_tech_pvt(ast1);
+       call2 = ast_channel_tech_pvt(ast2);
+#endif
        if (!call1 || !call2) {
                CDEBUG(NULL, NULL, "Bridge, but we don't have two call instances, exitting.\n");
                ast_mutex_unlock(&chan_lock);
                return AST_BRIDGE_COMPLETE;
        }
 
        if (!call1 || !call2) {
                CDEBUG(NULL, NULL, "Bridge, but we don't have two call instances, exitting.\n");
                ast_mutex_unlock(&chan_lock);
                return AST_BRIDGE_COMPLETE;
        }
 
-       /* join, if both call instances uses dsp 
+       /* join, if both call instances uses dsp
           ignore the case of fax detection here it may be benificial for ISDN fax machines or pass through.
           ignore the case of fax detection here it may be benificial for ISDN fax machines or pass through.
-       */
-       if (!call1->nodsp && !call2->nodsp) {
-               CDEBUG(NULL, NULL, "Both calls use DSP, bridging via DSP.\n");
-
-               /* get bridge id and join */
-               bridge_id = new_bridge_id();
-               
-               call1->bridge_id = bridge_id;
-               if (call1->bchannel)
-                       bchannel_join(call1->bchannel, bridge_id);
-
-               call2->bridge_id = bridge_id;
-               if (call2->bchannel)
-                       bchannel_join(call2->bchannel, bridge_id);
-       } else
-       if (call1->nodsp && call2->nodsp)
-               CDEBUG(NULL, NULL, "Both calls use no DSP, bridging in channel driver.\n");
-       else
-               CDEBUG(NULL, NULL, "One call uses no DSP, bridging in channel driver.\n");
+       */
+       CDEBUG(NULL, NULL, "Both calls use DSP, bridging via DSP.\n");
+
+       /* get bridge id and join */
+       bridge_id = new_bridge_id();
+
+       call1->bridge_id = bridge_id;
+       call2->bridge_id = bridge_id;
+       // FIXME: do bridiging
+       // bchannel_join(call1->bchannel, bridge_id);
+       // bchannel_join(call2->bchannel, bridge_id);
+
        call1->bridge_call = call2;
        call2->bridge_call = call1;
 
        call1->bridge_call = call2;
        call2->bridge_call = call1;
 
@@ -2434,9 +3243,9 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
 
                call2->on_hold = 0;
        }
 
                call2->on_hold = 0;
        }
-       
+
        ast_mutex_unlock(&chan_lock);
        ast_mutex_unlock(&chan_lock);
-       
+
        while(1) {
                to = -1;
                who = ast_waitfor_n(carr, 2, &to);
        while(1) {
                to = -1;
                who = ast_waitfor_n(carr, 2, &to);
@@ -2446,7 +3255,7 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
                        break;
                }
                f = ast_read(who);
                        break;
                }
                f = ast_read(who);
-    
+
                if (!f || f->frametype == AST_FRAME_CONTROL) {
                        if (!f)
                                CDEBUG(NULL, NULL, "Got hangup.\n");
                if (!f || f->frametype == AST_FRAME_CONTROL) {
                        if (!f)
                                CDEBUG(NULL, NULL, "Got hangup.\n");
@@ -2457,14 +3266,14 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
                        *rc=who;
                        break;
                }
                        *rc=who;
                        break;
                }
-               
+
                if ( f->frametype == AST_FRAME_DTMF ) {
                        CDEBUG(NULL, NULL, "Got DTMF.\n");
                        *fo=f;
                        *rc=who;
                        break;
                }
                if ( f->frametype == AST_FRAME_DTMF ) {
                        CDEBUG(NULL, NULL, "Got DTMF.\n");
                        *fo=f;
                        *rc=who;
                        break;
                }
-       
+
 
                if (who == ast1) {
                        ast_write(ast2,f);
 
                if (who == ast1) {
                        ast_write(ast2,f);
@@ -2472,28 +3281,27 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
                else {
                        ast_write(ast1,f);
                }
                else {
                        ast_write(ast1,f);
                }
-    
+
        }
        }
-       
+
        CDEBUG(NULL, NULL, "Releasing bridge.\n");
 
        /* split channels */
        ast_mutex_lock(&chan_lock);
        CDEBUG(NULL, NULL, "Releasing bridge.\n");
 
        /* split channels */
        ast_mutex_lock(&chan_lock);
+#if ASTERISK_VERSION_NUM < 110000
        call1 = ast1->tech_pvt;
        call2 = ast2->tech_pvt;
        call1 = ast1->tech_pvt;
        call2 = ast2->tech_pvt;
-       if (call1 && call1->bridge_id)
-       {
+#else
+       call1 = ast_channel_tech_pvt(ast1);
+       call2 = ast_channel_tech_pvt(ast2);
+#endif
+       if (call1 && call1->bridge_id) {
                call1->bridge_id = 0;
                call1->bridge_id = 0;
-               if (call1->bchannel)
-                       bchannel_join(call1->bchannel, 0);
                if (call1->bridge_call)
                        call1->bridge_call->bridge_call = NULL;
        }
                if (call1->bridge_call)
                        call1->bridge_call->bridge_call = NULL;
        }
-       if (call2 && call1->bridge_id)
-       {
+       if (call2 && call1->bridge_id) {
                call2->bridge_id = 0;
                call2->bridge_id = 0;
-               if (call2->bchannel)
-                       bchannel_join(call2->bchannel, 0);
                if (call2->bridge_call)
                        call2->bridge_call->bridge_call = NULL;
        }
                if (call2->bridge_call)
                        call2->bridge_call->bridge_call = NULL;
        }
@@ -2504,9 +3312,11 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
        return AST_BRIDGE_COMPLETE;
 }
 static struct ast_channel_tech lcr_tech = {
        return AST_BRIDGE_COMPLETE;
 }
 static struct ast_channel_tech lcr_tech = {
-       .type="LCR",
+       .type= lcr_type,
        .description = "Channel driver for connecting to Linux-Call-Router",
        .description = "Channel driver for connecting to Linux-Call-Router",
+       #if ASTERISK_VERSION_NUM < 100000
        .capabilities = AST_FORMAT_ALAW,
        .capabilities = AST_FORMAT_ALAW,
+       #endif
        .requester = lcr_request,
 
        #ifdef LCR_FOR_ASTERISK
        .requester = lcr_request,
 
        #ifdef LCR_FOR_ASTERISK
@@ -2519,7 +3329,7 @@ static struct ast_channel_tech lcr_tech = {
        #endif
 
        .call = lcr_call,
        #endif
 
        .call = lcr_call,
-       .bridge = lcr_bridge, 
+       .bridge = lcr_bridge,
        .hangup = lcr_hangup,
        .answer = lcr_answer,
        .read = lcr_read,
        .hangup = lcr_hangup,
        .answer = lcr_answer,
        .read = lcr_read,
@@ -2622,8 +3432,12 @@ static struct ast_cli_entry cli_port_unload =
 
 
 #ifdef LCR_FOR_ASTERISK
 
 
 #ifdef LCR_FOR_ASTERISK
+#ifdef AST_1_8_OR_HIGHER
+static int lcr_config_exec(struct ast_channel *ast, const char *data)
+#else
 static int lcr_config_exec(struct ast_channel *ast, void *data)
 #endif
 static int lcr_config_exec(struct ast_channel *ast, void *data)
 #endif
+#endif
 
 #ifdef LCR_FOR_CALLWEAVER
 static int lcr_config_exec(struct ast_channel *ast, void *data, char **argv)
 
 #ifdef LCR_FOR_CALLWEAVER
 static int lcr_config_exec(struct ast_channel *ast, void *data, char **argv)
@@ -2636,11 +3450,11 @@ static int lcr_config_exec(struct ast_channel *ast, void *data, char **argv)
        #ifdef LCR_FOR_ASTERISK
        CDEBUG(NULL, ast, "Received lcr_config (data=%s)\n", (char *)data);
        #endif
        #ifdef LCR_FOR_ASTERISK
        CDEBUG(NULL, ast, "Received lcr_config (data=%s)\n", (char *)data);
        #endif
-       
+
        #ifdef LCR_FOR_CALLWEAVER
        CDEBUG(NULL, ast, "Received lcr_config (data=%s)\n", argv[0]);
        #endif
        #ifdef LCR_FOR_CALLWEAVER
        CDEBUG(NULL, ast, "Received lcr_config (data=%s)\n", argv[0]);
        #endif
-       
+
        /* find channel */
        call = call_first;
        while(call) {
        /* find channel */
        call = call_first;
        while(call) {
@@ -2649,15 +3463,23 @@ static int lcr_config_exec(struct ast_channel *ast, void *data, char **argv)
                call = call->next;
        }
        if (call)
                call = call->next;
        }
        if (call)
-               
+
                #ifdef LCR_FOR_ASTERISK
                apply_opt(call, (char *)data);
                #ifdef LCR_FOR_ASTERISK
                apply_opt(call, (char *)data);
-               #endif          
-               
-               #ifdef LCR_FOR_CALLWEAVER               
+               #endif
+
+               #ifdef LCR_FOR_CALLWEAVER
                apply_opt(call, (char *)argv[0]);
                #endif
 
                apply_opt(call, (char *)argv[0]);
                #endif
 
+               /* send options */
+               if (call->tx_queue) {
+                       union parameter newparam;
+
+                       memset(&newparam, 0, sizeof(union parameter));
+                       newparam.queue = call->tx_queue * 8;
+                       send_message(MESSAGE_DISABLE_DEJITTER, call->ref, &newparam);
+               }
        else
                CERROR(NULL, ast, "lcr_config app not called by chan_lcr channel.\n");
 
        else
                CERROR(NULL, ast, "lcr_config app not called by chan_lcr channel.\n");
 
@@ -2671,92 +3493,95 @@ static int lcr_config_exec(struct ast_channel *ast, void *data, char **argv)
 int load_module(void)
 {
        u_short i;
 int load_module(void)
 {
        u_short i;
+       char options_error[256];
 
        for (i = 0; i < 256; i++) {
                flip_bits[i] = (i>>7) | ((i>>5)&2) | ((i>>3)&4) | ((i>>1)&8)
                             | (i<<7) | ((i&2)<<5) | ((i&4)<<3) | ((i&8)<<1);
        }
 
 
        for (i = 0; i < 256; i++) {
                flip_bits[i] = (i>>7) | ((i>>5)&2) | ((i>>3)&4) | ((i>>1)&8)
                             | (i<<7) | ((i&2)<<5) | ((i&4)<<3) | ((i&8)<<1);
        }
 
-       if (read_options() == 0) {
+       if (read_options(options_error) == 0) {
                CERROR(NULL, NULL, "%s", options_error);
 
                #ifdef LCR_FOR_ASTERISK
                return AST_MODULE_LOAD_DECLINE;
                CERROR(NULL, NULL, "%s", options_error);
 
                #ifdef LCR_FOR_ASTERISK
                return AST_MODULE_LOAD_DECLINE;
-               #endif          
-               
+               #endif
+
                #ifdef LCR_FOR_CALLWEAVER
                return 0;
                #endif
                #ifdef LCR_FOR_CALLWEAVER
                return 0;
                #endif
-                       
+
        }
 
        ast_mutex_init(&chan_lock);
        ast_mutex_init(&log_lock);
 
        }
 
        ast_mutex_init(&chan_lock);
        ast_mutex_init(&log_lock);
 
-       if (open_socket() < 0) {
-               /* continue with closed socket */
-       }
-
-       if (bchannel_initialize()) {
-               CERROR(NULL, NULL, "Unable to open mISDN device\n");
-               close_socket();
-               
-               #ifdef LCR_FOR_ASTERISK
+       #if ASTERISK_VERSION_NUM < 100000
+       lcr_tech.capabilities = (options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW;
+       #else
+       struct ast_format tmp;
+       ast_format_set(&tmp ,(options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW , 0);
+       if (!(lcr_tech.capabilities = ast_format_cap_alloc())) {
                return AST_MODULE_LOAD_DECLINE;
                return AST_MODULE_LOAD_DECLINE;
-               #endif          
-               
-               #ifdef LCR_FOR_CALLWEAVER
-               return 0;
-               #endif
        }
        }
-       mISDN_created = 1;
-
-       lcr_tech.capabilities = (options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW;
+       ast_format_cap_add(lcr_tech.capabilities, &tmp);
+       #endif
        if (ast_channel_register(&lcr_tech)) {
                CERROR(NULL, NULL, "Unable to register channel class\n");
        if (ast_channel_register(&lcr_tech)) {
                CERROR(NULL, NULL, "Unable to register channel class\n");
-               bchannel_deinitialize();
                close_socket();
 
                #ifdef LCR_FOR_ASTERISK
                return AST_MODULE_LOAD_DECLINE;
                close_socket();
 
                #ifdef LCR_FOR_ASTERISK
                return AST_MODULE_LOAD_DECLINE;
-               #endif          
-               
+               #endif
+
                #ifdef LCR_FOR_CALLWEAVER
                return 0;
                #endif
        }
 
        ast_register_application("lcr_config", lcr_config_exec, "lcr_config",
                #ifdef LCR_FOR_CALLWEAVER
                return 0;
                #endif
        }
 
        ast_register_application("lcr_config", lcr_config_exec, "lcr_config",
-                               
+
                                 #ifdef LCR_FOR_ASTERISK
                                 "lcr_config(<opt><optarg>:<opt>:...)\n"
                                 #endif
                                 #ifdef LCR_FOR_ASTERISK
                                 "lcr_config(<opt><optarg>:<opt>:...)\n"
                                 #endif
-                                
+
                                 #ifdef LCR_FOR_CALLWEAVER
                                 #ifdef LCR_FOR_CALLWEAVER
-                                "lcr_config(<opt><optarg>:<opt>:...)\n",                                
+                                "lcr_config(<opt><optarg>:<opt>:...)\n",
                                 #endif
                                 #endif
-                                                        
+
                                 "Sets LCR opts. and optargs\n"
                                 "\n"
                                 "The available options are:\n"
                                 "    d - Send display text on called phone, text is the optarg.\n"
                                 "Sets LCR opts. and optargs\n"
                                 "\n"
                                 "The available options are:\n"
                                 "    d - Send display text on called phone, text is the optarg.\n"
-                                "    n - Don't detect dtmf tones on called channel.\n"
-                                "    h - Force data call (HDLC).\n" 
-                                "    t - Disable mISDN_dsp features (required for fax application).\n"
-                                "    f - Adding fax detection. It it timeouts, mISDN_dsp is used.\n"
-                                "        Use time to detect for optarg.\n"
+                                "    D - Forward detected dtmf tones from LCR.\n"
+                                "    h - Force data call (HDLC).\n"
+                                "    q - Add queue to make fax stream seamless (required for fax app).\n"
+                                "        Use queue size in miliseconds for optarg. (try 250)\n"
+                                "    a - Adding DTMF detection.\n"
+                                "    f - Adding fax detection.\n"
+#if 0
                                 "    c - Make crypted outgoing call, optarg is keyindex.\n"
                                 "    e - Perform echo cancelation on this channel.\n"
                                 "    c - Make crypted outgoing call, optarg is keyindex.\n"
                                 "    e - Perform echo cancelation on this channel.\n"
+#endif
                                 "        Takes mISDN pipeline option as optarg.\n"
                                 "        Takes mISDN pipeline option as optarg.\n"
-                                "    s - Send Non Inband DTMF as inband.\n"
+                                "    s - Send Non Inband DTMF as inband. (disables LCR's DTMF)\n"
                                 "    r - re-buffer packets (160 bytes). Required for some SIP-phones and fax applications.\n"
                                 "    r - re-buffer packets (160 bytes). Required for some SIP-phones and fax applications.\n"
+#if 0
                                 "   vr - rxgain control\n"
                                 "   vt - txgain control\n"
                                 "   vr - rxgain control\n"
                                 "   vt - txgain control\n"
+#endif
                                 "        Volume changes at factor 2 ^ optarg.\n"
                                 "        Volume changes at factor 2 ^ optarg.\n"
+                                "    k - use keypad to dial this call.\n"
+                                "\n"
+                                "set LCR_TRANSFERCAPABILITY to the numerical bearer capabilty in order to alter caller's capability\n"
+                                " -> use 16 for fax (3.1k audio)\n"
+                                "\n"
+                                "To send a fax, you need to set LCR_TRANSFERCAPABILITY environment to 16, also you need to set\n"
+                                "options: \"n:t:q250\" for seamless audio transmission.\n"
                );
 
                );
 
-#if 0  
+
+#if 0
        ast_cli_register(&cli_show_lcr);
        ast_cli_register(&cli_show_calls);
        ast_cli_register(&cli_reload_routing);
        ast_cli_register(&cli_show_lcr);
        ast_cli_register(&cli_show_calls);
        ast_cli_register(&cli_reload_routing);
@@ -2766,22 +3591,19 @@ int load_module(void)
        ast_cli_register(&cli_port_unload);
 #endif
 
        ast_cli_register(&cli_port_unload);
 #endif
 
-       quit = 0;       
-       if ((pthread_create(&chan_tid, NULL, chan_thread, NULL)<0))
-       {
+       if ((pthread_create(&chan_tid, NULL, chan_thread, NULL)<0)) {
                /* failed to create thread */
                /* failed to create thread */
-               bchannel_deinitialize();
                close_socket();
                ast_channel_unregister(&lcr_tech);
 
                #ifdef LCR_FOR_ASTERISK
                return AST_MODULE_LOAD_DECLINE;
                close_socket();
                ast_channel_unregister(&lcr_tech);
 
                #ifdef LCR_FOR_ASTERISK
                return AST_MODULE_LOAD_DECLINE;
-               #endif          
-               
+               #endif
+
                #ifdef LCR_FOR_CALLWEAVER
                return 0;
                #endif
                #ifdef LCR_FOR_CALLWEAVER
                return 0;
                #endif
-               
+
        }
        return 0;
 }
        }
        return 0;
 }
@@ -2789,26 +3611,32 @@ int load_module(void)
 int unload_module(void)
 {
        /* First, take us out of the channel loop */
 int unload_module(void)
 {
        /* First, take us out of the channel loop */
-       CDEBUG(NULL, NULL, "-- Unregistering mISDN Channel Driver --\n");
+       CDEBUG(NULL, NULL, "-- Unregistering Linux-Call-Router Channel Driver --\n");
 
 
-       quit = 1;
-       pthread_join(chan_tid, NULL);   
-       
-       ast_channel_unregister(&lcr_tech);
+       pthread_cancel(chan_tid);
+
+       close_socket();
 
 
-        ast_unregister_application("lcr_config");
+       del_timer(&socket_retry);
 
 
+       unregister_fd(&wake_fd);
+       close(wake_pipe[0]);
+       close(wake_pipe[1]);
 
 
-       if (mISDN_created) {
-               bchannel_deinitialize();
-               mISDN_created = 0;
-       }
+//     ast_mutex_unlock(&chan_lock);
+
+       ast_channel_unregister(&lcr_tech);
+
+       ast_unregister_application("lcr_config");
 
        if (lcr_sock >= 0) {
                close(lcr_sock);
                lcr_sock = -1;
        }
 
 
        if (lcr_sock >= 0) {
                close(lcr_sock);
                lcr_sock = -1;
        }
 
+#if ASTERISK_VERSION_NUM >= 100000
+       lcr_tech.capabilities = ast_format_cap_destroy(lcr_tech.capabilities);
+#endif
        return 0;
 }
 
        return 0;
 }
 
@@ -2824,6 +3652,7 @@ int reload_module(void)
 
 #ifdef LCR_FOR_CALLWEAVER
 int usecount(void)
 
 #ifdef LCR_FOR_CALLWEAVER
 int usecount(void)
+hae
 {
        int res;
        ast_mutex_lock(&usecnt_lock);
 {
        int res;
        ast_mutex_lock(&usecnt_lock);