</enum>
<enum name="dialmode">
<para>R/W Pulse and tone dialing mode of the channel.</para>
- <para>Disabling tone dialing using this option will not disable the DSP used for DTMF detection.
+ <para>Disabling tone dialing using this option will not automatically disable the DSP used for DTMF detection.
To do that, also set the <literal>digitdetect</literal> option. If digit detection is disabled,
DTMF will not be detected, regardless of the <literal>dialmode</literal> setting.
The <literal>digitdetect</literal> setting has no impact on pulse dialing detection.</para>
<para>If set, overrides the setting in <literal>chan_dahdi.conf</literal> for that channel.</para>
+ <para>The <literal>dialmode</literal> setting applies to the DAHDI channel as a whole, but is reset for each call,
+ so modifications made using the <literal>CHANNEL</literal> function apply temporarily per-call.
+ The <literal>digitdetect</literal> setting applies to the entire DAHDI channel,
+ so any changes made to this setting will affect all calls concurrently on the same DAHDI channel.
+ <literal>digitdetect</literal> is reset once all calls on the line have cleared.</para>
<enumlist>
<enum name="both" />
<enum name="pulse" />
.mohsuggest = "",
.parkinglot = "",
.transfertobusy = 1,
- .dialmode = 0,
+ .permdialmode = ANALOG_DIALMODE_BOTH,
.ani_info_digits = 2,
.ani_wink_time = 1000,
p->callwaitcas = 0;
p->callwaiting = p->permcallwaiting;
p->hidecallerid = p->permhidecallerid;
+ if (dahdi_analog_lib_handles(p->sig, p->radio, 0) && !p->owner) {
+ /* The code in sig_analog handles resetting to permdialmode on originations;
+ * this addresses the edge case of multiple calls that do not involve
+ * origination inbetween, i.e. multiple incoming calls. */
+ struct analog_pvt *analog_p = p->sig_pvt;
+ /* If no calls remain, reset dialmode.
+ * This way, if the next call is an incoming call,
+ * it's already been reset. */
+ analog_p->dialmode = analog_p->permdialmode;
+ }
p->waitingfordt.tv_sec = 0;
p->dialing = 0;
p->rdnis[0] = '\0';
}
/* analog pvt is used for pulse dialing, so update both */
if (!strcasecmp(value, "pulse")) {
- p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_PULSE;
+ analog_p->dialmode = ANALOG_DIALMODE_PULSE;
} else if (!strcasecmp(value, "dtmf") || !strcasecmp(value, "tone")) {
- p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_DTMF;
+ analog_p->dialmode = ANALOG_DIALMODE_DTMF;
} else if (!strcasecmp(value, "none")) {
- p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_NONE;
+ analog_p->dialmode = ANALOG_DIALMODE_NONE;
} else if (!strcasecmp(value, "both")) {
- p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_BOTH;
+ analog_p->dialmode = ANALOG_DIALMODE_BOTH;
} else {
ast_log(LOG_WARNING, "'%s' is an invalid setting for %s\n", value, data);
res = -1;
f = &p->subs[idx].f;
if (f) {
+ struct analog_pvt *analog_p = p->sig_pvt;
switch (f->frametype) {
case AST_FRAME_DTMF_BEGIN:
case AST_FRAME_DTMF_END:
} else {
dahdi_handle_dtmf(ast, idx, &f);
}
- if (!(p->dialmode == ANALOG_DIALMODE_BOTH || p->dialmode == ANALOG_DIALMODE_DTMF)) {
+ if (!(analog_p->dialmode == ANALOG_DIALMODE_BOTH || analog_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);
}
tmp->immediate = conf->chan.immediate;
tmp->immediatering = conf->chan.immediatering;
tmp->transfertobusy = conf->chan.transfertobusy;
- tmp->dialmode = conf->chan.dialmode;
+ tmp->permdialmode = conf->chan.permdialmode;
if (chan_sig & __DAHDI_SIG_FXS) {
tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
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->permdialmode = conf->chan.permdialmode;
analog_p->use_callerid = tmp->use_callerid;
analog_p->usedistinctiveringdetection = tmp->usedistinctiveringdetection;
analog_p->use_smdi = tmp->use_smdi;
confp->chan.transfertobusy = ast_true(v->value);
} else if (!strcasecmp(v->name, "dialmode")) {
if (!strcasecmp(v->value, "pulse")) {
- confp->chan.dialmode = ANALOG_DIALMODE_PULSE;
+ confp->chan.permdialmode = ANALOG_DIALMODE_PULSE;
} else if (!strcasecmp(v->value, "dtmf") || !strcasecmp(v->value, "tone")) {
- confp->chan.dialmode = ANALOG_DIALMODE_DTMF;
+ confp->chan.permdialmode = ANALOG_DIALMODE_DTMF;
} else if (!strcasecmp(v->value, "none")) {
- confp->chan.dialmode = ANALOG_DIALMODE_NONE;
+ confp->chan.permdialmode = ANALOG_DIALMODE_NONE;
} else {
- confp->chan.dialmode = ANALOG_DIALMODE_BOTH;
+ confp->chan.permdialmode = ANALOG_DIALMODE_BOTH;
}
} else if (!strcasecmp(v->name, "mwimonitor")) {
confp->chan.mwimonitor_neon = 0;
static int analog_stop_callwait(struct analog_pvt *p)
{
p->callwaitcas = 0;
+
+ /* There are 3 scenarios in which we need to reset the dialmode to permdialmode.
+ * 1) When placing a new outgoing call (either the first or a three-way)
+ * 2) When receiving a new incoming call
+ * 2A) If it's the first incoming call (not a call waiting), we reset
+ * in dahdi_hangup.
+ * 2B ) If it's a call waiting we've answered, either by swapping calls
+ * or having it ring through, we call analog_stop_callwait. That's this! */
+ p->dialmode = p->permdialmode;
+
if (analog_callbacks.stop_callwait) {
return analog_callbacks.stop_callwait(p->chan_pvt);
}
*/
p->hidecallerid = p->permhidecallerid;
+ /* Set the default dial mode.
+ * As with Caller ID, this is independent for each call,
+ * and changes made using the CHANNEL function are only temporary.
+ * This reset ensures temporary changes are discarded when a new call is originated.
+ *
+ * XXX There is a slight edge case in that because the dialmode is reset to permdialmode,
+ * assuming permdialmode=both, if a user disables dtmf during call 1, then flashes and
+ * starts call 2, this will set dialmode back to permcallmode on the private,
+ * allowing tone dialing to (correctly) work on call 2.
+ * If the user flashes back to call 1, however, tone dialing will again work on call 1.
+ *
+ * This problem does not exist with the other settings that involve a "permanent"
+ * and "transient" settings (e.g. hidecallerid, callwaiting), because hidecallerid
+ * only matters when originating a call, so as soon as it's been placed, it doesn't
+ * matter if it gets reset. For callwaiting, the setting is supposed to be common
+ * to the entire channel private (all subchannels), which is NOT the case with this setting.
+ *
+ * The correct and probably only fix for this edge case is to move dialmode out of the channel private
+ * (which is shared by all subchannels), and into the Asterisk channel structure. Just using an array for
+ * each chan_dahdi subchannel won't work because the indices change as calls flip around.
+ */
+ p->dialmode = p->permdialmode;
+
/* Read the first digit */
timeout = analog_get_firstdigit_timeout(p);
/* If starting a threeway call, never timeout on the first digit so someone