1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * faxtester_tests.c
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2003, 2005, 2006 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 Lesser General Public License version 2.1,
14 * as 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 Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * $Id: tsb85_tests.c,v 1.8 2008/07/25 13:56:54 steveu Exp $
26 */
27
28 /*! \file */
29
30 #if defined(HAVE_CONFIG_H)
31 #include <config.h>
32 #endif
33
34 #include <inttypes.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include "floating_fudge.h"
40 #if defined(HAVE_TGMATH_H)
41 #include <tgmath.h>
42 #endif
43 #if defined(HAVE_MATH_H)
44 #include <math.h>
45 #endif
46 #include <assert.h>
47 #include <fcntl.h>
48 #include <time.h>
49 #include <unistd.h>
50 #include <audiofile.h>
51
52 #if defined(HAVE_LIBXML_XMLMEMORY_H)
53 #include <libxml/xmlmemory.h>
54 #endif
55 #if defined(HAVE_LIBXML_PARSER_H)
56 #include <libxml/parser.h>
57 #endif
58 #if defined(HAVE_LIBXML_XINCLUDE_H)
59 #include <libxml/xinclude.h>
60 #endif
61
62 #include "spandsp.h"
63 #include "fax_tester.h"
64
65 #define INPUT_TIFF_FILE_NAME "../test-data/itu/fax/itutests.tif"
66 #define OUTPUT_TIFF_FILE_NAME "tsb85.tif"
67
68 #define OUTPUT_FILE_NAME_WAVE "tsb85.wav"
69
70 #define SAMPLES_PER_CHUNK 160
71
72 AFfilehandle out_handle;
73 AFfilesetup filesetup;
74
75 int use_receiver_not_ready = FALSE;
76 int test_local_interrupt = FALSE;
77
78 faxtester_state_t state;
79
80 uint8_t image[1000000];
81
82 static int next_step(faxtester_state_t *s);
83
phase_b_handler(t30_state_t * s,void * user_data,int result)84 static int phase_b_handler(t30_state_t *s, void *user_data, int result)
85 {
86 int i;
87 const char *u;
88
89 i = (intptr_t) user_data;
90 if ((u = t30_get_rx_ident(s)))
91 printf("%d: Phase B: remote ident '%s'\n", i, u);
92 if ((u = t30_get_rx_sub_address(s)))
93 printf("%d: Phase B: remote sub-address '%s'\n", i, u);
94 if ((u = t30_get_rx_polled_sub_address(s)))
95 printf("%d: Phase B: remote polled sub-address '%s'\n", i, u);
96 if ((u = t30_get_rx_selective_polling_address(s)))
97 printf("%d: Phase B: remote selective polling address '%s'\n", i, u);
98 if ((u = t30_get_rx_sender_ident(s)))
99 printf("%d: Phase B: remote sender ident '%s'\n", i, u);
100 if ((u = t30_get_rx_password(s)))
101 printf("%d: Phase B: remote password '%s'\n", i, u);
102 printf("%d: Phase B handler on channel %d - (0x%X) %s\n", i, i, result, t30_frametype(result));
103 return T30_ERR_OK;
104 }
105 /*- End of function --------------------------------------------------------*/
106
phase_d_handler(t30_state_t * s,void * user_data,int result)107 static int phase_d_handler(t30_state_t *s, void *user_data, int result)
108 {
109 int i;
110 t30_stats_t t;
111 const char *u;
112
113 i = (intptr_t) user_data;
114 t30_get_transfer_statistics(s, &t);
115
116 printf("%d: Phase D handler on channel %d - (0x%X) %s\n", i, i, result, t30_frametype(result));
117 printf("%d: Phase D: bit rate %d\n", i, t.bit_rate);
118 printf("%d: Phase D: ECM %s\n", i, (t.error_correcting_mode) ? "on" : "off");
119 printf("%d: Phase D: pages transferred %d\n", i, t.pages_transferred);
120 printf("%d: Phase D: pages in the file %d\n", i, t.pages_in_file);
121 printf("%d: Phase D: image size %d x %d\n", i, t.width, t.length);
122 printf("%d: Phase D: image resolution %d x %d\n", i, t.x_resolution, t.y_resolution);
123 printf("%d: Phase D: bad rows %d\n", i, t.bad_rows);
124 printf("%d: Phase D: longest bad row run %d\n", i, t.longest_bad_row_run);
125 printf("%d: Phase D: compression type %d\n", i, t.encoding);
126 printf("%d: Phase D: image size %d bytes\n", i, t.image_size);
127 if ((u = t30_get_tx_ident(s)))
128 printf("%d: Phase D: local ident '%s'\n", i, u);
129 if ((u = t30_get_rx_ident(s)))
130 printf("%d: Phase D: remote ident '%s'\n", i, u);
131 printf("%d: Phase D: bits per row - min %d, max %d\n", i, s->t4.min_row_bits, s->t4.max_row_bits);
132
133 if (use_receiver_not_ready)
134 t30_set_receiver_not_ready(s, 3);
135
136 if (test_local_interrupt)
137 {
138 if (i == 0)
139 {
140 printf("%d: Initiating interrupt request\n", i);
141 t30_local_interrupt_request(s, TRUE);
142 }
143 else
144 {
145 switch (result)
146 {
147 case T30_PIP:
148 case T30_PRI_MPS:
149 case T30_PRI_EOM:
150 case T30_PRI_EOP:
151 printf("%d: Accepting interrupt request\n", i);
152 t30_local_interrupt_request(s, TRUE);
153 break;
154 case T30_PIN:
155 break;
156 }
157 }
158 }
159 return T30_ERR_OK;
160 }
161 /*- End of function --------------------------------------------------------*/
162
phase_e_handler(t30_state_t * s,void * user_data,int result)163 static void phase_e_handler(t30_state_t *s, void *user_data, int result)
164 {
165 int i;
166 t30_stats_t t;
167 const char *u;
168
169 i = (intptr_t) user_data;
170 printf("%d: Phase E handler on channel %d - (%d) %s\n", i, i, result, t30_completion_code_to_str(result));
171 t30_get_transfer_statistics(s, &t);
172 printf("%d: Phase E: bit rate %d\n", i, t.bit_rate);
173 printf("%d: Phase E: ECM %s\n", i, (t.error_correcting_mode) ? "on" : "off");
174 printf("%d: Phase E: pages transferred %d\n", i, t.pages_transferred);
175 printf("%d: Phase E: pages in the file %d\n", i, t.pages_in_file);
176 printf("%d: Phase E: image size %d x %d\n", i, t.width, t.length);
177 printf("%d: Phase E: image resolution %d x %d\n", i, t.x_resolution, t.y_resolution);
178 printf("%d: Phase E: bad rows %d\n", i, t.bad_rows);
179 printf("%d: Phase E: longest bad row run %d\n", i, t.longest_bad_row_run);
180 printf("%d: Phase E: coding method %s\n", i, t4_encoding_to_str(t.encoding));
181 printf("%d: Phase E: image size %d bytes\n", i, t.image_size);
182 //printf("%d: Phase E: local ident '%s'\n", i, info->ident);
183 if ((u = t30_get_rx_ident(s)))
184 printf("%d: Phase E: remote ident '%s'\n", i, u);
185 if ((u = t30_get_rx_country(s)))
186 printf("%d: Phase E: Remote was made in '%s'\n", i, u);
187 if ((u = t30_get_rx_vendor(s)))
188 printf("%d: Phase E: Remote was made by '%s'\n", i, u);
189 if ((u = t30_get_rx_model(s)))
190 printf("%d: Phase E: Remote is model '%s'\n", i, u);
191 }
192 /*- End of function --------------------------------------------------------*/
193
t30_real_time_frame_handler(t30_state_t * s,void * user_data,int direction,const uint8_t * msg,int len)194 static void t30_real_time_frame_handler(t30_state_t *s,
195 void *user_data,
196 int direction,
197 const uint8_t *msg,
198 int len)
199 {
200 printf("T.30: Real time frame handler - %s, %s, length = %d\n",
201 (direction) ? "line->T.30" : "T.30->line",
202 t30_frametype(msg[2]),
203 len);
204 }
205 /*- End of function --------------------------------------------------------*/
206
document_handler(t30_state_t * s,void * user_data,int event)207 static int document_handler(t30_state_t *s, void *user_data, int event)
208 {
209 int i;
210
211 i = (intptr_t) user_data;
212 printf("%d: Document handler on channel %d - event %d\n", i, i, event);
213 return FALSE;
214 }
215 /*- End of function --------------------------------------------------------*/
216
faxtester_real_time_frame_handler(faxtester_state_t * s,void * user_data,int direction,const uint8_t * msg,int len)217 static void faxtester_real_time_frame_handler(faxtester_state_t *s,
218 void *user_data,
219 int direction,
220 const uint8_t *msg,
221 int len)
222 {
223 printf("Tester: Real time frame handler - %s, %s, length = %d\n",
224 (direction) ? "line->tester" : "tester->line",
225 t30_frametype(msg[2]),
226 len);
227 if (msg[1] == 0x13)
228 next_step(s);
229 }
230 /*- End of function --------------------------------------------------------*/
231
faxtester_front_end_step_complete_handler(faxtester_state_t * s,void * user_data)232 static void faxtester_front_end_step_complete_handler(faxtester_state_t *s, void *user_data)
233 {
234 next_step(s);
235 }
236 /*- End of function --------------------------------------------------------*/
237
string_to_msg(uint8_t msg[],uint8_t mask[],const char buf[])238 static int string_to_msg(uint8_t msg[], uint8_t mask[], const char buf[])
239 {
240 int i;
241 int x;
242 const char *t;
243
244 msg[0] = 0;
245 mask[0] = 0xFF;
246 i = 0;
247 t = (char *) buf;
248 while (*t)
249 {
250 /* Skip white space */
251 while (isspace(*t))
252 t++;
253 /* If we find ... we allow arbitrary addition info beyond this point in the message */
254 if (t[0] == '.' && t[1] == '.' && t[2] == '.')
255 {
256 return -i;
257 }
258 else if (isxdigit(*t))
259 {
260 for ( ; isxdigit(*t); t++)
261 {
262 x = *t;
263 if (x >= 'a')
264 x -= 0x20;
265 if (x >= 'A')
266 x -= ('A' - 10);
267 else
268 x -= '0';
269 msg[i] = (msg[i] << 4) | x;
270 }
271 mask[i] = 0xFF;
272 if (*t == '/')
273 {
274 /* There is a mask following the byte */
275 mask[i] = 0;
276 for (t++; isxdigit(*t); t++)
277 {
278 x = *t;
279 if (x >= 'a')
280 x -= 0x20;
281 if (x >= 'A')
282 x -= ('A' - 10);
283 else
284 x -= '0';
285 mask[i] = (mask[i] << 4) | x;
286 }
287 }
288 if (*t && !isspace(*t))
289 {
290 /* Bad string */
291 return 0;
292 }
293 i++;
294 }
295 }
296 return i;
297 }
298 /*- End of function --------------------------------------------------------*/
299
300 #if 0
301 static void string_test2(const uint8_t msg[], int len)
302 {
303 int i;
304
305 if (len > 0)
306 {
307 for (i = 0; i < len - 1; i++)
308 printf("%02X ", msg[i]);
309 printf("%02X", msg[i]);
310 }
311 }
312 /*- End of function --------------------------------------------------------*/
313
314 static void string_test3(const char buf[])
315 {
316 uint8_t msg[1000];
317 uint8_t mask[1000];
318 int len;
319 int i;
320
321 len = string_to_msg(msg, mask, buf);
322 printf("Len = %d: ", len);
323 string_test2(msg, abs(len));
324 printf("/");
325 string_test2(mask, abs(len));
326 printf("\n");
327 }
328 /*- End of function --------------------------------------------------------*/
329
330 static int string_test(void)
331 {
332 string_test3("FF C8 12 34 56 78");
333 string_test3("FF C8 12/55 34 56/aA 78 ");
334 string_test3("FF C8 12/55 34 56/aA 78 ...");
335 string_test3("FF C8 12/55 34 56/aA 78...");
336 string_test3("FF C8 12/55 34 56/aA 78 ... 99 88 77");
337 exit(0);
338 }
339 /*- End of function --------------------------------------------------------*/
340 #endif
341
corrupt_image(uint8_t image[],int len,const char * bad_rows)342 static void corrupt_image(uint8_t image[], int len, const char *bad_rows)
343 {
344 int i;
345 int j;
346 int k;
347 uint32_t bits;
348 uint32_t bitsx;
349 int list[1000];
350 int x;
351 int row;
352 const char *s;
353
354 /* Form the list of rows to be hit */
355 x = 0;
356 s = bad_rows;
357 while (*s)
358 {
359 while (isspace(*s))
360 s++;
361 if (sscanf(s, "%d", &list[x]) < 1)
362 break;
363 x++;
364 while (isdigit(*s))
365 s++;
366 if (*s == ',')
367 s++;
368 }
369
370 /* Go through the image, and corrupt the first bit of every listed row */
371 bits = 0x7FF;
372 bitsx = 0x7FF;
373 row = 0;
374 for (i = 0; i < len; i++)
375 {
376 bits ^= (image[i] << 11);
377 bitsx ^= (image[i] << 11);
378 for (j = 0; j < 8; j++)
379 {
380 if ((bits & 0xFFF) == 0x800)
381 {
382 /* We are at an EOL. Is this row in the list of rows to be corrupted? */
383 row++;
384 for (k = 0; k < x; k++)
385 {
386 if (list[k] == row)
387 {
388 /* Corrupt this row. TSB85 says to hit the first bit after the EOL */
389 bitsx ^= 0x1000;
390 }
391 }
392 }
393 bits >>= 1;
394 bitsx >>= 1;
395 }
396 image[i] = (bitsx >> 3) & 0xFF;
397 }
398 printf("%d rows found. %d corrupted\n", row, x);
399 }
400 /*- End of function --------------------------------------------------------*/
401
next_step(faxtester_state_t * s)402 static int next_step(faxtester_state_t *s)
403 {
404 int delay;
405 int flags;
406 xmlChar *dir;
407 xmlChar *type;
408 xmlChar *modem;
409 xmlChar *value;
410 xmlChar *tag;
411 xmlChar *bad_rows;
412 uint8_t buf[1000];
413 uint8_t mask[1000];
414 int i;
415 int hdlc;
416 int short_train;
417 int min_row_bits;
418 int compression;
419 int compression_step;
420 int len;
421 t4_state_t t4_state;
422
423 if (s->cur == NULL)
424 {
425 if (!s->final_delayed)
426 {
427 /* Add a bit of waiting at the end, to ensure everything gets flushed through,
428 any timers can expire, etc. */
429 faxtester_set_rx_type(s, T30_MODEM_NONE, FALSE, FALSE);
430 faxtester_set_tx_type(s, T30_MODEM_PAUSE, 120000, FALSE);
431 s->final_delayed = TRUE;
432 return 1;
433 }
434 /* Finished */
435 exit(0);
436 }
437 while (s->cur && xmlStrcmp(s->cur->name, (const xmlChar *) "step") != 0)
438 s->cur = s->cur->next;
439 if (s->cur == NULL)
440 {
441 /* Finished */
442 exit(0);
443 }
444
445 dir = xmlGetProp(s->cur, (const xmlChar *) "dir");
446 type = xmlGetProp(s->cur, (const xmlChar *) "type");
447 modem = xmlGetProp(s->cur, (const xmlChar *) "modem");
448 value = xmlGetProp(s->cur, (const xmlChar *) "value");
449 tag = xmlGetProp(s->cur, (const xmlChar *) "tag");
450 bad_rows = xmlGetProp(s->cur, (const xmlChar *) "bad_rows");
451
452 s->cur = s->cur->next;
453
454 printf("Dir - %s, type - %s, modem - %s, value - %s, tag - %s\n",
455 (dir) ? (const char *) dir : "",
456 (type) ? (const char *) type : "",
457 (modem) ? (const char *) modem : "",
458 (value) ? (const char *) value : "",
459 (tag) ? (const char *) tag : "");
460 if (type == NULL)
461 return 1;
462 /*endif*/
463 if (dir && strcasecmp((const char *) dir, "R") == 0)
464 {
465 if (strcasecmp((const char *) type, "HDLC") == 0)
466 {
467 faxtester_set_rx_type(s, T30_MODEM_V21, FALSE, TRUE);
468 faxtester_set_tx_type(s, T30_MODEM_NONE, FALSE, FALSE);
469 i = string_to_msg(buf, mask, (const char *) value);
470 bit_reverse(buf, buf, abs(i));
471 }
472 else
473 {
474 return 0;
475 }
476 }
477 else
478 {
479 if (modem)
480 {
481 hdlc = (strcasecmp((const char *) type, "PREAMBLE") == 0);
482 short_train = (strcasecmp((const char *) type, "TCF") == 0);
483 faxtester_set_rx_type(s, T30_MODEM_NONE, FALSE, FALSE);
484 if (strcasecmp((const char *) modem, "V.21") == 0)
485 {
486 faxtester_set_tx_type(s, T30_MODEM_V21, FALSE, TRUE);
487 }
488 else if (strcasecmp((const char *) modem, "V.17/14400") == 0)
489 {
490 faxtester_set_tx_type(s, T30_MODEM_V17_14400, short_train, hdlc);
491 }
492 else if (strcasecmp((const char *) modem, "V.17/12000") == 0)
493 {
494 faxtester_set_tx_type(s, T30_MODEM_V17_12000, short_train, hdlc);
495 }
496 else if (strcasecmp((const char *) modem, "V.17/9600") == 0)
497 {
498 faxtester_set_tx_type(s, T30_MODEM_V17_9600, short_train, hdlc);
499 }
500 else if (strcasecmp((const char *) modem, "V.17/7200") == 0)
501 {
502 faxtester_set_tx_type(s, T30_MODEM_V17_7200, short_train, hdlc);
503 }
504 else if (strcasecmp((const char *) modem, "V.29/9600") == 0)
505 {
506 faxtester_set_tx_type(s, T30_MODEM_V29_9600, FALSE, hdlc);
507 }
508 else if (strcasecmp((const char *) modem, "V.29/7200") == 0)
509 {
510 faxtester_set_tx_type(s, T30_MODEM_V29_7200, FALSE, hdlc);
511 }
512 else if (strcasecmp((const char *) modem, "V.27ter/4800") == 0)
513 {
514 faxtester_set_tx_type(s, T30_MODEM_V27TER_4800, FALSE, hdlc);
515 }
516 else if (strcasecmp((const char *) modem, "V.27ter/2400") == 0)
517 {
518 faxtester_set_tx_type(s, T30_MODEM_V27TER_2400, FALSE, hdlc);
519 }
520 else
521 {
522 printf("Unrecognised modem\n");
523 }
524 }
525
526 if (strcasecmp((const char *) type, "CALL") == 0)
527 {
528 return 0;
529 }
530 else if (strcasecmp((const char *) type, "ANSWER") == 0)
531 {
532 return 0;
533 }
534 else if (strcasecmp((const char *) type, "CNG") == 0)
535 {
536 faxtester_set_rx_type(s, T30_MODEM_NONE, FALSE, FALSE);
537 faxtester_set_tx_type(s, T30_MODEM_CNG, FALSE, FALSE);
538 }
539 else if (strcasecmp((const char *) type, "CED") == 0)
540 {
541 faxtester_set_rx_type(s, T30_MODEM_NONE, FALSE, FALSE);
542 faxtester_set_tx_type(s, T30_MODEM_CED, FALSE, FALSE);
543 }
544 else if (strcasecmp((const char *) type, "WAIT") == 0)
545 {
546 delay = (value) ? atoi((const char *) value) : 1;
547 faxtester_set_rx_type(s, T30_MODEM_NONE, FALSE, FALSE);
548 faxtester_set_tx_type(s, T30_MODEM_PAUSE, delay, FALSE);
549 }
550 else if (strcasecmp((const char *) type, "PREAMBLE") == 0)
551 {
552 flags = (value) ? atoi((const char *) value) : 37;
553 faxtester_send_hdlc_flags(s, flags);
554 }
555 else if (strcasecmp((const char *) type, "POSTAMBLE") == 0)
556 {
557 flags = (value) ? atoi((const char *) value) : 5;
558 faxtester_send_hdlc_flags(s, flags);
559 }
560 else if (strcasecmp((const char *) type, "HDLC") == 0)
561 {
562 i = string_to_msg(buf, mask, (const char *) value);
563 bit_reverse(buf, buf, abs(i));
564 faxtester_send_hdlc_msg(s, buf, abs(i));
565 }
566 else if (strcasecmp((const char *) type, "TCF") == 0)
567 {
568 if (value)
569 i = atoi((const char *) value);
570 else
571 i = 450;
572 memset(image, 0, i);
573 faxtester_set_image_buffer(s, image, i);
574 }
575 else if (strcasecmp((const char *) type, "MSG") == 0)
576 {
577 min_row_bits = 0;
578 compression_step = 0;
579 if (t4_tx_init(&t4_state, (const char *) value, -1, -1) == NULL)
580 {
581 printf("Failed to init T.4 send\n");
582 exit(2);
583 }
584 t4_tx_set_min_row_bits(&t4_state, min_row_bits);
585 t4_tx_set_header_info(&t4_state, NULL);
586 switch (compression_step)
587 {
588 case 0:
589 compression = T4_COMPRESSION_ITU_T4_1D;
590 break;
591 case 1:
592 compression = T4_COMPRESSION_ITU_T4_2D;
593 break;
594 case 2:
595 compression = T4_COMPRESSION_ITU_T6;
596 break;
597 }
598 t4_tx_set_tx_encoding(&t4_state, compression);
599 if (t4_tx_start_page(&t4_state))
600 {
601 printf("Failed to start T.4 send\n");
602 exit(2);
603 }
604 len = t4_tx_get_chunk(&t4_state, image, sizeof(image));
605 if (bad_rows)
606 {
607 printf("We need to corrupt the image\n");
608 corrupt_image(image, len, (const char *) bad_rows);
609 }
610 t4_tx_end(&t4_state);
611 faxtester_set_image_buffer(s, image, len);
612 }
613 else
614 {
615 return 0;
616 }
617 /*endif*/
618 }
619 /*endif*/
620 return 1;
621 }
622 /*- End of function --------------------------------------------------------*/
623
exchange(faxtester_state_t * s)624 static void exchange(faxtester_state_t *s)
625 {
626 int16_t amp[SAMPLES_PER_CHUNK];
627 int16_t out_amp[2*SAMPLES_PER_CHUNK];
628 int len;
629 int i;
630 fax_state_t fax;
631 int total_audio_time;
632 const char *input_tiff_file_name;
633 const char *output_tiff_file_name;
634 int log_audio;
635 t30_state_t *t30;
636
637 log_audio = TRUE;
638 input_tiff_file_name = INPUT_TIFF_FILE_NAME;
639 output_tiff_file_name = OUTPUT_TIFF_FILE_NAME;
640
641 if (log_audio)
642 {
643 if ((filesetup = afNewFileSetup()) == AF_NULL_FILESETUP)
644 {
645 fprintf(stderr, " Failed to create file setup\n");
646 exit(2);
647 }
648 afInitSampleFormat(filesetup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16);
649 afInitRate(filesetup, AF_DEFAULT_TRACK, (float) SAMPLE_RATE);
650 afInitFileFormat(filesetup, AF_FILE_WAVE);
651 afInitChannels(filesetup, AF_DEFAULT_TRACK, 2);
652
653 if ((out_handle = afOpenFile(OUTPUT_FILE_NAME_WAVE, "w", filesetup)) == AF_NULL_FILEHANDLE)
654 {
655 fprintf(stderr, " Cannot create wave file '%s'\n", OUTPUT_FILE_NAME_WAVE);
656 exit(2);
657 }
658 }
659
660 total_audio_time = 0;
661
662 faxtester_set_transmit_on_idle(&state, TRUE);
663 faxtester_set_real_time_frame_handler(&state, faxtester_real_time_frame_handler, NULL);
664 faxtester_set_front_end_step_complete_handler(&state, faxtester_front_end_step_complete_handler, NULL);
665
666 fax_init(&fax, FALSE);
667 t30 = fax_get_t30_state(&fax);
668 fax_set_transmit_on_idle(&fax, TRUE);
669 fax_set_tep_mode(&fax, TRUE);
670 t30_set_tx_ident(t30, "1234567890");
671 t30_set_tx_sub_address(t30, "Sub-address");
672 t30_set_tx_sender_ident(t30, "Sender ID");
673 t30_set_tx_password(t30, "Password");
674 t30_set_tx_polled_sub_address(t30, "Polled sub-address");
675 t30_set_tx_selective_polling_address(t30, "Sel polling address");
676 t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
677 t30_set_ecm_capability(t30, TRUE);
678 t30_set_supported_t30_features(t30,
679 T30_SUPPORT_IDENTIFICATION
680 | T30_SUPPORT_SELECTIVE_POLLING
681 | T30_SUPPORT_SUB_ADDRESSING);
682 t30_set_supported_image_sizes(t30,
683 T30_SUPPORT_US_LETTER_LENGTH
684 | T30_SUPPORT_US_LEGAL_LENGTH
685 | T30_SUPPORT_UNLIMITED_LENGTH
686 | T30_SUPPORT_215MM_WIDTH
687 | T30_SUPPORT_255MM_WIDTH
688 | T30_SUPPORT_303MM_WIDTH);
689 t30_set_supported_resolutions(t30,
690 T30_SUPPORT_STANDARD_RESOLUTION
691 | T30_SUPPORT_FINE_RESOLUTION
692 | T30_SUPPORT_SUPERFINE_RESOLUTION
693 | T30_SUPPORT_R8_RESOLUTION
694 | T30_SUPPORT_R16_RESOLUTION
695 | T30_SUPPORT_300_300_RESOLUTION
696 | T30_SUPPORT_400_400_RESOLUTION
697 | T30_SUPPORT_600_600_RESOLUTION
698 | T30_SUPPORT_1200_1200_RESOLUTION
699 | T30_SUPPORT_300_600_RESOLUTION
700 | T30_SUPPORT_400_800_RESOLUTION
701 | T30_SUPPORT_600_1200_RESOLUTION);
702 t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17);
703 t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
704 t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 1);
705 t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 1);
706 t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 1);
707 t30_set_real_time_frame_handler(t30, t30_real_time_frame_handler, (void *) (intptr_t) 1);
708 t30_set_document_handler(t30, document_handler, (void *) (intptr_t) 1);
709 t30_set_rx_file(t30, output_tiff_file_name, -1);
710 //t30_set_tx_file(t30, input_tiff_file_name, -1, -1);
711
712 span_log_set_level(&t30->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
713 span_log_set_tag(&t30->logging, "A");
714 span_log_set_level(&fax.fe.modems.v29_rx.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
715 span_log_set_tag(&fax.fe.modems.v29_rx.logging, "A");
716 span_log_set_level(&fax.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
717 span_log_set_tag(&fax.logging, "A");
718
719 while (next_step(s) == 0)
720 ;
721 for (;;)
722 {
723 len = fax_tx(&fax, amp, SAMPLES_PER_CHUNK);
724 faxtester_rx(s, amp, len);
725 if (log_audio)
726 {
727 for (i = 0; i < len; i++)
728 out_amp[2*i + 0] = amp[i];
729 }
730
731 total_audio_time += SAMPLES_PER_CHUNK;
732 span_log_bump_samples(&fax.t30.logging, len);
733 span_log_bump_samples(&fax.fe.modems.v29_rx.logging, len);
734 span_log_bump_samples(&fax.logging, len);
735
736 len = faxtester_tx(s, amp, 160);
737 if (fax_rx(&fax, amp, len))
738 break;
739 if (log_audio)
740 {
741 for (i = 0; i < len; i++)
742 out_amp[2*i + 1] = amp[i];
743 if (afWriteFrames(out_handle, AF_DEFAULT_TRACK, out_amp, SAMPLES_PER_CHUNK) != SAMPLES_PER_CHUNK)
744 break;
745 }
746 }
747 if (log_audio)
748 {
749 if (afCloseFile(out_handle))
750 {
751 fprintf(stderr, " Cannot close wave file '%s'\n", OUTPUT_FILE_NAME_WAVE);
752 exit(2);
753 }
754 afFreeFileSetup(filesetup);
755 }
756 }
757 /*- End of function --------------------------------------------------------*/
758
parse_test_group(faxtester_state_t * s,xmlDocPtr doc,xmlNsPtr ns,xmlNodePtr cur,const char * test)759 static int parse_test_group(faxtester_state_t *s, xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur, const char *test)
760 {
761 xmlChar *x;
762
763 while (cur)
764 {
765 if (xmlStrcmp(cur->name, (const xmlChar *) "test") == 0)
766 {
767 if ((x = xmlGetProp(cur, (const xmlChar *) "name")))
768 {
769 if (xmlStrcmp(x, (const xmlChar *) test) == 0)
770 {
771 printf("Found '%s'\n", (char *) x);
772 s->cur = cur->xmlChildrenNode;
773 return 0;
774 }
775 /*endif*/
776 }
777 /*endif*/
778 }
779 /*endif*/
780 cur = cur->next;
781 }
782 /*endwhile*/
783 return -1;
784 }
785 /*- End of function --------------------------------------------------------*/
786
get_test_set(faxtester_state_t * s,const char * test_file,const char * test)787 static int get_test_set(faxtester_state_t *s, const char *test_file, const char *test)
788 {
789 xmlDocPtr doc;
790 xmlNsPtr ns;
791 xmlNodePtr cur;
792 #if 0
793 xmlValidCtxt valid;
794 #endif
795
796 ns = NULL;
797 xmlKeepBlanksDefault(0);
798 xmlCleanupParser();
799 doc = xmlParseFile(test_file);
800 if (doc == NULL)
801 {
802 fprintf(stderr, "No document\n");
803 exit(2);
804 }
805 /*endif*/
806 xmlXIncludeProcess(doc);
807 #if 0
808 if (!xmlValidateDocument(&valid, doc))
809 {
810 fprintf(stderr, "Invalid document\n");
811 exit(2);
812 }
813 /*endif*/
814 #endif
815 /* Check the document is of the right kind */
816 if ((cur = xmlDocGetRootElement(doc)) == NULL)
817 {
818 fprintf(stderr, "Empty document\n");
819 xmlFreeDoc(doc);
820 exit(2);
821 }
822 /*endif*/
823 if (xmlStrcmp(cur->name, (const xmlChar *) "fax-tests"))
824 {
825 fprintf(stderr, "Document of the wrong type, root node != fax-tests");
826 xmlFreeDoc(doc);
827 exit(2);
828 }
829 /*endif*/
830 cur = cur->xmlChildrenNode;
831 while (cur && xmlIsBlankNode(cur))
832 cur = cur->next;
833 /*endwhile*/
834 if (cur == NULL)
835 exit(2);
836 /*endif*/
837 while (cur)
838 {
839 if (xmlStrcmp(cur->name, (const xmlChar *) "test-group") == 0)
840 {
841 if (parse_test_group(s, doc, ns, cur->xmlChildrenNode, test) == 0)
842 {
843 /* We found the test we want, so run it. */
844 exchange(s);
845 break;
846 }
847 /*endif*/
848 }
849 /*endif*/
850 cur = cur->next;
851 }
852 /*endwhile*/
853 xmlFreeDoc(doc);
854 return 0;
855 }
856 /*- End of function --------------------------------------------------------*/
857
main(int argc,char * argv[])858 int main(int argc, char *argv[])
859 {
860 const char *test_name;
861
862 //string_test();
863
864 test_name = "MRGN01";
865 if (argc > 1)
866 test_name = argv[1];
867
868 faxtester_init(&state, TRUE);
869 get_test_set(&state, "../spandsp/tsb85.xml", test_name);
870 printf("Done\n");
871 return 0;
872 }
873 /*- End of function --------------------------------------------------------*/
874 /*- End of file ------------------------------------------------------------*/
875