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)
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
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;
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;
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;
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;
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;
}
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 --------------------------------------------------------*/
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)
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,
#include <assert.h>
#include "spandsp/telephony.h"
+#include "spandsp/bit_operations.h"
#include "spandsp/async.h"
#include "spandsp/private/async.h"
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;
}
/*- 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;
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 ------------------------------------------------------------*/
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;
}
}
/*- 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)
{
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);
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,
/*! \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 */
\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.
+/*! 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.
+ \param s The receiver context.
+ \param data_bits The number of data bits.
\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 put_byte The callback routine used to put the received data.
\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,
+SPAN_DECLARE(async_rx_state_t *) async_rx_init(async_rx_state_t *s,
int data_bits,
int parity_bits,
int stop_bits,
int use_v14,
- get_byte_func_t get_byte,
+ put_byte_func_t put_byte,
void *user_data);
-SPAN_DECLARE(int) async_tx_release(async_tx_state_t *s);
+SPAN_DECLARE(int) async_rx_release(async_rx_state_t *s);
-SPAN_DECLARE(int) async_tx_free(async_tx_state_t *s);
+SPAN_DECLARE(int) async_rx_free(async_rx_state_t *s);
+
+/*! 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.
\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 receiver context.
- \brief Initialise an asynchronous data receiver context.
- \param s The receiver context.
- \param data_bits The number of data bits.
+/*! 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 put_byte The callback routine used to put the received data.
+ \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_rx_state_t *) async_rx_init(async_rx_state_t *s,
+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,
- put_byte_func_t put_byte,
+ get_byte_func_t get_byte,
void *user_data);
-SPAN_DECLARE(int) async_rx_release(async_rx_state_t *s);
-
-SPAN_DECLARE(int) async_rx_free(async_rx_state_t *s);
+SPAN_DECLARE(int) async_tx_release(async_tx_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);
+SPAN_DECLARE(int) async_tx_free(async_tx_state_t *s);
#if defined(__cplusplus)
}
#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
/*! \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.
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. */
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. */
*/
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;
{
/*! \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;
/*!
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];
/*! \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];
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 --------------------------------------------------------*/
\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.
/*! 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)
}
/* 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)
{
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;
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;
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;
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);
+ bad = T30_ERR_OK;
break;
- default:
- bad = T30_ERR_NORESSUPPORT;
+ }
+ 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;
{
case T4_X_RESOLUTION_R8:
/* No bits to set for this */
- break;
- default:
- bad = T30_ERR_NORESSUPPORT;
+ bad = T30_ERR_OK;
break;
}
break;
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
- set_ctrl_bit(s->dcs_frame, 18);
- break;
- default:
- /* T.30 does not support this width */
- bad = T30_ERR_NOSIZESUPPORT;
- break;
+ {
+ /* We do not support this width and resolution combination */
+ bad = T30_ERR_NOSIZESUPPORT;
+ }
}
- if (bad != T30_ERR_OK)
+ 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)))
{
- 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;
+ 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);
+ }
+ else
+ {
+ /* We do not support this width and resolution combination */
+ bad = T30_ERR_NOSIZESUPPORT;
+ }
}
- switch (s->image_width)
+ else
{
- 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 */
+ /* We do not support this width and resolution combination */
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. */
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);
};
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);
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)
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)
{
/* 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;
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;
}
}
}
/*- 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;
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:
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 ------------------------------------------------------------*/
}
/*- 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 ------------------------------------------------------------*/