Mercurial > hg > audiostuff
comparison spandsp-0.0.6pre17/tests/tsb85_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 * tsb85_tests.c | |
5 * | |
6 * Written by Steve Underwood <steveu@coppice.org> | |
7 * | |
8 * Copyright (C) 2008 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.32 2009/05/30 15:23:14 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 #if defined(HAVE_TGMATH_H) | |
40 #include <tgmath.h> | |
41 #endif | |
42 #if defined(HAVE_MATH_H) | |
43 #include <math.h> | |
44 #endif | |
45 #include "floating_fudge.h" | |
46 #include <assert.h> | |
47 #include <fcntl.h> | |
48 #include <time.h> | |
49 #include <unistd.h> | |
50 #include <sndfile.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 //#if defined(WITH_SPANDSP_INTERNALS) | |
63 #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES | |
64 //#endif | |
65 | |
66 #include "spandsp.h" | |
67 #include "spandsp-sim.h" | |
68 | |
69 #include "fax_tester.h" | |
70 #include "fax_utils.h" | |
71 | |
72 #define OUTPUT_TIFF_FILE_NAME "tsb85.tif" | |
73 | |
74 #define OUTPUT_FILE_NAME_WAVE "tsb85.wav" | |
75 | |
76 #define SAMPLES_PER_CHUNK 160 | |
77 | |
78 SNDFILE *out_handle; | |
79 | |
80 int use_receiver_not_ready = FALSE; | |
81 int test_local_interrupt = FALSE; | |
82 | |
83 const char *output_tiff_file_name; | |
84 | |
85 fax_state_t *fax; | |
86 faxtester_state_t state; | |
87 | |
88 uint8_t image[1000000]; | |
89 | |
90 uint8_t awaited[1000]; | |
91 int awaited_len = 0; | |
92 | |
93 char image_path[1024]; | |
94 | |
95 t30_exchanged_info_t expected_rx_info; | |
96 | |
97 char next_tx_file[1000]; | |
98 | |
99 static int next_step(faxtester_state_t *s); | |
100 | |
101 static int phase_b_handler(t30_state_t *s, void *user_data, int result) | |
102 { | |
103 int i; | |
104 int status; | |
105 const char *u; | |
106 | |
107 i = (intptr_t) user_data; | |
108 status = T30_ERR_OK; | |
109 if ((u = t30_get_rx_ident(s))) | |
110 { | |
111 printf("%c: Phase B: remote ident '%s'\n", i, u); | |
112 if (expected_rx_info.ident[0] && strcmp(expected_rx_info.ident, u)) | |
113 { | |
114 printf("%c: Phase B: remote ident incorrect! - expected '%s'\n", i, expected_rx_info.ident); | |
115 status = T30_ERR_IDENT_UNACCEPTABLE; | |
116 } | |
117 } | |
118 else | |
119 { | |
120 if (expected_rx_info.ident[0]) | |
121 { | |
122 printf("%c: Phase B: remote ident missing!\n", i); | |
123 status = T30_ERR_IDENT_UNACCEPTABLE; | |
124 } | |
125 } | |
126 if ((u = t30_get_rx_sub_address(s))) | |
127 { | |
128 printf("%c: Phase B: remote sub-address '%s'\n", i, u); | |
129 if (expected_rx_info.sub_address[0] && strcmp(expected_rx_info.sub_address, u)) | |
130 { | |
131 printf("%c: Phase B: remote sub-address incorrect! - expected '%s'\n", i, expected_rx_info.sub_address); | |
132 status = T30_ERR_SUB_UNACCEPTABLE; | |
133 } | |
134 } | |
135 else | |
136 { | |
137 if (expected_rx_info.sub_address[0]) | |
138 { | |
139 printf("%c: Phase B: remote sub-address missing!\n", i); | |
140 status = T30_ERR_SUB_UNACCEPTABLE; | |
141 } | |
142 } | |
143 if ((u = t30_get_rx_polled_sub_address(s))) | |
144 { | |
145 printf("%c: Phase B: remote polled sub-address '%s'\n", i, u); | |
146 if (expected_rx_info.polled_sub_address[0] && strcmp(expected_rx_info.polled_sub_address, u)) | |
147 { | |
148 printf("%c: Phase B: remote polled sub-address incorrect! - expected '%s'\n", i, expected_rx_info.polled_sub_address); | |
149 status = T30_ERR_PSA_UNACCEPTABLE; | |
150 } | |
151 } | |
152 else | |
153 { | |
154 if (expected_rx_info.polled_sub_address[0]) | |
155 { | |
156 printf("%c: Phase B: remote polled sub-address missing!\n", i); | |
157 status = T30_ERR_PSA_UNACCEPTABLE; | |
158 } | |
159 } | |
160 if ((u = t30_get_rx_selective_polling_address(s))) | |
161 { | |
162 printf("%c: Phase B: remote selective polling address '%s'\n", i, u); | |
163 if (expected_rx_info.selective_polling_address[0] && strcmp(expected_rx_info.selective_polling_address, u)) | |
164 { | |
165 printf("%c: Phase B: remote selective polling address incorrect! - expected '%s'\n", i, expected_rx_info.selective_polling_address); | |
166 status = T30_ERR_SEP_UNACCEPTABLE; | |
167 } | |
168 } | |
169 else | |
170 { | |
171 if (expected_rx_info.selective_polling_address[0]) | |
172 { | |
173 printf("%c: Phase B: remote selective polling address missing!\n", i); | |
174 status = T30_ERR_SEP_UNACCEPTABLE; | |
175 } | |
176 } | |
177 if ((u = t30_get_rx_sender_ident(s))) | |
178 { | |
179 printf("%c: Phase B: remote sender ident '%s'\n", i, u); | |
180 if (expected_rx_info.sender_ident[0] && strcmp(expected_rx_info.sender_ident, u)) | |
181 { | |
182 printf("%c: Phase B: remote sender ident incorrect! - expected '%s'\n", i, expected_rx_info.sender_ident); | |
183 status = T30_ERR_SID_UNACCEPTABLE; | |
184 } | |
185 } | |
186 else | |
187 { | |
188 if (expected_rx_info.sender_ident[0]) | |
189 { | |
190 printf("%c: Phase B: remote sender ident missing!\n", i); | |
191 status = T30_ERR_SID_UNACCEPTABLE; | |
192 } | |
193 } | |
194 if ((u = t30_get_rx_password(s))) | |
195 { | |
196 printf("%c: Phase B: remote password '%s'\n", i, u); | |
197 if (expected_rx_info.password[0] && strcmp(expected_rx_info.password, u)) | |
198 { | |
199 printf("%c: Phase B: remote password incorrect! - expected '%s'\n", i, expected_rx_info.password); | |
200 status = T30_ERR_PWD_UNACCEPTABLE; | |
201 } | |
202 } | |
203 else | |
204 { | |
205 if (expected_rx_info.password[0]) | |
206 { | |
207 printf("%c: Phase B: remote password missing!\n", i); | |
208 status = T30_ERR_PWD_UNACCEPTABLE; | |
209 } | |
210 } | |
211 printf("%c: Phase B handler on channel %d - (0x%X) %s\n", i, i, result, t30_frametype(result)); | |
212 return status; | |
213 } | |
214 /*- End of function --------------------------------------------------------*/ | |
215 | |
216 static int phase_d_handler(t30_state_t *s, void *user_data, int result) | |
217 { | |
218 int i; | |
219 char tag[20]; | |
220 | |
221 i = (intptr_t) user_data; | |
222 snprintf(tag, sizeof(tag), "%c: Phase D:", i); | |
223 | |
224 printf("%c: Phase D handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result)); | |
225 log_transfer_statistics(s, tag); | |
226 log_tx_parameters(s, tag); | |
227 log_rx_parameters(s, tag); | |
228 | |
229 if (use_receiver_not_ready) | |
230 t30_set_receiver_not_ready(s, 3); | |
231 | |
232 if (test_local_interrupt) | |
233 { | |
234 if (i == 'A') | |
235 { | |
236 printf("%c: Initiating interrupt request\n", i); | |
237 t30_local_interrupt_request(s, TRUE); | |
238 } | |
239 else | |
240 { | |
241 switch (result) | |
242 { | |
243 case T30_PIP: | |
244 case T30_PRI_MPS: | |
245 case T30_PRI_EOM: | |
246 case T30_PRI_EOP: | |
247 printf("%c: Accepting interrupt request\n", i); | |
248 t30_local_interrupt_request(s, TRUE); | |
249 break; | |
250 case T30_PIN: | |
251 break; | |
252 } | |
253 } | |
254 } | |
255 return T30_ERR_OK; | |
256 } | |
257 /*- End of function --------------------------------------------------------*/ | |
258 | |
259 static void phase_e_handler(t30_state_t *s, void *user_data, int result) | |
260 { | |
261 int i; | |
262 char tag[20]; | |
263 | |
264 i = (intptr_t) user_data; | |
265 snprintf(tag, sizeof(tag), "%c: Phase E:", i); | |
266 printf("%c: Phase E handler on channel %c - (%d) %s\n", i, i, result, t30_completion_code_to_str(result)); | |
267 log_transfer_statistics(s, tag); | |
268 log_tx_parameters(s, tag); | |
269 log_rx_parameters(s, tag); | |
270 } | |
271 /*- End of function --------------------------------------------------------*/ | |
272 | |
273 static void t30_real_time_frame_handler(t30_state_t *s, | |
274 void *user_data, | |
275 int direction, | |
276 const uint8_t *msg, | |
277 int len) | |
278 { | |
279 if (msg == NULL) | |
280 { | |
281 } | |
282 else | |
283 { | |
284 fprintf(stderr, | |
285 "T.30: Real time frame handler - %s, %s, length = %d\n", | |
286 (direction) ? "line->T.30" : "T.30->line", | |
287 t30_frametype(msg[2]), | |
288 len); | |
289 } | |
290 } | |
291 /*- End of function --------------------------------------------------------*/ | |
292 | |
293 static int document_handler(t30_state_t *s, void *user_data, int event) | |
294 { | |
295 int i; | |
296 | |
297 i = (intptr_t) user_data; | |
298 fprintf(stderr, "%d: Document handler on channel %d - event %d\n", i, i, event); | |
299 if (next_tx_file[0]) | |
300 { | |
301 t30_set_tx_file(s, next_tx_file, -1, -1); | |
302 next_tx_file[0] = '\0'; | |
303 return TRUE; | |
304 } | |
305 return FALSE; | |
306 } | |
307 /*- End of function --------------------------------------------------------*/ | |
308 | |
309 static void faxtester_real_time_frame_handler(faxtester_state_t *s, | |
310 void *user_data, | |
311 int direction, | |
312 const uint8_t *msg, | |
313 int len) | |
314 { | |
315 if (msg == NULL) | |
316 { | |
317 while (next_step(s) == 0) | |
318 ; | |
319 /*endwhile*/ | |
320 } | |
321 else | |
322 { | |
323 fprintf(stderr, | |
324 "TST: Real time frame handler - %s, %s, length = %d\n", | |
325 (direction) ? "line->tester" : "tester->line", | |
326 t30_frametype(msg[2]), | |
327 len); | |
328 if (direction && msg[1] == awaited[1]) | |
329 { | |
330 if ((awaited_len >= 0 && len != abs(awaited_len)) | |
331 || | |
332 (awaited_len < 0 && len < abs(awaited_len)) | |
333 || | |
334 memcmp(msg, awaited, abs(awaited_len)) != 0) | |
335 { | |
336 span_log_buf(&s->logging, SPAN_LOG_FLOW, "Expected", awaited, abs(awaited_len)); | |
337 span_log_buf(&s->logging, SPAN_LOG_FLOW, "Received", msg, len); | |
338 printf("Test failed\n"); | |
339 exit(2); | |
340 } | |
341 } | |
342 if (msg[1] == awaited[1]) | |
343 { | |
344 while (next_step(s) == 0) | |
345 ; | |
346 /*endwhile*/ | |
347 } | |
348 } | |
349 } | |
350 /*- End of function --------------------------------------------------------*/ | |
351 | |
352 static void faxtester_front_end_step_complete_handler(faxtester_state_t *s, void *user_data) | |
353 { | |
354 while (next_step(s) == 0) | |
355 ; | |
356 /*endwhile*/ | |
357 } | |
358 /*- End of function --------------------------------------------------------*/ | |
359 | |
360 static void faxtester_front_end_step_timeout_handler(faxtester_state_t *s, void *user_data) | |
361 { | |
362 span_log(&s->logging, SPAN_LOG_FLOW, "FAX tester step timed out\n"); | |
363 printf("Test failed\n"); | |
364 exit(2); | |
365 } | |
366 /*- End of function --------------------------------------------------------*/ | |
367 | |
368 static void fax_prepare(void) | |
369 { | |
370 t30_state_t *t30; | |
371 logging_state_t *logging; | |
372 | |
373 t30 = fax_get_t30_state(fax); | |
374 fax_set_transmit_on_idle(fax, TRUE); | |
375 fax_set_tep_mode(fax, TRUE); | |
376 #if 0 | |
377 t30_set_tx_ident(t30, "1234567890"); | |
378 t30_set_tx_sub_address(t30, "Sub-address"); | |
379 t30_set_tx_sender_ident(t30, "Sender ID"); | |
380 t30_set_tx_password(t30, "Password"); | |
381 t30_set_tx_polled_sub_address(t30, "Polled sub-address"); | |
382 t30_set_tx_selective_polling_address(t30, "Sel polling address"); | |
383 #endif | |
384 t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp NSF\x00", 16); | |
385 //t30_set_tx_nss(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp NSS\x00", 16); | |
386 t30_set_tx_nsc(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp NSC\x00", 16); | |
387 t30_set_ecm_capability(t30, TRUE); | |
388 t30_set_supported_t30_features(t30, | |
389 T30_SUPPORT_IDENTIFICATION | |
390 | T30_SUPPORT_SELECTIVE_POLLING | |
391 | T30_SUPPORT_SUB_ADDRESSING); | |
392 t30_set_supported_image_sizes(t30, | |
393 T30_SUPPORT_US_LETTER_LENGTH | |
394 | T30_SUPPORT_US_LEGAL_LENGTH | |
395 | T30_SUPPORT_UNLIMITED_LENGTH | |
396 | T30_SUPPORT_215MM_WIDTH | |
397 | T30_SUPPORT_255MM_WIDTH | |
398 | T30_SUPPORT_303MM_WIDTH); | |
399 t30_set_supported_resolutions(t30, | |
400 T30_SUPPORT_STANDARD_RESOLUTION | |
401 | T30_SUPPORT_FINE_RESOLUTION | |
402 | T30_SUPPORT_SUPERFINE_RESOLUTION | |
403 | T30_SUPPORT_R8_RESOLUTION | |
404 | T30_SUPPORT_R16_RESOLUTION | |
405 | T30_SUPPORT_300_300_RESOLUTION | |
406 | T30_SUPPORT_400_400_RESOLUTION | |
407 | T30_SUPPORT_600_600_RESOLUTION | |
408 | T30_SUPPORT_1200_1200_RESOLUTION | |
409 | T30_SUPPORT_300_600_RESOLUTION | |
410 | T30_SUPPORT_400_800_RESOLUTION | |
411 | T30_SUPPORT_600_1200_RESOLUTION); | |
412 t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17); | |
413 t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION); | |
414 t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'A'); | |
415 t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'A'); | |
416 t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'A'); | |
417 t30_set_real_time_frame_handler(t30, t30_real_time_frame_handler, (void *) (intptr_t) 'A'); | |
418 t30_set_document_handler(t30, document_handler, (void *) (intptr_t) 'A'); | |
419 | |
420 logging = fax_get_logging_state(fax); | |
421 span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW); | |
422 span_log_set_tag(logging, "A"); | |
423 | |
424 logging = t30_get_logging_state(t30); | |
425 span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW); | |
426 span_log_set_tag(logging, "A"); | |
427 | |
428 #if 0 | |
429 span_log_set_level(&fax.modems.v27ter_rx.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW); | |
430 span_log_set_tag(&fax.modems.v27ter_rx.logging, "A"); | |
431 span_log_set_level(&fax.modems.v29_rx.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW); | |
432 span_log_set_tag(&fax.modems.v29_rx.logging, "A"); | |
433 span_log_set_level(&fax.modems.v17_rx.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW); | |
434 span_log_set_tag(&fax.modems.v17_rx.logging, "A"); | |
435 #endif | |
436 } | |
437 /*- End of function --------------------------------------------------------*/ | |
438 | |
439 static int string_to_msg(uint8_t msg[], uint8_t mask[], const char buf[]) | |
440 { | |
441 int i; | |
442 int x; | |
443 const char *t; | |
444 | |
445 msg[0] = 0; | |
446 mask[0] = 0xFF; | |
447 i = 0; | |
448 t = (char *) buf; | |
449 while (*t) | |
450 { | |
451 /* Skip white space */ | |
452 while (isspace(*t)) | |
453 t++; | |
454 /* If we find ... we allow arbitrary addition info beyond this point in the message */ | |
455 if (t[0] == '.' && t[1] == '.' && t[2] == '.') | |
456 { | |
457 return -i; | |
458 } | |
459 else if (isxdigit(*t)) | |
460 { | |
461 for ( ; isxdigit(*t); t++) | |
462 { | |
463 x = *t; | |
464 if (x >= 'a') | |
465 x -= 0x20; | |
466 if (x >= 'A') | |
467 x -= ('A' - 10); | |
468 else | |
469 x -= '0'; | |
470 msg[i] = (msg[i] << 4) | x; | |
471 } | |
472 mask[i] = 0xFF; | |
473 if (*t == '/') | |
474 { | |
475 /* There is a mask following the byte */ | |
476 mask[i] = 0; | |
477 for (t++; isxdigit(*t); t++) | |
478 { | |
479 x = *t; | |
480 if (x >= 'a') | |
481 x -= 0x20; | |
482 if (x >= 'A') | |
483 x -= ('A' - 10); | |
484 else | |
485 x -= '0'; | |
486 mask[i] = (mask[i] << 4) | x; | |
487 } | |
488 } | |
489 if (*t && !isspace(*t)) | |
490 { | |
491 /* Bad string */ | |
492 return 0; | |
493 } | |
494 i++; | |
495 } | |
496 } | |
497 return i; | |
498 } | |
499 /*- End of function --------------------------------------------------------*/ | |
500 | |
501 #if 0 | |
502 static void string_test2(const uint8_t msg[], int len) | |
503 { | |
504 int i; | |
505 | |
506 if (len > 0) | |
507 { | |
508 for (i = 0; i < len - 1; i++) | |
509 printf("%02X ", msg[i]); | |
510 printf("%02X", msg[i]); | |
511 } | |
512 } | |
513 /*- End of function --------------------------------------------------------*/ | |
514 | |
515 static void string_test3(const char buf[]) | |
516 { | |
517 uint8_t msg[1000]; | |
518 uint8_t mask[1000]; | |
519 int len; | |
520 int i; | |
521 | |
522 len = string_to_msg(msg, mask, buf); | |
523 printf("Len = %d: ", len); | |
524 string_test2(msg, abs(len)); | |
525 printf("/"); | |
526 string_test2(mask, abs(len)); | |
527 printf("\n"); | |
528 } | |
529 /*- End of function --------------------------------------------------------*/ | |
530 | |
531 static int string_test(void) | |
532 { | |
533 string_test3("FF C8 12 34 56 78"); | |
534 string_test3("FF C8 12/55 34 56/aA 78 "); | |
535 string_test3("FF C8 12/55 34 56/aA 78 ..."); | |
536 string_test3("FF C8 12/55 34 56/aA 78..."); | |
537 string_test3("FF C8 12/55 34 56/aA 78 ... 99 88 77"); | |
538 exit(0); | |
539 } | |
540 /*- End of function --------------------------------------------------------*/ | |
541 #endif | |
542 | |
543 static void corrupt_image(faxtester_state_t *s, uint8_t image[], int len, const char *bad_rows) | |
544 { | |
545 int i; | |
546 int j; | |
547 int k; | |
548 uint32_t bits; | |
549 uint32_t bitsx; | |
550 int list[1000]; | |
551 int x; | |
552 int row; | |
553 const char *t; | |
554 | |
555 /* Form the list of rows to be hit */ | |
556 x = 0; | |
557 t = bad_rows; | |
558 while (*t) | |
559 { | |
560 while (isspace(*t)) | |
561 t++; | |
562 if (sscanf(t, "%d", &list[x]) < 1) | |
563 break; | |
564 x++; | |
565 while (isdigit(*t)) | |
566 t++; | |
567 if (*t == ',') | |
568 t++; | |
569 } | |
570 | |
571 /* Go through the image, and corrupt the first bit of every listed row */ | |
572 bits = 0x7FF; | |
573 bitsx = 0x7FF; | |
574 row = 0; | |
575 for (i = 0; i < len; i++) | |
576 { | |
577 bits ^= (image[i] << 11); | |
578 bitsx ^= (image[i] << 11); | |
579 for (j = 0; j < 8; j++) | |
580 { | |
581 if ((bits & 0xFFF) == 0x800) | |
582 { | |
583 /* We are at an EOL. Is this row in the list of rows to be corrupted? */ | |
584 row++; | |
585 for (k = 0; k < x; k++) | |
586 { | |
587 if (list[k] == row) | |
588 { | |
589 /* Corrupt this row. TSB85 says to hit the first bit after the EOL */ | |
590 bitsx ^= 0x1000; | |
591 } | |
592 } | |
593 } | |
594 bits >>= 1; | |
595 bitsx >>= 1; | |
596 } | |
597 image[i] = (bitsx >> 3) & 0xFF; | |
598 } | |
599 span_log(&s->logging, SPAN_LOG_FLOW, "%d rows found. %d corrupted\n", row, x); | |
600 } | |
601 /*- End of function --------------------------------------------------------*/ | |
602 | |
603 static int next_step(faxtester_state_t *s) | |
604 { | |
605 int delay; | |
606 int flags; | |
607 xmlChar *dir; | |
608 xmlChar *type; | |
609 xmlChar *modem; | |
610 xmlChar *value; | |
611 xmlChar *tag; | |
612 xmlChar *bad_rows; | |
613 xmlChar *crc_error; | |
614 xmlChar *pattern; | |
615 xmlChar *timeout; | |
616 xmlChar *min_bits; | |
617 xmlChar *frame_size; | |
618 xmlChar *block; | |
619 xmlChar *compression; | |
620 uint8_t buf[1000]; | |
621 uint8_t mask[1000]; | |
622 char path[1024]; | |
623 int i; | |
624 int j; | |
625 int hdlc; | |
626 int short_train; | |
627 int min_row_bits; | |
628 int ecm_frame_size; | |
629 int ecm_block; | |
630 int compression_type; | |
631 int timer; | |
632 int len; | |
633 t4_state_t t4_state; | |
634 t30_state_t *t30; | |
635 | |
636 if (s->cur == NULL) | |
637 { | |
638 if (!s->final_delayed) | |
639 { | |
640 /* Add a bit of waiting at the end, to ensure everything gets flushed through, | |
641 any timers can expire, etc. */ | |
642 faxtester_set_timeout(s, -1); | |
643 faxtester_set_rx_type(s, T30_MODEM_NONE, 0, FALSE, FALSE); | |
644 faxtester_set_tx_type(s, T30_MODEM_PAUSE, 0, 120000, FALSE); | |
645 s->final_delayed = TRUE; | |
646 return 1; | |
647 } | |
648 /* Finished */ | |
649 printf("Test passed\n"); | |
650 exit(0); | |
651 } | |
652 while (s->cur && xmlStrcmp(s->cur->name, (const xmlChar *) "step") != 0) | |
653 s->cur = s->cur->next; | |
654 if (s->cur == NULL) | |
655 { | |
656 /* Finished */ | |
657 printf("Test passed\n"); | |
658 exit(0); | |
659 } | |
660 | |
661 dir = xmlGetProp(s->cur, (const xmlChar *) "dir"); | |
662 type = xmlGetProp(s->cur, (const xmlChar *) "type"); | |
663 modem = xmlGetProp(s->cur, (const xmlChar *) "modem"); | |
664 value = xmlGetProp(s->cur, (const xmlChar *) "value"); | |
665 tag = xmlGetProp(s->cur, (const xmlChar *) "tag"); | |
666 bad_rows = xmlGetProp(s->cur, (const xmlChar *) "bad_rows"); | |
667 crc_error = xmlGetProp(s->cur, (const xmlChar *) "crc_error"); | |
668 pattern = xmlGetProp(s->cur, (const xmlChar *) "pattern"); | |
669 timeout = xmlGetProp(s->cur, (const xmlChar *) "timeout"); | |
670 min_bits = xmlGetProp(s->cur, (const xmlChar *) "min_bits"); | |
671 frame_size = xmlGetProp(s->cur, (const xmlChar *) "frame_size"); | |
672 block = xmlGetProp(s->cur, (const xmlChar *) "block"); | |
673 compression = xmlGetProp(s->cur, (const xmlChar *) "compression"); | |
674 | |
675 s->cur = s->cur->next; | |
676 | |
677 span_log(&s->logging, | |
678 SPAN_LOG_FLOW, | |
679 "Dir - %s, type - %s, modem - %s, value - %s, timeout - %s, tag - %s\n", | |
680 (dir) ? (const char *) dir : "", | |
681 (type) ? (const char *) type : "", | |
682 (modem) ? (const char *) modem : "", | |
683 (value) ? (const char *) value : "", | |
684 (timeout) ? (const char *) timeout : "", | |
685 (tag) ? (const char *) tag : ""); | |
686 if (type == NULL) | |
687 return 1; | |
688 if (timeout) | |
689 timer = atoi((const char *) timeout); | |
690 else | |
691 timer = -1; | |
692 | |
693 if (dir && strcasecmp((const char *) dir, "R") == 0) | |
694 { | |
695 /* Receive always has a timeout applied. */ | |
696 if (timer < 0) | |
697 timer = 7000; | |
698 faxtester_set_timeout(s, timer); | |
699 if (modem) | |
700 { | |
701 hdlc = (strcasecmp((const char *) type, "PREAMBLE") == 0); | |
702 short_train = (strcasecmp((const char *) type, "TCF") != 0); | |
703 faxtester_set_tx_type(s, T30_MODEM_NONE, 0, FALSE, FALSE); | |
704 if (strcasecmp((const char *) modem, "V.21") == 0) | |
705 { | |
706 faxtester_set_rx_type(s, T30_MODEM_V21, 300, FALSE, TRUE); | |
707 } | |
708 else if (strcasecmp((const char *) modem, "V.17/14400") == 0) | |
709 { | |
710 faxtester_set_rx_type(s, T30_MODEM_V17, 14400, short_train, hdlc); | |
711 } | |
712 else if (strcasecmp((const char *) modem, "V.17/12000") == 0) | |
713 { | |
714 faxtester_set_rx_type(s, T30_MODEM_V17, 12000, short_train, hdlc); | |
715 } | |
716 else if (strcasecmp((const char *) modem, "V.17/9600") == 0) | |
717 { | |
718 faxtester_set_rx_type(s, T30_MODEM_V17, 9600, short_train, hdlc); | |
719 } | |
720 else if (strcasecmp((const char *) modem, "V.17/7200") == 0) | |
721 { | |
722 faxtester_set_rx_type(s, T30_MODEM_V17, 7200, short_train, hdlc); | |
723 } | |
724 else if (strcasecmp((const char *) modem, "V.29/9600") == 0) | |
725 { | |
726 faxtester_set_rx_type(s, T30_MODEM_V29, 9600, FALSE, hdlc); | |
727 } | |
728 else if (strcasecmp((const char *) modem, "V.29/7200") == 0) | |
729 { | |
730 faxtester_set_rx_type(s, T30_MODEM_V29, 7200, FALSE, hdlc); | |
731 } | |
732 else if (strcasecmp((const char *) modem, "V.27ter/4800") == 0) | |
733 { | |
734 faxtester_set_rx_type(s, T30_MODEM_V27TER, 4800, FALSE, hdlc); | |
735 } | |
736 else if (strcasecmp((const char *) modem, "V.27ter/2400") == 0) | |
737 { | |
738 faxtester_set_rx_type(s, T30_MODEM_V27TER, 2400, FALSE, hdlc); | |
739 } | |
740 else | |
741 { | |
742 span_log(&s->logging, SPAN_LOG_FLOW, "Unrecognised modem\n"); | |
743 } | |
744 } | |
745 | |
746 if (strcasecmp((const char *) type, "SET") == 0) | |
747 { | |
748 if (strcasecmp((const char *) tag, "IDENT") == 0) | |
749 strcpy(expected_rx_info.ident, (const char *) value); | |
750 else if (strcasecmp((const char *) tag, "SUB") == 0) | |
751 strcpy(expected_rx_info.sub_address, (const char *) value); | |
752 else if (strcasecmp((const char *) tag, "SEP") == 0) | |
753 strcpy(expected_rx_info.selective_polling_address, (const char *) value); | |
754 else if (strcasecmp((const char *) tag, "PSA") == 0) | |
755 strcpy(expected_rx_info.polled_sub_address, (const char *) value); | |
756 else if (strcasecmp((const char *) tag, "SID") == 0) | |
757 strcpy(expected_rx_info.sender_ident, (const char *) value); | |
758 else if (strcasecmp((const char *) tag, "PWD") == 0) | |
759 strcpy(expected_rx_info.password, (const char *) value); | |
760 return 0; | |
761 } | |
762 else if (strcasecmp((const char *) type, "CNG") == 0) | |
763 { | |
764 /* Look for CNG */ | |
765 faxtester_set_rx_type(s, T30_MODEM_CNG, 0, FALSE, FALSE); | |
766 faxtester_set_tx_type(s, T30_MODEM_NONE, 0, FALSE, FALSE); | |
767 } | |
768 else if (strcasecmp((const char *) type, "CED") == 0) | |
769 { | |
770 /* Look for CED */ | |
771 faxtester_set_rx_type(s, T30_MODEM_CED, 0, FALSE, FALSE); | |
772 faxtester_set_tx_type(s, T30_MODEM_NONE, 0, FALSE, FALSE); | |
773 } | |
774 else if (strcasecmp((const char *) type, "HDLC") == 0) | |
775 { | |
776 i = string_to_msg(buf, mask, (const char *) value); | |
777 bit_reverse(awaited, buf, abs(i)); | |
778 awaited_len = i; | |
779 } | |
780 else if (strcasecmp((const char *) type, "TCF") == 0) | |
781 { | |
782 } | |
783 else if (strcasecmp((const char *) type, "MSG") == 0) | |
784 { | |
785 } | |
786 else if (strcasecmp((const char *) type, "PP") == 0) | |
787 { | |
788 } | |
789 else if (strcasecmp((const char *) type, "SILENCE") == 0) | |
790 { | |
791 faxtest_set_rx_silence(s); | |
792 } | |
793 else | |
794 { | |
795 span_log(&s->logging, SPAN_LOG_FLOW, "Unrecognised type '%s'\n", (const char *) type); | |
796 return 0; | |
797 } | |
798 } | |
799 else | |
800 { | |
801 faxtester_set_timeout(s, timer); | |
802 if (modem) | |
803 { | |
804 hdlc = (strcasecmp((const char *) type, "PREAMBLE") == 0); | |
805 short_train = (strcasecmp((const char *) type, "TCF") != 0); | |
806 faxtester_set_rx_type(s, T30_MODEM_NONE, 0, FALSE, FALSE); | |
807 if (strcasecmp((const char *) modem, "V.21") == 0) | |
808 { | |
809 faxtester_set_tx_type(s, T30_MODEM_V21, 300, FALSE, TRUE); | |
810 } | |
811 else if (strcasecmp((const char *) modem, "V.17/14400") == 0) | |
812 { | |
813 faxtester_set_tx_type(s, T30_MODEM_V17, 14400, short_train, hdlc); | |
814 } | |
815 else if (strcasecmp((const char *) modem, "V.17/12000") == 0) | |
816 { | |
817 faxtester_set_tx_type(s, T30_MODEM_V17, 12000, short_train, hdlc); | |
818 } | |
819 else if (strcasecmp((const char *) modem, "V.17/9600") == 0) | |
820 { | |
821 faxtester_set_tx_type(s, T30_MODEM_V17, 9600, short_train, hdlc); | |
822 } | |
823 else if (strcasecmp((const char *) modem, "V.17/7200") == 0) | |
824 { | |
825 faxtester_set_tx_type(s, T30_MODEM_V17, 7200, short_train, hdlc); | |
826 } | |
827 else if (strcasecmp((const char *) modem, "V.29/9600") == 0) | |
828 { | |
829 faxtester_set_tx_type(s, T30_MODEM_V29, 9600, FALSE, hdlc); | |
830 } | |
831 else if (strcasecmp((const char *) modem, "V.29/7200") == 0) | |
832 { | |
833 faxtester_set_tx_type(s, T30_MODEM_V29, 7200, FALSE, hdlc); | |
834 } | |
835 else if (strcasecmp((const char *) modem, "V.27ter/4800") == 0) | |
836 { | |
837 faxtester_set_tx_type(s, T30_MODEM_V27TER, 4800, FALSE, hdlc); | |
838 } | |
839 else if (strcasecmp((const char *) modem, "V.27ter/2400") == 0) | |
840 { | |
841 faxtester_set_tx_type(s, T30_MODEM_V27TER, 2400, FALSE, hdlc); | |
842 } | |
843 else | |
844 { | |
845 span_log(&s->logging, SPAN_LOG_FLOW, "Unrecognised modem\n"); | |
846 } | |
847 } | |
848 | |
849 if (strcasecmp((const char *) type, "SET") == 0) | |
850 { | |
851 t30 = fax_get_t30_state(fax); | |
852 if (strcasecmp((const char *) tag, "IDENT") == 0) | |
853 t30_set_tx_ident(t30, (const char *) value); | |
854 else if (strcasecmp((const char *) tag, "SUB") == 0) | |
855 t30_set_tx_sub_address(t30, (const char *) value); | |
856 else if (strcasecmp((const char *) tag, "SEP") == 0) | |
857 t30_set_tx_selective_polling_address(t30, (const char *) value); | |
858 else if (strcasecmp((const char *) tag, "PSA") == 0) | |
859 t30_set_tx_polled_sub_address(t30, (const char *) value); | |
860 else if (strcasecmp((const char *) tag, "SID") == 0) | |
861 t30_set_tx_sender_ident(t30, (const char *) value); | |
862 else if (strcasecmp((const char *) tag, "PWD") == 0) | |
863 t30_set_tx_password(t30, (const char *) value); | |
864 else if (strcasecmp((const char *) tag, "RXFILE") == 0) | |
865 { | |
866 if (value) | |
867 t30_set_rx_file(t30, (const char *) value, -1); | |
868 else | |
869 t30_set_rx_file(t30, output_tiff_file_name, -1); | |
870 } | |
871 else if (strcasecmp((const char *) tag, "TXFILE") == 0) | |
872 { | |
873 sprintf(next_tx_file, "%s/%s", image_path, (const char *) value); | |
874 printf("Push '%s'\n", next_tx_file); | |
875 } | |
876 return 0; | |
877 } | |
878 else if (strcasecmp((const char *) type, "CALL") == 0) | |
879 { | |
880 fax = fax_init(NULL, FALSE); | |
881 fax_prepare(); | |
882 next_tx_file[0] = '\0'; | |
883 t30 = fax_get_t30_state(fax); | |
884 t30_set_rx_file(t30, output_tiff_file_name, -1); | |
885 /* Avoid libtiff 3.8.2 and earlier bug on complex 2D lines. */ | |
886 t30_set_rx_encoding(t30, T4_COMPRESSION_ITU_T4_1D); | |
887 if (value) | |
888 { | |
889 sprintf(path, "%s/%s", image_path, (const char *) value); | |
890 t30_set_tx_file(t30, path, -1, -1); | |
891 } | |
892 return 0; | |
893 } | |
894 else if (strcasecmp((const char *) type, "ANSWER") == 0) | |
895 { | |
896 fax = fax_init(NULL, TRUE); | |
897 fax_prepare(); | |
898 next_tx_file[0] = '\0'; | |
899 t30 = fax_get_t30_state(fax); | |
900 /* Avoid libtiff 3.8.2 and earlier bug on complex 2D lines. */ | |
901 t30_set_rx_encoding(t30, T4_COMPRESSION_ITU_T4_1D); | |
902 if (value) | |
903 { | |
904 sprintf(path, "%s/%s", image_path, (const char *) value); | |
905 t30_set_tx_file(t30, path, -1, -1); | |
906 } | |
907 return 0; | |
908 } | |
909 else if (strcasecmp((const char *) type, "CNG") == 0) | |
910 { | |
911 faxtester_set_rx_type(s, T30_MODEM_NONE, 0, FALSE, FALSE); | |
912 faxtester_set_tx_type(s, T30_MODEM_CNG, 0, FALSE, FALSE); | |
913 } | |
914 else if (strcasecmp((const char *) type, "CED") == 0) | |
915 { | |
916 faxtester_set_rx_type(s, T30_MODEM_NONE, 0, FALSE, FALSE); | |
917 faxtester_set_tx_type(s, T30_MODEM_CED, 0, FALSE, FALSE); | |
918 } | |
919 else if (strcasecmp((const char *) type, "WAIT") == 0) | |
920 { | |
921 delay = (value) ? atoi((const char *) value) : 1; | |
922 faxtester_set_rx_type(s, T30_MODEM_NONE, 0, FALSE, FALSE); | |
923 faxtester_set_tx_type(s, T30_MODEM_PAUSE, 0, delay, FALSE); | |
924 } | |
925 else if (strcasecmp((const char *) type, "PREAMBLE") == 0) | |
926 { | |
927 flags = (value) ? atoi((const char *) value) : 37; | |
928 faxtester_send_hdlc_flags(s, flags); | |
929 } | |
930 else if (strcasecmp((const char *) type, "POSTAMBLE") == 0) | |
931 { | |
932 flags = (value) ? atoi((const char *) value) : 5; | |
933 faxtester_send_hdlc_flags(s, flags); | |
934 } | |
935 else if (strcasecmp((const char *) type, "HDLC") == 0) | |
936 { | |
937 i = string_to_msg(buf, mask, (const char *) value); | |
938 bit_reverse(buf, buf, abs(i)); | |
939 if (crc_error && strcasecmp((const char *) crc_error, "0") == 0) | |
940 faxtester_send_hdlc_msg(s, buf, abs(i), FALSE); | |
941 else | |
942 faxtester_send_hdlc_msg(s, buf, abs(i), TRUE); | |
943 } | |
944 else if (strcasecmp((const char *) type, "TCF") == 0) | |
945 { | |
946 if (value) | |
947 i = atoi((const char *) value); | |
948 else | |
949 i = 450; | |
950 if (pattern) | |
951 { | |
952 /* TODO: implement proper patterns */ | |
953 j = atoi((const char *) pattern); | |
954 memset(image, 0x55, j); | |
955 if (i > j) | |
956 memset(image + j, 0, i - j); | |
957 } | |
958 else | |
959 { | |
960 memset(image, 0, i); | |
961 } | |
962 faxtester_set_non_ecm_image_buffer(s, image, i); | |
963 } | |
964 else if (strcasecmp((const char *) type, "MSG") == 0) | |
965 { | |
966 /* A non-ECM page */ | |
967 min_row_bits = (min_bits) ? atoi((const char *) min_bits) : 0; | |
968 sprintf(path, "%s/%s", image_path, (const char *) value); | |
969 if (t4_tx_init(&t4_state, path, -1, -1) == NULL) | |
970 { | |
971 span_log(&s->logging, SPAN_LOG_FLOW, "Failed to init T.4 send\n"); | |
972 printf("Test failed\n"); | |
973 exit(2); | |
974 } | |
975 t4_tx_set_min_row_bits(&t4_state, min_row_bits); | |
976 t4_tx_set_header_info(&t4_state, NULL); | |
977 compression_type = T4_COMPRESSION_ITU_T4_1D; | |
978 if (compression) | |
979 { | |
980 if (strcasecmp((const char *) compression, "T.4 2D") == 0) | |
981 compression_type = T4_COMPRESSION_ITU_T4_2D; | |
982 else if (strcasecmp((const char *) compression, "T.6") == 0) | |
983 compression_type = T4_COMPRESSION_ITU_T6; | |
984 } | |
985 t4_tx_set_tx_encoding(&t4_state, compression_type); | |
986 if (t4_tx_start_page(&t4_state)) | |
987 { | |
988 span_log(&s->logging, SPAN_LOG_FLOW, "Failed to start T.4 send\n"); | |
989 printf("Test failed\n"); | |
990 exit(2); | |
991 } | |
992 len = t4_tx_get_chunk(&t4_state, image, sizeof(image)); | |
993 if (bad_rows) | |
994 { | |
995 span_log(&s->logging, SPAN_LOG_FLOW, "We need to corrupt the image\n"); | |
996 corrupt_image(s, image, len, (const char *) bad_rows); | |
997 } | |
998 t4_tx_release(&t4_state); | |
999 span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM image is %d bytes\n", len); | |
1000 faxtester_set_non_ecm_image_buffer(s, image, len); | |
1001 } | |
1002 else if (strcasecmp((const char *) type, "PP") == 0) | |
1003 { | |
1004 min_row_bits = (min_bits) ? atoi((const char *) min_bits) : 0; | |
1005 ecm_block = (block) ? atoi((const char *) block) : 0; | |
1006 ecm_frame_size = (frame_size) ? atoi((const char *) frame_size) : 64; | |
1007 i = (crc_error) ? atoi((const char *) crc_error) : -1; | |
1008 sprintf(path, "%s/%s", image_path, (const char *) value); | |
1009 if (t4_tx_init(&t4_state, path, -1, -1) == NULL) | |
1010 { | |
1011 span_log(&s->logging, SPAN_LOG_FLOW, "Failed to init T.4 send\n"); | |
1012 printf("Test failed\n"); | |
1013 exit(2); | |
1014 } | |
1015 t4_tx_set_min_row_bits(&t4_state, min_row_bits); | |
1016 t4_tx_set_header_info(&t4_state, NULL); | |
1017 compression_type = T4_COMPRESSION_ITU_T4_1D; | |
1018 if (compression) | |
1019 { | |
1020 if (strcasecmp((const char *) compression, "T.4 2D") == 0) | |
1021 compression_type = T4_COMPRESSION_ITU_T4_2D; | |
1022 else if (strcasecmp((const char *) compression, "T.6") == 0) | |
1023 compression_type = T4_COMPRESSION_ITU_T6; | |
1024 } | |
1025 t4_tx_set_tx_encoding(&t4_state, compression_type); | |
1026 if (t4_tx_start_page(&t4_state)) | |
1027 { | |
1028 span_log(&s->logging, SPAN_LOG_FLOW, "Failed to start T.4 send\n"); | |
1029 printf("Test failed\n"); | |
1030 exit(2); | |
1031 } | |
1032 /*endif*/ | |
1033 len = t4_tx_get_chunk(&t4_state, image, sizeof(image)); | |
1034 if (bad_rows) | |
1035 { | |
1036 span_log(&s->logging, SPAN_LOG_FLOW, "We need to corrupt the image\n"); | |
1037 corrupt_image(s, image, len, (const char *) bad_rows); | |
1038 } | |
1039 /*endif*/ | |
1040 t4_tx_release(&t4_state); | |
1041 span_log(&s->logging, SPAN_LOG_FLOW, "ECM image is %d bytes\n", len); | |
1042 faxtester_set_ecm_image_buffer(s, image, len, ecm_block, ecm_frame_size, i); | |
1043 } | |
1044 else | |
1045 { | |
1046 span_log(&s->logging, SPAN_LOG_FLOW, "Unrecognised type '%s'\n", (const char *) type); | |
1047 return 0; | |
1048 } | |
1049 /*endif*/ | |
1050 } | |
1051 /*endif*/ | |
1052 return 1; | |
1053 } | |
1054 /*- End of function --------------------------------------------------------*/ | |
1055 | |
1056 static void exchange(faxtester_state_t *s) | |
1057 { | |
1058 int16_t amp[SAMPLES_PER_CHUNK]; | |
1059 int16_t out_amp[2*SAMPLES_PER_CHUNK]; | |
1060 int len; | |
1061 int i; | |
1062 int total_audio_time; | |
1063 int log_audio; | |
1064 logging_state_t *logging; | |
1065 | |
1066 log_audio = TRUE; | |
1067 output_tiff_file_name = OUTPUT_TIFF_FILE_NAME; | |
1068 | |
1069 if (log_audio) | |
1070 { | |
1071 if ((out_handle = sf_open_telephony_write(OUTPUT_FILE_NAME_WAVE, 2)) == NULL) | |
1072 { | |
1073 fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_FILE_NAME_WAVE); | |
1074 printf("Test failed\n"); | |
1075 exit(2); | |
1076 } | |
1077 /*endif*/ | |
1078 } | |
1079 /*endif*/ | |
1080 | |
1081 total_audio_time = 0; | |
1082 | |
1083 faxtester_set_transmit_on_idle(&state, TRUE); | |
1084 faxtester_set_real_time_frame_handler(&state, faxtester_real_time_frame_handler, NULL); | |
1085 faxtester_set_front_end_step_complete_handler(&state, faxtester_front_end_step_complete_handler, NULL); | |
1086 faxtester_set_front_end_step_timeout_handler(&state, faxtester_front_end_step_timeout_handler, NULL); | |
1087 | |
1088 fax = fax_init(NULL, FALSE); | |
1089 fax_prepare(); | |
1090 next_tx_file[0] = '\0'; | |
1091 | |
1092 while (next_step(s) == 0) | |
1093 ; | |
1094 /*endwhile*/ | |
1095 for (;;) | |
1096 { | |
1097 len = fax_tx(fax, amp, SAMPLES_PER_CHUNK); | |
1098 faxtester_rx(s, amp, len); | |
1099 if (log_audio) | |
1100 { | |
1101 for (i = 0; i < len; i++) | |
1102 out_amp[2*i + 0] = amp[i]; | |
1103 /*endfor*/ | |
1104 } | |
1105 /*endif*/ | |
1106 | |
1107 total_audio_time += SAMPLES_PER_CHUNK; | |
1108 | |
1109 logging = t30_get_logging_state(fax_get_t30_state(fax)); | |
1110 span_log_bump_samples(logging, len); | |
1111 #if 0 | |
1112 span_log_bump_samples(&fax.modems.v27ter_rx.logging, len); | |
1113 span_log_bump_samples(&fax.modems.v29_rx.logging, len); | |
1114 span_log_bump_samples(&fax.modems.v17_rx.logging, len); | |
1115 #endif | |
1116 logging = fax_get_logging_state(fax); | |
1117 span_log_bump_samples(logging, len); | |
1118 | |
1119 span_log_bump_samples(&s->logging, len); | |
1120 | |
1121 len = faxtester_tx(s, amp, 160); | |
1122 if (fax_rx(fax, amp, len)) | |
1123 break; | |
1124 /*endif*/ | |
1125 if (log_audio) | |
1126 { | |
1127 for (i = 0; i < len; i++) | |
1128 out_amp[2*i + 1] = amp[i]; | |
1129 /*endfor*/ | |
1130 if (sf_writef_short(out_handle, out_amp, SAMPLES_PER_CHUNK) != SAMPLES_PER_CHUNK) | |
1131 break; | |
1132 /*endif*/ | |
1133 } | |
1134 /*endif*/ | |
1135 } | |
1136 /*endfor*/ | |
1137 if (log_audio) | |
1138 { | |
1139 if (sf_close(out_handle)) | |
1140 { | |
1141 fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME_WAVE); | |
1142 printf("Test failed\n"); | |
1143 exit(2); | |
1144 } | |
1145 /*endif*/ | |
1146 } | |
1147 /*endif*/ | |
1148 } | |
1149 /*- End of function --------------------------------------------------------*/ | |
1150 | |
1151 static int parse_config(faxtester_state_t *s, xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur) | |
1152 { | |
1153 xmlChar *x; | |
1154 xmlChar *y; | |
1155 | |
1156 while (cur) | |
1157 { | |
1158 if (xmlStrcmp(cur->name, (const xmlChar *) "path") == 0) | |
1159 { | |
1160 if ((x = xmlGetProp(cur, (const xmlChar *) "type")) | |
1161 && | |
1162 (y = xmlGetProp(cur, (const xmlChar *) "value"))) | |
1163 { | |
1164 if (strcasecmp((const char *) x, "IMAGE") == 0) | |
1165 { | |
1166 span_log(&s->logging, SPAN_LOG_FLOW, "Found '%s' '%s'\n", (char *) x, (char *) y); | |
1167 strcpy(image_path, (const char *) y); | |
1168 } | |
1169 /*endif*/ | |
1170 } | |
1171 /*endif*/ | |
1172 } | |
1173 /*endif*/ | |
1174 cur = cur->next; | |
1175 } | |
1176 /*endwhile*/ | |
1177 return -1; | |
1178 } | |
1179 /*- End of function --------------------------------------------------------*/ | |
1180 | |
1181 static int parse_test_group(faxtester_state_t *s, xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur, const char *test) | |
1182 { | |
1183 xmlChar *x; | |
1184 | |
1185 while (cur) | |
1186 { | |
1187 if (xmlStrcmp(cur->name, (const xmlChar *) "test") == 0) | |
1188 { | |
1189 if ((x = xmlGetProp(cur, (const xmlChar *) "name"))) | |
1190 { | |
1191 if (xmlStrcmp(x, (const xmlChar *) test) == 0) | |
1192 { | |
1193 span_log(&s->logging, SPAN_LOG_FLOW, "Found '%s'\n", (char *) x); | |
1194 s->cur = cur->xmlChildrenNode; | |
1195 return 0; | |
1196 } | |
1197 /*endif*/ | |
1198 } | |
1199 /*endif*/ | |
1200 } | |
1201 /*endif*/ | |
1202 cur = cur->next; | |
1203 } | |
1204 /*endwhile*/ | |
1205 return -1; | |
1206 } | |
1207 /*- End of function --------------------------------------------------------*/ | |
1208 | |
1209 static int get_test_set(faxtester_state_t *s, const char *test_file, const char *test) | |
1210 { | |
1211 xmlDocPtr doc; | |
1212 xmlNsPtr ns; | |
1213 xmlNodePtr cur; | |
1214 xmlValidCtxt valid; | |
1215 | |
1216 ns = NULL; | |
1217 xmlKeepBlanksDefault(0); | |
1218 xmlCleanupParser(); | |
1219 if ((doc = xmlParseFile(test_file)) == NULL) | |
1220 { | |
1221 fprintf(stderr, "No document\n"); | |
1222 printf("Test failed\n"); | |
1223 exit(2); | |
1224 } | |
1225 /*endif*/ | |
1226 xmlXIncludeProcess(doc); | |
1227 if (!xmlValidateDocument(&valid, doc)) | |
1228 { | |
1229 fprintf(stderr, "Invalid document\n"); | |
1230 printf("Test failed\n"); | |
1231 exit(2); | |
1232 } | |
1233 /*endif*/ | |
1234 | |
1235 /* Check the document is of the right kind */ | |
1236 if ((cur = xmlDocGetRootElement(doc)) == NULL) | |
1237 { | |
1238 xmlFreeDoc(doc); | |
1239 fprintf(stderr, "Empty document\n"); | |
1240 printf("Test failed\n"); | |
1241 exit(2); | |
1242 } | |
1243 /*endif*/ | |
1244 if (xmlStrcmp(cur->name, (const xmlChar *) "fax-tests")) | |
1245 { | |
1246 xmlFreeDoc(doc); | |
1247 fprintf(stderr, "Document of the wrong type, root node != fax-tests"); | |
1248 printf("Test failed\n"); | |
1249 exit(2); | |
1250 } | |
1251 /*endif*/ | |
1252 cur = cur->xmlChildrenNode; | |
1253 while (cur && xmlIsBlankNode(cur)) | |
1254 cur = cur->next; | |
1255 /*endwhile*/ | |
1256 if (cur == NULL) | |
1257 { | |
1258 printf("Test failed\n"); | |
1259 exit(2); | |
1260 } | |
1261 /*endif*/ | |
1262 while (cur) | |
1263 { | |
1264 if (xmlStrcmp(cur->name, (const xmlChar *) "config") == 0) | |
1265 { | |
1266 parse_config(s, doc, ns, cur->xmlChildrenNode); | |
1267 } | |
1268 /*endif*/ | |
1269 if (xmlStrcmp(cur->name, (const xmlChar *) "test-group") == 0) | |
1270 { | |
1271 if (parse_test_group(s, doc, ns, cur->xmlChildrenNode, test) == 0) | |
1272 { | |
1273 /* We found the test we want, so run it. */ | |
1274 exchange(s); | |
1275 break; | |
1276 } | |
1277 /*endif*/ | |
1278 } | |
1279 /*endif*/ | |
1280 cur = cur->next; | |
1281 } | |
1282 /*endwhile*/ | |
1283 xmlFreeDoc(doc); | |
1284 return 0; | |
1285 } | |
1286 /*- End of function --------------------------------------------------------*/ | |
1287 | |
1288 int main(int argc, char *argv[]) | |
1289 { | |
1290 const char *test_name; | |
1291 | |
1292 //string_test(); | |
1293 | |
1294 test_name = "MRGN01"; | |
1295 if (argc > 1) | |
1296 test_name = argv[1]; | |
1297 | |
1298 strcpy(image_path, "."); | |
1299 faxtester_init(&state, TRUE); | |
1300 memset(&expected_rx_info, 0, sizeof(expected_rx_info)); | |
1301 span_log_set_level(&state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW); | |
1302 span_log_set_tag(&state.logging, "B"); | |
1303 get_test_set(&state, "../spandsp/tsb85.xml", test_name); | |
1304 printf("Done\n"); | |
1305 return 0; | |
1306 } | |
1307 /*- End of function --------------------------------------------------------*/ | |
1308 /*- End of file ------------------------------------------------------------*/ |