From b64b8c13bb87daba25c5788fbd7f67cb3b84cee4 Mon Sep 17 00:00:00 2001 From: Ralph Little Date: Sat, 19 Nov 2022 14:20:00 -0800 Subject: [PATCH] brother_mfp: Added support for source option. Can now select Flatbed or ADF for supported machines. --- backend/brother_mfp/brother_mfp-common.h | 19 +- backend/brother_mfp/brother_mfp-driver.cpp | 31 +- backend/brother_mfp/brother_mfp-driver.h | 6 +- backend/brother_mfp/brother_mfp-encoder.cpp | 246 +++++++++++++--- backend/brother_mfp/brother_mfp-encoder.h | 83 +++++- backend/brother_mfp/brother_mfp.cpp | 266 +++++++++++++----- .../brother_mfp/brother_mfp_tests_family4.cpp | 18 +- 7 files changed, 514 insertions(+), 155 deletions(-) diff --git a/backend/brother_mfp/brother_mfp-common.h b/backend/brother_mfp/brother_mfp-common.h index 508b59c9a..5c0b3c06b 100644 --- a/backend/brother_mfp/brother_mfp-common.h +++ b/backend/brother_mfp/brother_mfp-common.h @@ -39,19 +39,20 @@ #define CAP_MODE_GRAY_DITHER (1u << 2) #define CAP_MODE_BW (1u << 3) -#define CAP_MODE_BUTTON_SCAN_EMAIL (1u << 4) -#define CAP_MODE_BUTTON_SCAN_OCR (1u << 5) -#define CAP_MODE_BUTTON_SCAN_FILE (1u << 6) -#define CAP_MODE_BUTTON_SCAN_IMAGE (1u << 7) +#define CAP_BUTTON_HAS_SCAN_EMAIL (1u << 4) +#define CAP_BUTTON_HAS_SCAN_OCR (1u << 5) +#define CAP_BUTTON_HAS_SCAN_FILE (1u << 6) +#define CAP_BUTTON_HAS_SCAN_IMAGE (1u << 7) -#define CAP_MODE_HAS_ADF (1u << 8) -#define CAP_MODE_HAS_ADF_IS_DUPLEX (1u << 9) +#define CAP_SOURCE_HAS_FLATBED (1u << 8) +#define CAP_SOURCE_HAS_ADF (1u << 9) +#define CAP_SOURCE_HAS_ADF_DUPLEX (1u << 10) -#define CAP_MODE_HAS_RAW (1u << 10) -#define CAP_MODE_HAS_JPEG (1u << 11) +#define CAP_ENCODING_HAS_RAW (1u << 11) +#define CAP_ENCODING_HAS_JPEG (1u << 12) // Oddities of particular models. -#define CAP_MODE_RAW_IS_CrYCb (1u << 12) +#define CAP_ENCODING_RAW_IS_CrYCb (1u << 13) /* * Diagnostic levels. diff --git a/backend/brother_mfp/brother_mfp-driver.cpp b/backend/brother_mfp/brother_mfp-driver.cpp index e83f9599e..aa792c27e 100644 --- a/backend/brother_mfp/brother_mfp-driver.cpp +++ b/backend/brother_mfp/brother_mfp-driver.cpp @@ -418,7 +418,8 @@ SANE_Status BrotherUSBDriver::ReadScanData (SANE_Byte *data, size_t max_length, res = encoder->DecodeStatusToSaneStatus(dec_ret); - if ((dec_ret == DECODE_STATUS_ENDOFDATA) || (dec_ret == DECODE_STATUS_ENDOFFRAME_NO_MORE)) + if ((dec_ret == DECODE_STATUS_ENDOFDATA) || (dec_ret == DECODE_STATUS_ENDOFFRAME_NO_MORE) + || (dec_ret == DECODE_STATUS_NO_DOCS)) { next_frame_number++; out_of_docs = true; @@ -850,23 +851,17 @@ SANE_Status BrotherUSBDriver::StartScan () } /* - * Construct the "ADF" block. - * - * This is a query to see if the ADF contains documents. - * TBH I don't really know why we would do this because the source - * (flatbed/ADF) selection seems to be automatic. Perhaps there is a way - * to select the source that we haven't seen to override that behaviour? - * I add it here for completeness though. + * Construct the Source select block. * */ packet_len = 0; - dec_ret = encoder->EncodeADFBlock (small_buffer, sizeof(small_buffer), &packet_len); + dec_ret = encoder->EncodeSourceSelectBlock (small_buffer, sizeof(small_buffer), &packet_len); if (dec_ret != DECODE_STATUS_UNSUPPORTED) { if (dec_ret != DECODE_STATUS_GOOD) { DBG (DBG_SERIOUS, - "BrotherUSBDriver::StartScan: failed to generate ADF block: %d\n", + "BrotherUSBDriver::StartScan: failed to generate source select block: %d\n", dec_ret); (void) CancelScan (); return SANE_STATUS_INVAL; @@ -876,14 +871,14 @@ SANE_Status BrotherUSBDriver::StartScan () res = sanei_usb_write_bulk (fd, small_buffer, &buf_size); if (res != SANE_STATUS_GOOD) { - DBG (DBG_SERIOUS, "BrotherUSBDriver::StartScan: failed to send ADF block: %d\n", res); + DBG (DBG_SERIOUS, "BrotherUSBDriver::StartScan: failed to send source select block: %d\n", res); (void) CancelScan (); return res; } if (buf_size != packet_len) { - DBG (DBG_SERIOUS, "BrotherUSBDriver::StartScan: failed to write ADF block\n"); + DBG (DBG_SERIOUS, "BrotherUSBDriver::StartScan: failed to write source select block\n"); (void) CancelScan (); return SANE_STATUS_IO_ERROR; } @@ -899,27 +894,27 @@ SANE_Status BrotherUSBDriver::StartScan () if (res != SANE_STATUS_GOOD) { DBG (DBG_SERIOUS, - "BrotherUSBDriver::StartScan: failed to read ADF block response: %d\n", + "BrotherUSBDriver::StartScan: failed to read source select block response: %d\n", res); (void) CancelScan (); return res; } - BrotherADFResponse adf_resp; + BrotherSourceStatusResponse source_resp; - dec_ret = encoder->DecodeADFBlockResp (small_buffer, buf_size, adf_resp); + dec_ret = encoder->DecodeSourceStatusBlockResp (small_buffer, buf_size, source_resp); if (dec_ret != DECODE_STATUS_GOOD) { DBG (DBG_SERIOUS, - "BrotherUSBDriver::StartScan: ADF block response block invalid: %d\n", + "BrotherUSBDriver::StartScan: source select response block invalid: %d\n", dec_ret); (void) CancelScan (); return encoder->DecodeStatusToSaneStatus(dec_ret); } DBG (DBG_DETAIL, - "BrotherUSBDriver::StartScan: ADF reports readiness?: %s\n", - adf_resp.adf_ready? "Yes": "No"); + "BrotherUSBDriver::StartScan: Source reports readiness?: %s\n", + source_resp.source_ready? "Yes": "No"); } /* diff --git a/backend/brother_mfp/brother_mfp-driver.h b/backend/brother_mfp/brother_mfp-driver.h index 120bcb7c1..34ff6185a 100644 --- a/backend/brother_mfp/brother_mfp-driver.h +++ b/backend/brother_mfp/brother_mfp-driver.h @@ -105,6 +105,11 @@ public: * Parameter setting. * */ + SANE_Status SetSource (BrotherSource source) + { + return encoder->DecodeStatusToSaneStatus (encoder->SetSource (source)); + } + SANE_Status SetScanMode (BrotherScanMode scan_mode) { return encoder->DecodeStatusToSaneStatus (encoder->SetScanMode (scan_mode)); @@ -144,7 +149,6 @@ protected: BrotherFamily family; SANE_Word capabilities; - BrotherParameters scan_params; BrotherEncoder *encoder; }; diff --git a/backend/brother_mfp/brother_mfp-encoder.cpp b/backend/brother_mfp/brother_mfp-encoder.cpp index 3378ad5ff..9d7e1ed6f 100644 --- a/backend/brother_mfp/brother_mfp-encoder.cpp +++ b/backend/brother_mfp/brother_mfp-encoder.cpp @@ -78,6 +78,11 @@ // unsure as to the meaning of this or how to get it again. #define BROTHER_DATA_BLOCK_CLEARING_PAPER 0xc5 +/* + * Other protocol error? + * + */ +#define BROTHER_DATA_BLOCK_PROTOCOL_ERROR 0xd0 const char* BrotherEncoder::ScanModeToText (BrotherScanMode scan_mode) { @@ -87,6 +92,14 @@ const char* BrotherEncoder::ScanModeToText (BrotherScanMode scan_mode) return scan_mode_text[scan_mode]; } + +DecodeStatus BrotherEncoder::SetSource (BrotherSource source) +{ + scan_params.param_source = source; + + return DECODE_STATUS_GOOD; +} + DecodeStatus BrotherEncoder::SetScanMode (BrotherScanMode scan_mode) { @@ -212,14 +225,14 @@ DecodeStatus BrotherEncoderFamily2::DecodeQueryBlockResp (const SANE_Byte *data, return DECODE_STATUS_GOOD; } -DecodeStatus BrotherEncoderFamily2::EncodeADFBlock (SANE_Byte *data, size_t data_len, size_t *length) +DecodeStatus BrotherEncoderFamily2::EncodeSourceStatusBlock (SANE_Byte *data, size_t data_len, size_t *length) { *length = snprintf ((char*) data, data_len, "\x1b" "D\nADF\n" "\x80"); if (*length > data_len) { DBG (DBG_SERIOUS, - "BrotherEncoderFamily2::EncodeBasicParameterBlock: ADF block too long for buffer: %zu\n", + "BrotherEncoderFamily2::EncodeBasicParameterBlock: source status too long for buffer: %zu\n", *length); return DECODE_STATUS_INVAL; } @@ -227,13 +240,13 @@ DecodeStatus BrotherEncoderFamily2::EncodeADFBlock (SANE_Byte *data, size_t data return DECODE_STATUS_GOOD; } -DecodeStatus BrotherEncoderFamily2::DecodeADFBlockResp (const SANE_Byte *data, size_t data_len, - BrotherADFResponse &response) +DecodeStatus BrotherEncoderFamily2::DecodeSourceStatusBlockResp (const SANE_Byte *data, size_t data_len, + BrotherSourceStatusResponse &response) { if (data_len != 1) { DBG (DBG_SERIOUS, - "BrotherEncoderFamily2::DecodeADFBlockResp: ADF block response invalid: %zu\n", + "BrotherEncoderFamily2::DecodeSourceStatusBlockResp: source status response invalid: %zu\n", data_len); return DECODE_STATUS_ERROR; } @@ -251,11 +264,11 @@ DecodeStatus BrotherEncoderFamily2::DecodeADFBlockResp (const SANE_Byte *data, s return DECODE_STATUS_COVER_OPEN; case BROTHER_DATA_BLOCK_NO_DOCS: - response.adf_ready = SANE_FALSE; + response.source_ready = SANE_FALSE; return DECODE_STATUS_GOOD; case BROTHER_DATA_BLOCK_SCAN_FINISHED: - response.adf_ready = SANE_TRUE; + response.source_ready = SANE_TRUE; return DECODE_STATUS_GOOD; default: @@ -263,6 +276,54 @@ DecodeStatus BrotherEncoderFamily2::DecodeADFBlockResp (const SANE_Byte *data, s } } +DecodeStatus BrotherEncoderFamily2::EncodeSourceSelectBlock (SANE_Byte *data, size_t data_len, size_t *length) +{ + *length = snprintf ((char*) data, + data_len, + "\x1b" "S\n%s\n" "\x80", + scan_params.param_source == BROTHER_SOURCE_FLATBED ? "FB" : "ADF"); + + if (*length > data_len) + { + DBG (DBG_SERIOUS, + "BrotherEncoderFamily2::EncodeSourceSelectBlock: Source select block too long for buffer: %zu\n", + *length); + return DECODE_STATUS_INVAL; + } + + return DECODE_STATUS_GOOD; +} + +DecodeStatus BrotherEncoderFamily2::DecodeSourceSelectBlockResp (const SANE_Byte *data, + size_t data_len, + BrotherSourceStatusResponse &response) +{ + if (data_len != 1) + { + DBG (DBG_SERIOUS, + "BrotherEncoderFamily2::DecodeSourceStatusBlockResp: source select response invalid: %zu\n", + data_len); + return DECODE_STATUS_ERROR; + } + + /* + * We can get error condition codes from this block. + * + */ + switch (data[0]) + { + case BROTHER_DATA_BLOCK_SCAN_FINISHED: + response.source_ready = SANE_TRUE; + return DECODE_STATUS_GOOD; + + case BROTHER_DATA_BLOCK_PROTOCOL_ERROR: + response.source_ready = SANE_FALSE; + return DECODE_STATUS_INVAL; + + default: + return DECODE_STATUS_ERROR; + } +} DecodeStatus BrotherEncoderFamily2::DecodeSessionResp (const SANE_Byte *data, size_t data_len, BrotherSessionResponse &response) @@ -493,12 +554,11 @@ DecodeStatus BrotherEncoderFamily2::DecodeScanData (const SANE_Byte *src_data, s * Detect special case situations. * */ - if ((ret_status == DECODE_STATUS_ENDOFDATA) - || (ret_status == DECODE_STATUS_ENDOFFRAME_WITH_MORE)) + if (ret_status != DECODE_STATUS_GOOD) { DBG (DBG_IMPORTANT, - "BrotherEncoderFamily2::DecodeScanData: %s detected.\n", - ret_status == DECODE_STATUS_ENDOFDATA ? "ENDOFDATA" : "ENDOFFRAME_WITH_MORE"); + "BrotherEncoderFamily2::DecodeScanData: %s.\n", + DecodeStatusToString (ret_status)); current_header.block_type = 0; @@ -682,6 +742,12 @@ DecodeStatus BrotherEncoderFamily2::DecodeScanDataHeader (const SANE_Byte *src_d header.block_len = 0; + if (header.block_type == BROTHER_DATA_BLOCK_NO_DOCS) + { + *src_data_consumed = 1; + return DECODE_STATUS_NO_DOCS; + } + if (header.block_type == BROTHER_DATA_BLOCK_SCAN_FINISHED) { *src_data_consumed = 1; @@ -833,14 +899,14 @@ DecodeStatus BrotherEncoderFamily3::DecodeQueryBlockResp (const SANE_Byte *data, return DECODE_STATUS_GOOD; } -DecodeStatus BrotherEncoderFamily3::EncodeADFBlock (SANE_Byte *data, size_t data_len, size_t *length) +DecodeStatus BrotherEncoderFamily3::EncodeSourceStatusBlock (SANE_Byte *data, size_t data_len, size_t *length) { *length = snprintf ((char*) data, data_len, "\x1b" "D\nADF\n" "\x80"); if (*length > data_len) { DBG (DBG_SERIOUS, - "BrotherEncoderFamily3::EncodeBasicParameterBlock: ADF block too long for buffer: %zu\n", + "BrotherEncoderFamily3::EncodeBasicParameterBlock: source status too long for buffer: %zu\n", *length); return DECODE_STATUS_INVAL; } @@ -848,13 +914,13 @@ DecodeStatus BrotherEncoderFamily3::EncodeADFBlock (SANE_Byte *data, size_t data return DECODE_STATUS_GOOD; } -DecodeStatus BrotherEncoderFamily3::DecodeADFBlockResp (const SANE_Byte *data, size_t data_len, - BrotherADFResponse &response) +DecodeStatus BrotherEncoderFamily3::DecodeSourceStatusBlockResp (const SANE_Byte *data, size_t data_len, + BrotherSourceStatusResponse &response) { if (data_len != 1) { DBG (DBG_SERIOUS, - "BrotherEncoderFamily2::DecodeADFBlockResp: ADF block response invalid: %zu\n", + "BrotherEncoderFamily2::DecodeSourceStatusBlockResp: source status response invalid: %zu\n", data_len); return DECODE_STATUS_ERROR; } @@ -872,11 +938,11 @@ DecodeStatus BrotherEncoderFamily3::DecodeADFBlockResp (const SANE_Byte *data, s return DECODE_STATUS_COVER_OPEN; case BROTHER_DATA_BLOCK_NO_DOCS: - response.adf_ready = SANE_FALSE; + response.source_ready = SANE_FALSE; return DECODE_STATUS_GOOD; case BROTHER_DATA_BLOCK_SCAN_FINISHED: - response.adf_ready = SANE_TRUE; + response.source_ready = SANE_TRUE; return DECODE_STATUS_GOOD; default: @@ -884,6 +950,55 @@ DecodeStatus BrotherEncoderFamily3::DecodeADFBlockResp (const SANE_Byte *data, s } } +DecodeStatus BrotherEncoderFamily3::EncodeSourceSelectBlock (SANE_Byte *data, size_t data_len, size_t *length) +{ + *length = snprintf ((char*) data, + data_len, + "\x1b" "S\n%s\n" "\x80", + scan_params.param_source == BROTHER_SOURCE_FLATBED ? "FB" : "ADF"); + + if (*length > data_len) + { + DBG (DBG_SERIOUS, + "BrotherEncoderFamily3::EncodeSourceSelectBlock: Source select block too long for buffer: %zu\n", + *length); + return DECODE_STATUS_INVAL; + } + + return DECODE_STATUS_GOOD; +} + +DecodeStatus BrotherEncoderFamily3::DecodeSourceSelectBlockResp (const SANE_Byte *data, + size_t data_len, + BrotherSourceStatusResponse &response) +{ + if (data_len != 1) + { + DBG (DBG_SERIOUS, + "BrotherEncoderFamily3::DecodeSourceStatusBlockResp: source select response invalid: %zu\n", + data_len); + return DECODE_STATUS_ERROR; + } + + /* + * We can get error condition codes from this block. + * + */ + switch (data[0]) + { + case BROTHER_DATA_BLOCK_SCAN_FINISHED: + response.source_ready = SANE_TRUE; + return DECODE_STATUS_GOOD; + + case BROTHER_DATA_BLOCK_PROTOCOL_ERROR: + response.source_ready = SANE_FALSE; + return DECODE_STATUS_INVAL; + + default: + return DECODE_STATUS_ERROR; + } +} + DecodeStatus BrotherEncoderFamily3::DecodeSessionResp (const SANE_Byte *data, size_t data_len, BrotherSessionResponse &response) { @@ -1113,12 +1228,11 @@ DecodeStatus BrotherEncoderFamily3::DecodeScanData (const SANE_Byte *src_data, s * Detect special case situations. * */ - if ((ret_status == DECODE_STATUS_ENDOFDATA) - || (ret_status == DECODE_STATUS_ENDOFFRAME_WITH_MORE)) + if (ret_status != DECODE_STATUS_GOOD) { DBG (DBG_IMPORTANT, - "BrotherEncoderFamily3::DecodeScanData: %s.\n", - ret_status == DECODE_STATUS_ENDOFDATA ? "ENDOFDATA" : "ENDOFFRAME_WITH_MORE"); + "BrotherEncoderFamily2::DecodeScanData: %s.\n", + DecodeStatusToString (ret_status)); current_header.block_type = 0; @@ -1312,6 +1426,12 @@ DecodeStatus BrotherEncoderFamily3::DecodeScanDataHeader (const SANE_Byte *src_d header.block_len = 0; + if (header.block_type == BROTHER_DATA_BLOCK_NO_DOCS) + { + *src_data_consumed = 1; + return DECODE_STATUS_NO_DOCS; + } + if (header.block_type == BROTHER_DATA_BLOCK_SCAN_FINISHED) { *src_data_consumed = 1; @@ -1567,14 +1687,14 @@ DecodeStatus BrotherEncoderFamily4::DecodeBasicParameterBlockResp (const SANE_By return DECODE_STATUS_GOOD; } -DecodeStatus BrotherEncoderFamily4::EncodeADFBlock (SANE_Byte *data, size_t data_len, size_t *length) +DecodeStatus BrotherEncoderFamily4::EncodeSourceStatusBlock (SANE_Byte *data, size_t data_len, size_t *length) { *length = snprintf ((char*) data, data_len, "\x1b" "D\nADF\n" "\x80"); if (*length > data_len) { DBG (DBG_SERIOUS, - "BrotherEncoderFamily4::EncodeBasicParameterBlock: ADF block too long for buffer: %zu\n", + "BrotherEncoderFamily4::EncodeSourceStatusBlock: Source status block too long for buffer: %zu\n", *length); return DECODE_STATUS_INVAL; } @@ -1582,13 +1702,14 @@ DecodeStatus BrotherEncoderFamily4::EncodeADFBlock (SANE_Byte *data, size_t data return DECODE_STATUS_GOOD; } -DecodeStatus BrotherEncoderFamily4::DecodeADFBlockResp (const SANE_Byte *data, size_t data_len, - BrotherADFResponse &response) +DecodeStatus BrotherEncoderFamily4::DecodeSourceStatusBlockResp (const SANE_Byte *data, + size_t data_len, + BrotherSourceStatusResponse &response) { if (data_len != 1) { DBG (DBG_SERIOUS, - "BrotherEncoderFamily2::DecodeADFBlockResp: ADF block response invalid: %zu\n", + "BrotherEncoderFamily2::DecodeSourceStatusBlockResp: source status response invalid: %zu\n", data_len); return DECODE_STATUS_ERROR; } @@ -1606,11 +1727,11 @@ DecodeStatus BrotherEncoderFamily4::DecodeADFBlockResp (const SANE_Byte *data, s return DECODE_STATUS_COVER_OPEN; case BROTHER_DATA_BLOCK_NO_DOCS: - response.adf_ready = SANE_FALSE; + response.source_ready = SANE_FALSE; return DECODE_STATUS_GOOD; case BROTHER_DATA_BLOCK_SCAN_FINISHED: - response.adf_ready = SANE_TRUE; + response.source_ready = SANE_TRUE; return DECODE_STATUS_GOOD; default: @@ -1618,6 +1739,55 @@ DecodeStatus BrotherEncoderFamily4::DecodeADFBlockResp (const SANE_Byte *data, s } } +DecodeStatus BrotherEncoderFamily4::EncodeSourceSelectBlock (SANE_Byte *data, size_t data_len, size_t *length) +{ + *length = snprintf ((char*) data, + data_len, + "\x1b" "S\n%s\n" "\x80", + scan_params.param_source == BROTHER_SOURCE_FLATBED ? "FB" : "ADF"); + + if (*length > data_len) + { + DBG (DBG_SERIOUS, + "BrotherEncoderFamily4::EncodeSourceSelectBlock: Source select block too long for buffer: %zu\n", + *length); + return DECODE_STATUS_INVAL; + } + + return DECODE_STATUS_GOOD; +} + +DecodeStatus BrotherEncoderFamily4::DecodeSourceSelectBlockResp (const SANE_Byte *data, + size_t data_len, + BrotherSourceStatusResponse &response) +{ + if (data_len != 1) + { + DBG (DBG_SERIOUS, + "BrotherEncoderFamily2::DecodeSourceStatusBlockResp: source select response invalid: %zu\n", + data_len); + return DECODE_STATUS_ERROR; + } + + /* + * We can get error condition codes from this block. + * + */ + switch (data[0]) + { + case BROTHER_DATA_BLOCK_SCAN_FINISHED: + response.source_ready = SANE_TRUE; + return DECODE_STATUS_GOOD; + + case BROTHER_DATA_BLOCK_PROTOCOL_ERROR: + response.source_ready = SANE_FALSE; + return DECODE_STATUS_INVAL; + + default: + return DECODE_STATUS_ERROR; + } +} + DecodeStatus BrotherEncoderFamily4::EncodeParameterBlockBlank (SANE_Byte *data, size_t data_len, size_t *length) { @@ -1753,15 +1923,11 @@ DecodeStatus BrotherEncoderFamily4::DecodeScanData (const SANE_Byte *src_data, s * Detect special case situations. * */ - if ((ret_status == DECODE_STATUS_ENDOFDATA) - || (ret_status == DECODE_STATUS_ENDOFFRAME_NO_MORE) - || (ret_status == DECODE_STATUS_ENDOFFRAME_WITH_MORE)) + if (ret_status != DECODE_STATUS_GOOD) { DBG (DBG_IMPORTANT, - "BrotherEncoderFamily4::DecodeScanData: %s.\n", - ret_status == DECODE_STATUS_ENDOFDATA ? "ENDOFDATA" : - ret_status == DECODE_STATUS_ENDOFFRAME_NO_MORE ? - "ENDOFFRAME_NO_MORE" : "ENDOFFRAME_WITH_MORE"); + "BrotherEncoderFamily2::DecodeScanData: %s.\n", + DecodeStatusToString (ret_status)); current_header.block_type = 0; @@ -1935,6 +2101,12 @@ DecodeStatus BrotherEncoderFamily4::DecodeScanDataHeader (const SANE_Byte *src_d header.block_len = 0; + if (header.block_type == BROTHER_DATA_BLOCK_NO_DOCS) + { + *src_data_consumed = 1; + return DECODE_STATUS_NO_DOCS; + } + if (header.block_type == BROTHER_DATA_BLOCK_SCAN_FINISHED) { *src_data_consumed = 1; @@ -2304,7 +2476,7 @@ DecodeStatus BrotherInterleavedRGBColourDecoder::DecodeScanData (const SANE_Byte * Sort out the raw encoding format. * */ - if (capabilities & CAP_MODE_RAW_IS_CrYCb) + if (capabilities & CAP_ENCODING_RAW_IS_CrYCb) { SANE_Byte R; SANE_Byte G; diff --git a/backend/brother_mfp/brother_mfp-encoder.h b/backend/brother_mfp/brother_mfp-encoder.h index cfd4ba22e..70d030eab 100644 --- a/backend/brother_mfp/brother_mfp-encoder.h +++ b/backend/brother_mfp/brother_mfp-encoder.h @@ -82,6 +82,13 @@ typedef enum BROTHER_SCAN_MODE_TEXT } BrotherScanMode; + +typedef enum +{ + BROTHER_SOURCE_FLATBED, + BROTHER_SOURCE_ADF, +} BrotherSource; + typedef SANE_Int BrotherSensor; #define BROTHER_SENSOR_NONE 0 @@ -116,6 +123,7 @@ struct BrotherParameters param_pixel_y_offset (0), param_pixel_y_height (0), param_scan_mode (BROTHER_SCAN_MODE_COLOR), + param_source(BROTHER_SOURCE_FLATBED), param_x_res(100), param_y_res(100) { @@ -130,6 +138,7 @@ struct BrotherParameters SANE_Int param_pixel_y_height; BrotherScanMode param_scan_mode; + BrotherSource param_source; SANE_Int param_x_res; SANE_Int param_y_res; @@ -148,9 +157,9 @@ struct BrotherQueryResponse // fill me }; -struct BrotherADFResponse +struct BrotherSourceStatusResponse { - SANE_Bool adf_ready; + SANE_Bool source_ready; }; @@ -173,6 +182,7 @@ enum DecodeStatus DECODE_STATUS_UNSUPPORTED, DECODE_STATUS_PAPER_JAM, DECODE_STATUS_COVER_OPEN, + DECODE_STATUS_NO_DOCS, }; struct ScanDataHeader @@ -199,6 +209,7 @@ public: virtual void NewPage () = 0; + DecodeStatus SetSource (BrotherSource source); DecodeStatus SetScanMode (BrotherScanMode scan_mode); DecodeStatus SetRes (SANE_Int x, SANE_Int y); DecodeStatus SetContrast (SANE_Int contrast); @@ -224,6 +235,29 @@ public: SANE_STATUS_UNSUPPORTED, SANE_STATUS_JAMMED, SANE_STATUS_COVER_OPEN, + SANE_STATUS_NO_DOCS, + }; + + return status_lookup[dec_ret]; + } + + const char *DecodeStatusToString(DecodeStatus dec_ret) + { + static const char * status_lookup[] = + { + "DECODE_STATUS_GOOD", + "DECODE_STATUS_TRUNCATED", + "DECODE_STATUS_ENDOFDATA", + "DECODE_STATUS_ENDOFFRAME_NO_MORE", + "DECODE_STATUS_ENDOFFRAME_WITH_MORE", + "DECODE_STATUS_CANCEL", + "DECODE_STATUS_ERROR", + "DECODE_STATUS_MEMORY", + "DECODE_STATUS_INVAL", + "DECODE_STATUS_UNSUPPORTED", + "DECODE_STATUS_PAPER_JAM", + "DECODE_STATUS_COVER_OPEN", + "DECODE_STATUS_NO_DOCS", }; return status_lookup[dec_ret]; @@ -254,10 +288,15 @@ public: virtual DecodeStatus DecodeBasicParameterBlockResp (const SANE_Byte *data, size_t data_len, BrotherBasicParamResponse &response) = 0; - virtual DecodeStatus EncodeADFBlock (SANE_Byte *data, size_t data_len, size_t *length) = 0; + virtual DecodeStatus EncodeSourceStatusBlock (SANE_Byte *data, size_t data_len, size_t *length) = 0; - virtual DecodeStatus DecodeADFBlockResp (const SANE_Byte *data, size_t data_len, - BrotherADFResponse &response) = 0; + virtual DecodeStatus DecodeSourceStatusBlockResp (const SANE_Byte *data, size_t data_len, + BrotherSourceStatusResponse &response) = 0; + + virtual DecodeStatus EncodeSourceSelectBlock (SANE_Byte *data, size_t data_len, size_t *length) = 0; + + virtual DecodeStatus DecodeSourceSelectBlockResp (const SANE_Byte *data, size_t data_len, + BrotherSourceStatusResponse &response) = 0; virtual DecodeStatus EncodeParameterBlock (SANE_Byte *data, size_t data_len, size_t *length) = 0; @@ -462,10 +501,15 @@ public: DecodeStatus DecodeBasicParameterBlockResp (const SANE_Byte *data, size_t data_len, BrotherBasicParamResponse &response) override; - DecodeStatus EncodeADFBlock (SANE_Byte *data, size_t data_len, size_t *length) override; + DecodeStatus EncodeSourceStatusBlock (SANE_Byte *data, size_t data_len, size_t *length) override; - DecodeStatus DecodeADFBlockResp (const SANE_Byte *data, size_t data_len, - BrotherADFResponse &response) override; + DecodeStatus DecodeSourceStatusBlockResp (const SANE_Byte *data, size_t data_len, + BrotherSourceStatusResponse &response) override; + + DecodeStatus EncodeSourceSelectBlock (SANE_Byte *data, size_t data_len, size_t *length) override; + + DecodeStatus DecodeSourceSelectBlockResp (const SANE_Byte *data, size_t data_len, + BrotherSourceStatusResponse &response) override; DecodeStatus EncodeParameterBlock (SANE_Byte *data, size_t data_len, size_t *length) override; @@ -530,10 +574,16 @@ public: DecodeStatus DecodeBasicParameterBlockResp (const SANE_Byte *data, size_t data_len, BrotherBasicParamResponse &response) override; - DecodeStatus EncodeADFBlock (SANE_Byte *data, size_t data_len, size_t *length) override; + DecodeStatus EncodeSourceStatusBlock (SANE_Byte *data, size_t data_len, size_t *length) override; + + DecodeStatus DecodeSourceStatusBlockResp (const SANE_Byte *data, size_t data_len, + BrotherSourceStatusResponse &response) override; + + DecodeStatus EncodeSourceSelectBlock (SANE_Byte *data, size_t data_len, size_t *length) override; + + DecodeStatus DecodeSourceSelectBlockResp (const SANE_Byte *data, size_t data_len, + BrotherSourceStatusResponse &response) override; - DecodeStatus DecodeADFBlockResp (const SANE_Byte *data, size_t data_len, - BrotherADFResponse &response) override; DecodeStatus EncodeParameterBlock (SANE_Byte *data, size_t data_len, size_t *length) override; DecodeStatus EncodeParameterBlockBlank (SANE_Byte *data, size_t data_len, size_t *length) @@ -596,10 +646,15 @@ public: DecodeStatus DecodeBasicParameterBlockResp (const SANE_Byte *data, size_t data_len, BrotherBasicParamResponse &response) override; - DecodeStatus EncodeADFBlock (SANE_Byte *data, size_t data_len, size_t *length) override; + DecodeStatus EncodeSourceStatusBlock (SANE_Byte *data, size_t data_len, size_t *length) override; - DecodeStatus DecodeADFBlockResp (const SANE_Byte *data, size_t data_len, - BrotherADFResponse &response) override; + DecodeStatus DecodeSourceStatusBlockResp (const SANE_Byte *data, size_t data_len, + BrotherSourceStatusResponse &response) override; + + DecodeStatus EncodeSourceSelectBlock (SANE_Byte *data, size_t data_len, size_t *length) override; + + DecodeStatus DecodeSourceSelectBlockResp (const SANE_Byte *data, size_t data_len, + BrotherSourceStatusResponse &response) override; DecodeStatus EncodeParameterBlock (SANE_Byte *data, size_t data_len, size_t *length) override; diff --git a/backend/brother_mfp/brother_mfp.cpp b/backend/brother_mfp/brother_mfp.cpp index b6789ecb5..46b831e6b 100644 --- a/backend/brother_mfp/brother_mfp.cpp +++ b/backend/brother_mfp/brother_mfp.cpp @@ -53,7 +53,10 @@ * Messages. * */ -#define SANE_VALUE_SCAN_MODE_GRAY_DITHER SANE_I18N("Gray (Dithered)") +#define SANE_VALUE_SCAN_MODE_GRAY_DITHER SANE_I18N("Gray (Dithered)") + +#define SANE_VALUE_SOURCE_FLATBED SANE_I18N("Flatbed") +#define SANE_VALUE_SOURCE_ADF SANE_I18N("Automatic Document Feeder") #define SANE_NAME_FILE_BUTTON "file-sensor" #define SANE_NAME_EMAIL_BUTTON "email-sensor" @@ -81,6 +84,7 @@ enum Brother_Option OPT_NUM_OPTS = 0, OPT_MODE_GROUP, + OPT_SOURCE, OPT_MODE, OPT_SPLIT_RESOLUTION, OPT_RESOLUTION, @@ -139,14 +143,15 @@ static Brother_Model models[] = CAP_MODE_GRAY | CAP_MODE_GRAY_DITHER | CAP_MODE_BW | - CAP_MODE_BUTTON_SCAN_EMAIL | - CAP_MODE_BUTTON_SCAN_FILE | - CAP_MODE_BUTTON_SCAN_OCR | - CAP_MODE_BUTTON_SCAN_IMAGE | - CAP_MODE_HAS_ADF | - CAP_MODE_RAW_IS_CrYCb | - CAP_MODE_HAS_RAW | - CAP_MODE_HAS_JPEG }, + CAP_BUTTON_HAS_SCAN_EMAIL | + CAP_BUTTON_HAS_SCAN_FILE | + CAP_BUTTON_HAS_SCAN_OCR | + CAP_BUTTON_HAS_SCAN_IMAGE | + CAP_SOURCE_HAS_ADF | + CAP_SOURCE_HAS_FLATBED | + CAP_ENCODING_RAW_IS_CrYCb | + CAP_ENCODING_HAS_RAW | + CAP_ENCODING_HAS_JPEG }, { "Brother", "DCP-7030", BROTHER_FAMILY_3, 0x04f9, 0x01ea, { 0, SANE_FIX(210), 0 }, @@ -157,12 +162,13 @@ static Brother_Model models[] = CAP_MODE_GRAY | CAP_MODE_GRAY_DITHER | CAP_MODE_BW | - CAP_MODE_BUTTON_SCAN_EMAIL | - CAP_MODE_BUTTON_SCAN_FILE | - CAP_MODE_BUTTON_SCAN_OCR | - CAP_MODE_BUTTON_SCAN_IMAGE | - CAP_MODE_HAS_RAW | - CAP_MODE_HAS_JPEG}, + CAP_BUTTON_HAS_SCAN_EMAIL | + CAP_BUTTON_HAS_SCAN_FILE | + CAP_BUTTON_HAS_SCAN_OCR | + CAP_BUTTON_HAS_SCAN_IMAGE | + CAP_SOURCE_HAS_FLATBED | + CAP_ENCODING_HAS_RAW | + CAP_ENCODING_HAS_JPEG}, // TODO: check dimensions { "Brother", "MFC-290C", BROTHER_FAMILY_3, 0x04f9, 0x01fd, @@ -174,13 +180,15 @@ static Brother_Model models[] = CAP_MODE_GRAY | CAP_MODE_GRAY_DITHER | CAP_MODE_BW | - CAP_MODE_BUTTON_SCAN_EMAIL | - CAP_MODE_BUTTON_SCAN_FILE | - CAP_MODE_BUTTON_SCAN_OCR | - CAP_MODE_BUTTON_SCAN_IMAGE | - CAP_MODE_RAW_IS_CrYCb | - CAP_MODE_HAS_RAW | - CAP_MODE_HAS_JPEG}, + CAP_SOURCE_HAS_FLATBED | + CAP_SOURCE_HAS_ADF | + CAP_BUTTON_HAS_SCAN_EMAIL | + CAP_BUTTON_HAS_SCAN_FILE | + CAP_BUTTON_HAS_SCAN_OCR | + CAP_BUTTON_HAS_SCAN_IMAGE | + CAP_ENCODING_RAW_IS_CrYCb | + CAP_ENCODING_HAS_RAW | + CAP_ENCODING_HAS_JPEG}, { "Brother", "MFC-J4320DW", BROTHER_FAMILY_4, 0x04f9, 0x033a, { 0, SANE_FIX(211.5), 0 }, @@ -191,11 +199,46 @@ static Brother_Model models[] = CAP_MODE_GRAY | CAP_MODE_GRAY_DITHER | CAP_MODE_BW | - CAP_MODE_BUTTON_SCAN_EMAIL | - CAP_MODE_BUTTON_SCAN_FILE | - CAP_MODE_BUTTON_SCAN_OCR | - CAP_MODE_BUTTON_SCAN_IMAGE | - CAP_MODE_HAS_JPEG }, + CAP_BUTTON_HAS_SCAN_EMAIL | + CAP_BUTTON_HAS_SCAN_FILE | + CAP_BUTTON_HAS_SCAN_OCR | + CAP_BUTTON_HAS_SCAN_IMAGE | + CAP_ENCODING_HAS_JPEG | + CAP_SOURCE_HAS_FLATBED}, + + { "Brother", "MFC-J4620DW", BROTHER_FAMILY_4, 0x04f9, 0x0340, + { 0, SANE_FIX(211.881), 0 }, + { 0, SANE_FIX(355.567), 0 }, + { 6, 100, 150, 200, 300, 600, 1200 }, + { 7, 100, 150, 200, 300, 600, 1200, 2400 }, + CAP_MODE_COLOUR | + CAP_MODE_GRAY | + CAP_MODE_GRAY_DITHER | + CAP_MODE_BW | + CAP_SOURCE_HAS_FLATBED | + CAP_SOURCE_HAS_ADF | + CAP_BUTTON_HAS_SCAN_EMAIL | + CAP_BUTTON_HAS_SCAN_FILE | + CAP_BUTTON_HAS_SCAN_OCR | + CAP_BUTTON_HAS_SCAN_IMAGE | + CAP_ENCODING_HAS_JPEG }, + + { "Brother", "ADS-2800W", BROTHER_FAMILY_4, 0x04f9, 0x0340, + { 0, SANE_FIX(215.000), 0 }, + { 0, SANE_FIX(355.000), 0 }, + { 6, 100, 150, 200, 300, 600 }, + { 6, 100, 150, 200, 300, 600 }, + CAP_MODE_COLOUR | + CAP_MODE_GRAY | + CAP_MODE_GRAY_DITHER | + CAP_MODE_BW | + CAP_SOURCE_HAS_FLATBED | + CAP_SOURCE_HAS_ADF | + CAP_BUTTON_HAS_SCAN_EMAIL | + CAP_BUTTON_HAS_SCAN_FILE | + CAP_BUTTON_HAS_SCAN_OCR | + CAP_BUTTON_HAS_SCAN_IMAGE | + CAP_ENCODING_HAS_JPEG }, {NULL, NULL, BROTHER_FAMILY_NONE, 0, 0, {0, 0, 0}, {0, 0, 0}, {0}, {0}, 0} }; @@ -208,6 +251,7 @@ struct BrotherDevice sane_device {nullptr, nullptr, nullptr, nullptr}, name (nullptr), modes {0}, + sources {0}, params {SANE_FRAME_GRAY, SANE_FALSE, 0, 0, 0, 0}, internal_scan_mode(nullptr), x_res (0), @@ -228,6 +272,7 @@ struct BrotherDevice Option_Value val[NUM_OPTIONS]; SANE_String_Const modes[10]; + SANE_String_Const sources[10]; SANE_Parameters params; const char *internal_scan_mode; SANE_Int x_res; @@ -354,6 +399,20 @@ attach_with_ret (const char *devicename, BrotherDevice **dev) device->modes[num_modes++] = SANE_VALUE_SCAN_MODE_LINEART; } + /* + * Create the sources list. + * + */ + size_t num_sources = 0; + if (model->capabilities & CAP_SOURCE_HAS_FLATBED) + { + device->sources[num_sources++] = SANE_VALUE_SOURCE_FLATBED; + } + if (model->capabilities & CAP_SOURCE_HAS_ADF) + { + device->sources[num_sources++] = SANE_VALUE_SOURCE_ADF; + } + ++num_devices; device->next = first_dev; first_dev = device; @@ -423,6 +482,39 @@ init_options (BrotherDevice *device) od->constraint.range = 0; device->val[OPT_MODE_GROUP].w = 0; + /* opt_source */ + od = &device->opt[OPT_SOURCE]; + od->name = SANE_NAME_SCAN_SOURCE; + od->title = SANE_TITLE_SCAN_SOURCE; + od->desc = SANE_DESC_SCAN_SOURCE; + od->type = SANE_TYPE_STRING; + od->unit = SANE_UNIT_NONE; + od->size = max_string_size (device->sources); + od->constraint_type = SANE_CONSTRAINT_STRING_LIST; + od->constraint.string_list = device->sources; + if (!device->sources[0]) + { + od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE; + device->val[OPT_SOURCE].s = new char[1]; + if (NULL == device->val[OPT_SOURCE].s) + { + DBG (DBG_SERIOUS, "init_options: failed to allocate source storage %zu\n", (size_t) od->size); + return SANE_STATUS_NO_MEM; + } + (void) strcpy (device->val[OPT_SOURCE].s, ""); + } + else + { + od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; + device->val[OPT_SOURCE].s = new char[od->size]; + if (NULL == device->val[OPT_SOURCE].s) + { + DBG (DBG_SERIOUS, "init_options: failed to allocate source storage %zu\n", (size_t) od->size); + return SANE_STATUS_NO_MEM; + } + (void) strcpy (device->val[OPT_SOURCE].s, device->sources[0]); + } + /* opt_mode */ od = &device->opt[OPT_MODE]; od->name = SANE_NAME_SCAN_MODE; @@ -622,8 +714,8 @@ init_options (BrotherDevice *device) od->unit = SANE_UNIT_NONE; od->size = 1 * sizeof(SANE_Bool); od->constraint_type = SANE_CONSTRAINT_NONE; - if ((device->model->capabilities & CAP_MODE_HAS_JPEG) - && (device->model->capabilities & CAP_MODE_HAS_RAW)) + if ((device->model->capabilities & CAP_ENCODING_HAS_JPEG) + && (device->model->capabilities & CAP_ENCODING_HAS_RAW)) od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED; else od->cap = SANE_CAP_INACTIVE; @@ -649,7 +741,7 @@ init_options (BrotherDevice *device) od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = 1 * sizeof(SANE_Bool); - if (device->model->capabilities & CAP_MODE_BUTTON_SCAN_EMAIL) + if (device->model->capabilities & CAP_BUTTON_HAS_SCAN_EMAIL) od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else @@ -663,7 +755,7 @@ init_options (BrotherDevice *device) od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = 1 * sizeof(SANE_Bool); - if (device->model->capabilities & CAP_MODE_BUTTON_SCAN_FILE) + if (device->model->capabilities & CAP_BUTTON_HAS_SCAN_FILE) od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else @@ -677,7 +769,7 @@ init_options (BrotherDevice *device) od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = 1 * sizeof(SANE_Bool); - if (device->model->capabilities & CAP_MODE_BUTTON_SCAN_IMAGE) + if (device->model->capabilities & CAP_BUTTON_HAS_SCAN_IMAGE) od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else @@ -691,7 +783,7 @@ init_options (BrotherDevice *device) od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = 1 * sizeof(SANE_Bool); - if (device->model->capabilities & CAP_MODE_BUTTON_SCAN_OCR) + if (device->model->capabilities & CAP_BUTTON_HAS_SCAN_OCR) od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else @@ -1078,39 +1170,54 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, status = SANE_STATUS_GOOD; break; - case OPT_MODE: - if (strcmp (device->val[option].s, (SANE_String)value) == 0) - { - DBG (DBG_DETAIL, "sane_control_option: option %d (%s) not changed\n", - option, device->opt[option].name); - break; - } - strcpy (device->val[option].s, (SANE_String) value); + case OPT_MODE: + if (strcmp (device->val[option].s, (SANE_String)value) == 0) + { + DBG (DBG_DETAIL, "sane_control_option: option %d (%s) not changed\n", + option, device->opt[option].name); + break; + } + strcpy (device->val[option].s, (SANE_String) value); - myinfo |= SANE_INFO_RELOAD_PARAMS; - myinfo |= SANE_INFO_RELOAD_OPTIONS; - DBG (DBG_DETAIL, "sane_control_option: set option %d (%s) to %s\n", - option, device->opt[option].name, (SANE_String) value); + myinfo |= SANE_INFO_RELOAD_PARAMS; + myinfo |= SANE_INFO_RELOAD_OPTIONS; + DBG (DBG_DETAIL, "sane_control_option: set option %d (%s) to %s\n", + option, device->opt[option].name, (SANE_String) value); - /* - * Mode affects other options: - * - * OPT_CONTRAST - * OPT_BRIGHTNESS - * - */ - if ((strcmp((SANE_String)value, SANE_VALUE_SCAN_MODE_COLOR) == 0) || - (strcmp((SANE_String)value, SANE_VALUE_SCAN_MODE_GRAY) == 0)) - { + /* + * Mode affects other options: + * + * OPT_CONTRAST + * OPT_BRIGHTNESS + * + */ + if ((strcmp((SANE_String)value, SANE_VALUE_SCAN_MODE_COLOR) == 0) || + (strcmp((SANE_String)value, SANE_VALUE_SCAN_MODE_GRAY) == 0)) + { device->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; device->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; - } - else - { + } + else + { device->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; device->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; - } - break; + } + break; + + case OPT_SOURCE: + if (strcmp (device->val[option].s, (SANE_String)value) == 0) + { + DBG (DBG_DETAIL, "sane_control_option: option %d (%s) not changed\n", + option, device->opt[option].name); + break; + } + strcpy (device->val[option].s, (SANE_String) value); + + myinfo |= SANE_INFO_RELOAD_PARAMS; + myinfo |= SANE_INFO_RELOAD_OPTIONS; + DBG (DBG_DETAIL, "sane_control_option: set option %d (%s) to %s\n", + option, device->opt[option].name, (SANE_String) value); + break; default: DBG (DBG_SERIOUS, "sane_control_option: trying to set unexpected option\n"); @@ -1140,11 +1247,12 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, (device->opt[option].unit == SANE_UNIT_DPI ? "dpi" : "")); break; } - case OPT_MODE: /* String (list) options */ - strcpy ((SANE_String)value, device->val[option].s); - DBG (DBG_DETAIL, "sane_control_option: get option %d (%s), value=`%s'\n", - option, device->opt[option].name, (SANE_String) value); - break; + case OPT_MODE: /* String (list) options */ + case OPT_SOURCE: + strcpy ((SANE_String)value, device->val[option].s); + DBG (DBG_DETAIL, "sane_control_option: get option %d (%s), value=`%s'\n", + option, device->opt[option].name, (SANE_String) value); + break; case OPT_RESOLUTION: case OPT_X_RESOLUTION: @@ -1273,6 +1381,29 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) } } + + /* + * Get the source from the option. + * Also note if we are doing centered geometry. + * + */ + if (strcmp(device->val[OPT_SOURCE].s, SANE_VALUE_SOURCE_FLATBED) == 0) + { + rc = device->driver->SetSource(BROTHER_SOURCE_FLATBED); + if (rc != SANE_STATUS_GOOD) + { + return rc; + } + } + else if (strcmp(device->val[OPT_SOURCE].s, SANE_VALUE_SOURCE_ADF) == 0) + { + rc = device->driver->SetSource(BROTHER_SOURCE_ADF); + if (rc != SANE_STATUS_GOOD) + { + return rc; + } + } + /* * Compute the geometry in terms of pixels at the selected resolution. * This is how the scanner wants it. @@ -1289,13 +1420,14 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) */ // pixel_x_width += 16; + SANE_Int pixel_x_offset = SANE_UNFIX (device->val[OPT_TL_X].w) / MM_IN_INCH * x_res; + SANE_Int pixel_y_height = SANE_UNFIX (device->val[OPT_BR_Y].w - device->val[OPT_TL_Y].w) / MM_IN_INCH * y_res; - SANE_Int pixel_x_offset = SANE_UNFIX (device->val[OPT_TL_X].w) / MM_IN_INCH * x_res; - SANE_Int pixel_y_offset = SANE_UNFIX (device->val[OPT_TL_Y].w) / MM_IN_INCH * y_res; + params->lines = pixel_y_height; params->last_frame = SANE_TRUE; diff --git a/testsuite/backend/brother_mfp/brother_mfp_tests_family4.cpp b/testsuite/backend/brother_mfp/brother_mfp_tests_family4.cpp index dac8e8608..748de2771 100644 --- a/testsuite/backend/brother_mfp/brother_mfp_tests_family4.cpp +++ b/testsuite/backend/brother_mfp/brother_mfp_tests_family4.cpp @@ -101,28 +101,28 @@ static void test_family4_decode_basic_param_resp() static void test_family4_decode_adf_resp() { DecodeStatus decode_resp; - BrotherADFResponse adf_resp; + BrotherSourceStatusResponse adf_resp; BrotherEncoderFamily4 encoder(0); // SUCCESS status const SANE_Byte *data = (const SANE_Byte *)"\xc2"; - decode_resp = encoder.DecodeADFBlockResp (data, 1, adf_resp); + decode_resp = encoder.DecodeSourceStatusBlockResp (data, 1, adf_resp); ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); - ASSERT_FALSE(adf_resp.adf_ready); + ASSERT_FALSE(adf_resp.source_ready); data = (const SANE_Byte *)"\x80"; - decode_resp = encoder.DecodeADFBlockResp (data, 1, adf_resp); + decode_resp = encoder.DecodeSourceStatusBlockResp (data, 1, adf_resp); ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); - ASSERT_TRUE(adf_resp.adf_ready); + ASSERT_TRUE(adf_resp.source_ready); // Wrong length. - decode_resp = encoder.DecodeADFBlockResp (data, 0, adf_resp); + decode_resp = encoder.DecodeSourceStatusBlockResp (data, 0, adf_resp); ASSERT_EQ(decode_resp, DECODE_STATUS_ERROR); - decode_resp = encoder.DecodeADFBlockResp (data, 20, adf_resp); + decode_resp = encoder.DecodeSourceStatusBlockResp (data, 20, adf_resp); ASSERT_EQ(decode_resp, DECODE_STATUS_ERROR); } @@ -376,7 +376,7 @@ static void test_family4_encode_adf() BrotherEncoderFamily4 encoder(0); // Standard call. - decode_resp = encoder.EncodeADFBlock (data_buffer, sizeof(data_buffer), &ret_length); + decode_resp = encoder.EncodeSourceStatusBlock (data_buffer, sizeof(data_buffer), &ret_length); ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); @@ -387,7 +387,7 @@ static void test_family4_encode_adf() } // Buffer too short. - decode_resp = encoder.EncodeADFBlock (data_buffer, 5, &ret_length); + decode_resp = encoder.EncodeSourceStatusBlock (data_buffer, 5, &ret_length); ASSERT_EQ(decode_resp, DECODE_STATUS_INVAL); }