summaryrefslogtreecommitdiff
path: root/backend/genesys_low.h
diff options
context:
space:
mode:
Diffstat (limited to 'backend/genesys_low.h')
-rw-r--r--backend/genesys_low.h1901
1 files changed, 1349 insertions, 552 deletions
diff --git a/backend/genesys_low.h b/backend/genesys_low.h
index 56627b4..e750808 100644
--- a/backend/genesys_low.h
+++ b/backend/genesys_low.h
@@ -1,4 +1,4 @@
-/* sane - Scanner Access Now Easy.
+/* sane - Scanner Access Now Easy.
Copyright (C) 2003 Oliver Rauch
Copyright (C) 2003, 2004 Henning Meier-Geinitz <henning@meier-geinitz.de>
@@ -81,56 +81,20 @@
#include "../include/_stdint.h"
-#ifndef UNIT_TESTING
-#define GENESYS_STATIC static
-#else
-#define GENESYS_STATIC
-#endif
-
-#define DBG_error0 0 /* errors/warnings printed even with devuglevel 0 */
-#define DBG_error 1 /* fatal errors */
-#define DBG_init 2 /* initialization and scanning time messages */
-#define DBG_warn 3 /* warnings and non-fatal errors */
-#define DBG_info 4 /* informational messages */
-#define DBG_proc 5 /* starting/finishing functions */
-#define DBG_io 6 /* io functions */
-#define DBG_io2 7 /* io functions that are called very often */
-#define DBG_data 8 /* log image data */
-
-/**
- * call a function and return on error
- */
-#define RIE(function) \
- do { status = function; \
- if (status != SANE_STATUS_GOOD) \
- { \
- DBG(DBG_error, "%s: %s\n", __func__, sane_strstatus (status)); \
- return status; \
- } \
- } while (SANE_FALSE)
-
-#define RIEF(function, mem) \
- do { status = function; \
- if (status != SANE_STATUS_GOOD) \
- { \
- free(mem); \
- DBG(DBG_error, "%s: %s\n", __func__, sane_strstatus (status)); \
- return status; \
- } \
- } while (SANE_FALSE)
-
-#define RIEF2(function, mem1, mem2) \
- do { status = function; \
- if (status != SANE_STATUS_GOOD) \
- { \
- free(mem1); \
- free(mem2); \
- return status; \
- } \
- } while (SANE_FALSE)
-
-#define DBGSTART DBG (DBG_proc, "%s start\n", __func__);
-#define DBGCOMPLETED DBG (DBG_proc, "%s completed\n", __func__);
+#include "genesys_error.h"
+#include "genesys_sanei.h"
+#include "genesys_serialize.h"
+
+#include <algorithm>
+#include <array>
+#include <cstring>
+#include <functional>
+#include <iostream>
+#include <limits>
+#include <memory>
+#include <stdexcept>
+#include <string>
+#include <vector>
#define FREE_IFNOT_NULL(x) if(x!=NULL) { free(x); x=NULL;}
@@ -163,11 +127,12 @@
#define GENESYS_FLAG_DARK_WHITE_CALIBRATION (1 << 12) /**< yet another calibration method. does white and dark shading in one run, depending on a black and a white strip*/
#define GENESYS_FLAG_CUSTOM_GAMMA (1 << 13) /**< allow custom gamma tables */
#define GENESYS_FLAG_NO_CALIBRATION (1 << 14) /**< allow scanners to use skip the calibration, needed for sheetfed scanners */
-#define GENESYS_FLAG_HALF_CCD_MODE (1 << 15) /**< scanner has setting for half ccd mode */
#define GENESYS_FLAG_SIS_SENSOR (1 << 16) /**< handling of multi-segments sensors in software */
#define GENESYS_FLAG_SHADING_NO_MOVE (1 << 17) /**< scanner doesn't move sensor during shading calibration */
#define GENESYS_FLAG_SHADING_REPARK (1 << 18) /**< repark head between shading scans */
#define GENESYS_FLAG_FULL_HWDPI_MODE (1 << 19) /**< scanner always use maximum hw dpi to setup the sensor */
+// scanner has infrared transparency scanning capability
+#define GENESYS_FLAG_HAS_UTA_INFRARED (1 << 20)
#define GENESYS_HAS_NO_BUTTONS 0 /**< scanner has no supported button */
#define GENESYS_HAS_SCAN_SW (1 << 0) /**< scanner has SCAN button */
@@ -207,9 +172,6 @@
#define BULK_RAM 0x00
#define BULK_REGISTER 0x11
-#define BULKIN_MAXSIZE 0xFE00
-#define GL646_BULKIN_MAXSIZE 0xFFC0
-#define GL646_BULKIN_MINSIZE 0x0800
#define BULKOUT_MAXSIZE 0xF000
/* AFE values */
@@ -236,77 +198,619 @@
#define FEBUSY 0x02
#define MOTORENB 0x01
-typedef struct Genesys_Register_Set
+#define GENESYS_MAX_REGS 256
+
+enum class ScanMethod : unsigned {
+ // normal scan method
+ FLATBED = 0,
+ // scan using transparency adaptor
+ TRANSPARENCY = 1,
+ // scan using transparency adaptor via infrared channel
+ TRANSPARENCY_INFRARED = 2
+};
+
+inline void serialize(std::istream& str, ScanMethod& x)
+{
+ unsigned value;
+ serialize(str, value);
+ x = static_cast<ScanMethod>(value);
+}
+
+inline void serialize(std::ostream& str, ScanMethod& x)
+{
+ unsigned value = static_cast<unsigned>(x);
+ serialize(str, value);
+}
+
+enum class ScanColorMode : unsigned {
+ LINEART = 0,
+ HALFTONE,
+ GRAY,
+ COLOR_SINGLE_PASS
+};
+
+inline void serialize(std::istream& str, ScanColorMode& x)
+{
+ unsigned value;
+ serialize(str, value);
+ x = static_cast<ScanColorMode>(value);
+}
+
+inline void serialize(std::ostream& str, ScanColorMode& x)
+{
+ unsigned value = static_cast<unsigned>(x);
+ serialize(str, value);
+}
+
+enum class ColorFilter : unsigned {
+ RED = 0,
+ GREEN,
+ BLUE,
+ NONE
+};
+
+inline void serialize(std::istream& str, ColorFilter& x)
+{
+ unsigned value;
+ serialize(str, value);
+ x = static_cast<ColorFilter>(value);
+}
+
+inline void serialize(std::ostream& str, ColorFilter& x)
+{
+ unsigned value = static_cast<unsigned>(x);
+ serialize(str, value);
+}
+
+struct GenesysRegister {
+ uint16_t address = 0;
+ uint8_t value = 0;
+};
+
+inline bool operator<(const GenesysRegister& lhs, const GenesysRegister& rhs)
+{
+ return lhs.address < rhs.address;
+}
+
+struct GenesysRegisterSetState {
+ bool is_lamp_on = false;
+ bool is_xpa_on = false;
+};
+
+class Genesys_Register_Set {
+public:
+ using container = std::vector<GenesysRegister>;
+ using iterator = typename container::iterator;
+ using const_iterator = typename container::const_iterator;
+
+ // FIXME: this shouldn't live here, but in a separate struct that contains Genesys_Register_Set
+ GenesysRegisterSetState state;
+
+ enum Options {
+ SEQUENTIAL = 1
+ };
+
+ Genesys_Register_Set()
+ {
+ registers_.reserve(GENESYS_MAX_REGS);
+ }
+
+ // by default the register set is sorted by address. In certain cases it's importand to send
+ // the registers in certain order: use the SEQUENTIAL option for that
+ Genesys_Register_Set(Options opts) : Genesys_Register_Set()
+ {
+ if ((opts & SEQUENTIAL) == SEQUENTIAL) {
+ sorted_ = false;
+ }
+ }
+
+ void init_reg(uint16_t address, uint8_t default_value)
+ {
+ if (find_reg_index(address) >= 0) {
+ set8(address, default_value);
+ return;
+ }
+ GenesysRegister reg;
+ reg.address = address;
+ reg.value = default_value;
+ registers_.push_back(reg);
+ if (sorted_)
+ std::sort(registers_.begin(), registers_.end());
+ }
+
+ void remove_reg(uint16_t address)
+ {
+ int i = find_reg_index(address);
+ if (i < 0) {
+ throw std::runtime_error("the register does not exist");
+ }
+ registers_.erase(registers_.begin() + i);
+ }
+
+ GenesysRegister& find_reg(uint16_t address)
+ {
+ int i = find_reg_index(address);
+ if (i < 0) {
+ throw std::runtime_error("the register does not exist");
+ }
+ return registers_[i];
+ }
+
+ const GenesysRegister& find_reg(uint16_t address) const
+ {
+ int i = find_reg_index(address);
+ if (i < 0) {
+ throw std::runtime_error("the register does not exist");
+ }
+ return registers_[i];
+ }
+
+ GenesysRegister* find_reg_address(uint16_t address)
+ {
+ return &find_reg(address);
+ }
+
+ const GenesysRegister* find_reg_address(uint16_t address) const
+ {
+ return &find_reg(address);
+ }
+
+ void set8(uint16_t address, uint8_t value)
+ {
+ find_reg(address).value = value;
+ }
+
+ void set8_mask(uint16_t address, uint8_t value, uint8_t mask)
+ {
+ auto& reg = find_reg(address);
+ reg.value = (reg.value & ~mask) | value;
+ }
+
+ void set16(uint16_t address, uint16_t value)
+ {
+ find_reg(address).value = (value >> 8) & 0xff;
+ find_reg(address + 1).value = value & 0xff;
+ }
+
+ void set24(uint16_t address, uint32_t value)
+ {
+ find_reg(address).value = (value >> 16) & 0xff;
+ find_reg(address + 1).value = (value >> 8) & 0xff;
+ find_reg(address + 2).value = value & 0xff;
+ }
+
+ uint8_t get8(uint16_t address) const
+ {
+ return find_reg(address).value;
+ }
+
+ uint16_t get16(uint16_t address) const
+ {
+ return (find_reg(address).value << 8) | find_reg(address + 1).value;
+ }
+
+ uint32_t get24(uint16_t address) const
+ {
+ return (find_reg(address).value << 16) |
+ (find_reg(address + 1).value << 8) |
+ find_reg(address + 2).value;
+ }
+
+ void clear() { registers_.clear(); }
+ size_t size() const { return registers_.size(); }
+
+ iterator begin() { return registers_.begin(); }
+ const_iterator begin() const { return registers_.begin(); }
+
+ iterator end() { return registers_.end(); }
+ const_iterator end() const { return registers_.end(); }
+
+private:
+ int find_reg_index(uint16_t address) const
+ {
+ if (!sorted_) {
+ for (size_t i = 0; i < registers_.size(); i++) {
+ if (registers_[i].address == address) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ GenesysRegister search;
+ search.address = address;
+ auto it = std::lower_bound(registers_.begin(), registers_.end(), search);
+ if (it == registers_.end())
+ return -1;
+ if (it->address != address)
+ return -1;
+ return std::distance(registers_.begin(), it);
+ }
+
+ // registers are stored in a sorted vector
+ bool sorted_ = true;
+ std::vector<GenesysRegister> registers_;
+};
+
+template<class T, size_t Size>
+struct AssignableArray : public std::array<T, Size> {
+ AssignableArray() = default;
+ AssignableArray(const AssignableArray&) = default;
+ AssignableArray& operator=(const AssignableArray&) = default;
+
+ AssignableArray& operator=(std::initializer_list<T> init)
+ {
+ if (init.size() != std::array<T, Size>::size())
+ throw std::runtime_error("An array of incorrect size assigned");
+ std::copy(init.begin(), init.end(), std::array<T, Size>::begin());
+ return *this;
+ }
+};
+
+struct GenesysRegisterSetting {
+ GenesysRegisterSetting() = default;
+
+ GenesysRegisterSetting(uint16_t p_address, uint8_t p_value) :
+ address(p_address), value(p_value)
+ {}
+
+ GenesysRegisterSetting(uint16_t p_address, uint8_t p_value, uint8_t p_mask) :
+ address(p_address), value(p_value), mask(p_mask)
+ {}
+
+ uint16_t address = 0;
+ uint8_t value = 0;
+ uint8_t mask = 0xff;
+
+ bool operator==(const GenesysRegisterSetting& other) const
+ {
+ return address == other.address && value == other.value && mask == other.mask;
+ }
+};
+
+template<class Stream>
+void serialize(Stream& str, GenesysRegisterSetting& reg)
+{
+ serialize(str, reg.address);
+ serialize(str, reg.value);
+ serialize(str, reg.mask);
+}
+
+class GenesysRegisterSettingSet {
+public:
+ using container = std::vector<GenesysRegisterSetting>;
+ using iterator = typename container::iterator;
+ using const_iterator = typename container::const_iterator;
+
+ GenesysRegisterSettingSet() = default;
+ GenesysRegisterSettingSet(std::initializer_list<GenesysRegisterSetting> ilist) : regs_(ilist) {}
+
+ iterator begin() { return regs_.begin(); }
+ const_iterator begin() const { return regs_.begin(); }
+ iterator end() { return regs_.end(); }
+ const_iterator end() const { return regs_.end(); }
+
+ GenesysRegisterSetting& operator[](size_t i) { return regs_[i]; }
+ const GenesysRegisterSetting& operator[](size_t i) const { return regs_[i]; }
+
+ size_t size() const { return regs_.size(); }
+ bool empty() const { return regs_.empty(); }
+ void clear() { regs_.clear(); }
+
+ void push_back(GenesysRegisterSetting reg) { regs_.push_back(reg); }
+
+ void merge(const GenesysRegisterSettingSet& other)
+ {
+ for (const auto& reg : other) {
+ set_value(reg.address, reg.value);
+ }
+ }
+
+ uint8_t get_value(uint16_t address) const
+ {
+ for (const auto& reg : regs_) {
+ if (reg.address == address)
+ return reg.value;
+ }
+ throw std::runtime_error("Unknown register");
+ }
+
+ void set_value(uint16_t address, uint8_t value)
+ {
+ for (auto& reg : regs_) {
+ if (reg.address == address) {
+ reg.value = value;
+ return;
+ }
+ }
+ push_back(GenesysRegisterSetting(address, value));
+ }
+
+ friend void serialize(std::istream& str, GenesysRegisterSettingSet& reg);
+ friend void serialize(std::ostream& str, GenesysRegisterSettingSet& reg);
+
+ bool operator==(const GenesysRegisterSettingSet& other) const
+ {
+ return regs_ == other.regs_;
+ }
+
+private:
+ std::vector<GenesysRegisterSetting> regs_;
+};
+
+inline void serialize(std::istream& str, GenesysRegisterSettingSet& reg)
+{
+ reg.clear();
+ const size_t max_register_address =
+ 1 << (sizeof(GenesysRegisterSetting::address) * CHAR_BIT);
+ serialize(str, reg.regs_, max_register_address);
+}
+
+inline void serialize(std::ostream& str, GenesysRegisterSettingSet& reg)
+{
+ serialize(str, reg.regs_);
+}
+
+struct GenesysFrontendLayout
{
- uint16_t address;
- uint8_t value;
-} Genesys_Register_Set;
+ std::array<uint16_t, 3> offset_addr = {};
+ std::array<uint16_t, 3> gain_addr = {};
+
+ bool operator==(const GenesysFrontendLayout& other) const
+ {
+ return offset_addr == other.offset_addr && gain_addr == other.gain_addr;
+ }
+};
/** @brief Data structure to set up analog frontend.
- * The analog frontend converts analog value from image sensor to
- * digital value. It has its own control registers which are set up
- * with this structure. The values are written using sanei_genesys_fe_write_data.
- * The actual register addresses they map to depends on the frontend used.
- * @see sanei_genesys_fe_write_data
+ The analog frontend converts analog value from image sensor to digital value. It has its own
+ control registers which are set up with this structure. The values are written using
+ sanei_genesys_fe_write_data.
*/
-typedef struct
+struct Genesys_Frontend
{
- uint8_t fe_id; /**< id of the frontend description */
- uint8_t reg[4]; /**< values to set up frontend control register, they
- usually map to analog register 0x00 to 0x03 */
- uint8_t sign[3]; /**< sets the sign of the digital value */
- uint8_t offset[3]; /**< offset correction to apply to signal, most often
- maps to frontend register 0x20-0x22 */
- uint8_t gain[3]; /**< amplification to apply to signal, most often
- maps to frontend register 0x28-0x2a */
- uint8_t reg2[3]; /**< extra control registers */
-} Genesys_Frontend;
-
-typedef struct
+ Genesys_Frontend() = default;
+
+ // id of the frontend description
+ uint8_t fe_id = 0;
+
+ // all registers of the frontend
+ GenesysRegisterSettingSet regs;
+
+ // extra control registers
+ std::array<uint8_t, 3> reg2 = {};
+
+ GenesysFrontendLayout layout;
+
+ void set_offset(unsigned which, uint8_t value)
+ {
+ regs.set_value(layout.offset_addr[which], value);
+ }
+
+ void set_gain(unsigned which, uint8_t value)
+ {
+ regs.set_value(layout.gain_addr[which], value);
+ }
+
+ uint8_t get_offset(unsigned which) const
+ {
+ return regs.get_value(layout.offset_addr[which]);
+ }
+
+ uint8_t get_gain(unsigned which) const
+ {
+ return regs.get_value(layout.gain_addr[which]);
+ }
+
+ bool operator==(const Genesys_Frontend& other) const
+ {
+ return fe_id == other.fe_id &&
+ regs == other.regs &&
+ reg2 == other.reg2 &&
+ layout == other.layout;
+ }
+};
+
+template<class Stream>
+void serialize(Stream& str, Genesys_Frontend& x)
{
- uint8_t sensor_id; /**< id of the sensor description */
- int optical_res;
- int black_pixels;
- int dummy_pixel; /* value of dummy register. */
- int CCD_start_xoffset; /* last pixel of CCD margin at optical resolution */
- int sensor_pixels; /* total pixels used by the sensor */
- int fau_gain_white_ref; /* TA CCD target code (reference gain) */
- int gain_white_ref; /* CCD target code (reference gain) */
- uint8_t regs_0x08_0x0b[4];
- uint8_t regs_0x10_0x1d[14];
- uint8_t regs_0x52_0x5e[13];
- float gamma[3]; /**< red, green and blue gamma coefficient for default gamma tables */
- uint16_t *gamma_table[3]; /**< sensor specific gamma tables */
-} Genesys_Sensor;
-
-typedef struct
+ serialize(str, x.fe_id);
+ serialize_newline(str);
+ serialize(str, x.regs);
+ serialize_newline(str);
+ serialize(str, x.reg2);
+ serialize_newline(str);
+ serialize(str, x.layout.offset_addr);
+ serialize(str, x.layout.gain_addr);
+}
+
+struct SensorExposure {
+ uint16_t red, green, blue;
+};
+
+struct Genesys_Sensor {
+
+ Genesys_Sensor() = default;
+ ~Genesys_Sensor() = default;
+
+ // id of the sensor description
+ uint8_t sensor_id = 0;
+ int optical_res = 0;
+
+ // the minimum and maximum resolution this sensor is usable at. -1 means that the resolution
+ // can be any.
+ int min_resolution = -1;
+ int max_resolution = -1;
+
+ // the scan method used with the sensor
+ ScanMethod method = ScanMethod::FLATBED;
+
+ // CCD may present itself as half or quarter-size CCD on certain resolutions
+ int ccd_size_divisor = 1;
+
+ int black_pixels = 0;
+ // value of the dummy register
+ int dummy_pixel = 0;
+ // last pixel of CCD margin at optical resolution
+ int CCD_start_xoffset = 0;
+ // total pixels used by the sensor
+ int sensor_pixels = 0;
+ // TA CCD target code (reference gain)
+ int fau_gain_white_ref = 0;
+ // CCD target code (reference gain)
+ int gain_white_ref = 0;
+
+ // red, green and blue initial exposure values
+ SensorExposure exposure;
+
+ int exposure_lperiod = -1;
+
+ GenesysRegisterSettingSet custom_regs;
+ GenesysRegisterSettingSet custom_fe_regs;
+
+ // red, green and blue gamma coefficient for default gamma tables
+ AssignableArray<float, 3> gamma;
+
+ int get_ccd_size_divisor_for_dpi(int xres) const
+ {
+ if (ccd_size_divisor >= 4 && xres * 4 <= optical_res) {
+ return 4;
+ }
+ if (ccd_size_divisor >= 2 && xres * 2 <= optical_res) {
+ return 2;
+ }
+ return 1;
+ }
+
+ bool operator==(const Genesys_Sensor& other) const
+ {
+ return sensor_id == other.sensor_id &&
+ optical_res == other.optical_res &&
+ min_resolution == other.min_resolution &&
+ max_resolution == other.max_resolution &&
+ method == other.method &&
+ ccd_size_divisor == other.ccd_size_divisor &&
+ black_pixels == other.black_pixels &&
+ dummy_pixel == other.dummy_pixel &&
+ CCD_start_xoffset == other.CCD_start_xoffset &&
+ sensor_pixels == other.sensor_pixels &&
+ fau_gain_white_ref == other.fau_gain_white_ref &&
+ gain_white_ref == other.gain_white_ref &&
+ exposure.blue == other.exposure.blue &&
+ exposure.green == other.exposure.green &&
+ exposure.red == other.exposure.red &&
+ exposure_lperiod == other.exposure_lperiod &&
+ custom_regs == other.custom_regs &&
+ custom_fe_regs == other.custom_fe_regs &&
+ gamma == other.gamma;
+ }
+};
+
+template<class Stream>
+void serialize(Stream& str, Genesys_Sensor& x)
{
- uint8_t gpo_id; /**< id of the gpo description */
- uint8_t value[2]; /**< registers 0x6c and 0x6d on gl843 */
- uint8_t enable[2]; /**< registers 0x6e and 0x6F on gl843 */
-} Genesys_Gpo;
+ serialize(str, x.sensor_id);
+ serialize(str, x.optical_res);
+ serialize(str, x.min_resolution);
+ serialize(str, x.max_resolution);
+ serialize(str, x.method);
+ serialize(str, x.ccd_size_divisor);
+ serialize(str, x.black_pixels);
+ serialize(str, x.dummy_pixel);
+ serialize(str, x.CCD_start_xoffset);
+ serialize(str, x.sensor_pixels);
+ serialize(str, x.fau_gain_white_ref);
+ serialize(str, x.gain_white_ref);
+ serialize_newline(str);
+ serialize(str, x.exposure.blue);
+ serialize(str, x.exposure.green);
+ serialize(str, x.exposure.red);
+ serialize(str, x.exposure_lperiod);
+ serialize_newline(str);
+ serialize(str, x.custom_regs);
+ serialize_newline(str);
+ serialize(str, x.custom_fe_regs);
+ serialize_newline(str);
+ serialize(str, x.gamma);
+}
-typedef struct
+struct Genesys_Gpo
{
- SANE_Int maximum_start_speed; /* maximum speed allowed when accelerating from standstill. Unit: pixeltime/step */
- SANE_Int maximum_speed; /* maximum speed allowed. Unit: pixeltime/step */
- SANE_Int minimum_steps; /* number of steps used for default curve */
- float g; /* power for non-linear acceleration curves. */
-/* vs*(1-i^g)+ve*(i^g) where
- vs = start speed, ve = end speed,
- i = 0.0 for first entry and i = 1.0 for last entry in default table*/
-} Genesys_Motor_Slope;
+ Genesys_Gpo() = default;
+
+ Genesys_Gpo(uint8_t id, const std::array<uint8_t, 2>& v, const std::array<uint8_t, 2>& e)
+ {
+ gpo_id = id;
+ value[0] = v[0];
+ value[1] = v[1];
+ enable[0] = e[0];
+ enable[1] = e[1];
+ }
+ // Genesys_Gpo
+ uint8_t gpo_id = 0;
-typedef struct
+ // registers 0x6c and 0x6d on GL841, GL842, GL843, GL846, GL848 and possibly others
+ uint8_t value[2] = { 0, 0 };
+
+ // registers 0x6e and 0x6f on GL841, GL842, GL843, GL846, GL848 and possibly others
+ uint8_t enable[2] = { 0, 0 };
+};
+
+struct Genesys_Motor_Slope
+{
+ Genesys_Motor_Slope() = default;
+ Genesys_Motor_Slope(int p_maximum_start_speed, int p_maximum_speed, int p_minimum_steps,
+ float p_g) :
+ maximum_start_speed(p_maximum_start_speed),
+ maximum_speed(p_maximum_speed),
+ minimum_steps(p_minimum_steps),
+ g(p_g)
+ {}
+
+ // maximum speed allowed when accelerating from standstill. Unit: pixeltime/step
+ int maximum_start_speed = 0;
+ // maximum speed allowed. Unit: pixeltime/step
+ int maximum_speed = 0;
+ // number of steps used for default curve
+ int minimum_steps = 0;
+
+ /* power for non-linear acceleration curves.
+ vs*(1-i^g)+ve*(i^g) where
+ vs = start speed, ve = end speed,
+ i = 0.0 for first entry and i = 1.0 for last entry in default table
+ */
+ float g = 0;
+};
+
+
+struct Genesys_Motor
{
- uint8_t motor_id; /**< id of the motor description */
- SANE_Int base_ydpi; /* motor base steps. Unit: 1/" */
- SANE_Int optical_ydpi; /* maximum resolution in y-direction. Unit: 1/" */
- SANE_Int max_step_type; /* maximum step type. 0-2 */
- SANE_Int power_mode_count; /* number of power modes*/
- Genesys_Motor_Slope slopes[2][3]; /* slopes to derive individual slopes from */
-} Genesys_Motor;
+ Genesys_Motor() = default;
+ Genesys_Motor(uint8_t p_motor_id, int p_base_ydpi, int p_optical_ydpi, int p_max_step_type,
+ int p_power_mode_count,
+ const std::vector<std::vector<Genesys_Motor_Slope>>& p_slopes) :
+ motor_id(p_motor_id),
+ base_ydpi(p_base_ydpi),
+ optical_ydpi(p_optical_ydpi),
+ max_step_type(p_max_step_type),
+ power_mode_count(p_power_mode_count),
+ slopes(p_slopes)
+ {}
+
+ // id of the motor description
+ uint8_t motor_id = 0;
+ // motor base steps. Unit: 1/inch
+ int base_ydpi = 0;
+ // maximum resolution in y-direction. Unit: 1/inch
+ int optical_ydpi = 0;
+ // maximum step type. 0-2
+ int max_step_type = 0;
+ // number of power modes
+ int power_mode_count = 0;
+ // slopes to derive individual slopes from
+ std::vector<std::vector<Genesys_Motor_Slope>> slopes;
+};
typedef enum Genesys_Color_Order
{
@@ -329,116 +833,175 @@ Genesys_Color_Order;
#define GENESYS_GL123 123
#define GENESYS_GL124 124
-#define GENESYS_MAX_REGS 256
+enum Genesys_Model_Type
+{
+ MODEL_UMAX_ASTRA_4500 = 0,
+ MODEL_CANON_LIDE_50,
+ MODEL_PANASONIC_KV_SS080,
+ MODEL_HP_SCANJET_4850C,
+ MODEL_HP_SCANJET_G4010,
+ MODEL_HP_SCANJET_G4050,
+ MODEL_CANON_CANOSCAN_4400F,
+ MODEL_CANON_CANOSCAN_8400F,
+ MODEL_CANON_CANOSCAN_8600F,
+ MODEL_CANON_LIDE_100,
+ MODEL_CANON_LIDE_110,
+ MODEL_CANON_LIDE_120,
+ MODEL_CANON_LIDE_210,
+ MODEL_CANON_LIDE_220,
+ MODEL_CANON_CANOSCAN_5600F,
+ MODEL_CANON_LIDE_700F,
+ MODEL_CANON_LIDE_200,
+ MODEL_CANON_LIDE_60,
+ MODEL_CANON_LIDE_80,
+ MODEL_HP_SCANJET_2300C,
+ MODEL_HP_SCANJET_2400C,
+ MODEL_VISIONEER_STROBE_XP200,
+ MODEL_HP_SCANJET_3670C,
+ MODEL_PLUSTEK_OPTICPRO_ST12,
+ MODEL_PLUSTEK_OPTICPRO_ST24,
+ MODEL_MEDION_MD5345,
+ MODEL_VISIONEER_STROBE_XP300,
+ MODEL_SYSCAN_DOCKETPORT_665,
+ MODEL_VISIONEER_ROADWARRIOR,
+ MODEL_SYSCAN_DOCKETPORT_465,
+ MODEL_VISIONEER_STROBE_XP100_REVISION3,
+ MODEL_PENTAX_DSMOBILE_600,
+ MODEL_SYSCAN_DOCKETPORT_467,
+ MODEL_SYSCAN_DOCKETPORT_685,
+ MODEL_SYSCAN_DOCKETPORT_485,
+ MODEL_DCT_DOCKETPORT_487,
+ MODEL_VISIONEER_7100,
+ MODEL_XEROX_2400,
+ MODEL_XEROX_TRAVELSCANNER_100,
+ MODEL_PLUSTEK_OPTICPRO_3600,
+ MODEL_HP_SCANJET_N6310,
+ MODEL_PLUSTEK_OPTICBOOK_3800,
+ MODEL_CANON_IMAGE_FORMULA_101
+};
-#define DAC_WOLFSON_UMAX 0
-#define DAC_WOLFSON_ST12 1
-#define DAC_WOLFSON_ST24 2
-#define DAC_WOLFSON_5345 3
-#define DAC_WOLFSON_HP2400 4
-#define DAC_WOLFSON_HP2300 5
-#define DAC_CANONLIDE35 6
-#define DAC_AD_XP200 7 /* Analog Device frontend */
-#define DAC_WOLFSON_XP300 8
-#define DAC_WOLFSON_HP3670 9
-#define DAC_WOLFSON_DSM600 10
-#define DAC_CANONLIDE200 11
-#define DAC_KVSS080 12
-#define DAC_G4050 13
-#define DAC_CANONLIDE110 14
-#define DAC_PLUSTEK_3600 15
-#define DAC_CANONLIDE700 16
-#define DAC_CS8400F 17
-#define DAC_IMG101 18
-#define DAC_PLUSTEK3800 19
-#define DAC_CANONLIDE80 20
-#define DAC_CANONLIDE120 21
-
-#define CCD_UMAX 0
-#define CCD_ST12 1 /* SONY ILX548: 5340 Pixel ??? */
-#define CCD_ST24 2 /* SONY ILX569: 10680 Pixel ??? */
-#define CCD_5345 3
-#define CCD_HP2400 4
-#define CCD_HP2300 5
-#define CCD_CANONLIDE35 6
-#define CIS_XP200 7 /* CIS sensor for Strobe XP200 */
- /* 8 is unused currently */
-#define CCD_HP3670 9
-#define CCD_DP665 10
-#define CCD_ROADWARRIOR 11
-#define CCD_DSMOBILE600 12
-#define CCD_XP300 13
-#define CCD_DP685 14
-#define CIS_CANONLIDE200 15
-#define CIS_CANONLIDE100 16
-#define CCD_KVSS080 17
-#define CCD_G4050 18
-#define CIS_CANONLIDE110 19
-#define CCD_PLUSTEK_3600 20
-#define CCD_HP_N6310 21
-#define CIS_CANONLIDE700 22
-#define CCD_CS4400F 23
-#define CCD_CS8400F 24
-#define CCD_IMG101 25
-#define CCD_PLUSTEK3800 26
-#define CIS_CANONLIDE210 27
-#define CIS_CANONLIDE80 28
-#define CIS_CANONLIDE220 29
-#define CIS_CANONLIDE120 30
-
-#define GPO_UMAX 0
-#define GPO_ST12 1
-#define GPO_ST24 2
-#define GPO_5345 3
-#define GPO_HP2400 4
-#define GPO_HP2300 5
-#define GPO_CANONLIDE35 6
-#define GPO_XP200 7
-#define GPO_XP300 8
-#define GPO_HP3670 9
-#define GPO_DP665 10
-#define GPO_DP685 11
-#define GPO_CANONLIDE200 12
-#define GPO_KVSS080 13
-#define GPO_G4050 14
-#define GPO_CANONLIDE110 15
-#define GPO_PLUSTEK_3600 16
-#define GPO_CANONLIDE210 17
-#define GPO_HP_N6310 18
-#define GPO_CANONLIDE700 19
-#define GPO_CS4400F 20
-#define GPO_CS8400F 21
-#define GPO_IMG101 22
-#define GPO_PLUSTEK3800 23
-#define GPO_CANONLIDE80 24
-#define GPO_CANONLIDE120 25
-
-#define MOTOR_UMAX 0
-#define MOTOR_5345 1
-#define MOTOR_ST24 2
-#define MOTOR_HP2400 3
-#define MOTOR_HP2300 4
-#define MOTOR_CANONLIDE35 5
-#define MOTOR_XP200 6
-#define MOTOR_XP300 7
-#define MOTOR_HP3670 9
-#define MOTOR_DP665 10
-#define MOTOR_ROADWARRIOR 11
-#define MOTOR_DSMOBILE_600 12
-#define MOTOR_CANONLIDE200 13
-#define MOTOR_CANONLIDE100 14
-#define MOTOR_KVSS080 15
-#define MOTOR_G4050 16
-#define MOTOR_CANONLIDE110 17
-#define MOTOR_PLUSTEK_3600 18
-#define MOTOR_CANONLIDE700 19
-#define MOTOR_CS8400F 20
-#define MOTOR_IMG101 21
-#define MOTOR_PLUSTEK3800 22
-#define MOTOR_CANONLIDE210 23
-#define MOTOR_CANONLIDE80 24
-#define MOTOR_CANONLIDE120 25
+enum Genesys_Dac_Type
+{
+ DAC_WOLFSON_UMAX = 0,
+ DAC_WOLFSON_ST12,
+ DAC_WOLFSON_ST24,
+ DAC_WOLFSON_5345,
+ DAC_WOLFSON_HP2400,
+ DAC_WOLFSON_HP2300,
+ DAC_CANONLIDE35,
+ DAC_AD_XP200,
+ DAC_WOLFSON_XP300,
+ DAC_WOLFSON_HP3670,
+ DAC_WOLFSON_DSM600,
+ DAC_CANONLIDE200,
+ DAC_KVSS080,
+ DAC_G4050,
+ DAC_CANONLIDE110,
+ DAC_PLUSTEK_3600,
+ DAC_CANONLIDE700,
+ DAC_CS8400F,
+ DAC_CS8600F,
+ DAC_IMG101,
+ DAC_PLUSTEK3800,
+ DAC_CANONLIDE80,
+ DAC_CANONLIDE120
+};
+
+enum Genesys_Sensor_Type
+{
+ CCD_UMAX = 0,
+ CCD_ST12, // SONY ILX548: 5340 Pixel ???
+ CCD_ST24, // SONY ILX569: 10680 Pixel ???
+ CCD_5345,
+ CCD_HP2400,
+ CCD_HP2300,
+ CCD_CANONLIDE35,
+ CIS_XP200, // CIS sensor for Strobe XP200,
+ CCD_HP3670,
+ CCD_DP665,
+ CCD_ROADWARRIOR,
+ CCD_DSMOBILE600,
+ CCD_XP300,
+ CCD_DP685,
+ CIS_CANONLIDE200,
+ CIS_CANONLIDE100,
+ CCD_KVSS080,
+ CCD_G4050,
+ CIS_CANONLIDE110,
+ CCD_PLUSTEK_3600,
+ CCD_HP_N6310,
+ CIS_CANONLIDE700,
+ CCD_CS4400F,
+ CCD_CS8400F,
+ CCD_CS8600F,
+ CCD_IMG101,
+ CCD_PLUSTEK3800,
+ CIS_CANONLIDE210,
+ CIS_CANONLIDE80,
+ CIS_CANONLIDE220,
+ CIS_CANONLIDE120,
+};
+enum Genesys_Gpo_Type
+{
+ GPO_UMAX,
+ GPO_ST12,
+ GPO_ST24,
+ GPO_5345,
+ GPO_HP2400,
+ GPO_HP2300,
+ GPO_CANONLIDE35,
+ GPO_XP200,
+ GPO_XP300,
+ GPO_HP3670,
+ GPO_DP665,
+ GPO_DP685,
+ GPO_CANONLIDE200,
+ GPO_KVSS080,
+ GPO_G4050,
+ GPO_CANONLIDE110,
+ GPO_PLUSTEK_3600,
+ GPO_CANONLIDE210,
+ GPO_HP_N6310,
+ GPO_CANONLIDE700,
+ GPO_CS4400F,
+ GPO_CS8400F,
+ GPO_CS8600F,
+ GPO_IMG101,
+ GPO_PLUSTEK3800,
+ GPO_CANONLIDE80,
+ GPO_CANONLIDE120
+};
+
+enum Genesys_Motor_Type
+{
+ MOTOR_UMAX = 0,
+ MOTOR_5345,
+ MOTOR_ST24,
+ MOTOR_HP2400,
+ MOTOR_HP2300,
+ MOTOR_CANONLIDE35,
+ MOTOR_XP200,
+ MOTOR_XP300,
+ MOTOR_HP3670,
+ MOTOR_DP665,
+ MOTOR_ROADWARRIOR,
+ MOTOR_DSMOBILE_600,
+ MOTOR_CANONLIDE200,
+ MOTOR_CANONLIDE100,
+ MOTOR_KVSS080,
+ MOTOR_G4050,
+ MOTOR_CANONLIDE110,
+ MOTOR_PLUSTEK_3600,
+ MOTOR_CANONLIDE700,
+ MOTOR_CS8400F,
+ MOTOR_CS8600F,
+ MOTOR_IMG101,
+ MOTOR_PLUSTEK3800,
+ MOTOR_CANONLIDE210,
+ MOTOR_CANONLIDE80,
+ MOTOR_CANONLIDE120
+};
/* Forward typedefs */
typedef struct Genesys_Device Genesys_Device;
@@ -462,15 +1025,21 @@ typedef struct Genesys_Command_Set
/*@} */
+ bool (*needs_home_before_init_regs_for_scan) (Genesys_Device* dev);
+
/** For ASIC initialization */
SANE_Status (*init) (Genesys_Device * dev);
SANE_Status (*init_regs_for_warmup) (Genesys_Device * dev,
+ const Genesys_Sensor& sensor,
Genesys_Register_Set * regs,
int *channels, int *total_size);
- SANE_Status (*init_regs_for_coarse_calibration) (Genesys_Device * dev);
- SANE_Status (*init_regs_for_shading) (Genesys_Device * dev);
- SANE_Status (*init_regs_for_scan) (Genesys_Device * dev);
+ SANE_Status (*init_regs_for_coarse_calibration) (Genesys_Device * dev,
+ const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs);
+ SANE_Status (*init_regs_for_shading) (Genesys_Device * dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs);
+ SANE_Status (*init_regs_for_scan) (Genesys_Device * dev, const Genesys_Sensor& sensor);
SANE_Bool (*get_filter_bit) (Genesys_Register_Set * reg);
SANE_Bool (*get_lineart_bit) (Genesys_Register_Set * reg);
@@ -481,18 +1050,12 @@ typedef struct Genesys_Command_Set
SANE_Bool (*test_buffer_empty_bit) (SANE_Byte val);
SANE_Bool (*test_motor_flag_bit) (SANE_Byte val);
- int (*bulk_full_size) (void);
-
- SANE_Status (*set_fe) (Genesys_Device * dev, uint8_t set);
+ SANE_Status (*set_fe) (Genesys_Device * dev, const Genesys_Sensor& sensor, uint8_t set);
SANE_Status (*set_powersaving) (Genesys_Device * dev, int delay);
SANE_Status (*save_power) (Genesys_Device * dev, SANE_Bool enable);
- void (*set_motor_power) (Genesys_Register_Set * regs, SANE_Bool set);
- void (*set_lamp_power) (Genesys_Device * dev,
- Genesys_Register_Set * regs,
- SANE_Bool set);
-
SANE_Status (*begin_scan) (Genesys_Device * dev,
+ const Genesys_Sensor& sensor,
Genesys_Register_Set * regs,
SANE_Bool start_motor);
SANE_Status (*end_scan) (Genesys_Device * dev,
@@ -502,32 +1065,31 @@ typedef struct Genesys_Command_Set
/**
* Send gamma tables to ASIC
*/
- SANE_Status (*send_gamma_table) (Genesys_Device * dev);
+ SANE_Status (*send_gamma_table) (Genesys_Device * dev, const Genesys_Sensor& sensor);
SANE_Status (*search_start_position) (Genesys_Device * dev);
- SANE_Status (*offset_calibration) (Genesys_Device * dev);
- SANE_Status (*coarse_gain_calibration) (Genesys_Device * dev, int dpi);
- SANE_Status (*led_calibration) (Genesys_Device * dev);
-
+ SANE_Status (*offset_calibration) (Genesys_Device * dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs);
+ SANE_Status (*coarse_gain_calibration) (Genesys_Device * dev,
+ const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs, int dpi);
+ SANE_Status (*led_calibration) (Genesys_Device * dev, Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs);
+
+ void (*wait_for_motor_stop) (Genesys_Device* dev);
SANE_Status (*slow_back_home) (Genesys_Device * dev, SANE_Bool wait_until_home);
SANE_Status (*rewind) (Genesys_Device * dev);
SANE_Status (*bulk_write_register) (Genesys_Device * dev,
- Genesys_Register_Set * reg,
- size_t elems);
+ Genesys_Register_Set& regs);
+
SANE_Status (*bulk_write_data) (Genesys_Device * dev, uint8_t addr,
uint8_t * data, size_t len);
SANE_Status (*bulk_read_data) (Genesys_Device * dev, uint8_t addr,
uint8_t * data, size_t len);
- /* Updates hardware sensor information in Genesys_Scanner.val[].
- If possible, just get information for given option.
- The sensor state in Genesys_Scanner.val[] should be merged with the
- new sensor state, using the information that was last read by the frontend
- in Genesys_Scanner.last_val[], in such a way that a button up/down
- relative to Genesys_Scanner.last_val[] is not lost.
- */
+ // Updates hardware sensor information in Genesys_Scanner.val[].
SANE_Status (*update_hardware_sensors) (struct Genesys_Scanner * s);
/* functions for sheetfed scanners */
@@ -548,12 +1110,11 @@ typedef struct Genesys_Command_Set
/**
* search for an black or white area in forward or reverse
* direction */
- SANE_Status (*search_strip) (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black);
+ SANE_Status (*search_strip) (Genesys_Device * dev, const Genesys_Sensor& sensor,
+ SANE_Bool forward, SANE_Bool black);
- SANE_Status (*is_compatible_calibration) (
- Genesys_Device * dev,
- Genesys_Calibration_Cache *cache,
- SANE_Bool for_overwrite);
+ bool (*is_compatible_calibration) (Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Calibration_Cache* cache, SANE_Bool for_overwrite);
/* functions for transparency adapter */
/**
@@ -564,36 +1125,17 @@ typedef struct Genesys_Command_Set
/**
* write shading data calibration to ASIC
*/
- SANE_Status (*send_shading_data) (Genesys_Device * dev, uint8_t * data, int size);
+ SANE_Status (*send_shading_data) (Genesys_Device * dev, const Genesys_Sensor& sensor,
+ uint8_t * data, int size);
- /**
- * calculate current scan setup
- */
- SANE_Status (*calculate_current_setup) (Genesys_Device * dev);
+ // calculate current scan setup
+ void (*calculate_current_setup) (Genesys_Device * dev, const Genesys_Sensor& sensor);
/**
* cold boot init function
*/
SANE_Status (*asic_boot) (Genesys_Device * dev, SANE_Bool cold);
- /**
- * Scan register setting interface
- */
- SANE_Status (*init_scan_regs) (Genesys_Device * dev,
- Genesys_Register_Set * reg,
- float xres,
- float yres,
- float startx,
- float starty,
- float pixels,
- float lines,
- unsigned int depth,
- unsigned int channels,
- int scan_method,
- int scan_mode,
- int color_filter,
- unsigned int flags);
-
} Genesys_Command_Set;
/** @brief structure to describe a scanner model
@@ -605,6 +1147,7 @@ typedef struct Genesys_Model
SANE_String_Const name;
SANE_String_Const vendor;
SANE_String_Const model;
+ SANE_Int model_id;
SANE_Int asic_type; /* ASIC type gl646 or gl841 */
Genesys_Command_Set *cmd_set; /* pointers to low level functions */
@@ -653,108 +1196,277 @@ typedef struct Genesys_Model
SANE_Word buttons; /* Button flags, described existing buttons for the model */
/*@} */
SANE_Int shading_lines; /* how many lines are used for shading calibration */
+ SANE_Int shading_ta_lines; // how many lines are used for shading calibration in TA mode
SANE_Int search_lines; /* how many lines are used to search start position */
} Genesys_Model;
-#define SCAN_METHOD_FLATBED 0 /**< normal scan method */
-#define SCAN_METHOD_TRANSPARENCY 2 /**< scan using transparency adaptor */
-#define SCAN_METHOD_NEGATIVE 0x88 /**< scan using negative adaptor */
+struct Genesys_Settings
+{
+ ScanMethod scan_method = ScanMethod::FLATBED;
+ ScanColorMode scan_mode = ScanColorMode::LINEART;
-#define SCAN_MODE_LINEART 0 /**< lineart scan mode */
-#define SCAN_MODE_HALFTONE 1 /**< halftone scan mode */
-#define SCAN_MODE_GRAY 2 /**< gray scan mode */
-#define SCAN_MODE_COLOR 4 /**< color scan mode */
+ // horizontal dpi
+ int xres = 0;
+ // vertical dpi
+ int yres = 0;
-typedef struct
-{
- int scan_method; /* todo: change >=2: Transparency, 0x88: negative film */
- int scan_mode; /* todo: change 0,1 = lineart, halftone; 2 = gray, 3 = 3pass color, 4=single pass color */
- int xres; /**< horizontal dpi */
- int yres; /**< vertical dpi */
+ //x start on scan table in mm
+ double tl_x = 0;
+ // y start on scan table in mm
+ double tl_y = 0;
- double tl_x; /* x start on scan table in mm */
- double tl_y; /* y start on scan table in mm */
+ // number of lines at scan resolution
+ unsigned int lines = 0;
+ // number of pixels at scan resolution
+ unsigned int pixels = 0;
- unsigned int lines; /**< number of lines at scan resolution */
- unsigned int pixels; /**< number of pixels at scan resolution */
+ // bit depth of the scan
+ unsigned int depth = 0;
- unsigned int depth;/* bit depth of the scan */
+ ColorFilter color_filter = ColorFilter::NONE;
- /* todo : remove these fields ? */
- int exposure_time;
+ // true if scan is true gray, false if monochrome scan
+ int true_gray = 0;
- unsigned int color_filter;
+ // lineart threshold
+ int threshold = 0;
- /**< true if scan is true gray, false if monochrome scan */
- int true_gray;
+ // lineart threshold curve for dynamic rasterization
+ int threshold_curve = 0;
- /**< lineart threshold */
- int threshold;
+ // Disable interpolation for xres<yres
+ int disable_interpolation = 0;
- /**< lineart threshold curve for dynamic rasterization */
- int threshold_curve;
+ // true is lineart is generated from gray data by the dynamic rasterization algoright
+ int dynamic_lineart = 0;
- /**< Disable interpolation for xres<yres*/
- int disable_interpolation;
+ // value for contrast enhancement in the [-100..100] range
+ int contrast = 0;
- /**< Use double x resolution internally to provide better
- * quality */
- int double_xres;
+ // value for brightness enhancement in the [-100..100] range
+ int brightness = 0;
- /**< true is lineart is generated from gray data by
- * the dynamic rasterization algo */
- int dynamic_lineart;
+ // cache entries expiration time
+ int expiration_time = 0;
+};
- /**< value for contrast enhancement in the [-100..100] range */
- int contrast;
+struct SetupParams {
+
+ static constexpr unsigned NOT_SET = std::numeric_limits<unsigned>::max();
+
+ // resolution in x direction
+ unsigned xres = NOT_SET;
+ // resolution in y direction
+ unsigned yres = NOT_SET;
+ // start pixel in X direction, from dummy_pixel + 1
+ float startx = -1;
+ // start pixel in Y direction, counted according to base_ydpi
+ float starty = -1;
+ // the number of pixels in X direction
+ unsigned pixels = NOT_SET;
+ // the number of pixels in Y direction
+ unsigned lines = NOT_SET;
+ // the depth of the scan in bits. Allowed are 1, 8, 16
+ unsigned depth = NOT_SET;
+ // the number of channels
+ unsigned channels = NOT_SET;
+
+ ScanMethod scan_method = static_cast<ScanMethod>(NOT_SET);
+
+ ScanColorMode scan_mode = static_cast<ScanColorMode>(NOT_SET);
+
+ ColorFilter color_filter = static_cast<ColorFilter>(NOT_SET);
+
+ unsigned flags = NOT_SET;
+
+ void assert_valid() const
+ {
+ if (xres == NOT_SET || yres == NOT_SET || startx < 0 || starty < 0 ||
+ pixels == NOT_SET || lines == NOT_SET ||depth == NOT_SET || channels == NOT_SET ||
+ scan_method == static_cast<ScanMethod>(NOT_SET) ||
+ scan_mode == static_cast<ScanColorMode>(NOT_SET) ||
+ color_filter == static_cast<ColorFilter>(NOT_SET) ||
+ flags == NOT_SET)
+ {
+ throw std::runtime_error("SetupParams are not valid");
+ }
+ }
+
+ bool operator==(const SetupParams& other) const
+ {
+ return xres == other.xres &&
+ yres == other.yres &&
+ startx == other.startx &&
+ starty == other.starty &&
+ pixels == other.pixels &&
+ lines == other.lines &&
+ depth == other.depth &&
+ channels == other.channels &&
+ scan_method == other.scan_method &&
+ scan_mode == other.scan_mode &&
+ color_filter == other.color_filter &&
+ flags == other.flags;
+ }
+};
- /**< value for brightness enhancement in the [-100..100] range */
- int brightness;
-
- /**< cahe entries expiration time */
- int expiration_time;
-} Genesys_Settings;
+template<class Stream>
+void serialize(Stream& str, SetupParams& x)
+{
+ serialize(str, x.xres);
+ serialize(str, x.yres);
+ serialize(str, x.startx);
+ serialize(str, x.starty);
+ serialize(str, x.pixels);
+ serialize(str, x.lines);
+ serialize(str, x.depth);
+ serialize(str, x.channels);
+ serialize(str, x.scan_method);
+ serialize(str, x.scan_mode);
+ serialize(str, x.color_filter);
+ serialize(str, x.flags);
+}
-typedef struct Genesys_Current_Setup
+struct Genesys_Current_Setup
{
- int pixels; /* pixel count expected from scanner */
- int lines; /* line count expected from scanner */
- int depth; /* depth expected from scanner */
- int channels; /* channel count expected from scanner */
- int scan_method; /* scanning method: flatbed or XPA */
- int exposure_time; /* used exposure time */
- float xres; /* used xres */
- float yres; /* used yres*/
- SANE_Bool half_ccd; /* half ccd mode */
- SANE_Int stagger;
- SANE_Int max_shift; /* max shift of any ccd component, including staggered pixels*/
-} Genesys_Current_Setup;
-
-typedef struct Genesys_Buffer
+ // params used for this setup
+ SetupParams params;
+
+ // pixel count expected from scanner
+ int pixels = 0;
+ // line count expected from scanner
+ int lines = 0;
+ // depth expected from scanner
+ int depth = 0;
+ // channel count expected from scanner
+ int channels = 0;
+
+ // used exposure time
+ int exposure_time = 0;
+ // used xres
+ float xres = 0;
+ // used yres
+ float yres = 0;
+ // half ccd mode
+ unsigned ccd_size_divisor = 1;
+ SANE_Int stagger = 0;
+ // max shift of any ccd component, including staggered pixels
+ SANE_Int max_shift = 0;
+
+ bool operator==(const Genesys_Current_Setup& other) const
+ {
+ return params == other.params &&
+ pixels == other.pixels &&
+ lines == other.lines &&
+ depth == other.depth &&
+ channels == other.channels &&
+ exposure_time == other.exposure_time &&
+ xres == other.xres &&
+ yres == other.yres &&
+ ccd_size_divisor == other.ccd_size_divisor &&
+ stagger == other.stagger &&
+ max_shift == other.max_shift;
+ }
+};
+
+template<class Stream>
+void serialize(Stream& str, Genesys_Current_Setup& x)
{
- SANE_Byte *buffer;
- size_t size;
- size_t pos; /* current position in read buffer */
- size_t avail; /* data bytes currently in buffer */
-} Genesys_Buffer;
+ serialize(str, x.params);
+ serialize_newline(str);
+ serialize(str, x.pixels);
+ serialize(str, x.lines);
+ serialize(str, x.depth);
+ serialize(str, x.channels);
+ serialize(str, x.exposure_time);
+ serialize(str, x.xres);
+ serialize(str, x.yres);
+ serialize(str, x.ccd_size_divisor);
+ serialize(str, x.stagger);
+ serialize(str, x.max_shift);
+}
-struct Genesys_Calibration_Cache
+struct Genesys_Buffer
{
- Genesys_Current_Setup used_setup;/* used to check if entry is compatible */
- time_t last_calibration;
+ Genesys_Buffer() = default;
- Genesys_Frontend frontend;
- Genesys_Sensor sensor;
+ size_t size() const { return buffer_.size(); }
+ size_t avail() const { return avail_; }
+ size_t pos() const { return pos_; }
- size_t calib_pixels;
- size_t calib_channels;
- size_t average_size;
- uint8_t *white_average_data;
- uint8_t *dark_average_data;
+ // TODO: refactor code that uses this function to no longer use it
+ void set_pos(size_t pos) { pos_ = pos; }
- struct Genesys_Calibration_Cache *next;
+ void alloc(size_t size);
+ void clear();
+
+ void reset();
+
+ uint8_t* get_write_pos(size_t size);
+ uint8_t* get_read_pos(); // TODO: mark as const
+
+ void produce(size_t size);
+ void consume(size_t size);
+
+private:
+ std::vector<uint8_t> buffer_;
+ // current position in read buffer
+ size_t pos_ = 0;
+ // data bytes currently in buffer
+ size_t avail_ = 0;
};
+struct Genesys_Calibration_Cache
+{
+ Genesys_Calibration_Cache() = default;
+ ~Genesys_Calibration_Cache() = default;
+
+ // used to check if entry is compatible
+ Genesys_Current_Setup used_setup;
+ time_t last_calibration = 0;
+
+ Genesys_Frontend frontend;
+ Genesys_Sensor sensor;
+
+ size_t calib_pixels = 0;
+ size_t calib_channels = 0;
+ size_t average_size = 0;
+ std::vector<uint8_t> white_average_data;
+ std::vector<uint8_t> dark_average_data;
+
+ bool operator==(const Genesys_Calibration_Cache& other) const
+ {
+ return used_setup == other.used_setup &&
+ last_calibration == other.last_calibration &&
+ frontend == other.frontend &&
+ sensor == other.sensor &&
+ calib_pixels == other.calib_pixels &&
+ calib_channels == other.calib_channels &&
+ average_size == other.average_size &&
+ white_average_data == other.white_average_data &&
+ dark_average_data == other.dark_average_data;
+ }
+};
+
+template<class Stream>
+void serialize(Stream& str, Genesys_Calibration_Cache& x)
+{
+ serialize(str, x.used_setup);
+ serialize_newline(str);
+ serialize(str, x.last_calibration);
+ serialize_newline(str);
+ serialize(str, x.frontend);
+ serialize_newline(str);
+ serialize(str, x.sensor);
+ serialize_newline(str);
+ serialize(str, x.calib_pixels);
+ serialize(str, x.calib_channels);
+ serialize(str, x.average_size);
+ serialize_newline(str);
+ serialize(str, x.white_average_data);
+ serialize_newline(str);
+ serialize(str, x.dark_average_data);
+}
+
/**
* Describes the current device status for the backend
* session. This should be more accurately called
@@ -762,86 +1474,140 @@ struct Genesys_Calibration_Cache
*/
struct Genesys_Device
{
- SANE_Int dn;
- SANE_Word vendorId; /**< USB vendor identifier */
- SANE_Word productId; /**< USB product identifier */
- SANE_Int usb_mode; /**< USB mode: 1 for USB 1.1, 2 for USB 2.0,
- 0 unset and -1 for fake USB device */
- SANE_String file_name;
- SANE_String calib_file;
- Genesys_Model *model;
-
- Genesys_Register_Set reg[256];
- Genesys_Register_Set calib_reg[256];
- Genesys_Settings settings;
- Genesys_Frontend frontend;
- Genesys_Sensor sensor;
- Genesys_Gpo gpo;
- Genesys_Motor motor;
- uint16_t slope_table0[256];
- uint16_t slope_table1[256];
- uint8_t control[6];
- time_t init_date;
-
- size_t average_size;
- size_t calib_pixels; /**< number of pixels used during shading calibration */
- size_t calib_lines; /**< number of lines used during shading calibration */
- size_t calib_channels;
- size_t calib_resolution;
- uint8_t *white_average_data;
- uint8_t *dark_average_data;
- uint16_t dark[3];
-
- SANE_Bool already_initialized;
- SANE_Int scanhead_position_in_steps;
- SANE_Int lamp_off_time;
-
- SANE_Bool read_active;
- SANE_Bool parking; /**< signal wether the park command has been issued */
- SANE_Bool document; /**< for sheetfed scanner's, is TRUE when there
- is a document in the scanner */
-
- Genesys_Buffer read_buffer;
- Genesys_Buffer lines_buffer;
- Genesys_Buffer shrink_buffer;
- Genesys_Buffer out_buffer;
- Genesys_Buffer binarize_buffer; /**< buffer for digital lineart from gray data */
- Genesys_Buffer local_buffer; /**< local buffer for gray data during dynamix lineart */
-
- size_t read_bytes_left; /**< bytes to read from scanner */
-
- size_t total_bytes_read; /**< total bytes read sent to frontend */
- size_t total_bytes_to_read; /**< total bytes read to be sent to frontend */
- size_t wpl; /**< asic's word per line */
-
- Genesys_Current_Setup current_setup; /* contains the real used values */
-
- /**< look up table used in dynamic rasterization */
- unsigned char lineart_lut[256];
-
- Genesys_Calibration_Cache *calibration_cache;
-
- struct Genesys_Device *next;
-
- SANE_Int ld_shift_r; /**< used red line-distance shift*/
- SANE_Int ld_shift_g; /**< used green line-distance shift*/
- SANE_Int ld_shift_b; /**< used blue line-distance shift*/
- int segnb; /**< number of segments composing the sensor */
- int line_interp; /**< number of lines used in line interpolation */
- int line_count; /**< number of scan lines used during scan */
- size_t bpl; /**< bytes per full scan widthline */
- size_t dist; /**< bytes distance between an odd and an even pixel */
- size_t len; /**< number of even pixels */
- size_t cur; /**< current pixel position within sub window */
- size_t skip; /**< number of bytes to skip at start of line */
- size_t *order; /**< array describing the order of the sub-segments of the sensor */
- Genesys_Buffer oe_buffer; /**< buffer to handle even/odd data */
-
- SANE_Bool buffer_image; /**< when true the scanned picture is first buffered
- * to allow software image enhancements */
- SANE_Byte *img_buffer; /**< image buffer where the scanned picture is stored */
-
- FILE *binary; /**< binary logger file */
+ Genesys_Device() = default;
+ ~Genesys_Device();
+
+ using Calibration = std::vector<Genesys_Calibration_Cache>;
+
+ // frees commonly used data
+ void clear();
+
+ UsbDevice usb_dev;
+ 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;
+
+ SANE_String file_name = nullptr;
+ std::string calib_file;
+
+ // if enabled, no calibration data will be loaded or saved to files
+ SANE_Int force_calibration = 0;
+ Genesys_Model *model = nullptr;
+
+ Genesys_Register_Set reg;
+ Genesys_Register_Set calib_reg;
+ Genesys_Settings settings;
+ Genesys_Frontend frontend, frontend_initial;
+ Genesys_Gpo gpo;
+ Genesys_Motor motor;
+ uint8_t control[6] = {};
+ time_t init_date = 0;
+
+ 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;
+ // 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<uint16_t> gamma_override_tables[3];
+
+ std::vector<uint8_t> white_average_data;
+ std::vector<uint8_t> dark_average_data;
+ uint16_t dark[3] = {};
+
+ SANE_Bool already_initialized = 0;
+ SANE_Int scanhead_position_in_steps = 0;
+ SANE_Int lamp_off_time = 0;
+
+ SANE_Bool read_active = 0;
+ // signal wether the park command has been issued
+ SANE_Bool parking = 0;
+
+ // for sheetfed scanner's, is TRUE when there is a document in the scanner
+ SANE_Bool document = 0;
+
+ SANE_Bool needs_home_ta = 0;
+
+ Genesys_Buffer read_buffer;
+ Genesys_Buffer lines_buffer;
+ Genesys_Buffer shrink_buffer;
+ Genesys_Buffer out_buffer;
+
+ // buffer for digital lineart from gray data
+ Genesys_Buffer binarize_buffer = {};
+ // local buffer for gray data during dynamix lineart
+ Genesys_Buffer local_buffer = {};
+
+ // bytes to read from scanner
+ size_t read_bytes_left = 0;
+
+ // 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;
+ // asic's word per line
+ size_t wpl = 0;
+
+ // contains the real used values
+ Genesys_Current_Setup current_setup;
+
+ // look up table used in dynamic rasterization
+ unsigned char lineart_lut[256] = {};
+
+ Calibration calibration_cache;
+
+ // used red line-distance shift
+ SANE_Int ld_shift_r = 0;
+ // used green line-distance shift
+ SANE_Int ld_shift_g = 0;
+ // used blue line-distance shift
+ SANE_Int ld_shift_b = 0;
+ // number of segments composing the sensor
+ int segnb = 0;
+ // number of lines used in line interpolation
+ int line_interp = 0;
+ // number of scan lines used during scan
+ int line_count = 0;
+ // bytes per full scan widthline
+ size_t bpl = 0;
+ // bytes distance between an odd and an even pixel
+ size_t dist = 0;
+ // number of even pixels
+ size_t len = 0;
+ // current pixel position within sub window
+ size_t cur = 0;
+ // number of bytes to skip at start of line
+ size_t skip = 0;
+
+ // array describing the order of the sub-segments of the sensor
+ size_t* order = nullptr;
+
+ // buffer to handle even/odd data
+ Genesys_Buffer oe_buffer = {};
+
+ // when true the scanned picture is first buffered to allow software image enhancements
+ SANE_Bool buffer_image = 0;
+
+ // image buffer where the scanned picture is stored
+ std::vector<uint8_t> img_buffer;
+
+ // binary logger file
+ FILE *binary = nullptr;
};
typedef struct Genesys_USB_Device_Entry
@@ -858,7 +1624,7 @@ typedef struct {
int motor_type; /**< motor id */
int exposure; /**< exposure for the slope table */
int step_type; /**< default step type for given exposure */
- uint32_t *table; /**< 0 terminated slope table at full step */
+ uint32_t *table; // 0-terminated slope table at full step (i.e. step_type == 0)
} Motor_Profile;
#define FULL_STEP 0
@@ -908,13 +1674,26 @@ typedef struct {
/* common functions needed by low level specific functions */
/*--------------------------------------------------------------------------*/
-extern Genesys_Register_Set *sanei_genesys_get_address (Genesys_Register_Set * regs, uint16_t addr);
+inline GenesysRegister* sanei_genesys_get_address(Genesys_Register_Set* regs, uint16_t addr)
+{
+ auto* ret = regs->find_reg_address(addr);
+ if (ret == nullptr) {
+ DBG(DBG_error, "%s: failed to find address for register 0x%02x, crash expected !\n",
+ __func__, addr);
+ }
+ return ret;
+}
-extern SANE_Byte
-sanei_genesys_read_reg_from_set (Genesys_Register_Set * regs, uint16_t address);
+inline uint8_t sanei_genesys_read_reg_from_set(Genesys_Register_Set* regs, uint16_t address)
+{
+ return regs->get8(address);
+}
-extern void
-sanei_genesys_set_reg_from_set (Genesys_Register_Set * regs, uint16_t address, SANE_Byte value);
+inline void sanei_genesys_set_reg_from_set(Genesys_Register_Set* regs, uint16_t address,
+ uint8_t value)
+{
+ regs->set8(address, value);
+}
extern SANE_Status sanei_genesys_init_cmd_set (Genesys_Device * dev);
@@ -931,25 +1710,38 @@ extern SANE_Status
sanei_genesys_write_hregister (Genesys_Device * dev, uint16_t reg, uint8_t val);
extern SANE_Status
-sanei_genesys_bulk_write_register (Genesys_Device * dev,
- Genesys_Register_Set * reg,
- size_t elems);
+sanei_genesys_bulk_write_register(Genesys_Device * dev,
+ Genesys_Register_Set& regs);
extern SANE_Status sanei_genesys_write_0x8c (Genesys_Device * dev, uint8_t index, uint8_t val);
+extern unsigned sanei_genesys_get_bulk_max_size(Genesys_Device * dev);
+
+extern SANE_Status sanei_genesys_bulk_read_data(Genesys_Device * dev, uint8_t addr, uint8_t* data,
+ size_t len);
+
+extern SANE_Status sanei_genesys_bulk_write_data(Genesys_Device * dev, uint8_t addr, uint8_t* data,
+ size_t len);
+
extern SANE_Status sanei_genesys_get_status (Genesys_Device * dev, uint8_t * status);
extern void sanei_genesys_print_status (uint8_t val);
extern SANE_Status
-sanei_genesys_write_ahb (SANE_Int dn, int usb_mode, uint32_t addr, uint32_t size, uint8_t * data);
-
-extern void sanei_genesys_init_fe (Genesys_Device * dev);
+sanei_genesys_write_ahb(Genesys_Device* dev, uint32_t addr, uint32_t size, uint8_t * data);
extern void sanei_genesys_init_structs (Genesys_Device * dev);
+const Genesys_Sensor& sanei_genesys_find_sensor_any(Genesys_Device* dev);
+Genesys_Sensor& sanei_genesys_find_sensor_any_for_write(Genesys_Device* dev);
+const Genesys_Sensor& sanei_genesys_find_sensor(Genesys_Device* dev, int dpi,
+ ScanMethod scan_method = ScanMethod::FLATBED);
+Genesys_Sensor& sanei_genesys_find_sensor_for_write(Genesys_Device* dev, int dpi,
+ ScanMethod scan_method = ScanMethod::FLATBED);
+
extern SANE_Status
-sanei_genesys_init_shading_data (Genesys_Device * dev, int pixels_per_line);
+sanei_genesys_init_shading_data (Genesys_Device * dev, const Genesys_Sensor& sensor,
+ int pixels_per_line);
extern SANE_Status sanei_genesys_read_valid_words (Genesys_Device * dev,
unsigned int *steps);
@@ -960,6 +1752,11 @@ extern SANE_Status sanei_genesys_read_scancnt (Genesys_Device * dev,
extern SANE_Status sanei_genesys_read_feed_steps (Genesys_Device * dev,
unsigned int *steps);
+void sanei_genesys_set_lamp_power(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs, bool set);
+
+void sanei_genesys_set_motor_power(Genesys_Register_Set& regs, bool set);
+
extern void
sanei_genesys_calculate_zmode2 (SANE_Bool two_table,
uint32_t exposure_time,
@@ -1026,24 +1823,28 @@ sanei_genesys_create_slope_table3 (Genesys_Device * dev,
unsigned int *final_exposure,
int power_mode);
-extern void
-sanei_genesys_create_gamma_table (uint16_t * gamma_table, int size,
- float maximum, float gamma_max,
- float gamma);
+void sanei_genesys_create_default_gamma_table(Genesys_Device* dev,
+ std::vector<uint16_t>& gamma_table, float gamma);
+
+std::vector<uint16_t> get_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ int color);
-extern SANE_Status sanei_genesys_send_gamma_table (Genesys_Device * dev);
+SANE_Status sanei_genesys_send_gamma_table(Genesys_Device * dev, const Genesys_Sensor& sensor);
extern SANE_Status sanei_genesys_start_motor (Genesys_Device * dev);
extern SANE_Status sanei_genesys_stop_motor (Genesys_Device * dev);
extern SANE_Status
-sanei_genesys_search_reference_point (Genesys_Device * dev, uint8_t * data,
- int start_pixel, int dpi, int width,
- int height);
+sanei_genesys_search_reference_point(Genesys_Device * dev, Genesys_Sensor& sensor,
+ uint8_t * data,
+ int start_pixel, int dpi, int width,
+ int height);
+
+extern SANE_Status sanei_genesys_write_file(const char *filename, uint8_t* data, size_t length);
extern SANE_Status
-sanei_genesys_write_pnm_file (char *filename, uint8_t * data, int depth,
+sanei_genesys_write_pnm_file (const char *filename, uint8_t * data, int depth,
int channels, int pixels_per_line, int lines);
extern SANE_Status
@@ -1053,35 +1854,54 @@ extern SANE_Status
sanei_genesys_read_data_from_scanner (Genesys_Device * dev, uint8_t * data,
size_t size);
-extern SANE_Status
-sanei_genesys_buffer_alloc(Genesys_Buffer * buf, size_t size);
-
-extern SANE_Status
-sanei_genesys_buffer_free(Genesys_Buffer * buf);
-
-extern SANE_Byte *
-sanei_genesys_buffer_get_write_pos(Genesys_Buffer * buf, size_t size);
-
-extern SANE_Byte *
-sanei_genesys_buffer_get_read_pos(Genesys_Buffer * buf);
+inline void sanei_genesys_set_double(Genesys_Register_Set* regs, uint16_t addr, uint16_t value)
+{
+ regs->set16(addr, value);
+}
-extern SANE_Status
-sanei_genesys_buffer_produce(Genesys_Buffer * buf, size_t size);
+inline void sanei_genesys_set_triple(Genesys_Register_Set* regs, uint16_t addr, uint32_t value)
+{
+ regs->set24(addr, value);
+}
-extern SANE_Status
-sanei_genesys_buffer_consume(Genesys_Buffer * buf, size_t size);
+inline void sanei_genesys_get_double(Genesys_Register_Set* regs, uint16_t addr, uint16_t* value)
+{
+ *value = regs->get16(addr);
+}
-extern SANE_Status
-sanei_genesys_set_double(Genesys_Register_Set *regs, uint16_t addr, uint16_t value);
+inline void sanei_genesys_get_triple(Genesys_Register_Set* regs, uint16_t addr, uint32_t* value)
+{
+ *value = regs->get24(addr);
+}
-extern SANE_Status
-sanei_genesys_set_triple(Genesys_Register_Set *regs, uint16_t addr, uint32_t value);
+inline void sanei_genesys_set_exposure(Genesys_Register_Set& regs, const SensorExposure& exposure)
+{
+ regs.set8(0x10, (exposure.red >> 8) & 0xff);
+ regs.set8(0x11, exposure.red & 0xff);
+ regs.set8(0x12, (exposure.green >> 8) & 0xff);
+ regs.set8(0x13, exposure.green & 0xff);
+ regs.set8(0x14, (exposure.blue >> 8) & 0xff);
+ regs.set8(0x15, exposure.blue & 0xff);
+}
-extern SANE_Status
-sanei_genesys_get_double(Genesys_Register_Set *regs, uint16_t addr, uint16_t *value);
+inline uint16_t sanei_genesys_fixup_exposure_value(uint16_t value)
+{
+ if ((value & 0xff00) == 0) {
+ value |= 0x100;
+ }
+ if ((value & 0x00ff) == 0) {
+ value |= 0x1;
+ }
+ return value;
+}
-extern SANE_Status
-sanei_genesys_get_triple(Genesys_Register_Set *regs, uint16_t addr, uint32_t *value);
+inline SensorExposure sanei_genesys_fixup_exposure(SensorExposure exposure)
+{
+ exposure.red = sanei_genesys_fixup_exposure_value(exposure.red);
+ exposure.green = sanei_genesys_fixup_exposure_value(exposure.green);
+ exposure.blue = sanei_genesys_fixup_exposure_value(exposure.blue);
+ return exposure;
+}
extern SANE_Status
sanei_genesys_wait_for_home(Genesys_Device *dev);
@@ -1089,8 +1909,10 @@ sanei_genesys_wait_for_home(Genesys_Device *dev);
extern SANE_Status
sanei_genesys_asic_init(Genesys_Device *dev, SANE_Bool cold);
-extern
-int sanei_genesys_compute_dpihw(Genesys_Device *dev, int xres);
+int sanei_genesys_compute_dpihw(Genesys_Device *dev, const Genesys_Sensor& sensor, int xres);
+
+int sanei_genesys_compute_dpihw_calibration(Genesys_Device *dev, const Genesys_Sensor& sensor,
+ int xres);
extern
Motor_Profile *sanei_genesys_get_motor_profile(Motor_Profile *motors, int motor_type, int exposure);
@@ -1119,15 +1941,8 @@ int sanei_genesys_get_lowest_ydpi(Genesys_Device *dev);
extern
int sanei_genesys_get_lowest_dpi(Genesys_Device *dev);
-/**
- * reads previously cached calibration data
- * from file
- */
-extern SANE_Status
-sanei_genesys_read_calibration (Genesys_Device * dev);
-
-extern SANE_Status
-sanei_genesys_is_compatible_calibration (Genesys_Device * dev,
+extern bool
+sanei_genesys_is_compatible_calibration (Genesys_Device * dev, const Genesys_Sensor& sensor,
Genesys_Calibration_Cache * cache,
int for_overwrite);
@@ -1160,78 +1975,12 @@ sanei_genesys_load_lut (unsigned char * lut,
extern SANE_Status
sanei_genesys_generate_gamma_buffer(Genesys_Device * dev,
+ const Genesys_Sensor& sensor,
int bits,
int max,
int size,
uint8_t *gamma);
-#ifdef UNIT_TESTING
-SANE_Status
-genesys_send_offset_and_shading (Genesys_Device * dev,
- uint8_t * data,
- int size);
-
-void
-genesys_average_data (uint8_t * average_data,
- uint8_t * calibration_data,
- uint32_t lines,
- uint32_t pixel_components_per_line);
-
-void
-compute_averaged_planar (Genesys_Device * dev,
- uint8_t * shading_data,
- unsigned int pixels_per_line,
- unsigned int words_per_color,
- unsigned int channels,
- unsigned int o,
- unsigned int coeff,
- unsigned int target_bright,
- unsigned int target_dark);
-
-
-void
-compute_coefficients (Genesys_Device * dev,
- uint8_t * shading_data,
- unsigned int pixels_per_line,
- unsigned int channels,
- unsigned int cmat[3],
- int offset,
- unsigned int coeff,
- unsigned int target);
-
-void
-compute_planar_coefficients (Genesys_Device * dev,
- uint8_t * shading_data,
- unsigned int factor,
- unsigned int pixels_per_line,
- unsigned int words_per_color,
- unsigned int channels,
- unsigned int cmat[3],
- unsigned int offset,
- unsigned int coeff,
- unsigned int target);
-
-void
-compute_shifted_coefficients (Genesys_Device * dev,
- uint8_t * shading_data,
- unsigned int pixels_per_line,
- unsigned int channels,
- unsigned int cmat[3],
- int offset,
- unsigned int coeff,
- unsigned int target_dark,
- unsigned int target_bright,
- unsigned int patch_size); /* contigous extent */
-
-SANE_Status
-probe_genesys_devices (void);
-
-SANE_Status genesys_flatbed_calibration (Genesys_Device *dev);
-
-SANE_Status genesys_send_shading_coefficient (Genesys_Device *dev);
-#endif
-
-
/*---------------------------------------------------------------------------*/
/* ASIC specific functions declarations */
/*---------------------------------------------------------------------------*/
@@ -1242,4 +1991,52 @@ extern SANE_Status sanei_gl846_init_cmd_set (Genesys_Device * dev);
extern SANE_Status sanei_gl847_init_cmd_set (Genesys_Device * dev);
extern SANE_Status sanei_gl124_init_cmd_set (Genesys_Device * dev);
+// same as usleep, except that it does nothing if testing mode is enabled
+extern void sanei_genesys_usleep(unsigned int useconds);
+
+// same as sanei_genesys_usleep just that the duration is in milliseconds
+extern void sanei_genesys_sleep_ms(unsigned int milliseconds);
+
+void add_function_to_run_at_backend_exit(std::function<void()> function);
+
+// calls functions added via add_function_to_run_at_backend_exit() in reverse order of being
+// added.
+void run_functions_at_backend_exit();
+
+template<class T>
+class StaticInit {
+public:
+ StaticInit() = default;
+ StaticInit(const StaticInit&) = delete;
+ StaticInit& operator=(const StaticInit&) = delete;
+
+ template<class... Args>
+ void init(Args&& ... args)
+ {
+ ptr_ = std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+ add_function_to_run_at_backend_exit([this](){ deinit(); });
+ }
+
+ void deinit()
+ {
+ ptr_.release();
+ }
+
+ const T* operator->() const { return ptr_.get(); }
+ T* operator->() { return ptr_.get(); }
+ const T& operator*() const { return *ptr_.get(); }
+ T& operator*() { return *ptr_.get(); }
+
+private:
+ std::unique_ptr<T> ptr_;
+};
+
+extern StaticInit<std::vector<Genesys_Sensor>> s_sensors;
+void genesys_init_sensor_tables();
+void genesys_init_frontend_tables();
+
+void debug_dump(unsigned level, const Genesys_Settings& settings);
+void debug_dump(unsigned level, const SetupParams& params);
+void debug_dump(unsigned level, const Genesys_Current_Setup& setup);
+
#endif /* not GENESYS_LOW_H */