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