diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 8ce0526f4d..8957790b3b 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -261,6 +261,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.
+
+
+
+
+
+
+
+
@@ -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,
@@ -7008,6 +7020,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;
@@ -7113,6 +7149,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;
}
@@ -8996,6 +9053,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) {
@@ -12779,6 +12843,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;
@@ -13112,6 +13177,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;
@@ -18308,6 +18374,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 76ee645c26..1abb8d6e48 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 7e9acda55c..07e1cdd2aa 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 6333351c0d..4affe264c3 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.