comparison spandsp-0.0.6pre17/tests/t31_tests.c @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
comparison
equal deleted inserted replaced
3:c6c5a16ce2f2 4:26cd8f1ef0b1
1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * t31_tests.c - Tests for the T.31 modem.
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2004 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2, as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * $Id: t31_tests.c,v 1.72 2009/05/30 15:23:14 steveu Exp $
26 */
27
28 /*! \file */
29
30 /*! \page t31_tests_page T.31 tests
31 \section t31_tests_page_sec_1 What does it do?
32 */
33
34 /* Enable the following definition to enable direct probing into the FAX structures */
35 //#define WITH_SPANDSP_INTERNALS
36
37 #if defined(HAVE_CONFIG_H)
38 #include "config.h"
39 #endif
40
41 #if defined(HAVE_FL_FL_H) && defined(HAVE_FL_FL_CARTESIAN_H) && defined(HAVE_FL_FL_AUDIO_METER_H)
42 #define ENABLE_GUI
43 #endif
44
45 #include <stdlib.h>
46 #include <stdio.h>
47 #include <fcntl.h>
48 #include <unistd.h>
49 #include <string.h>
50 #include <assert.h>
51 #include <sndfile.h>
52
53 //#if defined(WITH_SPANDSP_INTERNALS)
54 #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
55 //#endif
56
57 #include "spandsp.h"
58 #include "spandsp/t30_fcf.h"
59 #include "spandsp-sim.h"
60
61 #if defined(ENABLE_GUI)
62 #include "media_monitor.h"
63 #endif
64 #include "fax_utils.h"
65
66 #define INPUT_FILE_NAME "../test-data/itu/fax/itu1.tif"
67 #define OUTPUT_FILE_NAME "t31.tif"
68 #define OUTPUT_WAVE_FILE_NAME "t31_tests.wav"
69
70 enum
71 {
72 ETX = 0x03,
73 DLE = 0x10,
74 SUB = 0x1A
75 };
76
77 #define MANUFACTURER "www.soft-switch.org"
78
79 #define SAMPLES_PER_CHUNK 160
80
81 struct command_response_s
82 {
83 const char *command;
84 int len_command;
85 const char *response;
86 int len_response;
87 };
88
89 g1050_state_t *path_a_to_b;
90 g1050_state_t *path_b_to_a;
91
92 double when = 0.0;
93
94 #define EXCHANGE(a,b) {a, sizeof(a) - 1, b, sizeof(b) - 1}
95 #define RESPONSE(b) {"", 0, b, sizeof(b) - 1}
96 #define FAST_RESPONSE(b) {NULL, -1, b, sizeof(b) - 1}
97 #define FAST_SEND(b) {(const char *) 1, -2, b, sizeof(b) - 1}
98 #define FAST_SEND_TCF(b) {(const char *) 2, -2, b, sizeof(b) - 1}
99
100 static const struct command_response_s fax_send_test_seq[] =
101 {
102 EXCHANGE("ATE0\r", "ATE0\r\r\nOK\r\n"),
103 EXCHANGE("AT+FCLASS=1\r", "\r\nOK\r\n"),
104 EXCHANGE("ATD123456789\r", "\r\nCONNECT\r\n"),
105 //<NSF frame> AT+FRH=3 is implied when dialing in the AT+FCLASS=1 state
106 //RESPONSE("\xFF\x03\x10\x03"),
107 //RESPONSE("\r\nOK\r\n"),
108 //EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"),
109 //<CSI frame data>
110 RESPONSE("\xFF\x03\x40\x31\x31\x31\x31\x31\x31\x31\x31\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x1e\x46\x10\x03"),
111 RESPONSE("\r\nOK\r\n"),
112 EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"),
113 //<DIS frame data>
114 RESPONSE("\xFF\x13\x80\x00\xEE\xF8\x80\x80\x91\x80\x80\x80\x18\x78\x57\x10\x03"), // For audio FAXing
115 //RESPONSE("\xFF\x13\x80\x04\xEE\xF8\x80\x80\x91\x80\x80\x80\x18\xE4\xE7\x10\x03"), // For T.38 FAXing
116 RESPONSE("\r\nOK\r\n"),
117 //EXCHANGE("AT+FRH=3\r", "\r\nNO CARRIER\r\n"),
118 EXCHANGE("AT+FTH=3\r", "\r\nCONNECT\r\n"),
119 //<TSI frame data>
120 EXCHANGE("\xFF\x03\x43\x32\x32\x32\x32\x32\x32\x32\x32\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x10\x03", "\r\nCONNECT\r\n"),
121 //<DCS frame data>
122 EXCHANGE("\xFF\x13\x83\x01\xC6\x80\x80\x80\x80\x01\xFD\x13\x10\x03", "\r\nOK\r\n"),
123 //Do a wait for timed silence at this point, or there won't be one in the tests
124 EXCHANGE("AT+FRS=7\r", "\r\nOK\r\n"),
125 //EXCHANGE("AT+FTS=8;+FTM=96\r", "\r\nCONNECT\r\n"),
126 EXCHANGE("AT+FTS=8\r", "\r\nOK\r\n"),
127 EXCHANGE("AT+FTM=96\r", "\r\nCONNECT\r\n"),
128 //<TCF data pattern>
129 FAST_SEND_TCF("\r\nOK\r\n"),
130 EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"),
131 //<CFR frame data>
132 RESPONSE("\xFF\x13\x84\xEA\x7D\x10\x03"),
133 RESPONSE("\r\nOK\r\n"),
134 EXCHANGE("AT+FTM=96\r", "\r\nCONNECT\r\n"),
135 //<page image data>
136 FAST_SEND("\r\nOK\r\n"),
137 //EXCHANGE("AT+FTS=8;+FTH=3\r", "\r\nCONNECT\r\n"),
138 EXCHANGE("AT+FTS=8\r", "\r\nOK\r\n"),
139 EXCHANGE("AT+FTH=3\r", "\r\nCONNECT\r\n"),
140 //<EOP frame data>
141 EXCHANGE("\xFF\x13\x2E\x10\x03", "\r\nOK\r\n"),
142 EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"),
143 //<MCF frame data>
144 RESPONSE("\xFF\x13\x8C\xA2\xF1\x10\x03"),
145 RESPONSE("\r\nOK\r\n"),
146 EXCHANGE("AT+FTH=3\r", "\r\nCONNECT\r\n"),
147 // <DCN frame data>
148 EXCHANGE("\xFF\x13\xFB\x10\x03", "\r\nOK\r\n"),
149 EXCHANGE("ATH0\r", "\r\nOK\r\n")
150 };
151
152 static const struct command_response_s fax_receive_test_seq[] =
153 {
154 EXCHANGE("ATE0\r", "ATE0\r\r\nOK\r\n"),
155 EXCHANGE("AT+FCLASS=1\r", "\r\nOK\r\n"),
156 RESPONSE("\r\nRING\r\n"),
157 EXCHANGE("ATA\r", "\r\nCONNECT\r\n"),
158 //<CSI frame data>
159 EXCHANGE("\xFF\x03\x40\x32\x32\x32\x32\x32\x32\x32\x32\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x10\x03", "\r\nCONNECT\r\n"),
160 //<DIS frame data>
161 EXCHANGE("\xFF\x13\x80\x01\xCE\xF4\x80\x80\x81\x80\x80\x80\x18\x10\x03", "\r\nOK\r\n"),
162 EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"),
163 //<TSI frame data>
164 RESPONSE("\xFF\x03\x43\x31\x31\x31\x31\x31\x31\x31\x31\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\xAA\x1F\x10\x03"),
165 RESPONSE("\r\nOK\r\n"),
166 EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"),
167 //<DCS frame data>
168 RESPONSE("\xFF\x13\x83\x00\xC6\x74\x53\x00\x10\x03"),
169 RESPONSE("\r\nOK\r\n"),
170 EXCHANGE("AT+FRM=96\r", "\r\nCONNECT\r\n"),
171 //<TCF data>
172 FAST_RESPONSE(NULL),
173 RESPONSE("\r\nNO CARRIER\r\n"),
174 EXCHANGE("AT+FTH=3\r", "\r\nCONNECT\r\n"),
175 //<CFR frame data>
176 EXCHANGE("\xFF\x13\x84\x10\x03", "\r\nOK\r\n"),
177 EXCHANGE("AT+FRM=96\r", "\r\nCONNECT\r\n"),
178 //<page image data>
179 FAST_RESPONSE(NULL),
180 RESPONSE("\r\nNO CARRIER\r\n"),
181 EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"),
182 //<EOP frame data>
183 RESPONSE("\xFF\x13\x2F\x33\x66\x10\x03"),
184 RESPONSE("\r\nOK\r\n"),
185 EXCHANGE("AT+FTH=3\r", "\r\nCONNECT\r\n"),
186 //<MCF frame data>
187 EXCHANGE("\xFF\x13\x8C\x10\x03", "\r\nOK\r\n"),
188 EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"),
189 //<DCN frame data>
190 RESPONSE("\xFF\x13\xfb\x9a\xf6\x10\x03"),
191 RESPONSE("\r\nOK\r\n"),
192 EXCHANGE("ATH0\r", "\r\nOK\r\n")
193 };
194
195 char *decode_test_file = NULL;
196 int countdown = 0;
197 int command_response_test_step = -1;
198 char response_buf[1000];
199 int response_buf_ptr = 0;
200 int answered = FALSE;
201 int kick = FALSE;
202 int dled = FALSE;
203 int done = FALSE;
204
205 static const struct command_response_s *fax_test_seq;
206
207 int test_seq_ptr = 0;
208
209 t31_state_t *t31_state;
210
211 static int phase_b_handler(t30_state_t *s, void *user_data, int result)
212 {
213 int i;
214 char tag[20];
215
216 i = (int) (intptr_t) user_data;
217 snprintf(tag, sizeof(tag), "%c: Phase B:", i);
218 printf("%c: Phase B handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
219 log_rx_parameters(s, tag);
220 return T30_ERR_OK;
221 }
222 /*- End of function --------------------------------------------------------*/
223
224 static int phase_d_handler(t30_state_t *s, void *user_data, int result)
225 {
226 int i;
227 char tag[20];
228
229 i = (int) (intptr_t) user_data;
230 snprintf(tag, sizeof(tag), "%c: Phase D:", i);
231 printf("%c: Phase D handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
232 log_transfer_statistics(s, tag);
233 log_tx_parameters(s, tag);
234 log_rx_parameters(s, tag);
235 return T30_ERR_OK;
236 }
237 /*- End of function --------------------------------------------------------*/
238
239 static void phase_e_handler(t30_state_t *s, void *user_data, int result)
240 {
241 int i;
242 char tag[20];
243
244 i = (intptr_t) user_data;
245 snprintf(tag, sizeof(tag), "%c: Phase E:", i);
246 printf("Phase E handler on channel %c\n", i);
247 log_transfer_statistics(s, tag);
248 log_tx_parameters(s, tag);
249 log_rx_parameters(s, tag);
250 //exit(0);
251 }
252 /*- End of function --------------------------------------------------------*/
253
254 static int modem_call_control(t31_state_t *s, void *user_data, int op, const char *num)
255 {
256 switch (op)
257 {
258 case AT_MODEM_CONTROL_ANSWER:
259 printf("\nModem control - Answering\n");
260 answered = TRUE;
261 break;
262 case AT_MODEM_CONTROL_CALL:
263 printf("\nModem control - Dialing '%s'\n", num);
264 t31_call_event(t31_state, AT_CALL_EVENT_CONNECTED);
265 break;
266 case AT_MODEM_CONTROL_HANGUP:
267 printf("\nModem control - Hanging up\n");
268 done = TRUE;
269 break;
270 case AT_MODEM_CONTROL_OFFHOOK:
271 printf("\nModem control - Going off hook\n");
272 break;
273 case AT_MODEM_CONTROL_DTR:
274 printf("\nModem control - DTR %d\n", (int) (intptr_t) num);
275 break;
276 case AT_MODEM_CONTROL_RTS:
277 printf("\nModem control - RTS %d\n", (int) (intptr_t) num);
278 break;
279 case AT_MODEM_CONTROL_CTS:
280 printf("\nModem control - CTS %d\n", (int) (intptr_t) num);
281 break;
282 case AT_MODEM_CONTROL_CAR:
283 printf("\nModem control - CAR %d\n", (int) (intptr_t) num);
284 break;
285 case AT_MODEM_CONTROL_RNG:
286 printf("\nModem control - RNG %d\n", (int) (intptr_t) num);
287 break;
288 case AT_MODEM_CONTROL_DSR:
289 printf("\nModem control - DSR %d\n", (int) (intptr_t) num);
290 break;
291 default:
292 printf("\nModem control - operation %d\n", op);
293 break;
294 }
295 /*endswitch*/
296 return 0;
297 }
298 /*- End of function --------------------------------------------------------*/
299
300 static int at_tx_handler(at_state_t *s, void *user_data, const uint8_t *buf, size_t len)
301 {
302 size_t i;
303
304 i = 0;
305 if (fax_test_seq[test_seq_ptr].command == NULL)
306 {
307 /* TCF or non-ECM image data expected */
308 for ( ; i < len; i++)
309 {
310 if (dled)
311 {
312 if (buf[i] == ETX)
313 {
314 printf("\nFast data ended\n");
315 response_buf_ptr = 0;
316 response_buf[response_buf_ptr] = '\0';
317 test_seq_ptr++;
318 if (fax_test_seq[test_seq_ptr].command)
319 kick = TRUE;
320 break;
321 }
322 dled = FALSE;
323 }
324 else
325 {
326 if (buf[i] == DLE)
327 dled = TRUE;
328 }
329 }
330 i++;
331 if (i >= len)
332 return 0;
333 }
334 for ( ; i < len; i++)
335 {
336 response_buf[response_buf_ptr++] = buf[i];
337 putchar(buf[i]);
338 }
339 response_buf[response_buf_ptr] = '\0';
340 printf("Expected ");
341 for (i = 0; i < response_buf_ptr; i++)
342 printf("%02x ", fax_test_seq[test_seq_ptr].response[i] & 0xFF);
343 printf("\n");
344 printf("Response ");
345 for (i = 0; i < response_buf_ptr; i++)
346 printf("%02x ", response_buf[i] & 0xFF);
347 printf("\n");
348 printf("Match %d against %d\n", response_buf_ptr, fax_test_seq[test_seq_ptr].len_response);
349 if (response_buf_ptr >= fax_test_seq[test_seq_ptr].len_response
350 &&
351 memcmp(fax_test_seq[test_seq_ptr].response, response_buf, fax_test_seq[test_seq_ptr].len_response) == 0)
352 {
353 printf("\nMatched\n");
354 test_seq_ptr++;
355 response_buf_ptr = 0;
356 response_buf[response_buf_ptr] = '\0';
357 if (fax_test_seq[test_seq_ptr].command)
358 kick = TRUE;
359 else
360 dled = FALSE;
361 }
362 return 0;
363 }
364 /*- End of function --------------------------------------------------------*/
365
366 static int t38_tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count)
367 {
368 t31_state_t *t;
369 int i;
370
371 /* This routine queues messages between two instances of T.38 processing */
372 t = (t31_state_t *) user_data;
373 span_log(&s->logging, SPAN_LOG_FLOW, "Send seq %d, len %d, count %d\n", s->tx_seq_no, len, count);
374
375 for (i = 0; i < count; i++)
376 {
377 if (g1050_put(path_a_to_b, buf, len, s->tx_seq_no, when) < 0)
378 printf("Lost packet %d\n", s->tx_seq_no);
379 }
380 return 0;
381 }
382 /*- End of function --------------------------------------------------------*/
383
384 static int t31_tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count)
385 {
386 //t38_terminal_state_t *t;
387 int i;
388
389 /* This routine queues messages between two instances of T.38 processing */
390 //t = (t38_terminal_state_t *) user_data;
391 span_log(&s->logging, SPAN_LOG_FLOW, "Send seq %d, len %d, count %d\n", s->tx_seq_no, len, count);
392
393 for (i = 0; i < count; i++)
394 {
395 if (g1050_put(path_b_to_a, buf, len, s->tx_seq_no, when) < 0)
396 printf("Lost packet %d\n", s->tx_seq_no);
397 }
398 return 0;
399 }
400 /*- End of function --------------------------------------------------------*/
401
402 static int t38_tests(int use_gui, int test_sending, int model_no, int speed_pattern_no)
403 {
404 t38_terminal_state_t *t38_state;
405 int fast_send;
406 int fast_send_tcf;
407 int fast_blocks;
408 uint8_t fast_buf[1000];
409 int msg_len;
410 uint8_t msg[1024];
411 int t38_version;
412 int without_pacing;
413 int use_tep;
414 int seq_no;
415 double tx_when;
416 double rx_when;
417 t30_state_t *t30;
418 t38_core_state_t *t38_core;
419 logging_state_t *logging;
420 int i;
421
422 t38_version = 1;
423 without_pacing = FALSE;
424 use_tep = FALSE;
425
426 srand48(0x1234567);
427 if ((path_a_to_b = g1050_init(model_no, speed_pattern_no, 100, 33)) == NULL)
428 {
429 fprintf(stderr, "Failed to start IP network path model\n");
430 exit(2);
431 }
432 if ((path_b_to_a = g1050_init(model_no, speed_pattern_no, 100, 33)) == NULL)
433 {
434 fprintf(stderr, "Failed to start IP network path model\n");
435 exit(2);
436 }
437 if ((t31_state = t31_init(NULL, at_tx_handler, NULL, modem_call_control, NULL, t31_tx_packet_handler, NULL)) == NULL)
438 {
439 fprintf(stderr, " Cannot start the T.31 T.38 modem\n");
440 exit(2);
441 }
442 logging = t31_get_logging_state(t31_state);
443 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
444 span_log_set_tag(logging, "T.31");
445
446 t38_core = t31_get_t38_core_state(t31_state);
447 span_log_set_level(&t38_core->logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
448 span_log_set_tag(&t38_core->logging, "T.31");
449
450 span_log_set_level(&t31_state->at_state.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
451 span_log_set_tag(&t31_state->at_state.logging, "T.31");
452
453 t31_set_mode(t31_state, TRUE);
454 t38_set_t38_version(t38_core, t38_version);
455
456 if (test_sending)
457 {
458 if ((t38_state = t38_terminal_init(NULL, FALSE, t38_tx_packet_handler, t31_state)) == NULL)
459 {
460 fprintf(stderr, "Cannot start the T.38 channel\n");
461 exit(2);
462 }
463 t30 = t38_terminal_get_t30_state(t38_state);
464 t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1);
465 fax_test_seq = fax_send_test_seq;
466 countdown = 0;
467 }
468 else
469 {
470 if ((t38_state = t38_terminal_init(NULL, TRUE, t38_tx_packet_handler, t31_state)) == NULL)
471 {
472 fprintf(stderr, "Cannot start the T.38 channel\n");
473 exit(2);
474 }
475 t30 = t38_terminal_get_t30_state(t38_state);
476 t30_set_tx_file(t30, INPUT_FILE_NAME, -1, -1);
477 fax_test_seq = fax_receive_test_seq;
478 countdown = 250;
479 }
480
481 t30 = t38_terminal_get_t30_state(t38_state);
482 t38_core = t38_terminal_get_t38_core_state(t38_state);
483 t38_set_t38_version(t38_core, t38_version);
484 t38_terminal_set_config(t38_state, without_pacing);
485 t38_terminal_set_tep_mode(t38_state, use_tep);
486
487 t30_set_tx_ident(t30, "11111111");
488 t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17);
489 //t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
490 t30_set_phase_b_handler(t30, phase_b_handler, (void *) 'A');
491 t30_set_phase_d_handler(t30, phase_d_handler, (void *) 'A');
492 t30_set_phase_e_handler(t30, phase_e_handler, (void *) 'A');
493
494 logging = t38_terminal_get_logging_state(t38_state);
495 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
496 span_log_set_tag(logging, "T.38");
497
498 t38_core = t38_terminal_get_t38_core_state(t38_state);
499 span_log_set_level(&t38_core->logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
500 span_log_set_tag(&t38_core->logging, "T.38");
501
502 logging = t30_get_logging_state(t30);
503 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
504 span_log_set_tag(logging, "T.38");
505
506 fast_send = FALSE;
507 fast_send_tcf = TRUE;
508 fast_blocks = 0;
509 kick = TRUE;
510 #if defined(ENABLE_GUI)
511 if (use_gui)
512 start_media_monitor();
513 #endif
514 while (!done)
515 {
516 logging = t38_terminal_get_logging_state(t38_state);
517 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
518 t38_core = t38_terminal_get_t38_core_state(t38_state);
519 logging = t38_core_get_logging_state(t38_core);
520 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
521 t30 = t38_terminal_get_t30_state(t38_state);
522 logging = t30_get_logging_state(t30);
523 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
524
525 logging = t31_get_logging_state(t31_state);
526 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
527 t38_core = t31_get_t38_core_state(t31_state);
528 logging = t38_core_get_logging_state(t38_core);
529 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
530 span_log_bump_samples(&t31_state->at_state.logging, SAMPLES_PER_CHUNK);
531
532 t38_terminal_send_timeout(t38_state, SAMPLES_PER_CHUNK);
533 t31_t38_send_timeout(t31_state, SAMPLES_PER_CHUNK);
534
535 when += (float) SAMPLES_PER_CHUNK/(float) SAMPLE_RATE;
536
537 if (kick)
538 {
539 kick = FALSE;
540 if (fax_test_seq[test_seq_ptr].command > (const char *) 2)
541 {
542 if (fax_test_seq[test_seq_ptr].command[0])
543 {
544 printf("%s\n", fax_test_seq[test_seq_ptr].command);
545 t31_at_rx(t31_state, fax_test_seq[test_seq_ptr].command, fax_test_seq[test_seq_ptr].len_command);
546 }
547 }
548 else
549 {
550 if (fax_test_seq[test_seq_ptr].command == (const char *) 2)
551 {
552 printf("Fast send TCF\n");
553 fast_send = TRUE;
554 fast_send_tcf = TRUE;
555 fast_blocks = 100;
556 }
557 else
558 {
559 printf("Fast send image\n");
560 fast_send = TRUE;
561 fast_send_tcf = FALSE;
562 fast_blocks = 100;
563 }
564 }
565 }
566 if (fast_send)
567 {
568 /* Send fast modem data */
569 if (fast_send_tcf)
570 {
571 memset(fast_buf, 0, 36);
572 }
573 else
574 {
575 if (fast_blocks == 1)
576 {
577 /* Create the end of page condition */
578 for (i = 0; i < 36; i += 2)
579 {
580 fast_buf[i] = 0x00;
581 fast_buf[i + 1] = 0x80;
582 }
583 }
584 else
585 {
586 /* Create a chunk of white page */
587 for (i = 0; i < 36; i += 4)
588 {
589 fast_buf[i] = 0x00;
590 fast_buf[i + 1] = 0x80;
591 fast_buf[i + 2] = 0xB2;
592 fast_buf[i + 3] = 0x01;
593 }
594 }
595 }
596 if (fast_blocks == 1)
597 {
598 /* Insert EOLs */
599 fast_buf[35] = ETX;
600 fast_buf[34] = DLE;
601 fast_buf[31] =
602 fast_buf[28] =
603 fast_buf[25] =
604 fast_buf[22] =
605 fast_buf[19] =
606 fast_buf[16] = 1;
607 }
608 t31_at_rx(t31_state, (char *) fast_buf, 36);
609 if (--fast_blocks == 0)
610 fast_send = FALSE;
611 }
612 if (countdown)
613 {
614 if (answered)
615 {
616 countdown = 0;
617 t31_call_event(t31_state, AT_CALL_EVENT_ANSWERED);
618 }
619 else if (--countdown == 0)
620 {
621 t31_call_event(t31_state, AT_CALL_EVENT_ALERTING);
622 countdown = 250;
623 }
624 }
625 while ((msg_len = g1050_get(path_a_to_b, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
626 {
627 #if defined(ENABLE_GUI)
628 if (use_gui)
629 media_monitor_rx(seq_no, tx_when, rx_when);
630 #endif
631 t38_core = t31_get_t38_core_state(t31_state);
632 t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no);
633 }
634 while ((msg_len = g1050_get(path_b_to_a, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
635 {
636 #if defined(ENABLE_GUI)
637 if (use_gui)
638 media_monitor_rx(seq_no, tx_when, rx_when);
639 #endif
640 t38_core = t38_terminal_get_t38_core_state(t38_state);
641 t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no);
642 }
643 #if defined(ENABLE_GUI)
644 if (use_gui)
645 media_monitor_update_display();
646 #endif
647 }
648 t38_terminal_release(t38_state);
649 return 0;
650 }
651 /*- End of function --------------------------------------------------------*/
652
653 static int t30_tests(int log_audio, int test_sending)
654 {
655 int k;
656 int outframes;
657 fax_state_t *fax_state;
658 int16_t t30_amp[SAMPLES_PER_CHUNK];
659 int16_t t31_amp[SAMPLES_PER_CHUNK];
660 int16_t silence[SAMPLES_PER_CHUNK];
661 int16_t out_amp[2*SAMPLES_PER_CHUNK];
662 int t30_len;
663 int t31_len;
664 SNDFILE *wave_handle;
665 SNDFILE *in_handle;
666 int fast_send;
667 int fast_send_tcf;
668 int fast_blocks;
669 uint8_t fast_buf[1000];
670 t30_state_t *t30;
671 logging_state_t *logging;
672 int i;
673
674 wave_handle = NULL;
675 if (log_audio)
676 {
677 if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL)
678 {
679 fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
680 exit(2);
681 }
682 }
683
684 memset(silence, 0, sizeof(silence));
685
686 in_handle = NULL;
687 if (decode_test_file)
688 {
689 if ((in_handle = sf_open_telephony_read(decode_test_file, 1)) == NULL)
690 {
691 fprintf(stderr, " Cannot create audio file '%s'\n", decode_test_file);
692 exit(2);
693 }
694 }
695
696 if ((t31_state = t31_init(NULL, at_tx_handler, NULL, modem_call_control, NULL, NULL, NULL)) == NULL)
697 {
698 fprintf(stderr, " Cannot start the T.31 FAX modem\n");
699 exit(2);
700 }
701 logging = t31_get_logging_state(t31_state);
702 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
703 span_log_set_tag(logging, "T.31");
704
705 if (test_sending)
706 {
707 fax_state = fax_init(NULL, FALSE);
708 t30 = fax_get_t30_state(fax_state);
709 t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1);
710 fax_test_seq = fax_send_test_seq;
711 countdown = 0;
712 }
713 else
714 {
715 fax_state = fax_init(NULL, TRUE);
716 t30 = fax_get_t30_state(fax_state);
717 t30_set_tx_file(t30, INPUT_FILE_NAME, -1, -1);
718 fax_test_seq = fax_receive_test_seq;
719 countdown = 250;
720 }
721
722 t30_set_tx_ident(t30, "11111111");
723 t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17);
724 t30_set_phase_b_handler(t30, phase_b_handler, (void *) 'A');
725 t30_set_phase_d_handler(t30, phase_d_handler, (void *) 'A');
726 t30_set_phase_e_handler(t30, phase_e_handler, (void *) 'A');
727 memset(t30_amp, 0, sizeof(t30_amp));
728
729 logging = t30_get_logging_state(t30);
730 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
731 span_log_set_tag(logging, "FAX");
732
733 logging = fax_get_logging_state(fax_state);
734 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
735 span_log_set_tag(logging, "FAX");
736
737 fast_send = FALSE;
738 fast_send_tcf = TRUE;
739 fast_blocks = 0;
740 kick = TRUE;
741 while (!done)
742 {
743 if (kick)
744 {
745 kick = FALSE;
746 if (fax_test_seq[test_seq_ptr].command > (const char *) 2)
747 {
748 if (fax_test_seq[test_seq_ptr].command[0])
749 {
750 printf("%s\n", fax_test_seq[test_seq_ptr].command);
751 t31_at_rx(t31_state, fax_test_seq[test_seq_ptr].command, fax_test_seq[test_seq_ptr].len_command);
752 }
753 }
754 else
755 {
756 if (fax_test_seq[test_seq_ptr].command == (const char *) 2)
757 {
758 printf("Fast send TCF\n");
759 fast_send = TRUE;
760 fast_send_tcf = TRUE;
761 fast_blocks = 100;
762 }
763 else
764 {
765 printf("Fast send image\n");
766 fast_send = TRUE;
767 fast_send_tcf = FALSE;
768 fast_blocks = 100;
769 }
770 }
771 }
772 if (fast_send)
773 {
774 /* Send fast modem data */
775 if (fast_send_tcf)
776 {
777 memset(fast_buf, 0, 36);
778 }
779 else
780 {
781 if (fast_blocks == 1)
782 {
783 /* Create the end of page condition */
784 for (i = 0; i < 36; i += 2)
785 {
786 fast_buf[i] = 0x00;
787 fast_buf[i + 1] = 0x80;
788 }
789 }
790 else
791 {
792 /* Create a chunk of white page */
793 for (i = 0; i < 36; i += 4)
794 {
795 fast_buf[i] = 0x00;
796 fast_buf[i + 1] = 0x80;
797 fast_buf[i + 2] = 0xB2;
798 fast_buf[i + 3] = 0x01;
799 }
800 }
801 }
802 if (fast_blocks == 1)
803 {
804 /* Insert EOLs */
805 fast_buf[35] = ETX;
806 fast_buf[34] = DLE;
807 fast_buf[31] =
808 fast_buf[28] =
809 fast_buf[25] =
810 fast_buf[22] =
811 fast_buf[19] =
812 fast_buf[16] = 1;
813 }
814 t31_at_rx(t31_state, (char *) fast_buf, 36);
815 if (--fast_blocks == 0)
816 fast_send = FALSE;
817 }
818 t30_len = fax_tx(fax_state, t30_amp, SAMPLES_PER_CHUNK);
819 /* The receive side always expects a full block of samples, but the
820 transmit side may not be sending any when it doesn't need to. We
821 may need to pad with some silence. */
822 if (t30_len < SAMPLES_PER_CHUNK)
823 {
824 memset(t30_amp + t30_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len));
825 t30_len = SAMPLES_PER_CHUNK;
826 }
827 if (log_audio)
828 {
829 for (k = 0; k < t30_len; k++)
830 out_amp[2*k] = t30_amp[k];
831 }
832 if (t31_rx(t31_state, t30_amp, t30_len))
833 break;
834 if (countdown)
835 {
836 if (answered)
837 {
838 countdown = 0;
839 t31_call_event(t31_state, AT_CALL_EVENT_ANSWERED);
840 }
841 else if (--countdown == 0)
842 {
843 t31_call_event(t31_state, AT_CALL_EVENT_ALERTING);
844 countdown = 250;
845 }
846 }
847
848 t31_len = t31_tx(t31_state, t31_amp, SAMPLES_PER_CHUNK);
849 if (t31_len < SAMPLES_PER_CHUNK)
850 {
851 memset(t31_amp + t31_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t31_len));
852 t31_len = SAMPLES_PER_CHUNK;
853 }
854 if (log_audio)
855 {
856 for (k = 0; k < t31_len; k++)
857 out_amp[2*k + 1] = t31_amp[k];
858 }
859 if (fax_rx(fax_state, t31_amp, SAMPLES_PER_CHUNK))
860 break;
861
862 span_log_bump_samples(&fax_state->logging, SAMPLES_PER_CHUNK);
863 span_log_bump_samples(&t30->logging, SAMPLES_PER_CHUNK);
864
865 if (log_audio)
866 {
867 outframes = sf_writef_short(wave_handle, out_amp, SAMPLES_PER_CHUNK);
868 if (outframes != SAMPLES_PER_CHUNK)
869 break;
870 }
871 }
872 if (decode_test_file)
873 {
874 if (sf_close(in_handle) != 0)
875 {
876 fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file);
877 exit(2);
878 }
879 }
880 if (log_audio)
881 {
882 if (sf_close(wave_handle) != 0)
883 {
884 fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
885 exit(2);
886 }
887 }
888 return 0;
889 }
890 /*- End of function --------------------------------------------------------*/
891
892 int main(int argc, char *argv[])
893 {
894 int log_audio;
895 int t38_mode;
896 int test_sending;
897 int use_gui;
898 int opt;
899
900 decode_test_file = NULL;
901 log_audio = FALSE;
902 test_sending = FALSE;
903 t38_mode = FALSE;
904 use_gui = FALSE;
905 while ((opt = getopt(argc, argv, "d:glrst")) != -1)
906 {
907 switch (opt)
908 {
909 case 'd':
910 decode_test_file = optarg;
911 break;
912 case 'g':
913 #if defined(ENABLE_GUI)
914 use_gui = TRUE;
915 #else
916 fprintf(stderr, "Graphical monitoring not available\n");
917 exit(2);
918 #endif
919 break;
920 case 'l':
921 log_audio = TRUE;
922 break;
923 case 'r':
924 test_sending = FALSE;
925 break;
926 case 's':
927 test_sending = TRUE;
928 break;
929 case 't':
930 t38_mode = TRUE;
931 break;
932 default:
933 //usage();
934 exit(2);
935 break;
936 }
937 }
938
939 if (t38_mode)
940 t38_tests(use_gui, test_sending, 0, 1);
941 else
942 t30_tests(log_audio, test_sending);
943 if (done)
944 {
945 printf("Tests passed\n");
946 }
947 return 0;
948 }
949 /*- End of function --------------------------------------------------------*/
950 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.