From 449ef38eada031558d14b6fba3281fdc27842872 Mon Sep 17 00:00:00 2001 From: Naveen Albert Date: Mon, 28 Mar 2022 18:03:48 +0000 Subject: [PATCH] chan_dahdi: Add dialmode option for FXS lines. Currently, both pulse and tone dialing are always enabled on all FXS lines, with no way of disabling one or the other. In some circumstances, it is desirable or necessary to disable one of these, and this behavior can be problematic. A new "dialmode" option is added which allows setting the methods to support on a per channel basis for FXS (FXO signalled lines). The four options are "both", "pulse", "dtmf"/"tone", and "none". Additionally, integration with the CHANNEL function is added so that this setting can be updated for a channel during a call. ASTERISK-29992 #close Change-Id: Id3fb3fbf031ef8d5e8c867836f226f8e9023cd26 --- channels/chan_dahdi.c | 76 +++++++++++++++++++++ channels/chan_dahdi.h | 1 + channels/sig_analog.c | 10 ++- channels/sig_analog.h | 8 +++ configs/samples/chan_dahdi.conf.sample | 11 ++- doc/CHANGES-staging/chan_dahdi_dialmode.txt | 10 +++ 6 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 doc/CHANGES-staging/chan_dahdi_dialmode.txt diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index ad7a8e5e54..b9416e570a 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -232,6 +232,17 @@ completely disabled) voice Voice mode (returns from FAX mode, reverting the changes that were made) + + R/W Pulse and tone dialing mode of the channel. + If set, overrides the setting in chan_dahdi.conf for that channel. + + + + + + + + @@ -952,6 +963,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, @@ -6834,6 +6846,30 @@ 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 = p->sig_pvt; + if (analog_p) { + ast_mutex_lock(&p->lock); + 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; + } + ast_mutex_unlock(&p->lock); + } else { + ast_log(LOG_WARNING, "%s only supported on analog channels\n", data); + *buf = '\0'; + res = -1; + } } else { *buf = '\0'; res = -1; @@ -6939,6 +6975,27 @@ 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 = p->sig_pvt; + if (!analog_p) { + ast_log(LOG_WARNING, "%s only supported on analog channels\n", data); + return -1; + } + ast_mutex_lock(&p->lock); + /* 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; } @@ -8815,6 +8872,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) { @@ -12597,6 +12661,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; @@ -12930,6 +12995,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; @@ -18121,6 +18187,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 de813f21bf..8f16687528 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 64f1114fde..2b9da105cd 100644 --- a/channels/sig_analog.c +++ b/channels/sig_analog.c @@ -2768,9 +2768,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 488be3662e..3c27105892 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 5c3af43623..1e75318543 100644 --- a/configs/samples/chan_dahdi.conf.sample +++ b/configs/samples/chan_dahdi.conf.sample @@ -1126,10 +1126,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 diff --git a/doc/CHANGES-staging/chan_dahdi_dialmode.txt b/doc/CHANGES-staging/chan_dahdi_dialmode.txt new file mode 100644 index 0000000000..2e77a29a70 --- /dev/null +++ b/doc/CHANGES-staging/chan_dahdi_dialmode.txt @@ -0,0 +1,10 @@ +Subject: chan_dahdi + +A "dialmode" option has been added which allows +specifying, on a per-channel basis, what methods +of subscriber dialing (pulse and/or tone) are +permitted. + +Additionally, this can be changed on a channel +at any point during a call using the CHANNEL +function.