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