diff --git a/UPGRADE.txt b/UPGRADE.txt index fa77d5e9b76065383ab0e3ac5091a509f9b39883..af77d85f2568b390a67137043bb9805abb73d588 100644 --- a/UPGRADE.txt +++ b/UPGRADE.txt @@ -22,6 +22,14 @@ === UPGRADE-13.txt -- Upgrade info for 12 to 13 =========================================================== +Channel Drivers: + +chan_dahdi: + - For users using the FXO port (FXS signaling) distinctive ring detection + feature, you will need to adjust the dringX count values. The count + values now only record ring end events instead of any DAHDI event. A + ring-ring-ring pattern would exceed the pattern limits and stop + Caller-ID detection. =========================================================== =========================================================== diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 72c8497f087473f1cf1121ed66c12221c24b4b8b..53899d8699b3acb65a351c06895f95a0cb66ed53 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -1301,13 +1301,21 @@ static int my_start_cid_detect(void *pvt, int cid_signalling) return 0; } +static int restore_gains(struct dahdi_pvt *p); + static int my_stop_cid_detect(void *pvt) { struct dahdi_pvt *p = pvt; int index = SUB_REAL; - if (p->cs) + + if (p->cs) { callerid_free(p->cs); + } + + /* Restore linear mode after Caller*ID processing */ dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); + restore_gains(p); + return 0; } @@ -1383,7 +1391,6 @@ static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_e } static const char *event2str(int event); -static int restore_gains(struct dahdi_pvt *p); static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata) { @@ -1396,7 +1403,7 @@ static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int int i; int res; int checkaftercid = 0; - + const char *matched_context; struct dahdi_pvt *p = pvt; struct analog_pvt *analog_p = p->sig_pvt; @@ -1406,19 +1413,15 @@ static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int checkaftercid = 1; } - /* We must have a ring by now, so, if configured, lets try to listen for - * distinctive ringing */ + /* We must have a ring by now so lets try to listen for distinctive ringing */ if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) { /* Clear the current ring data array so we don't have old data in it. */ for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++) ringdata[receivedRingT] = 0; receivedRingT = 0; - if (checkaftercid && distinctiveringaftercid) + + if (checkaftercid && distinctiveringaftercid) { ast_verb(3, "Detecting post-CID distinctive ring\n"); - /* Check to see if context is what it should be, if not set to be. */ - else if (strcmp(p->context,p->defcontext) != 0) { - ast_copy_string(p->context, p->defcontext, sizeof(p->context)); - ast_channel_context_set(chan, p->defcontext); } for (;;) { @@ -1431,22 +1434,23 @@ static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int } if (i & DAHDI_IOMUX_SIGEVENT) { res = dahdi_get_event(p->subs[idx].dfd); + ast_debug(3, "Got event %d (%s)...\n", res, event2str(res)); if (res == DAHDI_EVENT_NOALARM) { p->inalarm = 0; analog_p->inalarm = 0; - } - ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); - res = 0; - /* Let us detect distinctive ring */ - - ringdata[receivedRingT] = analog_p->ringt; + } else if (res == DAHDI_EVENT_RINGOFFHOOK) { + /* Let us detect distinctive ring */ + ringdata[receivedRingT] = analog_p->ringt; - if (analog_p->ringt < analog_p->ringt_base/2) - break; - /* Increment the ringT counter so we can match it against - values in chan_dahdi.conf for distinctive ring */ - if (++receivedRingT == RING_PATTERNS) - break; + if (analog_p->ringt < analog_p->ringt_base / 2) { + break; + } + /* Increment the ringT counter so we can match it against + values in chan_dahdi.conf for distinctive ring */ + if (++receivedRingT == RING_PATTERNS) { + break; + } + } } else if (i & DAHDI_IOMUX_READ) { res = read(p->subs[idx].dfd, buf, sizeof(buf)); if (res < 0) { @@ -1465,44 +1469,49 @@ static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int } } } - if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) { - /* this only shows up if you have n of the dring patterns filled in */ - ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]); - for (counter = 0; counter < 3; counter++) { - /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */ - distMatches = 0; - /* this only shows up if you have n of the dring patterns filled in */ - ast_verb(3, "Checking %d,%d,%d\n", - p->drings.ringnum[counter].ring[0], - p->drings.ringnum[counter].ring[1], - p->drings.ringnum[counter].ring[2]); - for (counter1 = 0; counter1 < 3; counter1++) { - ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); - if (p->drings.ringnum[counter].ring[counter1] == -1) { - ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", - ringdata[counter1]); - distMatches++; - } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && - ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { - ast_verb(3, "Ring pattern matched in range: %d to %d\n", - (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), - (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); - distMatches++; - } - } - if (distMatches == 3) { - /* The ring matches, set the context to whatever is for distinctive ring.. */ - ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context)); - ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext)); - ast_verb(3, "Distinctive Ring matched context %s\n",p->context); + /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */ + ast_verb(3, "Detected ring pattern: %d,%d,%d\n", ringdata[0], ringdata[1], ringdata[2]); + matched_context = p->defcontext; + for (counter = 0; counter < 3; counter++) { + int range = p->drings.ringnum[counter].range; + + distMatches = 0; + ast_verb(3, "Checking %d,%d,%d with +/- %d range\n", + p->drings.ringnum[counter].ring[0], + p->drings.ringnum[counter].ring[1], + p->drings.ringnum[counter].ring[2], + range); + for (counter1 = 0; counter1 < 3; counter1++) { + int ring = p->drings.ringnum[counter].ring[counter1]; + + if (ring == -1) { + ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", + ringdata[counter1]); + distMatches++; + } else if (ring - range <= ringdata[counter1] && ringdata[counter1] <= ring + range) { + ast_verb(3, "Ring pattern %d is in range: %d to %d\n", + ringdata[counter1], ring - range, ring + range); + distMatches++; + } else { + /* The current dring pattern cannot match. */ break; } } + + if (distMatches == 3) { + /* The ring matches, set the context to whatever is for distinctive ring.. */ + matched_context = S_OR(p->drings.ringContext[counter].contextData, p->defcontext); + ast_verb(3, "Matched Distinctive Ring context %s\n", matched_context); + break; + } + } + + /* Set selected distinctive ring context if not already set. */ + if (strcmp(p->context, matched_context) != 0) { + ast_copy_string(p->context, matched_context, sizeof(p->context)); + ast_channel_context_set(chan, matched_context); } - /* Restore linear mode (if appropriate) for Caller*ID processing */ - dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); - restore_gains(p); return 0; } @@ -12788,6 +12797,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, analog_p->transfer = conf->chan.transfer; analog_p->transfertobusy = conf->chan.transfertobusy; analog_p->use_callerid = tmp->use_callerid; + analog_p->usedistinctiveringdetection = tmp->usedistinctiveringdetection; analog_p->use_smdi = tmp->use_smdi; analog_p->smdi_iface = tmp->smdi_iface; analog_p->outsigmod = ANALOG_SIG_NONE; diff --git a/channels/chan_dahdi.h b/channels/chan_dahdi.h index e4a689a1abb538bb7e9ea2ac93d08fd62cda82fe..4bb5d19a229c7c06ad6a273f9d9c9cb056892976 100644 --- a/channels/chan_dahdi.h +++ b/channels/chan_dahdi.h @@ -447,7 +447,7 @@ struct dahdi_pvt { */ char description[32]; /*! - * \brief Saved context string. + * \brief Default distinctive ring context. */ char defcontext[AST_MAX_CONTEXT]; /*! \brief Extension to use in the dialplan. */ diff --git a/channels/sig_analog.c b/channels/sig_analog.c index 0c7701772e1e8453b013f41e2fe96c188674c0f8..1d44a29b9b99cae4457619b78364e8823ea0ac0f 100644 --- a/channels/sig_analog.c +++ b/channels/sig_analog.c @@ -1636,6 +1636,9 @@ static void analog_decrease_ss_count(void) static int analog_distinctive_ring(struct ast_channel *chan, struct analog_pvt *p, int idx, int *ringdata) { + if (!p->usedistinctiveringdetection) { + return 0; + } if (analog_callbacks.distinctive_ring) { return analog_callbacks.distinctive_ring(chan, p->chan_pvt, idx, ringdata); } @@ -2453,50 +2456,53 @@ static void *__analog_ss_thread(void *data) /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { - int timeout = 10000; /* Ten seconds */ - struct timeval start = ast_tvnow(); - enum analog_event ev; - namebuf[0] = 0; numbuf[0] = 0; if (!analog_start_cid_detect(p, p->cid_signalling)) { + int timeout = 10000; /* Ten seconds */ + struct timeval start = ast_tvnow(); + enum analog_event ev; int off_ms; int ms; struct timeval off_start; - while (1) { - res = analog_get_callerid(p, namebuf, numbuf, &ev, timeout - ast_tvdiff_ms(ast_tvnow(), start)); + if (!p->usedistinctiveringdetection) { + /* Disable distinctive ring timeout count */ + analog_set_ringtimeout(p, 0); + } + while ((ms = ast_remaining_ms(start, timeout))) { + res = analog_get_callerid(p, namebuf, numbuf, &ev, ms); + if (res < 0) { + ast_log(LOG_WARNING, + "CallerID returned with error on channel '%s'\n", + ast_channel_name(chan)); + break; + } if (res == 0) { break; } - - if (res == 1) { - if (ev == ANALOG_EVENT_NOALARM) { - analog_set_alarm(p, 0); - } - if (p->cid_signalling == CID_SIG_V23_JP) { - if (ev == ANALOG_EVENT_RINGBEGIN) { - analog_off_hook(p); - usleep(1); - } - } else { - ev = ANALOG_EVENT_NONE; - break; - } + if (res != 1) { + continue; } - - if (ast_tvdiff_ms(ast_tvnow(), start) > timeout) + if (ev == ANALOG_EVENT_NOALARM) { + analog_set_alarm(p, 0); + } + if (p->cid_signalling == CID_SIG_V23_JP) { + if (ev == ANALOG_EVENT_RINGBEGIN) { + analog_off_hook(p); + usleep(1); + } + } else { break; - + } } + name = namebuf; number = numbuf; - analog_stop_cid_detect(p); - if (p->cid_signalling == CID_SIG_V23_JP) { - res = analog_on_hook(p); + analog_on_hook(p); usleep(1); } @@ -2510,11 +2516,13 @@ static void *__analog_ss_thread(void *data) if (res <= 0) { ast_log(LOG_WARNING, "CID timed out waiting for ring. Exiting simple switch\n"); + analog_stop_cid_detect(p); ast_hangup(chan); goto quit; } if (!(f = ast_read(chan))) { ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); + analog_stop_cid_detect(p); ast_hangup(chan); goto quit; } @@ -2524,13 +2532,11 @@ static void *__analog_ss_thread(void *data) break; /* Got ring */ } - if (analog_distinctive_ring(chan, p, idx, NULL)) { + res = analog_distinctive_ring(chan, p, idx, NULL); + analog_stop_cid_detect(p); + if (res) { goto quit; } - - if (res < 0) { - ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", ast_channel_name(chan)); - } } else { ast_log(LOG_WARNING, "Unable to get caller ID space\n"); } @@ -2542,66 +2548,67 @@ static void *__analog_ss_thread(void *data) goto quit; } } else if (p->use_callerid && p->cid_start == ANALOG_CID_START_RING) { - int timeout = 10000; /* Ten seconds */ - struct timeval start = ast_tvnow(); - enum analog_event ev; - int curRingData[RING_PATTERNS] = { 0 }; - int receivedRingT = 0; - namebuf[0] = 0; numbuf[0] = 0; if (!analog_start_cid_detect(p, p->cid_signalling)) { - while (1) { - res = analog_get_callerid(p, namebuf, numbuf, &ev, timeout - ast_tvdiff_ms(ast_tvnow(), start)); + int timeout = 10000; /* Ten seconds */ + struct timeval start = ast_tvnow(); + enum analog_event ev; + int ring_data[RING_PATTERNS] = { 0 }; + int ring_data_idx = 0; + int ms; + if (!p->usedistinctiveringdetection) { + /* Disable distinctive ring timeout count */ + analog_set_ringtimeout(p, 0); + } + while ((ms = ast_remaining_ms(start, timeout))) { + res = analog_get_callerid(p, namebuf, numbuf, &ev, ms); + if (res < 0) { + ast_log(LOG_WARNING, + "CallerID returned with error on channel '%s'\n", + ast_channel_name(chan)); + break; + } if (res == 0) { break; } - - if (res == 1 || res == 2) { - if (ev == ANALOG_EVENT_NOALARM) { - analog_set_alarm(p, 0); - } else if (ev == ANALOG_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { - ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); - p->polarity = POLARITY_IDLE; - ast_hangup(chan); - goto quit; - } else if (ev != ANALOG_EVENT_NONE && ev != ANALOG_EVENT_RINGBEGIN && ev != ANALOG_EVENT_RINGOFFHOOK) { - break; - } - if (res != 2) { - /* Let us detect callerid when the telco uses distinctive ring */ - curRingData[receivedRingT] = p->ringt; - - if (p->ringt < p->ringt_base/2) { - break; - } - /* Increment the ringT counter so we can match it against - values in chan_dahdi.conf for distinctive ring */ - if (++receivedRingT == RING_PATTERNS) { - break; - } - } + if (res != 1) { + continue; } - - if (ast_tvdiff_ms(ast_tvnow(), start) > timeout) { - break; + if (ev == ANALOG_EVENT_NOALARM) { + analog_set_alarm(p, 0); + } else if (ev == ANALOG_EVENT_POLARITY + && p->hanguponpolarityswitch + && p->polarity == POLARITY_REV) { + ast_debug(1, + "Hanging up due to polarity reversal on channel %d while detecting callerid\n", + p->channel); + p->polarity = POLARITY_IDLE; + analog_stop_cid_detect(p); + ast_hangup(chan); + goto quit; + } else if (ev == ANALOG_EVENT_RINGOFFHOOK + && p->usedistinctiveringdetection + && ring_data_idx < RING_PATTERNS) { + /* + * Detect callerid while collecting possible + * distinctive ring pattern. + */ + ring_data[ring_data_idx] = p->ringt; + ++ring_data_idx; } - } + name = namebuf; number = numbuf; + res = analog_distinctive_ring(chan, p, idx, ring_data); analog_stop_cid_detect(p); - - if (analog_distinctive_ring(chan, p, idx, curRingData)) { + if (res) { goto quit; } - - if (res < 0) { - ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", ast_channel_name(chan)); - } } else { ast_log(LOG_WARNING, "Unable to get caller ID space\n"); } diff --git a/channels/sig_analog.h b/channels/sig_analog.h index 13c92c657ba3f5248cfea4d571ec2f70d9553d0f..6415b6eb8c9b383971884e3eae3069ac428bc40a 100644 --- a/channels/sig_analog.h +++ b/channels/sig_analog.h @@ -281,6 +281,7 @@ struct analog_pvt { unsigned int transfer:1; unsigned int transfertobusy:1; /*!< allow flash-transfers to busy channels */ unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */ + unsigned int usedistinctiveringdetection:1; unsigned int callwaitingcallerid:1; /*!< TRUE if send caller ID for Call Waiting */ /*! * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled