sane-project-backends/backend/brother_mfp/brother_mfp-encoder.h

634 wiersze
18 KiB
C++

/* sane - Scanner Access Now Easy.
BACKEND brother_mfp
Copyright (C) 2022 Ralph Little <skelband@gmail.com>
This file is part of the SANE package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
This file implements a SANE backend for Brother Multifunction Devices.
*/
#pragma once
#include "../include/sane/config.h"
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <jpeglib.h>
#include <jerror.h>
#include "brother_mfp-common.h"
#include "../include/sane/sane.h"
#include "../include/sane/sanei.h"
#include "../include/sane/saneopts.h"
#include "../include/sane/sanei_config.h"
#include "../include/sane/sanei_usb.h"
/*
* Functionality sets.
*
* For the moment, I am going to assume that the various proprietary
* drivers follow the broad protocol versions and I will reflect this
* until I see different.
*
* So these will reflect the brscan2, brscan3, etc that Brother use.
*
* We will have a encoder/decoder for each family.
* From what I have seen, pretty much all the Brother families implement
* the same basic protocol sequence, just with variations in technology.
* So we don't need to abstract out the entire sequence, just the encoding
* and decoding of each packet. The biggest aspect by far is the difference
* in scan data formats.
*
*/
typedef enum
{
BROTHER_FAMILY_NONE,
BROTHER_FAMILY_1,
BROTHER_FAMILY_2,
BROTHER_FAMILY_3,
BROTHER_FAMILY_4,
BROTHER_FAMILY_5
} BrotherFamily;
typedef enum
{
BROTHER_SCAN_MODE_COLOR,
BROTHER_SCAN_MODE_GRAY,
BROTHER_SCAN_MODE_GRAY_DITHERED,
BROTHER_SCAN_MODE_TEXT
} BrotherScanMode;
typedef SANE_Int BrotherSensor;
#define BROTHER_SENSOR_NONE 0
#define BROTHER_SENSOR_EMAIL (1 << 0)
#define BROTHER_SENSOR_FILE (1 << 1)
#define BROTHER_SENSOR_OCR (1 << 2)
#define BROTHER_SENSOR_IMAGE (1 << 3)
struct BrotherSessionResponse
{
SANE_Bool ready;
};
struct BrotherButtonQueryResponse
{
SANE_Bool has_button_press;
};
struct BrotherButtonStateResponse
{
BrotherSensor button_value; // raw value we get from the packet
};
struct BrotherParameters
{
BrotherParameters():
param_brightness (0),
param_contrast (0),
param_compression (SANE_TRUE),
param_pixel_x_offset (0),
param_pixel_x_width (0),
param_pixel_y_offset (0),
param_pixel_y_height (0),
param_scan_mode (BROTHER_SCAN_MODE_COLOR),
param_x_res(100),
param_y_res(100)
{
}
SANE_Int param_brightness;
SANE_Int param_contrast;
SANE_Bool param_compression;
SANE_Int param_pixel_x_offset;
SANE_Int param_pixel_x_width;
SANE_Int param_pixel_y_offset;
SANE_Int param_pixel_y_height;
BrotherScanMode param_scan_mode;
SANE_Int param_x_res;
SANE_Int param_y_res;
};
struct BrotherBasicParamResponse
{
int dummy;
// fill me
};
struct BrotherADFResponse
{
SANE_Byte resp_code;
};
/*
* DecodeStatus
*
* DECODE_STATUS_GOOD - decode finished. Nothing more to do.
* DECODE_STATUS_TRUNCATED - starved of input. Need more src data.
* DECODE_STATUS_MORE - starved of output. Have more output available.
* DECODE_STATUS_ERROR - format of the data is incorrect.
*
*/
enum DecodeStatus
{
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
};
struct ScanDataHeader
{
ScanDataHeader():
block_type(0),
block_len(0)
{
}
SANE_Byte block_type;
size_t block_len;
};
class BrotherEncoder
{
public:
BrotherEncoder ()
{
}
virtual ~BrotherEncoder ()
{
}
virtual void NewPage () = 0;
DecodeStatus SetScanMode (BrotherScanMode scan_mode);
DecodeStatus SetRes (SANE_Int x, SANE_Int y);
DecodeStatus SetContrast (SANE_Int contrast);
DecodeStatus SetBrightness (SANE_Int brightness);
DecodeStatus SetCompression (SANE_Bool compression);
DecodeStatus SetScanDimensions (SANE_Int pixel_x_offset, SANE_Int pixel_x_width,
SANE_Int pixel_y_offset, SANE_Int pixel_y_height);
SANE_Status DecodeStatusToSaneStatus(DecodeStatus dec_ret)
{
static SANE_Status status_lookup[] =
{
SANE_STATUS_GOOD,
SANE_STATUS_GOOD,
SANE_STATUS_EOF,
SANE_STATUS_EOF,
SANE_STATUS_EOF,
SANE_STATUS_CANCELLED,
SANE_STATUS_IO_ERROR,
SANE_STATUS_NO_MEM,
SANE_STATUS_INVAL,
SANE_STATUS_UNSUPPORTED
};
return status_lookup[dec_ret];
}
static const char* ScanModeToText (BrotherScanMode scan_mode);
virtual DecodeStatus DecodeSessionResp (const SANE_Byte *data, size_t data_len,
BrotherSessionResponse &response) = 0;
virtual DecodeStatus DecodeButtonQueryResp (const SANE_Byte *data, size_t data_len,
BrotherButtonQueryResponse &response) = 0;
virtual DecodeStatus DecodeButtonStateResp (const SANE_Byte *data, size_t data_len,
BrotherButtonStateResponse &response) = 0;
virtual DecodeStatus EncodeBasicParameterBlock (SANE_Byte *data, size_t data_len,
size_t *length) = 0;
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 DecodeADFBlockResp (const SANE_Byte *data, size_t data_len,
BrotherADFResponse &response) = 0;
virtual DecodeStatus EncodeParameterBlock (SANE_Byte *data, size_t data_len, size_t *length) = 0;
virtual DecodeStatus EncodeParameterBlockBlank (SANE_Byte *data, size_t data_len,
size_t *length) = 0;
virtual DecodeStatus DecodeScanData (const SANE_Byte *src_data, size_t src_data_len,
size_t *src_data_consumed, SANE_Byte *dst_data,
size_t dest_data_len, size_t *dest_data_written) = 0;
protected:
BrotherParameters scan_params;
};
#include <setjmp.h>
class BrotherJFIFDecoder
{
public:
BrotherJFIFDecoder():
decompress_bytes(0)
{
/*
* Not sure if this is a safe way to get the cinfo into
* a consistent state but at least all pointers will be NULL.
*
*/
(void)memset(&state.cinfo, 0, sizeof(state.cinfo));
// TODO: override error stuff to avoid exit on error.
// Also provide a mechanism to check for errors.
state.cinfo.err = jpeg_std_error(&state.jerr);
state.cinfo.err->error_exit = ErrorExitManager;
jpeg_create_decompress (&state.cinfo);
/*
* Set up source manager.
*
*/
state.src_mgr.init_source = InitSource;
state.src_mgr.fill_input_buffer = FillInputBuffer;
state.src_mgr.skip_input_data = SkipInputData;
state.src_mgr.resync_to_restart = jpeg_resync_to_restart;
state.src_mgr.term_source = TermSource;
state.cinfo.src = &state.src_mgr;
}
static void ErrorExitManager(j_common_ptr cinfo);
~BrotherJFIFDecoder()
{
jpeg_destroy_decompress(&state.cinfo);
}
void NewBlock();
void NewPage(const BrotherParameters &params);
DecodeStatus DecodeScanData (const SANE_Byte *src_data, size_t src_data_len,
size_t *src_data_consumed, SANE_Byte *dst_data, size_t dest_data_len,
size_t *dest_data_written);
private:
static void InitSource (j_decompress_ptr cinfo);
static boolean FillInputBuffer(j_decompress_ptr cinfo);
static void SkipInputData(j_decompress_ptr cinfo, long num_bytes);
static void TermSource(j_decompress_ptr cinfo);
DecodeStatus DecodeScanData_CompressBuffer (const SANE_Byte *src_data, size_t src_data_len,
size_t *src_data_consumed, SANE_Byte *dst_data, size_t dest_data_len,
size_t *dest_data_written);
struct CompressionState
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
struct jpeg_source_mgr src_mgr;
bool have_read_header;
} state;
SANE_Byte decompress_buffer[1024 * 16];
size_t decompress_bytes;
// TODO: Move me to the state.
static jmp_buf my_env;
BrotherParameters decode_params;
};
class BrotherGrayRLengthDecoder
{
public:
BrotherGrayRLengthDecoder()
{
}
void NewBlock();
void NewPage(const BrotherParameters &params);
DecodeStatus DecodeScanData (const SANE_Byte *src_data, size_t src_data_len,
size_t *src_data_consumed, SANE_Byte *dst_data, size_t dest_data_len,
size_t *dest_data_written);
private:
BrotherParameters decode_params;
};
class BrotherInterleavedRGBColourDecoder
{
public:
BrotherInterleavedRGBColourDecoder(SANE_Word capabilities):
capabilities(capabilities),
scanline_buffer(nullptr),
scanline_buffer_size(0),
scanline_length(0),
scanline_buffer_data(0)
{
}
~BrotherInterleavedRGBColourDecoder()
{
free(scanline_buffer);
}
void NewBlock();
void NewPage(const BrotherParameters &params);
DecodeStatus DecodeScanData (const SANE_Byte *src_data, size_t src_data_len,
size_t *src_data_consumed, SANE_Byte *dst_data, size_t dest_data_len,
size_t *dest_data_written);
enum ChannelEncoding
{
CHANNELS_RGB, // RGB
CHANNELS_CrYCb // YCrCb
};
private:
void ConvertYCbCrToRGB (SANE_Byte y, SANE_Byte cb, SANE_Byte cr, SANE_Byte *red, SANE_Byte *green,
SANE_Byte *blue);
BrotherParameters decode_params;
SANE_Word capabilities;
SANE_Byte *scanline_buffer;
size_t scanline_buffer_size;
size_t scanline_length;
size_t scanline_buffer_data;
};
class BrotherGrayRawDecoder
{
public:
BrotherGrayRawDecoder()
{
}
void NewBlock();
void NewPage(const BrotherParameters &params);
DecodeStatus DecodeScanData (const SANE_Byte *src_data, size_t src_data_len,
size_t *src_data_consumed, SANE_Byte *dst_data, size_t dest_data_len,
size_t *dest_data_written);
private:
BrotherParameters decode_params;
};
class BrotherEncoderFamily2 : public BrotherEncoder
{
public:
BrotherEncoderFamily2(SANE_Word capabilities):
colour_decoder(capabilities)
{
}
~BrotherEncoderFamily2 ()
{
}
void NewPage () override
{
current_header.block_type = 0;
jfif_decoder.NewPage (scan_params);
gray_decoder.NewPage (scan_params);
gray_raw_decoder.NewPage (scan_params);
colour_decoder.NewPage (scan_params);
}
DecodeStatus DecodeSessionResp (const SANE_Byte *data, size_t data_len,
BrotherSessionResponse &response) override;
DecodeStatus EncodeBasicParameterBlock (SANE_Byte *data, size_t data_len, size_t *length)
override;
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
{
(void) data;
(void) data_len;
(void) length;
return DECODE_STATUS_UNSUPPORTED;
}
DecodeStatus DecodeADFBlockResp (const SANE_Byte *data, size_t data_len,
BrotherADFResponse &response) override
{
(void) data;
(void) data_len;
(void) response;
return DECODE_STATUS_UNSUPPORTED;
}
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)
override;
DecodeStatus DecodeScanData (const SANE_Byte *src_data, size_t src_data_len,
size_t *src_data_consumed, SANE_Byte *dst_data, size_t dest_data_len,
size_t *dest_data_written) override;
DecodeStatus DecodeButtonQueryResp (const SANE_Byte *data, size_t data_len,
BrotherButtonQueryResponse &response) override;
DecodeStatus DecodeButtonStateResp (const SANE_Byte *data, size_t data_len,
BrotherButtonStateResponse &response) override;
private:
DecodeStatus DecodeScanDataHeader (const SANE_Byte *src_data, size_t src_data_len,
size_t *src_data_consumed, ScanDataHeader &header);
ScanDataHeader current_header;
BrotherJFIFDecoder jfif_decoder;
BrotherGrayRLengthDecoder gray_decoder;
BrotherGrayRawDecoder gray_raw_decoder;
BrotherInterleavedRGBColourDecoder colour_decoder;
};
class BrotherEncoderFamily3 : public BrotherEncoder
{
public:
BrotherEncoderFamily3(SANE_Word capabilities):
colour_decoder(capabilities)
{
}
~BrotherEncoderFamily3 ()
{
}
void NewPage() override
{
current_header.block_type = 0;
gray_raw_decoder.NewPage(scan_params);
gray_decoder.NewPage(scan_params);
colour_decoder.NewPage(scan_params);
jfif_decoder.NewPage(scan_params);
}
DecodeStatus DecodeSessionResp (const SANE_Byte *data, size_t data_len,
BrotherSessionResponse &response) override;
DecodeStatus EncodeBasicParameterBlock (SANE_Byte *data, size_t data_len, size_t *length)
override;
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
{
(void) data;
(void) data_len;
(void) length;
return DECODE_STATUS_UNSUPPORTED;
}
DecodeStatus DecodeADFBlockResp (const SANE_Byte *data, size_t data_len,
BrotherADFResponse &response) override
{
(void) data;
(void) data_len;
(void) response;
return DECODE_STATUS_UNSUPPORTED;
}
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)
override;
DecodeStatus DecodeScanData (const SANE_Byte *src_data, size_t src_data_len,
size_t *src_data_consumed, SANE_Byte *dst_data, size_t dest_data_len,
size_t *dest_data_written) override;
DecodeStatus DecodeButtonQueryResp (const SANE_Byte *data, size_t data_len,
BrotherButtonQueryResponse &response) override;
DecodeStatus DecodeButtonStateResp (const SANE_Byte *data, size_t data_len,
BrotherButtonStateResponse &response) override;
private:
DecodeStatus DecodeScanDataHeader (const SANE_Byte *src_data, size_t src_data_len,
size_t *src_data_consumed, ScanDataHeader &header);
ScanDataHeader current_header;
BrotherGrayRawDecoder gray_raw_decoder;
BrotherGrayRLengthDecoder gray_decoder;
BrotherInterleavedRGBColourDecoder colour_decoder;
BrotherJFIFDecoder jfif_decoder;
};
class BrotherEncoderFamily4 : public BrotherEncoder
{
public:
BrotherEncoderFamily4(SANE_Word capabilities)
{
(void)capabilities;
}
~BrotherEncoderFamily4 ()
{
}
void NewPage() override
{
current_header.block_type = 0;
jfif_decoder.NewPage(scan_params);
gray_decoder.NewPage (scan_params);
gray_raw_decoder.NewPage (scan_params);
}
DecodeStatus DecodeSessionResp (const SANE_Byte *data, size_t data_len,
BrotherSessionResponse &response) override;
DecodeStatus EncodeBasicParameterBlock (SANE_Byte *data, size_t data_len, size_t *length)
override;
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 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)
override;
DecodeStatus DecodeScanData (const SANE_Byte *src_data, size_t src_data_len,
size_t *src_data_consumed, SANE_Byte *dst_data, size_t dest_data_len,
size_t *dest_data_written) override;
DecodeStatus DecodeButtonQueryResp (const SANE_Byte *data, size_t data_len,
BrotherButtonQueryResponse &response) override;
DecodeStatus DecodeButtonStateResp (const SANE_Byte *data, size_t data_len,
BrotherButtonStateResponse &response) override;
private:
DecodeStatus DecodeScanDataHeader (const SANE_Byte *src_data, size_t src_data_len,
size_t *src_data_consumed, ScanDataHeader &header);
ScanDataHeader current_header;
BrotherJFIFDecoder jfif_decoder;
BrotherGrayRLengthDecoder gray_decoder;
BrotherGrayRawDecoder gray_raw_decoder;
};