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