Mercurial > hg > audiostuff
view spandsp-0.0.3/spandsp-0.0.3/src/t31.c @ 5:f762bf195c4b
import spandsp-0.0.3
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 16:00:21 +0200 |
parents | |
children |
line wrap: on
line source
/* * SpanDSP - a series of DSP components for telephony * * t31.c - A T.31 compatible class 1 FAX modem interface. * * Written by Steve Underwood <steveu@coppice.org> * * Special thanks to Lee Howard <faxguy@howardsilvan.com> * for his great work debugging and polishing this code. * * Copyright (C) 2004, 2005, 2006 Steve Underwood * * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: t31.c,v 1.83 2006/11/30 15:41:47 steveu Exp $ */ /*! \file */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #define _GNU_SOURCE #include <inttypes.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <time.h> #include <memory.h> #include <string.h> #include <ctype.h> #if defined(HAVE_TGMATH_H) #include <tgmath.h> #endif #if defined(HAVE_MATH_H) #include <math.h> #endif #include <assert.h> #include <tiffio.h> #include "spandsp/telephony.h" #include "spandsp/logging.h" #include "spandsp/bit_operations.h" #include "spandsp/dc_restore.h" #include "spandsp/queue.h" #include "spandsp/power_meter.h" #include "spandsp/complex.h" #include "spandsp/tone_generate.h" #include "spandsp/async.h" #include "spandsp/hdlc.h" #include "spandsp/silence_gen.h" #include "spandsp/fsk.h" #include "spandsp/v29rx.h" #include "spandsp/v29tx.h" #include "spandsp/v27ter_rx.h" #include "spandsp/v27ter_tx.h" #if defined(ENABLE_V17) #include "spandsp/v17rx.h" #include "spandsp/v17tx.h" #endif #include "spandsp/t4.h" #include "spandsp/t30.h" #include "spandsp/t38_core.h" #include "spandsp/at_interpreter.h" #include "spandsp/t31.h" #define MS_PER_TX_CHUNK 30 #define INDICATOR_TX_COUNT 4 #define DEFAULT_DTE_TIMEOUT 5 typedef const char *(*at_cmd_service_t)(t31_state_t *s, const char *cmd); #define ETX 0x03 #define DLE 0x10 #define SUB 0x1A enum { T31_FLUSH, T31_SILENCE_TX, T31_SILENCE_RX, T31_CED_TONE, T31_CNG_TONE, T31_NOCNG_TONE, T31_V21_TX, T31_V17_TX, T31_V27TER_TX, T31_V29_TX, T31_V21_RX, T31_V17_RX, T31_V27TER_RX, T31_V29_RX }; enum { T38_TIMED_STEP_NONE = 0, T38_TIMED_STEP_NON_ECM_MODEM, T38_TIMED_STEP_NON_ECM_MODEM_2, T38_TIMED_STEP_NON_ECM_MODEM_3, T38_TIMED_STEP_HDLC_MODEM, T38_TIMED_STEP_HDLC_MODEM_2, T38_TIMED_STEP_HDLC_MODEM_3, T38_TIMED_STEP_HDLC_MODEM_4, T38_TIMED_STEP_PAUSE }; static int restart_modem(t31_state_t *s, int new_modem); static void hdlc_accept(void *user_data, int ok, const uint8_t *msg, int len); #if defined(ENABLE_V17) static int early_v17_rx(void *user_data, const int16_t amp[], int len); #endif static int early_v27ter_rx(void *user_data, const int16_t amp[], int len); static int early_v29_rx(void *user_data, const int16_t amp[], int len); static int dummy_rx(void *s, const int16_t amp[], int len); static int silence_rx(void *user_data, const int16_t amp[], int len); static int cng_rx(void *user_data, const int16_t amp[], int len); static __inline__ void t31_set_at_rx_mode(t31_state_t *s, int new_mode) { s->at_state.at_rx_mode = new_mode; } /*- End of function --------------------------------------------------------*/ static int process_rx_indicator(t38_core_state_t *s, void *user_data, int indicator) { t31_state_t *t; t = (t31_state_t *) user_data; switch (indicator) { case T38_IND_NO_SIGNAL: break; case T38_IND_CNG: break; case T38_IND_CED: break; case T38_IND_V21_PREAMBLE: t->hdlc_rx_len = 0; break; case T38_IND_V27TER_2400_TRAINING: break; case T38_IND_V27TER_4800_TRAINING: break; case T38_IND_V29_7200_TRAINING: break; case T38_IND_V29_9600_TRAINING: break; case T38_IND_V17_7200_SHORT_TRAINING: break; case T38_IND_V17_7200_LONG_TRAINING: break; case T38_IND_V17_9600_SHORT_TRAINING: break; case T38_IND_V17_9600_LONG_TRAINING: break; case T38_IND_V17_12000_SHORT_TRAINING: break; case T38_IND_V17_12000_LONG_TRAINING: break; case T38_IND_V17_14400_SHORT_TRAINING: break; case T38_IND_V17_14400_LONG_TRAINING: break; case T38_IND_V8_ANSAM: break; case T38_IND_V8_SIGNAL: break; case T38_IND_V34_CNTL_CHANNEL_1200: break; case T38_IND_V34_PRI_CHANNEL: break; case T38_IND_V34_CC_RETRAIN: break; case T38_IND_V33_12000_TRAINING: break; case T38_IND_V33_14400_TRAINING: break; default: break; } t->missing_data = FALSE; return 0; } /*- End of function --------------------------------------------------------*/ static int process_rx_data(t38_core_state_t *s, void *user_data, int data_type, int field_type, const uint8_t *buf, int len) { t31_state_t *t; int i; t = (t31_state_t *) user_data; switch (data_type) { case T38_DATA_V21: case T38_DATA_V27TER_2400: case T38_DATA_V27TER_4800: case T38_DATA_V29_7200: case T38_DATA_V29_9600: case T38_DATA_V17_7200: case T38_DATA_V17_9600: case T38_DATA_V17_12000: case T38_DATA_V17_14400: case T38_DATA_V8: case T38_DATA_V34_PRI_RATE: case T38_DATA_V34_CC_1200: case T38_DATA_V34_PRI_CH: case T38_DATA_V33_12000: case T38_DATA_V33_14400: default: break; } switch (field_type) { case T38_FIELD_HDLC_DATA: if (t->hdlc_rx_len + len <= 256 - 2) { for (i = 0; i < len; i++) t->hdlc_rx_buf[t->hdlc_rx_len++] = bit_reverse8(buf[i]); } break; case T38_FIELD_HDLC_FCS_OK: if (len > 0) span_log(&t->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK!\n"); span_log(&t->logging, SPAN_LOG_FLOW, "Type %s - CRC OK (%s)\n", t30_frametype(t->tx_data[2]), (t->missing_data) ? "missing octets" : "clean"); /* Don't deal with zero length frames. Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK packets, when they have sent no data for the body of the frame. */ if (t->current_rx_type == T31_V21_RX && t->tx_out_bytes > 0 && !t->missing_data) hdlc_accept((void *) t, TRUE, t->hdlc_rx_buf, t->hdlc_rx_len); t->hdlc_rx_len = 0; t->missing_data = FALSE; break; case T38_FIELD_HDLC_FCS_BAD: if (len > 0) span_log(&t->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD!\n"); span_log(&t->logging, SPAN_LOG_FLOW, "Type %s - CRC bad (%s)\n", t30_frametype(t->tx_data[2]), (t->missing_data) ? "missing octets" : "clean"); t->hdlc_rx_len = 0; t->missing_data = FALSE; break; case T38_FIELD_HDLC_FCS_OK_SIG_END: if (len > 0) span_log(&t->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK_SIG_END!\n"); span_log(&t->logging, SPAN_LOG_FLOW, "Type %s - CRC OK, sig end (%s)\n", t30_frametype(t->tx_data[2]), (t->missing_data) ? "missing octets" : "clean"); if (t->current_rx_type == T31_V21_RX) { /* Don't deal with zero length frames. Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK packets, when they have sent no data for the body of the frame. */ if (t->tx_out_bytes > 0) hdlc_accept((void *) t, TRUE, t->hdlc_rx_buf, t->hdlc_rx_len); hdlc_accept((void *) t, TRUE, NULL, PUTBIT_CARRIER_DOWN); } t->tx_out_bytes = 0; t->missing_data = FALSE; t->hdlc_rx_len = 0; t->missing_data = FALSE; break; case T38_FIELD_HDLC_FCS_BAD_SIG_END: if (len > 0) span_log(&t->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD_SIG_END!\n"); span_log(&t->logging, SPAN_LOG_FLOW, "Type %s - CRC bad, sig end (%s)\n", t30_frametype(t->tx_data[2]), (t->missing_data) ? "missing octets" : "clean"); if (t->current_rx_type == T31_V21_RX) hdlc_accept((void *) t, TRUE, NULL, PUTBIT_CARRIER_DOWN); t->hdlc_rx_len = 0; t->missing_data = FALSE; break; case T38_FIELD_HDLC_SIG_END: if (len > 0) span_log(&t->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_SIG_END!\n"); /* This message is expected under 2 circumstances. One is as an alternative to T38_FIELD_HDLC_FCS_OK_SIG_END - i.e. they send T38_FIELD_HDLC_FCS_OK, and then T38_FIELD_HDLC_SIG_END when the carrier actually drops. The other is because the HDLC signal drops unexpectedly - i.e. not just after a final frame. */ if (t->current_rx_type == T31_V21_RX) hdlc_accept((void *) t, TRUE, NULL, PUTBIT_CARRIER_DOWN); t->hdlc_rx_len = 0; t->missing_data = FALSE; break; case T38_FIELD_T4_NON_ECM_DATA: break; case T38_FIELD_T4_NON_ECM_SIG_END: break; case T38_FIELD_CM_MESSAGE: case T38_FIELD_JM_MESSAGE: case T38_FIELD_CI_MESSAGE: case T38_FIELD_V34RATE: default: break; } return 0; } /*- End of function --------------------------------------------------------*/ static int process_rx_missing(t38_core_state_t *s, void *user_data, int rx_seq_no, int expected_seq_no) { t31_state_t *t; t = (t31_state_t *) user_data; t->missing_data = TRUE; return 0; } /*- End of function --------------------------------------------------------*/ int t31_t38_send_timeout(t31_state_t *s, int samples) { int len; uint8_t buf[100]; /* Training times for all the modem options, with and without TEP */ static const int training_time[] = { 0, 0, /* T38_IND_NO_SIGNAL */ 0, 0, /* T38_IND_CNG */ 0, 0, /* T38_IND_CED */ 1000, 1000, /* T38_IND_V21_PREAMBLE */ 943, 1158, /* T38_IND_V27TER_2400_TRAINING */ 708, 923, /* T38_IND_V27TER_4800_TRAINING */ 234, 454, /* T38_IND_V29_7200_TRAINING */ 234, 454, /* T38_IND_V29_9600_TRAINING */ 142, 367, /* T38_IND_V17_7200_SHORT_TRAINING */ 1393, 1618, /* T38_IND_V17_7200_LONG_TRAINING */ 142, 367, /* T38_IND_V17_9600_SHORT_TRAINING */ 1393, 1618, /* T38_IND_V17_9600_LONG_TRAINING */ 142, 367, /* T38_IND_V17_12000_SHORT_TRAINING */ 1393, 1618, /* T38_IND_V17_12000_LONG_TRAINING */ 142, 367, /* T38_IND_V17_14400_SHORT_TRAINING */ 1393, 1618, /* T38_IND_V17_14400_LONG_TRAINING */ 0, 0, /* T38_IND_V8_ANSAM */ 0, 0, /* T38_IND_V8_SIGNAL */ 0, 0, /* T38_IND_V34_CNTL_CHANNEL_1200 */ 0, 0, /* T38_IND_V34_PRI_CHANNEL */ 0, 0, /* T38_IND_V34_CC_RETRAIN */ 0, 0, /* T38_IND_V33_12000_TRAINING */ 0, 0, /* T38_IND_V33_14400_TRAINING */ }; s->call_samples += samples; if (s->timed_step == T38_TIMED_STEP_NONE) return 0; if (s->call_samples < s->next_send_samples) return 0; len = 0; switch (s->timed_step) { case T38_TIMED_STEP_NON_ECM_MODEM: /* Create a 75ms silence */ t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, INDICATOR_TX_COUNT); s->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_2; s->next_send_samples += ms_to_samples(75); break; case T38_TIMED_STEP_NON_ECM_MODEM_2: /* Switch on a fast modem, and give the training time to complete */ t38_core_send_indicator(&s->t38, s->next_tx_indicator, INDICATOR_TX_COUNT); s->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_3; s->next_send_samples += ms_to_samples(training_time[s->next_tx_indicator << 1]); break; case T38_TIMED_STEP_NON_ECM_MODEM_3: /* Send a chunk of non-ECM image data */ //if ((len = get_non_ecm_image_chunk(s, buf, s->octets_per_non_ecm_packet))) // t38_core_send_data(&s->t38, s->current_tx_data, T38_FIELD_T4_NON_ECM_DATA, buf, abs(len)); if (len > 0) { s->next_send_samples += ms_to_samples(MS_PER_TX_CHUNK); } else { t38_core_send_data(&s->t38, s->current_tx_data, T38_FIELD_T4_NON_ECM_SIG_END, NULL, 0); t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, INDICATOR_TX_COUNT); s->timed_step = T38_TIMED_STEP_NONE; } break; case T38_TIMED_STEP_HDLC_MODEM: /* Send HDLC preambling */ t38_core_send_indicator(&s->t38, s->next_tx_indicator, INDICATOR_TX_COUNT); s->next_send_samples += ms_to_samples(training_time[s->next_tx_indicator << 1]); s->timed_step = T38_TIMED_STEP_HDLC_MODEM_2; break; case T38_TIMED_STEP_HDLC_MODEM_2: /* Send HDLC octet */ buf[0] = bit_reverse8(s->hdlc_tx_buf[s->hdlc_tx_ptr++]); t38_core_send_data(&s->t38, s->current_tx_data, T38_FIELD_HDLC_DATA, buf, 1); if (s->hdlc_tx_ptr >= s->hdlc_tx_len) s->timed_step = T38_TIMED_STEP_HDLC_MODEM_3; s->next_send_samples += ms_to_samples(MS_PER_TX_CHUNK); break; case T38_TIMED_STEP_HDLC_MODEM_3: /* End of HDLC frame */ s->hdlc_tx_ptr = 0; if (s->hdlc_final) { s->hdlc_tx_len = 0; t38_core_send_data(&s->t38, s->current_tx_data, T38_FIELD_HDLC_FCS_OK_SIG_END, NULL, 0); s->timed_step = T38_TIMED_STEP_HDLC_MODEM_4; at_put_response_code(&s->at_state, AT_RESPONSE_CODE_OK); t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND); s->hdlc_final = FALSE; restart_modem(s, T31_SILENCE_TX); } else { t38_core_send_data(&s->t38, s->current_tx_data, T38_FIELD_HDLC_FCS_OK, NULL, 0); s->timed_step = T38_TIMED_STEP_HDLC_MODEM_2; at_put_response_code(&s->at_state, AT_RESPONSE_CODE_CONNECT); } s->next_send_samples += ms_to_samples(MS_PER_TX_CHUNK); break; case T38_TIMED_STEP_HDLC_MODEM_4: /* End of HDLC transmission */ /* We have already sent T38_FIELD_HDLC_FCS_OK_SIG_END. It seems some boxes may not like us sending a T38_FIELD_HDLC_SIG_END at this point. Just say there is no signal. */ //t38_core_send_data(&s->t38, s->current_tx_data, T38_FIELD_HDLC_SIG_END, NULL, 0); t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, INDICATOR_TX_COUNT); s->timed_step = T38_TIMED_STEP_NONE; break; case T38_TIMED_STEP_PAUSE: /* End of timed pause */ s->timed_step = T38_TIMED_STEP_NONE; break; } return 0; } /*- End of function --------------------------------------------------------*/ static int t31_modem_control_handler(at_state_t *s, void *user_data, int op, const char *num) { t31_state_t *t; t = (t31_state_t *) user_data; switch (op) { case AT_MODEM_CONTROL_ANSWER: t->call_samples = 0; break; case AT_MODEM_CONTROL_CALL: t->call_samples = 0; break; case AT_MODEM_CONTROL_ONHOOK: if (t->tx_holding) { t->tx_holding = FALSE; /* Tell the application to release further data */ at_modem_control(&t->at_state, AT_MODEM_CONTROL_CTS, (void *) 1); } if (t->at_state.rx_signal_present) { t->at_state.rx_data[t->at_state.rx_data_bytes++] = DLE; t->at_state.rx_data[t->at_state.rx_data_bytes++] = ETX; t->at_state.at_tx_handler(&t->at_state, t->at_state.at_tx_user_data, t->at_state.rx_data, t->at_state.rx_data_bytes); t->at_state.rx_data_bytes = 0; } restart_modem(t, T31_SILENCE_TX); break; case AT_MODEM_CONTROL_RESTART: restart_modem(t, (int) (intptr_t) num); return 0; case AT_MODEM_CONTROL_DTE_TIMEOUT: if (num) t->dte_data_timeout = t->call_samples + ms_to_samples((intptr_t) num); else t->dte_data_timeout = 0; return 0; } return t->modem_control_handler(t, t->modem_control_user_data, op, num); } /*- End of function --------------------------------------------------------*/ static void non_ecm_put_bit(void *user_data, int bit) { t31_state_t *s; s = (t31_state_t *) user_data; if (bit < 0) { /* Special conditions */ switch (bit) { case PUTBIT_TRAINING_FAILED: s->at_state.rx_trained = FALSE; break; case PUTBIT_TRAINING_SUCCEEDED: /* The modem is now trained */ at_put_response_code(&s->at_state, AT_RESPONSE_CODE_CONNECT); s->at_state.rx_signal_present = TRUE; s->at_state.rx_trained = TRUE; break; case PUTBIT_CARRIER_UP: break; case PUTBIT_CARRIER_DOWN: if (s->at_state.rx_signal_present) { s->at_state.rx_data[s->at_state.rx_data_bytes++] = DLE; s->at_state.rx_data[s->at_state.rx_data_bytes++] = ETX; s->at_state.at_tx_handler(&s->at_state, s->at_state.at_tx_user_data, s->at_state.rx_data, s->at_state.rx_data_bytes); s->at_state.rx_data_bytes = 0; at_put_response_code(&s->at_state, AT_RESPONSE_CODE_NO_CARRIER); t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND); } s->at_state.rx_signal_present = FALSE; s->at_state.rx_trained = FALSE; break; default: if (s->at_state.p.result_code_format) span_log(&s->logging, SPAN_LOG_FLOW, "Eh!\n"); break; } return; } s->current_byte = (s->current_byte >> 1) | (bit << 7); if (++s->bit_no >= 8) { if (s->current_byte == DLE) s->at_state.rx_data[s->at_state.rx_data_bytes++] = (uint8_t) s->current_byte; s->at_state.rx_data[s->at_state.rx_data_bytes++] = (uint8_t) s->current_byte; if (s->at_state.rx_data_bytes >= 250) { s->at_state.at_tx_handler(&s->at_state, s->at_state.at_tx_user_data, s->at_state.rx_data, s->at_state.rx_data_bytes); s->at_state.rx_data_bytes = 0; } s->bit_no = 0; s->current_byte = 0; } } /*- End of function --------------------------------------------------------*/ static int non_ecm_get_bit(void *user_data) { t31_state_t *s; int bit; int fill; s = (t31_state_t *) user_data; if (s->bit_no <= 0) { if (s->tx_out_bytes != s->tx_in_bytes) { /* There is real data available to send */ s->current_byte = s->tx_data[s->tx_out_bytes]; s->tx_out_bytes = (s->tx_out_bytes + 1) & (T31_TX_BUF_LEN - 1); if (s->tx_holding) { /* See if the buffer is approaching empty. It might be time to release flow control. */ fill = (s->tx_in_bytes - s->tx_out_bytes); if (s->tx_in_bytes < s->tx_out_bytes) fill += (T31_TX_BUF_LEN + 1); if (fill < T31_TX_BUF_LOW_TIDE) { s->tx_holding = FALSE; /* Tell the application to release further data */ at_modem_control(&s->at_state, AT_MODEM_CONTROL_CTS, (void *) 1); } } s->tx_data_started = TRUE; } else { if (s->data_final) { s->data_final = FALSE; /* This will put the modem into its shutdown sequence. When it has finally shut down, an OK response will be sent. */ return PUTBIT_END_OF_DATA; } /* Fill with 0xFF bytes at the start of transmission, or 0x00 if we are in the middle of transmission. This follows T.31 and T.30 practice. */ s->current_byte = (s->tx_data_started) ? 0x00 : 0xFF; } s->bit_no = 8; } s->bit_no--; bit = s->current_byte & 1; s->current_byte >>= 1; return bit; } /*- End of function --------------------------------------------------------*/ static void hdlc_tx_underflow(void *user_data) { t31_state_t *s; s = (t31_state_t *) user_data; if (s->hdlc_final) { s->hdlc_final = FALSE; /* Schedule an orderly shutdown of the modem */ hdlc_tx_frame(&(s->hdlctx), NULL, 0); } else { at_put_response_code(&s->at_state, AT_RESPONSE_CODE_CONNECT); } } /*- End of function --------------------------------------------------------*/ static void hdlc_accept(void *user_data, int ok, const uint8_t *msg, int len) { uint8_t buf[256]; t31_state_t *s; int i; s = (t31_state_t *) user_data; if (len < 0) { /* Special conditions */ switch (len) { case PUTBIT_TRAINING_FAILED: s->at_state.rx_trained = FALSE; break; case PUTBIT_TRAINING_SUCCEEDED: /* The modem is now trained */ s->at_state.rx_signal_present = TRUE; s->at_state.rx_trained = TRUE; break; case PUTBIT_CARRIER_UP: if (s->modem == T31_CNG_TONE || s->modem == T31_NOCNG_TONE || s->modem == T31_V21_RX) { s->at_state.rx_signal_present = TRUE; s->rx_message_received = FALSE; } break; case PUTBIT_CARRIER_DOWN: if (s->rx_message_received) { if (s->at_state.dte_is_waiting) { if (s->at_state.ok_is_pending) { at_put_response_code(&s->at_state, AT_RESPONSE_CODE_OK); s->at_state.ok_is_pending = FALSE; } else { at_put_response_code(&s->at_state, AT_RESPONSE_CODE_NO_CARRIER); t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND); } s->at_state.dte_is_waiting = FALSE; } else { buf[0] = AT_RESPONSE_CODE_NO_CARRIER; queue_write_msg(&(s->rx_queue), buf, 1); } } s->at_state.rx_signal_present = FALSE; s->at_state.rx_trained = FALSE; break; case PUTBIT_FRAMING_OK: if (s->modem == T31_CNG_TONE || s->modem == T31_NOCNG_TONE) { /* Once we get any valid HDLC the CNG tone stops, and we drop to the V.21 receive modem on its own. */ s->modem = T31_V21_RX; s->at_state.transmit = FALSE; } if (s->modem != T31_V21_RX) { /* V.21 has been detected while expecting a different carrier. If +FAR=0 then result +FCERROR and return to command-mode. If +FAR=1 then report +FRH:3 and CONNECT, switching to V.21 receive mode. */ if (s->at_state.p.adaptive_receive) { s->at_state.rx_signal_present = TRUE; s->rx_message_received = TRUE; s->modem = T31_V21_RX; s->at_state.transmit = FALSE; s->at_state.dte_is_waiting = TRUE; at_put_response_code(&s->at_state, AT_RESPONSE_CODE_FRH3); at_put_response_code(&s->at_state, AT_RESPONSE_CODE_CONNECT); } else { s->modem = T31_SILENCE_TX; t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND); s->rx_message_received = FALSE; at_put_response_code(&s->at_state, AT_RESPONSE_CODE_FCERROR); } } else { if (!s->rx_message_received) { /* Report CONNECT as soon as possible to avoid a timeout. */ at_put_response_code(&s->at_state, AT_RESPONSE_CODE_CONNECT); s->rx_message_received = TRUE; } } break; case PUTBIT_ABORT: /* Just ignore these */ break; default: span_log(&s->logging, SPAN_LOG_WARNING, "Unexpected HDLC special length - %d!\n", len); break; } return; } /* If OK is pending then we just ignore whatever comes in */ if (!s->at_state.ok_is_pending) { if (s->at_state.dte_is_waiting) { /* Send straight away */ /* It is safe to look at the two bytes beyond the length of the message, and expect to find the FCS there. */ for (i = 0; i < len + 2; i++) { if (msg[i] == DLE) s->at_state.rx_data[s->at_state.rx_data_bytes++] = DLE; s->at_state.rx_data[s->at_state.rx_data_bytes++] = msg[i]; } s->at_state.rx_data[s->at_state.rx_data_bytes++] = DLE; s->at_state.rx_data[s->at_state.rx_data_bytes++] = ETX; s->at_state.at_tx_handler(&s->at_state, s->at_state.at_tx_user_data, s->at_state.rx_data, s->at_state.rx_data_bytes); s->at_state.rx_data_bytes = 0; if (msg[1] == 0x13 && ok) { /* This is the last frame. We don't send OK until the carrier drops to avoid redetecting it later. */ s->at_state.ok_is_pending = TRUE; } else { at_put_response_code(&s->at_state, (ok) ? AT_RESPONSE_CODE_OK : AT_RESPONSE_CODE_ERROR); s->at_state.dte_is_waiting = FALSE; s->rx_message_received = FALSE; } } else { /* Queue it */ buf[0] = (ok) ? AT_RESPONSE_CODE_OK : AT_RESPONSE_CODE_ERROR; /* It is safe to look at the two bytes beyond the length of the message, and expect to find the FCS there. */ memcpy(buf + 1, msg, len + 2); queue_write_msg(&(s->rx_queue), buf, len + 3); } } t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND); } /*- End of function --------------------------------------------------------*/ static void t31_v21_rx(t31_state_t *s) { hdlc_rx_init(&(s->hdlcrx), FALSE, TRUE, 5, hdlc_accept, s); s->at_state.ok_is_pending = FALSE; s->hdlc_final = FALSE; s->hdlc_tx_len = 0; s->dled = FALSE; fsk_rx_init(&(s->v21rx), &preset_fsk_specs[FSK_V21CH2], TRUE, (put_bit_func_t) hdlc_rx_put_bit, &(s->hdlcrx)); s->at_state.transmit = TRUE; } /*- End of function --------------------------------------------------------*/ static int restart_modem(t31_state_t *s, int new_modem) { tone_gen_descriptor_t tone_desc; int ind; span_log(&s->logging, SPAN_LOG_FLOW, "Restart modem %d\n", new_modem); if (s->modem == new_modem) return 0; queue_flush(&(s->rx_queue)); s->modem = new_modem; s->data_final = FALSE; s->at_state.rx_signal_present = FALSE; s->at_state.rx_trained = FALSE; s->rx_message_received = FALSE; s->rx_handler = (span_rx_handler_t *) &dummy_rx; s->rx_user_data = NULL; switch (s->modem) { case T31_CNG_TONE: if (s->t38_mode) { t38_core_send_indicator(&s->t38, T38_IND_CNG, INDICATOR_TX_COUNT); } else { /* CNG is special, since we need to receive V.21 HDLC messages while sending the tone. Everything else in FAX processing sends only one way at a time. */ /* 0.5s of 1100Hz + 3.0s of silence repeating */ make_tone_gen_descriptor(&tone_desc, 1100, -11, 0, 0, 500, 3000, 0, 0, TRUE); tone_gen_init(&(s->tone_gen), &tone_desc); /* Do V.21/HDLC receive in parallel. The other end may send its first message at any time. The CNG tone will continue until we get a valid preamble. */ s->rx_handler = (span_rx_handler_t *) &cng_rx; s->rx_user_data = s; t31_v21_rx(s); s->tx_handler = (span_tx_handler_t *) &tone_gen; s->tx_user_data = &(s->tone_gen); s->next_tx_handler = NULL; } s->at_state.transmit = TRUE; break; case T31_NOCNG_TONE: if (s->t38_mode) { } else { s->rx_handler = (span_rx_handler_t *) &cng_rx; s->rx_user_data = s; t31_v21_rx(s); silence_gen_set(&(s->silence_gen), 0); s->tx_handler = (span_tx_handler_t *) &silence_gen; s->tx_user_data = &(s->silence_gen); } s->at_state.transmit = FALSE; break; case T31_CED_TONE: if (s->t38_mode) { t38_core_send_indicator(&s->t38, T38_IND_CED, INDICATOR_TX_COUNT); } else { silence_gen_alter(&(s->silence_gen), ms_to_samples(200)); make_tone_gen_descriptor(&tone_desc, 2100, -11, 0, 0, 2600, 75, 0, 0, FALSE); tone_gen_init(&(s->tone_gen), &tone_desc); s->tx_handler = (span_tx_handler_t *) &silence_gen; s->tx_user_data = &(s->silence_gen); s->next_tx_handler = (span_tx_handler_t *) &tone_gen; s->next_tx_user_data = &(s->tone_gen); } s->at_state.transmit = TRUE; break; case T31_V21_TX: if (s->t38_mode) { t38_core_send_indicator(&s->t38, T38_IND_V21_PREAMBLE, INDICATOR_TX_COUNT); } else { hdlc_tx_init(&(s->hdlctx), FALSE, 2, FALSE, hdlc_tx_underflow, s); /* The spec says 1s +-15% of preamble. So, the minimum is 32 octets. */ hdlc_tx_preamble(&(s->hdlctx), 32); fsk_tx_init(&(s->v21tx), &preset_fsk_specs[FSK_V21CH2], (get_bit_func_t) hdlc_tx_get_bit, &(s->hdlctx)); s->tx_handler = (span_tx_handler_t *) &fsk_tx; s->tx_user_data = &(s->v21tx); s->next_tx_handler = NULL; } s->hdlc_final = FALSE; s->hdlc_tx_len = 0; s->dled = FALSE; s->at_state.transmit = TRUE; break; case T31_V21_RX: if (s->t38_mode) { } else { s->rx_handler = (span_rx_handler_t *) &fsk_rx; s->rx_user_data = &(s->v21rx); t31_v21_rx(s); } break; #if defined(ENABLE_V17) case T31_V17_TX: if (s->t38_mode) { switch (s->bit_rate) { case 7200: ind = (s->short_train) ? T38_IND_V17_7200_SHORT_TRAINING : T38_IND_V17_7200_LONG_TRAINING; break; case 9600: ind = (s->short_train) ? T38_IND_V17_9600_SHORT_TRAINING : T38_IND_V17_9600_LONG_TRAINING; break; case 12000: ind = (s->short_train) ? T38_IND_V17_12000_SHORT_TRAINING : T38_IND_V17_12000_LONG_TRAINING; break; case 14400: default: ind = (s->short_train) ? T38_IND_V17_14400_SHORT_TRAINING : T38_IND_V17_14400_LONG_TRAINING; break; } t38_core_send_indicator(&s->t38, ind, INDICATOR_TX_COUNT); } else { v17_tx_restart(&(s->v17tx), s->bit_rate, FALSE, s->short_train); s->tx_handler = (span_tx_handler_t *) &v17_tx; s->tx_user_data = &(s->v17tx); s->next_tx_handler = NULL; } s->tx_out_bytes = 0; s->tx_data_started = FALSE; s->at_state.transmit = TRUE; break; case T31_V17_RX: if (!s->t38_mode) { s->rx_handler = (span_rx_handler_t *) &early_v17_rx; s->rx_user_data = s; v17_rx_restart(&(s->v17rx), s->bit_rate, s->short_train); /* Allow for +FCERROR/+FRH:3 */ t31_v21_rx(s); } s->at_state.transmit = FALSE; break; #endif case T31_V27TER_TX: if (s->t38_mode) { switch (s->bit_rate) { case 2400: ind = T38_IND_V27TER_2400_TRAINING; break; case 4800: default: ind = T38_IND_V27TER_4800_TRAINING; break; } t38_core_send_indicator(&s->t38, ind, INDICATOR_TX_COUNT); } else { v27ter_tx_restart(&(s->v27ter_tx), s->bit_rate, FALSE); s->tx_handler = (span_tx_handler_t *) &v27ter_tx; s->tx_user_data = &(s->v27ter_tx); s->next_tx_handler = NULL; } s->tx_out_bytes = 0; s->tx_data_started = FALSE; s->at_state.transmit = TRUE; break; case T31_V27TER_RX: if (!s->t38_mode) { s->rx_handler = (span_rx_handler_t *) &early_v27ter_rx; s->rx_user_data = s; v27ter_rx_restart(&(s->v27ter_rx), s->bit_rate, FALSE); /* Allow for +FCERROR/+FRH:3 */ t31_v21_rx(s); } s->at_state.transmit = FALSE; break; case T31_V29_TX: if (s->t38_mode) { switch (s->bit_rate) { case 7200: ind = T38_IND_V29_7200_TRAINING; break; case 9600: default: ind = T38_IND_V29_9600_TRAINING; break; } t38_core_send_indicator(&s->t38, ind, INDICATOR_TX_COUNT); } else { v29_tx_restart(&(s->v29tx), s->bit_rate, FALSE); s->tx_handler = (span_tx_handler_t *) &v29_tx; s->tx_user_data = &(s->v29tx); s->next_tx_handler = NULL; } s->tx_out_bytes = 0; s->tx_data_started = FALSE; s->at_state.transmit = TRUE; break; case T31_V29_RX: if (!s->t38_mode) { s->rx_handler = (span_rx_handler_t *) &early_v29_rx; s->rx_user_data = s; v29_rx_restart(&(s->v29rx), s->bit_rate, FALSE); /* Allow for +FCERROR/+FRH:3 */ t31_v21_rx(s); } s->at_state.transmit = FALSE; break; case T31_SILENCE_TX: if (s->t38_mode) { t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, INDICATOR_TX_COUNT); } else { silence_gen_set(&(s->silence_gen), 0); s->tx_handler = (span_tx_handler_t *) &silence_gen; s->tx_user_data = &(s->silence_gen); s->next_tx_handler = NULL; } s->at_state.transmit = FALSE; break; case T31_SILENCE_RX: if (!s->t38_mode) { s->rx_handler = (span_rx_handler_t *) &silence_rx; s->rx_user_data = s; silence_gen_set(&(s->silence_gen), 0); s->tx_handler = (span_tx_handler_t *) &silence_gen; s->tx_user_data = &(s->silence_gen); s->next_tx_handler = NULL; } s->at_state.transmit = FALSE; break; case T31_FLUSH: /* Send 200ms of silence to "push" the last audio out */ if (s->t38_mode) { t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, INDICATOR_TX_COUNT); } else { s->modem = T31_SILENCE_TX; silence_gen_alter(&(s->silence_gen), ms_to_samples(200)); s->tx_handler = (span_tx_handler_t *) &silence_gen; s->tx_user_data = &(s->silence_gen); s->next_tx_handler = NULL; s->at_state.transmit = TRUE; } break; } s->bit_no = 0; s->current_byte = 0xFF; s->tx_in_bytes = 0; return 0; } /*- End of function --------------------------------------------------------*/ static __inline__ void dle_unstuff_hdlc(t31_state_t *s, const char *stuffed, int len) { int i; for (i = 0; i < len; i++) { if (s->dled) { s->dled = FALSE; if (stuffed[i] == ETX) { if (s->t38_mode) { } else { hdlc_tx_frame(&(s->hdlctx), s->hdlc_tx_buf, s->hdlc_tx_len); } s->hdlc_final = (s->hdlc_tx_buf[1] & 0x10); s->hdlc_tx_len = 0; } else if (stuffed[i] == SUB) { s->hdlc_tx_buf[s->hdlc_tx_len++] = DLE; s->hdlc_tx_buf[s->hdlc_tx_len++] = DLE; } else { s->hdlc_tx_buf[s->hdlc_tx_len++] = stuffed[i]; } } else { if (stuffed[i] == DLE) s->dled = TRUE; else s->hdlc_tx_buf[s->hdlc_tx_len++] = stuffed[i]; } } } /*- End of function --------------------------------------------------------*/ static __inline__ void dle_unstuff(t31_state_t *s, const char *stuffed, int len) { int i; int fill; int next; for (i = 0; i < len; i++) { if (s->dled) { s->dled = FALSE; if (stuffed[i] == ETX) { s->data_final = TRUE; t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND); return; } } else if (stuffed[i] == DLE) { s->dled = TRUE; continue; } s->tx_data[s->tx_in_bytes] = stuffed[i]; next = (s->tx_in_bytes + 1) & (T31_TX_BUF_LEN - 1); if (next == s->tx_out_bytes) { /* Oops. We hit the end of the buffer. Give up. Loose stuff. :-( */ return; } s->tx_in_bytes = next; } if (!s->tx_holding) { /* See if the buffer is approaching full. We might need to apply flow control. */ fill = (s->tx_in_bytes - s->tx_out_bytes); if (s->tx_in_bytes < s->tx_out_bytes) fill += (T31_TX_BUF_LEN + 1); if (fill > T31_TX_BUF_HIGH_TIDE) { s->tx_holding = TRUE; /* Tell the application to hold further data */ at_modem_control(&s->at_state, AT_MODEM_CONTROL_CTS, (void *) 0); } } } /*- End of function --------------------------------------------------------*/ static int process_class1_cmd(at_state_t *t, void *user_data, int direction, int operation, int val) { int new_modem; int new_transmit; int i; int len; int immediate_response; t31_state_t *s; uint8_t msg[256]; s = (t31_state_t *) user_data; new_transmit = direction; immediate_response = TRUE; switch (operation) { case 'S': s->at_state.transmit = new_transmit; if (new_transmit) { /* Send a specified period of silence, to space transmissions. */ restart_modem(s, T31_SILENCE_TX); silence_gen_alter(&(s->silence_gen), val*80); s->at_state.transmit = TRUE; } else { /* Wait until we have received a specified period of silence. */ queue_flush(&(s->rx_queue)); s->silence_awaited = val*80; t31_set_at_rx_mode(s, AT_MODE_DELIVERY); restart_modem(s, T31_SILENCE_RX); } immediate_response = FALSE; span_log(&s->logging, SPAN_LOG_FLOW, "Silence %dms\n", val*10); break; case 'H': switch (val) { case 3: new_modem = (new_transmit) ? T31_V21_TX : T31_V21_RX; s->short_train = FALSE; s->bit_rate = 300; break; default: return -1; } span_log(&s->logging, SPAN_LOG_FLOW, "HDLC\n"); if (new_modem != s->modem) { restart_modem(s, new_modem); immediate_response = FALSE; } s->at_state.transmit = new_transmit; if (new_transmit) { t31_set_at_rx_mode(s, AT_MODE_HDLC); at_put_response_code(&s->at_state, AT_RESPONSE_CODE_CONNECT); } else { /* Send straight away, if there is something queued. */ t31_set_at_rx_mode(s, AT_MODE_DELIVERY); s->rx_message_received = FALSE; do { if (!queue_empty(&(s->rx_queue))) { len = queue_read_msg(&(s->rx_queue), msg, 256); if (len > 1) { if (msg[0] == AT_RESPONSE_CODE_OK) at_put_response_code(&s->at_state, AT_RESPONSE_CODE_CONNECT); for (i = 1; i < len; i++) { if (msg[i] == DLE) s->at_state.rx_data[s->at_state.rx_data_bytes++] = DLE; s->at_state.rx_data[s->at_state.rx_data_bytes++] = msg[i]; } s->at_state.rx_data[s->at_state.rx_data_bytes++] = DLE; s->at_state.rx_data[s->at_state.rx_data_bytes++] = ETX; s->at_state.at_tx_handler(&s->at_state, s->at_state.at_tx_user_data, s->at_state.rx_data, s->at_state.rx_data_bytes); s->at_state.rx_data_bytes = 0; } at_put_response_code(&s->at_state, msg[0]); } else { s->at_state.dte_is_waiting = TRUE; break; } } while (msg[0] == AT_RESPONSE_CODE_CONNECT); } immediate_response = FALSE; break; default: switch (val) { case 24: new_modem = (new_transmit) ? T31_V27TER_TX : T31_V27TER_RX; s->short_train = FALSE; s->bit_rate = 2400; break; case 48: new_modem = (new_transmit) ? T31_V27TER_TX : T31_V27TER_RX; s->short_train = FALSE; s->bit_rate = 4800; break; case 72: new_modem = (new_transmit) ? T31_V29_TX : T31_V29_RX; s->short_train = FALSE; s->bit_rate = 7200; break; case 96: new_modem = (new_transmit) ? T31_V29_TX : T31_V29_RX; s->short_train = FALSE; s->bit_rate = 9600; break; #if defined(ENABLE_V17) case 73: new_modem = (new_transmit) ? T31_V17_TX : T31_V17_RX; s->short_train = FALSE; s->bit_rate = 7200; break; case 74: new_modem = (new_transmit) ? T31_V17_TX : T31_V17_RX; s->short_train = TRUE; s->bit_rate = 7200; break; case 97: new_modem = (new_transmit) ? T31_V17_TX : T31_V17_RX; s->short_train = FALSE; s->bit_rate = 9600; break; case 98: new_modem = (new_transmit) ? T31_V17_TX : T31_V17_RX; s->short_train = TRUE; s->bit_rate = 9600; break; case 121: new_modem = (new_transmit) ? T31_V17_TX : T31_V17_RX; s->short_train = FALSE; s->bit_rate = 12000; break; case 122: new_modem = (new_transmit) ? T31_V17_TX : T31_V17_RX; s->short_train = TRUE; s->bit_rate = 12000; break; case 145: new_modem = (new_transmit) ? T31_V17_TX : T31_V17_RX; s->short_train = FALSE; s->bit_rate = 14400; break; case 146: new_modem = (new_transmit) ? T31_V17_TX : T31_V17_RX; s->short_train = TRUE; s->bit_rate = 14400; break; #endif default: return -1; } span_log(&s->logging, SPAN_LOG_FLOW, "Short training = %d, bit rate = %d\n", s->short_train, s->bit_rate); if (new_transmit) { t31_set_at_rx_mode(s, AT_MODE_STUFFED); at_put_response_code(&s->at_state, AT_RESPONSE_CODE_CONNECT); } else { t31_set_at_rx_mode(s, AT_MODE_DELIVERY); } restart_modem(s, new_modem); immediate_response = FALSE; break; } return immediate_response; } /*- End of function --------------------------------------------------------*/ void t31_call_event(t31_state_t *s, int event) { span_log(&s->logging, SPAN_LOG_FLOW, "Call event %d received\n", event); at_call_event(&s->at_state, event); } /*- End of function --------------------------------------------------------*/ int t31_at_rx(t31_state_t *s, const char *t, int len) { if (s->dte_data_timeout) s->dte_data_timeout = s->call_samples + ms_to_samples(5000); switch (s->at_state.at_rx_mode) { case AT_MODE_ONHOOK_COMMAND: case AT_MODE_OFFHOOK_COMMAND: at_interpreter(&s->at_state, t, len); break; case AT_MODE_DELIVERY: /* Data from the DTE in this state returns us to command mode */ if (len) { s->at_state.rx_data_bytes = 0; s->at_state.transmit = FALSE; s->modem = T31_SILENCE_TX; t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND); at_put_response_code(&s->at_state, AT_RESPONSE_CODE_OK); } break; case AT_MODE_HDLC: dle_unstuff_hdlc(s, t, len); break; case AT_MODE_STUFFED: dle_unstuff(s, t, len); break; } return len; } /*- End of function --------------------------------------------------------*/ static int dummy_rx(void *user_data, const int16_t amp[], int len) { return 0; } /*- End of function --------------------------------------------------------*/ static int silence_rx(void *user_data, const int16_t amp[], int len) { t31_state_t *s; /* Searching for a specified minimum period of silence. */ s = (t31_state_t *) user_data; if (s->silence_awaited && s->silence_heard >= s->silence_awaited) { at_put_response_code(&s->at_state, AT_RESPONSE_CODE_OK); t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND); s->silence_heard = 0; s->silence_awaited = 0; } return 0; } /*- End of function --------------------------------------------------------*/ static int cng_rx(void *user_data, const int16_t amp[], int len) { t31_state_t *s; s = (t31_state_t *) user_data; if (s->call_samples > ms_to_samples(s->at_state.p.s_regs[7]*1000)) { /* After calling, S7 has elapsed... no carrier found. */ at_put_response_code(&s->at_state, AT_RESPONSE_CODE_NO_CARRIER); restart_modem(s, T31_SILENCE_TX); at_modem_control(&s->at_state, AT_MODEM_CONTROL_HANGUP, NULL); t31_set_at_rx_mode(s, AT_MODE_ONHOOK_COMMAND); } else { fsk_rx(&(s->v21rx), amp, len); } return 0; } /*- End of function --------------------------------------------------------*/ #if defined(ENABLE_V17) static int early_v17_rx(void *user_data, const int16_t amp[], int len) { t31_state_t *s; s = (t31_state_t *) user_data; v17_rx(&(s->v17rx), amp, len); if (s->at_state.rx_trained) { /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&(s->v17rx))); s->rx_handler = (span_rx_handler_t *) &v17_rx; s->rx_user_data = &(s->v17rx); } else { fsk_rx(&(s->v21rx), amp, len); if (s->rx_message_received) { /* We have received something, and the fast modem has not trained. We must be receiving valid V.21 */ span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.21\n"); s->rx_handler = (span_rx_handler_t *) &fsk_rx; s->rx_user_data = &(s->v21rx); } } return len; } /*- End of function --------------------------------------------------------*/ #endif static int early_v27ter_rx(void *user_data, const int16_t amp[], int len) { t31_state_t *s; s = (t31_state_t *) user_data; v27ter_rx(&(s->v27ter_rx), amp, len); if (s->at_state.rx_trained) { /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&(s->v27ter_rx))); s->rx_handler = (span_rx_handler_t *) &v27ter_rx; s->rx_user_data = &(s->v27ter_rx); } else { fsk_rx(&(s->v21rx), amp, len); if (s->rx_message_received) { /* We have received something, and the fast modem has not trained. We must be receiving valid V.21 */ span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.21\n"); s->rx_handler = (span_rx_handler_t *) &fsk_rx; s->rx_user_data = &(s->v21rx); } } return len; } /*- End of function --------------------------------------------------------*/ static int early_v29_rx(void *user_data, const int16_t amp[], int len) { t31_state_t *s; s = (t31_state_t *) user_data; v29_rx(&(s->v29rx), amp, len); if (s->at_state.rx_trained) { /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&(s->v29rx))); s->rx_handler = (span_rx_handler_t *) &v29_rx; s->rx_user_data = &(s->v29rx); } else { fsk_rx(&(s->v21rx), amp, len); if (s->rx_message_received) { /* We have received something, and the fast modem has not trained. We must be receiving valid V.21 */ span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.21\n"); s->rx_handler = (span_rx_handler_t *) &fsk_rx; s->rx_user_data = &(s->v21rx); } } return len; } /*- End of function --------------------------------------------------------*/ int t31_rx(t31_state_t *s, int16_t amp[], int len) { int i; int32_t power; /* Monitor for received silence. Maximum needed detection is AT+FRS=255 (255*10ms). */ /* We could probably only run this loop if (s->modem == T31_SILENCE_RX), however, the spec says "when silence has been present on the line for the amount of time specified". That means some of the silence may have occurred before the AT+FRS=n command. This condition, however, is not likely to ever be the case. (AT+FRS=n will usually be issued before the remote goes silent.) */ for (i = 0; i < len; i++) { /* Clean up any DC influence. */ power = power_meter_update(&(s->rx_power), amp[i] - s->last_sample); s->last_sample = amp[i]; if (power > s->silence_threshold_power) { s->silence_heard = 0; } else { if (s->silence_heard <= ms_to_samples(255*10)) s->silence_heard++; } } /* Time is determined by counting the samples in audio packets coming in. */ s->call_samples += len; /* In HDLC transmit mode, if 5 seconds elapse without data from the DTE we must treat this as an error. We return the result ERROR, and change to command-mode. */ if (s->dte_data_timeout && s->call_samples > s->dte_data_timeout) { t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND); at_put_response_code(&s->at_state, AT_RESPONSE_CODE_ERROR); restart_modem(s, T31_SILENCE_TX); } if (!s->at_state.transmit || s->modem == T31_CNG_TONE) s->rx_handler(s->rx_user_data, amp, len); return 0; } /*- End of function --------------------------------------------------------*/ static int set_next_tx_type(t31_state_t *s) { if (s->next_tx_handler) { s->tx_handler = s->next_tx_handler; s->tx_user_data = s->next_tx_user_data; s->next_tx_handler = NULL; return 0; } /* If there is nothing else to change to, so use zero length silence */ silence_gen_alter(&(s->silence_gen), 0); s->tx_handler = (span_tx_handler_t *) &silence_gen; s->tx_user_data = &(s->silence_gen); s->next_tx_handler = NULL; return -1; } /*- End of function --------------------------------------------------------*/ int t31_tx(t31_state_t *s, int16_t amp[], int max_len) { int len; len = 0; if (s->at_state.transmit) { if ((len = s->tx_handler(s->tx_user_data, amp, max_len)) < max_len) { /* Allow for one change of tx handler within a block */ set_next_tx_type(s); if ((len += s->tx_handler(s->tx_user_data, amp + len, max_len - len)) < max_len) { switch (s->modem) { case T31_SILENCE_TX: s->modem = -1; at_put_response_code(&s->at_state, AT_RESPONSE_CODE_OK); if (s->at_state.do_hangup) { at_modem_control(&s->at_state, AT_MODEM_CONTROL_HANGUP, NULL); t31_set_at_rx_mode(s, AT_MODE_ONHOOK_COMMAND); s->at_state.do_hangup = FALSE; } else { t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND); } break; case T31_CED_TONE: /* Go directly to V.21/HDLC transmit. */ s->modem = -1; restart_modem(s, T31_V21_TX); t31_set_at_rx_mode(s, AT_MODE_HDLC); break; case T31_V21_TX: #if defined(ENABLE_V17) case T31_V17_TX: #endif case T31_V27TER_TX: case T31_V29_TX: s->modem = -1; at_put_response_code(&s->at_state, AT_RESPONSE_CODE_OK); t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND); restart_modem(s, T31_SILENCE_TX); break; } } } } if (s->transmit_on_idle) { /* Pad to the requested length with silence */ memset(amp, 0, max_len*sizeof(int16_t)); len = max_len; } return len; } /*- End of function --------------------------------------------------------*/ void t31_set_transmit_on_idle(t31_state_t *s, int transmit_on_idle) { s->transmit_on_idle = transmit_on_idle; } /*- End of function --------------------------------------------------------*/ t31_state_t *t31_init(t31_state_t *s, at_tx_handler_t *at_tx_handler, void *at_tx_user_data, t31_modem_control_handler_t *modem_control_handler, void *modem_control_user_data, t38_tx_packet_handler_t *tx_t38_packet_handler, void *tx_t38_packet_user_data) { if (at_tx_handler == NULL || modem_control_handler == NULL) return NULL; memset(s, 0, sizeof(*s)); span_log_init(&s->logging, SPAN_LOG_NONE, NULL); span_log_set_protocol(&s->logging, "T.31"); s->modem_control_handler = modem_control_handler; s->modem_control_user_data = modem_control_user_data; #if defined(ENABLE_V17) v17_rx_init(&(s->v17rx), 14400, non_ecm_put_bit, s); v17_tx_init(&(s->v17tx), 14400, FALSE, non_ecm_get_bit, s); #endif v29_rx_init(&(s->v29rx), 9600, non_ecm_put_bit, s); v29_rx_signal_cutoff(&(s->v29rx), -45.5); v29_tx_init(&(s->v29tx), 9600, FALSE, non_ecm_get_bit, s); v27ter_rx_init(&(s->v27ter_rx), 4800, non_ecm_put_bit, s); v27ter_tx_init(&(s->v27ter_tx), 4800, FALSE, non_ecm_get_bit, s); silence_gen_init(&(s->silence_gen), 0); power_meter_init(&(s->rx_power), 4); s->last_sample = 0; s->silence_threshold_power = power_meter_level_dbm0(-43); s->at_state.rx_signal_present = FALSE; s->at_state.rx_trained = FALSE; s->at_state.do_hangup = FALSE; s->at_state.line_ptr = 0; s->silence_heard = 0; s->silence_awaited = 0; s->call_samples = 0; s->modem = -1; s->at_state.transmit = TRUE; s->rx_handler = dummy_rx; s->rx_user_data = NULL; s->tx_handler = (span_tx_handler_t *) &silence_gen; s->tx_user_data = &(s->silence_gen); if (queue_create(&(s->rx_queue), 4096, QUEUE_WRITE_ATOMIC | QUEUE_READ_ATOMIC) < 0) return NULL; at_init(&s->at_state, at_tx_handler, at_tx_user_data, t31_modem_control_handler, s); at_set_class1_handler(&s->at_state, process_class1_cmd, s); s->at_state.dte_inactivity_timeout = DEFAULT_DTE_TIMEOUT; if (tx_t38_packet_handler) { t38_core_init(&s->t38, process_rx_indicator, process_rx_data, process_rx_missing, (void *) s); s->t38.tx_packet_handler = tx_t38_packet_handler; s->t38.tx_packet_user_data = tx_t38_packet_user_data; } s->t38_mode = FALSE; return s; } /*- End of function --------------------------------------------------------*/ int t31_release(t31_state_t *s) { at_reset_call_info(&s->at_state); free(s); return 0; } /*- End of function --------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/