kopia lustrzana https://gitlab.com/sane-project/backends
brother_mfp: Added support for source option.
Can now select Flatbed or ADF for supported machines.brother_mfp_backend
rodzic
ca760d54b3
commit
b64b8c13bb
|
@ -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.
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue