Skip to content

Commit bab4354

Browse files
committed
res_dialpulse: Add debugging mode to DialSpeedTest.
Currently, DialSpeedTest expects a full 10 pps to measure pulse timings. However, it can be desirable to measure pulse timing without receiving a full 10 pulses, e.g. for Sangoma cards using wanpipe, which messes up hook timings and usually yields fewer than 10 pulses. In this case, do the best we can and stop the test automatically, even if 10 pulses have not been received.
1 parent baf1693 commit bab4354

File tree

1 file changed

+53
-22
lines changed

1 file changed

+53
-22
lines changed

res/res_dialpulse.c

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@
6969
</parameter>
7070
<parameter name="options">
7171
<optionlist>
72+
<option name="d">
73+
<para>Diagnostics mode. This will not wait for 10 pulses,
74+
but only until pulses are no longer detected, and then
75+
report the number of pulses and other statistics.</para>
76+
<para>Useful if you are troubleshooting faulty dials
77+
or known-good dials with faulty equipment.</para>
78+
</option>
7279
<option name="t">
7380
<para>Automatically play the appropriate tone depending on
7481
the outcome of the test. If the dial is slow, the caller
@@ -118,27 +125,35 @@
118125
<para>The break percentage of a dial.</para>
119126
<para>Only set if the test is performed on an FXS channel using DAHDI.</para>
120127
</variable>
128+
<variable name="DIALPULSECOUNT">
129+
<para>The actual number of dial pulses received during the test.</para>
130+
<para>Normally this will be 10, but may be fewer if running in diagnostics mode.</para>
131+
</variable>
121132
</variablelist>
122133
</description>
123134
</application>
124135
***/
125136

126137
enum read_option_flags {
127138
OPT_TONE = (1 << 0),
139+
OPT_READJUSTMENT = (1 << 1),
140+
OPT_DIAGNOSTICS = (1 << 2),
128141
};
129142

130143
AST_APP_OPTIONS(dspeed_app_options, {
144+
AST_APP_OPTION('d', OPT_DIAGNOSTICS),
145+
AST_APP_OPTION('r', OPT_READJUSTMENT),
131146
AST_APP_OPTION('t', OPT_TONE),
132147
});
133148

134149
static const char *dspeed_name = "DialSpeedTest";
135150

136-
static int dspeed_test(struct ast_channel *chan, int timeout)
151+
static int dspeed_test(struct ast_channel *chan, int timeout, int *restrict pulsecount, int diagnostics)
137152
{
138153
struct ast_frame *frame = NULL;
139-
struct timeval start;
154+
struct timeval start, lastpulse;
140155
int remaining_time = timeout;
141-
int pulses_read = 0, res = 0;
156+
int res = 0;
142157
struct timespec begin, end;
143158

144159
start = ast_tvnow();
@@ -149,6 +164,13 @@ static int dspeed_test(struct ast_channel *chan, int timeout)
149164
if (remaining_time <= 0) {
150165
break;
151166
}
167+
} else if (diagnostics && *pulsecount > 1 && ast_remaining_ms(lastpulse, 800) <= 0) {
168+
/* 800 milliseconds since we received the last dial pulse...
169+
* safe to say that there probably aren't more coming, stop the test.
170+
* We need at least 2 dial pulses to measure any sort of timings,
171+
* so don't stop after just 1. */
172+
ast_verb(5, "Dial pulse test timed out (%d pulses received)\n", *pulsecount);
173+
break;
152174
}
153175
if (ast_waitfor(chan, 1000) > 0) {
154176
frame = ast_read(chan);
@@ -157,11 +179,15 @@ static int dspeed_test(struct ast_channel *chan, int timeout)
157179
res = -1;
158180
break;
159181
} else if (frame->frametype == AST_FRAME_CONTROL && frame->subclass.integer == AST_CONTROL_PULSE) {
160-
if (++pulses_read == 1) {
182+
if (++(*pulsecount) == 1) {
183+
ast_debug(3, "Starting pulse timer now\n");
161184
begin = ast_tsnow(); /* start the pulse timer */
162185
}
163-
ast_debug(2, "Dial pulse speed test: pulse %d\n", pulses_read);
164-
if (pulses_read == 10) {
186+
ast_debug(2, "Dial pulse speed test: pulse %d\n", *pulsecount);
187+
end = ast_tsnow();
188+
lastpulse = ast_tvnow();
189+
if (*pulsecount == 10) {
190+
ast_frfree(frame);
165191
break;
166192
}
167193
}
@@ -170,8 +196,7 @@ static int dspeed_test(struct ast_channel *chan, int timeout)
170196
res = -1;
171197
}
172198
}
173-
if (pulses_read) {
174-
end = ast_tsnow();
199+
if (*pulsecount) {
175200
res = ((end.tv_sec * 1000 + end.tv_nsec / 1000000) - (begin.tv_sec * 1000 + begin.tv_nsec / 1000000));
176201
}
177202
return res;
@@ -182,7 +207,9 @@ static int dspeed_exec(struct ast_channel *chan, const char *data)
182207
double tosec;
183208
struct ast_flags flags = {0};
184209
char *file = NULL, *argcopy = NULL;
185-
int res, to = 0, pps = 0, tone = 0;
210+
int tone = 0, readjust = 0, diagnostics = 0;
211+
int res, to = 0, pps = 0;
212+
int pulsecount = 0;
186213

187214
AST_DECLARE_APP_ARGS(arglist,
188215
AST_APP_ARG(file);
@@ -196,9 +223,9 @@ static int dspeed_exec(struct ast_channel *chan, const char *data)
196223

197224
if (!ast_strlen_zero(arglist.options)) {
198225
ast_app_parse_options(dspeed_app_options, &flags, NULL, arglist.options);
199-
if (ast_test_flag(&flags, OPT_TONE)) {
200-
tone = 1;
201-
}
226+
tone = ast_test_flag(&flags, OPT_TONE) ? 1 : 0;
227+
readjust = ast_test_flag(&flags, OPT_READJUSTMENT) ? 1 : 0;
228+
diagnostics = ast_test_flag(&flags, OPT_DIAGNOSTICS) ? 1 : 0;
202229
}
203230
if (!ast_strlen_zero(arglist.timeout)) {
204231
tosec = atof(arglist.timeout);
@@ -238,7 +265,7 @@ static int dspeed_exec(struct ast_channel *chan, const char *data)
238265
ast_streamfile(chan, file, ast_channel_language(chan));
239266
}
240267

241-
res = dspeed_test(chan, to);
268+
res = dspeed_test(chan, to, &pulsecount, diagnostics);
242269
if (ast_strlen_zero(file)) {
243270
ast_playtones_stop(chan);
244271
} else {
@@ -250,14 +277,14 @@ static int dspeed_exec(struct ast_channel *chan, const char *data)
250277
} else if (!res) {
251278
pbx_builtin_setvar_helper(chan, "DIALPULSERESULT", "TIMEOUT");
252279
} else if (res > 0) {
253-
#define BUFFER_LEN 8
280+
#define BUFFER_LEN 11
254281
const char *result;
255282
char buf[BUFFER_LEN];
256283
double dialpps;
257284
struct ast_tone_zone_sound *ts = NULL;
258285

259286
if (!pps) { /* try to determine whether this is a 10 pps or 20 pps dial */
260-
pps = res < 650 ? 20 : 10; /* if it took less than 650 ms for 10 pulses, assume it's a 20 pps dial */
287+
pps = res < 650 && pulsecount == 10 ? 20 : 10; /* if it took less than 650 ms for 10 pulses, assume it's a 20 pps dial */
261288
}
262289

263290
/*
@@ -276,17 +303,21 @@ static int dspeed_exec(struct ast_channel *chan, const char *data)
276303
*
277304
* So, whether it's 10 or 20 pps, x = 9000.
278305
*/
279-
dialpps = 9000.0 / res; /* 10 pps = (10000 - 1000) / elapsed time */
280-
snprintf(buf, BUFFER_LEN, "%.3f", dialpps);
306+
dialpps = (1000.0 * (pulsecount - 1)) / res; /* 10 pps = (10000 - 1000) / elapsed time */
307+
ast_debug(3, "pulsecount: %d, dialpps = %f/%d\n", pulsecount, (1000.0 * (pulsecount - 1)), res);
308+
snprintf(buf, sizeof(buf), "%.3f", dialpps);
281309
pbx_builtin_setvar_helper(chan, "DIALPULSESPEED", buf);
282310

311+
snprintf(buf, sizeof(buf), "%d", pulsecount);
312+
pbx_builtin_setvar_helper(chan, "DIALPULSECOUNT", buf);
313+
283314
/* These timings (8-11 and 9.5-10.5, for 10pps dials) are found in a number of telephone documents. */
284-
if (dialpps < pps - 2) {
315+
if (dialpps < pps - (readjust ? 0.5 : 2)) {
285316
result = "SLOW";
286317
if (tone) {
287318
ts = ast_get_indication_tone(ast_channel_zone(chan), "busy");
288319
}
289-
} else if (dialpps > pps + 1) {
320+
} else if (dialpps > (pps + (readjust ? 0.5 : 1))) {
290321
result = "FAST";
291322
if (tone) {
292323
ts = ast_get_indication_tone(ast_channel_zone(chan), "congestion");
@@ -301,7 +332,7 @@ static int dspeed_exec(struct ast_channel *chan, const char *data)
301332
}
302333
}
303334

304-
ast_verb(3, "Dial speed was %.3f pps (%s) (took %d ms for %d pps test)", dialpps, result, res, pps);
335+
ast_verb(3, "Dial speed was %.3f pps (%s) (took %d ms for %d pps test, %d pulses)", dialpps, result, res, pps, pulsecount);
305336
pbx_builtin_setvar_helper(chan, "DIALPULSERESULT", result);
306337

307338
#ifdef HAVE_DAHDI
@@ -341,9 +372,9 @@ static int dspeed_exec(struct ast_channel *chan, const char *data)
341372

342373
ast_verb(3, "Dial make/break ratio is %.3f%% make, %.3f%% break\n", makeratio, breakratio);
343374

344-
snprintf(pct, 4, "%d", (int) round(makeratio));
375+
snprintf(pct, sizeof(pct), "%d", (int) round(makeratio));
345376
pbx_builtin_setvar_helper(chan, "DIALPULSEPERCENTMAKE", pct);
346-
snprintf(pct, 4, "%d", (int) round(breakratio));
377+
snprintf(pct, sizeof(pct), "%d", (int) round(breakratio));
347378
pbx_builtin_setvar_helper(chan, "DIALPULSEPERCENTBREAK", pct);
348379
} else {
349380
ast_log(LOG_WARNING, "No make/break ratio information available\n");

0 commit comments

Comments
 (0)