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 ------------------------------------------------------------*/ |
