free_call(*callp);
return(NULL);
}
+ fcntl((*callp)->pipe[0], F_SETFL, O_NONBLOCK);
CDEBUG(*callp, NULL, "Call instance allocated.\n");
return(*callp);
}
break;
case 't':
if (opt[1] != '\0') {
- CERROR(call, call->ast, "Option 't' (transparent) expects no parameter.\n", opt);
+ CERROR(call, call->ast, "Option 't' (no_dsp) expects no parameter.\n", opt);
break;
}
- CDEBUG(call, call->ast, "Option 't' (transparent).\n");
- if (!call->transparent) {
- call->transparent = 1;
+ CDEBUG(call, call->ast, "Option 't' (no dsp).\n");
+ if (!call->nodsp) {
+ call->nodsp = 1;
newmode = 1;
}
break;
bchannel_pipeline(call->bchannel, call->pipeline);
break;
case 'r':
- if (opt[1] == '\0') {
+ if (opt[1] != '\0') {
CERROR(call, call->ast, "Option 'r' (re-buffer 160 bytes) expects no parameter.\n", opt);
break;
}
/* re-open, if bchannel is created */
if (call->bchannel && call->bchannel->b_sock > -1) {
bchannel_destroy(call->bchannel);
- if (bchannel_create(call->bchannel, ((call->transparent)?1:0) + ((call->hdlc)?2:0)))
+ if (bchannel_create(call->bchannel, ((call->nodsp)?1:0) + ((call->hdlc)?2:0)))
bchannel_activate(call->bchannel, 1);
}
}
newparam.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
}
newparam.setup.capainfo.bearer_capa = ast->transfercapability;
- newparam.setup.capainfo.bearer_info1 = (options.law=='a')?3:2;
newparam.setup.capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
+ if (call->hdlc)
+ newparam.setup.capainfo.source_mode = B_MODE_HDLC;
+ else {
+ newparam.setup.capainfo.source_mode = B_MODE_TRANSPARENT;
+ newparam.setup.capainfo.bearer_info1 = (options.law=='a')?3:2;
+ }
newparam.setup.capainfo.hlc = INFO_HLC_NONE;
newparam.setup.capainfo.exthlc = INFO_HLC_NONE;
send_message(MESSAGE_SETUP, call->ref, &newparam);
goto release;
}
call->pbx_started = 1;
- return;
+// if (call->state == CHAN_LCR_STATE_IN_DIALING)
+ ast_setstate(ast, AST_STATE_RINGING);
+// else
+// ast_setstate(ast, AST_STATE_RINGING);
+// return;
}
/*
}
ast->transfercapability = param->setup.capainfo.bearer_capa;
/* enable hdlc if transcap is data */
- if (ast->transfercapability == INFO_BC_DATAUNRESTRICTED
- || ast->transfercapability == INFO_BC_DATARESTRICTED
- || ast->transfercapability == INFO_BC_VIDEO)
+ 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);
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])
strncat(call->queue_string, param->information.id, sizeof(call->queue_string)-1);
bchannel_join(bchannel, call->bridge_id);
}
/* create only, if call exists, othewhise it bchannel is freed below... */
- if (bchannel_create(bchannel, ((call->transparent)?1:0) + ((call->hdlc)?2:0)))
+ if (bchannel_create(bchannel, ((call->nodsp)?1:0) + ((call->hdlc)?2:0)))
bchannel_activate(bchannel, 1);
}
/* acknowledge */
CDEBUG(call, ast, "Sending queued digit '%c' to Asterisk.\n", *p);
/* send digit to asterisk */
memset(&fr, 0, sizeof(fr));
- fr.frametype = AST_FRAME_DTMF;
+ fr.frametype = AST_FRAME_DTMF_BEGIN;
fr.subclass = *p;
fr.delivery = ast_tv(0, 0);
- fr.len = 100;
+ ast_queue_frame(ast, &fr);
+ fr.frametype = AST_FRAME_DTMF_END;
ast_queue_frame(ast, &fr);
break;
default:
return -1;
}
- CDEBUG(call, ast, "Received answer from Asterisk.\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));
/* send connect message to lcr */
- memset(&newparam, 0, sizeof(union parameter));
- memcpy(&newparam.connectinfo, &call->connectinfo, sizeof(struct connect_info));
- send_message(MESSAGE_CONNECT, call->ref, &newparam);
+ if (call->state != CHAN_LCR_STATE_CONNECT) {
+ memset(&newparam, 0, sizeof(union parameter));
+ memcpy(&newparam.connectinfo, &call->connectinfo, sizeof(struct connect_info));
+ send_message(MESSAGE_CONNECT, call->ref, &newparam);
+ call->state = CHAN_LCR_STATE_CONNECT;
+ }
/* change state */
- call->state = CHAN_LCR_STATE_CONNECT;
/* request bchannel */
if (!call->bchannel) {
CDEBUG(call, ast, "Requesting B-channel.\n");
if (ast->hangupcause > 0)
send_release_and_import(call, ast->hangupcause, LOCATION_PRIVATE_LOCAL);
else
- send_release_and_import(call, CAUSE_RESSOURCEUNAVAIL, LOCATION_PRIVATE_LOCAL);
+ send_release_and_import(call, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL);
/* remove call */
free_call(call);
if (!pthread_equal(tid, chan_tid))
static struct ast_frame *lcr_read(struct ast_channel *ast)
{
struct chan_call *call;
- int i, len;
- unsigned char *p;
+ int len;
ast_mutex_lock(&chan_lock);
call = ast->tech_pvt;
return NULL;
}
if (call->pipe[0] > -1) {
- len = read(call->pipe[0], call->read_buff, sizeof(call->read_buff));
+ if (call->rebuffer && !call->hdlc) {
+ len = read(call->pipe[0], call->read_buff, 160);
+ } else {
+ len = read(call->pipe[0], call->read_buff, sizeof(call->read_buff));
+ }
+ if (len < 0 && errno == EAGAIN) {
+ ast_mutex_unlock(&chan_lock);
+ return &ast_null_frame;
+ }
if (len <= 0) {
close(call->pipe[0]);
call->pipe[0] = -1;
+ ast_mutex_unlock(&chan_lock);
return NULL;
}
}
- p = call->read_buff;
- for (i = 0; i < len; i++) {
- *p = flip_bits[*p];
- p++;
- }
-
call->read_fr.frametype = AST_FRAME_VOICE;
call->read_fr.subclass = ast->nativeformats;
call->read_fr.datalen = len;
carr[0] = ast1;
carr[1] = ast2;
-
+
/* join via dsp (if the channels are currently open) */
ast_mutex_lock(&chan_lock);
- bridge_id = new_bridge_id();
call1 = ast1->tech_pvt;
call2 = ast2->tech_pvt;
- if (call1 && call2)
- {
+ 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 */
+ if (!call1->nodsp && !call2->nodsp) {
+ CDEBUG(NULL, NULL, "Both calls use DSP, briding 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);
- call1->bridge_call = call2;
- }
- if (call2)
- {
+
call2->bridge_id = bridge_id;
if (call2->bchannel)
bchannel_join(call2->bchannel, bridge_id);
- call2->bridge_call = call1;
+ } else
+ if (call1->nodsp && call2->nodsp)
+ CDEBUG(NULL, NULL, "Both calls use no DSP, briding in channel driver.\n");
+ else
+ CDEBUG(NULL, NULL, "One call uses no DSP, briding in channel driver.\n");
+ call1->bridge_call = call2;
+ call2->bridge_call = call1;
+
+ if (call1->state == CHAN_LCR_STATE_IN_SETUP
+ || call1->state == CHAN_LCR_STATE_IN_DIALING
+ || call1->state == CHAN_LCR_STATE_IN_PROCEEDING
+ || call1->state == CHAN_LCR_STATE_IN_ALERTING) {
+ CDEBUG(call1, ast1, "Bridge established before lcr_answer, so we call it ourself: Calling lcr_answer...\n");
+ lcr_answer(ast1);
+ }
+ if (call2->state == CHAN_LCR_STATE_IN_SETUP
+ || call2->state == CHAN_LCR_STATE_IN_DIALING
+ || call2->state == CHAN_LCR_STATE_IN_PROCEEDING
+ || call2->state == CHAN_LCR_STATE_IN_ALERTING) {
+ CDEBUG(call2, ast2, "Bridge established before lcr_answer, so we call it ourself: Calling lcr_answer...\n");
+ lcr_answer(ast2);
}
+
ast_mutex_unlock(&chan_lock);
while(1) {
ast_mutex_lock(&chan_lock);
call1 = ast1->tech_pvt;
call2 = ast2->tech_pvt;
- if (call1)
+ if (call1 && call1->bridge_id)
{
call1->bridge_id = 0;
if (call1->bchannel)
bchannel_join(call1->bchannel, 0);
if (call1->bridge_call)
call1->bridge_call->bridge_call = NULL;
- call1->bridge_call = NULL;
}
- if (call2)
+ if (call2 && call1->bridge_id)
{
call2->bridge_id = 0;
if (call2->bchannel)
bchannel_join(call2->bchannel, 0);
if (call2->bridge_call)
call2->bridge_call->bridge_call = NULL;
- call2->bridge_call = NULL;
}
+ call1->bridge_call = NULL;
+ call2->bridge_call = NULL;
ast_mutex_unlock(&chan_lock);
return AST_BRIDGE_COMPLETE;
" 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 all audio features (required for fax application).\n"
+ " t - Disable mISDN_dsp features (required for fax application).\n"
" c - Make crypted outgoing call, optarg is keyindex.\n"
" e - Perform echo cancelation on this channel.\n"
" Takes mISDN pipeline option as optarg.\n"