diff options
Diffstat (limited to 'backend/genesys/device.h')
-rw-r--r-- | backend/genesys/device.h | 387 |
1 files changed, 387 insertions, 0 deletions
diff --git a/backend/genesys/device.h b/backend/genesys/device.h new file mode 100644 index 0000000..6c744c9 --- /dev/null +++ b/backend/genesys/device.h @@ -0,0 +1,387 @@ +/* sane - Scanner Access Now Easy. + + Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt> + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, the authors of SANE give permission for + additional uses of the libraries contained in this release of SANE. + + The exception is that, if you link a SANE library with other files + to produce an executable, this does not by itself cause the + resulting executable to be covered by the GNU General Public + License. Your use of that executable is in no way restricted on + account of linking the SANE library code into it. + + This exception does not, however, invalidate any other reasons why + the executable file might be covered by the GNU General Public + License. + + If you submit changes to SANE to the maintainers to be included in + a subsequent release, you agree by submitting the changes that + those changes may be distributed with this exception intact. + + If you write modifications of your own for SANE, it is your choice + whether to permit this exception to apply to your modifications. + If you do not wish that, delete this exception notice. +*/ + +#ifndef BACKEND_GENESYS_DEVICE_H +#define BACKEND_GENESYS_DEVICE_H + +#include "calibration.h" +#include "command_set.h" +#include "buffer.h" +#include "enums.h" +#include "image_pipeline.h" +#include "motor.h" +#include "settings.h" +#include "sensor.h" +#include "register.h" +#include "usb_device.h" +#include "scanner_interface.h" +#include <vector> + +namespace genesys { + +struct Genesys_Gpo +{ + Genesys_Gpo() = default; + + // Genesys_Gpo + GpioId id = GpioId::UNKNOWN; + + /* GL646 and possibly others: + - have the value registers at 0x66 and 0x67 + - have the enable registers at 0x68 and 0x69 + + GL841, GL842, GL843, GL846, GL848 and possibly others: + - have the value registers at 0x6c and 0x6d. + - have the enable registers at 0x6e and 0x6f. + */ + GenesysRegisterSettingSet regs; +}; + +/// Stores a SANE_Fixed value which is automatically converted from and to floating-point values +class FixedFloat +{ +public: + FixedFloat() = default; + FixedFloat(const FixedFloat&) = default; + FixedFloat(double number) : value_{SANE_FIX(number)} {} + FixedFloat& operator=(const FixedFloat&) = default; + FixedFloat& operator=(double number) { value_ = SANE_FIX(number); return *this; } + + operator double() const { return value(); } + + double value() const { return SANE_UNFIX(value_); } + +private: + SANE_Fixed value_ = 0; +}; + +struct MethodResolutions +{ + std::vector<ScanMethod> methods; + std::vector<unsigned> resolutions_x; + std::vector<unsigned> resolutions_y; + + unsigned get_min_resolution_x() const + { + return *std::min_element(resolutions_x.begin(), resolutions_x.end()); + } + + unsigned get_min_resolution_y() const + { + return *std::min_element(resolutions_y.begin(), resolutions_y.end()); + } + + std::vector<unsigned> get_resolutions() const; +}; + +/** @brief structure to describe a scanner model + * This structure describes a model. It is composed of information on the + * sensor, the motor, scanner geometry and flags to drive operation. + */ +struct Genesys_Model +{ + Genesys_Model() = default; + + const char* name = nullptr; + const char* vendor = nullptr; + const char* model = nullptr; + ModelId model_id = ModelId::UNKNOWN; + + AsicType asic_type = AsicType::UNKNOWN; + + // possible x and y resolutions for each method supported by the scanner + std::vector<MethodResolutions> resolutions; + + // possible depths in gray mode + std::vector<unsigned> bpp_gray_values; + // possible depths in color mode + std::vector<unsigned> bpp_color_values; + + // the default scanning method. This is used when moving the head for example + ScanMethod default_method = ScanMethod::FLATBED; + + // All offsets below are with respect to the sensor home position + + // Start of scan area in mm + FixedFloat x_offset = 0; + + // Start of scan area in mm (Amount of feeding needed to get to the medium) + FixedFloat y_offset = 0; + + // Size of scan area in mm + FixedFloat x_size = 0; + + // Size of scan area in mm + FixedFloat y_size = 0; + + // Start of white strip in mm + FixedFloat y_offset_calib_white = 0; + + // Start of black mark in mm + FixedFloat x_offset_calib_black = 0; + + // Start of scan area in transparency mode in mm + FixedFloat x_offset_ta = 0; + + // Start of scan area in transparency mode in mm + FixedFloat y_offset_ta = 0; + + // Size of scan area in transparency mode in mm + FixedFloat x_size_ta = 0; + + // Size of scan area in transparency mode in mm + FixedFloat y_size_ta = 0; + + // The position of the sensor when it's aligned with the lamp for transparency scanning + FixedFloat y_offset_sensor_to_ta = 0; + + // Start of white strip in transparency mode in mm + FixedFloat y_offset_calib_white_ta = 0; + + // Start of black strip in transparency mode in mm + FixedFloat y_offset_calib_black_ta = 0; + + // Size of scan area after paper sensor stop sensing document in mm + FixedFloat post_scan = 0; + + // Amount of feeding needed to eject document after finishing scanning in mm + FixedFloat eject_feed = 0; + + // Line-distance correction (in pixel at optical_ydpi) for CCD scanners + SANE_Int ld_shift_r = 0; + SANE_Int ld_shift_g = 0; + SANE_Int ld_shift_b = 0; + + // Order of the CCD/CIS colors + ColorOrder line_mode_color_order = ColorOrder::RGB; + + // Is this a CIS or CCD scanner? + bool is_cis = false; + + // Is this sheetfed scanner? + bool is_sheetfed = false; + + // sensor type + SensorId sensor_id = SensorId::UNKNOWN; + // Analog-Digital converter type + AdcId adc_id = AdcId::UNKNOWN; + // General purpose output type + GpioId gpio_id = GpioId::UNKNOWN; + // stepper motor type + MotorId motor_id = MotorId::UNKNOWN; + + // Which hacks are needed for this scanner? + SANE_Word flags = 0; + + // Button flags, described existing buttons for the model + SANE_Word buttons = 0; + + // how many lines are used for shading calibration + SANE_Int shading_lines = 0; + // how many lines are used for shading calibration in TA mode + SANE_Int shading_ta_lines = 0; + // how many lines are used to search start position + SANE_Int search_lines = 0; + + const MethodResolutions& get_resolution_settings(ScanMethod method) const; + + std::vector<unsigned> get_resolutions(ScanMethod method) const; +}; + +/** + * Describes the current device status for the backend + * session. This should be more accurately called + * Genesys_Session . + */ +struct Genesys_Device +{ + Genesys_Device() = default; + ~Genesys_Device(); + + using Calibration = std::vector<Genesys_Calibration_Cache>; + + // frees commonly used data + void clear(); + + SANE_Word vendorId = 0; /**< USB vendor identifier */ + SANE_Word productId = 0; /**< USB product identifier */ + + // USB mode: + // 0: not set + // 1: USB 1.1 + // 2: USB 2.0 + SANE_Int usb_mode = 0; + + std::string file_name; + std::string calib_file; + + // if enabled, no calibration data will be loaded or saved to files + SANE_Int force_calibration = 0; + // if enabled, will ignore the scan offsets and start scanning at true origin. This allows + // acquiring the positions of the black and white strips and the actual scan area + bool ignore_offsets = false; + + Genesys_Model *model = nullptr; + + // pointers to low level functions + std::unique_ptr<CommandSet> cmd_set; + + Genesys_Register_Set reg; + Genesys_Register_Set calib_reg; + Genesys_Settings settings; + Genesys_Frontend frontend, frontend_initial; + + // whether the frontend is initialized. This is currently used just to preserve historical + // behavior + bool frontend_is_init = false; + + Genesys_Gpo gpo; + Genesys_Motor motor; + std::uint8_t control[6] = {}; + + size_t average_size = 0; + // number of pixels used during shading calibration + size_t calib_pixels = 0; + // number of lines used during shading calibration + size_t calib_lines = 0; + size_t calib_channels = 0; + size_t calib_resolution = 0; + // bytes to read from USB when calibrating. If 0, this is not set + size_t calib_total_bytes_to_read = 0; + + // the session that was configured for calibration + ScanSession calib_session; + + // certain scanners support much higher resolution when scanning transparency, but we can't + // read whole width of the scanner as a single line at that resolution. Thus for stuff like + // calibration we want to read only the possible calibration area. + size_t calib_pixels_offset = 0; + + // gamma overrides. If a respective array is not empty then it means that the gamma for that + // color is overridden. + std::vector<std::uint16_t> gamma_override_tables[3]; + + std::vector<std::uint16_t> white_average_data; + std::vector<std::uint16_t> dark_average_data; + + bool already_initialized = false; + + bool read_active = false; + // signal wether the park command has been issued + bool parking = false; + + // for sheetfed scanner's, is TRUE when there is a document in the scanner + bool document = false; + + Genesys_Buffer read_buffer; + + // buffer for digital lineart from gray data + Genesys_Buffer binarize_buffer; + // local buffer for gray data during dynamix lineart + Genesys_Buffer local_buffer; + + // total bytes read sent to frontend + size_t total_bytes_read = 0; + // total bytes read to be sent to frontend + size_t total_bytes_to_read = 0; + + // contains computed data for the current setup + ScanSession session; + + // look up table used in dynamic rasterization + unsigned char lineart_lut[256] = {}; + + Calibration calibration_cache; + + // number of scan lines used during scan + int line_count = 0; + + // array describing the order of the sub-segments of the sensor + std::vector<unsigned> segment_order; + + // buffer to handle even/odd data + Genesys_Buffer oe_buffer = {}; + + // stores information about how the input image should be processed + ImagePipelineStack pipeline; + + // an buffer that allows reading from `pipeline` in chunks of any size + ImageBuffer pipeline_buffer; + + // when true the scanned picture is first buffered to allow software image enhancements + bool buffer_image = false; + + // image buffer where the scanned picture is stored + std::vector<std::uint8_t> img_buffer; + + ImagePipelineNodeBytesSource& get_pipeline_source(); + + std::unique_ptr<ScannerInterface> interface; + + bool is_head_pos_known(ScanHeadId scan_head) const; + unsigned head_pos(ScanHeadId scan_head) const; + void set_head_pos_unknown(); + void set_head_pos_zero(ScanHeadId scan_head); + void advance_head_pos_by_session(ScanHeadId scan_head); + void advance_head_pos_by_steps(ScanHeadId scan_head, Direction direction, unsigned steps); + +private: + // the position of the primary scan head in motor->base_dpi units + unsigned head_pos_primary_ = 0; + bool is_head_pos_primary_known_ = true; + + // the position of the secondary scan head in motor->base_dpi units. Only certain scanners + // have a secondary scan head. + unsigned head_pos_secondary_ = 0; + bool is_head_pos_secondary_known_ = true; + + friend class ScannerInterfaceUsb; +}; + +std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev); + +void apply_reg_settings_to_device(Genesys_Device& dev, const GenesysRegisterSettingSet& regs); + +} // namespace genesys + +#endif |