T.38 now gets reset as a T.31 call starts

This commit is contained in:
Steve Underwood 2013-01-12 16:21:42 +08:00
parent 29bfcb16be
commit ef22570afa
2 changed files with 55 additions and 52 deletions

View File

@ -116,11 +116,11 @@ typedef struct
int octets_per_data_packet; int octets_per_data_packet;
/*! \brief An HDLC context used when sending HDLC messages to the terminal port /*! \brief An HDLC context used when sending HDLC messages to the terminal port
(ECM mode support). */ as if it were non-ECM data (ECM mode support). */
hdlc_tx_state_t hdlc_tx_term; hdlc_tx_state_t hdlc_tx_non_ecm;
/*! \brief An HDLC context used when receiving HDLC messages from the terminal port. /*! \brief An HDLC context used when receiving HDLC messages from the terminal port.
(ECM mode support). */ as if it were non-ECM data (ECM mode support). */
hdlc_rx_state_t hdlc_rx_term; hdlc_rx_state_t hdlc_rx_non_ecm;
struct struct
{ {
@ -196,7 +196,7 @@ struct t31_state_s
struct struct
{ {
/*! \brief The transmit buffer. */ /*! \brief The transmit buffer. */
uint8_t data[T31_TX_BUF_LEN]; uint8_t buf[T31_TX_BUF_LEN];
/*! \brief The number of bytes stored in the transmit buffer. */ /*! \brief The number of bytes stored in the transmit buffer. */
int in_bytes; int in_bytes;
/*! \brief The number of bytes sent from the transmit buffer. */ /*! \brief The number of bytes sent from the transmit buffer. */

View File

@ -184,8 +184,8 @@ enum
static int restart_modem(t31_state_t *s, int new_modem); static int restart_modem(t31_state_t *s, int new_modem);
static void hdlc_accept_frame(void *user_data, const uint8_t *msg, int len, int ok); static void hdlc_accept_frame(void *user_data, const uint8_t *msg, int len, int ok);
static void hdlc_accept_frame2(void *user_data, const uint8_t *msg, int len, int ok); static void hdlc_accept_t38_frame(void *user_data, const uint8_t *msg, int len, int ok);
static void hdlc_accept_frame3(void *user_data, const uint8_t *msg, int len, int ok); static void hdlc_accept_non_ecm_frame(void *user_data, const uint8_t *msg, int len, int ok);
static int silence_rx(void *user_data, 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 int cng_rx(void *user_data, const int16_t amp[], int len);
static void non_ecm_put_bit(void *user_data, int bit); static void non_ecm_put_bit(void *user_data, int bit);
@ -501,7 +501,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
} }
else else
{ {
hdlc_accept_frame2(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, !fe->rx_data_missing); hdlc_accept_t38_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, !fe->rx_data_missing);
} }
/*endif*/ /*endif*/
} }
@ -527,7 +527,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
if (data_type == T38_DATA_V21) if (data_type == T38_DATA_V21)
hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, FALSE); hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, FALSE);
else else
hdlc_accept_frame2(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, FALSE); hdlc_accept_t38_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, FALSE);
/*endif*/ /*endif*/
} }
/*endif*/ /*endif*/
@ -572,7 +572,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
} }
else else
{ {
hdlc_accept_frame2(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, !fe->rx_data_missing); hdlc_accept_t38_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, !fe->rx_data_missing);
non_ecm_rx_status(s, SIG_STATUS_CARRIER_DOWN); non_ecm_rx_status(s, SIG_STATUS_CARRIER_DOWN);
} }
/*endif*/ /*endif*/
@ -603,7 +603,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
} }
else else
{ {
hdlc_accept_frame2(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, FALSE); hdlc_accept_t38_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, FALSE);
non_ecm_rx_status(s, SIG_STATUS_CARRIER_DOWN); non_ecm_rx_status(s, SIG_STATUS_CARRIER_DOWN);
} }
/*endif*/ /*endif*/
@ -1340,9 +1340,11 @@ static int t31_modem_control_handler(at_state_t *s, void *user_data, int op, con
{ {
case AT_MODEM_CONTROL_CALL: case AT_MODEM_CONTROL_CALL:
t->call_samples = 0; t->call_samples = 0;
t38_core_restart(&t->t38_fe.t38);
break; break;
case AT_MODEM_CONTROL_ANSWER: case AT_MODEM_CONTROL_ANSWER:
t->call_samples = 0; t->call_samples = 0;
t38_core_restart(&t->t38_fe.t38);
break; break;
case AT_MODEM_CONTROL_ONHOOK: case AT_MODEM_CONTROL_ONHOOK:
if (t->non_ecm_tx.holding) if (t->non_ecm_tx.holding)
@ -1511,7 +1513,7 @@ static int non_ecm_get_bit(void *user_data)
if (s->non_ecm_tx.out_bytes != s->non_ecm_tx.in_bytes) if (s->non_ecm_tx.out_bytes != s->non_ecm_tx.in_bytes)
{ {
/* There is real data available to send */ /* There is real data available to send */
s->audio.current_byte = s->non_ecm_tx.data[s->non_ecm_tx.out_bytes++]; s->audio.current_byte = s->non_ecm_tx.buf[s->non_ecm_tx.out_bytes++];
if (s->non_ecm_tx.out_bytes > T31_TX_BUF_LEN - 1) if (s->non_ecm_tx.out_bytes > T31_TX_BUF_LEN - 1)
{ {
s->non_ecm_tx.out_bytes = T31_TX_BUF_LEN - 1; s->non_ecm_tx.out_bytes = T31_TX_BUF_LEN - 1;
@ -1569,7 +1571,7 @@ static int non_ecm_get(void *user_data, uint8_t buf[], int len)
if (s->non_ecm_tx.out_bytes != s->non_ecm_tx.in_bytes) if (s->non_ecm_tx.out_bytes != s->non_ecm_tx.in_bytes)
{ {
/* There is real data available to send */ /* There is real data available to send */
buf[i] = s->non_ecm_tx.data[s->non_ecm_tx.out_bytes++]; buf[i] = s->non_ecm_tx.buf[s->non_ecm_tx.out_bytes++];
if (s->non_ecm_tx.out_bytes > T31_TX_BUF_LEN - 1) if (s->non_ecm_tx.out_bytes > T31_TX_BUF_LEN - 1)
{ {
s->non_ecm_tx.out_bytes = T31_TX_BUF_LEN - 1; s->non_ecm_tx.out_bytes = T31_TX_BUF_LEN - 1;
@ -1865,7 +1867,7 @@ static void hdlc_accept_frame(void *user_data, const uint8_t *msg, int len, int
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
static void hdlc_accept_frame2(void *user_data, const uint8_t *msg, int len, int ok) static void hdlc_accept_t38_frame(void *user_data, const uint8_t *msg, int len, int ok)
{ {
t31_state_t *s; t31_state_t *s;
int i; int i;
@ -1880,7 +1882,8 @@ static void hdlc_accept_frame2(void *user_data, const uint8_t *msg, int len, int
uint8_t buf2[2*len + 20]; uint8_t buf2[2*len + 20];
#endif #endif
/* Accept an ECM image mode HDLC frame received as T.38 */ /* Accept an ECM image mode HDLC frame, received as T.38, and convert to an HDLC
bit stream to be fed to the FAX software. */
if (len < 0) if (len < 0)
return; return;
/*endif*/ /*endif*/
@ -1892,33 +1895,33 @@ static void hdlc_accept_frame2(void *user_data, const uint8_t *msg, int len, int
crc ^= 0xFFFF; crc ^= 0xFFFF;
/*endif*/ /*endif*/
ptr = 0; ptr = 0;
buf2[ptr++] = s->t38_fe.hdlc_tx_term.idle_octet; buf2[ptr++] = s->t38_fe.hdlc_tx_non_ecm.idle_octet;
buf2[ptr++] = s->t38_fe.hdlc_tx_term.idle_octet; buf2[ptr++] = s->t38_fe.hdlc_tx_non_ecm.idle_octet;
for (pos = 0; pos < len; pos++) for (pos = 0; pos < len; pos++)
{ {
byte_in_progress = msg[pos]; byte_in_progress = msg[pos];
i = bottom_bit(byte_in_progress | 0x100); i = bottom_bit(byte_in_progress | 0x100);
s->t38_fe.hdlc_tx_term.octets_in_progress <<= i; s->t38_fe.hdlc_tx_non_ecm.octets_in_progress <<= i;
byte_in_progress >>= i; byte_in_progress >>= i;
for ( ; i < 8; i++) for ( ; i < 8; i++)
{ {
s->t38_fe.hdlc_tx_term.octets_in_progress = (s->t38_fe.hdlc_tx_term.octets_in_progress << 1) | (byte_in_progress & 0x01); s->t38_fe.hdlc_tx_non_ecm.octets_in_progress = (s->t38_fe.hdlc_tx_non_ecm.octets_in_progress << 1) | (byte_in_progress & 0x01);
byte_in_progress >>= 1; byte_in_progress >>= 1;
if ((s->t38_fe.hdlc_tx_term.octets_in_progress & 0x1F) == 0x1F) if ((s->t38_fe.hdlc_tx_non_ecm.octets_in_progress & 0x1F) == 0x1F)
{ {
/* There are 5 ones - stuff */ /* There are 5 ones - stuff */
s->t38_fe.hdlc_tx_term.octets_in_progress <<= 1; s->t38_fe.hdlc_tx_non_ecm.octets_in_progress <<= 1;
s->t38_fe.hdlc_tx_term.num_bits++; s->t38_fe.hdlc_tx_non_ecm.num_bits++;
} }
/*endif*/ /*endif*/
} }
/*endfor*/ /*endfor*/
/* An input byte will generate between 8 and 10 output bits */ /* An input byte will generate between 8 and 10 output bits */
buf2[ptr++] = (s->t38_fe.hdlc_tx_term.octets_in_progress >> s->t38_fe.hdlc_tx_term.num_bits) & 0xFF; buf2[ptr++] = (s->t38_fe.hdlc_tx_non_ecm.octets_in_progress >> s->t38_fe.hdlc_tx_non_ecm.num_bits) & 0xFF;
if (s->t38_fe.hdlc_tx_term.num_bits >= 8) if (s->t38_fe.hdlc_tx_non_ecm.num_bits >= 8)
{ {
s->t38_fe.hdlc_tx_term.num_bits -= 8; s->t38_fe.hdlc_tx_non_ecm.num_bits -= 8;
buf2[ptr++] = (s->t38_fe.hdlc_tx_term.octets_in_progress >> s->t38_fe.hdlc_tx_term.num_bits) & 0xFF; buf2[ptr++] = (s->t38_fe.hdlc_tx_non_ecm.octets_in_progress >> s->t38_fe.hdlc_tx_non_ecm.num_bits) & 0xFF;
} }
/*endif*/ /*endif*/
} }
@ -1929,27 +1932,27 @@ static void hdlc_accept_frame2(void *user_data, const uint8_t *msg, int len, int
byte_in_progress = crc & 0xFF; byte_in_progress = crc & 0xFF;
crc >>= 8; crc >>= 8;
i = bottom_bit(byte_in_progress | 0x100); i = bottom_bit(byte_in_progress | 0x100);
s->t38_fe.hdlc_tx_term.octets_in_progress <<= i; s->t38_fe.hdlc_tx_non_ecm.octets_in_progress <<= i;
byte_in_progress >>= i; byte_in_progress >>= i;
for ( ; i < 8; i++) for ( ; i < 8; i++)
{ {
s->t38_fe.hdlc_tx_term.octets_in_progress = (s->t38_fe.hdlc_tx_term.octets_in_progress << 1) | (byte_in_progress & 0x01); s->t38_fe.hdlc_tx_non_ecm.octets_in_progress = (s->t38_fe.hdlc_tx_non_ecm.octets_in_progress << 1) | (byte_in_progress & 0x01);
byte_in_progress >>= 1; byte_in_progress >>= 1;
if ((s->t38_fe.hdlc_tx_term.octets_in_progress & 0x1F) == 0x1F) if ((s->t38_fe.hdlc_tx_non_ecm.octets_in_progress & 0x1F) == 0x1F)
{ {
/* There are 5 ones - stuff */ /* There are 5 ones - stuff */
s->t38_fe.hdlc_tx_term.octets_in_progress <<= 1; s->t38_fe.hdlc_tx_non_ecm.octets_in_progress <<= 1;
s->t38_fe.hdlc_tx_term.num_bits++; s->t38_fe.hdlc_tx_non_ecm.num_bits++;
} }
/*endif*/ /*endif*/
} }
/*endfor*/ /*endfor*/
/* An input byte will generate between 8 and 10 output bits */ /* An input byte will generate between 8 and 10 output bits */
buf2[ptr++] = (s->t38_fe.hdlc_tx_term.octets_in_progress >> s->t38_fe.hdlc_tx_term.num_bits) & 0xFF; buf2[ptr++] = (s->t38_fe.hdlc_tx_non_ecm.octets_in_progress >> s->t38_fe.hdlc_tx_non_ecm.num_bits) & 0xFF;
if (s->t38_fe.hdlc_tx_term.num_bits >= 8) if (s->t38_fe.hdlc_tx_non_ecm.num_bits >= 8)
{ {
s->t38_fe.hdlc_tx_term.num_bits -= 8; s->t38_fe.hdlc_tx_non_ecm.num_bits -= 8;
buf2[ptr++] = (s->t38_fe.hdlc_tx_term.octets_in_progress >> s->t38_fe.hdlc_tx_term.num_bits) & 0xFF; buf2[ptr++] = (s->t38_fe.hdlc_tx_non_ecm.octets_in_progress >> s->t38_fe.hdlc_tx_non_ecm.num_bits) & 0xFF;
} }
/*endif*/ /*endif*/
} }
@ -1958,21 +1961,21 @@ static void hdlc_accept_frame2(void *user_data, const uint8_t *msg, int len, int
/* Finish off the current byte with some flag bits. If we are at the /* Finish off the current byte with some flag bits. If we are at the
start of a byte we need a at least one whole byte of flag to ensure start of a byte we need a at least one whole byte of flag to ensure
we cannot end up with back to back frames, and no flag octet at all */ we cannot end up with back to back frames, and no flag octet at all */
txbyte = (uint8_t) ((s->t38_fe.hdlc_tx_term.octets_in_progress << (8 - s->t38_fe.hdlc_tx_term.num_bits)) | (0x7E >> s->t38_fe.hdlc_tx_term.num_bits)); txbyte = (uint8_t) ((s->t38_fe.hdlc_tx_non_ecm.octets_in_progress << (8 - s->t38_fe.hdlc_tx_non_ecm.num_bits)) | (0x7E >> s->t38_fe.hdlc_tx_non_ecm.num_bits));
/* Create a rotated octet of flag for idling... */ /* Create a rotated octet of flag for idling... */
s->t38_fe.hdlc_tx_term.idle_octet = (0x7E7E >> s->t38_fe.hdlc_tx_term.num_bits) & 0xFF; s->t38_fe.hdlc_tx_non_ecm.idle_octet = (0x7E7E >> s->t38_fe.hdlc_tx_non_ecm.num_bits) & 0xFF;
/* ...and the partial flag octet needed to start off the next message. */ /* ...and the partial flag octet needed to start off the next message. */
s->t38_fe.hdlc_tx_term.octets_in_progress = s->t38_fe.hdlc_tx_term.idle_octet >> (8 - s->t38_fe.hdlc_tx_term.num_bits); s->t38_fe.hdlc_tx_non_ecm.octets_in_progress = s->t38_fe.hdlc_tx_non_ecm.idle_octet >> (8 - s->t38_fe.hdlc_tx_non_ecm.num_bits);
buf2[ptr++] = txbyte; buf2[ptr++] = txbyte;
buf2[ptr++] = s->t38_fe.hdlc_tx_term.idle_octet; buf2[ptr++] = s->t38_fe.hdlc_tx_non_ecm.idle_octet;
buf2[ptr++] = s->t38_fe.hdlc_tx_term.idle_octet; buf2[ptr++] = s->t38_fe.hdlc_tx_non_ecm.idle_octet;
bit_reverse(buf2, buf2, ptr); bit_reverse(buf2, buf2, ptr);
non_ecm_put(s, buf2, ptr); non_ecm_put(s, buf2, ptr);
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
static void hdlc_accept_frame3(void *user_data, const uint8_t *msg, int len, int ok) static void hdlc_accept_non_ecm_frame(void *user_data, const uint8_t *msg, int len, int ok)
{ {
t31_state_t *s; t31_state_t *s;
@ -2337,12 +2340,12 @@ static __inline__ void dle_unstuff_fake_hdlc(t31_state_t *s, const char *stuffed
} }
else if (s->at_state.p.double_escape && stuffed[i] == SUB) else if (s->at_state.p.double_escape && stuffed[i] == SUB)
{ {
hdlc_rx_put_byte(&s->t38_fe.hdlc_rx_term, bit_reverse8(DLE)); hdlc_rx_put_byte(&s->t38_fe.hdlc_rx_non_ecm, bit_reverse8(DLE));
hdlc_rx_put_byte(&s->t38_fe.hdlc_rx_term, bit_reverse8(DLE)); hdlc_rx_put_byte(&s->t38_fe.hdlc_rx_non_ecm, bit_reverse8(DLE));
} }
else else
{ {
hdlc_rx_put_byte(&s->t38_fe.hdlc_rx_term, bit_reverse8(stuffed[i])); hdlc_rx_put_byte(&s->t38_fe.hdlc_rx_non_ecm, bit_reverse8(stuffed[i]));
} }
/*endif*/ /*endif*/
} }
@ -2351,7 +2354,7 @@ static __inline__ void dle_unstuff_fake_hdlc(t31_state_t *s, const char *stuffed
if (stuffed[i] == DLE) if (stuffed[i] == DLE)
s->dled = TRUE; s->dled = TRUE;
else else
hdlc_rx_put_byte(&s->t38_fe.hdlc_rx_term, bit_reverse8(stuffed[i])); hdlc_rx_put_byte(&s->t38_fe.hdlc_rx_non_ecm, bit_reverse8(stuffed[i]));
/*endif*/ /*endif*/
} }
/*endif*/ /*endif*/
@ -2378,12 +2381,12 @@ static __inline__ void dle_unstuff(t31_state_t *s, const char *stuffed, int len)
/*endif*/ /*endif*/
if (s->at_state.p.double_escape && stuffed[i] == SUB) if (s->at_state.p.double_escape && stuffed[i] == SUB)
{ {
s->non_ecm_tx.data[s->non_ecm_tx.in_bytes++] = DLE; s->non_ecm_tx.buf[s->non_ecm_tx.in_bytes++] = DLE;
s->non_ecm_tx.data[s->non_ecm_tx.in_bytes++] = DLE; s->non_ecm_tx.buf[s->non_ecm_tx.in_bytes++] = DLE;
} }
else else
{ {
s->non_ecm_tx.data[s->non_ecm_tx.in_bytes++] = stuffed[i]; s->non_ecm_tx.buf[s->non_ecm_tx.in_bytes++] = stuffed[i];
} }
/*endif*/ /*endif*/
} }
@ -2392,7 +2395,7 @@ static __inline__ void dle_unstuff(t31_state_t *s, const char *stuffed, int len)
if (stuffed[i] == DLE) if (stuffed[i] == DLE)
s->dled = TRUE; s->dled = TRUE;
else else
s->non_ecm_tx.data[s->non_ecm_tx.in_bytes++] = stuffed[i]; s->non_ecm_tx.buf[s->non_ecm_tx.in_bytes++] = stuffed[i];
/*endif*/ /*endif*/
} }
/*endif*/ /*endif*/
@ -2703,7 +2706,7 @@ SPAN_DECLARE(int) t31_at_rx(t31_state_t *s, const char *t, int len)
{ {
/* Make room for new data in existing data buffer. */ /* Make room for new data in existing data buffer. */
s->non_ecm_tx.in_bytes -= s->non_ecm_tx.out_bytes; s->non_ecm_tx.in_bytes -= s->non_ecm_tx.out_bytes;
memmove(&s->non_ecm_tx.data[0], &s->non_ecm_tx.data[s->non_ecm_tx.out_bytes], s->non_ecm_tx.in_bytes); memmove(&s->non_ecm_tx.buf[0], &s->non_ecm_tx.buf[s->non_ecm_tx.out_bytes], s->non_ecm_tx.in_bytes);
s->non_ecm_tx.out_bytes = 0; s->non_ecm_tx.out_bytes = 0;
} }
/*endif*/ /*endif*/
@ -2975,8 +2978,8 @@ static int t31_t38_fe_init(t31_state_t *t,
t->hdlc_tx.ptr = 0; t->hdlc_tx.ptr = 0;
hdlc_tx_init(&s->hdlc_tx_term, FALSE, 1, FALSE, hdlc_tx_underflow2, s); hdlc_tx_init(&s->hdlc_tx_non_ecm, FALSE, 1, FALSE, hdlc_tx_underflow2, s);
hdlc_rx_init(&s->hdlc_rx_term, FALSE, TRUE, 2, hdlc_accept_frame3, t); hdlc_rx_init(&s->hdlc_rx_non_ecm, FALSE, TRUE, 2, hdlc_accept_non_ecm_frame, t);
return 0; return 0;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/