Skip to content

Commit 114631e

Browse files
committed
app_fsk: Fix several application correctness issues.
* Fix arguments being overwritten after parsing. * Fix Bell 103. We were using the originating frequencies for the sender and the terminating frequencies for the receiver, even though the frequencies should be originating on both sides. * Bell 202 now kind of works - most data comes through but some is corrupted. * Don't abort receiver if we haven't started sending yet and reduce false positives for FSK EOF. * Add leading mark tone for reliable synchronization. * Add trailing mark tone for reliable reception of last character.
1 parent 7f57305 commit 114631e

1 file changed

Lines changed: 123 additions & 52 deletions

File tree

apps/app_fsk.c

Lines changed: 123 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@
102102
<para>Name of modem protocol to use. Default is Bell 103.</para>
103103
<enumlist>
104104
<enum name="103">
105-
<para>Bell 103 modem (300 baud), terminating</para>
105+
<para>Bell 103 modem (300 baud), originating</para>
106106
</enum>
107107
<enum name="202">
108108
<para>Bell 202 modem (1200 baud)</para>
@@ -144,6 +144,7 @@ struct receive_buffer {
144144
int ptr;
145145
unsigned int quitoncarrierlost:1;
146146
unsigned int fsk_eof:1;
147+
unsigned int got_data:1;
147148
char *buffer;
148149
};
149150

@@ -168,26 +169,29 @@ static void rx_status(void *user_data, int status)
168169

169170
static void get_bit(void *user_data, int bit)
170171
{
172+
char c;
171173
struct receive_buffer *data = user_data;
172174
if (bit < 0) {
173175
rx_status(user_data, bit);
174176
return;
175177
}
176-
ast_debug(2, "Got '%c' on the stream\n", (char) bit & 0xff);
177-
*(data->buffer + data->ptr++) = (char) bit & 0xff;
178+
c = (char) bit & 0xff;
179+
data->got_data = 1;
180+
ast_debug(2, "Got %d '%c' on the stream\n", c, isprint(c) ? c : ' ');
181+
*(data->buffer + data->ptr++) = c;
178182
}
179183

180184
static int put_bit(struct transmit_buffer *user_data)
181185
{
182186
int8_t data;
183187

184188
if (user_data->ptr <= user_data->bytes2send) {
185-
if ((user_data->current_bit_no != 0) && (user_data->current_bit_no != 9)) {
186-
data = *((int8_t *)user_data->buffer + user_data->ptr) & (1 << (user_data->current_bit_no - 1));
187-
} else if (user_data->current_bit_no != 9) {
188-
data = 0;
189+
if (user_data->current_bit_no == 0) {
190+
data = 0; /* start bit */
191+
} else if (user_data->current_bit_no <= 8) {
192+
data = *((int8_t *) user_data->buffer + user_data->ptr) & (1 << (user_data->current_bit_no - 1));
189193
} else {
190-
data = 1;
194+
data = 1; /* stop bit */
191195
}
192196
++user_data->current_bit_no;
193197
if (user_data->current_bit_no == 10) {
@@ -214,9 +218,6 @@ static int fsk_tx_exec(struct ast_channel *chan, const char *data)
214218
.samples = BLOCK_LEN,
215219
.data.ptr = &caller_amp,
216220
};
217-
struct ast_format * native_format;
218-
unsigned int sampling_rate;
219-
struct ast_format * write_format;
220221
int samples;
221222
int modem;
222223
int res = 0;
@@ -226,10 +227,7 @@ static int fsk_tx_exec(struct ast_channel *chan, const char *data)
226227
AST_APP_ARG(data);
227228
);
228229

229-
native_format = ast_format_cap_get_format(ast_channel_nativeformats(chan), 0);
230-
sampling_rate = ast_format_get_sample_rate(native_format);
231-
write_format = ast_format_cache_get_slin_by_rate(sampling_rate);
232-
f.subclass.format = write_format;
230+
f.subclass.format = ast_format_slin;
233231

234232
if (ast_strlen_zero(data)) {
235233
ast_log(LOG_WARNING, "SendFSK requires an argument\n");
@@ -257,25 +255,49 @@ static int fsk_tx_exec(struct ast_channel *chan, const char *data)
257255

258256
ast_debug(1, "Modem channel is '%s'\n", preset_fsk_specs[modem].name);
259257

260-
out = ast_malloc(sizeof(*out));
258+
if ((res = ast_set_write_format(chan, ast_format_slin)) < 0) {
259+
ast_log(LOG_ERROR, "Unable to set channel to linear mode\n");
260+
return -1;
261+
}
262+
263+
out = ast_calloc(1, sizeof(*out));
261264
if (!out) {
262265
return -1;
263266
}
264267
out->buffer = arglist.data;
265268
out->bytes2send = strlen(arglist.data);
266-
out->current_bit_no = 0;
267-
out->ptr = 0;
268269

269270
memset(caller_amp, 0, sizeof(*caller_amp));
270271

271272
caller_tx = fsk_tx_init(NULL, &preset_fsk_specs[modem], (get_bit_func_t) &put_bit, out);
273+
if (!caller_tx) {
274+
ast_free(out);
275+
return -1;
276+
}
277+
278+
/* Send a few frames of mark tone first, to allow receiver to synchronize */
279+
for (samples = 0; samples < 7; samples++) {
280+
res = ast_waitfor(chan, -1);
281+
fr = ast_read(chan);
282+
if (!fr) {
283+
ast_debug(2, "User hung up\n");
284+
goto abort;
285+
}
286+
ast_frfree(fr);
287+
fsk_tx(caller_tx, caller_amp, BLOCK_LEN);
288+
if (ast_write(chan, &f) < 0) {
289+
ast_debug(1, "Failed to write mark tone\n");
290+
goto abort;
291+
}
292+
}
293+
294+
/* Send the payload */
272295
while (out->ptr < out->bytes2send) {
273296
res = ast_waitfor(chan, 1000);
274297
fr = ast_read(chan);
275298
if (!fr) {
276299
ast_debug(2, "User hung up\n");
277-
res = -1;
278-
break;
300+
goto abort;
279301
}
280302
if (fr->frametype == AST_FRAME_DTMF) {
281303
ast_debug(1, "User pressed a key\n");
@@ -284,23 +306,35 @@ static int fsk_tx_exec(struct ast_channel *chan, const char *data)
284306
samples = fsk_tx(caller_tx, caller_amp, BLOCK_LEN);
285307
if ((res = ast_write(chan, &f)) < 0) {
286308
ast_debug(1, "Failed to write %d samples\n", samples);
287-
res = -1;
288-
break;
309+
goto abort;
289310
}
290311
}
291-
memset(caller_amp, 0, sizeof(caller_amp));
292-
res = ast_waitfor(chan, -1);
293-
fr = ast_read(chan);
294-
if (!fr) {
295-
ast_debug(2, "User hung up\n");
296-
return -1;
297-
}
298-
ast_frfree(fr);
299-
if (ast_write(chan, &f) < 0) {
300-
res = -1;
312+
313+
/* Send a few extra frames of mark tone to allow receiver to reliably receive last bit of data */
314+
for (samples = 0; samples < 4; samples++) {
315+
res = ast_waitfor(chan, -1);
316+
fr = ast_read(chan);
317+
if (!fr) {
318+
ast_debug(2, "User hung up\n");
319+
goto abort;
320+
}
321+
ast_frfree(fr);
322+
fsk_tx(caller_tx, caller_amp, BLOCK_LEN);
323+
if (ast_write(chan, &f) < 0) {
324+
ast_debug(1, "Failed to write mark tone\n");
325+
goto abort;
326+
}
301327
}
328+
302329
ast_debug(1, "SendFSK Completed.\n");
330+
ast_free(out);
331+
fsk_tx_free(caller_tx);
303332
return 0;
333+
334+
abort:
335+
ast_free(out);
336+
fsk_tx_free(caller_tx);
337+
return -1;
304338
}
305339

306340
static int fsk_rx_exec(struct ast_channel *chan, const char *data)
@@ -315,6 +349,8 @@ static int fsk_rx_exec(struct ast_channel *chan, const char *data)
315349
int modem;
316350
int silence_flag = 0;
317351
int res = 0;
352+
int retries = 0;
353+
int eof_count = 0;
318354

319355
AST_DECLARE_APP_ARGS(arglist,
320356
AST_APP_ARG(variable);
@@ -340,10 +376,10 @@ static int fsk_rx_exec(struct ast_channel *chan, const char *data)
340376
}
341377
}
342378

343-
modem = FSK_BELL103CH2;
379+
modem = FSK_BELL103CH1;
344380
if (!ast_strlen_zero(arglist.modem)) {
345381
if (!strcmp(arglist.modem, "103")) {
346-
modem = FSK_BELL103CH2;
382+
modem = FSK_BELL103CH1;
347383
} else if (!strcmp(arglist.modem, "202")) {
348384
modem = FSK_BELL202;
349385
} else {
@@ -360,11 +396,13 @@ static int fsk_rx_exec(struct ast_channel *chan, const char *data)
360396
}
361397

362398
memset(output_frame, 0, sizeof(output_frame));
363-
in = ast_malloc(sizeof(*in));
399+
in = ast_calloc(1, sizeof(*in));
364400
if (!in) {
365401
return -1;
366402
}
367403

404+
in->quitoncarrierlost = 1;
405+
368406
if (!ast_strlen_zero(arglist.options)) {
369407
ast_app_parse_options(read_app_options, &flags, NULL, arglist.options);
370408
if (ast_test_flag(&flags, OPT_HANGOUT )) {
@@ -375,34 +413,59 @@ static int fsk_rx_exec(struct ast_channel *chan, const char *data)
375413
}
376414
}
377415

378-
in->fsk_eof = 0;
379-
in->quitoncarrierlost = 1;
380-
381416
in->buffer = ast_calloc(1, 65536); /* Reserve 64KB space for receive buffer. */
382417
if (!in->buffer) {
383418
ast_free(in);
384419
return -1;
385420
}
386-
387-
in->ptr = 0;
388-
389421
if (silence_flag) {
390422
silgen = ast_channel_start_silence_generator(chan);
391423
}
392424
caller_rx = fsk_rx_init(NULL, &preset_fsk_specs[modem], FSK_FRAME_MODE_8N1_FRAMES, get_bit, in);
425+
if (!caller_rx) {
426+
ast_free(in->buffer);
427+
ast_free(in);
428+
return -1;
429+
}
393430
fsk_rx_set_modem_status_handler(caller_rx, rx_status, (void *) in);
394431
while (ast_waitfor(chan, -1) > -1) {
395432
f = ast_read(chan);
396433
if (!f) {
397-
res = -1;
398-
break;
434+
ast_debug(1, "No more frames to read\n");
435+
goto done; /* Caller hung up immediately, but there might be data to read */
399436
}
400-
if (f->frametype == AST_FRAME_VOICE){
437+
if (f->frametype == AST_FRAME_VOICE) {
401438
fsk_rx(caller_rx, f->data.ptr, f->samples);
402439
}
403-
if (in->fsk_eof != 0) {
404-
ast_debug(1, "fsk_eof\n");
405-
break;
440+
if (in->fsk_eof) {
441+
if (!in->got_data) {
442+
/* Don't abort immediately if there's no carrier present yet,
443+
* the sender may not have started sending yet...
444+
* to a point, if we never get anything after a while (5 seconds), abort anyways. */
445+
if (++retries > 250) {
446+
ast_log(LOG_WARNING, "No FSK data received\n");
447+
ast_frfree(f);
448+
goto done; /* This is normal success */
449+
}
450+
ast_debug(4, "fsk_eof, but no data received yet, waiting...\n");
451+
eof_count = in->fsk_eof = 0; /* Reset */
452+
} else {
453+
eof_count++;
454+
ast_debug(3, "FSK eof count %d\n", eof_count);
455+
/* Require 2 carrier downs in a row to signify EOF
456+
* Note that rx_status only fires when receiving FSK audio,
457+
* but even if we really only get one carrier down,
458+
* this still works because the next loop iteration here,
459+
* fsk_eof will still be set true and we'll break,
460+
* i.e. SpanDSP telling us carrier down + next frame is not FSK. */
461+
if (eof_count > 1) {
462+
ast_debug(1, "FSK carrier seems to have dropped\n");
463+
ast_frfree(f);
464+
goto done; /* This is typically normal success */
465+
}
466+
}
467+
} else {
468+
eof_count = 0;
406469
}
407470
f->subclass.format = ast_format_slin;
408471
f->datalen = BLOCK_LEN;
@@ -411,24 +474,32 @@ static int fsk_rx_exec(struct ast_channel *chan, const char *data)
411474
f->src = __PRETTY_FUNCTION__;
412475
f->data.ptr = &output_frame;
413476
if (ast_write(chan, f) < 0) {
414-
res = -1;
477+
ast_debug(1, "No more frames to read\n");
415478
ast_frfree(f);
416-
break;
479+
goto abort;
417480
}
418-
ast_frfree(f);
419481
}
420482
if (!f) {
421483
ast_debug(1, "Got hangup\n");
422-
res = -1;
484+
goto abort;
423485
}
486+
487+
done:
424488
ast_debug(1, "received buffer is: %s\n", in->buffer);
425489
pbx_builtin_setvar_helper(chan, arglist.variable, in->buffer);
426-
ast_free(in->buffer);
427490
if (silgen) {
428491
ast_channel_stop_silence_generator(chan, silgen);
429492
}
493+
ast_free(in->buffer);
430494
ast_free(in);
495+
fsk_rx_free(caller_rx);
431496
return 0;
497+
498+
abort:
499+
ast_free(in->buffer);
500+
ast_free(in);
501+
fsk_rx_free(caller_rx);
502+
return -1;
432503
}
433504

434505
static int unload_module(void)

0 commit comments

Comments
 (0)