]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
chan_dahdi: Add dialmode option for FXS lines.
authorNaveen Albert <asterisk@phreaknet.org>
Fri, 28 Apr 2023 18:57:37 +0000 (18:57 +0000)
committerNaveen Albert <asterisk@phreaknet.org>
Tue, 2 May 2023 14:06:28 +0000 (14:06 +0000)
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.

Resolves: #35
ASTERISK-29992

UserNote: 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.

channels/chan_dahdi.c
channels/chan_dahdi.h
channels/sig_analog.c
channels/sig_analog.h
configs/samples/chan_dahdi.conf.sample

index cfddb3a7941ddab7db228269d985f834e397f174..f97c902878b38d01a60b78c61ef0b856f6be72d3 100644 (file)
                                        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;
index de813f21bf653ae56fda64cc7afc0e75c3209327..8f1668752806c54d9f7f59e60cbf6c8938f404b6 100644 (file)
@@ -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 */
index b694a96082378a9e975cdee8036d8b9c64bf9870..5ae96d9418d2598acde993ae713ca23bebd88350 100644 (file)
@@ -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;
        }
 
index 7e9acda55cac35c5ed5819d5c10b4b08c98a17ef..07e1cdd2aa1a7613c05074c8e495993b79891491 100644 (file)
@@ -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;
index 6b2954975091b4eca90aaf47fbb9d4d484f7ee89..c54f482566715b4560e9e013bec08774ab1f75bc 100644 (file)
@@ -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