• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
37 namespace genesys {
38 
39 struct 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 
57 struct 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 
68 struct MethodResolutions
69 {
70     std::vector<ScanMethod> methods;
71     std::vector<unsigned> resolutions_x;
72     std::vector<unsigned> resolutions_y;
73 
get_min_resolution_xMethodResolutions74     unsigned get_min_resolution_x() const
75     {
76         return *std::min_element(resolutions_x.begin(), resolutions_x.end());
77     }
78 
get_nearest_resolution_xMethodResolutions79     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 
get_min_resolution_yMethodResolutions89     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  */
101 struct 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  */
234 struct 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 
330 private:
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 
343 std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev);
344 
345 void apply_reg_settings_to_device(Genesys_Device& dev, const GenesysRegisterSettingSet& regs);
346 
347 void apply_reg_settings_to_device_write_only(Genesys_Device& dev,
348                                              const GenesysRegisterSettingSet& regs);
349 GenesysRegisterSettingSet
350     apply_reg_settings_to_device_with_backup(Genesys_Device& dev,
351                                              const GenesysRegisterSettingSet& regs);
352 
353 } // namespace genesys
354 
355 #endif
356