Mercurial > hg > audiostuff
comparison spandsp-0.0.6pre17/tests/fax_tester.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 * faxtester_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: fax_tester.c,v 1.23 2009/11/02 13:25:20 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 #if defined(HAVE_TGMATH_H) | |
| 39 #include <tgmath.h> | |
| 40 #endif | |
| 41 #if defined(HAVE_MATH_H) | |
| 42 #include <math.h> | |
| 43 #endif | |
| 44 #include "floating_fudge.h" | |
| 45 #include <assert.h> | |
| 46 #include <fcntl.h> | |
| 47 #include <time.h> | |
| 48 #include <unistd.h> | |
| 49 | |
| 50 #if defined(HAVE_LIBXML_XMLMEMORY_H) | |
| 51 #include <libxml/xmlmemory.h> | |
| 52 #endif | |
| 53 #if defined(HAVE_LIBXML_PARSER_H) | |
| 54 #include <libxml/parser.h> | |
| 55 #endif | |
| 56 #if defined(HAVE_LIBXML_XINCLUDE_H) | |
| 57 #include <libxml/xinclude.h> | |
| 58 #endif | |
| 59 | |
| 60 //#if defined(WITH_SPANDSP_INTERNALS) | |
| 61 #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES | |
| 62 //#endif | |
| 63 | |
| 64 #include "spandsp.h" | |
| 65 | |
| 66 #include "fax_tester.h" | |
| 67 | |
| 68 #define HDLC_FRAMING_OK_THRESHOLD 5 | |
| 69 | |
| 70 static void timer_update(faxtester_state_t *s, int len) | |
| 71 { | |
| 72 s->timer += len; | |
| 73 if (s->timer > s->timeout) | |
| 74 { | |
| 75 s->timeout = 0x7FFFFFFFFFFFFFFFLL; | |
| 76 if (s->front_end_step_timeout_handler) | |
| 77 s->front_end_step_timeout_handler(s, s->front_end_step_timeout_user_data); | |
| 78 } | |
| 79 } | |
| 80 /*- End of function --------------------------------------------------------*/ | |
| 81 | |
| 82 static void front_end_step_complete(faxtester_state_t *s) | |
| 83 { | |
| 84 if (s->front_end_step_complete_handler) | |
| 85 s->front_end_step_complete_handler(s, s->front_end_step_complete_user_data); | |
| 86 } | |
| 87 /*- End of function --------------------------------------------------------*/ | |
| 88 | |
| 89 void faxtester_send_hdlc_flags(faxtester_state_t *s, int flags) | |
| 90 { | |
| 91 hdlc_tx_flags(&(s->modems.hdlc_tx), flags); | |
| 92 } | |
| 93 /*- End of function --------------------------------------------------------*/ | |
| 94 | |
| 95 void faxtester_send_hdlc_msg(faxtester_state_t *s, const uint8_t *msg, int len, int crc_ok) | |
| 96 { | |
| 97 hdlc_tx_frame(&(s->modems.hdlc_tx), msg, len); | |
| 98 if (!crc_ok) | |
| 99 hdlc_tx_corrupt_frame(&(s->modems.hdlc_tx)); | |
| 100 } | |
| 101 /*- End of function --------------------------------------------------------*/ | |
| 102 | |
| 103 static void hdlc_underflow_handler(void *user_data) | |
| 104 { | |
| 105 faxtester_state_t *s; | |
| 106 uint8_t buf[400]; | |
| 107 | |
| 108 s = (faxtester_state_t *) user_data; | |
| 109 | |
| 110 if (s->image_buffer) | |
| 111 { | |
| 112 /* We are sending an ECM image */ | |
| 113 if (s->image_ptr < s->image_len) | |
| 114 { | |
| 115 buf[0] = 0xFF; | |
| 116 buf[1] = 0x03; | |
| 117 buf[2] = 0x06; | |
| 118 buf[3] = s->image_ptr/s->ecm_frame_size; | |
| 119 memcpy(buf + 4, &s->image_buffer[s->image_ptr], s->ecm_frame_size); | |
| 120 hdlc_tx_frame(&(s->modems.hdlc_tx), buf, 4 + s->ecm_frame_size); | |
| 121 if (s->corrupt_crc >= 0 && s->corrupt_crc == s->image_ptr/s->ecm_frame_size) | |
| 122 hdlc_tx_corrupt_frame(&(s->modems.hdlc_tx)); | |
| 123 s->image_ptr += s->ecm_frame_size; | |
| 124 return; | |
| 125 } | |
| 126 else | |
| 127 { | |
| 128 /* The actual image is over. We are sending the final RCP frames. */ | |
| 129 if (s->image_bit_ptr > 2) | |
| 130 { | |
| 131 s->image_bit_ptr--; | |
| 132 buf[0] = 0xFF; | |
| 133 buf[1] = 0x03; | |
| 134 buf[2] = 0x86; | |
| 135 hdlc_tx_frame(&(s->modems.hdlc_tx), buf, 3); | |
| 136 return; | |
| 137 } | |
| 138 else | |
| 139 { | |
| 140 /* All done. */ | |
| 141 s->image_buffer = NULL; | |
| 142 } | |
| 143 } | |
| 144 } | |
| 145 front_end_step_complete(s); | |
| 146 } | |
| 147 /*- End of function --------------------------------------------------------*/ | |
| 148 | |
| 149 static void modem_tx_status(void *user_data, int status) | |
| 150 { | |
| 151 faxtester_state_t *s; | |
| 152 | |
| 153 s = (faxtester_state_t *) user_data; | |
| 154 printf("Tx status is %s (%d)\n", signal_status_to_str(status), status); | |
| 155 switch (status) | |
| 156 { | |
| 157 case SIG_STATUS_SHUTDOWN_COMPLETE: | |
| 158 front_end_step_complete(s); | |
| 159 break; | |
| 160 } | |
| 161 } | |
| 162 /*- End of function --------------------------------------------------------*/ | |
| 163 | |
| 164 static void tone_detected(void *user_data, int tone, int level, int delay) | |
| 165 { | |
| 166 faxtester_state_t *s; | |
| 167 | |
| 168 s = (faxtester_state_t *) user_data; | |
| 169 span_log(&s->logging, | |
| 170 SPAN_LOG_FLOW, | |
| 171 "%s (%d) declared (%ddBm0)\n", | |
| 172 modem_connect_tone_to_str(tone), | |
| 173 tone, | |
| 174 level); | |
| 175 if (tone != MODEM_CONNECT_TONES_NONE) | |
| 176 { | |
| 177 s->tone_on_time = s->timer; | |
| 178 } | |
| 179 else | |
| 180 { | |
| 181 span_log(&s->logging, | |
| 182 SPAN_LOG_FLOW, | |
| 183 "Tone was on for %fs\n", | |
| 184 (float) (s->timer - s->tone_on_time)/SAMPLE_RATE + 0.55); | |
| 185 } | |
| 186 s->tone_state = tone; | |
| 187 if (tone == MODEM_CONNECT_TONES_NONE) | |
| 188 front_end_step_complete(s); | |
| 189 } | |
| 190 /*- End of function --------------------------------------------------------*/ | |
| 191 | |
| 192 static int non_ecm_get_bit(void *user_data) | |
| 193 { | |
| 194 faxtester_state_t *s; | |
| 195 int bit; | |
| 196 | |
| 197 s = (faxtester_state_t *) user_data; | |
| 198 if (s->image_bit_ptr == 0) | |
| 199 { | |
| 200 if (s->image_ptr >= s->image_len) | |
| 201 { | |
| 202 s->image_buffer = NULL; | |
| 203 return SIG_STATUS_END_OF_DATA; | |
| 204 } | |
| 205 s->image_bit_ptr = 8; | |
| 206 s->image_ptr++; | |
| 207 } | |
| 208 s->image_bit_ptr--; | |
| 209 bit = (s->image_buffer[s->image_ptr] >> (7 - s->image_bit_ptr)) & 0x01; | |
| 210 //printf("Rx bit - %d\n", bit); | |
| 211 return bit; | |
| 212 } | |
| 213 /*- End of function --------------------------------------------------------*/ | |
| 214 | |
| 215 void faxtester_set_non_ecm_image_buffer(faxtester_state_t *s, const uint8_t *buf, int len) | |
| 216 { | |
| 217 s->image_ptr = 0; | |
| 218 s->image_bit_ptr = 8; | |
| 219 s->image_len = len; | |
| 220 s->image_buffer = buf; | |
| 221 } | |
| 222 /*- End of function --------------------------------------------------------*/ | |
| 223 | |
| 224 void faxtester_set_ecm_image_buffer(faxtester_state_t *s, const uint8_t *buf, int len, int block, int frame_size, int crc_hit) | |
| 225 { | |
| 226 int start; | |
| 227 | |
| 228 start = 256*frame_size*block; | |
| 229 if (len > start + 256*frame_size) | |
| 230 len = start + 256*frame_size; | |
| 231 | |
| 232 s->ecm_frame_size = frame_size; | |
| 233 s->image_ptr = start; | |
| 234 s->image_bit_ptr = 8; | |
| 235 s->image_len = len; | |
| 236 s->image_buffer = buf; | |
| 237 s->corrupt_crc = crc_hit; | |
| 238 /* Send the first frame */ | |
| 239 hdlc_underflow_handler(s); | |
| 240 } | |
| 241 /*- End of function --------------------------------------------------------*/ | |
| 242 | |
| 243 static void non_ecm_rx_status(void *user_data, int status) | |
| 244 { | |
| 245 faxtester_state_t *s; | |
| 246 | |
| 247 s = (faxtester_state_t *) user_data; | |
| 248 span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM carrier status is %s (%d)\n", signal_status_to_str(status), status); | |
| 249 switch (status) | |
| 250 { | |
| 251 case SIG_STATUS_TRAINING_FAILED: | |
| 252 s->modems.rx_trained = FALSE; | |
| 253 break; | |
| 254 case SIG_STATUS_TRAINING_SUCCEEDED: | |
| 255 /* The modem is now trained */ | |
| 256 s->modems.rx_trained = TRUE; | |
| 257 break; | |
| 258 case SIG_STATUS_CARRIER_UP: | |
| 259 s->modems.rx_signal_present = TRUE; | |
| 260 break; | |
| 261 case SIG_STATUS_CARRIER_DOWN: | |
| 262 if (s->modems.rx_trained) | |
| 263 { | |
| 264 if (s->real_time_frame_handler) | |
| 265 s->real_time_frame_handler(s, s->real_time_frame_user_data, TRUE, NULL, 0); | |
| 266 } | |
| 267 s->modems.rx_signal_present = FALSE; | |
| 268 s->modems.rx_trained = FALSE; | |
| 269 break; | |
| 270 } | |
| 271 } | |
| 272 /*- End of function --------------------------------------------------------*/ | |
| 273 | |
| 274 static void non_ecm_put_bit(void *user_data, int bit) | |
| 275 { | |
| 276 faxtester_state_t *s; | |
| 277 | |
| 278 if (bit < 0) | |
| 279 { | |
| 280 non_ecm_rx_status(user_data, bit); | |
| 281 return; | |
| 282 } | |
| 283 s = (faxtester_state_t *) user_data; | |
| 284 } | |
| 285 /*- End of function --------------------------------------------------------*/ | |
| 286 | |
| 287 static void hdlc_rx_status(void *user_data, int status) | |
| 288 { | |
| 289 faxtester_state_t *s; | |
| 290 | |
| 291 s = (faxtester_state_t *) user_data; | |
| 292 fprintf(stderr, "HDLC carrier status is %s (%d)\n", signal_status_to_str(status), status); | |
| 293 switch (status) | |
| 294 { | |
| 295 case SIG_STATUS_TRAINING_FAILED: | |
| 296 s->modems.rx_trained = FALSE; | |
| 297 break; | |
| 298 case SIG_STATUS_TRAINING_SUCCEEDED: | |
| 299 /* The modem is now trained */ | |
| 300 s->modems.rx_trained = TRUE; | |
| 301 break; | |
| 302 case SIG_STATUS_CARRIER_UP: | |
| 303 s->modems.rx_signal_present = TRUE; | |
| 304 break; | |
| 305 case SIG_STATUS_CARRIER_DOWN: | |
| 306 s->modems.rx_signal_present = FALSE; | |
| 307 s->modems.rx_trained = FALSE; | |
| 308 break; | |
| 309 } | |
| 310 } | |
| 311 /*- End of function --------------------------------------------------------*/ | |
| 312 | |
| 313 static void hdlc_accept(void *user_data, const uint8_t *msg, int len, int ok) | |
| 314 { | |
| 315 faxtester_state_t *s; | |
| 316 | |
| 317 if (len < 0) | |
| 318 { | |
| 319 hdlc_rx_status(user_data, len); | |
| 320 return; | |
| 321 } | |
| 322 s = (faxtester_state_t *) user_data; | |
| 323 if (s->real_time_frame_handler) | |
| 324 s->real_time_frame_handler(s, s->real_time_frame_user_data, TRUE, msg, len); | |
| 325 } | |
| 326 /*- End of function --------------------------------------------------------*/ | |
| 327 | |
| 328 static int v17_v21_rx(void *user_data, const int16_t amp[], int len) | |
| 329 { | |
| 330 faxtester_state_t *t; | |
| 331 fax_modems_state_t *s; | |
| 332 | |
| 333 t = (faxtester_state_t *) user_data; | |
| 334 s = &t->modems; | |
| 335 v17_rx(&s->v17_rx, amp, len); | |
| 336 fsk_rx(&s->v21_rx, amp, len); | |
| 337 if (s->rx_trained) | |
| 338 { | |
| 339 /* The fast modem has trained, so we no longer need to run the slow | |
| 340 one in parallel. */ | |
| 341 span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx)); | |
| 342 s->rx_handler = (span_rx_handler_t *) &v17_rx; | |
| 343 s->rx_user_data = &s->v17_rx; | |
| 344 } | |
| 345 return 0; | |
| 346 } | |
| 347 /*- End of function --------------------------------------------------------*/ | |
| 348 | |
| 349 static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len) | |
| 350 { | |
| 351 faxtester_state_t *t; | |
| 352 fax_modems_state_t *s; | |
| 353 | |
| 354 t = (faxtester_state_t *) user_data; | |
| 355 s = &t->modems; | |
| 356 v27ter_rx(&s->v27ter_rx, amp, len); | |
| 357 fsk_rx(&s->v21_rx, amp, len); | |
| 358 if (s->rx_trained) | |
| 359 { | |
| 360 /* The fast modem has trained, so we no longer need to run the slow | |
| 361 one in parallel. */ | |
| 362 span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx)); | |
| 363 s->rx_handler = (span_rx_handler_t *) &v27ter_rx; | |
| 364 s->rx_user_data = &s->v27ter_rx; | |
| 365 } | |
| 366 return 0; | |
| 367 } | |
| 368 /*- End of function --------------------------------------------------------*/ | |
| 369 | |
| 370 static int v29_v21_rx(void *user_data, const int16_t amp[], int len) | |
| 371 { | |
| 372 faxtester_state_t *t; | |
| 373 fax_modems_state_t *s; | |
| 374 | |
| 375 t = (faxtester_state_t *) user_data; | |
| 376 s = &t->modems; | |
| 377 v29_rx(&s->v29_rx, amp, len); | |
| 378 fsk_rx(&s->v21_rx, amp, len); | |
| 379 if (s->rx_trained) | |
| 380 { | |
| 381 /* The fast modem has trained, so we no longer need to run the slow | |
| 382 one in parallel. */ | |
| 383 span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx)); | |
| 384 s->rx_handler = (span_rx_handler_t *) &v29_rx; | |
| 385 s->rx_user_data = &s->v29_rx; | |
| 386 } | |
| 387 return 0; | |
| 388 } | |
| 389 /*- End of function --------------------------------------------------------*/ | |
| 390 | |
| 391 int faxtester_rx(faxtester_state_t *s, int16_t *amp, int len) | |
| 392 { | |
| 393 int i; | |
| 394 | |
| 395 for (i = 0; i < len; i++) | |
| 396 amp[i] = dc_restore(&(s->modems.dc_restore), amp[i]); | |
| 397 s->modems.rx_handler(s->modems.rx_user_data, amp, len); | |
| 398 timer_update(s, len); | |
| 399 if (s->wait_for_silence) | |
| 400 { | |
| 401 if (!s->modems.rx_signal_present) | |
| 402 { | |
| 403 s->wait_for_silence = FALSE; | |
| 404 front_end_step_complete(s); | |
| 405 } | |
| 406 } | |
| 407 return 0; | |
| 408 } | |
| 409 /*- End of function --------------------------------------------------------*/ | |
| 410 | |
| 411 int faxtester_tx(faxtester_state_t *s, int16_t *amp, int max_len) | |
| 412 { | |
| 413 int len; | |
| 414 int required_len; | |
| 415 | |
| 416 required_len = max_len; | |
| 417 len = 0; | |
| 418 if (s->transmit) | |
| 419 { | |
| 420 while ((len += s->modems.tx_handler(s->modems.tx_user_data, amp + len, max_len - len)) < max_len) | |
| 421 { | |
| 422 /* Allow for a change of tx handler within a block */ | |
| 423 front_end_step_complete(s); | |
| 424 if (!s->transmit) | |
| 425 { | |
| 426 if (s->modems.transmit_on_idle) | |
| 427 { | |
| 428 /* Pad to the requested length with silence */ | |
| 429 memset(amp + len, 0, (max_len - len)*sizeof(int16_t)); | |
| 430 len = max_len; | |
| 431 } | |
| 432 break; | |
| 433 } | |
| 434 } | |
| 435 } | |
| 436 else | |
| 437 { | |
| 438 if (s->modems.transmit_on_idle) | |
| 439 { | |
| 440 /* Pad to the requested length with silence */ | |
| 441 memset(amp, 0, max_len*sizeof(int16_t)); | |
| 442 len = max_len; | |
| 443 } | |
| 444 } | |
| 445 return len; | |
| 446 } | |
| 447 /*- End of function --------------------------------------------------------*/ | |
| 448 | |
| 449 void faxtest_set_rx_silence(faxtester_state_t *s) | |
| 450 { | |
| 451 s->wait_for_silence = TRUE; | |
| 452 } | |
| 453 /*- End of function --------------------------------------------------------*/ | |
| 454 | |
| 455 void faxtester_set_rx_type(void *user_data, int type, int bit_rate, int short_train, int use_hdlc) | |
| 456 { | |
| 457 faxtester_state_t *s; | |
| 458 put_bit_func_t put_bit_func; | |
| 459 void *put_bit_user_data; | |
| 460 fax_modems_state_t *t; | |
| 461 int tone; | |
| 462 | |
| 463 s = (faxtester_state_t *) user_data; | |
| 464 t = &s->modems; | |
| 465 span_log(&s->logging, SPAN_LOG_FLOW, "Set rx type %d\n", type); | |
| 466 if (s->current_rx_type == type) | |
| 467 return; | |
| 468 s->current_rx_type = type; | |
| 469 if (use_hdlc) | |
| 470 { | |
| 471 put_bit_func = (put_bit_func_t) hdlc_rx_put_bit; | |
| 472 put_bit_user_data = (void *) &t->hdlc_rx; | |
| 473 hdlc_rx_init(&t->hdlc_rx, FALSE, FALSE, HDLC_FRAMING_OK_THRESHOLD, hdlc_accept, s); | |
| 474 } | |
| 475 else | |
| 476 { | |
| 477 put_bit_func = non_ecm_put_bit; | |
| 478 put_bit_user_data = (void *) s; | |
| 479 } | |
| 480 switch (type) | |
| 481 { | |
| 482 case T30_MODEM_CED: | |
| 483 case T30_MODEM_CNG: | |
| 484 if (type == T30_MODEM_CED) | |
| 485 tone = MODEM_CONNECT_TONES_FAX_CED; | |
| 486 else | |
| 487 tone = MODEM_CONNECT_TONES_FAX_CNG; | |
| 488 modem_connect_tones_rx_init(&t->connect_rx, | |
| 489 tone, | |
| 490 tone_detected, | |
| 491 (void *) s); | |
| 492 t->rx_handler = (span_rx_handler_t *) &modem_connect_tones_rx; | |
| 493 t->rx_user_data = &t->connect_rx; | |
| 494 s->tone_state = MODEM_CONNECT_TONES_NONE; | |
| 495 break; | |
| 496 case T30_MODEM_V21: | |
| 497 if (s->flush_handler) | |
| 498 s->flush_handler(s, s->flush_user_data, 3); | |
| 499 fsk_rx_init(&t->v21_rx, &preset_fsk_specs[FSK_V21CH2], FSK_FRAME_MODE_SYNC, (put_bit_func_t) hdlc_rx_put_bit, put_bit_user_data); | |
| 500 fsk_rx_signal_cutoff(&t->v21_rx, -45.5); | |
| 501 t->rx_handler = (span_rx_handler_t *) &fsk_rx; | |
| 502 t->rx_user_data = &t->v21_rx; | |
| 503 break; | |
| 504 case T30_MODEM_V27TER: | |
| 505 v27ter_rx_restart(&t->v27ter_rx, bit_rate, FALSE); | |
| 506 v27ter_rx_set_put_bit(&t->v27ter_rx, put_bit_func, put_bit_user_data); | |
| 507 t->rx_handler = (span_rx_handler_t *) &v27ter_v21_rx; | |
| 508 t->rx_user_data = s; | |
| 509 break; | |
| 510 case T30_MODEM_V29: | |
| 511 v29_rx_restart(&t->v29_rx, bit_rate, FALSE); | |
| 512 v29_rx_set_put_bit(&t->v29_rx, put_bit_func, put_bit_user_data); | |
| 513 t->rx_handler = (span_rx_handler_t *) &v29_v21_rx; | |
| 514 t->rx_user_data = s; | |
| 515 break; | |
| 516 case T30_MODEM_V17: | |
| 517 v17_rx_restart(&t->v17_rx, bit_rate, short_train); | |
| 518 v17_rx_set_put_bit(&t->v17_rx, put_bit_func, put_bit_user_data); | |
| 519 t->rx_handler = (span_rx_handler_t *) &v17_v21_rx; | |
| 520 t->rx_user_data = s; | |
| 521 break; | |
| 522 case T30_MODEM_DONE: | |
| 523 span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n"); | |
| 524 default: | |
| 525 t->rx_handler = (span_rx_handler_t *) &span_dummy_rx; | |
| 526 t->rx_user_data = s; | |
| 527 break; | |
| 528 } | |
| 529 } | |
| 530 /*- End of function --------------------------------------------------------*/ | |
| 531 | |
| 532 void faxtester_set_tx_type(void *user_data, int type, int bit_rate, int short_train, int use_hdlc) | |
| 533 { | |
| 534 faxtester_state_t *s; | |
| 535 get_bit_func_t get_bit_func; | |
| 536 void *get_bit_user_data; | |
| 537 fax_modems_state_t *t; | |
| 538 int tone; | |
| 539 | |
| 540 s = (faxtester_state_t *) user_data; | |
| 541 t = &s->modems; | |
| 542 span_log(&s->logging, SPAN_LOG_FLOW, "Set tx type %d\n", type); | |
| 543 if (s->current_tx_type == type) | |
| 544 return; | |
| 545 if (use_hdlc) | |
| 546 { | |
| 547 get_bit_func = (get_bit_func_t) hdlc_tx_get_bit; | |
| 548 get_bit_user_data = (void *) &t->hdlc_tx; | |
| 549 } | |
| 550 else | |
| 551 { | |
| 552 get_bit_func = non_ecm_get_bit; | |
| 553 get_bit_user_data = (void *) s; | |
| 554 } | |
| 555 switch (type) | |
| 556 { | |
| 557 case T30_MODEM_PAUSE: | |
| 558 silence_gen_alter(&t->silence_gen, ms_to_samples(short_train)); | |
| 559 t->tx_handler = (span_tx_handler_t *) &silence_gen; | |
| 560 t->tx_user_data = &t->silence_gen; | |
| 561 s->transmit = TRUE; | |
| 562 break; | |
| 563 case T30_MODEM_CED: | |
| 564 case T30_MODEM_CNG: | |
| 565 if (type == T30_MODEM_CED) | |
| 566 tone = MODEM_CONNECT_TONES_FAX_CED; | |
| 567 else | |
| 568 tone = MODEM_CONNECT_TONES_FAX_CNG; | |
| 569 modem_connect_tones_tx_init(&t->connect_tx, tone); | |
| 570 t->tx_handler = (span_tx_handler_t *) &modem_connect_tones_tx; | |
| 571 t->tx_user_data = &t->connect_tx; | |
| 572 s->transmit = TRUE; | |
| 573 break; | |
| 574 case T30_MODEM_V21: | |
| 575 fsk_tx_init(&t->v21_tx, &preset_fsk_specs[FSK_V21CH2], get_bit_func, get_bit_user_data); | |
| 576 fsk_tx_set_modem_status_handler(&t->v21_tx, modem_tx_status, (void *) s); | |
| 577 t->tx_handler = (span_tx_handler_t *) &fsk_tx; | |
| 578 t->tx_user_data = &t->v21_tx; | |
| 579 s->transmit = TRUE; | |
| 580 break; | |
| 581 case T30_MODEM_V27TER: | |
| 582 v27ter_tx_restart(&t->v27ter_tx, bit_rate, t->use_tep); | |
| 583 v27ter_tx_set_get_bit(&t->v27ter_tx, get_bit_func, get_bit_user_data); | |
| 584 v27ter_tx_set_modem_status_handler(&t->v27ter_tx, modem_tx_status, (void *) s); | |
| 585 t->tx_handler = (span_tx_handler_t *) &v27ter_tx; | |
| 586 t->tx_user_data = &t->v27ter_tx; | |
| 587 /* For any fast modem, set 200ms of preamble flags */ | |
| 588 hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5)); | |
| 589 s->transmit = TRUE; | |
| 590 break; | |
| 591 case T30_MODEM_V29: | |
| 592 v29_tx_restart(&t->v29_tx, bit_rate, t->use_tep); | |
| 593 v29_tx_set_get_bit(&t->v29_tx, get_bit_func, get_bit_user_data); | |
| 594 v29_tx_set_modem_status_handler(&t->v29_tx, modem_tx_status, (void *) s); | |
| 595 t->tx_handler = (span_tx_handler_t *) &v29_tx; | |
| 596 t->tx_user_data = &t->v29_tx; | |
| 597 /* For any fast modem, set 200ms of preamble flags */ | |
| 598 hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5)); | |
| 599 s->transmit = TRUE; | |
| 600 break; | |
| 601 case T30_MODEM_V17: | |
| 602 v17_tx_restart(&t->v17_tx, bit_rate, t->use_tep, short_train); | |
| 603 v17_tx_set_get_bit(&t->v17_tx, get_bit_func, get_bit_user_data); | |
| 604 v17_tx_set_modem_status_handler(&t->v17_tx, modem_tx_status, (void *) s); | |
| 605 t->tx_handler = (span_tx_handler_t *) &v17_tx; | |
| 606 t->tx_user_data = &t->v17_tx; | |
| 607 /* For any fast modem, set 200ms of preamble flags */ | |
| 608 hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5)); | |
| 609 s->transmit = TRUE; | |
| 610 break; | |
| 611 case T30_MODEM_DONE: | |
| 612 span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n"); | |
| 613 /* Fall through */ | |
| 614 default: | |
| 615 silence_gen_alter(&t->silence_gen, 0); | |
| 616 t->tx_handler = (span_tx_handler_t *) &silence_gen; | |
| 617 t->tx_user_data = &t->silence_gen; | |
| 618 s->transmit = FALSE; | |
| 619 break; | |
| 620 } | |
| 621 s->current_tx_type = type; | |
| 622 } | |
| 623 /*- End of function --------------------------------------------------------*/ | |
| 624 | |
| 625 void faxtester_set_timeout(faxtester_state_t *s, int timeout) | |
| 626 { | |
| 627 if (timeout >= 0) | |
| 628 s->timeout = s->timer + timeout*SAMPLE_RATE/1000; | |
| 629 else | |
| 630 s->timeout = 0x7FFFFFFFFFFFFFFFLL; | |
| 631 } | |
| 632 /*- End of function --------------------------------------------------------*/ | |
| 633 | |
| 634 void faxtester_set_transmit_on_idle(faxtester_state_t *s, int transmit_on_idle) | |
| 635 { | |
| 636 s->modems.transmit_on_idle = transmit_on_idle; | |
| 637 } | |
| 638 /*- End of function --------------------------------------------------------*/ | |
| 639 | |
| 640 void faxtester_set_tep_mode(faxtester_state_t *s, int use_tep) | |
| 641 { | |
| 642 s->modems.use_tep = use_tep; | |
| 643 } | |
| 644 /*- End of function --------------------------------------------------------*/ | |
| 645 | |
| 646 void faxtester_set_real_time_frame_handler(faxtester_state_t *s, faxtester_real_time_frame_handler_t *handler, void *user_data) | |
| 647 { | |
| 648 s->real_time_frame_handler = handler; | |
| 649 s->real_time_frame_user_data = user_data; | |
| 650 } | |
| 651 /*- End of function --------------------------------------------------------*/ | |
| 652 | |
| 653 void faxtester_set_front_end_step_complete_handler(faxtester_state_t *s, faxtester_front_end_step_complete_handler_t *handler, void *user_data) | |
| 654 { | |
| 655 s->front_end_step_complete_handler = handler; | |
| 656 s->front_end_step_complete_user_data = user_data; | |
| 657 } | |
| 658 /*- End of function --------------------------------------------------------*/ | |
| 659 | |
| 660 void faxtester_set_front_end_step_timeout_handler(faxtester_state_t *s, faxtester_front_end_step_complete_handler_t *handler, void *user_data) | |
| 661 { | |
| 662 s->front_end_step_timeout_handler = handler; | |
| 663 s->front_end_step_timeout_user_data = user_data; | |
| 664 } | |
| 665 /*- End of function --------------------------------------------------------*/ | |
| 666 | |
| 667 static void faxtester_fax_modems_init(fax_modems_state_t *s, int use_tep, void *user_data) | |
| 668 { | |
| 669 s->use_tep = use_tep; | |
| 670 | |
| 671 hdlc_rx_init(&s->hdlc_rx, FALSE, FALSE, HDLC_FRAMING_OK_THRESHOLD, hdlc_accept, user_data); | |
| 672 hdlc_tx_init(&s->hdlc_tx, FALSE, 2, FALSE, hdlc_underflow_handler, user_data); | |
| 673 fsk_rx_init(&s->v21_rx, &preset_fsk_specs[FSK_V21CH2], FSK_FRAME_MODE_SYNC, (put_bit_func_t) hdlc_rx_put_bit, &s->hdlc_rx); | |
| 674 fsk_rx_signal_cutoff(&s->v21_rx, -45.5); | |
| 675 fsk_tx_init(&s->v21_tx, &preset_fsk_specs[FSK_V21CH2], (get_bit_func_t) hdlc_tx_get_bit, &s->hdlc_tx); | |
| 676 fsk_tx_set_modem_status_handler(&s->v21_tx, modem_tx_status, user_data); | |
| 677 v17_rx_init(&s->v17_rx, 14400, non_ecm_put_bit, user_data); | |
| 678 v17_tx_init(&s->v17_tx, 14400, s->use_tep, non_ecm_get_bit, user_data); | |
| 679 v17_tx_set_modem_status_handler(&s->v17_tx, modem_tx_status, user_data); | |
| 680 v29_rx_init(&s->v29_rx, 9600, non_ecm_put_bit, user_data); | |
| 681 v29_rx_signal_cutoff(&s->v29_rx, -45.5); | |
| 682 v29_tx_init(&s->v29_tx, 9600, s->use_tep, non_ecm_get_bit, user_data); | |
| 683 v29_tx_set_modem_status_handler(&s->v29_tx, modem_tx_status, user_data); | |
| 684 v27ter_rx_init(&s->v27ter_rx, 4800, non_ecm_put_bit, user_data); | |
| 685 v27ter_tx_init(&s->v27ter_tx, 4800, s->use_tep, non_ecm_get_bit, user_data); | |
| 686 v27ter_tx_set_modem_status_handler(&s->v27ter_tx, modem_tx_status, user_data); | |
| 687 silence_gen_init(&s->silence_gen, 0); | |
| 688 modem_connect_tones_tx_init(&s->connect_tx, MODEM_CONNECT_TONES_FAX_CNG); | |
| 689 modem_connect_tones_rx_init(&s->connect_rx, | |
| 690 MODEM_CONNECT_TONES_FAX_CNG, | |
| 691 tone_detected, | |
| 692 user_data); | |
| 693 dc_restore_init(&s->dc_restore); | |
| 694 | |
| 695 s->rx_signal_present = FALSE; | |
| 696 s->rx_handler = (span_rx_handler_t *) &span_dummy_rx; | |
| 697 s->rx_user_data = NULL; | |
| 698 s->tx_handler = (span_tx_handler_t *) &silence_gen; | |
| 699 s->tx_user_data = &s->silence_gen; | |
| 700 } | |
| 701 /*- End of function --------------------------------------------------------*/ | |
| 702 | |
| 703 faxtester_state_t *faxtester_init(faxtester_state_t *s, int calling_party) | |
| 704 { | |
| 705 if (s == NULL) | |
| 706 { | |
| 707 if ((s = (faxtester_state_t *) malloc(sizeof(*s))) == NULL) | |
| 708 return NULL; | |
| 709 } | |
| 710 | |
| 711 memset(s, 0, sizeof(*s)); | |
| 712 span_log_init(&s->logging, SPAN_LOG_NONE, NULL); | |
| 713 span_log_set_protocol(&s->logging, "TST"); | |
| 714 faxtester_fax_modems_init(&s->modems, FALSE, s); | |
| 715 faxtester_set_timeout(s, -1); | |
| 716 faxtester_set_tx_type(s, T30_MODEM_NONE, 0, FALSE, FALSE); | |
| 717 | |
| 718 return s; | |
| 719 } | |
| 720 /*- End of function --------------------------------------------------------*/ | |
| 721 | |
| 722 int faxtester_release(faxtester_state_t *s) | |
| 723 { | |
| 724 return 0; | |
| 725 } | |
| 726 /*- End of function --------------------------------------------------------*/ | |
| 727 | |
| 728 int faxtester_free(faxtester_state_t *s) | |
| 729 { | |
| 730 free(s); | |
| 731 return 0; | |
| 732 } | |
| 733 /*- End of function --------------------------------------------------------*/ | |
| 734 | |
| 735 void faxtester_set_flush_handler(faxtester_state_t *s, faxtester_flush_handler_t *handler, void *user_data) | |
| 736 { | |
| 737 s->flush_handler = handler; | |
| 738 s->flush_user_data = user_data; | |
| 739 } | |
| 740 /*- End of function --------------------------------------------------------*/ | |
| 741 /*- End of file ------------------------------------------------------------*/ |
