diff options
author | Doug Bailey <dbailey@digium.com> | 2009-09-03 19:40:37 +0000 |
---|---|---|
committer | Doug Bailey <dbailey@digium.com> | 2009-09-03 19:40:37 +0000 |
commit | 8430c87faa75061e453e511a2286c0f521807529 (patch) | |
tree | 62d0b8b63640906ae24ee935eab37f1171d7e12a | |
parent | 148552de240c2507c1a9732c15615e5a8a93f295 (diff) |
Added detection DTMF CID without polarity change alert.
Added detection of DTMF tone energy levels on FXO channels in chan_dahdi
monitoring loop so DTMF CID can be detected without the need of a polarity
change precursor.
(closes issue #9096)
Reported by: fleed
Patches:
9096-chan_dahdi-trunk.diff uploaded by dbailey (license 819)
Tested by: cyberplant, sum, maturs
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@216094 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r-- | channels/chan_dahdi.c | 80 | ||||
-rw-r--r-- | channels/sig_analog.c | 30 | ||||
-rw-r--r-- | channels/sig_analog.h | 3 | ||||
-rw-r--r-- | include/asterisk/callerid.h | 7 |
4 files changed, 109 insertions, 11 deletions
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 7f4c7f6d1..e6e83ed31 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -416,6 +416,7 @@ static int distinctiveringaftercid = 0; static int numbufs = 4; static int mwilevel = 512; +static int dtmfcid_level = 256; #ifdef HAVE_PRI #ifdef PRI_GETSET_TIMERS @@ -1081,7 +1082,9 @@ static struct dahdi_pvt { int span; /*!< Span number */ time_t guardtime; /*!< Must wait this much time before using for new call */ int cid_signalling; /*!< CID signalling type bell202 or v23 */ - int cid_start; /*!< CID start indicator, polarity or ring */ + int cid_start; /*!< CID start indicator, polarity or ring or DTMF without warning event */ + int dtmfcid_holdoff_state; /*!< State indicator that allows for line to settle before checking for dtmf energy */ + struct timeval dtmfcid_delay; /*!< Time value used for allow line to settle */ int callingpres; /*!< The value of calling presentation that we're going to use when placing a PRI call */ int callwaitingrepeat; /*!< How many samples to wait before repeating call waiting */ int cidcwexpire; /*!< When to expire our muting for CID/CW */ @@ -8924,7 +8927,8 @@ static void *analog_ss_thread(void *data) /* If we want caller id, we're in a prering state due to a polarity reversal * and we're set to use a polarity reversal to trigger the start of caller id, * grab the caller id and wait for ringing to start... */ - } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) { + } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && + (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) { /* If set to use DTMF CID signalling, listen for DTMF */ if (p->cid_signalling == CID_SIG_DTMF) { int k = 0; @@ -10082,8 +10086,10 @@ static void *do_monitor(void *data) pfds[count].events = POLLPRI; pfds[count].revents = 0; /* Message waiting or r2 channels also get watched for reading */ - if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk) + if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || + (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) { pfds[count].events |= POLLIN; + } count++; } } else { @@ -10094,8 +10100,10 @@ static void *do_monitor(void *data) pfds[count].revents = 0; /* If we are monitoring for VMWI or sending CID, we need to read from the channel as well */ - if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk) + if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || + (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) { pfds[count].events |= POLLIN; + } count++; } } @@ -10185,7 +10193,7 @@ static void *do_monitor(void *data) i = i->next; continue; } - if (!i->mwimonitor_fsk && !i->mwisendactive) { + if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) { ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd); i = i->next; continue; @@ -10213,6 +10221,50 @@ static void *do_monitor(void *data) i->mwimonitoractive = 1; } } + /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */ + } else if (i->cid_start == CID_START_DTMF_NOALERT) { + int energy; + struct timeval now; + /* State machine dtmfcid_holdoff_state allows for the line to settle + * before checking agin for dtmf energy. Presently waits for 500 mS before checking again + */ + if (1 == i->dtmfcid_holdoff_state) { + gettimeofday(&i->dtmfcid_delay, NULL); + i->dtmfcid_holdoff_state = 2; + } else if (2 == i->dtmfcid_holdoff_state) { + gettimeofday(&now, NULL); + if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) { + i->dtmfcid_holdoff_state = 0; + } + } else { + energy = calc_energy((unsigned char *) buf, res, AST_LAW(i)); + if (!i->mwisendactive && energy > dtmfcid_level) { + pthread_t threadid; + struct ast_channel *chan; + ast_mutex_unlock(&iflock); + if (analog_lib_handles(i->sig, i->radio, i->oprmode)) { + res = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID); + if (res) { + ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); + } else { + i->dtmfcid_holdoff_state = 1; + } + } else { + chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0, NULL); + if (!chan) { + ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); + } else { + res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan); + if (res) { + ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); + } else { + i->dtmfcid_holdoff_state = 1; + } + } + } + ast_mutex_lock(&iflock); + } + } } if (i->mwisendactive) { mwi_send_process_buffer(i, res); @@ -11191,7 +11243,19 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, analog_p->echotraining = conf->chan.echotraining; analog_p->cid_signalling = conf->chan.cid_signalling; analog_p->stripmsd = conf->chan.stripmsd; - analog_p->cid_start = ANALOG_CID_START_RING; + switch (conf->chan.cid_start) { + case CID_START_POLARITY: + analog_p->cid_start = ANALOG_CID_START_POLARITY; + break; + case CID_START_POLARITY_IN: + analog_p->cid_start = ANALOG_CID_START_POLARITY_IN; + break; + case CID_START_DTMF_NOALERT: + analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT; + break; + default: + analog_p->cid_start = ANALOG_CID_START_RING; + } analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid; analog_p->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection; analog_p->ringt = conf->chan.ringt; @@ -15181,6 +15245,8 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct confp->chan.cid_start = CID_START_POLARITY_IN; else if (!strcasecmp(v->value, "polarity")) confp->chan.cid_start = CID_START_POLARITY; + else if (!strcasecmp(v->value, "dtmf")) + confp->chan.cid_start = CID_START_DTMF_NOALERT; else if (ast_true(v->value)) confp->chan.cid_start = CID_START_RING; } else if (!strcasecmp(v->name, "threewaycalling")) { @@ -16016,6 +16082,8 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); } else if (!strcasecmp(v->name, "mwilevel")) { mwilevel = atoi(v->value); + } else if (!strcasecmp(v->name, "dtmfcidlevel")) { + dtmfcid_level = atoi(v->value); } } else if (!(options & PROC_DAHDI_OPT_NOWARN) ) ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno); diff --git a/channels/sig_analog.c b/channels/sig_analog.c index ae6620f49..2b4119fb7 100644 --- a/channels/sig_analog.c +++ b/channels/sig_analog.c @@ -193,6 +193,8 @@ enum analog_cid_start analog_str_to_cidstart(const char *value) return ANALOG_CID_START_POLARITY; } else if (!strcasecmp(value, "polarity_in")) { return ANALOG_CID_START_POLARITY_IN; + } else if (!strcasecmp(value, "dtmf")) { + return ANALOG_CID_START_DTMF_NOALERT; } return 0; @@ -207,6 +209,8 @@ const char *analog_cidstart_to_str(enum analog_cid_start cid_start) return "Polarity"; case ANALOG_CID_START_POLARITY_IN: return "Polarity_In"; + case ANALOG_CID_START_DTMF_NOALERT: + return "DTMF"; } return "Unknown"; @@ -2032,7 +2036,8 @@ static void *__analog_ss_thread(void *data) /* If we want caller id, we're in a prering state due to a polarity reversal * and we're set to use a polarity reversal to trigger the start of caller id, * grab the caller id and wait for ringing to start... */ - if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == ANALOG_CID_START_POLARITY || p->cid_start == ANALOG_CID_START_POLARITY_IN))) { + if (p->use_callerid && (chan->_state == AST_STATE_PRERING && + (p->cid_start == ANALOG_CID_START_POLARITY || p->cid_start == ANALOG_CID_START_POLARITY_IN || p->cid_start == ANALOG_CID_START_DTMF_NOALERT))) { /* If set to use DTMF CID signalling, listen for DTMF */ if (p->cid_signalling == CID_SIG_DTMF) { int i = 0; @@ -3239,7 +3244,7 @@ int analog_handle_init_event(struct analog_pvt *i, int event) case ANALOG_SIG_SF_FEATB: case ANALOG_SIG_SF: /* Check for callerid, digits, etc */ - if (i->cid_start == ANALOG_CID_START_POLARITY_IN) { + if (i->cid_start == ANALOG_CID_START_POLARITY_IN || i->cid_start == ANALOG_CID_START_DTMF_NOALERT) { chan = analog_new_ast_channel(i, AST_STATE_PRERING, 0, ANALOG_SUB_REAL, NULL); } else { chan = analog_new_ast_channel(i, AST_STATE_RING, 0, ANALOG_SUB_REAL, NULL); @@ -3356,6 +3361,27 @@ int analog_handle_init_event(struct analog_pvt *i, int event) "interface %d\n", i->channel); } break; + case ANALOG_EVENT_DTMFCID: + switch (i->sig) { + case ANALOG_SIG_FXSLS: + case ANALOG_SIG_FXSKS: + case ANALOG_SIG_FXSGS: + if (i->cid_start == ANALOG_CID_START_DTMF_NOALERT) { + ast_verbose(VERBOSE_PREFIX_2 "Starting DTMF CID detection on channel %d\n", + i->channel); + chan = analog_new_ast_channel(i, AST_STATE_PRERING, 0, ANALOG_SUB_REAL, NULL); + i->ss_astchan = chan; + if (chan && ast_pthread_create(&threadid, &attr, __analog_ss_thread, i)) { + ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); + } + } + break; + default: + ast_log(LOG_WARNING, "handle_init_event detected " + "dtmfcid generation event on non-FXO (ANALOG_SIG_FXS) " + "interface %d\n", i->channel); + } + break; case ANALOG_EVENT_NEONMWI_ACTIVE: analog_handle_notify_message(NULL, i, -1, ANALOG_EVENT_NEONMWI_ACTIVE); break; diff --git a/channels/sig_analog.h b/channels/sig_analog.h index 381655021..b937ec665 100644 --- a/channels/sig_analog.h +++ b/channels/sig_analog.h @@ -80,6 +80,7 @@ enum analog_event { ANALOG_EVENT_ERROR, ANALOG_EVENT_NEONMWI_ACTIVE, ANALOG_EVENT_NEONMWI_INACTIVE, + ANALOG_EVENT_DTMFCID, }; enum analog_sub { @@ -97,6 +98,7 @@ enum analog_cid_start { ANALOG_CID_START_POLARITY = 1, ANALOG_CID_START_POLARITY_IN, ANALOG_CID_START_RING, + ANALOG_CID_START_DTMF_NOALERT, }; #define ANALOG_MAX_CID 300 @@ -187,6 +189,7 @@ struct analog_callback { void (* const decrease_ss_count)(void); int (* const distinctive_ring)(struct ast_channel *chan, void *pvt, int idx, int *ringdata); + /* Sets the specified sub-channel in and out of signed linear mode, returns the value that was overwritten */ int (* const set_linear_mode)(void *pvt, int idx, int linear_mode); void (* const get_and_handle_alarms)(void *pvt); void * (* const get_sigpvt_bridged_channel)(struct ast_channel *chan); diff --git a/include/asterisk/callerid.h b/include/asterisk/callerid.h index b8ff53cc1..717248c12 100644 --- a/include/asterisk/callerid.h +++ b/include/asterisk/callerid.h @@ -60,9 +60,10 @@ #define CID_SIG_V23_JP 4 #define CID_SIG_SMDI 5 -#define CID_START_RING 1 -#define CID_START_POLARITY 2 -#define CID_START_POLARITY_IN 3 +#define CID_START_RING 1 +#define CID_START_POLARITY 2 +#define CID_START_POLARITY_IN 3 +#define CID_START_DTMF_NOALERT 4 /* defines dealing with message waiting indication generation */ /*! MWI SDMF format */ |