1 /* sane - Scanner Access Now Easy.
2
3 Copyright (C) 2003 Oliver Rauch
4 Copyright (C) 2003, 2004 Henning Meier-Geinitz <henning@meier-geinitz.de>
5 Copyright (C) 2004, 2005 Gerhard Jaeger <gerhard@gjaeger.de>
6 Copyright (C) 2004-2013 Stéphane Voltz <stef.dev@free.fr>
7 Copyright (C) 2005-2009 Pierre Willenbrock <pierre@pirsoft.dnsalias.org>
8 Copyright (C) 2006 Laurent Charpentier <laurent_pubs@yahoo.com>
9 Parts of the structs have been taken from the gt68xx backend by
10 Sergey Vlasov <vsu@altlinux.ru> et al.
11
12 This file is part of the SANE package.
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program. If not, see <https://www.gnu.org/licenses/>.
26
27 As a special exception, the authors of SANE give permission for
28 additional uses of the libraries contained in this release of SANE.
29
30 The exception is that, if you link a SANE library with other files
31 to produce an executable, this does not by itself cause the
32 resulting executable to be covered by the GNU General Public
33 License. Your use of that executable is in no way restricted on
34 account of linking the SANE library code into it.
35
36 This exception does not, however, invalidate any other reasons why
37 the executable file might be covered by the GNU General Public
38 License.
39
40 If you submit changes to SANE to the maintainers to be included in
41 a subsequent release, you agree by submitting the changes that
42 those changes may be distributed with this exception intact.
43
44 If you write modifications of your own for SANE, it is your choice
45 whether to permit this exception to apply to your modifications.
46 If you do not wish that, delete this exception notice.
47 */
48
49 #ifndef GENESYS_LOW_H
50 #define GENESYS_LOW_H
51
52
53 #include "../include/sane/config.h"
54
55 #include <errno.h>
56 #include <string.h>
57 #include <stdlib.h>
58 #include <unistd.h>
59 #include <math.h>
60 #include <stddef.h>
61 #ifdef HAVE_SYS_TIME_H
62 #include <sys/time.h>
63 #endif
64 #ifdef HAVE_SYS_TYPES_H
65 #include <sys/types.h>
66 #endif
67 #ifdef HAVE_MKDIR
68 #include <sys/stat.h>
69 #include <sys/types.h>
70 #endif
71
72 #include "../include/sane/sane.h"
73 #include "../include/sane/sanei.h"
74 #include "../include/sane/saneopts.h"
75
76 #include "../include/sane/sanei_backend.h"
77 #include "../include/sane/sanei_usb.h"
78
79 #include "../include/_stdint.h"
80
81 #include "device.h"
82 #include "enums.h"
83 #include "error.h"
84 #include "fwd.h"
85 #include "usb_device.h"
86 #include "sensor.h"
87 #include "serialize.h"
88 #include "settings.h"
89 #include "static_init.h"
90 #include "status.h"
91 #include "register.h"
92
93 #include <algorithm>
94 #include <array>
95 #include <cstring>
96 #include <functional>
97 #include <iostream>
98 #include <sstream>
99 #include <limits>
100 #include <memory>
101 #include <stdexcept>
102 #include <string>
103 #include <vector>
104
105 #define GENESYS_RED 0
106 #define GENESYS_GREEN 1
107 #define GENESYS_BLUE 2
108
109 #define GENESYS_HAS_NO_BUTTONS 0 /**< scanner has no supported button */
110 #define GENESYS_HAS_SCAN_SW (1 << 0) /**< scanner has SCAN button */
111 #define GENESYS_HAS_FILE_SW (1 << 1) /**< scanner has FILE button */
112 #define GENESYS_HAS_COPY_SW (1 << 2) /**< scanner has COPY button */
113 #define GENESYS_HAS_EMAIL_SW (1 << 3) /**< scanner has EMAIL button */
114 #define GENESYS_HAS_PAGE_LOADED_SW (1 << 4) /**< scanner has paper in detection */
115 #define GENESYS_HAS_OCR_SW (1 << 5) /**< scanner has OCR button */
116 #define GENESYS_HAS_POWER_SW (1 << 6) /**< scanner has power button */
117 #define GENESYS_HAS_CALIBRATE (1 << 7) /**< scanner has 'calibrate' software button to start calibration */
118 #define GENESYS_HAS_EXTRA_SW (1 << 8) /**< scanner has extra function button */
119
120 /* USB control message values */
121 #define REQUEST_TYPE_IN (USB_TYPE_VENDOR | USB_DIR_IN)
122 #define REQUEST_TYPE_OUT (USB_TYPE_VENDOR | USB_DIR_OUT)
123 #define REQUEST_REGISTER 0x0c
124 #define REQUEST_BUFFER 0x04
125 #define VALUE_BUFFER 0x82
126 #define VALUE_SET_REGISTER 0x83
127 #define VALUE_READ_REGISTER 0x84
128 #define VALUE_WRITE_REGISTER 0x85
129 #define VALUE_INIT 0x87
130 #define GPIO_OUTPUT_ENABLE 0x89
131 #define GPIO_READ 0x8a
132 #define GPIO_WRITE 0x8b
133 #define VALUE_BUF_ENDACCESS 0x8c
134 #define VALUE_GET_REGISTER 0x8e
135 #define INDEX 0x00
136
137 /* todo: used?
138 #define VALUE_READ_STATUS 0x86
139 */
140
141 /* Read/write bulk data/registers */
142 #define BULK_OUT 0x01
143 #define BULK_IN 0x00
144 #define BULK_RAM 0x00
145 #define BULK_REGISTER 0x11
146
147 #define BULKOUT_MAXSIZE 0xF000
148
149 /* AFE values */
150 #define AFE_INIT 1
151 #define AFE_SET 2
152 #define AFE_POWER_SAVE 4
153
154 namespace genesys {
155
156 class UsbDeviceEntry {
157 public:
158 static constexpr std::uint16_t BCD_DEVICE_NOT_SET = 0xffff;
159
UsbDeviceEntry(std::uint16_t vendor_id,std::uint16_t product_id,const Genesys_Model & model)160 UsbDeviceEntry(std::uint16_t vendor_id, std::uint16_t product_id,
161 const Genesys_Model& model) :
162 vendor_{vendor_id}, product_{product_id},
163 bcd_device_{BCD_DEVICE_NOT_SET}, model_{model}
164 {}
165
UsbDeviceEntry(std::uint16_t vendor_id,std::uint16_t product_id,std::uint16_t bcd_device,const Genesys_Model & model)166 UsbDeviceEntry(std::uint16_t vendor_id, std::uint16_t product_id, std::uint16_t bcd_device,
167 const Genesys_Model& model) :
168 vendor_{vendor_id}, product_{product_id},
169 bcd_device_{bcd_device}, model_{model}
170 {}
171
vendor_id()172 std::uint16_t vendor_id() const { return vendor_; }
product_id()173 std::uint16_t product_id() const { return product_; }
bcd_device()174 std::uint16_t bcd_device() const { return bcd_device_; }
175
model()176 const Genesys_Model& model() const { return model_; }
177
matches(std::uint16_t vendor_id,std::uint16_t product_id,std::uint16_t bcd_device)178 bool matches(std::uint16_t vendor_id, std::uint16_t product_id, std::uint16_t bcd_device)
179 {
180 if (vendor_ != vendor_id)
181 return false;
182 if (product_ != product_id)
183 return false;
184 if (bcd_device_ != BCD_DEVICE_NOT_SET && bcd_device != BCD_DEVICE_NOT_SET &&
185 bcd_device_ != bcd_device)
186 {
187 return false;
188 }
189 return true;
190 }
191
192 private:
193 // USB vendor identifier
194 std::uint16_t vendor_;
195 // USB product identifier
196 std::uint16_t product_;
197 // USB bcdProduct identifier
198 std::uint16_t bcd_device_;
199 // Scanner model information
200 Genesys_Model model_;
201 };
202
203 /*--------------------------------------------------------------------------*/
204 /* common functions needed by low level specific functions */
205 /*--------------------------------------------------------------------------*/
206
207 std::unique_ptr<CommandSet> create_cmd_set(AsicType asic_type);
208
209 // reads the status of the scanner
210 Status scanner_read_status(Genesys_Device& dev);
211
212 // reads the status of the scanner reliably. This is done by reading the status twice. The first
213 // read sometimes returns the home sensor as engaged when this is not true.
214 Status scanner_read_reliable_status(Genesys_Device& dev);
215
216 // reads and prints the scanner status
217 void scanner_read_print_status(Genesys_Device& dev);
218
219 void debug_print_status(DebugMessageHelper& dbg, Status status);
220
221 void scanner_register_rw_clear_bits(Genesys_Device& dev, std::uint16_t address, std::uint8_t mask);
222 void scanner_register_rw_set_bits(Genesys_Device& dev, std::uint16_t address, std::uint8_t mask);
223 void scanner_register_rw_bits(Genesys_Device& dev, std::uint16_t address,
224 std::uint8_t value, std::uint8_t mask);
225
226 extern void sanei_genesys_write_ahb(Genesys_Device* dev, uint32_t addr, uint32_t size,
227 uint8_t* data);
228
229 extern void sanei_genesys_init_structs (Genesys_Device * dev);
230
231 const Genesys_Sensor& sanei_genesys_find_sensor_any(const Genesys_Device* dev);
232 const Genesys_Sensor& sanei_genesys_find_sensor(const Genesys_Device* dev, unsigned dpi,
233 unsigned channels, ScanMethod scan_method);
234 bool sanei_genesys_has_sensor(const Genesys_Device* dev, unsigned dpi, unsigned channels,
235 ScanMethod scan_method);
236 Genesys_Sensor& sanei_genesys_find_sensor_for_write(Genesys_Device* dev, unsigned dpi,
237 unsigned channels, ScanMethod scan_method);
238
239 std::vector<std::reference_wrapper<const Genesys_Sensor>>
240 sanei_genesys_find_sensors_all(const Genesys_Device* dev, ScanMethod scan_method);
241 std::vector<std::reference_wrapper<Genesys_Sensor>>
242 sanei_genesys_find_sensors_all_for_write(Genesys_Device* dev, ScanMethod scan_method);
243
244 extern void sanei_genesys_init_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor,
245 int pixels_per_line);
246
247 extern void sanei_genesys_read_valid_words(Genesys_Device* dev, unsigned int* steps);
248
249 extern void sanei_genesys_read_scancnt(Genesys_Device* dev, unsigned int* steps);
250
251 extern void sanei_genesys_read_feed_steps(Genesys_Device* dev, unsigned int* steps);
252
253 void sanei_genesys_set_lamp_power(Genesys_Device* dev, const Genesys_Sensor& sensor,
254 Genesys_Register_Set& regs, bool set);
255
256 void sanei_genesys_set_motor_power(Genesys_Register_Set& regs, bool set);
257
258 bool should_enable_gamma(const ScanSession& session, const Genesys_Sensor& sensor);
259
260 /** Calculates the values of the Z{1,2}MOD registers. They are a phase correction to synchronize
261 with the line clock during acceleration and deceleration.
262
263 two_table is true if moving is done by two tables, false otherwise.
264
265 acceleration_steps is the number of steps for acceleration, i.e. the number written to
266 REG_STEPNO.
267
268 move_steps number of steps to move, i.e. the number written to REG_FEEDL.
269
270 buffer_acceleration_steps, the number of steps for acceleration when buffer condition is met,
271 i.e. the number written to REG_FWDSTEP.
272 */
273 void sanei_genesys_calculate_zmod(bool two_table,
274 uint32_t exposure_time,
275 const std::vector<uint16_t>& slope_table,
276 unsigned acceleration_steps,
277 unsigned move_steps,
278 unsigned buffer_acceleration_steps,
279 uint32_t* out_z1, uint32_t* out_z2);
280
281 extern void sanei_genesys_set_buffer_address(Genesys_Device* dev, uint32_t addr);
282
283 unsigned sanei_genesys_get_bulk_max_size(AsicType asic_type);
284
285 SANE_Int sanei_genesys_exposure_time2(Genesys_Device* dev, const MotorProfile& profile, float ydpi,
286 int endpixel, int led_exposure);
287
288 void sanei_genesys_create_default_gamma_table(Genesys_Device* dev,
289 std::vector<uint16_t>& gamma_table, float gamma);
290
291 std::vector<uint16_t> get_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor,
292 int color);
293
294 void sanei_genesys_send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor);
295
296 extern void sanei_genesys_stop_motor(Genesys_Device* dev);
297
298 // moves the scan head by the specified steps at the motor base dpi
299 void scanner_move(Genesys_Device& dev, ScanMethod scan_method, unsigned steps, Direction direction);
300
301 void scanner_move_back_home(Genesys_Device& dev, bool wait_until_home);
302 void scanner_move_back_home_ta(Genesys_Device& dev);
303
304 /** Search for a full width black or white strip.
305 This function searches for a black or white stripe across the scanning area.
306 When searching backward, the searched area must completely be of the desired
307 color since this area will be used for calibration which scans forward.
308
309 @param dev scanner device
310 @param forward true if searching forward, false if searching backward
311 @param black true if searching for a black strip, false for a white strip
312 */
313 void scanner_search_strip(Genesys_Device& dev, bool forward, bool black);
314
315 bool should_calibrate_only_active_area(const Genesys_Device& dev,
316 const Genesys_Settings& settings);
317
318 void scanner_offset_calibration(Genesys_Device& dev, const Genesys_Sensor& sensor,
319 Genesys_Register_Set& regs);
320
321 void scanner_coarse_gain_calibration(Genesys_Device& dev, const Genesys_Sensor& sensor,
322 Genesys_Register_Set& regs, unsigned dpi);
323
324 SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor& sensor,
325 Genesys_Register_Set& regs);
326
327 void scanner_clear_scan_and_feed_counts(Genesys_Device& dev);
328
329 void scanner_send_slope_table(Genesys_Device* dev, const Genesys_Sensor& sensor, unsigned table_nr,
330 const std::vector<uint16_t>& slope_table);
331
332 extern void sanei_genesys_write_file(const char* filename, const std::uint8_t* data,
333 std::size_t length);
334
335 void wait_until_buffer_non_empty(Genesys_Device* dev, bool check_status_twice = false);
336
337 extern void sanei_genesys_read_data_from_scanner(Genesys_Device* dev, uint8_t* data, size_t size);
338
339 Image read_unshuffled_image_from_scanner(Genesys_Device* dev, const ScanSession& session,
340 std::size_t total_bytes);
341
342 void regs_set_exposure(AsicType asic_type, Genesys_Register_Set& regs,
343 const SensorExposure& exposure);
344
345 void regs_set_optical_off(AsicType asic_type, Genesys_Register_Set& regs);
346
347 void sanei_genesys_set_dpihw(Genesys_Register_Set& regs, unsigned dpihw);
348
sanei_genesys_fixup_exposure(SensorExposure exposure)349 inline SensorExposure sanei_genesys_fixup_exposure(SensorExposure exposure)
350 {
351 exposure.red = std::max<std::uint16_t>(1, exposure.red);
352 exposure.green = std::max<std::uint16_t>(1, exposure.green);
353 exposure.blue = std::max<std::uint16_t>(1, exposure.blue);
354 return exposure;
355 }
356
357 bool get_registers_gain4_bit(AsicType asic_type, const Genesys_Register_Set& regs);
358
359 extern void sanei_genesys_wait_for_home(Genesys_Device* dev);
360
361 extern void sanei_genesys_asic_init(Genesys_Device* dev);
362
363 void scanner_start_action(Genesys_Device& dev, bool start_motor);
364 void scanner_stop_action(Genesys_Device& dev);
365 void scanner_stop_action_no_move(Genesys_Device& dev, Genesys_Register_Set& regs);
366
367 bool scanner_is_motor_stopped(Genesys_Device& dev);
368
369 void scanner_setup_sensor(Genesys_Device& dev, const Genesys_Sensor& sensor,
370 Genesys_Register_Set& regs);
371
372 const MotorProfile* get_motor_profile_ptr(const std::vector<MotorProfile>& profiles,
373 unsigned exposure,
374 const ScanSession& session);
375
376 const MotorProfile& get_motor_profile(const std::vector<MotorProfile>& profiles,
377 unsigned exposure,
378 const ScanSession& session);
379
380 MotorSlopeTable create_slope_table(AsicType asic_type, const Genesys_Motor& motor, unsigned ydpi,
381 unsigned exposure, unsigned step_multiplier,
382 const MotorProfile& motor_profile);
383
384 MotorSlopeTable create_slope_table_fastest(AsicType asic_type, unsigned step_multiplier,
385 const MotorProfile& motor_profile);
386
387 /** @brief find lowest motor resolution for the device.
388 * Parses the resolution list for motor and
389 * returns the lowest value.
390 * @param dev for which to find the lowest motor resolution
391 * @return the lowest available motor resolution for the device
392 */
393 extern
394 int sanei_genesys_get_lowest_ydpi(Genesys_Device *dev);
395
396 /** @brief find lowest resolution for the device.
397 * Parses the resolution list for motor and sensor and
398 * returns the lowest value.
399 * @param dev for which to find the lowest resolution
400 * @return the lowest available resolution for the device
401 */
402 extern
403 int sanei_genesys_get_lowest_dpi(Genesys_Device *dev);
404
405 bool sanei_genesys_is_compatible_calibration(Genesys_Device* dev,
406 const ScanSession& session,
407 const Genesys_Calibration_Cache* cache,
408 bool for_overwrite);
409
410 extern void sanei_genesys_load_lut(unsigned char* lut,
411 int in_bits, int out_bits,
412 int out_min, int out_max,
413 int slope, int offset);
414
415 extern void sanei_genesys_generate_gamma_buffer(Genesys_Device* dev,
416 const Genesys_Sensor& sensor,
417 int bits,
418 int max,
419 int size,
420 uint8_t* gamma);
421
422 unsigned session_adjust_output_pixels(unsigned output_pixels,
423 const Genesys_Device& dev, const Genesys_Sensor& sensor,
424 unsigned output_xresolution, unsigned output_yresolution,
425 bool adjust_output_pixels);
426
427 void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Sensor& sensor);
428
429 ImagePipelineStack build_image_pipeline(const Genesys_Device& dev, const ScanSession& session,
430 unsigned pipeline_index, bool log_image_data);
431
432 // sets up a image pipeline for device `dev`
433 void setup_image_pipeline(Genesys_Device& dev, const ScanSession& session);
434
435 std::uint8_t compute_frontend_gain(float value, float target_value,
436 FrontendType frontend_type);
437
438 /*---------------------------------------------------------------------------*/
439 /* ASIC specific functions declarations */
440 /*---------------------------------------------------------------------------*/
441
442 extern StaticInit<std::vector<Genesys_Sensor>> s_sensors;
443 extern StaticInit<std::vector<Genesys_Frontend>> s_frontends;
444 extern StaticInit<std::vector<Genesys_Gpo>> s_gpo;
445 extern StaticInit<std::vector<MemoryLayout>> s_memory_layout;
446 extern StaticInit<std::vector<Genesys_Motor>> s_motors;
447 extern StaticInit<std::vector<UsbDeviceEntry>> s_usb_devices;
448
449 void genesys_init_sensor_tables();
450 void genesys_init_frontend_tables();
451 void genesys_init_gpo_tables();
452 void genesys_init_memory_layout_tables();
453 void genesys_init_motor_tables();
454 void genesys_init_usb_device_tables();
455 void verify_sensor_tables();
456 void verify_usb_device_tables();
457
458 template<class T>
debug_dump(unsigned level,const T & value)459 void debug_dump(unsigned level, const T& value)
460 {
461 std::stringstream out;
462 out << value;
463 DBG(level, "%s\n", out.str().c_str());
464 }
465
466 } // namespace genesys
467
468 #endif /* not GENESYS_LOW_H */
469