summaryrefslogtreecommitdiff
path: root/backend/genesys/device.h
diff options
context:
space:
mode:
Diffstat (limited to 'backend/genesys/device.h')
-rw-r--r--backend/genesys/device.h387
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