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