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