+
+ 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, ¶m->connectinfo, sizeof(struct connect_info));
+ /* queue event to asterisk */
+ if (call->ast && call->pbx_started) {
+ if (!wake_global) {
+ wake_global = 1;
+ char byte = 0;
+ write(wake_pipe[1], &byte, 1);
+ }
+ strncat(call->queue_string, "N", sizeof(call->queue_string)-1);
+ }
+}
+
+/*
+ * incoming disconnect from LCR
+ */
+static void lcr_in_disconnect(struct chan_call *call, int message_type, union parameter *param)
+{
+ struct ast_channel *ast = call->ast;
+
+ CDEBUG(call, call->ast, "Incomming disconnect from LCR. (cause=%d)\n", param->disconnectinfo.cause);
+
+ /* change state */
+ call->state = CHAN_LCR_STATE_IN_DISCONNECT;
+ /* save cause */
+ call->cause = param->disconnectinfo.cause;
+ call->location = param->disconnectinfo.location;
+ /* if bridge, forward disconnect and return */
+#ifdef TODO
+ feature flag
+ 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 */
+ send_release_and_import(call, call->cause, call->location);
+ call->ref = 0;
+ /* change to release state */
+ call->state = CHAN_LCR_STATE_RELEASE;
+ /* queue release asterisk */
+ if (ast) {
+ ast->hangupcause = call->cause;
+ if (call->pbx_started) {
+ if (!wake_global) {
+ wake_global = 1;
+ char byte = 0;
+ write(wake_pipe[1], &byte, 1);
+ }
+ strcpy(call->queue_string, "H"); // overwrite other indications
+ } else {
+ ast_hangup(ast); // call will be destroyed here
+ }
+ }
+}
+
+/*
+ * incoming release from LCR
+ */
+static void lcr_in_release(struct chan_call *call, int message_type, union parameter *param)
+{
+ struct ast_channel *ast = call->ast;
+
+ CDEBUG(call, call->ast, "Incomming release from LCR, releasing ref. (cause=%d)\n", param->disconnectinfo.cause);
+
+ /* release ref */
+ call->ref = 0;
+ /* 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 we have an asterisk instance, queue hangup, else we are done */
+ if (ast) {
+ ast->hangupcause = call->cause;
+ if (call->pbx_started) {
+ if (!wake_global) {
+ wake_global = 1;
+ char byte = 0;
+ write(wake_pipe[1], &byte, 1);
+ }
+ strcpy(call->queue_string, "H");
+ } else {
+ ast_hangup(ast); // call will be destroyed here
+ }
+ } else {
+ free_call(call);
+ }
+
+}
+
+/*
+ * incoming information from LCR
+ */
+static void lcr_in_information(struct chan_call *call, int message_type, union parameter *param)
+{
+ 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 (!call->pbx_started) {
+ CDEBUG(call, call->ast, "Asterisk not started, adding digits to number.\n");
+ strncat(ast->exten, param->information.id, AST_MAX_EXTENSION-1);
+ 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);
+ }
+
+ /* queue digits */
+ if (call->state == CHAN_LCR_STATE_IN_DIALING && param->information.id[0]) {
+ if (!wake_global) {
+ wake_global = 1;
+ char byte = 0;
+ write(wake_pipe[1], &byte, 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) {
+ CDEBUG(call, call->ast, "Call is connected, bridging.\n");
+ bridge_message_if_bridged(call, message_type, param);
+ }
+}
+
+/*
+ * incoming information from LCR
+ */
+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);
+
+ /* 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 */
+ bridge_message_if_bridged(call, message_type, param);
+}
+
+/*
+ * incoming information from LCR
+ */
+static void lcr_in_facility(struct chan_call *call, int message_type, union parameter *param)
+{
+ CDEBUG(call, call->ast, "Incomming facility from LCR.\n");
+
+ if (!call->ast) return;
+
+ /* use bridge to forware message not supported by asterisk */
+ bridge_message_if_bridged(call, message_type, param);
+}
+
+/*
+ * 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 */
+ 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);
+ }
+ /* queue PROGRESS, because tones are available */
+ if (call->ast && call->pbx_started) {
+ if (!wake_global) {
+ wake_global = 1;
+ char byte = 0;
+ 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)
+{
+ struct ast_channel *ast = call->ast;
+ char digit[2];
+
+ if (!ast)
+ return;
+ if (!call->pbx_started)
+ return;
+
+ if (!call->dsp_dtmf) {
+ CDEBUG(call, call->ast, "Recognised DTMF digit '%c', but ignoring. This is fixed in later mISDN driver.\n", val);
+ return;
+ }
+
+ 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;
+ write(wake_pipe[1], &byte, 1);
+ }
+ strncat(call->queue_string, digit, sizeof(call->queue_string)-1);
+}
+
+/*
+ * message received from LCR
+ */
+int receive_message(int message_type, unsigned int ref, union parameter *param)
+{