69
69
</parameter>
70
70
<parameter name="options">
71
71
<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>
72
79
<option name="t">
73
80
<para>Automatically play the appropriate tone depending on
74
81
the outcome of the test. If the dial is slow, the caller
118
125
<para>The break percentage of a dial.</para>
119
126
<para>Only set if the test is performed on an FXS channel using DAHDI.</para>
120
127
</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>
121
132
</variablelist>
122
133
</description>
123
134
</application>
124
135
***/
125
136
126
137
enum read_option_flags {
127
138
OPT_TONE = (1 << 0 ),
139
+ OPT_READJUSTMENT = (1 << 1 ),
140
+ OPT_DIAGNOSTICS = (1 << 2 ),
128
141
};
129
142
130
143
AST_APP_OPTIONS (dspeed_app_options , {
144
+ AST_APP_OPTION ('d' , OPT_DIAGNOSTICS ),
145
+ AST_APP_OPTION ('r' , OPT_READJUSTMENT ),
131
146
AST_APP_OPTION ('t' , OPT_TONE ),
132
147
});
133
148
134
149
static const char * dspeed_name = "DialSpeedTest" ;
135
150
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 )
137
152
{
138
153
struct ast_frame * frame = NULL ;
139
- struct timeval start ;
154
+ struct timeval start , lastpulse ;
140
155
int remaining_time = timeout ;
141
- int pulses_read = 0 , res = 0 ;
156
+ int res = 0 ;
142
157
struct timespec begin , end ;
143
158
144
159
start = ast_tvnow ();
@@ -149,6 +164,13 @@ static int dspeed_test(struct ast_channel *chan, int timeout)
149
164
if (remaining_time <= 0 ) {
150
165
break ;
151
166
}
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 ;
152
174
}
153
175
if (ast_waitfor (chan , 1000 ) > 0 ) {
154
176
frame = ast_read (chan );
@@ -157,11 +179,15 @@ static int dspeed_test(struct ast_channel *chan, int timeout)
157
179
res = -1 ;
158
180
break ;
159
181
} 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" );
161
184
begin = ast_tsnow (); /* start the pulse timer */
162
185
}
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 );
165
191
break ;
166
192
}
167
193
}
@@ -170,8 +196,7 @@ static int dspeed_test(struct ast_channel *chan, int timeout)
170
196
res = -1 ;
171
197
}
172
198
}
173
- if (pulses_read ) {
174
- end = ast_tsnow ();
199
+ if (* pulsecount ) {
175
200
res = ((end .tv_sec * 1000 + end .tv_nsec / 1000000 ) - (begin .tv_sec * 1000 + begin .tv_nsec / 1000000 ));
176
201
}
177
202
return res ;
@@ -182,7 +207,9 @@ static int dspeed_exec(struct ast_channel *chan, const char *data)
182
207
double tosec ;
183
208
struct ast_flags flags = {0 };
184
209
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 ;
186
213
187
214
AST_DECLARE_APP_ARGS (arglist ,
188
215
AST_APP_ARG (file );
@@ -196,9 +223,9 @@ static int dspeed_exec(struct ast_channel *chan, const char *data)
196
223
197
224
if (!ast_strlen_zero (arglist .options )) {
198
225
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 ;
202
229
}
203
230
if (!ast_strlen_zero (arglist .timeout )) {
204
231
tosec = atof (arglist .timeout );
@@ -238,7 +265,7 @@ static int dspeed_exec(struct ast_channel *chan, const char *data)
238
265
ast_streamfile (chan , file , ast_channel_language (chan ));
239
266
}
240
267
241
- res = dspeed_test (chan , to );
268
+ res = dspeed_test (chan , to , & pulsecount , diagnostics );
242
269
if (ast_strlen_zero (file )) {
243
270
ast_playtones_stop (chan );
244
271
} else {
@@ -250,14 +277,14 @@ static int dspeed_exec(struct ast_channel *chan, const char *data)
250
277
} else if (!res ) {
251
278
pbx_builtin_setvar_helper (chan , "DIALPULSERESULT" , "TIMEOUT" );
252
279
} else if (res > 0 ) {
253
- #define BUFFER_LEN 8
280
+ #define BUFFER_LEN 11
254
281
const char * result ;
255
282
char buf [BUFFER_LEN ];
256
283
double dialpps ;
257
284
struct ast_tone_zone_sound * ts = NULL ;
258
285
259
286
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 */
261
288
}
262
289
263
290
/*
@@ -276,17 +303,21 @@ static int dspeed_exec(struct ast_channel *chan, const char *data)
276
303
*
277
304
* So, whether it's 10 or 20 pps, x = 9000.
278
305
*/
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 );
281
309
pbx_builtin_setvar_helper (chan , "DIALPULSESPEED" , buf );
282
310
311
+ snprintf (buf , sizeof (buf ), "%d" , pulsecount );
312
+ pbx_builtin_setvar_helper (chan , "DIALPULSECOUNT" , buf );
313
+
283
314
/* 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 ) ) {
285
316
result = "SLOW" ;
286
317
if (tone ) {
287
318
ts = ast_get_indication_tone (ast_channel_zone (chan ), "busy" );
288
319
}
289
- } else if (dialpps > pps + 1 ) {
320
+ } else if (dialpps > ( pps + ( readjust ? 0.5 : 1 )) ) {
290
321
result = "FAST" ;
291
322
if (tone ) {
292
323
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)
301
332
}
302
333
}
303
334
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 );
305
336
pbx_builtin_setvar_helper (chan , "DIALPULSERESULT" , result );
306
337
307
338
#ifdef HAVE_DAHDI
@@ -341,9 +372,9 @@ static int dspeed_exec(struct ast_channel *chan, const char *data)
341
372
342
373
ast_verb (3 , "Dial make/break ratio is %.3f%% make, %.3f%% break\n" , makeratio , breakratio );
343
374
344
- snprintf (pct , 4 , "%d" , (int ) round (makeratio ));
375
+ snprintf (pct , sizeof ( pct ) , "%d" , (int ) round (makeratio ));
345
376
pbx_builtin_setvar_helper (chan , "DIALPULSEPERCENTMAKE" , pct );
346
- snprintf (pct , 4 , "%d" , (int ) round (breakratio ));
377
+ snprintf (pct , sizeof ( pct ) , "%d" , (int ) round (breakratio ));
347
378
pbx_builtin_setvar_helper (chan , "DIALPULSEPERCENTBREAK" , pct );
348
379
} else {
349
380
ast_log (LOG_WARNING , "No make/break ratio information available\n" );
0 commit comments