From: Steve Underwood Date: Sat, 9 Mar 2013 14:19:47 +0000 (+0800) Subject: Chnaged T.30 x-rex, y-res, width vetting to be more rigorous. X-Git-Tag: v1.3.17-final~117 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1d289b3617dafde2b02ae9128d565bff0a8bf064;p=thirdparty%2Ffreeswitch.git Chnaged T.30 x-rex, y-res, width vetting to be more rigorous. Various little tweaks to spandsp --- diff --git a/libs/spandsp/src/ademco_contactid.c b/libs/spandsp/src/ademco_contactid.c index 39ce670bde..6862567184 100644 --- a/libs/spandsp/src/ademco_contactid.c +++ b/libs/spandsp/src/ademco_contactid.c @@ -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; diff --git a/libs/spandsp/src/adsi.c b/libs/spandsp/src/adsi.c index 54d4137682..647bf371ab 100644 --- a/libs/spandsp/src/adsi.c +++ b/libs/spandsp/src/adsi.c @@ -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, diff --git a/libs/spandsp/src/async.c b/libs/spandsp/src/async.c index 1bfa65d910..49e25fde23 100644 --- a/libs/spandsp/src/async.c +++ b/libs/spandsp/src/async.c @@ -35,6 +35,7 @@ #include #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 ------------------------------------------------------------*/ diff --git a/libs/spandsp/src/dtmf.c b/libs/spandsp/src/dtmf.c index ee61f0095c..196e3d3eca 100644 --- a/libs/spandsp/src/dtmf.c +++ b/libs/spandsp/src/dtmf.c @@ -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); diff --git a/libs/spandsp/src/fsk.c b/libs/spandsp/src/fsk.c index 3f53aa7bc8..d95f757468 100644 --- a/libs/spandsp/src/fsk.c +++ b/libs/spandsp/src/fsk.c @@ -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, diff --git a/libs/spandsp/src/spandsp/async.h b/libs/spandsp/src/spandsp/async.h index 8d643dd720..1b22cd5caf 100644 --- a/libs/spandsp/src/spandsp/async.h +++ b/libs/spandsp/src/spandsp/async.h @@ -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,27 +147,44 @@ 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. +/*! 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. @@ -173,38 +192,27 @@ SPAN_DECLARE(int) async_tx_free(async_tx_state_t *s); \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) } diff --git a/libs/spandsp/src/spandsp/dtmf.h b/libs/spandsp/src/spandsp/dtmf.h index a9aeb64ef9..58ea779088 100644 --- a/libs/spandsp/src/spandsp/dtmf.h +++ b/libs/spandsp/src/spandsp/dtmf.h @@ -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. diff --git a/libs/spandsp/src/spandsp/private/async.h b/libs/spandsp/src/spandsp/private/async.h index 715d659d9e..7354aaf967 100644 --- a/libs/spandsp/src/spandsp/private/async.h +++ b/libs/spandsp/src/spandsp/private/async.h @@ -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. */ diff --git a/libs/spandsp/src/spandsp/private/dtmf.h b/libs/spandsp/src/spandsp/private/dtmf.h index e063470d78..eae20ad4d5 100644 --- a/libs/spandsp/src/spandsp/private/dtmf.h +++ b/libs/spandsp/src/spandsp/private/dtmf.h @@ -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; diff --git a/libs/spandsp/src/spandsp/private/t38_gateway.h b/libs/spandsp/src/spandsp/private/t38_gateway.h index 075a9b221c..e8e74c2af9 100644 --- a/libs/spandsp/src/spandsp/private/t38_gateway.h +++ b/libs/spandsp/src/spandsp/private/t38_gateway.h @@ -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; /*! diff --git a/libs/spandsp/src/spandsp/private/v22bis.h b/libs/spandsp/src/spandsp/private/v22bis.h index b601b0c02d..5a03cb79f8 100644 --- a/libs/spandsp/src/spandsp/private/v22bis.h +++ b/libs/spandsp/src/spandsp/private/v22bis.h @@ -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]; diff --git a/libs/spandsp/src/spandsp/saturated.h b/libs/spandsp/src/spandsp/saturated.h index 8c159fee3a..fcefbe96ab 100644 --- a/libs/spandsp/src/spandsp/saturated.h +++ b/libs/spandsp/src/spandsp/saturated.h @@ -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 --------------------------------------------------------*/ diff --git a/libs/spandsp/src/spandsp/v18.h b/libs/spandsp/src/spandsp/v18.h index bc73c7e619..08219ec0be 100644 --- a/libs/spandsp/src/spandsp/v18.h +++ b/libs/spandsp/src/spandsp/v18.h @@ -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. diff --git a/libs/spandsp/src/spandsp/v42.h b/libs/spandsp/src/spandsp/v42.h index bdd34e86f1..5ab26262dd 100644 --- a/libs/spandsp/src/spandsp/v42.h +++ b/libs/spandsp/src/spandsp/v42.h @@ -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) } diff --git a/libs/spandsp/src/t30.c b/libs/spandsp/src/t30.c index 38f160d7ff..5c495dbb81 100644 --- a/libs/spandsp/src/t30.c +++ b/libs/spandsp/src/t30.c @@ -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); + 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; @@ -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 - 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. */ @@ -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) diff --git a/libs/spandsp/src/v18.c b/libs/spandsp/src/v18.c index 639ae0770c..e1cfdc005a 100644 --- a/libs/spandsp/src/v18.c +++ b/libs/spandsp/src/v18.c @@ -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 ------------------------------------------------------------*/ diff --git a/libs/spandsp/src/v42.c b/libs/spandsp/src/v42.c index eec5a87099..3e73d67c27 100644 --- a/libs/spandsp/src/v42.c +++ b/libs/spandsp/src/v42.c @@ -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 ------------------------------------------------------------*/