diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 5607eb01b7b9dd9b37d33d5d84c496fc614cd99f..e49a7996a9fd930fdafa42142bf2742e4365fea5 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -261,6 +261,17 @@ completely disabled)</para> <para> <literal>voice</literal> Voice mode (returns from FAX mode, reverting the changes that were made)</para> </enum> + <enum name="dialmode"> + <para>R/W Pulse and tone dialing mode of the channel.</para> + <para>If set, overrides the setting in <literal>chan_dahdi.conf</literal> for that channel.</para> + <enumlist> + <enum name="both" /> + <enum name="pulse" /> + <enum name="dtmf" /> + <enum name="tone" /> + <enum name="none" /> + </enumlist> + </enum> </enumlist> </info> <info name="Dial_Resource" language="en_US" tech="DAHDI"> @@ -1034,6 +1045,7 @@ static struct dahdi_chan_conf dahdi_chan_conf_default(void) .mohsuggest = "", .parkinglot = "", .transfertobusy = 1, + .dialmode = 0, .ani_info_digits = 2, .ani_wink_time = 1000, @@ -7009,6 +7021,32 @@ static int dahdi_func_read(struct ast_channel *chan, const char *function, char } ast_mutex_unlock(&p->lock); #endif /* defined(HAVE_PRI) */ + } else if (!strcasecmp(data, "dialmode")) { + struct analog_pvt *analog_p; + ast_mutex_lock(&p->lock); + analog_p = p->sig_pvt; + /* Hardcode p->radio and p->oprmode as 0 since we're using this to check for analogness, not the handler */ + if (dahdi_analog_lib_handles(p->sig, 0, 0) && analog_p) { + switch (analog_p->dialmode) { + case ANALOG_DIALMODE_BOTH: + ast_copy_string(buf, "both", len); + break; + case ANALOG_DIALMODE_PULSE: + ast_copy_string(buf, "pulse", len); + break; + case ANALOG_DIALMODE_DTMF: + ast_copy_string(buf, "dtmf", len); + break; + case ANALOG_DIALMODE_NONE: + ast_copy_string(buf, "none", len); + break; + } + } else { + ast_log(LOG_WARNING, "%s only supported on analog channels\n", data); + *buf = '\0'; + res = -1; + } + ast_mutex_unlock(&p->lock); } else { *buf = '\0'; res = -1; @@ -7114,6 +7152,30 @@ static int dahdi_func_write(struct ast_channel *chan, const char *function, char ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data); res = -1; } + } else if (!strcasecmp(data, "dialmode")) { + struct analog_pvt *analog_p; + + ast_mutex_lock(&p->lock); + analog_p = p->sig_pvt; + if (!dahdi_analog_lib_handles(p->sig, 0, 0) || !analog_p) { + ast_log(LOG_WARNING, "%s only supported on analog channels\n", data); + ast_mutex_unlock(&p->lock); + return -1; + } + /* analog pvt is used for pulse dialing, so update both */ + if (!strcasecmp(value, "pulse")) { + p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_PULSE; + } else if (!strcasecmp(value, "dtmf") || !strcasecmp(value, "tone")) { + p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_DTMF; + } else if (!strcasecmp(value, "none")) { + p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_NONE; + } else if (!strcasecmp(value, "both")) { + p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_BOTH; + } else { + ast_log(LOG_WARNING, "'%s' is an invalid setting for %s\n", value, data); + res = -1; + } + ast_mutex_unlock(&p->lock); } else { res = -1; } @@ -8997,6 +9059,13 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast) } else { dahdi_handle_dtmf(ast, idx, &f); } + if (!(p->dialmode == ANALOG_DIALMODE_BOTH || p->dialmode == ANALOG_DIALMODE_DTMF)) { + if (f->frametype == AST_FRAME_DTMF_END) { /* only show this message when the key is let go of */ + ast_debug(1, "Dropping DTMF digit '%c' because tone dialing is disabled\n", f->subclass.integer); + } + f->frametype = AST_FRAME_NULL; + f->subclass.integer = 0; + } break; case AST_FRAME_VOICE: if (p->cidspill || p->cid_suppress_expire) { @@ -12780,6 +12849,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, #endif tmp->immediate = conf->chan.immediate; tmp->transfertobusy = conf->chan.transfertobusy; + tmp->dialmode = conf->chan.dialmode; if (chan_sig & __DAHDI_SIG_FXS) { tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk; tmp->mwimonitor_neon = conf->chan.mwimonitor_neon; @@ -13113,6 +13183,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, analog_p->threewaycalling = conf->chan.threewaycalling; analog_p->transfer = conf->chan.transfer; analog_p->transfertobusy = conf->chan.transfertobusy; + analog_p->dialmode = conf->chan.dialmode; analog_p->use_callerid = tmp->use_callerid; analog_p->usedistinctiveringdetection = tmp->usedistinctiveringdetection; analog_p->use_smdi = tmp->use_smdi; @@ -18314,6 +18385,16 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct confp->chan.immediate = ast_true(v->value); } else if (!strcasecmp(v->name, "transfertobusy")) { confp->chan.transfertobusy = ast_true(v->value); + } else if (!strcasecmp(v->name, "dialmode")) { + if (!strcasecmp(v->value, "pulse")) { + confp->chan.dialmode = ANALOG_DIALMODE_PULSE; + } else if (!strcasecmp(v->value, "dtmf") || !strcasecmp(v->value, "tone")) { + confp->chan.dialmode = ANALOG_DIALMODE_DTMF; + } else if (!strcasecmp(v->value, "none")) { + confp->chan.dialmode = ANALOG_DIALMODE_NONE; + } else { + confp->chan.dialmode = ANALOG_DIALMODE_BOTH; + } } else if (!strcasecmp(v->name, "mwimonitor")) { confp->chan.mwimonitor_neon = 0; confp->chan.mwimonitor_fsk = 0; diff --git a/channels/chan_dahdi.h b/channels/chan_dahdi.h index de813f21bf653ae56fda64cc7afc0e75c3209327..8f1668752806c54d9f7f59e60cbf6c8938f404b6 100644 --- a/channels/chan_dahdi.h +++ b/channels/chan_dahdi.h @@ -146,6 +146,7 @@ struct dahdi_pvt { * \note Set to a couple of nonzero values but it is only tested like a boolean. */ int radio; + int dialmode; /*!< Dialing Modes Allowed (Pulse/Tone) */ int outsigmod; /*!< Outbound Signalling style (modifier) */ int oprmode; /*!< "Operator Services" mode */ struct dahdi_pvt *oprpeer; /*!< "Operator Services" peer tech_pvt ptr */ diff --git a/channels/sig_analog.c b/channels/sig_analog.c index b694a96082378a9e975cdee8036d8b9c64bf9870..5ae96d9418d2598acde993ae713ca23bebd88350 100644 --- a/channels/sig_analog.c +++ b/channels/sig_analog.c @@ -2775,9 +2775,13 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ analog_set_pulsedial(p, (res & ANALOG_EVENT_PULSEDIGIT) ? 1 : 0); ast_debug(1, "Detected %sdigit '%c'\n", (res & ANALOG_EVENT_PULSEDIGIT) ? "pulse ": "", res & 0xff); analog_confmute(p, 0); - p->subs[idx].f.frametype = AST_FRAME_DTMF_END; - p->subs[idx].f.subclass.integer = res & 0xff; - analog_handle_dtmf(p, ast, idx, &f); + if (p->dialmode == ANALOG_DIALMODE_BOTH || p->dialmode == ANALOG_DIALMODE_PULSE) { + p->subs[idx].f.frametype = AST_FRAME_DTMF_END; + p->subs[idx].f.subclass.integer = res & 0xff; + analog_handle_dtmf(p, ast, idx, &f); + } else { + ast_debug(1, "Dropping pulse digit '%c' because pulse dialing disabled on channel %d\n", res & 0xff, p->channel); + } return f; } diff --git a/channels/sig_analog.h b/channels/sig_analog.h index 7e9acda55cac35c5ed5819d5c10b4b08c98a17ef..07e1cdd2aa1a7613c05074c8e495993b79891491 100644 --- a/channels/sig_analog.h +++ b/channels/sig_analog.h @@ -116,6 +116,13 @@ enum analog_dsp_digitmode { ANALOG_DIGITMODE_MF, }; +enum analog_dialmode { + ANALOG_DIALMODE_BOTH = 0, + ANALOG_DIALMODE_PULSE, + ANALOG_DIALMODE_DTMF, + ANALOG_DIALMODE_NONE, +}; + enum analog_cid_start { ANALOG_CID_START_POLARITY = 1, ANALOG_CID_START_POLARITY_IN, @@ -308,6 +315,7 @@ struct analog_pvt { int channel; /*!< Channel Number */ enum analog_sigtype outsigmod; + enum analog_dialmode dialmode; /*!< Which of pulse and/or tone dialing to support */ int echotraining; int cid_signalling; /*!< Asterisk callerid type we're using */ int polarityonanswerdelay; diff --git a/configs/samples/chan_dahdi.conf.sample b/configs/samples/chan_dahdi.conf.sample index 6b2954975091b4eca90aaf47fbb9d4d484f7ee89..c54f482566715b4560e9e013bec08774ab1f75bc 100644 --- a/configs/samples/chan_dahdi.conf.sample +++ b/configs/samples/chan_dahdi.conf.sample @@ -1131,10 +1131,19 @@ pickupgroup=1 ; ; For FXO (FXS signalled) devices, whether to use pulse dial instead of DTMF ; Pulse digits from phones (FXS devices, FXO signalling) are always -; detected. +; detected, unless the dialmode setting has been changed from the default. ; ;pulsedial=yes ; +; For FXS (FXO signalled) devices, the dialing modes to support for the channel. +; By default, both pulse and tone (DTMF) dialing are always detected. +; May be set to "pulse" if you only want to allow pulse dialing on a line. +; May be set to "dtmf" or "tone" to only allow tone dialing on a line. +; May be set to "none" to prevent dialing entirely. +; You can also change this during a call using the CHANNEL function in the dialplan. +; +;dialmode=both +; ; For fax detection, uncomment one of the following lines. The default is *OFF* ; ;faxdetect=both