Some preparations for colour FAX

This commit is contained in:
Steve Underwood 2013-04-02 20:31:19 +08:00
parent e23b6a22bd
commit f758d53ef5
17 changed files with 761 additions and 424 deletions

View File

@ -437,18 +437,17 @@ static const struct ademco_code_s ademco_codes[] =
{-1, "???"}
};
#define GOERTZEL_SAMPLES_PER_BLOCK 55 /* We need to detect over a +-5% range */
#if defined(SPANDSP_USE_FIXED_POINT)
#define GOERTZEL_SAMPLES_PER_BLOCK 55 /* We need to detect over a +-5% range */
#define DETECTION_THRESHOLD 16439 /* -42dBm0 [((GOERTZEL_SAMPLES_PER_BLOCK*GOERTZEL_SAMPLES_PER_BLOCK*32768.0/(1.4142*128.0))*10^((-42 - DBM0_MAX_SINE_POWER)/20.0))^2] */
#define TONE_TWIST 4 /* 6dB */
#define TONE_TO_TOTAL_ENERGY 64 /* -3dB */
#define DETECTION_THRESHOLD 3035 /* -42dBm0 */
#define TONE_TO_TOTAL_ENERGY 45.2233f /* -0.85dB */
#else
#define GOERTZEL_SAMPLES_PER_BLOCK 55 /* We need to detect over a +-5% range */
#define DETECTION_THRESHOLD 2104205.6f /* -42dBm0 [((GOERTZEL_SAMPLES_PER_BLOCK*GOERTZEL_SAMPLES_PER_BLOCK*32768.0/1.4142)*10^((-42 - DBM0_MAX_SINE_POWER)/20.0))^2] */
#define TONE_TWIST 3.981f /* 6dB */
#define TONE_TO_TOTAL_ENERGY 1.995f /* 3dB */
#define DETECTION_THRESHOLD 49728296.6f /* -42dBm0 [((GOERTZEL_SAMPLES_PER_BLOCK*32768.0/1.4142)*10^((-42 - DBM0_MAX_SINE_POWER)/20.0))^2] */
#define TONE_TO_TOTAL_ENERGY 45.2233f /* -0.85dB [GOERTZEL_SAMPLES_PER_BLOCK*10^(-0.85/10.0)] */
#endif
static int tone_rx_init = FALSE;
static goertzel_descriptor_t tone_1400_desc;
static goertzel_descriptor_t tone_2300_desc;
@ -1083,8 +1082,6 @@ SPAN_DECLARE(ademco_contactid_sender_state_t *) ademco_contactid_sender_init(ade
tone_report_func_t callback,
void *user_data)
{
static int initialised = FALSE;
if (s == NULL)
{
if ((s = (ademco_contactid_sender_state_t *) malloc(sizeof (*s))) == NULL)
@ -1094,10 +1091,11 @@ SPAN_DECLARE(ademco_contactid_sender_state_t *) ademco_contactid_sender_init(ade
span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
span_log_set_protocol(&s->logging, "Ademco");
if (!initialised)
if (!tone_rx_init)
{
make_goertzel_descriptor(&tone_1400_desc, 1400.0f, GOERTZEL_SAMPLES_PER_BLOCK);
make_goertzel_descriptor(&tone_2300_desc, 2300.0f, GOERTZEL_SAMPLES_PER_BLOCK);
tone_rx_init = TRUE;
}
goertzel_init(&s->tone_1400, &tone_1400_desc);
goertzel_init(&s->tone_2300, &tone_2300_desc);

View File

@ -62,6 +62,8 @@
#define DEFAULT_DTMF_TX_ON_TIME 50
#define DEFAULT_DTMF_TX_OFF_TIME 55
#define DTMF_SAMPLES_PER_BLOCK 102
#if defined(SPANDSP_USE_FIXED_POINT)
#define DTMF_THRESHOLD 10438 /* -42dBm0 */
#define DTMF_NORMAL_TWIST 6.309f /* 8dB */
@ -70,16 +72,14 @@
#define DTMF_RELATIVE_PEAK_COL 6.309f /* 8dB */
#define DTMF_TO_TOTAL_ENERGY 83.868f /* -0.85dB */
#define DTMF_POWER_OFFSET 68.251f /* 10*log(256.0*256.0*DTMF_SAMPLES_PER_BLOCK) */
#define DTMF_SAMPLES_PER_BLOCK 102
#else
#define DTMF_THRESHOLD 171032462.0f /* -42dBm0 [((DTMF_SAMPLES_PER_BLOCK*32768.0/1.4142)*10^((-42 - DBM0_MAX_SINE_POWER)/20.0))^2 => 171032462.0] */
#define DTMF_THRESHOLD 171032462.0f /* -42dBm0 [((DTMF_SAMPLES_PER_BLOCK*32768.0/1.4142)*10^((-42 - DBM0_MAX_SINE_POWER)/20.0))^2] */
#define DTMF_NORMAL_TWIST 6.309f /* 8dB [10^(8/10) => 6.309] */
#define DTMF_REVERSE_TWIST 2.512f /* 4dB */
#define DTMF_RELATIVE_PEAK_ROW 6.309f /* 8dB */
#define DTMF_RELATIVE_PEAK_COL 6.309f /* 8dB */
#define DTMF_TO_TOTAL_ENERGY 83.868f /* -0.85dB [DTMF_SAMPLES_PER_BLOCK*10^(-0.85/10.0)] */
#define DTMF_POWER_OFFSET 110.395f /* 10*log(32768.0*32768.0*DTMF_SAMPLES_PER_BLOCK) */
#define DTMF_SAMPLES_PER_BLOCK 102
#endif
static const float dtmf_row[] =
@ -93,6 +93,7 @@ static const float dtmf_col[] =
static const char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
static int dtmf_rx_inited = FALSE;
static goertzel_descriptor_t dtmf_detect_row[4];
static goertzel_descriptor_t dtmf_detect_col[4];
@ -409,7 +410,6 @@ SPAN_DECLARE(dtmf_rx_state_t *) dtmf_rx_init(dtmf_rx_state_t *s,
void *user_data)
{
int i;
static int initialised = FALSE;
if (s == NULL)
{
@ -431,14 +431,14 @@ SPAN_DECLARE(dtmf_rx_state_t *) dtmf_rx_init(dtmf_rx_state_t *s,
s->in_digit = 0;
s->last_hit = 0;
if (!initialised)
if (!dtmf_rx_inited)
{
for (i = 0; i < 4; i++)
{
make_goertzel_descriptor(&dtmf_detect_row[i], dtmf_row[i], DTMF_SAMPLES_PER_BLOCK);
make_goertzel_descriptor(&dtmf_detect_col[i], dtmf_col[i], DTMF_SAMPLES_PER_BLOCK);
}
initialised = TRUE;
dtmf_rx_inited = TRUE;
}
for (i = 0; i < 4; i++)
{

View File

@ -52,8 +52,10 @@ struct t30_state_s
int supported_modems;
/*! \brief A bit mask of the currently supported image compression modes. */
int supported_compressions;
/*! \brief A bit mask of the currently supported image resolutions. */
int supported_resolutions;
/*! \brief A bit mask of the currently supported bi-level image resolutions. */
int supported_bilevel_resolutions;
/*! \brief A bit mask of the currently supported colour image resolutions. */
int supported_colour_resolutions;
/*! \brief A bit mask of the currently supported image sizes. */
int supported_image_sizes;
/*! \brief A bit mask of the currently supported T.30 special features. */
@ -218,6 +220,12 @@ struct t30_state_s
/*! \brief TRUE if a local T.30 interrupt is pending. */
int local_interrupt_pending;
/*! \brief The common ground in compression schemes between the local and far ends. */
int mutual_compressions;
/*! \brief The common group supported bi-level image resolutions. */
int mutual_bilevel_resolutions;
/*! \brief The common group supported colour image resolutions. */
int mutual_colour_resolutions;
/*! \brief The image coding to be used on the line for non-bilevel images. */
int multilevel_line_encoding;
/*! \brief The image coding being used on the line. */

View File

@ -33,6 +33,7 @@ struct v18_state_s
int mode;
put_msg_func_t put_msg;
void *user_data;
int repeat_shifts;
union
{
@ -46,6 +47,7 @@ struct v18_state_s
async_tx_state_t asynctx;
int baudot_tx_shift;
int tx_signal_on;
uint8_t next_byte;
int byte_no;
fsk_rx_state_t fskrx;
@ -56,7 +58,7 @@ struct v18_state_s
int rx_msg_len;
int bit_pos;
int in_progress;
int repeat_shifts;
int rx_suppression;
/*! \brief Error and flow logging control */
logging_state_t logging;

View File

@ -369,7 +369,7 @@ enum
/*! T.45 run length colour compression */
T30_SUPPORT_COMPRESSION_T45 = 0x80,
/*! T.81 + T.30 Annex E colour JPEG compression */
T30_SUPPORT_COMPRESSION_T81 = 0x100,
T30_SUPPORT_COMPRESSION_T42_T81 = 0x100,
/*! T.81 + T.30 Annex K colour sYCC-JPEG compression */
T30_SUPPORT_COMPRESSION_SYCC_T81 = 0x200,
/*! T.88 monochrome JBIG2 compression */
@ -382,34 +382,37 @@ enum
enum
{
/*! Support standard FAX Y-resolution 98/100dpi */
T30_SUPPORT_STANDARD_RESOLUTION = 0x01,
/*! Support fine FAX Y-resolution 196/200dpi */
T30_SUPPORT_FINE_RESOLUTION = 0x02,
/*! Support super-fine FAX Y-resolution 392/400dpi */
T30_SUPPORT_SUPERFINE_RESOLUTION = 0x04,
/*! Standard FAX resolution 204dpi x 98dpi - bi-level only */
T30_SUPPORT_RESOLUTION_R8_STANDARD = 0x1,
/*! Fine FAX resolution 204dpi x 196dpi - bi-level only */
T30_SUPPORT_RESOLUTION_R8_FINE = 0x2,
/*! Super-fine FAX resolution 204dpi x 391dpi - bi-level only */
T30_SUPPORT_RESOLUTION_R8_SUPERFINE = 0x4,
/*! Double FAX resolution 408dpi x 391dpi - bi-level only */
T30_SUPPORT_RESOLUTION_R16_SUPERFINE = 0x8,
/*! Support half FAX X-resolution 100/102dpi */
T30_SUPPORT_R4_RESOLUTION = 0x10000,
/*! Support standard FAX X-resolution 200/204dpi */
T30_SUPPORT_R8_RESOLUTION = 0x20000,
/*! Support double FAX X-resolution 400dpi */
T30_SUPPORT_R16_RESOLUTION = 0x40000,
/*! Support 300dpi x 300 dpi */
T30_SUPPORT_300_300_RESOLUTION = 0x100000,
/*! Support 400dpi x 400 dpi */
T30_SUPPORT_400_400_RESOLUTION = 0x200000,
/*! Support 600dpi x 600 dpi */
T30_SUPPORT_600_600_RESOLUTION = 0x400000,
/*! Support 1200dpi x 1200 dpi */
T30_SUPPORT_1200_1200_RESOLUTION = 0x800000,
/*! Support 300dpi x 600 dpi */
T30_SUPPORT_300_600_RESOLUTION = 0x1000000,
/*! Support 400dpi x 800 dpi */
T30_SUPPORT_400_800_RESOLUTION = 0x2000000,
/*! Support 600dpi x 1200 dpi */
T30_SUPPORT_600_1200_RESOLUTION = 0x4000000
/*! 100dpi x 100 dpi - gray scale and colour only */
T30_SUPPORT_RESOLUTION_100_100 = 0x10,
/*! 200dpi x 100 dpi - bi-level only */
T30_SUPPORT_RESOLUTION_200_100 = 0x20,
/*! 200dpi x 200 dpi */
T30_SUPPORT_RESOLUTION_200_200 = 0x40,
/*! 200dpi x 400 dpi - bi-level only */
T30_SUPPORT_RESOLUTION_200_400 = 0x80,
/*! 300dpi x 300 dpi */
T30_SUPPORT_RESOLUTION_300_300 = 0x100,
/*! 300dpi x 600 dpi - bi-level only */
T30_SUPPORT_RESOLUTION_300_600 = 0x200,
/*! 400dpi x 400 dpi */
T30_SUPPORT_RESOLUTION_400_400 = 0x400,
/*! 400dpi x 800 dpi - bi-level only */
T30_SUPPORT_RESOLUTION_400_800 = 0x800,
/*! 600dpi x 600 dpi */
T30_SUPPORT_RESOLUTION_600_600 = 0x1000,
/*! 600dpi x 1200 dpi - bi-level only */
T30_SUPPORT_RESOLUTION_600_1200 = 0x2000,
/*! 1200dpi x 1200 dpi */
T30_SUPPORT_RESOLUTION_1200_1200 = 0x4000
};
enum

View File

@ -65,9 +65,9 @@ typedef enum
/*! T.45 run length colour compression */
T4_COMPRESSION_T45 = 7,
/*! T.42 + T.81 + T.30 Annex E colour JPEG coding */
T4_COMPRESSION_T42 = 8,
T4_COMPRESSION_T42_T81 = 8,
/*! T.42 + T.81 + T.30 Annex K colour sYCC-JPEG coding */
T4_COMPRESSION_SYCC_T42 = 9
T4_COMPRESSION_SYCC_T81 = 9
} t4_image_compression_t;
/*! Image type */

View File

@ -1178,22 +1178,24 @@ int t30_build_dis_or_dtc(t30_state_t *s)
/* V.17 is only valid when combined with V.29 and V.27ter, so if we enable V.17 we force the others too. */
if ((s->supported_modems & T30_SUPPORT_V17))
s->local_dis_dtc_frame[4] |= (DISBIT6 | DISBIT4 | DISBIT3);
if ((s->supported_resolutions & T30_SUPPORT_FINE_RESOLUTION))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE);
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T4_2D))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE);
/* 215mm wide is always supported */
if ((s->supported_image_sizes & T30_SUPPORT_303MM_WIDTH))
set_ctrl_bit(s->local_dis_dtc_frame, 18);
else if ((s->supported_image_sizes & T30_SUPPORT_255MM_WIDTH))
set_ctrl_bit(s->local_dis_dtc_frame, 17);
/* A4 is always supported. */
if ((s->supported_image_sizes & T30_SUPPORT_UNLIMITED_LENGTH))
set_ctrl_bit(s->local_dis_dtc_frame, 20);
else if ((s->supported_image_sizes & T30_SUPPORT_B4_LENGTH))
set_ctrl_bit(s->local_dis_dtc_frame, 19);
/* No scan-line padding required, but some may be specified by the application. */
set_ctrl_bits(s->local_dis_dtc_frame, s->local_min_scan_time_code, 21);
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T4_2D))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE);
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_NONE))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_UNCOMPRESSED_CAPABLE);
if (s->ecm_allowed)
@ -1204,21 +1206,29 @@ int t30_build_dis_or_dtc(t30_state_t *s)
also offering the ECM option needed to support them. */
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T6))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE);
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T43))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T43_CAPABLE);
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T45))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T45_CAPABLE);
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T81))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE);
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_SYCC_T81))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_SYCC_T81_CAPABLE);
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T85))
{
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T85_CAPABLE);
/* Bit 79 set with bit 78 clear is invalid, so only check for L0
support here. */
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T85_L0))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T85_L0_CAPABLE);
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T85_CAPABLE);
}
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T42_T81))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE);
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T43))
{
/* Note 25 of table 2/T.30 */
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T43_CAPABLE);
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE);
}
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T45))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T45_CAPABLE);
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_SYCC_T81))
{
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE);
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_SYCC_T81_CAPABLE);
}
//if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T89))
// set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T89_CAPABLE);
@ -1232,14 +1242,6 @@ int t30_build_dis_or_dtc(t30_state_t *s)
/* No plane interleave */
/* No G.726 */
/* No extended voice coding */
if ((s->supported_resolutions & T30_SUPPORT_SUPERFINE_RESOLUTION))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE);
if ((s->supported_resolutions & T30_SUPPORT_300_300_RESOLUTION))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_300_300_CAPABLE);
if ((s->supported_resolutions & (T30_SUPPORT_400_400_RESOLUTION | T30_SUPPORT_R16_RESOLUTION)))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_400_400_CAPABLE);
/* Metric */
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_METRIC_RESOLUTION_PREFERRED);
/* Superfine minimum scan line time pattern follows fine */
if ((s->supported_t30_features & T30_SUPPORT_SELECTIVE_POLLING))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_SELECTIVE_POLLING_CAPABLE);
@ -1281,26 +1283,64 @@ int t30_build_dis_or_dtc(t30_state_t *s)
/* No alternative hashing system number 3 */
/* No T.44 (mixed raster content) */
/* No page length maximum strip size for T.44 (mixed raster content) */
/* No colour/grey scale 300x300 or 400x400 */
/* No colour/grey scale 100x100 */
/* No simple phase C BFT negotiations */
/* No extended BFT negotiations */
if ((s->supported_t30_features & T30_SUPPORT_INTERNET_SELECTIVE_POLLING_ADDRESS))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_INTERNET_SELECTIVE_POLLING_ADDRESS);
if ((s->supported_t30_features & T30_SUPPORT_INTERNET_ROUTING_ADDRESS))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_INTERNET_ROUTING_ADDRESS);
if ((s->supported_resolutions & T30_SUPPORT_600_600_RESOLUTION))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_600_600_CAPABLE);
if ((s->supported_resolutions & T30_SUPPORT_1200_1200_RESOLUTION))
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_1200_1200))
{
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_1200_1200_CAPABLE);
if ((s->supported_resolutions & T30_SUPPORT_300_600_RESOLUTION))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_300_600_CAPABLE);
if ((s->supported_resolutions & T30_SUPPORT_400_800_RESOLUTION))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_400_800_CAPABLE);
if ((s->supported_resolutions & T30_SUPPORT_600_1200_RESOLUTION))
if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_1200_1200))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_1200_1200_CAPABLE);
}
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_600_1200))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_600_1200_CAPABLE);
/* No colour/grey scale 600x600 */
/* No colour/grey scale 1200x1200 */
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_600_600))
{
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_600_600_CAPABLE);
if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_600_600))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_600_600_CAPABLE);
}
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_400_800))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_400_800_CAPABLE);
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_R16_SUPERFINE))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_400_400_CAPABLE);
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_400_400))
{
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_400_400_CAPABLE);
if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_400_400))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_300_300_400_400_CAPABLE);
}
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_300_600))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_300_600_CAPABLE);
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_300_300))
{
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_300_300_CAPABLE);
if ((s->supported_colour_resolutions & T4_RESOLUTION_300_300))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_300_300_400_400_CAPABLE);
}
if ((s->supported_bilevel_resolutions & (T30_SUPPORT_RESOLUTION_200_400 | T30_SUPPORT_RESOLUTION_R8_SUPERFINE)))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE);
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_R8_FINE))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE);
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_200_200))
{
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE);
//if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_200_200))
// set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_???_CAPABLE);
}
/* Standard FAX resolution bi-level image support goes without saying */
if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_100_100))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_100_100_CAPABLE);
if ((s->supported_bilevel_resolutions & (T30_SUPPORT_RESOLUTION_R8_STANDARD | T30_SUPPORT_RESOLUTION_R8_FINE | T30_SUPPORT_RESOLUTION_R8_SUPERFINE | T30_SUPPORT_RESOLUTION_R16_SUPERFINE)))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED);
if ((s->supported_bilevel_resolutions & (T30_SUPPORT_RESOLUTION_200_100 | T30_SUPPORT_RESOLUTION_200_200 | T30_SUPPORT_RESOLUTION_200_400 | T30_SUPPORT_RESOLUTION_300_300 | T30_SUPPORT_RESOLUTION_300_600 | T30_SUPPORT_RESOLUTION_400_400 | T30_SUPPORT_RESOLUTION_400_800 | T30_SUPPORT_RESOLUTION_600_600 | T30_SUPPORT_RESOLUTION_600_1200 | T30_SUPPORT_RESOLUTION_1200_1200)))
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_METRIC_RESOLUTION_PREFERRED);
/* No double sided printing (alternate mode) */
/* No double sided printing (continuous mode) */
/* No black and white mixed raster content profile */
@ -1370,7 +1410,7 @@ static int build_dcs(t30_state_t *s)
/* Select the compression to use. */
switch (s->line_encoding)
{
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, 21);
break;
@ -1413,17 +1453,17 @@ static int build_dcs(t30_state_t *s)
case T4_Y_RESOLUTION_1200:
switch (s->x_resolution)
{
case T4_X_RESOLUTION_600:
if ((s->supported_resolutions & T30_SUPPORT_600_1200_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_1200_CAPABLE))
case T4_X_RESOLUTION_1200:
if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_1200_1200))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_1200);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_1200_1200);
bad = T30_ERR_OK;
}
break;
case T4_X_RESOLUTION_1200:
if ((s->supported_resolutions & T30_SUPPORT_1200_1200_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_1200_1200_CAPABLE))
case T4_X_RESOLUTION_600:
if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_600_1200))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_1200_1200);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_1200);
bad = T30_ERR_OK;
}
break;
@ -1433,7 +1473,7 @@ 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) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_400_800_CAPABLE))
if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_400_800))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_800);
bad = T30_ERR_OK;
@ -1444,17 +1484,17 @@ static int build_dcs(t30_state_t *s)
case T4_Y_RESOLUTION_600:
switch (s->x_resolution)
{
case T4_X_RESOLUTION_300:
if ((s->supported_resolutions & T30_SUPPORT_300_600_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_600_CAPABLE))
case T4_X_RESOLUTION_600:
if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_600_600))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_600);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_600);
bad = T30_ERR_OK;
}
break;
case T4_X_RESOLUTION_600:
if ((s->supported_resolutions & T30_SUPPORT_600_600_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_600_CAPABLE))
case T4_X_RESOLUTION_300:
if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_300_600))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_600);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_600);
bad = T30_ERR_OK;
}
break;
@ -1464,7 +1504,7 @@ 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) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_300_CAPABLE))
if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_300_300))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_300);
bad = T30_ERR_OK;
@ -1473,15 +1513,37 @@ static int build_dcs(t30_state_t *s)
}
break;
case T4_Y_RESOLUTION_SUPERFINE:
if ((s->supported_resolutions & T30_SUPPORT_SUPERFINE_RESOLUTION))
case T4_Y_RESOLUTION_400:
if (s->x_resolution == T4_X_RESOLUTION_400 && s->y_resolution == T4_Y_RESOLUTION_400)
{
if (s->x_resolution == T4_X_RESOLUTION_R16 && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_400_400_CAPABLE))
if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_400_400))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
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))
}
else if (s->x_resolution == T4_X_RESOLUTION_R16 && s->y_resolution == T4_Y_RESOLUTION_SUPERFINE)
{
if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_R16_SUPERFINE))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
bad = T30_ERR_OK;
break;
}
}
else if (s->x_resolution == T4_X_RESOLUTION_200 && s->y_resolution == T4_Y_RESOLUTION_400)
{
if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_200_400))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
bad = T30_ERR_OK;
break;
}
}
else if (s->x_resolution == T4_X_RESOLUTION_R8 && s->y_resolution == T4_Y_RESOLUTION_SUPERFINE)
{
if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_R8_SUPERFINE))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
bad = T30_ERR_OK;
@ -1491,24 +1553,38 @@ static int build_dcs(t30_state_t *s)
row_squashing_ratio <<= 1;
/* Fall through */
case T4_Y_RESOLUTION_FINE:
if ((s->supported_resolutions & T30_SUPPORT_FINE_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE))
case T4_Y_RESOLUTION_200:
if (s->x_resolution == T4_X_RESOLUTION_200 && s->y_resolution == T4_Y_RESOLUTION_200)
{
switch (s->x_resolution)
if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_200_200))
{
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
bad = T30_ERR_OK;
break;
}
}
else if (s->x_resolution == T4_X_RESOLUTION_R8 && s->y_resolution == T4_Y_RESOLUTION_FINE)
{
if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_R8_FINE))
{
case T4_X_RESOLUTION_R8:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
bad = T30_ERR_OK;
break;
}
break;
}
row_squashing_ratio <<= 1;
/* Fall through */
default:
case T4_Y_RESOLUTION_STANDARD:
switch (s->x_resolution)
case T4_Y_RESOLUTION_100:
if (s->x_resolution == T4_X_RESOLUTION_R8 && s->y_resolution == T4_Y_RESOLUTION_STANDARD)
{
/* No bits to set for this */
bad = T30_ERR_OK;
break;
}
else if (s->x_resolution == T4_X_RESOLUTION_200 && s->y_resolution == T4_Y_RESOLUTION_100)
{
case T4_X_RESOLUTION_R8:
/* No bits to set for this */
bad = T30_ERR_OK;
break;
@ -1528,11 +1604,11 @@ static int build_dcs(t30_state_t *s)
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. */
if (((s->image_width == T4_WIDTH_R8_A4) && (s->x_resolution == T4_X_RESOLUTION_R8))
if (((s->image_width == T4_WIDTH_200_A4) && (s->x_resolution == T4_X_RESOLUTION_200 || 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_400_A4) && (s->x_resolution == T4_X_RESOLUTION_400 || s->x_resolution == T4_X_RESOLUTION_R16))
||
((s->image_width == T4_WIDTH_600_A4) && (s->x_resolution == T4_X_RESOLUTION_600))
||
@ -1541,15 +1617,15 @@ static int build_dcs(t30_state_t *s)
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A4\n");
/* No width related bits need to be set. */
}
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)))
else if (((s->image_width == T4_WIDTH_200_B4) && (s->x_resolution == T4_X_RESOLUTION_200 || 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_400_B4) && (s->x_resolution == T4_X_RESOLUTION_400 || 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)
&&
@ -1564,15 +1640,15 @@ static int build_dcs(t30_state_t *s)
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)))
else if (((s->image_width == T4_WIDTH_200_A3) && (s->x_resolution == T4_X_RESOLUTION_200 || 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_400_A3) && (s->x_resolution == T4_X_RESOLUTION_400 || 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)
&&
@ -1618,6 +1694,7 @@ static int build_dcs(t30_state_t *s)
if ((s->iaf & T30_IAF_MODE_FLOW_CONTROL) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T38_FLOW_CONTROL_CAPABLE))
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T38_FLOW_CONTROL_CAPABLE);
if ((s->iaf & T30_IAF_MODE_CONTINUOUS_FLOW) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T38_FAX_CAPABLE))
{
/* Clear the modem type bits, in accordance with note 77 of Table 2/T.30 */
@ -1984,7 +2061,11 @@ static int start_sending_document(t30_state_t *s)
t4_tx_set_header_tz(&s->t4.tx, &s->tz);
if (tx_start_page(s))
{
span_log(&s->logging, SPAN_LOG_WARNING, "Something seems to be wrong in the file\n");
t30_set_status(s, T30_ERR_FILEERROR);
return -1;
}
s->x_resolution = t4_tx_get_x_resolution(&s->t4.tx);
s->y_resolution = t4_tx_get_y_resolution(&s->t4.tx);
@ -2082,63 +2163,119 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
s->error_correcting_mode = (s->ecm_allowed && (s->far_dis_dtc_frame[6] & DISBIT3) != 0);
/* 256 octets per ECM frame */
s->octets_per_ecm_frame = 256;
/* Now we know if we are going to use ECM, select the compression to use. */
/* Now we know if we are going to use ECM, select the compressions which we can use. */
s->mutual_compressions = s->supported_compressions;
if (!s->error_correcting_mode)
{
/* Without error correction our choices are very limited */
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T4_2D)
&&
test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE))
{
s->line_encoding = T4_COMPRESSION_T4_2D;
}
else
{
s->line_encoding = T4_COMPRESSION_T4_1D;
}
/* Remove any compression schemes which need error correction to work. */
s->mutual_compressions &= (0xF0000000 | T30_SUPPORT_COMPRESSION_NONE | T30_SUPPORT_COMPRESSION_T4_1D | T30_SUPPORT_COMPRESSION_T4_2D);
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE))
s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T4_2D;
}
else
{
#if defined(SPANDSP_SUPPORT_T42x) || defined(SPANDSP_SUPPORT_T43)
/* With error correction colour may be possible/required */
if ((0 & (T30_SUPPORT_COMPRESSION_T43 | T30_SUPPORT_COMPRESSION_T45 | T30_SUPPORT_COMPRESSION_T81 | T30_SUPPORT_COMPRESSION_SYCC_T81)))
{
s->line_encoding = T4_COMPRESSION_T85_L0;
}
else
#endif
{
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T85_L0)
&&
test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_L0_CAPABLE))
{
s->line_encoding = T4_COMPRESSION_T85_L0;
}
else if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T85)
&&
test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_CAPABLE))
{
s->line_encoding = T4_COMPRESSION_T85;
}
else if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T6)
&&
test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE))
{
s->line_encoding = T4_COMPRESSION_T6;
}
else if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T4_2D)
&&
test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE))
{
s->line_encoding = T4_COMPRESSION_T4_2D;
}
else
{
s->line_encoding = T4_COMPRESSION_T4_1D;
}
}
/* Check the bi-level capabilities */
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE))
s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T4_2D;
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE))
s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T6;
/* T.85 L0 capable without T.85 capable is an invalid combination, so let
just zap both capabilities if the far end is not T.85 capable. */
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_CAPABLE))
s->mutual_compressions &= ~(T30_SUPPORT_COMPRESSION_T85 | T30_SUPPORT_COMPRESSION_T85_L0);
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_L0_CAPABLE))
s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T85_L0;
}
/* Choose a compression scheme from amongst those mutually available */
if ((s->mutual_compressions & T30_SUPPORT_COMPRESSION_T85_L0))
s->line_encoding = T4_COMPRESSION_T85_L0;
else if ((s->mutual_compressions & T30_SUPPORT_COMPRESSION_T85))
s->line_encoding = T4_COMPRESSION_T85;
else if ((s->mutual_compressions & T30_SUPPORT_COMPRESSION_T6))
s->line_encoding = T4_COMPRESSION_T6;
else if ((s->mutual_compressions & T30_SUPPORT_COMPRESSION_T4_2D))
s->line_encoding = T4_COMPRESSION_T4_2D;
else
s->line_encoding = T4_COMPRESSION_T4_1D;
span_log(&s->logging, SPAN_LOG_FLOW, "Choose compression %s (%d)\n", t4_encoding_to_str(s->line_encoding), s->line_encoding);
s->mutual_bilevel_resolutions = s->supported_bilevel_resolutions;
s->mutual_colour_resolutions = s->supported_colour_resolutions;
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_1200_1200_CAPABLE))
{
s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_1200_1200;
s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_1200_1200;
}
else
{
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_1200_1200_CAPABLE))
s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_1200_1200;
}
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_1200_CAPABLE))
s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_600_1200;
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_600_CAPABLE))
{
s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_600_600;
s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_600_600;
}
else
{
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_600_600_CAPABLE))
s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_600_600;
}
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_400_800_CAPABLE))
s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_400_800;
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_400_400_CAPABLE))
{
s->mutual_bilevel_resolutions &= ~(T30_SUPPORT_RESOLUTION_400_400 | T30_SUPPORT_RESOLUTION_R16_SUPERFINE);
s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_400_400;
}
else
{
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_300_300_400_400_CAPABLE))
s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_400_400;
}
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_600_CAPABLE))
s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_300_600;
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_300_CAPABLE))
{
s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_300_300;
s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_300_300;
}
else
{
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_300_300_400_400_CAPABLE))
s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_300_300;
}
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE))
{
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED))
s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_200_400;
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_METRIC_RESOLUTION_PREFERRED))
s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_R8_SUPERFINE;
}
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE))
{
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED))
s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_200_200;
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_METRIC_RESOLUTION_PREFERRED))
s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_R8_FINE;
s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_200_200;
}
else
{
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED))
s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_200_200;
}
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED))
s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_200_100;
/* Never suppress T30_SUPPORT_RESOLUTION_R8_STANDARD */
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_100_100_CAPABLE))
s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_100_100;
switch (s->far_dis_dtc_frame[4] & (DISBIT6 | DISBIT5 | DISBIT4 | DISBIT3))
{
case (DISBIT6 | DISBIT4 | DISBIT3):
@ -2192,60 +2329,7 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
return -1;
}
}
#if 0
/* T.4 1D is always available */
bi_level_support = T30_SUPPORT_COMPRESSION_T4_1D;
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE))
bi_level_support |= T30_SUPPORT_COMPRESSION_T4_2D;
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE))
bi_level_support |= T30_SUPPORT_COMPRESSION_T6;
/* Bit 79 set with bit 78 clear is invalid, so let's completely ignore 79
if 78 is clear. */
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_CAPABLE))
{
bi_level_support |= T30_SUPPORT_COMPRESSION_T85;
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_L0_CAPABLE)
bi_level_support |= T30_SUPPORT_COMPRESSION_T85_L0;
}
gray_support = 0;
colour_support = 0;
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE))
{
/* Multi-level coding available */
gray_support |= T30_SUPPORT_COMPRESSION_T81;
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE))
gray_support |= T30_SUPPORT_COMPRESSION_T81_12BIT;
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T43_CAPABLE))
{
gray_support |= T30_SUPPORT_COMPRESSION_T43;
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE))
gray_support |= T30_SUPPORT_COMPRESSION_T43_12BIT;
}
if (test_ctrl_bit(s->far_dis_dtc_frame, bit69))
{
/* Colour coding available */
colour_support |= T30_SUPPORT_COMPRESSION_T81;
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE))
colour_support |= T30_SUPPORT_COMPRESSION_T81_12BIT;
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING))
{
colour_support |= T30_SUPPORT_COMPRESSION_T81_SUBSAMPLING;
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE))
colour_support |= T30_SUPPORT_COMPRESSION_T81_SUBSAMPLING_12BIT;
}
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T43_CAPABLE))
{
colour_support |= T30_SUPPORT_COMPRESSION_T43;
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE))
colour_support |= T30_SUPPORT_COMPRESSION_T43_12BIT;
}
}
/* bit74 custom illuminant */
/* bit75 custom gamut range */
}
#endif
queue_phase(s, T30_PHASE_B_TX);
/* Try to send something */
if (s->tx_file[0])
@ -2310,10 +2394,10 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{
static const int widths[6][4] =
{
{ T4_WIDTH_R4_A4, T4_WIDTH_R4_B4, T4_WIDTH_R4_A3, -1}, /* R4 resolution - no longer used in recent versions of T.30 */
{ T4_WIDTH_R8_A4, T4_WIDTH_R8_B4, T4_WIDTH_R8_A3, -1}, /* R8 resolution */
{ T4_WIDTH_100_A4, T4_WIDTH_100_B4, T4_WIDTH_100_A3, -1}, /* 100/inch */
{ T4_WIDTH_200_A4, T4_WIDTH_200_B4, T4_WIDTH_200_A3, -1}, /* 200/inch / R8 resolution */
{ T4_WIDTH_300_A4, T4_WIDTH_300_B4, T4_WIDTH_300_A3, -1}, /* 300/inch resolution */
{ T4_WIDTH_R16_A4, T4_WIDTH_R16_B4, T4_WIDTH_R16_A3, -1}, /* R16 resolution */
{ T4_WIDTH_400_A4, T4_WIDTH_400_B4, T4_WIDTH_400_A3, -1}, /* 400/inch / R16 resolution */
{ T4_WIDTH_600_A4, T4_WIDTH_600_B4, T4_WIDTH_600_A3, -1}, /* 600/inch resolution */
{T4_WIDTH_1200_A4, T4_WIDTH_1200_B4, T4_WIDTH_1200_A3, -1} /* 1200/inch resolution */
};
@ -2353,93 +2437,221 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
s->x_resolution = -1;
s->y_resolution = -1;
//s->current_page_resolution = 0;
x = -1;
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_1200_1200))
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE))
{
if ((s->supported_resolutions & T30_SUPPORT_1200_1200_RESOLUTION))
/* Gray scale or colour image */
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_COLOUR_GRAY_1200_1200))
{
s->x_resolution = T4_X_RESOLUTION_1200;
s->y_resolution = T4_Y_RESOLUTION_1200;
x = 5;
if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_1200_1200))
{
s->x_resolution = T4_X_RESOLUTION_1200;
s->y_resolution = T4_Y_RESOLUTION_1200;
//s->current_page_resolution = T4_RESOLUTION_1200_1200;
x = 5;
}
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_1200))
{
if ((s->supported_resolutions & T30_SUPPORT_600_1200_RESOLUTION))
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_COLOUR_GRAY_600_600))
{
s->x_resolution = T4_X_RESOLUTION_600;
s->y_resolution = T4_Y_RESOLUTION_1200;
x = 4;
if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_600_600))
{
s->x_resolution = T4_X_RESOLUTION_600;
s->y_resolution = T4_Y_RESOLUTION_600;
//s->current_page_resolution = T4_RESOLUTION_600_600;
x = 4;
}
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_600))
{
if ((s->supported_resolutions & T30_SUPPORT_600_600_RESOLUTION))
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_400))
{
s->x_resolution = T4_X_RESOLUTION_600;
s->y_resolution = T4_Y_RESOLUTION_600;
x = 4;
if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_400_400))
{
s->x_resolution = T4_X_RESOLUTION_400;
s->y_resolution = T4_Y_RESOLUTION_400;
//s->current_page_resolution = T4_RESOLUTION_400_400;
x = 3;
}
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_800))
{
if ((s->supported_resolutions & T30_SUPPORT_400_800_RESOLUTION))
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_300))
{
s->x_resolution = T4_X_RESOLUTION_R16;
s->y_resolution = T4_Y_RESOLUTION_800;
x = 3;
if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_300_300))
{
s->x_resolution = T4_X_RESOLUTION_300;
s->y_resolution = T4_Y_RESOLUTION_300;
//s->current_page_resolution = T4_RESOLUTION_300_300;
x = 2;
}
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_400))
{
if ((s->supported_resolutions & T30_SUPPORT_400_400_RESOLUTION))
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_200_200))
{
s->x_resolution = T4_X_RESOLUTION_R16;
s->y_resolution = T4_Y_RESOLUTION_SUPERFINE;
x = 3;
if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_200_200))
{
s->x_resolution = T4_X_RESOLUTION_200;
s->y_resolution = T4_Y_RESOLUTION_200;
//s->current_page_resolution = T4_RESOLUTION_200_200;
x = 1;
}
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_600))
{
if ((s->supported_resolutions & T30_SUPPORT_300_600_RESOLUTION))
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_COLOUR_GRAY_100_100))
{
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))
{
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))
{
if ((s->supported_resolutions & T30_SUPPORT_FINE_RESOLUTION))
{
s->x_resolution = T4_X_RESOLUTION_R8;
s->y_resolution = T4_Y_RESOLUTION_FINE;
x = 1;
if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_100_100))
{
s->x_resolution = T4_X_RESOLUTION_100;
s->y_resolution = T4_Y_RESOLUTION_100;
//s->current_page_resolution = T4_RESOLUTION_100_100;
x = 0;
}
}
}
else
{
s->x_resolution = T4_X_RESOLUTION_R8;
s->y_resolution = T4_Y_RESOLUTION_STANDARD;
x = 1;
/* Bi-level image */
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_1200_1200))
{
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_1200_1200))
{
s->x_resolution = T4_X_RESOLUTION_1200;
s->y_resolution = T4_Y_RESOLUTION_1200;
//s->current_page_resolution = T4_RESOLUTION_1200_1200;
x = 5;
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_1200))
{
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_600_1200))
{
s->x_resolution = T4_X_RESOLUTION_600;
s->y_resolution = T4_Y_RESOLUTION_1200;
//s->current_page_resolution = T4_RESOLUTION_600_1200;
x = 4;
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_600))
{
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_600_600))
{
s->x_resolution = T4_X_RESOLUTION_600;
s->y_resolution = T4_Y_RESOLUTION_600;
//s->current_page_resolution = T4_RESOLUTION_600_600;
x = 4;
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_800))
{
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_400_800))
{
s->x_resolution = T4_X_RESOLUTION_400;
s->y_resolution = T4_Y_RESOLUTION_800;
//s->current_page_resolution = T4_RESOLUTION_400_800;
x = 3;
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_400))
{
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_INCH_RESOLUTION))
{
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_400_400))
{
s->x_resolution = T4_X_RESOLUTION_400;
s->y_resolution = T4_Y_RESOLUTION_400;
//s->current_page_resolution = T4_RESOLUTION_400_400;
x = 3;
}
}
else
{
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_R16_SUPERFINE))
{
s->x_resolution = T4_X_RESOLUTION_R16;
s->y_resolution = T4_Y_RESOLUTION_SUPERFINE;
//s->current_page_resolution = T4_RESOLUTION_R16_SUPERFINE;
x = 3;
}
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_600))
{
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_300_600))
{
s->x_resolution = T4_X_RESOLUTION_300;
s->y_resolution = T4_Y_RESOLUTION_600;
//s->current_page_resolution = T4_RESOLUTION_300_600;
x = 2;
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_300))
{
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_300_300))
{
s->x_resolution = T4_X_RESOLUTION_300;
s->y_resolution = T4_Y_RESOLUTION_300;
//s->current_page_resolution = T4_RESOLUTION_300_300;
x = 2;
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_200_400))
{
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_INCH_RESOLUTION))
{
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_200_400))
{
s->x_resolution = T4_X_RESOLUTION_200;
s->y_resolution = T4_Y_RESOLUTION_400;
//s->current_page_resolution = T4_RESOLUTION_200_400;
x = 1;
}
}
else
{
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_R8_SUPERFINE))
{
s->x_resolution = T4_X_RESOLUTION_R8;
s->y_resolution = T4_Y_RESOLUTION_SUPERFINE;
//s->current_page_resolution = T4_RESOLUTION_R8_SUPERFINE;
x = 1;
}
}
}
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_200_200))
{
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_INCH_RESOLUTION))
{
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_200_200))
{
s->x_resolution = T4_X_RESOLUTION_200;
s->y_resolution = T4_Y_RESOLUTION_200;
//s->current_page_resolution = T4_RESOLUTION_200_200;
x = 1;
}
}
else
{
if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_R8_FINE))
{
s->x_resolution = T4_X_RESOLUTION_R8;
s->y_resolution = T4_Y_RESOLUTION_FINE;
//s->current_page_resolution = T4_RESOLUTION_R8_FINE;
x = 1;
}
}
}
else
{
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_INCH_RESOLUTION))
{
s->x_resolution = T4_X_RESOLUTION_200;
s->y_resolution = T4_Y_RESOLUTION_100;
//s->current_page_resolution = T4_RESOLUTION_200_100;
x = 1;
}
else
{
s->x_resolution = T4_X_RESOLUTION_R8;
s->y_resolution = T4_Y_RESOLUTION_STANDARD;
//s->current_page_resolution = T4_RESOLUTION_R8_STANDARD;
x = 1;
}
}
}
if (x < 0)
@ -2454,7 +2666,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
#if defined(SPANDSP_SUPPORT_T42)
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE))
{
s->line_encoding = T4_COMPRESSION_T42;
s->line_encoding = T4_COMPRESSION_T42_T81;
}
else
#endif
@ -3693,8 +3905,7 @@ static void process_state_r(t30_state_t *s, const uint8_t *msg, int len)
process_rx_dcs(s, msg, len);
break;
case T30_DCN:
/* Received a DCN while waiting for a DIS */
t30_set_status(s, T30_ERR_TX_GOTDCN);
t30_set_status(s, T30_ERR_RX_DCNWHY);
disconnect(s);
break;
case T30_CRP:
@ -3722,7 +3933,7 @@ static void process_state_t(t30_state_t *s, const uint8_t *msg, int len)
process_rx_dis_dtc(s, msg, len);
break;
case T30_DCN:
t30_set_status(s, T30_ERR_RX_DCNWHY);
t30_set_status(s, T30_ERR_TX_GOTDCN);
disconnect(s);
break;
case T30_CRP:
@ -6420,10 +6631,9 @@ SPAN_DECLARE(t30_state_t *) t30_init(t30_state_t *s,
/* Default to the basic modems. */
s->supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17;
s->supported_compressions = T30_SUPPORT_COMPRESSION_T4_1D | T30_SUPPORT_COMPRESSION_T4_2D;
s->supported_resolutions = T30_SUPPORT_STANDARD_RESOLUTION
| T30_SUPPORT_FINE_RESOLUTION
| T30_SUPPORT_SUPERFINE_RESOLUTION
| T30_SUPPORT_R8_RESOLUTION;
s->supported_bilevel_resolutions = T30_SUPPORT_RESOLUTION_R8_STANDARD
| T30_SUPPORT_RESOLUTION_R8_FINE
| T30_SUPPORT_RESOLUTION_R8_SUPERFINE;
s->supported_image_sizes = T30_SUPPORT_US_LETTER_LENGTH
| T30_SUPPORT_US_LEGAL_LENGTH
| T30_SUPPORT_UNLIMITED_LENGTH

View File

@ -693,20 +693,18 @@ SPAN_DECLARE(int) t30_set_supported_modems(t30_state_t *s, int supported_modems)
SPAN_DECLARE(int) t30_set_supported_compressions(t30_state_t *s, int supported_compressions)
{
int mask;
/* Mask out the ones we actually support today. */
mask = T30_SUPPORT_COMPRESSION_T4_1D
| T30_SUPPORT_COMPRESSION_T4_2D
| T30_SUPPORT_COMPRESSION_T6
//| T30_SUPPORT_COMPRESSION_T81
supported_compressions &= T30_SUPPORT_COMPRESSION_T4_1D
| T30_SUPPORT_COMPRESSION_T4_2D
| T30_SUPPORT_COMPRESSION_T6
//| T30_SUPPORT_COMPRESSION_T81
#if defined(SPANDSP_SUPPORT_T43)
| T30_SUPPORT_COMPRESSION_T43
| T30_SUPPORT_COMPRESSION_T43
#endif
| T30_SUPPORT_COMPRESSION_T85
| T30_SUPPORT_COMPRESSION_T85_L0
| 0;
s->supported_compressions = supported_compressions & mask;
| T30_SUPPORT_COMPRESSION_T85
| T30_SUPPORT_COMPRESSION_T85_L0
| 0;
s->supported_compressions = supported_compressions;
t30_build_dis_or_dtc(s);
return 0;
}
@ -714,7 +712,7 @@ SPAN_DECLARE(int) t30_set_supported_compressions(t30_state_t *s, int supported_c
SPAN_DECLARE(int) t30_set_supported_resolutions(t30_state_t *s, int supported_resolutions)
{
s->supported_resolutions = supported_resolutions;
s->supported_bilevel_resolutions = supported_resolutions;
t30_build_dis_or_dtc(s);
return 0;
}

View File

@ -97,18 +97,18 @@ SPAN_DECLARE(const char *) t4_encoding_to_str(int encoding)
return "T.4 2-D";
case T4_COMPRESSION_T6:
return "T.6";
case T4_COMPRESSION_T42:
return "T.42";
case T4_COMPRESSION_SYCC_T42:
return "sYCC T.42";
case T4_COMPRESSION_T43:
return "T.43";
case T4_COMPRESSION_T45:
return "T.45";
case T4_COMPRESSION_T85:
return "T.85";
case T4_COMPRESSION_T85_L0:
return "T.85(L0)";
case T4_COMPRESSION_T42_T81:
return "T.81";
case T4_COMPRESSION_SYCC_T81:
return "sYCC T.81";
case T4_COMPRESSION_T43:
return "T.43";
case T4_COMPRESSION_T45:
return "T.45";
}
return "???";
}
@ -171,7 +171,7 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
output_compression = COMPRESSION_CCITT_T6;
break;
#if defined(SPANDSP_SUPPORT_T42)
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
output_compression = COMPRESSION_JPEG;
bits_per_sample = 8;
samples_per_pixel = 3;
@ -299,7 +299,7 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
case T4_COMPRESSION_T6:
image_length = t4_t6_decode_get_image_length(&s->decoder.t4_t6);
break;
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
image_length = t42_decode_get_image_length(&s->decoder.t42);
break;
#if defined(SPANDSP_SUPPORT_T43)
@ -454,7 +454,7 @@ SPAN_DECLARE(int) t4_rx_put(t4_rx_state_t *s, const uint8_t buf[], size_t len)
case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T6:
return t4_t6_decode_put(&s->decoder.t4_t6, buf, len);
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
return t42_decode_put(&s->decoder.t42, buf, len);
#if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43:
@ -529,10 +529,10 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int encoding)
}
s->line_encoding = encoding;
return t4_t6_decode_set_encoding(&s->decoder.t4_t6, encoding);
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
switch (s->line_encoding)
{
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
break;
default:
t42_decode_init(&s->decoder.t42, s->row_handler, s->row_handler_user_data);
@ -599,7 +599,7 @@ SPAN_DECLARE(int) t4_rx_set_row_write_handler(t4_rx_state_t *s, t4_row_write_han
case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T6:
return t4_t6_decode_set_row_write_handler(&s->decoder.t4_t6, handler, user_data);
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
return t42_decode_set_row_write_handler(&s->decoder.t42, handler, user_data);
#if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43:
@ -638,7 +638,7 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t
t->bad_rows = s->decoder.t4_t6.bad_rows;
t->longest_bad_row_run = s->decoder.t4_t6.longest_bad_row_run;
break;
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
t->type = 0;
t->width = t42_decode_get_image_width(&s->decoder.t42);
t->length = t42_decode_get_image_length(&s->decoder.t42);
@ -683,7 +683,7 @@ SPAN_DECLARE(int) t4_rx_start_page(t4_rx_state_t *s)
case T4_COMPRESSION_T6:
t4_t6_decode_restart(&s->decoder.t4_t6, s->image_width);
break;
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
t42_decode_restart(&s->decoder.t42);
break;
#if defined(SPANDSP_SUPPORT_T43)
@ -740,7 +740,7 @@ SPAN_DECLARE(int) t4_rx_end_page(t4_rx_state_t *s)
t4_t6_decode_put(&s->decoder.t4_t6, NULL, 0);
length = t4_t6_decode_get_image_length(&s->decoder.t4_t6);
break;
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
t42_decode_put(&s->decoder.t42, NULL, 0);
length = t42_decode_get_image_length(&s->decoder.t42);
break;
@ -840,7 +840,7 @@ SPAN_DECLARE(int) t4_rx_release(t4_rx_state_t *s)
case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T6:
return t4_t6_decode_release(&s->decoder.t4_t6);
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
return t42_decode_release(&s->decoder.t42);
#if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43:

View File

@ -642,7 +642,7 @@ static int set_row_read_handler(t4_tx_state_t *s, t4_row_read_handler_t handler,
case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T6:
return t4_t6_encode_set_row_read_handler(&s->encoder.t4_t6, handler, user_data);
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
return t42_encode_set_row_read_handler(&s->encoder.t42, handler, user_data);
#if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43:
@ -812,10 +812,10 @@ SPAN_DECLARE(int) t4_tx_set_tx_encoding(t4_tx_state_t *s, int encoding)
}
s->line_encoding = encoding;
return t4_t6_encode_set_encoding(&s->encoder.t4_t6, encoding);
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
switch (s->line_encoding)
{
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
break;
default:
t42_encode_init(&s->encoder.t42, s->image_width, s->image_length, s->row_handler, s->row_handler_user_data);
@ -877,7 +877,7 @@ SPAN_DECLARE(void) t4_tx_set_image_width(t4_tx_state_t *s, int image_width)
case T4_COMPRESSION_T6:
t4_t6_encode_set_image_width(&s->encoder.t4_t6, image_width);
break;
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
t42_encode_set_image_width(&s->encoder.t42, image_width);
break;
#if defined(SPANDSP_SUPPORT_T43)
@ -898,7 +898,7 @@ static void t4_tx_set_image_length(t4_tx_state_t *s, int image_length)
s->image_length = image_length;
switch (s->line_encoding)
{
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
t42_encode_set_image_length(&s->encoder.t42, image_length);
break;
#if defined(SPANDSP_SUPPORT_T43)
@ -1014,7 +1014,7 @@ SPAN_DECLARE(void) t4_tx_get_transfer_statistics(t4_tx_state_t *s, t4_stats_t *t
t->length = t4_t6_encode_get_image_length(&s->encoder.t4_t6)/s->row_squashing_ratio;
t->line_image_size = t4_t6_encode_get_compressed_image_size(&s->encoder.t4_t6)/8;
break;
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
t->type = 0;
t->width = t42_encode_get_image_width(&s->encoder.t42);
t->length = t42_encode_get_image_length(&s->encoder.t42)/s->row_squashing_ratio;
@ -1047,7 +1047,7 @@ SPAN_DECLARE(int) t4_tx_image_complete(t4_tx_state_t *s)
case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T6:
return t4_t6_encode_image_complete(&s->encoder.t4_t6);
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
return t42_encode_image_complete(&s->encoder.t42);
#if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43:
@ -1076,7 +1076,7 @@ SPAN_DECLARE(int) t4_tx_get(t4_tx_state_t *s, uint8_t buf[], size_t max_len)
case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T6:
return t4_t6_encode_get(&s->encoder.t4_t6, buf, max_len);
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
return t42_encode_get(&s->encoder.t42, buf, max_len);
#if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43:
@ -1115,7 +1115,7 @@ SPAN_DECLARE(int) t4_tx_start_page(t4_tx_state_t *s)
case T4_COMPRESSION_T6:
t4_t6_encode_restart(&s->encoder.t4_t6, s->image_width);
break;
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
t42_encode_restart(&s->encoder.t42, s->image_width, s->image_length);
break;
#if defined(SPANDSP_SUPPORT_T43)
@ -1237,7 +1237,7 @@ SPAN_DECLARE(int) t4_tx_release(t4_tx_state_t *s)
case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T6:
return t4_t6_encode_release(&s->encoder.t4_t6);
case T4_COMPRESSION_T42:
case T4_COMPRESSION_T42_T81:
return t42_encode_release(&s->encoder.t42);
#if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43:

View File

@ -629,22 +629,21 @@ SPAN_DECLARE(uint8_t) v18_decode_baudot(v18_state_t *s, uint8_t ch)
}
/*- End of function --------------------------------------------------------*/
static void v18_rx_dtmf(void *user_data, const char digits[], int len)
{
#if 0
v18_state_t *s;
s = (v18_state_t *) user_data;
#endif
}
/*- End of function --------------------------------------------------------*/
static int v18_tdd_get_async_byte(void *user_data)
{
v18_state_t *s;
int ch;
unsigned int x;
s = (v18_state_t *) user_data;
if (s->next_byte != 0xFF)
{
s->rx_suppression = (300*SAMPLE_RATE)/1000;
x = s->next_byte;
s->next_byte = (uint8_t) 0xFF;
return x;
}
if ((ch = queue_read_byte(&s->queue.queue)) >= 0)
return ch;
if (s->tx_signal_on)
@ -656,8 +655,38 @@ static int v18_tdd_get_async_byte(void *user_data)
}
/*- End of function --------------------------------------------------------*/
static void v18_dtmf_get(void *user_data)
{
v18_state_t *s;
int ch;
const char *v;
s = (v18_state_t *) user_data;
if ((ch = queue_read_byte(&s->queue.queue)) >= 0)
{
v = ascii_to_dtmf[ch & 0x7F];
dtmf_tx_put(&s->dtmftx, v, strlen(v));
s->rx_suppression = ((300 + 100*strlen(v))*SAMPLE_RATE)/1000;
}
}
/*- End of function --------------------------------------------------------*/
static int v18_edt_get_async_byte(void *user_data)
{
v18_state_t *s;
int ch;
s = (v18_state_t *) user_data;
if ((ch = queue_read_byte(&s->queue.queue)) >= 0)
{
s->rx_suppression = (300*SAMPLE_RATE)/1000;
return ch;
}
if (s->tx_signal_on)
{
/* The FSK should now be switched off. */
s->tx_signal_on = FALSE;
}
return 0;
}
/*- End of function --------------------------------------------------------*/
@ -709,23 +738,62 @@ static void v18_tdd_put_async_byte(void *user_data, int byte)
}
/*- End of function --------------------------------------------------------*/
static void v18_dtmf_put(void *user_data, const char dtmf[], int len)
{
v18_state_t *s;
char buf[128];
int i;
s = (v18_state_t *) user_data;
if (s->rx_suppression > 0)
return;
for (i = 0; i < len; i++)
{
s->rx_msg[s->rx_msg_len++] = dtmf[i];
if (dtmf[i] >= '0' && dtmf[i] <= '9')
{
s->rx_msg[s->rx_msg_len] = '\0';
if (v18_decode_dtmf(s, buf, (const char *) s->rx_msg) > 0)
s->put_msg(s->user_data, (const uint8_t *) buf, 1);
s->rx_msg_len = 0;
}
}
}
/*- End of function --------------------------------------------------------*/
static void v18_edt_put_async_byte(void *user_data, int byte)
{
v18_state_t *s;
s = (v18_state_t *) user_data;
if (s->rx_suppression > 0)
return;
}
/*- End of function --------------------------------------------------------*/
static void v18_bell103_put_async_byte(void *user_data, int byte)
{
v18_state_t *s;
s = (v18_state_t *) user_data;
if (s->rx_suppression > 0)
return;
}
/*- End of function --------------------------------------------------------*/
static void v18_videotex_put_async_byte(void *user_data, int byte)
{
v18_state_t *s;
s = (v18_state_t *) user_data;
if (s->rx_suppression > 0)
return;
}
/*- End of function --------------------------------------------------------*/
static void v18_textphone_put_async_byte(void *user_data, int byte)
{
v18_state_t *s;
s = (v18_state_t *) user_data;
if (s->rx_suppression > 0)
return;
}
/*- End of function --------------------------------------------------------*/
@ -759,6 +827,13 @@ SPAN_DECLARE_NONSTD(int) v18_tx(v18_state_t *s, int16_t *amp, int max_len)
SPAN_DECLARE_NONSTD(int) v18_rx(v18_state_t *s, const int16_t amp[], int len)
{
if (s->rx_suppression > 0)
{
if (s->rx_suppression > len)
s->rx_suppression -= len;
else
s->rx_suppression = 0;
}
switch (s->mode)
{
case V18_MODE_DTMF:
@ -776,6 +851,32 @@ SPAN_DECLARE_NONSTD(int) v18_rx(v18_state_t *s, const int16_t amp[], int len)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE_NONSTD(int) v18_rx_fillin(v18_state_t *s, int len)
{
if (s->rx_suppression > 0)
{
if (s->rx_suppression > len)
s->rx_suppression -= len;
else
s->rx_suppression = 0;
}
switch (s->mode)
{
case V18_MODE_DTMF:
/* Apply a message timeout. */
//s->in_progress -= len;
//if (s->in_progress <= 0)
// s->rx_msg_len = 0;
dtmf_rx_fillin(&s->dtmfrx, len);
break;
default:
fsk_rx_fillin(&s->fskrx, len);
break;
}
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len)
{
char buf[256 + 1];
@ -819,7 +920,7 @@ SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len)
SPAN_DECLARE(const char *) v18_mode_to_str(int mode)
{
switch (mode & 0xFF)
switch ((mode & 0xFF))
{
case V18_MODE_NONE:
return "None";
@ -870,6 +971,7 @@ SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s,
switch (s->mode)
{
case V18_MODE_5BIT_45:
s->repeat_shifts = mode & 0x100;
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, v18_tdd_get_async_byte, s);
/* Schedule an explicit shift at the start of baudot transmission */
@ -878,9 +980,10 @@ SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s,
ride over the fraction. */
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_WEITBRECHT], FSK_FRAME_MODE_5N1_FRAMES, v18_tdd_put_async_byte, s);
s->baudot_rx_shift = 0;
s->repeat_shifts = mode & 0x100;
s->next_byte = (uint8_t) 0xFF;
break;
case V18_MODE_5BIT_50:
s->repeat_shifts = mode & 0x100;
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_WEITBRECHT50], async_tx_get_bit, &s->asynctx);
async_tx_init(&s->asynctx, 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s);
/* Schedule an explicit shift at the start of baudot transmission */
@ -889,11 +992,11 @@ SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s,
ride over the fraction. */
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_WEITBRECHT50], FSK_FRAME_MODE_5N1_FRAMES, v18_tdd_put_async_byte, s);
s->baudot_rx_shift = 0;
s->repeat_shifts = mode & 0x100;
s->next_byte = (uint8_t) 0xFF;
break;
case V18_MODE_DTMF:
dtmf_tx_init(&s->dtmftx, NULL, NULL);
dtmf_rx_init(&s->dtmfrx, v18_rx_dtmf, s);
dtmf_tx_init(&s->dtmftx, v18_dtmf_get, s);
dtmf_rx_init(&s->dtmfrx, v18_dtmf_put, s);
break;
case V18_MODE_EDT:
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_V21CH1_110], async_tx_get_bit, &s->asynctx);

View File

@ -108,7 +108,7 @@ int main(int argc, char *argv[])
image_size = IMAGE_WIDTH*ROWS_PER_STRIPE/8;
memset(image_buffer, 0x18, image_size);
for (i = 0; i < IMAGE_LENGTH/ROWS_PER_STRIPE; i++)
for (i = 0; i*ROWS_PER_STRIPE < IMAGE_LENGTH; i++)
{
if (IMAGE_LENGTH > (i + 1)*ROWS_PER_STRIPE)
image_size = IMAGE_WIDTH*ROWS_PER_STRIPE/8;

View File

@ -59,6 +59,7 @@ int v14_test_async_tx_get_bit(void *user_data)
{
async_tx_state_t *s;
int bit;
int parity_bit;
static int destuff = 0;
/* Special routine to test V.14 rate adaption, by randomly skipping
@ -66,42 +67,39 @@ int v14_test_async_tx_get_bit(void *user_data)
s = (async_tx_state_t *) user_data;
if (s->bitpos == 0)
{
s->byte_in_progress = s->get_byte(s->user_data);
s->byte_in_progress &= (0xFFFF >> (16 - s->data_bits));
if (s->parity)
{
parity_bit = parity8(s->byte_in_progress);
if (s->parity == ASYNC_PARITY_ODD)
parity_bit ^= 1;
s->byte_in_progress |= (parity_bit << s->data_bits);
s->byte_in_progress |= (0xFFFF << (s->data_bits + 1));
}
else
{
s->byte_in_progress |= (0xFFFF << s->data_bits);
}
/* Start bit */
bit = 0;
s->byte_in_progress = s->get_byte(s->user_data);
s->parity_bit = 0;
s->bitpos++;
}
else if (s->bitpos <= s->data_bits)
{
bit = s->byte_in_progress & 1;
s->byte_in_progress >>= 1;
s->parity_bit ^= bit;
s->bitpos++;
if (!s->parity && s->bitpos == s->data_bits + 1)
{
/* Drop the stop bit on every fourth character for V.14 simulation*/
if ((++destuff & 3) == 0)
s->bitpos = 0;
}
}
else if (s->parity && s->bitpos == s->data_bits + 1)
{
if (s->parity == ASYNC_PARITY_ODD)
s->parity_bit ^= 1;
bit = s->parity_bit;
s->bitpos++;
/* Drop the stop bit on every fourth character for V.14 simulation */
if ((++destuff & 3) == 0)
s->bitpos = 0;
}
else
{
/* Stop bit(s) */
bit = 1;
s->bitpos++;
if (s->bitpos > s->data_bits + s->stop_bits)
s->bitpos = 0;
bit = s->byte_in_progress & 1;
s->byte_in_progress >>= 1;
/* Drop the stop bit on every fourth character for V.14 simulation */
if ((++destuff & 3) == 0)
{
if (++s->bitpos > s->total_bits - 1)
s->bitpos = 0;
}
else
{
if (++s->bitpos > s->total_bits)
s->bitpos = 0;
}
}
return bit;
}
@ -207,7 +205,7 @@ int main(int argc, char *argv[])
async_rx_put_bit(&rx_async, bit);
}
printf("Chars=%d/%d, PE=%d, FE=%d\n", tx_async_chars, rx_async_chars, rx_async.parity_errors, rx_async.framing_errors);
if (tx_async_chars != rx_async_chars + 1
if (tx_async_chars != rx_async_chars
||
rx_async.parity_errors
||

View File

@ -846,18 +846,20 @@ int main(int argc, char *argv[])
| T30_SUPPORT_255MM_WIDTH
| T30_SUPPORT_303MM_WIDTH);
t30_set_supported_resolutions(t30_state[i],
T30_SUPPORT_STANDARD_RESOLUTION
| T30_SUPPORT_FINE_RESOLUTION
| T30_SUPPORT_SUPERFINE_RESOLUTION
| T30_SUPPORT_R8_RESOLUTION
| T30_SUPPORT_R16_RESOLUTION
| T30_SUPPORT_300_300_RESOLUTION
| T30_SUPPORT_400_400_RESOLUTION
| T30_SUPPORT_600_600_RESOLUTION
| T30_SUPPORT_1200_1200_RESOLUTION
| T30_SUPPORT_300_600_RESOLUTION
| T30_SUPPORT_400_800_RESOLUTION
| T30_SUPPORT_600_1200_RESOLUTION);
T30_SUPPORT_RESOLUTION_R8_STANDARD
| T30_SUPPORT_RESOLUTION_R8_FINE
| T30_SUPPORT_RESOLUTION_R8_SUPERFINE
| T30_SUPPORT_RESOLUTION_R16_SUPERFINE
| T30_SUPPORT_RESOLUTION_200_100
| T30_SUPPORT_RESOLUTION_200_200
| T30_SUPPORT_RESOLUTION_200_400
| T30_SUPPORT_RESOLUTION_300_300
| T30_SUPPORT_RESOLUTION_300_600
| T30_SUPPORT_RESOLUTION_400_400
| T30_SUPPORT_RESOLUTION_400_800
| T30_SUPPORT_RESOLUTION_600_600
| T30_SUPPORT_RESOLUTION_600_1200
| T30_SUPPORT_RESOLUTION_1200_1200);
//t30_set_rx_encoding(t30_state[i], T4_COMPRESSION_T85);
t30_set_ecm_capability(t30_state[i], use_ecm);
if (use_ecm)

View File

@ -43,6 +43,19 @@ ITUTESTS_DIR=../test-data/itu/fax
for OPTS in "-p AA" "-p AA -e" "-p TT" "-p TT -e" "-p GG" "-p GG -e" "-p TG" "-p TG -e" "-p GT" "-p GT -e"
do
FILE="${ITUTESTS_DIR}/itutests.tif"
run_fax_test
FILE="${ITUTESTS_DIR}/100pages.tif"
run_fax_test
FILE="${ITUTESTS_DIR}/striped.tif"
run_fax_test
FILE="${ITUTESTS_DIR}/mixed_size_pages.tif"
run_fax_test
FILE="${ITUTESTS_DIR}/bilevel_R8_385_A4.tif"
run_fax_test

View File

@ -393,18 +393,20 @@ static void fax_prepare(void)
| T30_SUPPORT_255MM_WIDTH
| T30_SUPPORT_303MM_WIDTH);
t30_set_supported_resolutions(t30,
T30_SUPPORT_STANDARD_RESOLUTION
| T30_SUPPORT_FINE_RESOLUTION
| T30_SUPPORT_SUPERFINE_RESOLUTION
| T30_SUPPORT_R8_RESOLUTION
| T30_SUPPORT_R16_RESOLUTION
| T30_SUPPORT_300_300_RESOLUTION
| T30_SUPPORT_400_400_RESOLUTION
| T30_SUPPORT_600_600_RESOLUTION
| T30_SUPPORT_1200_1200_RESOLUTION
| T30_SUPPORT_300_600_RESOLUTION
| T30_SUPPORT_400_800_RESOLUTION
| T30_SUPPORT_600_1200_RESOLUTION);
T30_SUPPORT_RESOLUTION_R8_STANDARD
| T30_SUPPORT_RESOLUTION_R8_FINE
| T30_SUPPORT_RESOLUTION_R8_SUPERFINE
| T30_SUPPORT_RESOLUTION_R16_SUPERFINE
| T30_SUPPORT_RESOLUTION_200_100
| T30_SUPPORT_RESOLUTION_200_200
| T30_SUPPORT_RESOLUTION_200_400
| T30_SUPPORT_RESOLUTION_300_300
| T30_SUPPORT_RESOLUTION_300_600
| T30_SUPPORT_RESOLUTION_400_400
| T30_SUPPORT_RESOLUTION_400_800
| T30_SUPPORT_RESOLUTION_600_600
| T30_SUPPORT_RESOLUTION_600_1200
| T30_SUPPORT_RESOLUTION_1200_1200);
t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17);
t30_set_supported_compressions(t30, T30_SUPPORT_COMPRESSION_T4_1D | T30_SUPPORT_COMPRESSION_T4_2D | T30_SUPPORT_COMPRESSION_T6);
t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'A');

View File

@ -876,8 +876,8 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
T30_SUPPORT_US_LETTER_LENGTH | T30_SUPPORT_US_LEGAL_LENGTH | T30_SUPPORT_UNLIMITED_LENGTH
| T30_SUPPORT_215MM_WIDTH | T30_SUPPORT_255MM_WIDTH | T30_SUPPORT_303MM_WIDTH);
t30_set_supported_resolutions(t30,
T30_SUPPORT_STANDARD_RESOLUTION | T30_SUPPORT_FINE_RESOLUTION | T30_SUPPORT_SUPERFINE_RESOLUTION
| T30_SUPPORT_R8_RESOLUTION | T30_SUPPORT_R16_RESOLUTION);
T30_SUPPORT_RESOLUTION_R8_STANDARD | T30_SUPPORT_RESOLUTION_R8_FINE | T30_SUPPORT_RESOLUTION_R8_SUPERFINE
| T30_SUPPORT_RESOLUTION_R16_SUPERFINE);
if (pvt->disable_v17) {
t30_set_supported_modems(t30, T30_SUPPORT_V29 | T30_SUPPORT_V27TER);