Add pause one second W dial modifier.

* The following dialplan applications now recognize 'W' to pause sending
DTMF for one second in addition to the previously existing 'w' that paused
sending DTMF for half a second.  Dial, ExternalIVR, and SendDTMF.

* The chan_dahdi analog port dialing and deferred DTMF dialing for PRI now
distinguishes between 'w' and 'W'.  The 'w' pauses dialing for half a
second.  The 'W' pauses dialing for one second.

* Created dahdi_dial_str() in chan_dahdi that eliminated a lot of
duplicated dialing code and diagnostic messages for the channel driver.

(closes issue ASTERISK-20039)
Reported by: Jeremiah Gowdy
Patches:
      jgowdy-wait-6-22-2012.diff (license #5621) patch uploaded by Jeremiah Gowdy
      Expanded patch to add support in chan_dahdi.
Tested by: rmudgett


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@374030 65c4cc65-6c06-0410-ace0-fbb531ad65f3
changes/78/78/1
Richard Mudgett 13 years ago
parent 89d427ca24
commit b5138fccf4

@ -32,6 +32,23 @@ Queue:
- Queue logging for PAUSEALL/UNPAUSEALL now only occurs if the interface this is - Queue logging for PAUSEALL/UNPAUSEALL now only occurs if the interface this is
performed on is a member of at least one queue. performed on is a member of at least one queue.
Dial:
- Now recognizes 'W' to pause sending DTMF for one second in addition to
the previously existing 'w' that paused sending DTMF for half a second.
ExternalIVR:
- Now recognizes 'W' to pause sending DTMF for one second in addition to
the previously existing 'w' that paused sending DTMF for half a second.
SendDTMF:
- Now recognizes 'W' to pause sending DTMF for one second in addition to
the previously existing 'w' that paused sending DTMF for half a second.
chan_dahdi:
- Analog port dialing and deferred DTMF dialing for PRI now distinguishes
between 'w' and 'W'. The 'w' pauses dialing for half a second. The 'W'
pauses dialing for one second.
From 10 to 11: From 10 to 11:
Voicemail: Voicemail:

@ -47,7 +47,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<syntax> <syntax>
<parameter name="digits" required="true"> <parameter name="digits" required="true">
<para>List of digits 0-9,*#,a-d,A-D to send also w for a half second pause, <para>List of digits 0-9,*#,a-d,A-D to send also w for a half second pause,
and f or F for a flash-hook if the channel supports W for a one second pause, and f or F for a flash-hook if the channel supports
flash-hook.</para> flash-hook.</para>
</parameter> </parameter>
<parameter name="timeout_ms" required="false"> <parameter name="timeout_ms" required="false">

@ -1738,6 +1738,60 @@ static int analogsub_to_dahdisub(enum analog_sub analogsub)
return index; return index;
} }
/*!
* \internal
* \brief Send a dial string to DAHDI.
* \since 12.0.0
*
* \param pvt DAHDI private pointer
* \param operation DAHDI dial operation to do to string
* \param dial_str Dial string to send
*
* \retval 0 on success.
* \retval non-zero on error.
*/
static int dahdi_dial_str(struct dahdi_pvt *pvt, int operation, const char *dial_str)
{
int res;
int offset;
const char *pos;
struct dahdi_dialoperation zo = {
.op = operation,
};
/* Convert the W's to ww. */
pos = dial_str;
for (offset = 0; offset < sizeof(zo.dialstr) - 1; ++offset) {
if (!*pos) {
break;
}
if (*pos == 'W') {
/* Convert 'W' to "ww" */
++pos;
if (offset >= sizeof(zo.dialstr) - 3) {
/* No room to expand */
break;
}
zo.dialstr[offset] = 'w';
++offset;
zo.dialstr[offset] = 'w';
continue;
}
zo.dialstr[offset] = *pos++;
}
/* The zo initialization has already terminated the dialstr. */
ast_debug(1, "Channel %d: Dial str '%s' expanded to '%s' sent to DAHDI_DIAL.\n",
pvt->channel, dial_str, zo.dialstr);
res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
if (res) {
ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
pvt->channel, dial_str, strerror(errno));
}
return res;
}
static enum analog_event dahdievent_to_analogevent(int event); static enum analog_event dahdievent_to_analogevent(int event);
static int bump_gains(struct dahdi_pvt *p); static int bump_gains(struct dahdi_pvt *p);
static int dahdi_setlinear(int dfd, int linear); static int dahdi_setlinear(int dfd, int linear);
@ -2792,19 +2846,13 @@ static void my_pri_ss7_open_media(void *p)
*/ */
static void my_pri_dial_digits(void *p, const char *dial_string) static void my_pri_dial_digits(void *p, const char *dial_string)
{ {
struct dahdi_dialoperation zo = { char dial_str[DAHDI_MAX_DTMF_BUF];
.op = DAHDI_DIAL_OP_APPEND,
};
struct dahdi_pvt *pvt = p; struct dahdi_pvt *pvt = p;
int res; int res;
snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string); snprintf(dial_str, sizeof(dial_str), "T%s", dial_string);
ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr); res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo); if (!res) {
if (res) {
ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
pvt->channel, dial_string, strerror(errno));
} else {
pvt->dialing = 1; pvt->dialing = 1;
} }
} }
@ -3095,10 +3143,7 @@ static int my_start(void *pvt)
static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop) static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
{ {
int index = analogsub_to_dahdisub(sub);
int res;
struct dahdi_pvt *p = pvt; struct dahdi_pvt *p = pvt;
struct dahdi_dialoperation ddop;
if (dop->op != ANALOG_DIAL_OP_REPLACE) { if (dop->op != ANALOG_DIAL_OP_REPLACE) {
ast_log(LOG_ERROR, "Fix the dial_digits callback!\n"); ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
@ -3111,17 +3156,7 @@ static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoper
return -1; return -1;
} }
ddop.op = DAHDI_DIAL_OP_REPLACE; return dahdi_dial_str(p, DAHDI_DIAL_OP_REPLACE, dop->dialstr);
ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
if (res == -1) {
ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", ast_channel_name(p->owner), strerror(errno));
}
return res;
} }
static void dahdi_train_ec(struct dahdi_pvt *p); static void dahdi_train_ec(struct dahdi_pvt *p);
@ -4635,18 +4670,12 @@ static int dahdi_digit_begin(struct ast_channel *chan, char digit)
goto out; goto out;
if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
struct dahdi_dialoperation zo = { char dial_str[] = { 'T', digit, '\0' };
.op = DAHDI_DIAL_OP_APPEND,
};
zo.dialstr[0] = 'T'; res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
zo.dialstr[1] = digit; if (!res) {
zo.dialstr[2] = '\0';
if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
ast_channel_name(chan), digit, strerror(errno));
else
pvt->dialing = 1; pvt->dialing = 1;
}
} else { } else {
ast_debug(1, "Channel %s started VLDTMF digit '%c'\n", ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
ast_channel_name(chan), digit); ast_channel_name(chan), digit);
@ -8196,7 +8225,7 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
dahdi_train_ec(p); dahdi_train_ec(p);
ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
p->dop.op = DAHDI_DIAL_OP_REPLACE; p->dop.op = DAHDI_DIAL_OP_REPLACE;
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
p->echobreak = 0; p->echobreak = 0;
} else { } else {
p->dialing = 0; p->dialing = 0;
@ -8431,12 +8460,9 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
} else } else
p->echobreak = 0; p->echobreak = 0;
if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { if (dahdi_dial_str(p, p->dop.op, p->dop.dialstr)) {
int saveerr = errno;
x = DAHDI_ONHOOK; x = DAHDI_ONHOOK;
ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
return NULL; return NULL;
} }
p->dialing = 1; p->dialing = 1;
@ -8470,9 +8496,8 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
p->subs[idx].f.subclass.integer = 0; p->subs[idx].f.subclass.integer = 0;
} else if (!ast_strlen_zero(p->dop.dialstr)) { } else if (!ast_strlen_zero(p->dop.dialstr)) {
/* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
if (res < 0) { if (res) {
ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
p->dop.dialstr[0] = '\0'; p->dop.dialstr[0] = '\0';
return NULL; return NULL;
} else { } else {
@ -8843,9 +8868,8 @@ winkflashdone:
case SIG_EMWINK: case SIG_EMWINK:
/* FGD MF and EMWINK *Must* wait for wink */ /* FGD MF and EMWINK *Must* wait for wink */
if (!ast_strlen_zero(p->dop.dialstr)) { if (!ast_strlen_zero(p->dop.dialstr)) {
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
if (res < 0) { if (res) {
ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
p->dop.dialstr[0] = '\0'; p->dop.dialstr[0] = '\0';
return NULL; return NULL;
} else } else
@ -8873,9 +8897,8 @@ winkflashdone:
case SIG_SFWINK: case SIG_SFWINK:
case SIG_SF_FEATD: case SIG_SF_FEATD:
if (!ast_strlen_zero(p->dop.dialstr)) { if (!ast_strlen_zero(p->dop.dialstr)) {
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
if (res < 0) { if (res) {
ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
p->dop.dialstr[0] = '\0'; p->dop.dialstr[0] = '\0';
return NULL; return NULL;
} else } else
@ -9473,9 +9496,8 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast)
ast_dsp_set_features(p->dsp, p->dsp_features); ast_dsp_set_features(p->dsp, p->dsp_features);
ast_debug(1, "Got 10 samples of dialtone!\n"); ast_debug(1, "Got 10 samples of dialtone!\n");
if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */ if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
if (res < 0) { if (res) {
ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
p->dop.dialstr[0] = '\0'; p->dop.dialstr[0] = '\0';
ast_mutex_unlock(&p->lock); ast_mutex_unlock(&p->lock);
ast_frfree(f); ast_frfree(f);

@ -1257,10 +1257,7 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, const char *rdest
analog_set_waitingfordt(p, ast); analog_set_waitingfordt(p, ast);
if (!res) { if (!res) {
if (analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop)) { if (analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop)) {
int saveerr = errno;
analog_on_hook(p); analog_on_hook(p);
ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
return -1; return -1;
} }
} else { } else {
@ -2767,10 +2764,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
analog_train_echocanceller(p); analog_train_echocanceller(p);
ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
p->dop.op = ANALOG_DIAL_OP_REPLACE; p->dop.op = ANALOG_DIAL_OP_REPLACE;
if (analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop)) { analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop);
int dial_err = errno;
ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(dial_err));
}
p->echobreak = 0; p->echobreak = 0;
} else { } else {
analog_set_dialing(p, 0); analog_set_dialing(p, 0);
@ -2963,9 +2957,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
p->echobreak = 0; p->echobreak = 0;
} }
if (analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop)) { if (analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop)) {
int saveerr = errno;
analog_on_hook(p); analog_on_hook(p);
ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
return NULL; return NULL;
} }
analog_set_dialing(p, 1); analog_set_dialing(p, 1);
@ -2999,8 +2991,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
} else if (!ast_strlen_zero(p->dop.dialstr)) { } else if (!ast_strlen_zero(p->dop.dialstr)) {
/* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
res = analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop); res = analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop);
if (res < 0) { if (res) {
ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
p->dop.dialstr[0] = '\0'; p->dop.dialstr[0] = '\0';
return NULL; return NULL;
} else { } else {
@ -3409,8 +3400,7 @@ winkflashdone:
/* FGD MF and EMWINK *Must* wait for wink */ /* FGD MF and EMWINK *Must* wait for wink */
if (!ast_strlen_zero(p->dop.dialstr)) { if (!ast_strlen_zero(p->dop.dialstr)) {
res = analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop); res = analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop);
if (res < 0) { if (res) {
ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
p->dop.dialstr[0] = '\0'; p->dop.dialstr[0] = '\0';
return NULL; return NULL;
} else { } else {
@ -3441,8 +3431,7 @@ winkflashdone:
case ANALOG_SIG_SF_FEATD: case ANALOG_SIG_SF_FEATD:
if (!ast_strlen_zero(p->dop.dialstr)) { if (!ast_strlen_zero(p->dop.dialstr)) {
res = analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop); res = analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop);
if (res < 0) { if (res) {
ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
p->dop.dialstr[0] = '\0'; p->dop.dialstr[0] = '\0';
return NULL; return NULL;
} else { } else {

@ -757,6 +757,11 @@ int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const ch
if ((res = ast_safe_sleep(chan, 500))) { if ((res = ast_safe_sleep(chan, 500))) {
break; break;
} }
} else if (*ptr == 'W') {
/* 'W' -- wait a second */
if ((res = ast_safe_sleep(chan, 1000))) {
break;
}
} else if (strchr("0123456789*#abcdfABCDF", *ptr)) { } else if (strchr("0123456789*#abcdfABCDF", *ptr)) {
if (*ptr == 'f' || *ptr == 'F') { if (*ptr == 'f' || *ptr == 'F') {
/* ignore return values if not supported by channel */ /* ignore return values if not supported by channel */

Loading…
Cancel
Save