From ea234830413b864cc48dd95f84e32d36ecee9e90 Mon Sep 17 00:00:00 2001 From: MelwareDE Date: Mon, 11 Jul 2016 14:32:43 +0000 Subject: [PATCH] CAPI specs (5th edition diagrams in section A.5) say that early B3 should trigger on progress indication ("Progress tones available") and this is how chan_capi actually worked before revision 101 (2005-09-04). Q.931 (05.98) sections 5.1.2 and 5.4 also specify similar handling on lower level (they also add "Call is not end-to-end ISDN; further call progress information may be available in-band" as possible triggering indication). This patch adds 't' option to dial string that allows switching chan_capi to such mode of operation. Without this option set chan_capi works as it did previously. While we are at it also let's clean up handling of 'DISCONNECT' message received via INFO_IND - 'case 2' had unnecessary dependency on 'doB3' variable (only one value is possible by this point in code with i->outgoing being set), 'case 4' had unreachable branch and unnecessary predicates (which were always true). These changes should not cause any differences in operation. Signed-off-by: Maciej S. Szmigiero --- CHANGES | 2 ++ README | 6 +++- chan_capi.c | 86 ++++++++++++++++++++++++++++++++++------------------- chan_capi.h | 1 + 4 files changed, 63 insertions(+), 32 deletions(-) diff --git a/CHANGES b/CHANGES index cf16a94..03ceca7 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,8 @@ HEAD - refuse to reload on active channels - ast_devstate_changed() changes with new cache argument - check for bchannel information element on incoming call +- added 't' option to select in-band tones available indication as Q.931 + (thanks to Maciej S. Szmigiero ) chan_capi-1.1.6 diff --git a/README b/README index b7b11b9..1f28923 100644 --- a/README +++ b/README @@ -93,6 +93,9 @@ The Dial string The string consists of a list of characters with the following meaning: 'b' : early B3 always. 'B' : early B3 on successful calls only. + 't' : enable B3 only on in-band tones available indication as Q.931 (05/98) + recommends (without this option it will be enabled on "PROGRESS" or + "ALERTING" messages, any "Progress" indication or channel identification). 'd' : use the default caller ID that is set by defaultcid= in capi.conf 'o' : use overlap sending of number. (Useful if additional digits should be send afterwards or together @@ -371,7 +374,8 @@ you: indications) For normal PBX usage, you would use the "b" option, always Early B3. - +You can also add "t" option so B3 will be enabled only on in-band tones available +indication as Q.931 (05/98) recommends. Overlap sending (a.k.a. real dialtone) ====================================== diff --git a/chan_capi.c b/chan_capi.c index 4267d6e..897a638 100644 --- a/chan_capi.c +++ b/chan_capi.c @@ -1295,17 +1295,6 @@ void cc_start_b3(struct capi_pvt *i) } } -/* - * start early B3 - */ -static void start_early_b3(struct capi_pvt *i) -{ - if (i->doB3 != CAPI_B3_DONT) { - /* we do early B3 Connect */ - cc_start_b3(i); - } -} - /* * signal 'progress' to PBX */ @@ -1313,7 +1302,11 @@ static void send_progress(struct capi_pvt *i) { struct ast_frame fr = { AST_FRAME_CONTROL, }; - start_early_b3(i); + if (i->doB3 != CAPI_B3_DONT && + !(i->fsetting & CAPI_FSETTING_EARLYB3_ONLY_WHEN_TONES_AVAIL)) { + /* we do early B3 Connect */ + cc_start_b3(i); + } if (!(i->isdnstate & CAPI_ISDN_STATE_PROGRESS)) { i->isdnstate |= CAPI_ISDN_STATE_PROGRESS; @@ -1608,6 +1601,13 @@ static int pbx_capi_call(struct ast_channel *c, void *idest, int timeout) cc_log(LOG_WARNING, "B3 already set in '%s'\n", idest); i->doB3 = CAPI_B3_ON_SUCCESS; break; + case 't': /* enable B3 only on in-band tones available indication */ + if ((i->fsetting & CAPI_FSETTING_EARLYB3_ONLY_WHEN_TONES_AVAIL)) + cc_log(LOG_WARNING, + "B3 on in-band tones avail only already set in '%s'\n", + idest); + i->fsetting |= CAPI_FSETTING_EARLYB3_ONLY_WHEN_TONES_AVAIL; + break; case 'o': /* overlap sending of digits */ if (i->doOverlap) cc_log(LOG_WARNING, "Overlap already set in '%s'\n", idest); @@ -1649,6 +1649,18 @@ static int pbx_capi_call(struct ast_channel *c, void *idest, int timeout) return -1; } + if (((!dest) || (!dest[0])) && + i->fsetting & CAPI_FSETTING_EARLYB3_ONLY_WHEN_TONES_AVAIL) + cc_log(LOG_WARNING, + "dialtone request with B3 on in-band tones avail setting might not work on all exchanges in '%s'\n", + idest); + + if (i->doB3 == CAPI_B3_DONT && + i->fsetting & CAPI_FSETTING_EARLYB3_ONLY_WHEN_TONES_AVAIL) + cc_log(LOG_WARNING, + "B3 on in-band tones avail setting ignored when early B3 is disabled in '%s'\n", + idest); + i->peer = cc_get_peer_link_id(pbx_builtin_getvar_helper(c, "CAPIPEERLINKID")); i->outgoing = 1; @@ -3901,16 +3913,26 @@ static int search_did(struct ast_channel *c) */ static void handle_progress_indicator(_cmsg *CMSG, unsigned int PLCI, struct capi_pvt *i) { + int inband_info = 0; + if (INFO_IND_INFOELEMENT(CMSG)[0] < 2) { cc_verbose(3, 1, VERBOSE_PREFIX_4 "%s: Progress description missing\n", i->vname); return; } + if ((INFO_IND_INFOELEMENT(CMSG)[2] & 0x60) != 0x00) { + cc_verbose(3, 1, + VERBOSE_PREFIX_4 "%s: Progress description has unsupported coding\n", + i->vname); + return; + } + switch(INFO_IND_INFOELEMENT(CMSG)[2] & 0x7f) { case 0x01: cc_verbose(4, 1, VERBOSE_PREFIX_4 "%s: Not end-to-end ISDN\n", i->vname); + inband_info = 1; break; case 0x02: cc_verbose(4, 1, VERBOSE_PREFIX_4 "%s: Destination is non ISDN\n", @@ -3932,12 +3954,19 @@ static void handle_progress_indicator(_cmsg *CMSG, unsigned int PLCI, struct cap case 0x08: cc_verbose(4, 1, VERBOSE_PREFIX_4 "%s: In-band information available\n", i->vname); + inband_info = 1; break; default: cc_verbose(3, 1, VERBOSE_PREFIX_4 "%s: Unknown progress description %02x\n", i->vname, INFO_IND_INFOELEMENT(CMSG)[2]); } + + if (inband_info && i->doB3 != CAPI_B3_DONT && + i->fsetting & CAPI_FSETTING_EARLYB3_ONLY_WHEN_TONES_AVAIL) + cc_start_b3(i); + send_progress(i); + return; } @@ -4139,12 +4168,17 @@ static void capidev_handle_info_disconnect(_cmsg *CMSG, unsigned int PLCI, unsig } return; } - + + /* at this point the call is either incoming or we are always doing B3 */ + /* case 2: we are doing B3, and receive the 0x8045 after a successful call */ - if ((i->doB3 != CAPI_B3_DONT) && - (i->state == CAPI_STATE_CONNECTED) && (i->outgoing == 1)) { + if ((i->state == CAPI_STATE_CONNECTED) && (i->outgoing == 1)) { cc_verbose(4, 1, VERBOSE_PREFIX_3 "%s: Disconnect case 2\n", i->vname); + /* + * FIXME: is this right? if this is just a normal hangup of + * a successful call shouldn't it be the same as case 1? + */ capi_queue_cause_control(i, 1); return; } @@ -4165,22 +4199,11 @@ static void capidev_handle_info_disconnect(_cmsg *CMSG, unsigned int PLCI, unsig capi_queue_cause_control(i, 0); return; } - - /* case 4 (a.k.a. the italian case): B3 always. call is unsuccessful */ - if ((i->doB3 == CAPI_B3_ALWAYS) && (i->outgoing == 1)) { - cc_verbose(4, 1, VERBOSE_PREFIX_3 "%s: Disconnect case 4\n", - i->vname); - if ((i->state == CAPI_STATE_CONNECTED) && - (i->isdnstate & CAPI_ISDN_STATE_B3_UP)) { - capi_queue_cause_control(i, 1); - return; - } - /* wait for the 0x001e (PROGRESS), play audio and wait for a timeout from the network */ - return; - } - cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: Other case DISCONNECT INFO_IND\n", + + /* case 4 (a.k.a. the italian case): always doing B3 and call is unsuccessful */ + cc_verbose(4, 1, VERBOSE_PREFIX_3 "%s: Disconnect case 4\n", i->vname); - return; + /* play audio and wait for a timeout from the network */ } /* @@ -4285,7 +4308,8 @@ static void capidev_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsig case 0x0018: /* Channel Identification */ cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: info element CHANNEL IDENTIFICATION %02x\n", i->vname, INFO_IND_INFOELEMENT(CMSG)[1]); - if (i->doB3 == CAPI_B3_ON_SUCCESS) { + if (i->doB3 != CAPI_B3_DONT && + !(i->fsetting & CAPI_FSETTING_EARLYB3_ONLY_WHEN_TONES_AVAIL)) { /* try early B3 Connect */ cc_start_b3(i); } diff --git a/chan_capi.h b/chan_capi.h index 9b72e97..e1f3ccd 100644 --- a/chan_capi.h +++ b/chan_capi.h @@ -348,6 +348,7 @@ struct cc_capi_gains { /* Features and settings of current connection */ #define CAPI_FSETTING_STAYONLINE 0x00000001 #define CAPI_FSETTING_EARLY_BRIDGE 0x00000002 +#define CAPI_FSETTING_EARLYB3_ONLY_WHEN_TONES_AVAIL 0x00000004 /* Private qsig data for capi device */ struct cc_qsig_data {