diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 2c7b67322d..74c76f7fab 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -953,6 +953,10 @@ static struct dahdi_chan_conf dahdi_chan_conf_default(void) .parkinglot = "", .transfertobusy = 1, + .ani_info_digits = 2, + .ani_wink_time = 1000, + .ani_timeout = 10000, + .cid_signalling = CID_SIG_BELL, .cid_start = CID_START_RING, .dahditrcallerid = 0, @@ -12839,6 +12843,9 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; + tmp->ani_info_digits = conf->chan.ani_info_digits; + tmp->ani_wink_time = conf->chan.ani_wink_time; + tmp->ani_timeout = conf->chan.ani_timeout; tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; tmp->sendcalleridafter = conf->chan.sendcalleridafter; ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params); @@ -12944,6 +12951,9 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, analog_p->channel = tmp->channel; analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay; analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch; + analog_p->ani_info_digits = conf->chan.ani_info_digits; + analog_p->ani_timeout = conf->chan.ani_timeout; + analog_p->ani_wink_time = conf->chan.ani_wink_time; analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */ analog_p->callreturn = conf->chan.callreturn; @@ -18241,6 +18251,12 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct confp->chan.polarityonanswerdelay = atoi(v->value); } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { confp->chan.answeronpolarityswitch = ast_true(v->value); + } else if (!strcasecmp(v->name, "ani_info_digits")) { + confp->chan.ani_info_digits = atoi(v->value); + } else if (!strcasecmp(v->name, "ani_wink_time")) { + confp->chan.ani_wink_time = atoi(v->value); + } else if (!strcasecmp(v->name, "ani_timeout")) { + confp->chan.ani_timeout = atoi(v->value); } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { confp->chan.hanguponpolarityswitch = ast_true(v->value); } else if (!strcasecmp(v->name, "sendcalleridafter")) { diff --git a/channels/chan_dahdi.h b/channels/chan_dahdi.h index f98ebdc309..de813f21bf 100644 --- a/channels/chan_dahdi.h +++ b/channels/chan_dahdi.h @@ -181,6 +181,22 @@ struct dahdi_pvt { * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf */ unsigned int answeronpolarityswitch:1; + /*! + * \brief INTEGER, number of ANI INFO digits on a CAMA trunk. + * older switches use 1 INFO digit, newer switches use 2 INFO digits + * \note Set from the "ani_info_digits" value read in from chan_dahdi.conf + */ + unsigned int ani_info_digits:8; + /*! + * \brief INTEGER, length of ANI failure timeout in ms. + * \note Set from the "ani_timeout" value read in from chan_dahdi.conf + */ + unsigned int ani_timeout:16; + /*! + * \brief INTEGER, length of time to wait before sending ANI wink in ms. + * \note Set from the "ani_wink_time" value read in from chan_dahdi.conf + */ + unsigned int ani_wink_time:16; /*! * \brief TRUE if busy detection is enabled. * (Listens for the beep-beep busy pattern.) diff --git a/channels/sig_analog.c b/channels/sig_analog.c index 4356e02378..5bb5649b78 100644 --- a/channels/sig_analog.c +++ b/channels/sig_analog.c @@ -1864,7 +1864,6 @@ static void *__analog_ss_thread(void *data) if (p->sig == ANALOG_SIG_E911) { analog_off_hook(p); } - res = analog_my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); } if (res < 1) { analog_dsp_reset_and_flush_digits(p); @@ -1927,21 +1926,64 @@ static void *__analog_ss_thread(void *data) goto quit; } - if (p->sig == ANALOG_SIG_FGC_CAMA) { + if (p->sig == ANALOG_SIG_FGC_CAMA || p->sig == ANALOG_SIG_FGC_CAMAMF) { + /* This if block is where we process ANI for CAMA */ + char anibuf[100]; + struct ast_party_caller *caller; + + /* cnoffset is the point at which we pull the calling number out + * of anibuf. Must be the number of ani_info_digits + 1 to account + * for the KP, which is considered a digit. */ + + /* The 1XB with ANI-B will send a full 10 digits + * or 2 digits in case of ANI failure. + * (CD-95811-01 Section II, page 10) + * 10 digit string example: *08320123# + * 2 digit string example: *2 + * KP (*) and ST (#) are considered to be digits */ - if (ast_safe_sleep(chan,1000) == -1) { + int cnoffset = p->ani_info_digits + 1; + ast_debug(1, "cnoffset: %d\n", cnoffset); + + /* This is how long to wait before the wink to start ANI spill + * Pulled from chan_dahdi.conf, default is 1000ms */ + if (ast_safe_sleep(chan,p->ani_wink_time) == -1) { ast_hangup(chan); goto quit; } analog_off_hook(p); + ast_debug(1, "Sent wink to signal ANI start\n"); analog_dsp_set_digitmode(p, ANALOG_DIGITMODE_MF); - res = analog_my_getsigstr(chan, anibuf, "#", 10000); - if ((res > 0) && (strlen(anibuf) > 2)) { - if (anibuf[strlen(anibuf) - 1] == '#') { + + /* ani_timeout is configured in chan_dahdi.conf. default is 10000ms. + * ST, STP, ST2P, ST3P can all signal transmission complete, regardless of timeout */ + res = analog_my_getsigstr(chan, anibuf, "#ABC", p->ani_timeout); + + /* so we can work with the ani buffer */ + pbx_builtin_setvar_helper(chan, "ANIBUF", anibuf); + + /* as long as we get a terminating pulse OR the length of ANI buffer is at least >=2, we can treat + * this as a complete spill for the purposes of setting anistart */ + if ((res > 0) || (strlen(anibuf) >= 2)) { + char anistart[2] = "X"; + char f[10] = {0}; + if (strchr("#ABC", anibuf[strlen(anibuf) - 1])) { + anistart[0] = anibuf[strlen(anibuf) - 1]; anibuf[strlen(anibuf) - 1] = 0; } - ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); + ast_set_callerid(chan, anibuf + cnoffset, NULL, anibuf + cnoffset); + + caller = ast_channel_caller(chan); + strncpy(f, &(anibuf[1]), MIN((int)(p->ani_info_digits), sizeof(f)-1)); + caller->ani2 = atoi(f); + + anibuf[cnoffset] = 0; + + /* so we can work with the different start pulses as used in ANI-D */ + pbx_builtin_setvar_helper(chan, "ANISTART", anistart); + /* so we can use our ANI INFO digits in our dialplan */ + pbx_builtin_setvar_helper(chan, "ANI2", anibuf + 1); } analog_dsp_set_digitmode(p, ANALOG_DIGITMODE_DTMF); } @@ -2023,7 +2065,7 @@ static void *__analog_ss_thread(void *data) ast_copy_string(exten, "911", sizeof(exten)); } } else { - ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); + ast_log(LOG_WARNING, "A KP was expected to start signaling for Feature Group C CAMA-MF, but we got something else. Received: %s on channel %d\n", exten, p->channel); } } if (p->sig == ANALOG_SIG_FEATB) { @@ -2035,7 +2077,7 @@ static void *__analog_ss_thread(void *data) s1 = strsep(&stringp, "#"); ast_copy_string(exten, exten2 + 1, sizeof(exten)); } else { - ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); + ast_log(LOG_WARNING, "A KP was expected to start signaling for Feature Group B, but we got something else. Received: %s on channel %d\n", exten, p->channel); } } if ((p->sig == ANALOG_SIG_FEATDMF) || (p->sig == ANALOG_SIG_FEATDMF_TA)) { diff --git a/channels/sig_analog.h b/channels/sig_analog.h index 3b9dcf5a92..488be3662e 100644 --- a/channels/sig_analog.h +++ b/channels/sig_analog.h @@ -277,6 +277,10 @@ struct analog_pvt { int msgstate; /* XXX: Option Variables - Set by allocator of private structure */ + unsigned int ani_info_digits:8; /* Older switches use 1 INFO digit, newer switches use 2 */ + unsigned int ani_timeout:16; /* Time in ms before we give up waiting for ANI spill */ + unsigned int ani_wink_time:16; /* Safe wait time before we wink to start ANI spill */ + unsigned int answeronpolarityswitch:1; unsigned int callreturn:1; unsigned int cancallforward:1; diff --git a/configs/samples/chan_dahdi.conf.sample b/configs/samples/chan_dahdi.conf.sample index d24c22ba18..5c1d2ee9e5 100644 --- a/configs/samples/chan_dahdi.conf.sample +++ b/configs/samples/chan_dahdi.conf.sample @@ -1098,6 +1098,24 @@ pickupgroup=1 ; The default is -1: not to set anything. ;tonezone = 0 ; 0 is US ; +; The number of ANI info digits to expect before the main ANI spill. +; Switches using ANI-B, -C, and -D will usually send 1 digit. Modern digital +; systems will send 2, following NANPA ANI II requirements. +; +;ani_info_digits=2 +; +; Time in ms to wait before asterisk sends wink to start ANI spill. Can be +; shortened if your switch supports it. +; +;ani_wink_time=1000 +; +; Time in ms to wait for each digit in the spill including the ST pulse. +; This value can affect how long it takes to recognize ANI failures that do +; not send a ST pulse. If ANI failures take too long to recognize, you can +; lower this value. +; +;ani_timeout=10000 +; ; FXO (FXS signalled) devices must have a timeout to determine if there was a ; hangup before the line was answered. This value can be tweaked to shorten ; how long it takes before DAHDI considers a non-ringing line to have hungup.