summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDoug Bailey <dbailey@digium.com>2009-09-03 19:40:37 +0000
committerDoug Bailey <dbailey@digium.com>2009-09-03 19:40:37 +0000
commit8430c87faa75061e453e511a2286c0f521807529 (patch)
tree62d0b8b63640906ae24ee935eab37f1171d7e12a
parent148552de240c2507c1a9732c15615e5a8a93f295 (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.c80
-rw-r--r--channels/sig_analog.c30
-rw-r--r--channels/sig_analog.h3
-rw-r--r--include/asterisk/callerid.h7
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 */