1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
|
/* 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, see <https://www.gnu.org/licenses/>.
*/
#ifndef BACKEND_GENESYS_DEVICE_H
#define BACKEND_GENESYS_DEVICE_H
#include "calibration.h"
#include "command_set.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 "utilities.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;
};
struct MemoryLayout
{
// This is used on GL845, GL846, GL847 and GL124 which have special registers to define the
// memory layout
MemoryLayout() = default;
ValueFilter<ModelId> models;
GenesysRegisterSettingSet regs;
};
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_nearest_resolution_x(unsigned resolution) const
{
return *std::min_element(resolutions_x.begin(), resolutions_x.end(),
[&](unsigned lhs, unsigned rhs)
{
return std::abs(static_cast<int>(lhs) - static_cast<int>(resolution)) <
std::abs(static_cast<int>(rhs) - static_cast<int>(resolution));
});
}
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
float x_offset = 0;
// Start of scan area in mm (Amount of feeding needed to get to the medium)
float y_offset = 0;
// Size of scan area in mm
float x_size = 0;
// Size of scan area in mm
float y_size = 0;
// Start of white strip in mm for scanners that use separate dark and white shading calibration.
float y_offset_calib_white = 0;
// The size of the scan area that is used to acquire shading data in mm
float y_size_calib_mm = 0;
// Start of the black/white strip in mm for scanners that use unified dark and white shading
// calibration.
float y_offset_calib_dark_white_mm = 0;
// The size of the scan area that is used to acquire dark/white shading data in mm
float y_size_calib_dark_white_mm = 0;
// The width of the scan area that is used to acquire shading data
float x_size_calib_mm = 0;
// Start of black mark in mm
float x_offset_calib_black = 0;
// Start of scan area in transparency mode in mm
float x_offset_ta = 0;
// Start of scan area in transparency mode in mm
float y_offset_ta = 0;
// Size of scan area in transparency mode in mm
float x_size_ta = 0;
// Size of scan area in transparency mode in mm
float y_size_ta = 0;
// The position of the sensor when it's aligned with the lamp for transparency scanning
float y_offset_sensor_to_ta = 0;
// Start of white strip in transparency mode in mm
float y_offset_calib_white_ta = 0;
// Start of black strip in transparency mode in mm
float y_offset_calib_black_ta = 0;
// The size of the scan area that is used to acquire shading data in transparency mode in mm
float y_size_calib_ta_mm = 0;
// Size of scan area after paper sensor stop sensing document in mm
float post_scan = 0;
// Amount of feeding needed to eject document after finishing scanning in mm
float eject_feed = 0;
// Line-distance correction (in pixel at motor base_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 customizations are needed for this scanner?
ModelFlag flags = ModelFlag::NONE;
// Button flags, described existing buttons for the model
SANE_Word buttons = 0;
// how many lines are used to search start position
SANE_Int search_lines = 0;
// returns nullptr if method is not supported
const MethodResolutions* get_resolution_settings_ptr(ScanMethod method) const;
// throws if method is not supported
const MethodResolutions& get_resolution_settings(ScanMethod method) const;
std::vector<unsigned> get_resolutions(ScanMethod method) const;
bool has_method(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();
std::uint16_t vendorId = 0; // USB vendor identifier
std::uint16_t 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;
const Genesys_Model* model = nullptr;
// pointers to low level functions
std::unique_ptr<CommandSet> cmd_set;
Genesys_Register_Set reg;
Genesys_Register_Set initial_regs;
Genesys_Settings settings;
Genesys_Frontend frontend, frontend_initial;
Genesys_Gpo gpo;
MemoryLayout memory_layout;
Genesys_Motor motor;
std::uint8_t control[6] = {};
size_t average_size = 0;
// the session that was configured for calibration
ScanSession calib_session;
// 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 whether 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;
// 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;
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;
// 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;
ImagePipelineNodeBufferedCallableSource& 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(ScanHeadId scan_head);
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);
void apply_reg_settings_to_device_write_only(Genesys_Device& dev,
const GenesysRegisterSettingSet& regs);
GenesysRegisterSettingSet
apply_reg_settings_to_device_with_backup(Genesys_Device& dev,
const GenesysRegisterSettingSet& regs);
} // namespace genesys
#endif
|