1/* sane - Scanner Access Now Easy. 2 3 Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt> 4 5 This file is part of the SANE package. 6 7 This program is free software; you can redistribute it and/or 8 modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the 10 License, or (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <https://www.gnu.org/licenses/>. 19*/ 20 21#ifndef BACKEND_GENESYS_DEVICE_H 22#define BACKEND_GENESYS_DEVICE_H 23 24#include "calibration.h" 25#include "command_set.h" 26#include "enums.h" 27#include "image_pipeline.h" 28#include "motor.h" 29#include "settings.h" 30#include "sensor.h" 31#include "register.h" 32#include "usb_device.h" 33#include "scanner_interface.h" 34#include "utilities.h" 35#include <vector> 36 37namespace genesys { 38 39struct Genesys_Gpo 40{ 41 Genesys_Gpo() = default; 42 43 // Genesys_Gpo 44 GpioId id = GpioId::UNKNOWN; 45 46 /* GL646 and possibly others: 47 - have the value registers at 0x66 and 0x67 48 - have the enable registers at 0x68 and 0x69 49 50 GL841, GL842, GL843, GL846, GL848 and possibly others: 51 - have the value registers at 0x6c and 0x6d. 52 - have the enable registers at 0x6e and 0x6f. 53 */ 54 GenesysRegisterSettingSet regs; 55}; 56 57struct MemoryLayout 58{ 59 // This is used on GL845, GL846, GL847 and GL124 which have special registers to define the 60 // memory layout 61 MemoryLayout() = default; 62 63 ValueFilter<ModelId> models; 64 65 GenesysRegisterSettingSet regs; 66}; 67 68struct MethodResolutions 69{ 70 std::vector<ScanMethod> methods; 71 std::vector<unsigned> resolutions_x; 72 std::vector<unsigned> resolutions_y; 73 74 unsigned get_min_resolution_x() const 75 { 76 return *std::min_element(resolutions_x.begin(), resolutions_x.end()); 77 } 78 79 unsigned get_nearest_resolution_x(unsigned resolution) const 80 { 81 return *std::min_element(resolutions_x.begin(), resolutions_x.end(), 82 [&](unsigned lhs, unsigned rhs) 83 { 84 return std::abs(static_cast<int>(lhs) - static_cast<int>(resolution)) < 85 std::abs(static_cast<int>(rhs) - static_cast<int>(resolution)); 86 }); 87 } 88 89 unsigned get_min_resolution_y() const 90 { 91 return *std::min_element(resolutions_y.begin(), resolutions_y.end()); 92 } 93 94 std::vector<unsigned> get_resolutions() const; 95}; 96 97/** @brief structure to describe a scanner model 98 * This structure describes a model. It is composed of information on the 99 * sensor, the motor, scanner geometry and flags to drive operation. 100 */ 101struct Genesys_Model 102{ 103 Genesys_Model() = default; 104 105 const char* name = nullptr; 106 const char* vendor = nullptr; 107 const char* model = nullptr; 108 ModelId model_id = ModelId::UNKNOWN; 109 110 AsicType asic_type = AsicType::UNKNOWN; 111 112 // possible x and y resolutions for each method supported by the scanner 113 std::vector<MethodResolutions> resolutions; 114 115 // possible depths in gray mode 116 std::vector<unsigned> bpp_gray_values; 117 // possible depths in color mode 118 std::vector<unsigned> bpp_color_values; 119 120 // the default scanning method. This is used when moving the head for example 121 ScanMethod default_method = ScanMethod::FLATBED; 122 123 // All offsets below are with respect to the sensor home position 124 125 // Start of scan area in mm 126 float x_offset = 0; 127 128 // Start of scan area in mm (Amount of feeding needed to get to the medium) 129 float y_offset = 0; 130 131 // Size of scan area in mm 132 float x_size = 0; 133 134 // Size of scan area in mm 135 float y_size = 0; 136 137 // Start of white strip in mm for scanners that use separate dark and white shading calibration. 138 float y_offset_calib_white = 0; 139 140 // The size of the scan area that is used to acquire shading data in mm 141 float y_size_calib_mm = 0; 142 143 // Start of the black/white strip in mm for scanners that use unified dark and white shading 144 // calibration. 145 float y_offset_calib_dark_white_mm = 0; 146 147 // The size of the scan area that is used to acquire dark/white shading data in mm 148 float y_size_calib_dark_white_mm = 0; 149 150 // The width of the scan area that is used to acquire shading data 151 float x_size_calib_mm = 0; 152 153 // Start of black mark in mm 154 float x_offset_calib_black = 0; 155 156 // Start of scan area in transparency mode in mm 157 float x_offset_ta = 0; 158 159 // Start of scan area in transparency mode in mm 160 float y_offset_ta = 0; 161 162 // Size of scan area in transparency mode in mm 163 float x_size_ta = 0; 164 165 // Size of scan area in transparency mode in mm 166 float y_size_ta = 0; 167 168 // The position of the sensor when it's aligned with the lamp for transparency scanning 169 float y_offset_sensor_to_ta = 0; 170 171 // Start of white strip in transparency mode in mm 172 float y_offset_calib_white_ta = 0; 173 174 // Start of black strip in transparency mode in mm 175 float y_offset_calib_black_ta = 0; 176 177 // The size of the scan area that is used to acquire shading data in transparency mode in mm 178 float y_size_calib_ta_mm = 0; 179 180 // Size of scan area after paper sensor stop sensing document in mm 181 float post_scan = 0; 182 183 // Amount of feeding needed to eject document after finishing scanning in mm 184 float eject_feed = 0; 185 186 // Line-distance correction (in pixel at motor base_ydpi) for CCD scanners 187 SANE_Int ld_shift_r = 0; 188 SANE_Int ld_shift_g = 0; 189 SANE_Int ld_shift_b = 0; 190 191 // Order of the CCD/CIS colors 192 ColorOrder line_mode_color_order = ColorOrder::RGB; 193 194 // Is this a CIS or CCD scanner? 195 bool is_cis = false; 196 197 // Is this sheetfed scanner? 198 bool is_sheetfed = false; 199 200 // sensor type 201 SensorId sensor_id = SensorId::UNKNOWN; 202 // Analog-Digital converter type 203 AdcId adc_id = AdcId::UNKNOWN; 204 // General purpose output type 205 GpioId gpio_id = GpioId::UNKNOWN; 206 // stepper motor type 207 MotorId motor_id = MotorId::UNKNOWN; 208 209 // Which customizations are needed for this scanner? 210 ModelFlag flags = ModelFlag::NONE; 211 212 // Button flags, described existing buttons for the model 213 SANE_Word buttons = 0; 214 215 // how many lines are used to search start position 216 SANE_Int search_lines = 0; 217 218 // returns nullptr if method is not supported 219 const MethodResolutions* get_resolution_settings_ptr(ScanMethod method) const; 220 221 // throws if method is not supported 222 const MethodResolutions& get_resolution_settings(ScanMethod method) const; 223 224 std::vector<unsigned> get_resolutions(ScanMethod method) const; 225 226 bool has_method(ScanMethod method) const; 227}; 228 229/** 230 * Describes the current device status for the backend 231 * session. This should be more accurately called 232 * Genesys_Session . 233 */ 234struct Genesys_Device 235{ 236 Genesys_Device() = default; 237 ~Genesys_Device(); 238 239 using Calibration = std::vector<Genesys_Calibration_Cache>; 240 241 // frees commonly used data 242 void clear(); 243 244 std::uint16_t vendorId = 0; // USB vendor identifier 245 std::uint16_t productId = 0; // USB product identifier 246 247 // USB mode: 248 // 0: not set 249 // 1: USB 1.1 250 // 2: USB 2.0 251 SANE_Int usb_mode = 0; 252 253 std::string file_name; 254 std::string calib_file; 255 256 // if enabled, no calibration data will be loaded or saved to files 257 SANE_Int force_calibration = 0; 258 // if enabled, will ignore the scan offsets and start scanning at true origin. This allows 259 // acquiring the positions of the black and white strips and the actual scan area 260 bool ignore_offsets = false; 261 262 const Genesys_Model* model = nullptr; 263 264 // pointers to low level functions 265 std::unique_ptr<CommandSet> cmd_set; 266 267 Genesys_Register_Set reg; 268 Genesys_Register_Set initial_regs; 269 Genesys_Settings settings; 270 Genesys_Frontend frontend, frontend_initial; 271 Genesys_Gpo gpo; 272 MemoryLayout memory_layout; 273 Genesys_Motor motor; 274 std::uint8_t control[6] = {}; 275 276 size_t average_size = 0; 277 278 // the session that was configured for calibration 279 ScanSession calib_session; 280 281 // gamma overrides. If a respective array is not empty then it means that the gamma for that 282 // color is overridden. 283 std::vector<std::uint16_t> gamma_override_tables[3]; 284 285 std::vector<std::uint16_t> white_average_data; 286 std::vector<std::uint16_t> dark_average_data; 287 288 bool already_initialized = false; 289 290 bool read_active = false; 291 // signal whether the park command has been issued 292 bool parking = false; 293 294 // for sheetfed scanner's, is TRUE when there is a document in the scanner 295 bool document = false; 296 297 // total bytes read sent to frontend 298 size_t total_bytes_read = 0; 299 // total bytes read to be sent to frontend 300 size_t total_bytes_to_read = 0; 301 302 // contains computed data for the current setup 303 ScanSession session; 304 305 Calibration calibration_cache; 306 307 // number of scan lines used during scan 308 int line_count = 0; 309 310 // array describing the order of the sub-segments of the sensor 311 std::vector<unsigned> segment_order; 312 313 // stores information about how the input image should be processed 314 ImagePipelineStack pipeline; 315 316 // an buffer that allows reading from `pipeline` in chunks of any size 317 ImageBuffer pipeline_buffer; 318 319 ImagePipelineNodeBufferedCallableSource& get_pipeline_source(); 320 321 std::unique_ptr<ScannerInterface> interface; 322 323 bool is_head_pos_known(ScanHeadId scan_head) const; 324 unsigned head_pos(ScanHeadId scan_head) const; 325 void set_head_pos_unknown(ScanHeadId scan_head); 326 void set_head_pos_zero(ScanHeadId scan_head); 327 void advance_head_pos_by_session(ScanHeadId scan_head); 328 void advance_head_pos_by_steps(ScanHeadId scan_head, Direction direction, unsigned steps); 329 330private: 331 // the position of the primary scan head in motor->base_dpi units 332 unsigned head_pos_primary_ = 0; 333 bool is_head_pos_primary_known_ = true; 334 335 // the position of the secondary scan head in motor->base_dpi units. Only certain scanners 336 // have a secondary scan head. 337 unsigned head_pos_secondary_ = 0; 338 bool is_head_pos_secondary_known_ = true; 339 340 friend class ScannerInterfaceUsb; 341}; 342 343std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev); 344 345void apply_reg_settings_to_device(Genesys_Device& dev, const GenesysRegisterSettingSet& regs); 346 347void apply_reg_settings_to_device_write_only(Genesys_Device& dev, 348 const GenesysRegisterSettingSet& regs); 349GenesysRegisterSettingSet 350 apply_reg_settings_to_device_with_backup(Genesys_Device& dev, 351 const GenesysRegisterSettingSet& regs); 352 353} // namespace genesys 354 355#endif 356