static int t30_tests(int log_audio, int test_sending) { int k; int outframes; fax_state_t *fax_state; int16_t t30_amp[SAMPLES_PER_CHUNK]; int16_t t31_amp[SAMPLES_PER_CHUNK]; int16_t silence[SAMPLES_PER_CHUNK]; int16_t out_amp[2*SAMPLES_PER_CHUNK]; int t30_len; int t31_len; SNDFILE *wave_handle; SNDFILE *in_handle; int fast_send; int fast_send_tcf; int fast_blocks; uint8_t fast_buf[1000]; t30_state_t *t30; logging_state_t *logging; int i; wave_handle = NULL; if (log_audio) { if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME); exit(2); } } memset(silence, 0, sizeof(silence)); in_handle = NULL; if (decode_test_file) { if ((in_handle = sf_open_telephony_read(decode_test_file, 1)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", decode_test_file); exit(2); } } if ((t31_state = t31_init(NULL, at_tx_handler, NULL, modem_call_control, NULL, NULL, NULL)) == NULL) { fprintf(stderr, " Cannot start the T.31 FAX modem\n"); exit(2); } logging = t31_get_logging_state(t31_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.31"); if (test_sending) { fax_state = fax_init(NULL, FALSE); t30 = fax_get_t30_state(fax_state); t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1); fax_test_seq = fax_send_test_seq; countdown = 0; } else { fax_state = fax_init(NULL, TRUE); t30 = fax_get_t30_state(fax_state); t30_set_tx_file(t30, INPUT_FILE_NAME, -1, -1); fax_test_seq = fax_receive_test_seq; countdown = 250; } t30_set_tx_ident(t30, "11111111"); t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17); t30_set_phase_b_handler(t30, phase_b_handler, (void *) 'A'); t30_set_phase_d_handler(t30, phase_d_handler, (void *) 'A'); t30_set_phase_e_handler(t30, phase_e_handler, (void *) 'A'); memset(t30_amp, 0, sizeof(t30_amp)); logging = t30_get_logging_state(t30); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "FAX"); logging = fax_get_logging_state(fax_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "FAX"); fast_send = FALSE; fast_send_tcf = TRUE; fast_blocks = 0; kick = TRUE; while (!done) { if (kick) { kick = FALSE; if (fax_test_seq[test_seq_ptr].command > (const char *) 2) { if (fax_test_seq[test_seq_ptr].command[0]) { printf("%s\n", fax_test_seq[test_seq_ptr].command); t31_at_rx(t31_state, fax_test_seq[test_seq_ptr].command, fax_test_seq[test_seq_ptr].len_command); } } else { if (fax_test_seq[test_seq_ptr].command == (const char *) 2) { printf("Fast send TCF\n"); fast_send = TRUE; fast_send_tcf = TRUE; fast_blocks = 100; } else { printf("Fast send image\n"); fast_send = TRUE; fast_send_tcf = FALSE; fast_blocks = 100; } } } if (fast_send) { /* Send fast modem data */ if (fast_send_tcf) { memset(fast_buf, 0, 36); } else { if (fast_blocks == 1) { /* Create the end of page condition */ for (i = 0; i < 36; i += 2) { fast_buf[i] = 0x00; fast_buf[i + 1] = 0x80; } } else { /* Create a chunk of white page */ for (i = 0; i < 36; i += 4) { fast_buf[i] = 0x00; fast_buf[i + 1] = 0x80; fast_buf[i + 2] = 0xB2; fast_buf[i + 3] = 0x01; } } } if (fast_blocks == 1) { /* Insert EOLs */ fast_buf[35] = ETX; fast_buf[34] = DLE; fast_buf[31] = fast_buf[28] = fast_buf[25] = fast_buf[22] = fast_buf[19] = fast_buf[16] = 1; } t31_at_rx(t31_state, (char *) fast_buf, 36); if (--fast_blocks == 0) fast_send = FALSE; } t30_len = fax_tx(fax_state, t30_amp, SAMPLES_PER_CHUNK); /* The receive side always expects a full block of samples, but the transmit side may not be sending any when it doesn't need to. We may need to pad with some silence. */ if (t30_len < SAMPLES_PER_CHUNK) { memset(t30_amp + t30_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len)); t30_len = SAMPLES_PER_CHUNK; } if (log_audio) { for (k = 0; k < t30_len; k++) out_amp[2*k] = t30_amp[k]; } if (t31_rx(t31_state, t30_amp, t30_len)) break; if (countdown) { if (answered) { countdown = 0; t31_call_event(t31_state, AT_CALL_EVENT_ANSWERED); } else if (--countdown == 0) { t31_call_event(t31_state, AT_CALL_EVENT_ALERTING); countdown = 250; } } t31_len = t31_tx(t31_state, t31_amp, SAMPLES_PER_CHUNK); if (t31_len < SAMPLES_PER_CHUNK) { memset(t31_amp + t31_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t31_len)); t31_len = SAMPLES_PER_CHUNK; } if (log_audio) { for (k = 0; k < t31_len; k++) out_amp[2*k + 1] = t31_amp[k]; } if (fax_rx(fax_state, t31_amp, SAMPLES_PER_CHUNK)) break; logging = fax_get_logging_state(fax_state); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); logging = t30_get_logging_state(t30); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); logging = t31_get_logging_state(t31_state); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); if (log_audio) { outframes = sf_writef_short(wave_handle, out_amp, SAMPLES_PER_CHUNK); if (outframes != SAMPLES_PER_CHUNK) break; } } if (decode_test_file) { if (sf_close_telephony(in_handle)) { fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file); exit(2); } } if (log_audio) { if (sf_close_telephony(wave_handle)) { fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME); exit(2); } } return 0; }
static int t38_tests(int use_gui, int test_sending, int model_no, int speed_pattern_no) { t38_terminal_state_t *t38_state; int fast_send; int fast_send_tcf; int fast_blocks; uint8_t fast_buf[1000]; int msg_len; uint8_t msg[1024]; int t38_version; int without_pacing; int use_tep; int seq_no; double tx_when; double rx_when; t30_state_t *t30; t38_core_state_t *t38_core; logging_state_t *logging; int i; t38_version = 1; without_pacing = FALSE; use_tep = FALSE; srand48(0x1234567); if ((path_a_to_b = g1050_init(model_no, speed_pattern_no, 100, 33)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } if ((path_b_to_a = g1050_init(model_no, speed_pattern_no, 100, 33)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } if ((t31_state = t31_init(NULL, at_tx_handler, NULL, modem_call_control, NULL, t31_tx_packet_handler, NULL)) == NULL) { fprintf(stderr, " Cannot start the T.31 T.38 modem\n"); exit(2); } logging = t31_get_logging_state(t31_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.31"); t38_core = t31_get_t38_core_state(t31_state); logging = t38_core_get_logging_state(t38_core); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.31"); span_log_set_level(&t31_state->at_state.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&t31_state->at_state.logging, "T.31"); t31_set_mode(t31_state, TRUE); t38_set_t38_version(t38_core, t38_version); if (test_sending) { if ((t38_state = t38_terminal_init(NULL, FALSE, t38_tx_packet_handler, t31_state)) == NULL) { fprintf(stderr, "Cannot start the T.38 channel\n"); exit(2); } t30 = t38_terminal_get_t30_state(t38_state); t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1); fax_test_seq = fax_send_test_seq; countdown = 0; } else { if ((t38_state = t38_terminal_init(NULL, TRUE, t38_tx_packet_handler, t31_state)) == NULL) { fprintf(stderr, "Cannot start the T.38 channel\n"); exit(2); } t30 = t38_terminal_get_t30_state(t38_state); t30_set_tx_file(t30, INPUT_FILE_NAME, -1, -1); fax_test_seq = fax_receive_test_seq; countdown = 250; } t30 = t38_terminal_get_t30_state(t38_state); t38_core = t38_terminal_get_t38_core_state(t38_state); t38_set_t38_version(t38_core, t38_version); t38_terminal_set_config(t38_state, without_pacing); t38_terminal_set_tep_mode(t38_state, use_tep); t30_set_tx_ident(t30, "11111111"); t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17); //t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12); t30_set_phase_b_handler(t30, phase_b_handler, (void *) 'A'); t30_set_phase_d_handler(t30, phase_d_handler, (void *) 'A'); t30_set_phase_e_handler(t30, phase_e_handler, (void *) 'A'); logging = t38_terminal_get_logging_state(t38_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.38"); t38_core = t38_terminal_get_t38_core_state(t38_state); span_log_set_level(&t38_core->logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&t38_core->logging, "T.38"); logging = t30_get_logging_state(t30); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.38"); fast_send = FALSE; fast_send_tcf = TRUE; fast_blocks = 0; kick = TRUE; #if defined(ENABLE_GUI) if (use_gui) start_media_monitor(); #endif while (!done) { logging = t38_terminal_get_logging_state(t38_state); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); t38_core = t38_terminal_get_t38_core_state(t38_state); logging = t38_core_get_logging_state(t38_core); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); t30 = t38_terminal_get_t30_state(t38_state); logging = t30_get_logging_state(t30); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); logging = t31_get_logging_state(t31_state); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); t38_core = t31_get_t38_core_state(t31_state); logging = t38_core_get_logging_state(t38_core); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); span_log_bump_samples(&t31_state->at_state.logging, SAMPLES_PER_CHUNK); t38_terminal_send_timeout(t38_state, SAMPLES_PER_CHUNK); t31_t38_send_timeout(t31_state, SAMPLES_PER_CHUNK); when += (float) SAMPLES_PER_CHUNK/(float) SAMPLE_RATE; if (kick) { kick = FALSE; if (fax_test_seq[test_seq_ptr].command > (const char *) 2) { if (fax_test_seq[test_seq_ptr].command[0]) { printf("%s\n", fax_test_seq[test_seq_ptr].command); t31_at_rx(t31_state, fax_test_seq[test_seq_ptr].command, fax_test_seq[test_seq_ptr].len_command); } } else { if (fax_test_seq[test_seq_ptr].command == (const char *) 2) { printf("Fast send TCF\n"); fast_send = TRUE; fast_send_tcf = TRUE; fast_blocks = 100; } else { printf("Fast send image\n"); fast_send = TRUE; fast_send_tcf = FALSE; fast_blocks = 100; } } } if (fast_send) { /* Send fast modem data */ if (fast_send_tcf) { memset(fast_buf, 0, 36); } else { if (fast_blocks == 1) { /* Create the end of page condition */ for (i = 0; i < 36; i += 2) { fast_buf[i] = 0x00; fast_buf[i + 1] = 0x80; } } else { /* Create a chunk of white page */ for (i = 0; i < 36; i += 4) { fast_buf[i] = 0x00; fast_buf[i + 1] = 0x80; fast_buf[i + 2] = 0xB2; fast_buf[i + 3] = 0x01; } } } if (fast_blocks == 1) { /* Insert EOLs */ fast_buf[35] = ETX; fast_buf[34] = DLE; fast_buf[31] = fast_buf[28] = fast_buf[25] = fast_buf[22] = fast_buf[19] = fast_buf[16] = 1; } t31_at_rx(t31_state, (char *) fast_buf, 36); if (--fast_blocks == 0) fast_send = FALSE; } if (countdown) { if (answered) { countdown = 0; t31_call_event(t31_state, AT_CALL_EVENT_ANSWERED); } else if (--countdown == 0) { t31_call_event(t31_state, AT_CALL_EVENT_ALERTING); countdown = 250; } } while ((msg_len = g1050_get(path_a_to_b, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) { #if defined(ENABLE_GUI) if (use_gui) media_monitor_rx(seq_no, tx_when, rx_when); #endif t38_core = t31_get_t38_core_state(t31_state); t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no); } while ((msg_len = g1050_get(path_b_to_a, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) { #if defined(ENABLE_GUI) if (use_gui) media_monitor_rx(seq_no, tx_when, rx_when); #endif t38_core = t38_terminal_get_t38_core_state(t38_state); t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no); } #if defined(ENABLE_GUI) if (use_gui) media_monitor_update_display(); #endif } t38_terminal_release(t38_state); return 0; }
static int t30_tests(int t38_mode, int use_ecm, int use_gui, int log_audio, int test_sending, int g1050_model_no, int g1050_speed_pattern_no) { t38_terminal_state_t *t38_state; fax_state_t *fax_state; uint8_t msg[1024]; char buf[1024]; int len; int msg_len; int t30_len; int t31_len; int t38_version; int without_pacing; int use_tep; int seq_no; double tx_when; double rx_when; t30_state_t *t30; t38_core_state_t *t38_core; logging_state_t *logging; int k; int outframes; int ret; int16_t t30_amp[SAMPLES_PER_CHUNK]; int16_t t31_amp[SAMPLES_PER_CHUNK]; int16_t silence[SAMPLES_PER_CHUNK]; int16_t out_amp[2*SAMPLES_PER_CHUNK]; SNDFILE *wave_handle; SNDFILE *in_handle; at_state_t *at_state; #if defined(WIN32) DWORD read_bytes; OVERLAPPED o; #endif /* Test the T.31 modem against the full FAX machine in spandsp */ /* Set up the test environment */ t38_version = 1; without_pacing = FALSE; use_tep = FALSE; wave_handle = NULL; if (log_audio) { if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME); exit(2); } } in_handle = NULL; if (decode_test_file) { if ((in_handle = sf_open_telephony_read(decode_test_file, 1)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", decode_test_file); exit(2); } } srand48(0x1234567); if ((path_a_to_b = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } if ((path_b_to_a = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } t38_state = NULL; fax_state = NULL; if (test_sending) { if (t38_mode) { if ((t38_state = t38_terminal_init(NULL, FALSE, t38_tx_packet_handler, t31_state)) == NULL) { fprintf(stderr, "Cannot start the T.38 channel\n"); exit(2); } t30 = t38_terminal_get_t30_state(t38_state); } else { fax_state = fax_init(NULL, FALSE); t30 = fax_get_t30_state(fax_state); } t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1); countdown = 0; } else { if (t38_mode) { if ((t38_state = t38_terminal_init(NULL, TRUE, t38_tx_packet_handler, t31_state)) == NULL) { fprintf(stderr, "Cannot start the T.38 channel\n"); exit(2); } t30 = t38_terminal_get_t30_state(t38_state); } else { fax_state = fax_init(NULL, TRUE); t30 = fax_get_t30_state(fax_state); } t30_set_tx_file(t30, INPUT_FILE_NAME, -1, -1); countdown = 250; } t30_set_ecm_capability(t30, use_ecm); if (t38_mode) { t38_core = t38_terminal_get_t38_core_state(t38_state); t38_set_t38_version(t38_core, t38_version); t38_terminal_set_config(t38_state, without_pacing); t38_terminal_set_tep_mode(t38_state, use_tep); } t30_set_tx_ident(t30, "11111111"); t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17); //t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12); t30_set_phase_b_handler(t30, phase_b_handler, (void *) 'A'); t30_set_phase_d_handler(t30, phase_d_handler, (void *) 'A'); t30_set_phase_e_handler(t30, phase_e_handler, (void *) 'A'); if (t38_mode) logging = t38_terminal_get_logging_state(t38_state); else logging = t30_get_logging_state(t30); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, (t38_mode) ? "T.38" : "FAX"); if (t38_mode) { t38_core = t38_terminal_get_t38_core_state(t38_state); logging = t38_core_get_logging_state(t38_core); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.38"); logging = t30_get_logging_state(t30); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.38"); } else { logging = fax_get_logging_state(fax_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "FAX"); } memset(silence, 0, sizeof(silence)); memset(t30_amp, 0, sizeof(t30_amp)); /* Now set up and run the T.31 modem */ if ((t31_state = t31_init(NULL, at_tx_handler, &modem[0], t31_call_control, &modem[0], t31_tx_packet_handler, NULL)) == NULL) { fprintf(stderr, " Cannot start the T.31 modem\n"); exit(2); } at_state = t31_get_at_state(t31_state); logging = t31_get_logging_state(t31_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.31"); logging = at_get_logging_state(at_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.31"); if (t38_mode) { t38_core = t31_get_t38_core_state(t31_state); logging = t38_core_get_logging_state(t38_core); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.31"); t31_set_mode(t31_state, TRUE); t38_set_t38_version(t38_core, t38_version); } at_reset_call_info(at_state); at_set_call_info(at_state, "DATE", "1231"); at_set_call_info(at_state, "TIME", "1200"); at_set_call_info(at_state, "NAME", "Name"); at_set_call_info(at_state, "NMBR", "123456789"); at_set_call_info(at_state, "ANID", "987654321"); at_set_call_info(at_state, "USER", "User"); at_set_call_info(at_state, "CDID", "234567890"); at_set_call_info(at_state, "NDID", "345678901"); #if defined(ENABLE_GUI) if (use_gui) start_media_monitor(); #endif while (!done) { /* Deal with call setup, through the AT interface. */ if (test_sending) { } else { if (answered == 0) { if (--countdown == 0) { t31_call_event(t31_state, AT_CALL_EVENT_ALERTING); countdown = 250; } } else if (answered == 1) { printf("ZZZ\n"); answered = 2; t31_call_event(t31_state, AT_CALL_EVENT_ANSWERED); } } ret = modem_wait_sock(modem[0].master, 20, MODEM_POLL_READ); if ((ret & MODEM_POLL_READ)) { #if defined(WIN32) o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); /* Initialize the rest of the OVERLAPPED structure to zero. */ o.Internal = 0; o.InternalHigh = 0; o.Offset = 0; o.OffsetHigh = 0; assert(o.hEvent); if (!ReadFile(modem->master, buf, avail, &read_bytes, &o)) GetOverlappedResult(modem->master, &o, &read_bytes, TRUE); CloseHandle (o.hEvent); if ((len = read_bytes)) #else if ((len = read(modem[0].master, buf, 1024))) #endif { int i; printf("YYY %d - ", len); for (i = 0; i < len; i++) printf(" 0x%02x", buf[i] & 0xFF); printf("\n"); t31_at_rx(t31_state, buf, len); } } if (answered == 2) { if (t38_mode) { while ((msg_len = g1050_get(path_a_to_b, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) { #if defined(ENABLE_GUI) if (use_gui) media_monitor_rx(seq_no, tx_when, rx_when); #endif t38_core = t31_get_t38_core_state(t31_state); t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no); } while ((msg_len = g1050_get(path_b_to_a, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) { #if defined(ENABLE_GUI) if (use_gui) media_monitor_rx(seq_no, tx_when, rx_when); #endif t38_core = t38_terminal_get_t38_core_state(t38_state); t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no); } #if defined(ENABLE_GUI) if (use_gui) media_monitor_update_display(); #endif /* Bump the G.1050 models along */ when += (float) SAMPLES_PER_CHUNK/(float) SAMPLE_RATE; /* Bump things along on the t38_terminal side */ span_log_bump_samples(t38_terminal_get_logging_state(t38_state), SAMPLES_PER_CHUNK); t38_core = t38_terminal_get_t38_core_state(t38_state); span_log_bump_samples(t38_core_get_logging_state(t38_core), SAMPLES_PER_CHUNK); t38_terminal_send_timeout(t38_state, SAMPLES_PER_CHUNK); t31_t38_send_timeout(t31_state, SAMPLES_PER_CHUNK); } else { t30_len = fax_tx(fax_state, t30_amp, SAMPLES_PER_CHUNK); /* The receive side always expects a full block of samples, but the transmit side may not be sending any when it doesn't need to. We may need to pad with some silence. */ if (t30_len < SAMPLES_PER_CHUNK) { memset(t30_amp + t30_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len)); t30_len = SAMPLES_PER_CHUNK; } if (log_audio) { for (k = 0; k < t30_len; k++) out_amp[2*k] = t30_amp[k]; } if (t31_rx(t31_state, t30_amp, t30_len)) break; t31_len = t31_tx(t31_state, t31_amp, SAMPLES_PER_CHUNK); if (t31_len < SAMPLES_PER_CHUNK) { memset(t31_amp + t31_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t31_len)); t31_len = SAMPLES_PER_CHUNK; } if (log_audio) { for (k = 0; k < t31_len; k++) out_amp[2*k + 1] = t31_amp[k]; } if (fax_rx(fax_state, t31_amp, SAMPLES_PER_CHUNK)) break; if (log_audio) { outframes = sf_writef_short(wave_handle, out_amp, SAMPLES_PER_CHUNK); if (outframes != SAMPLES_PER_CHUNK) break; } /* Bump things along on the FAX machine side */ span_log_bump_samples(fax_get_logging_state(fax_state), SAMPLES_PER_CHUNK); } /* Bump things along on the FAX machine side */ span_log_bump_samples(t30_get_logging_state(t30), SAMPLES_PER_CHUNK); /* Bump things along on the T.31 modem side */ t38_core = t31_get_t38_core_state(t31_state); span_log_bump_samples(t38_core_get_logging_state(t38_core), SAMPLES_PER_CHUNK); span_log_bump_samples(t31_get_logging_state(t31_state), SAMPLES_PER_CHUNK); span_log_bump_samples(at_get_logging_state(t31_get_at_state(t31_state)), SAMPLES_PER_CHUNK); } } if (t38_mode) t38_terminal_release(t38_state); if (decode_test_file) { if (sf_close_telephony(in_handle)) { fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file); exit(2); } } if (log_audio) { if (sf_close_telephony(wave_handle)) { fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME); exit(2); } } if (!done) { printf("Tests failed\n"); return 2; } return 0; }
static int t30_tests(int t38_mode, int use_gui, int log_audio, int test_sending, int g1050_model_no, int g1050_speed_pattern_no) { t38_terminal_state_t *t38_state; fax_state_t *fax_state; int fast_send; int fast_send_tcf; int fast_blocks; int msg_len; int t30_len; int t31_len; int t38_version; int without_pacing; int use_tep; int seq_no; int i; int k; int outframes; uint8_t fast_buf[1000]; uint8_t msg[1024]; double tx_when; double rx_when; t30_state_t *t30; t38_core_state_t *t38_core; logging_state_t *logging; int16_t t30_amp[SAMPLES_PER_CHUNK]; int16_t t31_amp[SAMPLES_PER_CHUNK]; int16_t silence[SAMPLES_PER_CHUNK]; int16_t out_amp[2*SAMPLES_PER_CHUNK]; SNDFILE *wave_handle; SNDFILE *in_handle; /* Test the T.31 modem against the full FAX machine in spandsp */ /* Set up the test environment */ t38_version = 1; without_pacing = false; use_tep = false; wave_handle = NULL; if (log_audio) { if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME); exit(2); } } in_handle = NULL; if (decode_test_file) { if ((in_handle = sf_open_telephony_read(decode_test_file, 1)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", decode_test_file); exit(2); } } srand48(0x1234567); if ((path_a_to_b = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } if ((path_b_to_a = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } t38_state = NULL; fax_state = NULL; if (test_sending) { if (t38_mode) { if ((t38_state = t38_terminal_init(NULL, false, t38_tx_packet_handler, t31_state)) == NULL) { fprintf(stderr, "Cannot start the T.38 channel\n"); exit(2); } t30 = t38_terminal_get_t30_state(t38_state); } else { fax_state = fax_init(NULL, false); t30 = fax_get_t30_state(fax_state); } t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1); fax_test_seq = fax_send_test_seq; countdown = 0; } else { if (t38_mode) { if ((t38_state = t38_terminal_init(NULL, true, t38_tx_packet_handler, t31_state)) == NULL) { fprintf(stderr, "Cannot start the T.38 channel\n"); exit(2); } t30 = t38_terminal_get_t30_state(t38_state); } else { fax_state = fax_init(NULL, true); t30 = fax_get_t30_state(fax_state); } t30_set_tx_file(t30, INPUT_FILE_NAME, -1, -1); fax_test_seq = fax_receive_test_seq; countdown = 250; } if (t38_mode) { t38_core = t38_terminal_get_t38_core_state(t38_state); t38_set_t38_version(t38_core, t38_version); t38_terminal_set_config(t38_state, without_pacing); t38_terminal_set_tep_mode(t38_state, use_tep); } t30_set_tx_ident(t30, "11111111"); t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17); //t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12); t30_set_phase_b_handler(t30, phase_b_handler, (void *) 'A'); t30_set_phase_d_handler(t30, phase_d_handler, (void *) 'A'); t30_set_phase_e_handler(t30, phase_e_handler, (void *) 'A'); if (t38_mode) logging = t38_terminal_get_logging_state(t38_state); else logging = t30_get_logging_state(t30); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, (t38_mode) ? "T.38" : "FAX"); if (t38_mode) { t38_core = t38_terminal_get_t38_core_state(t38_state); span_log_set_level(&t38_core->logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&t38_core->logging, "T.38"); logging = t30_get_logging_state(t30); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.38"); } else { logging = fax_get_logging_state(fax_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "FAX"); } memset(silence, 0, sizeof(silence)); memset(t30_amp, 0, sizeof(t30_amp)); /* Now set up and run the T.31 modem */ if ((t31_state = t31_init(NULL, at_tx_handler, NULL, modem_call_control, NULL, t31_tx_packet_handler, NULL)) == NULL) { fprintf(stderr, " Cannot start the T.31 modem\n"); exit(2); } logging = t31_get_logging_state(t31_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.31"); logging = at_get_logging_state(t31_get_at_state(t31_state)); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.31"); if (t38_mode) { t38_core = t31_get_t38_core_state(t31_state); logging = t38_core_get_logging_state(t38_core); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.31"); t31_set_mode(t31_state, true); t38_set_t38_version(t38_core, t38_version); } fast_send = false; fast_send_tcf = true; fast_blocks = 0; kick = true; #if defined(ENABLE_GUI) if (use_gui) start_media_monitor(); #endif while (!done) { if (countdown) { /* Deal with call setup, through the AT interface. */ if (answered) { countdown = 0; t31_call_event(t31_state, AT_CALL_EVENT_ANSWERED); } else if (--countdown == 0) { t31_call_event(t31_state, AT_CALL_EVENT_ALERTING); countdown = 250; } } if (kick) { /* Work through the script */ kick = false; if (fax_test_seq[test_seq_ptr].command > (const char *) 2) { if (fax_test_seq[test_seq_ptr].command[0]) { printf("%s\n", fax_test_seq[test_seq_ptr].command); t31_at_rx(t31_state, fax_test_seq[test_seq_ptr].command, fax_test_seq[test_seq_ptr].len_command); } } else { if (fax_test_seq[test_seq_ptr].command == (const char *) 2) { printf("Fast send TCF\n"); fast_send = true; fast_send_tcf = true; fast_blocks = 100; } else { printf("Fast send image\n"); fast_send = true; fast_send_tcf = false; fast_blocks = 100; } } } if (fast_send) { /* Send fast modem data */ if (fast_send_tcf) { /* If we are sending TCF, its simply zeros */ memset(fast_buf, 0, 36); if (fast_blocks == 1) { /* Tell the modem this is the end of the TCF data */ fast_buf[34] = DLE; fast_buf[35] = ETX; } } else { /* If we are sending image data, we need to make it look like genuine image data, with proper EOL and RTC markers. */ if (fast_blocks > 1) { /* Create a chunk of white page, 1728 pixels wide. */ for (i = 0; i < 36; i += 4) { fast_buf[i] = 0x00; fast_buf[i + 1] = 0x80; fast_buf[i + 2] = 0xB2; fast_buf[i + 3] = 0x01; } } else { /* Create the end of page condition. */ for (i = 0; i < 36; i += 3) { fast_buf[i] = 0x00; fast_buf[i + 1] = 0x08; fast_buf[i + 2] = 0x80; } /* Tell the modem this is the end of the image data. */ fast_buf[34] = DLE; fast_buf[35] = ETX; } } t31_at_rx(t31_state, (char *) fast_buf, 36); if (--fast_blocks == 0) fast_send = false; } if (t38_mode) { while ((msg_len = g1050_get(path_a_to_b, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) { #if defined(ENABLE_GUI) if (use_gui) media_monitor_rx(seq_no, tx_when, rx_when); #endif t38_core = t31_get_t38_core_state(t31_state); t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no); } while ((msg_len = g1050_get(path_b_to_a, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) { #if defined(ENABLE_GUI) if (use_gui) media_monitor_rx(seq_no, tx_when, rx_when); #endif t38_core = t38_terminal_get_t38_core_state(t38_state); t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no); } #if defined(ENABLE_GUI) if (use_gui) media_monitor_update_display(); #endif /* Bump the G.1050 models along */ when += (float) SAMPLES_PER_CHUNK/(float) SAMPLE_RATE; /* Bump things along on the t38_terminal side */ span_log_bump_samples(t38_terminal_get_logging_state(t38_state), SAMPLES_PER_CHUNK); t38_core = t38_terminal_get_t38_core_state(t38_state); span_log_bump_samples(t38_core_get_logging_state(t38_core), SAMPLES_PER_CHUNK); t38_terminal_send_timeout(t38_state, SAMPLES_PER_CHUNK); t31_t38_send_timeout(t31_state, SAMPLES_PER_CHUNK); } else { t30_len = fax_tx(fax_state, t30_amp, SAMPLES_PER_CHUNK); /* The receive side always expects a full block of samples, but the transmit side may not be sending any when it doesn't need to. We may need to pad with some silence. */ if (t30_len < SAMPLES_PER_CHUNK) { memset(t30_amp + t30_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len)); t30_len = SAMPLES_PER_CHUNK; } if (log_audio) { for (k = 0; k < t30_len; k++) out_amp[2*k] = t30_amp[k]; } if (t31_rx(t31_state, t30_amp, t30_len)) break; t31_len = t31_tx(t31_state, t31_amp, SAMPLES_PER_CHUNK); if (t31_len < SAMPLES_PER_CHUNK) { memset(t31_amp + t31_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t31_len)); t31_len = SAMPLES_PER_CHUNK; } if (log_audio) { for (k = 0; k < t31_len; k++) out_amp[2*k + 1] = t31_amp[k]; } if (fax_rx(fax_state, t31_amp, SAMPLES_PER_CHUNK)) break; if (log_audio) { outframes = sf_writef_short(wave_handle, out_amp, SAMPLES_PER_CHUNK); if (outframes != SAMPLES_PER_CHUNK) break; } /* Bump things along on the FAX machine side */ span_log_bump_samples(fax_get_logging_state(fax_state), SAMPLES_PER_CHUNK); } /* Bump things along on the FAX machine side */ span_log_bump_samples(t30_get_logging_state(t30), SAMPLES_PER_CHUNK); /* Bump things along on the T.31 modem side */ t38_core = t31_get_t38_core_state(t31_state); span_log_bump_samples(t38_core_get_logging_state(t38_core), SAMPLES_PER_CHUNK); span_log_bump_samples(t31_get_logging_state(t31_state), SAMPLES_PER_CHUNK); span_log_bump_samples(at_get_logging_state(t31_get_at_state(t31_state)), SAMPLES_PER_CHUNK); } if (t38_mode) t38_terminal_release(t38_state); if (decode_test_file) { if (sf_close_telephony(in_handle)) { fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file); exit(2); } } if (log_audio) { if (sf_close_telephony(wave_handle)) { fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME); exit(2); } } if (!done || !sequence_terminated) { printf("Tests failed\n"); return -1; } return 0; }
int modem_close(modem_t *modem) { int r = 0; switch_status_t was_running = switch_test_flag(modem, MODEM_FLAG_RUNNING); switch_clear_flag(modem, MODEM_FLAG_RUNNING); #ifndef WIN32 if (modem->master > -1) { shutdown(modem->master, 2); close(modem->master); modem->master = -1; #else if (modem->master) { SetEvent(modem->threadAbort); CloseHandle(modem->threadAbort); CloseHandle(modem->master); modem->master = 0; #endif r++; } if (modem->slave > -1) { shutdown(modem->slave, 2); close(modem->slave); modem->slave = -1; r++; } if (modem->t31_state) { t31_free(modem->t31_state); modem->t31_state = NULL; } unlink(modem->devlink); if (was_running) { switch_mutex_lock(globals.mutex); globals.REF_COUNT--; switch_mutex_unlock(globals.mutex); } return r; } switch_status_t modem_init(modem_t *modem, modem_control_handler_t control_handler) { switch_status_t status = SWITCH_STATUS_SUCCESS; #ifdef WIN32 COMMTIMEOUTS timeouts={0}; #endif memset(modem, 0, sizeof(*modem)); modem->master = -1; modem->slave = -1; /* windows will have to try something like: http://com0com.cvs.sourceforge.net/viewvc/com0com/com0com/ReadMe.txt?revision=RELEASED */ #if USE_OPENPTY if (openpty(&modem->master, &modem->slave, NULL, NULL, NULL)) { if (modem->master < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to initialize pty\n"); status = SWITCH_STATUS_FALSE; goto end; } modem->stty = ttyname(modem->slave); #else #if WIN32 modem->slot = 4+globals.NEXT_ID++; /* need work here we start at COM4 for now*/ snprintf(modem->devlink, sizeof(modem->devlink), "COM%d", modem->slot); modem->master = CreateFile(modem->devlink, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); if(modem->master==INVALID_HANDLE_VALUE) { status = SWITCH_STATUS_FALSE; if(GetLastError()==ERROR_FILE_NOT_FOUND) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: Serial port does not exist\n"); goto end; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: Serial port open error\n"); goto end; } #elif !defined(HAVE_POSIX_OPENPT) modem->master = open("/dev/ptmx", O_RDWR); #else modem->master = posix_openpt(O_RDWR | O_NOCTTY); #endif #ifndef WIN32 if (modem->master < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to initialize UNIX98 master pty\n"); } if (grantpt(modem->master) < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to grant access to slave pty\n"); } if (unlockpt(modem->master) < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to unlock slave pty\n"); } modem->stty = ptsname(modem->master); if (modem->stty == NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to obtain slave pty filename\n"); } modem->slave = open(modem->stty, O_RDWR); if (modem->slave < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to open slave pty %s\n", modem->stty); } #endif #ifdef SOLARIS ioctl(modem->slave, I_PUSH, "ptem"); /* push ptem */ ioctl(modem->slave, I_PUSH, "ldterm"); /* push ldterm*/ #endif #endif #ifndef WIN32 modem->slot = globals.NEXT_ID++; snprintf(modem->devlink, sizeof(modem->devlink), "/dev/FS%d", modem->slot); unlink(modem->devlink); if (symlink(modem->stty, modem->devlink)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to create %s symbolic link\n", modem->devlink); modem_close(modem); status = SWITCH_STATUS_FALSE; goto end; } if (fcntl(modem->master, F_SETFL, fcntl(modem->master, F_GETFL, 0) | O_NONBLOCK)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot set up non-blocking read on %s\n", ttyname(modem->master)); modem_close(modem); status = SWITCH_STATUS_FALSE; goto end; } #else timeouts.ReadIntervalTimeout=50; timeouts.ReadTotalTimeoutConstant=50; timeouts.ReadTotalTimeoutMultiplier=10; timeouts.WriteTotalTimeoutConstant=50; timeouts.WriteTotalTimeoutMultiplier=10; SetCommMask(modem->master, EV_RXCHAR); if(!SetCommTimeouts(modem->master, &timeouts)){ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot set up non-blocking read on %s\n", modem->devlink); modem_close(modem); status = SWITCH_STATUS_FALSE; goto end; } modem->threadAbort = CreateEvent(NULL, TRUE, FALSE, NULL); #endif if (!(modem->t31_state = t31_init(NULL, t31_at_tx_handler, modem, t31_call_control_handler, modem, NULL, NULL))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot initialize the T.31 modem\n"); modem_close(modem); status = SWITCH_STATUS_FALSE; goto end; } if (spandsp_globals.modem_verbose) { span_log_set_message_handler(&modem->t31_state->logging, spanfax_log_message, NULL); span_log_set_message_handler(&modem->t31_state->audio.modems.fast_modems.v17_rx.logging, spanfax_log_message, NULL); span_log_set_message_handler(&modem->t31_state->audio.modems.fast_modems.v29_rx.logging, spanfax_log_message, NULL); span_log_set_message_handler(&modem->t31_state->audio.modems.fast_modems.v27ter_rx.logging, spanfax_log_message, NULL); modem->t31_state->logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW; modem->t31_state->audio.modems.fast_modems.v17_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW; modem->t31_state->audio.modems.fast_modems.v29_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW; modem->t31_state->audio.modems.fast_modems.v27ter_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW; } modem->control_handler = control_handler; modem->flags = 0; switch_set_flag(modem, MODEM_FLAG_RUNNING); switch_mutex_init(&modem->mutex, SWITCH_MUTEX_NESTED, globals.pool); switch_mutex_init(&modem->cond_mutex, SWITCH_MUTEX_NESTED, globals.pool); switch_thread_cond_create(&modem->cond, globals.pool); modem_set_state(modem, MODEM_STATE_INIT); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Modem [%s]->[%s] Ready\n", modem->devlink, modem->stty); switch_mutex_lock(globals.mutex); globals.REF_COUNT++; switch_mutex_unlock(globals.mutex); end: return status; } static switch_endpoint_interface_t *modem_endpoint_interface = NULL; struct private_object { switch_mutex_t *mutex; switch_core_session_t *session; switch_channel_t *channel; switch_codec_t read_codec; switch_codec_t write_codec; switch_frame_t read_frame; unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; switch_timer_t timer; modem_t *modem; switch_caller_profile_t *caller_profile; int dead; }; typedef struct private_object private_t; static switch_status_t channel_on_init(switch_core_session_t *session); static switch_status_t channel_on_hangup(switch_core_session_t *session); static switch_status_t channel_on_destroy(switch_core_session_t *session); static switch_status_t channel_on_routing(switch_core_session_t *session); static switch_status_t channel_on_exchange_media(switch_core_session_t *session); static switch_status_t channel_on_soft_execute(switch_core_session_t *session); static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, switch_caller_profile_t *outbound_profile, switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause); static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id); static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig); /* State methods they get called when the state changes to the specific state returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it. */ static switch_status_t channel_on_init(switch_core_session_t *session) { switch_channel_t *channel; private_t *tech_pvt = NULL; int to_ticks = 60, ring_ticks = 10, rt = ring_ticks; int rest = 500000; tech_pvt = switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { #ifndef WIN32 int tioflags; #endif char call_time[16]; char call_date[16]; switch_size_t retsize; switch_time_exp_t tm; switch_time_exp_lt(&tm, switch_micro_time_now()); switch_strftime(call_date, &retsize, sizeof(call_date), "%m%d", &tm); switch_strftime(call_time, &retsize, sizeof(call_time), "%H%M", &tm); #ifndef WIN32 ioctl(tech_pvt->modem->slave, TIOCMGET, &tioflags); tioflags |= TIOCM_RI; ioctl(tech_pvt->modem->slave, TIOCMSET, &tioflags); #endif at_reset_call_info(&tech_pvt->modem->t31_state->at_state); at_set_call_info(&tech_pvt->modem->t31_state->at_state, "DATE", call_date); at_set_call_info(&tech_pvt->modem->t31_state->at_state, "TIME", call_time); at_set_call_info(&tech_pvt->modem->t31_state->at_state, "NAME", tech_pvt->caller_profile->caller_id_name); at_set_call_info(&tech_pvt->modem->t31_state->at_state, "NMBR", tech_pvt->caller_profile->caller_id_number); at_set_call_info(&tech_pvt->modem->t31_state->at_state, "ANID", tech_pvt->caller_profile->ani); at_set_call_info(&tech_pvt->modem->t31_state->at_state, "USER", tech_pvt->caller_profile->username); at_set_call_info(&tech_pvt->modem->t31_state->at_state, "CDID", tech_pvt->caller_profile->context); at_set_call_info(&tech_pvt->modem->t31_state->at_state, "NDID", tech_pvt->caller_profile->destination_number); modem_set_state(tech_pvt->modem, MODEM_STATE_RINGING); t31_call_event(tech_pvt->modem->t31_state, AT_CALL_EVENT_ALERTING); while(to_ticks > 0 && switch_channel_up(channel) && modem_get_state(tech_pvt->modem) == MODEM_STATE_RINGING) { if (--rt <= 0) { t31_call_event(tech_pvt->modem->t31_state, AT_CALL_EVENT_ALERTING); rt = ring_ticks; } switch_yield(rest); to_ticks--; } if (to_ticks < 1 || modem_get_state(tech_pvt->modem) != MODEM_STATE_ANSWERED) { t31_call_event(tech_pvt->modem->t31_state, AT_CALL_EVENT_NO_ANSWER); switch_channel_hangup(channel, SWITCH_CAUSE_NO_ANSWER); } else { t31_call_event(tech_pvt->modem->t31_state, AT_CALL_EVENT_ANSWERED); modem_set_state(tech_pvt->modem, MODEM_STATE_CONNECTED); switch_channel_mark_answered(channel); } } switch_channel_set_state(channel, CS_ROUTING); return SWITCH_STATUS_SUCCESS; }
int main(int argc, char *argv[]) { int i; int k; int outframes; fax_state_t fax_state; int16_t t30_amp[SAMPLES_PER_CHUNK]; int16_t t31_amp[SAMPLES_PER_CHUNK]; int16_t silence[SAMPLES_PER_CHUNK]; int16_t out_amp[2*SAMPLES_PER_CHUNK]; int t30_len; int t31_len; AFfilesetup filesetup; AFfilehandle wave_handle; AFfilehandle in_handle; int log_audio; int test_sending; int fast_send; int fast_blocks; uint8_t fast_buf[1000]; decode_test_file = NULL; log_audio = FALSE; test_sending = FALSE; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-d") == 0) { decode_test_file = argv[++i]; continue; } if (strcmp(argv[i], "-l") == 0) { log_audio = TRUE; continue; } if (strcmp(argv[i], "-r") == 0) { test_sending = FALSE; continue; } if (strcmp(argv[i], "-s") == 0) { test_sending = TRUE; continue; } } filesetup = AF_NULL_FILESETUP; wave_handle = AF_NULL_FILEHANDLE; if (log_audio) { if ((filesetup = afNewFileSetup()) == AF_NULL_FILESETUP) { fprintf(stderr, " Failed to create file setup\n"); exit(2); } afInitSampleFormat(filesetup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16); afInitRate(filesetup, AF_DEFAULT_TRACK, (float) SAMPLE_RATE); afInitFileFormat(filesetup, AF_FILE_WAVE); afInitChannels(filesetup, AF_DEFAULT_TRACK, 2); if ((wave_handle = afOpenFile(OUTPUT_WAVE_FILE_NAME, "w", filesetup)) == AF_NULL_FILEHANDLE) { fprintf(stderr, " Cannot create wave file '%s'\n", OUTPUT_WAVE_FILE_NAME); exit(2); } } memset(silence, 0, sizeof(silence)); in_handle = NULL; if (decode_test_file) { if ((in_handle = afOpenFile(decode_test_file, "r", NULL)) == AF_NULL_FILEHANDLE) { fprintf(stderr, " Cannot create wave file '%s'\n", decode_test_file); exit(2); } } if (test_sending) { fax_init(&fax_state, FALSE); t30_set_rx_file(&fax_state.t30_state, OUTPUT_FILE_NAME, -1); fax_test_seq = fax_send_test_seq; countdown = 0; } else { fax_init(&fax_state, TRUE); t30_set_tx_file(&fax_state.t30_state, INPUT_FILE_NAME, -1, -1); fax_test_seq = fax_receive_test_seq; countdown = 250; } t30_set_local_ident(&fax_state.t30_state, "11111111"); t30_set_phase_b_handler(&fax_state.t30_state, phase_b_handler, (void *) 0); t30_set_phase_d_handler(&fax_state.t30_state, phase_d_handler, (void *) 0); t30_set_phase_e_handler(&fax_state.t30_state, phase_e_handler, (void *) 0); memset(t30_amp, 0, sizeof(t30_amp)); span_log_set_level(&fax_state.t30_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); span_log_set_tag(&fax_state.t30_state.logging, "YYY"); span_log_set_level(&fax_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); span_log_set_tag(&fax_state.logging, "YYY"); if (t31_init(&t31_state, at_tx_handler, NULL, modem_call_control, NULL, NULL, NULL) == NULL) { fprintf(stderr, " Cannot start the FAX modem\n"); exit(2); } span_log_set_level(&t31_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); span_log_set_tag(&t31_state.logging, "XXX"); fast_send = FALSE; fast_blocks = 0; kick = TRUE; while (!done) { if (kick) { kick = FALSE; if (fax_test_seq[test_seq_ptr].command > (const char *) 1) { if (fax_test_seq[test_seq_ptr].command[0]) { printf("%s\n", fax_test_seq[test_seq_ptr].command); t31_at_rx(&t31_state, fax_test_seq[test_seq_ptr].command, fax_test_seq[test_seq_ptr].len_command); } } else { printf("Fast send\n"); fast_send = TRUE; fast_blocks = 100; } } if (fast_send) { /* Send fast modem data */ memset(fast_buf, 0, 36); if (fast_blocks == 1) { /* Insert EOLs */ fast_buf[35] = ETX; fast_buf[34] = DLE; fast_buf[31] = fast_buf[28] = fast_buf[25] = fast_buf[22] = fast_buf[19] = fast_buf[16] = 1; } t31_at_rx(&t31_state, (char *) fast_buf, 36); if (--fast_blocks == 0) fast_send = FALSE; } t30_len = fax_tx(&fax_state, t30_amp, SAMPLES_PER_CHUNK); /* The receive side always expects a full block of samples, but the transmit side may not be sending any when it doesn't need to. We may need to pad with some silence. */ if (t30_len < SAMPLES_PER_CHUNK) { memset(t30_amp + t30_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len)); t30_len = SAMPLES_PER_CHUNK; } if (log_audio) { for (k = 0; k < t30_len; k++) out_amp[2*k] = t30_amp[k]; } if (t31_rx(&t31_state, t30_amp, t30_len)) break; if (countdown) { if (answered) { countdown = 0; t31_call_event(&t31_state, AT_CALL_EVENT_ANSWERED); } else if (--countdown == 0) { t31_call_event(&t31_state, AT_CALL_EVENT_ALERTING); countdown = 250; } } t31_len = t31_tx(&t31_state, t31_amp, SAMPLES_PER_CHUNK); if (t31_len < SAMPLES_PER_CHUNK) { memset(t31_amp + t31_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t31_len)); t31_len = SAMPLES_PER_CHUNK; } if (log_audio) { for (k = 0; k < t31_len; k++) out_amp[2*k + 1] = t31_amp[k]; } if (fax_rx(&fax_state, t31_amp, SAMPLES_PER_CHUNK)) break; if (log_audio) { outframes = afWriteFrames(wave_handle, AF_DEFAULT_TRACK, out_amp, SAMPLES_PER_CHUNK); if (outframes != SAMPLES_PER_CHUNK) break; } } if (decode_test_file) { if (afCloseFile(in_handle) != 0) { fprintf(stderr, " Cannot close wave file '%s'\n", decode_test_file); exit(2); } } if (log_audio) { if (afCloseFile(wave_handle) != 0) { fprintf(stderr, " Cannot close wave file '%s'\n", OUTPUT_WAVE_FILE_NAME); exit(2); } afFreeFileSetup(filesetup); } if (done) { printf("Tests passed\n"); } return 0; }