Index: channels/chan_dahdi.c =================================================================== --- channels/chan_dahdi.c (revision 432173) +++ channels/chan_dahdi.c (working copy) @@ -1026,7 +1026,7 @@ */ char description[32]; /*! - * \brief Saved context string. + * \brief Default distinctive ring context. */ char defcontext[AST_MAX_CONTEXT]; /*! \brief Extension to use in the dialplan. */ @@ -1759,13 +1759,21 @@ 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; } @@ -1842,7 +1850,6 @@ } 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) { @@ -1855,7 +1862,7 @@ int i; int res; int checkaftercid = 0; - + const char *matched_context; struct dahdi_pvt *p = pvt; struct analog_pvt *analog_p = p->sig_pvt; @@ -1865,19 +1872,15 @@ 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 (;;) { @@ -1889,22 +1892,23 @@ } 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; + } 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; + } } - ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); - res = 0; - /* 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; } else if (i & DAHDI_IOMUX_READ) { res = read(p->subs[idx].dfd, buf, sizeof(buf)); if (res < 0) { @@ -1924,45 +1928,50 @@ } } } - 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", + + /* 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 (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); + 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; + } } - /* Restore linear mode (if appropriate) for Caller*ID processing */ - dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); - restore_gains(p); + /* 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); + } + return 0; } @@ -13428,6 +13437,7 @@ 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; Index: channels/sig_analog.c =================================================================== --- channels/sig_analog.c (revision 432173) +++ channels/sig_analog.c (working copy) @@ -1678,6 +1678,9 @@ 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); } @@ -2454,50 +2457,53 @@ /* 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 (res != 1) { + continue; + } + 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); } - 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; - } + } else { + break; } + } - if (ast_tvdiff_ms(ast_tvnow(), start) > timeout) - 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); } @@ -2511,11 +2517,13 @@ 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; } @@ -2525,13 +2533,11 @@ 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"); } @@ -2545,66 +2551,74 @@ 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 curRingData[RING_PATTERNS] = { 0 }; + int receivedRingT = 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) { + continue; + } + 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) { + /* + * Detect callerid while collecting possible + * distinctive ring pattern. + */ + curRingData[receivedRingT] = p->ringt; - 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) { + if (p->ringt < p->ringt_base/2) { 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; - } + /* Increment the ringT counter so we can match it against + values in chan_dahdi.conf for distinctive ring */ + if (++receivedRingT == RING_PATTERNS) { + break; } } + } - if (ast_tvdiff_ms(ast_tvnow(), start) > timeout) { - break; - } - - } name = namebuf; number = numbuf; + res = analog_distinctive_ring(chan, p, idx, curRingData); 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"); } Index: channels/sig_analog.h =================================================================== --- channels/sig_analog.h (revision 432173) +++ channels/sig_analog.h (working copy) @@ -281,6 +281,7 @@ 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