Chnaged T.30 x-rex, y-res, width vetting to be more rigorous.
Various little tweaks to spandsp
This commit is contained in:
parent
7a29ef9586
commit
1d289b3617
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 ------------------------------------------------------------*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
/*!
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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 --------------------------------------------------------*/
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 ------------------------------------------------------------*/
|
||||
|
|
|
@ -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 ------------------------------------------------------------*/
|
||||
|
|
Loading…
Reference in New Issue