Chnaged T.30 x-rex, y-res, width vetting to be more rigorous.

Various little tweaks to spandsp
This commit is contained in:
Steve Underwood 2013-03-09 22:19:47 +08:00
parent 7a29ef9586
commit 1d289b3617
17 changed files with 498 additions and 319 deletions

View File

@ -84,7 +84,7 @@ Receiver now waits
Sender waits 250-300ms after end of 2300Hz tone
Send ACCT MT QXYZ GG CCC
Send ACCT MT QXYZ GG CCC S
ACCT = 4 digit account code (0-9, B-F)
MT = 2 digit message type (18 preferred, 98 optional)
@ -124,6 +124,74 @@ If kissoff doesn't start within 1.25s of the end of the DTMF, repeat the DTMF me
Receiver sends 750-1000ms of 1400Hz as the kissoff tone
Sender shall make 4 attempts before giving up. One successful kissoff resets the attempt counter
Ademco Express 4/1
ACCT MT C
ACCT = 4 digit account code (0-9, B-F)
MT = 2 digit message type (17)
C = alarm code
S = 1 digit hex checksum
Ademco Express 4/2
ACCT MT C Z S
ACCT = 4 digit account code (0-9, B-F)
MT = 2 digit message type (27)
C = 1 digit alarm code
Z = 1 digit zone or user number
S = 1 digit hex checksum
Ademco High speed
ACCT MT PPPPPPPP X S
ACCT = 4 digit account code (0-9, B-F)
MT = 2 digit message type (55)
PPPPPPPP = 8 digit status of each zone
X = 1 digit type of information in the PPPPPPPP field
S = 1 digit hex checksum
Each P digit contains one of the following values:
1 new alarm
2 new opening
3 new restore
4 new closing
5 normal
6 outstanding
The X field contains one of the following values:
0 AlarmNet messages
1 ambush or duress
2 opening by user (the first P field contains the user number)
3 bypass (the P fields indicate which zones are bypassed)
4 closing by user (the first P field contain the user number)
5 trouble (the P fields contain which zones are in trouble)
6 system trouble
7 normal message (the P fields indicate zone status)
8 low battery (the P fields indicate zone status)
9 test (the P fields indicate zone status)
Ademco Super fast
ACCT MT PPPPPPPP X S
ACCT = 4 digit account code (0-9, B-F)
MT = 2 digit message type (56)
There are versions somewhat like the above, with 8, 16 or 24 'P' digits,
and no message type
ACCT PPPPPPPP X
ACCT PPPPPPPPPPPPPPPP X
ACCT PPPPPPPPPPPPPPPPPPPPPPPP X
ACCT = 4 digit account code (0-9, B-F)
PPPPPPPP = 8, 16 or 24 digit status of each zone
X = 1 digit status of the communicator
S = 1 digit hex checksum
*/
struct ademco_code_s
@ -1040,7 +1108,7 @@ SPAN_DECLARE(ademco_contactid_sender_state_t *) ademco_contactid_sender_init(ade
s->step = 0;
s->remaining_samples = ms_to_samples(100);
dtmf_tx_init(&s->dtmf);
dtmf_tx_init(&s->dtmf, NULL, NULL);
/* The specified timing is 50-60ms on, 50-60ms off */
dtmf_tx_set_timing(&s->dtmf, 55, 55);
return s;

View File

@ -373,19 +373,19 @@ static void start_tx(adsi_tx_state_t *s)
switch (s->standard)
{
case ADSI_STANDARD_CLASS:
fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_BELL202], adsi_tx_get_bit, s);
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_BELL202], adsi_tx_get_bit, s);
break;
case ADSI_STANDARD_CLIP:
case ADSI_STANDARD_ACLIP:
case ADSI_STANDARD_JCLIP:
fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_V23CH1], adsi_tx_get_bit, s);
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_V23CH1], adsi_tx_get_bit, s);
break;
case ADSI_STANDARD_CLIP_DTMF:
dtmf_tx_init(&(s->dtmftx));
dtmf_tx_init(&s->dtmftx, NULL, NULL);
break;
case ADSI_STANDARD_TDD:
fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_WEITBRECHT], async_tx_get_bit, &(s->asynctx));
async_tx_init(&(s->asynctx), 5, ASYNC_PARITY_NONE, 2, FALSE, adsi_tdd_get_async_byte, s);
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_WEITBRECHT], async_tx_get_bit, &s->asynctx);
async_tx_init(&s->asynctx, 5, ASYNC_PARITY_NONE, 2, FALSE, adsi_tdd_get_async_byte, s);
/* Schedule an explicit shift at the start of baudot transmission */
s->baudot_shift = 2;
break;
@ -403,10 +403,10 @@ SPAN_DECLARE(int) adsi_rx(adsi_rx_state_t *s, const int16_t amp[], int len)
s->in_progress -= len;
if (s->in_progress <= 0)
s->msg_len = 0;
dtmf_rx(&(s->dtmfrx), amp, len);
dtmf_rx(&s->dtmfrx, amp, len);
break;
default:
fsk_rx(&(s->fskrx), amp, len);
fsk_rx(&s->fskrx, amp, len);
break;
}
return 0;
@ -435,20 +435,20 @@ SPAN_DECLARE(adsi_rx_state_t *) adsi_rx_init(adsi_rx_state_t *s,
switch (standard)
{
case ADSI_STANDARD_CLASS:
fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_BELL202], FSK_FRAME_MODE_ASYNC, adsi_rx_put_bit, s);
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_BELL202], FSK_FRAME_MODE_ASYNC, adsi_rx_put_bit, s);
break;
case ADSI_STANDARD_CLIP:
case ADSI_STANDARD_ACLIP:
case ADSI_STANDARD_JCLIP:
fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_V23CH1], FSK_FRAME_MODE_ASYNC, adsi_rx_put_bit, s);
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_V23CH1], FSK_FRAME_MODE_ASYNC, adsi_rx_put_bit, s);
break;
case ADSI_STANDARD_CLIP_DTMF:
dtmf_rx_init(&(s->dtmfrx), adsi_rx_dtmf, s);
dtmf_rx_init(&s->dtmfrx, adsi_rx_dtmf, s);
break;
case ADSI_STANDARD_TDD:
/* TDD uses 5 bit data, no parity and 1.5 stop bits. We scan for the first stop bit, and
ride over the fraction. */
fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_WEITBRECHT], FSK_FRAME_MODE_5N1_FRAMES, adsi_tdd_put_async_byte, s);
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_WEITBRECHT], FSK_FRAME_MODE_5N1_FRAMES, adsi_tdd_put_async_byte, s);
break;
}
s->standard = standard;
@ -475,19 +475,19 @@ SPAN_DECLARE(int) adsi_tx(adsi_tx_state_t *s, int16_t amp[], int max_len)
int len;
int lenx;
len = tone_gen(&(s->alert_tone_gen), amp, max_len);
len = tone_gen(&s->alert_tone_gen, amp, max_len);
if (s->tx_signal_on)
{
switch (s->standard)
{
case ADSI_STANDARD_CLIP_DTMF:
if (len < max_len)
len += dtmf_tx(&(s->dtmftx), amp, max_len - len);
len += dtmf_tx(&s->dtmftx, amp, max_len - len);
break;
default:
if (len < max_len)
{
if ((lenx = fsk_tx(&(s->fsktx), amp + len, max_len - len)) <= 0)
if ((lenx = fsk_tx(&s->fsktx, amp + len, max_len - len)) <= 0)
s->tx_signal_on = FALSE;
len += lenx;
}
@ -500,7 +500,7 @@ SPAN_DECLARE(int) adsi_tx(adsi_tx_state_t *s, int16_t amp[], int max_len)
SPAN_DECLARE(void) adsi_tx_send_alert_tone(adsi_tx_state_t *s)
{
tone_gen_init(&(s->alert_tone_gen), &(s->alert_tone_desc));
tone_gen_init(&s->alert_tone_gen, &s->alert_tone_desc);
}
/*- End of function --------------------------------------------------------*/
@ -583,7 +583,7 @@ SPAN_DECLARE(int) adsi_tx_put_message(adsi_tx_state_t *s, const uint8_t *msg, in
case ADSI_STANDARD_CLIP_DTMF:
if (len >= 128)
return -1;
len -= (int) dtmf_tx_put(&(s->dtmftx), (char *) msg, len);
len -= (int) dtmf_tx_put(&s->dtmftx, (char *) msg, len);
break;
case ADSI_STANDARD_JCLIP:
if (len > 128 - 9)
@ -662,7 +662,7 @@ SPAN_DECLARE(adsi_tx_state_t *) adsi_tx_init(adsi_tx_state_t *s, int standard)
return NULL;
}
memset(s, 0, sizeof(*s));
tone_gen_descriptor_init(&(s->alert_tone_desc),
tone_gen_descriptor_init(&s->alert_tone_desc,
2130,
-13,
2750,

View File

@ -35,6 +35,7 @@
#include <assert.h>
#include "spandsp/telephony.h"
#include "spandsp/bit_operations.h"
#include "spandsp/async.h"
#include "spandsp/private/async.h"
@ -75,55 +76,13 @@ SPAN_DECLARE(const char *) signal_status_to_str(int status)
return "Link disconnected";
case SIG_STATUS_LINK_ERROR:
return "Link error";
case SIG_STATUS_LINK_IDLE:
return "Link idle";
}
return "???";
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(async_rx_state_t *) async_rx_init(async_rx_state_t *s,
int data_bits,
int parity,
int stop_bits,
int use_v14,
put_byte_func_t put_byte,
void *user_data)
{
if (s == NULL)
{
if ((s = (async_rx_state_t *) malloc(sizeof(*s))) == NULL)
return NULL;
}
s->data_bits = data_bits;
s->parity = parity;
s->stop_bits = stop_bits;
s->use_v14 = use_v14;
s->put_byte = put_byte;
s->user_data = user_data;
s->byte_in_progress = 0;
s->bitpos = 0;
s->parity_bit = 0;
s->parity_errors = 0;
s->framing_errors = 0;
return s;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) async_rx_release(async_rx_state_t *s)
{
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) async_rx_free(async_rx_state_t *s)
{
free(s);
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE_NONSTD(void) async_rx_put_bit(void *user_data, int bit)
{
async_rx_state_t *s;
@ -205,45 +164,44 @@ SPAN_DECLARE_NONSTD(void) async_rx_put_bit(void *user_data, int bit)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(async_tx_state_t *) async_tx_init(async_tx_state_t *s,
SPAN_DECLARE(async_rx_state_t *) async_rx_init(async_rx_state_t *s,
int data_bits,
int parity,
int stop_bits,
int use_v14,
get_byte_func_t get_byte,
put_byte_func_t put_byte,
void *user_data)
{
if (s == NULL)
{
if ((s = (async_tx_state_t *) malloc(sizeof(*s))) == NULL)
if ((s = (async_rx_state_t *) malloc(sizeof(*s))) == NULL)
return NULL;
}
/* We have a use_v14 parameter for completeness, but right now V.14 only
applies to the receive side. We are unlikely to have an application where
flow control does not exist, so V.14 stuffing is not needed. */
s->data_bits = data_bits;
s->parity = parity;
s->stop_bits = stop_bits;
if (parity != ASYNC_PARITY_NONE)
s->stop_bits++;
s->get_byte = get_byte;
s->use_v14 = use_v14;
s->put_byte = put_byte;
s->user_data = user_data;
s->byte_in_progress = 0;
s->bitpos = 0;
s->parity_bit = 0;
s->parity_errors = 0;
s->framing_errors = 0;
return s;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) async_tx_release(async_tx_state_t *s)
SPAN_DECLARE(int) async_rx_release(async_rx_state_t *s)
{
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) async_tx_free(async_tx_state_t *s)
SPAN_DECLARE(int) async_rx_free(async_rx_state_t *s)
{
free(s);
return 0;
@ -295,4 +253,56 @@ SPAN_DECLARE_NONSTD(int) async_tx_get_bit(void *user_data)
return bit;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) async_tx_presend_bits(async_tx_state_t *s, int bits)
{
s->presend_bits = bits;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(async_tx_state_t *) async_tx_init(async_tx_state_t *s,
int data_bits,
int parity,
int stop_bits,
int use_v14,
get_byte_func_t get_byte,
void *user_data)
{
if (s == NULL)
{
if ((s = (async_tx_state_t *) malloc(sizeof(*s))) == NULL)
return NULL;
}
/* We have a use_v14 parameter for completeness, but right now V.14 only
applies to the receive side. We are unlikely to have an application where
flow control does not exist, so V.14 stuffing is not needed. */
s->data_bits = data_bits;
s->parity = parity;
s->stop_bits = stop_bits;
if (parity != ASYNC_PARITY_NONE)
s->stop_bits++;
s->get_byte = get_byte;
s->user_data = user_data;
s->byte_in_progress = 0;
s->bitpos = 0;
s->parity_bit = 0;
s->presend_bits = 0;
return s;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) async_tx_release(async_tx_state_t *s)
{
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) async_tx_free(async_tx_state_t *s)
{
free(s);
return 0;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/

View File

@ -508,21 +508,31 @@ SPAN_DECLARE(int) dtmf_tx(dtmf_tx_state_t *s, int16_t amp[], int max_samples)
if (s->tones.current_section >= 0)
{
/* Deal with the fragment left over from last time */
len = tone_gen(&(s->tones), amp, max_samples);
len = tone_gen(&s->tones, amp, max_samples);
}
while (len < max_samples && (digit = queue_read_byte(&s->queue.queue)) >= 0)
while (len < max_samples)
{
/* Step to the next digit */
if ((digit = queue_read_byte(&s->queue.queue)) < 0)
{
/* See if we can get some more digits */
if (s->callback == NULL)
break;
s->callback(s->callback_data);
if ((digit = queue_read_byte(&s->queue.queue)) < 0)
break;
}
if (digit == 0)
continue;
if ((cp = strchr(dtmf_positions, digit)) == NULL)
continue;
tone_gen_init(&(s->tones), &dtmf_digit_tones[cp - dtmf_positions]);
tone_gen_init(&s->tones, &dtmf_digit_tones[cp - dtmf_positions]);
s->tones.tone[0].gain = s->low_level;
s->tones.tone[1].gain = s->high_level;
s->tones.duration[0] = s->on_time;
s->tones.duration[1] = s->off_time;
len += tone_gen(&(s->tones), amp + len, max_samples - len);
len += tone_gen(&s->tones, amp + len, max_samples - len);
}
return len;
}
@ -562,7 +572,9 @@ SPAN_DECLARE(void) dtmf_tx_set_timing(dtmf_tx_state_t *s, int on_time, int off_t
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(dtmf_tx_state_t *) dtmf_tx_init(dtmf_tx_state_t *s)
SPAN_DECLARE(dtmf_tx_state_t *) dtmf_tx_init(dtmf_tx_state_t *s,
digits_tx_callback_t callback,
void *user_data)
{
if (s == NULL)
{
@ -572,7 +584,9 @@ SPAN_DECLARE(dtmf_tx_state_t *) dtmf_tx_init(dtmf_tx_state_t *s)
memset(s, 0, sizeof(*s));
if (!dtmf_tx_inited)
dtmf_tx_initialise();
tone_gen_init(&(s->tones), &dtmf_digit_tones[0]);
s->callback = callback;
s->callback_data = user_data;
tone_gen_init(&s->tones, &dtmf_digit_tones[0]);
dtmf_tx_set_level(s, DEFAULT_DTMF_TX_LEVEL, 0);
dtmf_tx_set_timing(s, -1, -1);
queue_init(&s->queue.queue, MAX_DTMF_DIGITS, QUEUE_READ_ATOMIC | QUEUE_WRITE_ATOMIC);

View File

@ -117,7 +117,7 @@ const fsk_spec_t preset_fsk_specs[] =
4545
},
{
"Weitbrecht 50", /* Used for Internatioal TDD (Telecoms Device for the Deaf) */
"Weitbrecht 50", /* Used for international TDD (Telecoms Device for the Deaf) */
1600 + 200,
1600 - 200,
-14,

View File

@ -86,7 +86,9 @@ enum
/*! \brief The link protocol (e.g. V.42) has disconnected. */
SIG_STATUS_LINK_DISCONNECTED = -15,
/*! \brief An error has occurred in the link protocol (e.g. V.42). */
SIG_STATUS_LINK_ERROR = -16
SIG_STATUS_LINK_ERROR = -16,
/*! \brief Keep the link in an idle state, as there is nothing to send. */
SIG_STATUS_LINK_IDLE = -17
};
/*! Message put function for data pumps */
@ -145,33 +147,16 @@ extern "C"
\return A pointer to the description. */
SPAN_DECLARE(const char *) signal_status_to_str(int status);
/*! Initialise an asynchronous data transmit context.
\brief Initialise an asynchronous data transmit context.
\param s The transmitter context.
\param data_bits The number of data bit.
\param parity_bits The type of parity.
\param stop_bits The number of stop bits.
\param use_v14 TRUE if V.14 rate adaption processing should be used.
\param get_byte The callback routine used to get the data to be transmitted.
\param user_data An opaque pointer.
\return A pointer to the initialised context, or NULL if there was a problem. */
SPAN_DECLARE(async_tx_state_t *) async_tx_init(async_tx_state_t *s,
int data_bits,
int parity_bits,
int stop_bits,
int use_v14,
get_byte_func_t get_byte,
void *user_data);
SPAN_DECLARE(int) async_tx_release(async_tx_state_t *s);
SPAN_DECLARE(int) async_tx_free(async_tx_state_t *s);
/*! Get the next bit of a transmitted serial bit stream.
\brief Get the next bit of a transmitted serial bit stream.
\param user_data An opaque point which must point to a transmitter context.
\return the next bit, or PUTBIT_END_OF_DATA to indicate the data stream has ended. */
SPAN_DECLARE_NONSTD(int) async_tx_get_bit(void *user_data);
/*! Accept a bit from a received serial bit stream
\brief Accept a bit from a received serial bit stream
\param user_data An opaque point which must point to a receiver context.
\param bit The new bit. Some special values are supported for this field.
- SIG_STATUS_CARRIER_UP
- SIG_STATUS_CARRIER_DOWN
- SIG_STATUS_TRAINING_SUCCEEDED
- SIG_STATUS_TRAINING_FAILED
- SIG_STATUS_END_OF_DATA */
SPAN_DECLARE_NONSTD(void) async_rx_put_bit(void *user_data, int bit);
/*! Initialise an asynchronous data receiver context.
\brief Initialise an asynchronous data receiver context.
@ -195,16 +180,39 @@ SPAN_DECLARE(int) async_rx_release(async_rx_state_t *s);
SPAN_DECLARE(int) async_rx_free(async_rx_state_t *s);
/*! Accept a bit from a received serial bit stream
\brief Accept a bit from a received serial bit stream
\param user_data An opaque point which must point to a receiver context.
\param bit The new bit. Some special values are supported for this field.
- SIG_STATUS_CARRIER_UP
- SIG_STATUS_CARRIER_DOWN
- SIG_STATUS_TRAINING_SUCCEEDED
- SIG_STATUS_TRAINING_FAILED
- SIG_STATUS_END_OF_DATA */
SPAN_DECLARE_NONSTD(void) async_rx_put_bit(void *user_data, int bit);
/*! Set a minimum number of bit times of stop bit state before character transmission commences.
\brief Set a minimum number of bit times of stop bit state before character transmission commences.
\param user_data An opaque point which must point to a transmitter context.
\param the number of bits. */
SPAN_DECLARE(void) async_tx_presend_bits(async_tx_state_t *s, int bits);
/*! Get the next bit of a transmitted serial bit stream.
\brief Get the next bit of a transmitted serial bit stream.
\param user_data An opaque point which must point to a transmitter context.
\return the next bit, or PUTBIT_END_OF_DATA to indicate the data stream has ended. */
SPAN_DECLARE_NONSTD(int) async_tx_get_bit(void *user_data);
/*! Initialise an asynchronous data transmit context.
\brief Initialise an asynchronous data transmit context.
\param s The transmitter context.
\param data_bits The number of data bit.
\param parity_bits The type of parity.
\param stop_bits The number of stop bits.
\param use_v14 TRUE if V.14 rate adaption processing should be used.
\param get_byte The callback routine used to get the data to be transmitted.
\param user_data An opaque pointer.
\return A pointer to the initialised context, or NULL if there was a problem. */
SPAN_DECLARE(async_tx_state_t *) async_tx_init(async_tx_state_t *s,
int data_bits,
int parity_bits,
int stop_bits,
int use_v14,
get_byte_func_t get_byte,
void *user_data);
SPAN_DECLARE(int) async_tx_release(async_tx_state_t *s);
SPAN_DECLARE(int) async_tx_free(async_tx_state_t *s);
#if defined(__cplusplus)
}

View File

@ -74,6 +74,7 @@ repertoire of 16 DTMF dual tones.
#define MAX_DTMF_DIGITS 128
typedef void (*digits_rx_callback_t)(void *user_data, const char *digits, int len);
typedef void (*digits_tx_callback_t)(void *user_data);
/*!
DTMF generator state descriptor. This defines the state of a single
@ -122,8 +123,13 @@ SPAN_DECLARE(void) dtmf_tx_set_timing(dtmf_tx_state_t *s, int on_time, int off_t
/*! \brief Initialise a DTMF tone generator context.
\param s The DTMF generator context.
\param callback An optional callback routine, used to get more digits.
\param user_data An opaque pointer which is associated with the context,
and supplied in callbacks.
\return A pointer to the DTMF generator context. */
SPAN_DECLARE(dtmf_tx_state_t *) dtmf_tx_init(dtmf_tx_state_t *s);
SPAN_DECLARE(dtmf_tx_state_t *) dtmf_tx_init(dtmf_tx_state_t *s,
digits_tx_callback_t callback,
void *user_data);
/*! \brief Release a DTMF tone generator context.
\param s The DTMF tone generator context.

View File

@ -43,9 +43,11 @@ struct async_tx_state_s
get_byte_func_t get_byte;
/*! \brief An opaque pointer passed when calling get_byte. */
void *user_data;
/*! \brief The minimum number of stop bits to send before character transmission begins. */
int presend_bits;
/*! \brief A current, partially transmitted, character. */
unsigned int byte_in_progress;
int32_t byte_in_progress;
/*! \brief The current bit position within a partially transmitted character. */
int bitpos;
/*! \brief Parity bit. */
@ -73,7 +75,7 @@ struct async_rx_state_s
void *user_data;
/*! \brief A current, partially complete, character. */
unsigned int byte_in_progress;
int32_t byte_in_progress;
/*! \brief The current bit position within a partially complete character. */
int bitpos;
/*! \brief Parity bit. */

View File

@ -32,6 +32,10 @@
*/
struct dtmf_tx_state_s
{
/*! Optional callback funcion to get more digits. */
digits_tx_callback_t callback;
/*! An opaque pointer passed to the callback function. */
void *callback_data;
tone_gen_state_t tones;
float low_level;
float high_level;

View File

@ -66,6 +66,10 @@ typedef struct
{
/*! \brief The FAX modem set for the audio side fo the gateway. */
fax_modems_state_t modems;
/*! \brief CED detector */
modem_connect_tones_rx_state_t connect_rx_ced;
/*! \brief CNG detector */
modem_connect_tones_rx_state_t connect_rx_cng;
} t38_gateway_audio_state_t;
/*!

View File

@ -138,7 +138,7 @@ struct v22bis_state_s
int constellation_state;
#if defined(SPANDSP_USE_FIXED_POINT)
/*! \brief The scaling factor accessed by the AGC algorithm. */
/*! \brief The scaling factor assessed by the AGC algorithm. */
int16_t agc_scaling;
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
int16_t rrc_filter[V22BIS_RX_FILTER_STEPS];
@ -158,7 +158,7 @@ struct v22bis_state_s
/*! \brief The integral part of the carrier tracking filter. */
int32_t carrier_track_i;
#else
/*! \brief The scaling factor accessed by the AGC algorithm. */
/*! \brief The scaling factor assessed by the AGC algorithm. */
float agc_scaling;
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
float rrc_filter[V22BIS_RX_FILTER_STEPS];

View File

@ -363,16 +363,24 @@ static __inline__ int32_t saturated_sub32(int32_t a, int32_t b)
static __inline__ int16_t saturated_mul16(int16_t a, int16_t b)
{
if (a == INT16_MIN && b == INT16_MIN)
int32_t product;
product = (int32_t) a*b;
if (product == 0x40000000)
return INT16_MAX;
/*endif*/
return (int16_t) (((int32_t) a*(int32_t) b) >> 15);
return product >> 15;
}
/*- End of function --------------------------------------------------------*/
static __inline__ int32_t saturated_mul16_32(int16_t a, int16_t b)
{
return ((int32_t) a*(int32_t) b) << 1;
int32_t product;
product = (int32_t) a*b;
if (product == 0x40000000)
return INT32_MAX;
return product << 1;
}
/*- End of function --------------------------------------------------------*/

View File

@ -140,9 +140,19 @@ SPAN_DECLARE_NONSTD(int) v18_tx(v18_state_t *s, int16_t amp[], int max_len);
\param s The V.18 context.
\param amp The audio sample buffer.
\param len The number of samples in the buffer.
\return The number of unprocessed samples.
*/
SPAN_DECLARE_NONSTD(int) v18_rx(v18_state_t *s, const int16_t amp[], int len);
/*! Fake processing of a missing block of received V.18 audio samples.
(e.g due to packet loss).
\brief Fake processing of a missing block of received V.18 audio samples.
\param s The V.18 context.
\param len The number of samples to fake.
\return The number of unprocessed samples.
*/
SPAN_DECLARE_NONSTD(int) v18_rx_fillin(v18_state_t *s, int len);
/*! \brief Put a string to a V.18 context's input buffer.
\param s The V.18 context.
\param msg The string to be added.

View File

@ -100,12 +100,12 @@ SPAN_DECLARE(void) v42_restart(v42_state_t *s);
/*! Release a V.42 context.
\param s The V.42 context.
\return 0 if OK */
SPAN_DECLARE(void) v42_release(v42_state_t *s);
SPAN_DECLARE(int) v42_release(v42_state_t *s);
/*! Free a V.42 context.
\param s The V.42 context.
\return 0 if OK */
SPAN_DECLARE(void) v42_free(v42_state_t *s);
SPAN_DECLARE(int) v42_free(v42_state_t *s);
#if defined(__cplusplus)
}

View File

@ -1406,7 +1406,7 @@ static int build_dcs(t30_state_t *s)
/* We have a file to send, so tell the far end to go into receive mode. */
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_RECEIVE_FAX_DOCUMENT);
/* Set the Y resolution bits */
bad = T30_ERR_OK;
bad = T30_ERR_NORESSUPPORT;
row_squashing_ratio = 1;
switch (s->y_resolution)
{
@ -1414,19 +1414,18 @@ static int build_dcs(t30_state_t *s)
switch (s->x_resolution)
{
case T4_X_RESOLUTION_600:
if (!(s->supported_resolutions & T30_SUPPORT_600_1200_RESOLUTION))
bad = T30_ERR_NORESSUPPORT;
else
if ((s->supported_resolutions & T30_SUPPORT_600_1200_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_1200_CAPABLE))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_1200);
bad = T30_ERR_OK;
}
break;
case T4_X_RESOLUTION_1200:
if (!(s->supported_resolutions & T30_SUPPORT_1200_1200_RESOLUTION))
bad = T30_ERR_NORESSUPPORT;
else
if ((s->supported_resolutions & T30_SUPPORT_1200_1200_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_1200_1200_CAPABLE))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_1200_1200);
break;
default:
bad = T30_ERR_NORESSUPPORT;
bad = T30_ERR_OK;
}
break;
}
break;
@ -1434,13 +1433,11 @@ static int build_dcs(t30_state_t *s)
switch (s->x_resolution)
{
case T4_X_RESOLUTION_R16:
if (!(s->supported_resolutions & T30_SUPPORT_400_800_RESOLUTION))
bad = T30_ERR_NORESSUPPORT;
else
if ((s->supported_resolutions & T30_SUPPORT_400_800_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_400_800_CAPABLE))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_800);
break;
default:
bad = T30_ERR_NORESSUPPORT;
bad = T30_ERR_OK;
}
break;
}
break;
@ -1448,19 +1445,18 @@ static int build_dcs(t30_state_t *s)
switch (s->x_resolution)
{
case T4_X_RESOLUTION_300:
if (!(s->supported_resolutions & T30_SUPPORT_300_600_RESOLUTION))
bad = T30_ERR_NORESSUPPORT;
else
if ((s->supported_resolutions & T30_SUPPORT_300_600_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_600_CAPABLE))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_600);
bad = T30_ERR_OK;
}
break;
case T4_X_RESOLUTION_600:
if (!(s->supported_resolutions & T30_SUPPORT_600_600_RESOLUTION))
bad = T30_ERR_NORESSUPPORT;
else
if ((s->supported_resolutions & T30_SUPPORT_600_600_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_600_CAPABLE))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_600);
break;
default:
bad = T30_ERR_NORESSUPPORT;
bad = T30_ERR_OK;
}
break;
}
break;
@ -1468,45 +1464,40 @@ static int build_dcs(t30_state_t *s)
switch (s->x_resolution)
{
case T4_X_RESOLUTION_300:
if (!(s->supported_resolutions & T30_SUPPORT_300_300_RESOLUTION))
bad = T30_ERR_NORESSUPPORT;
else
if ((s->supported_resolutions & T30_SUPPORT_300_300_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_300_CAPABLE))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_300);
break;
default:
bad = T30_ERR_NORESSUPPORT;
bad = T30_ERR_OK;
}
break;
}
break;
case T4_Y_RESOLUTION_SUPERFINE:
if ((s->supported_resolutions & T30_SUPPORT_SUPERFINE_RESOLUTION))
{
switch (s->x_resolution)
if (s->x_resolution == T4_X_RESOLUTION_R16 && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_400_400_CAPABLE))
{
case T4_X_RESOLUTION_R8:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
break;
case T4_X_RESOLUTION_R16:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
break;
default:
bad = T30_ERR_NORESSUPPORT;
bad = T30_ERR_OK;
break;
}
if (s->x_resolution == T4_X_RESOLUTION_R8 && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
bad = T30_ERR_OK;
break;
}
break;
}
row_squashing_ratio <<= 1;
/* Fall through */
case T4_Y_RESOLUTION_FINE:
if ((s->supported_resolutions & T30_SUPPORT_FINE_RESOLUTION))
if ((s->supported_resolutions & T30_SUPPORT_FINE_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE))
{
switch (s->x_resolution)
{
case T4_X_RESOLUTION_R8:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
break;
default:
bad = T30_ERR_NORESSUPPORT;
bad = T30_ERR_OK;
break;
}
break;
@ -1519,9 +1510,7 @@ static int build_dcs(t30_state_t *s)
{
case T4_X_RESOLUTION_R8:
/* No bits to set for this */
break;
default:
bad = T30_ERR_NORESSUPPORT;
bad = T30_ERR_OK;
break;
}
break;
@ -1533,97 +1522,89 @@ static int build_dcs(t30_state_t *s)
span_log(&s->logging, SPAN_LOG_FLOW, "Image resolution (%d x %d) not acceptable\n", s->x_resolution, s->y_resolution);
return -1;
}
/* Deal with the image width. The X resolution will fall in line with any valid width. */
/* Deal with the image width. */
/* Low (R4) res widths are not supported in recent versions of T.30 */
bad = T30_ERR_OK;
/* The following treats a width field of 11 like 10, which does what note 6 of Table 2/T.30
says we should do with the invalid value 11. */
switch (s->image_width)
if (((s->image_width == T4_WIDTH_R8_A4) && (s->x_resolution == T4_X_RESOLUTION_R8))
||
((s->image_width == T4_WIDTH_300_A4) && (s->x_resolution == T4_X_RESOLUTION_300))
||
((s->image_width == T4_WIDTH_R16_A4) && (s->x_resolution == T4_X_RESOLUTION_R16))
||
((s->image_width == T4_WIDTH_600_A4) && (s->x_resolution == T4_X_RESOLUTION_600))
||
((s->image_width == T4_WIDTH_1200_A4) && (s->x_resolution == T4_X_RESOLUTION_1200)))
{
case T4_WIDTH_R8_A4:
case T4_WIDTH_300_A4:
case T4_WIDTH_R16_A4:
case T4_WIDTH_600_A4:
case T4_WIDTH_1200_A4:
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A4 0x%x 0x%x\n", s->image_width, s->x_resolution);
/* No width related bits need to be set. */
break;
case T4_WIDTH_R8_B4:
case T4_WIDTH_300_B4:
case T4_WIDTH_R16_B4:
case T4_WIDTH_600_B4:
case T4_WIDTH_1200_B4:
if ((s->far_dis_dtc_frame[5] & (DISBIT2 | DISBIT1)) < 1)
bad = T30_ERR_NOSIZESUPPORT;
else if (!(s->supported_image_sizes & T30_SUPPORT_255MM_WIDTH))
bad = T30_ERR_NOSIZESUPPORT;
else
}
else if (((s->image_width == T4_WIDTH_R8_B4) && (s->x_resolution == T4_X_RESOLUTION_R8))
||
((s->image_width == T4_WIDTH_300_B4) && (s->x_resolution == T4_X_RESOLUTION_300))
||
((s->image_width == T4_WIDTH_R16_B4) && (s->x_resolution == T4_X_RESOLUTION_R16))
||
((s->image_width == T4_WIDTH_600_B4) && (s->x_resolution == T4_X_RESOLUTION_600))
||
((s->image_width == T4_WIDTH_1200_B4) && (s->x_resolution == T4_X_RESOLUTION_1200)))
{
if (((s->far_dis_dtc_frame[5] & (DISBIT2 | DISBIT1)) >= 1)
&&
(s->supported_image_sizes & T30_SUPPORT_255MM_WIDTH))
{
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is B4\n");
set_ctrl_bit(s->dcs_frame, 17);
break;
case T4_WIDTH_R8_A3:
case T4_WIDTH_300_A3:
case T4_WIDTH_R16_A3:
case T4_WIDTH_600_A3:
case T4_WIDTH_1200_A3:
if ((s->far_dis_dtc_frame[5] & (DISBIT2 | DISBIT1)) < 2)
bad = T30_ERR_NOSIZESUPPORT;
else if (!(s->supported_image_sizes & T30_SUPPORT_303MM_WIDTH))
bad = T30_ERR_NOSIZESUPPORT;
}
else
{
/* We do not support this width and resolution combination */
bad = T30_ERR_NOSIZESUPPORT;
}
}
else if (((s->image_width == T4_WIDTH_R8_A3) && (s->x_resolution == T4_X_RESOLUTION_R8))
||
((s->image_width == T4_WIDTH_300_A3) && (s->x_resolution == T4_X_RESOLUTION_300))
||
((s->image_width == T4_WIDTH_R16_A3) && (s->x_resolution == T4_X_RESOLUTION_R16))
||
((s->image_width == T4_WIDTH_600_A3) && (s->x_resolution == T4_X_RESOLUTION_600))
||
((s->image_width == T4_WIDTH_1200_A3) && (s->x_resolution == T4_X_RESOLUTION_1200)))
{
if (((s->far_dis_dtc_frame[5] & (DISBIT2 | DISBIT1)) >= 2)
&&
(s->supported_image_sizes & T30_SUPPORT_303MM_WIDTH))
{
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A3\n");
set_ctrl_bit(s->dcs_frame, 18);
break;
default:
/* T.30 does not support this width */
bad = T30_ERR_NOSIZESUPPORT;
break;
}
else
{
/* We do not support this width and resolution combination */
bad = T30_ERR_NOSIZESUPPORT;
}
}
else
{
/* We do not support this width and resolution combination */
bad = T30_ERR_NOSIZESUPPORT;
}
if (bad != T30_ERR_OK)
{
t30_set_status(s, bad);
span_log(&s->logging, SPAN_LOG_FLOW, "Image width (%d pixels) is not an acceptable FAX image width\n", s->image_width);
return -1;
}
switch (s->image_width)
{
case T4_WIDTH_R8_A4:
case T4_WIDTH_R8_B4:
case T4_WIDTH_R8_A3:
/* These are always OK */
break;
case T4_WIDTH_300_A4:
case T4_WIDTH_300_B4:
case T4_WIDTH_300_A3:
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_300_CAPABLE) && !test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_600_CAPABLE))
bad = T30_ERR_NOSIZESUPPORT;
break;
case T4_WIDTH_R16_A4:
case T4_WIDTH_R16_B4:
case T4_WIDTH_R16_A3:
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_400_400_CAPABLE))
bad = T30_ERR_NOSIZESUPPORT;
break;
case T4_WIDTH_600_A4:
case T4_WIDTH_600_B4:
case T4_WIDTH_600_A3:
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_600_CAPABLE) && !test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_1200_CAPABLE))
bad = T30_ERR_NOSIZESUPPORT;
break;
case T4_WIDTH_1200_A4:
case T4_WIDTH_1200_B4:
case T4_WIDTH_1200_A3:
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_1200_1200_CAPABLE))
bad = T30_ERR_NOSIZESUPPORT;
break;
default:
/* T.30 does not support this width */
bad = T30_ERR_NOSIZESUPPORT;
break;
}
if (bad != T30_ERR_OK)
{
t30_set_status(s, bad);
span_log(&s->logging, SPAN_LOG_FLOW, "Image width (%d pixels) is not an acceptable FAX image width\n", s->image_width);
span_log(&s->logging,
SPAN_LOG_FLOW,
"Image width (%d pixels) and resolution (%d x %d) is not an acceptable\n",
s->image_width,
s->x_resolution,
s->y_resolution);
return -1;
}
/* Deal with the image length */
/* If the other end supports unlimited length, then use that. Otherwise, if the other end supports
B4 use that, as its longer than the default A4 length. */
@ -2004,6 +1985,7 @@ static int start_sending_document(t30_state_t *s)
if (tx_start_page(s))
return -1;
s->x_resolution = t4_tx_get_x_resolution(&s->t4.tx);
s->y_resolution = t4_tx_get_y_resolution(&s->t4.tx);
s->image_width = t4_tx_get_image_width(&s->t4.tx);
@ -2337,6 +2319,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
};
uint8_t dcs_frame[T30_MAX_DIS_DTC_DCS_LEN];
int i;
int x;
int new_status;
t30_decode_dis_dtc_dcs(s, msg, len);
@ -2368,46 +2351,104 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
s->octets_per_ecm_frame = test_ctrl_bit(dcs_frame, T30_DCS_BIT_64_OCTET_ECM_FRAMES) ? 256 : 64;
s->x_resolution = -1;
s->y_resolution = -1;
x = -1;
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_1200_1200))
s->x_resolution = T4_X_RESOLUTION_1200;
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_600) || test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_1200))
s->x_resolution = T4_X_RESOLUTION_600;
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_400) || test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_800))
s->x_resolution = T4_X_RESOLUTION_R16;
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_300) || test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_600))
s->x_resolution = T4_X_RESOLUTION_300;
else
s->x_resolution = T4_X_RESOLUTION_R8;
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_1200_1200) || test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_1200))
s->y_resolution = T4_Y_RESOLUTION_1200;
{
if ((s->supported_resolutions & T30_SUPPORT_1200_1200_RESOLUTION))
{
s->x_resolution = T4_X_RESOLUTION_1200;
s->y_resolution = T4_Y_RESOLUTION_1200;
x = 5;
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_1200))
{
if ((s->supported_resolutions & T30_SUPPORT_600_1200_RESOLUTION))
{
s->x_resolution = T4_X_RESOLUTION_600;
s->y_resolution = T4_Y_RESOLUTION_1200;
x = 4;
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_600))
{
if ((s->supported_resolutions & T30_SUPPORT_600_600_RESOLUTION))
{
s->x_resolution = T4_X_RESOLUTION_600;
s->y_resolution = T4_Y_RESOLUTION_600;
x = 4;
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_800))
s->y_resolution = T4_Y_RESOLUTION_800;
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_600) || test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_600))
s->y_resolution = T4_Y_RESOLUTION_600;
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_200_400) || test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_400))
s->y_resolution = T4_Y_RESOLUTION_SUPERFINE;
{
if ((s->supported_resolutions & T30_SUPPORT_400_800_RESOLUTION))
{
s->x_resolution = T4_X_RESOLUTION_R16;
s->y_resolution = T4_Y_RESOLUTION_800;
x = 3;
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_400))
{
if ((s->supported_resolutions & T30_SUPPORT_400_400_RESOLUTION))
{
s->x_resolution = T4_X_RESOLUTION_R16;
s->y_resolution = T4_Y_RESOLUTION_SUPERFINE;
x = 3;
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_600))
{
if ((s->supported_resolutions & T30_SUPPORT_300_600_RESOLUTION))
{
s->x_resolution = T4_X_RESOLUTION_300;
s->y_resolution = T4_Y_RESOLUTION_600;
x = 2;
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_300))
s->y_resolution = T4_Y_RESOLUTION_300;
{
if ((s->supported_resolutions & T30_SUPPORT_300_300_RESOLUTION))
{
s->x_resolution = T4_X_RESOLUTION_300;
s->y_resolution = T4_Y_RESOLUTION_300;
x = 2;
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_200_400))
{
if ((s->supported_resolutions & T30_SUPPORT_SUPERFINE_RESOLUTION))
{
s->x_resolution = T4_X_RESOLUTION_R8;
s->y_resolution = T4_Y_RESOLUTION_SUPERFINE;
x = 1;
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_200_200))
s->y_resolution = T4_Y_RESOLUTION_FINE;
{
if ((s->supported_resolutions & T30_SUPPORT_FINE_RESOLUTION))
{
s->x_resolution = T4_X_RESOLUTION_R8;
s->y_resolution = T4_Y_RESOLUTION_FINE;
x = 1;
}
}
else
{
s->x_resolution = T4_X_RESOLUTION_R8;
s->y_resolution = T4_Y_RESOLUTION_STANDARD;
x = 1;
}
if (s->x_resolution == T4_X_RESOLUTION_1200)
i = 5;
else if (s->x_resolution == T4_X_RESOLUTION_600)
i = 4;
else if (s->x_resolution == T4_X_RESOLUTION_R16)
i = 3;
else if (s->x_resolution == T4_X_RESOLUTION_300)
i = 2;
else if (s->x_resolution == T4_X_RESOLUTION_R4)
i = 0;
else
i = 1;
if (x < 0)
{
t30_set_status(s, T30_ERR_NORESSUPPORT);
return -1;
}
s->image_width = widths[i][dcs_frame[5] & (DISBIT2 | DISBIT1)];
s->image_width = widths[x][dcs_frame[5] & (DISBIT2 | DISBIT1)];
/* Check which compression the far end has decided to use. */
#if defined(SPANDSP_SUPPORT_T42)

View File

@ -387,9 +387,9 @@ static int cmp(const void *s, const void *t)
SPAN_DECLARE(int) v18_encode_dtmf(v18_state_t *s, char dtmf[], const char msg[])
{
const char *t;
char *u;
const char *v;
char *u;
t = msg;
u = dtmf;
while (*t)
@ -685,7 +685,8 @@ static void v18_tdd_put_async_byte(void *user_data, int byte)
{
/* Whatever we have to date constitutes the message */
s->rx_msg[s->rx_msg_len] = '\0';
s->put_msg(s->user_data, s->rx_msg, s->rx_msg_len);
if (s->put_msg)
s->put_msg(s->user_data, s->rx_msg, s->rx_msg_len);
s->rx_msg_len = 0;
}
break;
@ -701,7 +702,8 @@ static void v18_tdd_put_async_byte(void *user_data, int byte)
if (s->rx_msg_len >= 256)
{
s->rx_msg[s->rx_msg_len] = '\0';
s->put_msg(s->user_data, s->rx_msg, s->rx_msg_len);
if (s->put_msg)
s->put_msg(s->user_data, s->rx_msg, s->rx_msg_len);
s->rx_msg_len = 0;
}
}
@ -815,6 +817,33 @@ SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(const char *) v18_mode_to_str(int mode)
{
switch (mode & 0xFF)
{
case V18_MODE_NONE:
return "None";
case V18_MODE_5BIT_45:
return "Weitbrecht TDD (45.45bps)";
case V18_MODE_5BIT_50:
return "Weitbrecht TDD (50bps)";
case V18_MODE_DTMF:
return "DTMF";
case V18_MODE_EDT:
return "EDT";
case V18_MODE_BELL103:
return "Bell 103";
case V18_MODE_V23VIDEOTEX:
return "Videotex";
case V18_MODE_V21TEXTPHONE:
return "V.21";
case V18_MODE_V18TEXTPHONE:
return "V.18 text telephone";
}
return "???";
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(logging_state_t *) v18_get_logging_state(v18_state_t *s)
{
return &s->logging;
@ -863,7 +892,7 @@ SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s,
s->repeat_shifts = mode & 0x100;
break;
case V18_MODE_DTMF:
dtmf_tx_init(&s->dtmftx);
dtmf_tx_init(&s->dtmftx, NULL, NULL);
dtmf_rx_init(&s->dtmfrx, v18_rx_dtmf, s);
break;
case V18_MODE_EDT:
@ -909,31 +938,4 @@ SPAN_DECLARE(int) v18_free(v18_state_t *s)
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(const char *) v18_mode_to_str(int mode)
{
switch (mode & 0xFF)
{
case V18_MODE_NONE:
return "None";
case V18_MODE_5BIT_45:
return "Weitbrecht TDD (45.45bps)";
case V18_MODE_5BIT_50:
return "Weitbrecht TDD (50bps)";
case V18_MODE_DTMF:
return "DTMF";
case V18_MODE_EDT:
return "EDT";
case V18_MODE_BELL103:
return "Bell 103";
case V18_MODE_V23VIDEOTEX:
return "Videotex";
case V18_MODE_V21TEXTPHONE:
return "V.21";
case V18_MODE_V18TEXTPHONE:
return "V.18 text telephone";
}
return "???";
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/

View File

@ -1554,16 +1554,18 @@ SPAN_DECLARE(v42_state_t *) v42_init(v42_state_t *ss,
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) v42_release(v42_state_t *s)
SPAN_DECLARE(int) v42_release(v42_state_t *s)
{
reset_lapm(s);
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) v42_free(v42_state_t *s)
SPAN_DECLARE(int) v42_free(v42_state_t *s)
{
v42_release(s);
free(s);
return 0;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/