Support early line-interconnect (bridge) as soon as the b-channels are up.
parent
54ca760357
commit
62dd326709
3
CHANGES
3
CHANGES
|
@ -8,6 +8,9 @@ HEAD
|
|||
signaled as subscriber-number. Here the complete prefix including area code must be added.
|
||||
- better counting of active b-channels.
|
||||
- make capicommand(progress) "early-B3" usable for non NT-mode incoming channels too.
|
||||
- support early Line-Interconnect (bridge) as soon as both b-channels are up. This bridges b-channels
|
||||
from beginning of call-establishment, even before calls are connected and the bridge command is received.
|
||||
Dial() option 'G' is used to activate this feature.
|
||||
|
||||
|
||||
chan_capi-1.1.1
|
||||
|
|
6
README
6
README
|
@ -102,6 +102,12 @@ The Dial string
|
|||
This is needed to give additional commands like CCBS after Hangup.
|
||||
To really hangup the CAPI connection, use either capicommand(hangup)
|
||||
or wait for chan_capi/network timeout (about 20 seconds).
|
||||
'G' : early Line-Interconnect / bridge: Use Line-Interconnect as soon as
|
||||
both b-channels are up. Both channels must be of type CAPI and
|
||||
the incoming call may need 'capicommand(progress)' to enable early-B3
|
||||
on it as well as dial option 'b' for the outgoing channel.
|
||||
Before Dial(), the capicommand(peerlink) must be used to signal the
|
||||
dialed channel its peer.
|
||||
|
||||
If the <interface-name> is used in dialstring, be sure the name (specified
|
||||
in capi.conf) does not start with 'contr' or 'g'.
|
||||
|
|
106
chan_capi.c
106
chan_capi.c
|
@ -893,6 +893,7 @@ static void interface_cleanup(struct capi_pvt *i)
|
|||
|
||||
i->isdnstate = 0;
|
||||
i->cause = 0;
|
||||
i->fsetting = 0;
|
||||
|
||||
i->whentohangup = 0;
|
||||
i->whentoqueuehangup = 0;
|
||||
|
@ -1061,7 +1062,7 @@ void capi_activehangup(struct capi_pvt *i, int state)
|
|||
return;
|
||||
}
|
||||
|
||||
if ((i->isdnstate & CAPI_ISDN_STATE_STAYONLINE)) {
|
||||
if ((i->fsetting & CAPI_FSETTING_STAYONLINE)) {
|
||||
/* user has requested to leave channel online for further actions
|
||||
like CCBS */
|
||||
cc_verbose(2, 1, VERBOSE_PREFIX_4 "%s: disconnect deferred, stay-online mode PLCI=%#x\n",
|
||||
|
@ -1217,9 +1218,14 @@ static int pbx_capi_call(struct ast_channel *c, char *idest, int timeout)
|
|||
use_defaultcid = 1;
|
||||
break;
|
||||
case 's': /* stay online */
|
||||
if ((i->isdnstate & CAPI_ISDN_STATE_STAYONLINE))
|
||||
if ((i->fsetting & CAPI_FSETTING_STAYONLINE))
|
||||
cc_log(LOG_WARNING, "'stay-online' already set in '%s'\n", idest);
|
||||
i->isdnstate |= CAPI_ISDN_STATE_STAYONLINE;
|
||||
i->fsetting |= CAPI_FSETTING_STAYONLINE;
|
||||
break;
|
||||
case 'G': /* early bridge */
|
||||
if ((i->fsetting & CAPI_FSETTING_EARLY_BRIDGE))
|
||||
cc_log(LOG_WARNING, "'early-bridge' already set in '%s'\n", idest);
|
||||
i->fsetting |= CAPI_FSETTING_EARLY_BRIDGE;
|
||||
break;
|
||||
case 'q': /* disable QSIG */
|
||||
cc_verbose(4, 0, VERBOSE_PREFIX_4 "%s: QSIG extensions for this call disabled\n",
|
||||
|
@ -1557,15 +1563,6 @@ static int line_interconnect(struct capi_pvt *i0, struct capi_pvt *i1, int start
|
|||
(i1->isdnstate & CAPI_ISDN_STATE_DISCONNECT))
|
||||
return -1;
|
||||
|
||||
if ((!(i0->isdnstate & CAPI_ISDN_STATE_B3_UP)) ||
|
||||
(!(i1->isdnstate & CAPI_ISDN_STATE_B3_UP))) {
|
||||
cc_verbose(3, 1, VERBOSE_PREFIX_2
|
||||
"%s:%s line interconnect aborted, at least "
|
||||
"one channel is not connected.\n",
|
||||
i0->vname, i1->vname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (start) {
|
||||
/* connect */
|
||||
capi_sendf(i1, 0, CAPI_FACILITY_REQ, i0->PLCI, get_capi_MessageNumber(),
|
||||
|
@ -1788,6 +1785,44 @@ static int pbx_capi_bridge_transfer(
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* activate / deactivate b-channel bridge
|
||||
*/
|
||||
static int capi_bridge(int start, struct capi_pvt *i0, struct capi_pvt *i1, int flags)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (start) {
|
||||
if ((i0->isdnstate & CAPI_ISDN_STATE_LI) ||
|
||||
(i1->isdnstate & CAPI_ISDN_STATE_LI)) {
|
||||
/* already in bridge */
|
||||
cc_verbose(4, 1, VERBOSE_PREFIX_3 "%s/%s: already in bridge.\n",
|
||||
i0->vname, i1->vname);
|
||||
return 0;
|
||||
}
|
||||
if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0))
|
||||
capi_detect_dtmf(i0, 0);
|
||||
|
||||
if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1))
|
||||
capi_detect_dtmf(i1, 0);
|
||||
|
||||
capi_echo_canceller(i0, EC_FUNCTION_DISABLE);
|
||||
capi_echo_canceller(i1, EC_FUNCTION_DISABLE);
|
||||
cc_verbose(4, 1, VERBOSE_PREFIX_3 "%s/%s: activating bridge.\n",
|
||||
i0->vname, i1->vname);
|
||||
ret = line_interconnect(i0, i1, 1);
|
||||
} else {
|
||||
cc_verbose(4, 1, VERBOSE_PREFIX_3 "%s/%s: deactivating bridge.\n",
|
||||
i0->vname, i1->vname);
|
||||
line_interconnect(i0, i1, 0);
|
||||
capi_detect_dtmf(i0, 1);
|
||||
capi_detect_dtmf(i1, 1);
|
||||
capi_echo_canceller(i0, EC_FUNCTION_ENABLE);
|
||||
capi_echo_canceller(i1, EC_FUNCTION_ENABLE);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* native bridging / line interconnect
|
||||
*/
|
||||
|
@ -1833,18 +1868,8 @@ static CC_BRIDGE_RETURN pbx_capi_bridge(
|
|||
capi_wait_for_b3_up(i0);
|
||||
capi_wait_for_b3_up(i1);
|
||||
|
||||
if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0))
|
||||
capi_detect_dtmf(i0, 0);
|
||||
|
||||
if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1))
|
||||
capi_detect_dtmf(i1, 0);
|
||||
|
||||
capi_echo_canceller(i0, EC_FUNCTION_DISABLE);
|
||||
capi_echo_canceller(i1, EC_FUNCTION_DISABLE);
|
||||
|
||||
if (line_interconnect(i0, i1, 1)) {
|
||||
ret = AST_BRIDGE_FAILED;
|
||||
goto return_from_bridge;
|
||||
if (capi_bridge(1, i0, i1, flags)) {
|
||||
return AST_BRIDGE_FAILED;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
|
@ -1881,18 +1906,7 @@ static CC_BRIDGE_RETURN pbx_capi_bridge(
|
|||
priority = !priority;
|
||||
}
|
||||
|
||||
line_interconnect(i0, i1, 0);
|
||||
|
||||
return_from_bridge:
|
||||
|
||||
if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0))
|
||||
capi_detect_dtmf(i0, 1);
|
||||
|
||||
if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1))
|
||||
capi_detect_dtmf(i1, 1);
|
||||
|
||||
capi_echo_canceller(i0, EC_FUNCTION_ENABLE);
|
||||
capi_echo_canceller(i1, EC_FUNCTION_ENABLE);
|
||||
capi_bridge(0, i0, i1, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -2700,7 +2714,7 @@ static void capidev_handle_info_disconnect(_cmsg *CMSG, unsigned int PLCI, unsig
|
|||
}
|
||||
capi_queue_cause_control(i, 0);
|
||||
} else {
|
||||
if ((i->isdnstate & CAPI_ISDN_STATE_STAYONLINE)) {
|
||||
if ((i->fsetting & CAPI_FSETTING_STAYONLINE)) {
|
||||
cc_verbose(3, 1, VERBOSE_PREFIX_2 "%s: stay-online hangup frame queued.\n",
|
||||
i->vname);
|
||||
i->whentoqueuehangup = time(NULL) + 1;
|
||||
|
@ -3449,6 +3463,20 @@ static void capidev_handle_connect_b3_active_indication(_cmsg *CMSG, unsigned in
|
|||
capi_detect_dtmf(i, 1);
|
||||
}
|
||||
|
||||
if (i->fsetting & CAPI_FSETTING_EARLY_BRIDGE) {
|
||||
if ((i->peer != NULL) && (i->peer->tech == &capi_tech)) {
|
||||
struct capi_pvt *i1;
|
||||
i1 = CC_CHANNEL_PVT(i->peer);
|
||||
if ((capi_controllers[i->controller]->lineinterconnect) &&
|
||||
(capi_controllers[i1->controller]->lineinterconnect) &&
|
||||
(i->bridge) && (i1->bridge)) {
|
||||
cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: activate early bridge to %s\n",
|
||||
i->vname, i1->vname);
|
||||
capi_bridge(1, i, i1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i->state == CAPI_STATE_CONNECTED) {
|
||||
capi_signal_answer(i);
|
||||
}
|
||||
|
@ -3499,7 +3527,7 @@ static void capidev_handle_disconnect_b3_indication(_cmsg *CMSG, unsigned int PL
|
|||
}
|
||||
|
||||
if ((i->state == CAPI_STATE_DISCONNECTING)) {
|
||||
if (!(i->isdnstate & CAPI_ISDN_STATE_STAYONLINE)) {
|
||||
if (!(i->fsetting & CAPI_FSETTING_STAYONLINE)) {
|
||||
/* active disconnect */
|
||||
capi_send_disconnect(PLCI, NULL);
|
||||
}
|
||||
|
@ -4567,7 +4595,7 @@ static void capi_disconnect(struct capi_pvt *i)
|
|||
{
|
||||
cc_mutex_lock(&i->lock);
|
||||
|
||||
i->isdnstate &= ~CAPI_ISDN_STATE_STAYONLINE;
|
||||
i->fsetting &= ~CAPI_FSETTING_STAYONLINE;
|
||||
if ((i->isdnstate & CAPI_ISDN_STATE_B3_UP)) {
|
||||
cc_disconnect_b3(i, 0);
|
||||
} else {
|
||||
|
|
10
chan_capi.h
10
chan_capi.h
|
@ -246,8 +246,7 @@ struct cc_capi_gains {
|
|||
#define CAPI_ISDN_STATE_EC 0x00002000
|
||||
#define CAPI_ISDN_STATE_DTMF 0x00004000
|
||||
#define CAPI_ISDN_STATE_B3_SELECT 0x00008000
|
||||
#define CAPI_ISDN_STATE_STAYONLINE 0x00010000
|
||||
#define CAPI_ISDN_STATE_ISDNPROGRESS 0x00020000
|
||||
#define CAPI_ISDN_STATE_ISDNPROGRESS 0x00010000
|
||||
#define CAPI_ISDN_STATE_3PTY 0x10000000
|
||||
#define CAPI_ISDN_STATE_PBX_DONT 0x40000000
|
||||
#define CAPI_ISDN_STATE_PBX 0x80000000
|
||||
|
@ -263,6 +262,10 @@ struct cc_capi_gains {
|
|||
#define CAPI_WAITEVENT_HOLD_IND 0x00040000
|
||||
#define CAPI_WAITEVENT_ECT_IND 0x00050000
|
||||
|
||||
/* Features and settings of current connection */
|
||||
#define CAPI_FSETTING_STAYONLINE 0x00000001
|
||||
#define CAPI_FSETTING_EARLY_BRIDGE 0x00000002
|
||||
|
||||
/* Private qsig data for capi device */
|
||||
struct cc_qsig_data {
|
||||
int calltransfer_active;
|
||||
|
@ -400,6 +403,9 @@ struct capi_pvt {
|
|||
/* Common ISDN Profile (CIP) */
|
||||
int cip;
|
||||
unsigned short transfercapability;
|
||||
|
||||
/* Features and settings of current connection */
|
||||
unsigned int fsetting;
|
||||
|
||||
/* if not null, receiving a fax */
|
||||
FILE *fFax;
|
||||
|
|
Loading…
Reference in New Issue