1 /* sane - Scanner Access Now Easy.
2    Copyright (C) 2007 Ilia Sotnikov <hostcc@gmail.com>
3    HP ScanJet 4570c support by Markham Thomas
4    ADF page detection and high DPI fixes by Bernard Badeer
5    scanbd integration by Damiano Scaramuzza and Bernard Badeer
6    This file is part of the SANE package.
7 
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2 of the
11    License, or (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <https://www.gnu.org/licenses/>.
20 
21    As a special exception, the authors of SANE give permission for
22    additional uses of the libraries contained in this release of SANE.
23 
24    The exception is that, if you link a SANE library with other files
25    to produce an executable, this does not by itself cause the
26    resulting executable to be covered by the GNU General Public
27    License.  Your use of that executable is in no way restricted on
28    account of linking the SANE library code into it.
29 
30    This exception does not, however, invalidate any other reasons why
31    the executable file might be covered by the GNU General Public
32    License.
33 
34    If you submit changes to SANE to the maintainers to be included in
35    a subsequent release, you agree by submitting the changes that
36    those changes may be distributed with this exception intact.
37 
38    If you write modifications of your own for SANE, it is your choice
39    whether to permit this exception to apply to your modifications.
40    If you do not wish that, delete this exception notice.
41 
42    This file is part of a SANE backend for
43    HP ScanJet 4500C/4570C/5500C/5550C/5590/7650 Scanners
44 */
45 
46 #include "../include/sane/config.h"
47 
48 #ifdef HAVE_UNISTD_H
49 # include <unistd.h>
50 #endif /* HAVE_UNISTD_H */
51 #ifdef HAVE_NETINET_IN_H
52 # include <netinet/in.h>
53 #endif /* HAVE_NETINET_IN_H */
54 #include <errno.h>
55 #include <string.h>
56 
57 #include "../include/sane/sanei_debug.h"
58 #include "../include/_stdint.h"
59 #include "hp5590_low.h"
60 #include "hp5590_cmds.h"
61 
62 static const struct hp5590_model
63 hp5590_models[] = {
64   {
65     SCANNER_HP4570,
66     0x03f0, 0x1305, "SILITEKIElwood",
67     "4570C/5500C", "Workgroup scanner",
68     PF_NONE
69   },
70   {
71     SCANNER_HP5550,
72     0x03f0, 0x1205, "SILITEKIPenguin",
73     "4500C/5550C", "Workgroup scanner",
74     PF_NO_USB_IN_USB_ACK                /* These devices need no
75                                          * acknowledgment after USB-in-USB
76                                          * commands */
77   },
78   {
79     SCANNER_HP5590,
80     0x03f0, 0x1705, "SILITEKIPenguin",
81     "5590", "Workgroup scanner",
82     PF_NONE
83   },
84   {
85     SCANNER_HP7650,
86     0x03f0, 0x1805, "SILITEKIArnold",
87     "7650", "Document scanner",
88     PF_NONE
89   }
90 };
91 
92 /* Debug levels */
93 #define DBG_err         0
94 #define DBG_proc        10
95 #define DBG_verbose     20
96 #define DBG_cmds        40
97 
98 #define hp5590_cmds_assert(exp) if(!(exp)) { \
99   DBG (DBG_err, "Assertion '%s' failed at %s:%u\n", #exp, __FILE__, __LINE__);\
100   return SANE_STATUS_INVAL; \
101 }
102 
103 #define WAKEUP_TIMEOUT          90
104 
105 /* First byte of init (0x12 cmd) response */
106 #define INIT_FLAG_TMA           1 << 0
107 #define INIT_FLAG_ADF           1 << 1
108 #define INIT_FLAG_LCD           1 << 3
109 
110 /* Power (0x24 cmd) */
111 #define POWER_FLAG_ON           1 << 1
112 
113 /* ADF (0x03 cmd) */
114 #define FLAG_ADF_EMPTY          1 << 1
115 
116 #define PART_NUMBER_LEN         10
117 
118 #define REVERSE_MAP_LEN         128 * 1024 / sizeof(uint16_t)
119 #define FORWARD_MAP_LEN         128 * 1024 / sizeof(uint16_t)
120 
121 /* Button flags */
122 /* From left to right */
123 /* 1:   Power
124  * 1:   Scan
125  * 2:   Collect
126  * 3:   File
127  * 4:   Email
128  * 5:   Copy
129  * 6,7: Up/down
130  * 8:   Mode
131  * 9:   Cancel
132  */
133 #define BUTTON_FLAG_EMAIL       1 << 15
134 #define BUTTON_FLAG_COPY        1 << 14
135 #define BUTTON_FLAG_DOWN        1 << 13
136 #define BUTTON_FLAG_MODE        1 << 12
137 #define BUTTON_FLAG_UP          1 << 11
138 #define BUTTON_FLAG_FILE        1 << 9
139 #define BUTTON_FLAG_POWER       1 << 5
140 #define BUTTON_FLAG_SCAN        1 << 2
141 #define BUTTON_FLAG_COLLECT     1 << 1
142 #define BUTTON_FLAG_CANCEL      1 << 0
143 
144 #define CMD_INIT                0x0012
145 #define CMD_EEPROM_ADDR         0x00f2
146 #define CMD_EEPROM_READ         0x0bf0
147 #define CMD_EEPROM_WRITE        0x0bf1
148 #define CMD_DATA_STATUS         0x0001
149 #define CMD_STOP_SCAN           0x011b
150 #define CMD_CONTROL_LAMP        0x00c0
151 #define CMD_POWER_STATUS        0x0024
152 #define CMD_SELECT_SOURCE       0x00d6
153 #define CMD_MISC_STATUS         0x0003
154 #define CMD_LOCK_UNLOCK         0x0000
155 #define CMD_SET_BASE_DPI        0x0015
156 #define CMD_SET_COLOR_MAP       0x0240
157 #define CMD_SET_SCAN_PARAMS     0x0025
158 #define CMD_GET_IMAGE_PARAMS    0x0034
159 #define CMD_START_SCAN          0x051b
160 #define CMD_BUTTON_STATUS       0x0020
161 #define CMD_LCD_STATUS          0x0021
162 
163 struct init_resp
164 {
165   uint8_t       flags;                  /* bit 0 - TMA, bit 1 - ADF, bit 3 - LCD present */
166   uint8_t       id[15];                 /* SILITEKPenguin */
167   uint8_t       pad1[9];                /* 00 00 00 00 00 00 00 00 00 */
168   uint8_t       version[5];             /* 0.0.67 */
169   uint16_t      max_dpi_x;              /* 09 60 = 2400 */
170   uint16_t      max_dpi_y;              /* 09 60 = 2400 */
171   uint16_t      max_pixels_x;           /* 4F B0 = 20400 (20400 / 2400 = 8.5")   */
172   uint16_t      max_pixels_y;           /* 6D E0 = 28128 (28128 / 2400 = 11.72") */
173   uint8_t       pad2[8];                /* 00 00 00 00 00 00 00 00 */
174   uint16_t      motor_param_normal;     /* 00 64 = 100 */
175   uint16_t      motor_param_max;        /* 03 E8 = 1000 */
176 } __attribute__ ((packed));
177 
178 struct power_resp
179 {
180   uint8_t flags;
181   uint16_t unk1;
182 } __attribute__ ((packed));
183 
184 /*
185  * 215.9 mm x 297.2 mm
186  * 8.5" x 11.72"
187  *
188  *   50 :  425.00 x  586.00
189  *   75 :  637.50 x  879.50
190  *  100 :  850.00 x 1172.00
191  *  150 : 1275.00 x 1758.00 (base DPI)
192  *  200 : 1700.00 x 2344.00
193  *  300 : 2550.00 x 3516.00 (base DPI)
194  *  400 : 3400.00 x 4688.00
195  *  600 : 5100.00 x 7032.00 (base DPI)
196  */
197 
198 #define SCAN_PARAMS_SOURCE_TMA_NEGATIVES        1 << 0
199 #define SCAN_PARAMS_SOURCE_TMA_SLIDES           1 << 1
200 #define SCAN_PARAMS_SOURCE_ADF                  1 << 2
201 #define SCAN_PARAMS_SOURCE_FLATBED              1 << 3
202 #define SCAN_PARAMS_SOURCE_SIMPLEX              1 << 4
203 #define SCAN_PARAMS_SOURCE_DUPLEX               1 << 6
204 
205 struct scan_params
206 {
207   uint8_t source;               /*
208                                  * TMA Negatives        : 11 = 17
209                                  * TMA Slides           : 12 = 18
210                                  * ADF                  : 14 = 20
211                                  * Flatbed              : 18 = 24
212                                  * ADF Duplex           : 54 = 84
213                                  */
214 
215   uint16_t dpi_x;               /*
216                                  *  50  : 00 64 = 100
217                                  *  75  : 00 64 = 100
218                                  * 100  : 00 64 = 100
219                                  * 150  : 00 c8 = 200
220                                  * 200  : 00 c8 = 200
221                                  * 300  : 01 2c = 300
222                                  * 400  : 02 58 = 600
223                                  * 600  : 02 58 = 600
224                                  * 1200 : 04 b0 = 1200
225                                  */
226 
227   uint16_t dpi_y;               /*
228                                  *  50  : 00 64 = 100
229                                  *  75  : 00 64 = 100
230                                  * 100  : 00 64 = 100
231                                  * 150  : 00 c8 = 200
232                                  * 200  : 00 c8 = 200
233                                  * 300  : 01 2c = 300
234                                  * 400  : 02 58 = 600
235                                  * 600  : 02 58 = 600
236                                  * 1200 : 04 b0 = 1200
237                                  */
238 
239   uint16_t top_x;               /*
240                                  * pixels * (Base DPI / current DPI)
241                                  * 00 00, 01 6e = 366 (x = 425 - 302 = 123)
242                                  * 04 b0 = 1200 (x = 425 - 24 = 401)
243                                  */
244 
245   uint16_t top_y;               /*
246                                  * pixels * (Base DPI / current DPI)
247                                  * 00 00, 06 99 = 1689 (y = 585 - 21 = 564)
248                                  */
249 
250   uint16_t size_x;              /* X pixels in Base DPI (CMD 15)
251                                  *  50          : 04f8 =  1272                           ; 150
252                                  *  75          : 04f8 =  1272                           ; 150
253                                  * 100          : 04f8 =  1272                           ; 150
254                                  * 100 TMA      : 00fc =   252                           ; 150
255                                  * 150          : 09f6 =  2550, 09f0 = 2544, 09f4 = 2548 ; 300
256                                  * 200          : 09f0 =  2544, 09f6 = 2550, 09f6 = 2550 ; 300
257                                  * 300          : 09f6 =  2550, 09f0 = 2544, 09f4 = 2548 ; 300
258                                  * 300 TMA      : 01fc =   508                           ; 300
259                                  * 400          : 13ec =  5100                           ; 600
260                                  * 600          : 13e8 =  5096, 13ec = 5100 ,13ec = 5100 ; 600
261                                  * 1200         : 27a8 = 10152                           ; 1200
262                                  */
263 
264   uint16_t size_y;              /* Y pixels in Base DPI (CMD 15)
265                                  *  50          : 06db =  1755 ; 150
266                                  *  75          : 06da =  1754 ; 150
267                                  * 100          : 06db =  1755 ; 150
268                                  * 100 TMA      : 0384 =   900 ; 150
269                                  * 150          : 0db6 =  3510 ; 300
270                                  * 200          : 0db6 =  3510 ; 300
271                                  * 300          : 0db6 =  3510 ; 300
272                                  * 300 TMA      : 0708 =  1800 ; 300
273                                  * 400          : 1b6c =  7020 ; 600
274                                  * 600          : 1b6c =  7020 ; 600
275                                  * 1200         : 36d8 = 14040 ; 1200
276                                  */
277 
278   uint16_t unk1;                /* 00 80 */
279 
280   uint16_t bw_gray_flag;        /*
281                                  * 00 40 - bw (ntsc gray)/gray,
282                                  * 00 20 - bw (by green band),
283                                  * 00 10 - bw (by red band),
284                                  * 00 30 - bw (by blue band),
285                                  * 00 00 - color
286                                  */
287 
288   uint8_t pixel_bits;           /*
289                                  * bw 50/75/150/400                             : 08 =  8
290                                  * bw 100/200/300/600/1200                      : 01 =  1
291                                  * gray 50/75/100/150/200/400/600               : 08 =  8
292                                  * color 24 bit 50/75/100/150/200/400/600       : 18 = 24
293                                  * color 48 bit 100/200                         : 30 = 48
294                                  */
295 
296   uint16_t flags;               /*
297                                  * 50/75/100/150/200/300                : e8 40 = 59456
298                                  * 400/600/1200                         : c8 40 = 51264
299                                  */
300 
301   uint16_t motor_param1;        /*
302                                  * 00 64 = 100
303                                  */
304   uint16_t motor_param2;        /*
305                                  * 00 64 = 100 - ADF, Flatbed, TMA slides
306                                  * 00 c8 = 200 - TMA Negatives
307                                  */
308   uint16_t motor_param3;        /*
309                                  * 00 64 = 100 - ADF, Flatbed, TMA slides
310                                  * 01 90 = 400 - TMA negatives
311                                  */
312   uint32_t pad1;                /* 00 00 00 00 */
313   uint16_t pad2;                /* 00 00 */
314   uint8_t mode;                 /* 00 - normal scan, 04 - preview scan */
315   uint16_t pad3;                /* 00 00 */
316 
317   uint16_t line_width;          /* Based on current .dpi_x
318                                  * bw 50                                : 03 50 =   848
319                                  * gray 50                              : 03 50 =   848
320                                  * color 50                             : 09 f0 =  2544 (3 * gray)
321                                  *
322                                  * bw 75                                : 03 50 =   848
323                                  * gray 75                              : 03 50 =   848
324                                  * color 75                             : 09 f0 =  2544 (3 * gray)
325                                  *
326                                  * bw 100                               : 00 6a =   106
327                                  * gray 100                             : 03 50 =   848 (8 * bw)
328                                  * color 100(24)                        : 09 f0 =  2544 (3 * gray)
329                                  * color 100(48)                        : 13 e0 =  5088 (2 * color 24)
330                                  * color 100(48) TMA                    : 03 f0 = 1008
331                                  *
332                                  * bw 150                               : 06 a4 =  1700
333                                  * gray 150                             : 06 a4 =  1700
334                                  * color 150                            : 13 ec =  5100 (3 * gray)
335                                  *
336                                  * bw 200                               : 00 d4 =   212
337                                  * gray 200                             : 06 a4 =  1700 (8 * bw)
338                                  * color 200(24)                        : 13 ec =  5100 (3 * gray)
339                                  * color 200(48)                        : 27 a8 = 10152
340                                  *
341                                  * bw 300                               : 01 3e =   318
342                                  * gray 300                             : 09 f4 =  2548 (8 * bw)
343                                  * color 300                            : 1d dc =  7644 (3 * gray)
344                                  * color 300(48) TMA                    : 0b e8 = 3048
345                                  *
346                                  * bw 400                               : 13 ec =  5100
347                                  * gray 400                             : 13 ec =  5100
348                                  * color 400                            : 3b c4 = 15300 (3 * gray)
349                                  *
350                                  * bw 600                               : 02 7d =   637
351                                  * gray 600                             : 13 ec =  5100 (8 * bw)
352                                  * color 600                            : 3b c4 = 15300 (3 * gray)
353                                  *
354                                  * bw 1200                              : 04 f5 =  1269
355                                  */
356 } __attribute__ ((packed));
357 
358 struct image_params
359 {
360   uint8_t signature;            /* c0 */
361   uint8_t pad1;         /* 00 */
362   uint32_t image_size;          /*
363                                  * bw 50                : 00 0f 23 a0 =    992 160
364                                  * gray 50              : 00 0f 23 a0 =    992 160
365                                  * color 50             : 00 2d 6a e0 =  2 976 480
366                                  *
367                                  * bw 75                : 00 0f 20 50 =    991 312
368                                  * gray 75              : 00 0f 20 50 =    991 312
369                                  * color 75             : 00 2d 60 f0 =  2 973 936
370                                  * color 75(48)         : 00 5a 86 40 =  5 932 608
371                                  *
372                                  * bw 100               : 00 01 e4 74 =    124 020
373                                  * gray 100             : 00 0f 23 a0 =    992 160
374                                  * color 100            : 00 2d 6a e0 =  2 976 480
375                                  * color 100(48)        : 00 5a 68 10 =  5 924 880
376                                  * color 100(48), preview: 00 5a d5 c0 = 5 952 960
377                                  *
378                                  * bw 150               : 00 3c b3 10 =   3 978 000
379                                  * gray 150             : 00 3c b3 10 =   3 978 000
380                                  * color 150            : 00 b6 19 30 =  11 934 000
381                                  * color 150(48)        : 01 6a 7b a0 =  23 755 680
382                                  *
383                                  * bw 200               : 00 07 91 d0 =     496 080
384                                  * gray 200             : 00 3c b3 10 =   3 978 000
385                                  * color 200            : 00 b6 19 30 =  11 934 000
386                                  * color 200(48)        : 01 6a f3 a0 =  23 786 400
387                                  *
388                                  * bw 300               : 00 11 08 14 =   1 116 180
389                                  * gray 300             : 00 88 77 78 =   8 943 480
390                                  * color 300            : 01 99 66 68 =  26 830 440
391                                  *
392                                  * bw 400               : 02 22 4b 90 =  35 802 000
393                                  * gray 400             : 02 22 4b 90 =  35 802 000
394                                  * color 400            : 06 66 e2 b0 = 107 406 000
395                                  *
396                                  * bw 600               : 00 44 3b bc =   4 471 740
397                                  * gray 600             : 02 22 4b 90 =  35 802 000
398                                  * color 600            : 06 66 e2 b0 = 107 406 000
399                                  */
400   uint16_t pad2;                /* 00 00 */
401   uint16_t line_width;
402   uint16_t real_size_y;
403   uint32_t pad3;                /* 00 00 00 00 */
404 } __attribute__ ((packed));
405 
406 struct lamp_state
407 {
408   uint8_t       unk1;           /* 02 */
409   uint8_t       flag;           /* 01 on start, 02 - TMA, 03 - all other */
410   uint16_t      turnoff_time;   /* 0a 0a, 03 36, 0f 36 */
411 } __attribute__ ((packed));
412 
413 struct color_map
414 {
415   uint8_t       color1[6];      /* 00 00 00 00 01 00 */
416   uint8_t       color2[6];      /* 00 00 00 00 01 00 */
417   uint8_t       color3[6];      /* 00 00 00 00 01 00 */
418 } __attribute__ ((packed));
419 
420 struct reg_03
421 {
422   uint8_t       unk1;           /* 0x0b - ADF ready, 0x03 - not */
423   uint8_t       unk2;           /* 0x80 */
424   uint8_t       adf_flags;      /* 0x01 - ADF ready when selected, 0x02 - not */
425 } __attribute__ ((packed));
426 
427 /******************************************************************************/
428 static SANE_Status
hp5590_model_def(enum hp_scanner_types scanner_type, const struct hp5590_model ** model)429 hp5590_model_def (enum hp_scanner_types scanner_type,
430                   const struct hp5590_model ** model)
431 {
432   unsigned int i;
433 
434   hp5590_cmds_assert (model != NULL);
435 
436   for (i = 0; i < sizeof (hp5590_models) / sizeof (struct hp5590_model); i++)
437     {
438       if (hp5590_models[i].scanner_type == scanner_type)
439         {
440           *model = &hp5590_models[i];
441           return SANE_STATUS_GOOD;
442         }
443     }
444 
445   return SANE_STATUS_INVAL;
446 }
447 
448 /******************************************************************************/
449 static SANE_Status
hp5590_vendor_product_id(enum hp_scanner_types scanner_type, SANE_Word * vendor_id, SANE_Word * product_id)450 hp5590_vendor_product_id (enum hp_scanner_types scanner_type,
451                           SANE_Word * vendor_id,
452                           SANE_Word * product_id)
453 {
454   const struct hp5590_model     *model;
455   SANE_Status                   ret;
456 
457   hp5590_cmds_assert (vendor_id != NULL);
458   hp5590_cmds_assert (product_id != NULL);
459 
460   ret = hp5590_model_def (scanner_type, &model);
461   if (ret != SANE_STATUS_GOOD)
462     return ret;
463   *vendor_id = model->usb_vendor_id;
464   *product_id = model->usb_product_id;
465 
466   return SANE_STATUS_GOOD;
467 }
468 
469 /******************************************************************************/
470 static SANE_Status
hp5590_init_scanner(SANE_Int dn, enum proto_flags proto_flags, struct scanner_info ** info, enum hp_scanner_types scanner_type)471 hp5590_init_scanner (SANE_Int dn,
472                      enum proto_flags proto_flags,
473                      struct scanner_info ** info,
474                      enum hp_scanner_types scanner_type)
475 {
476   struct init_resp              init_resp;
477   char                          id_buf[sizeof (init_resp.id) + 1];
478   char                          ver_buf[sizeof (init_resp.version) + 1];
479   SANE_Status                   ret;
480   const struct hp5590_model     *scanner_model;
481 
482   /*
483    * 0A 53 49 4C 49 54 45 4B 49 50 65 6E 67 75 69 6E  .SILITEKIPenguin
484    * 00 00 00 00 00 00 00 00 00 30 2E 30 36 37 09 60  .........0.067..
485    * 09 60 4F B0 6D E0 00 00 00 00 00 00 00 00 00 64  ..O.m..........d
486    * 03 E8                                            ..
487    */
488   DBG (DBG_proc, "%s\n", __func__);
489 
490   hp5590_cmds_assert (sizeof (init_resp) == 50);
491 
492   /* Init scanner */
493   ret = hp5590_cmd (dn,
494                     proto_flags,
495                     CMD_IN | CMD_VERIFY,
496                     CMD_INIT,
497                     (unsigned char *) &init_resp,
498                     sizeof (init_resp), CORE_NONE);
499   if (ret != SANE_STATUS_GOOD)
500     return ret;
501 
502   memset (id_buf, 0, sizeof (id_buf));
503   memcpy (id_buf, init_resp.id, sizeof (id_buf) - 1);
504   scanner_model = NULL;
505   if (scanner_type != SCANNER_NONE)
506     {
507       unsigned int i;
508       for (i = 0; i < sizeof (hp5590_models) / sizeof (struct hp5590_model);
509            i++)
510         {
511           if (hp5590_models[i].scanner_type == scanner_type)
512             {
513               if (strcmp (id_buf, hp5590_models[i].vendor_id) != 0)
514                 {
515                   DBG (DBG_err, "%s: Vendor id mismatch for scanner HP%s - "
516                        "required  '%s', got '%s'\n",
517                        __func__,
518                        hp5590_models[i].model,
519                        hp5590_models[i].vendor_id, id_buf);
520                   return SANE_STATUS_INVAL;
521                 }
522               scanner_model = &hp5590_models[i];
523               break;
524             }
525         }
526       hp5590_cmds_assert (scanner_model != NULL);
527     }
528 
529   if (scanner_model)
530     {
531       DBG (DBG_cmds, "HP%s flags (0x%02x)\n", scanner_model->model, init_resp.flags);
532 
533       DBG (DBG_cmds, "HP%s flags: ADF %s, TMA %s, LCD %s\n",
534            scanner_model->model,
535            init_resp.flags & INIT_FLAG_ADF ? "yes" : "no",
536            init_resp.flags & INIT_FLAG_TMA ? "yes" : "no",
537            init_resp.flags & INIT_FLAG_LCD ? "yes" : "no");
538 
539 
540       memset (ver_buf, 0, sizeof (ver_buf));
541       memcpy (ver_buf, init_resp.version, sizeof (ver_buf) - 1);
542       DBG (DBG_cmds, "HP%s firmware version: %s\n", scanner_model->model, ver_buf);
543 
544       DBG (DBG_cmds, "HP%s max resolution X: %u DPI\n",
545            scanner_model->model, ntohs (init_resp.max_dpi_x));
546       DBG (DBG_cmds, "HP%s max resolution Y: %u DPI\n",
547            scanner_model->model, ntohs (init_resp.max_dpi_y));
548       DBG (DBG_cmds, "HP%s max pixels X: %u\n",
549            scanner_model->model, ntohs (init_resp.max_pixels_x));
550       DBG (DBG_cmds, "HP%s max pixels Y: %u\n",
551            scanner_model->model, ntohs (init_resp.max_pixels_y));
552       DBG (DBG_cmds, "HP%s max size X: %.3f inches\n",
553            scanner_model->model,
554            ntohs (init_resp.max_pixels_x) * 1.0 /
555            ntohs (init_resp.max_dpi_x));
556       DBG (DBG_cmds, "HP%s max size Y: %.3f inches\n", scanner_model->model,
557            ntohs (init_resp.max_pixels_y) * 1.0 /
558            ntohs (init_resp.max_dpi_y));
559       DBG (DBG_cmds, "HP%s normal motor param: %u, max motor param: %u\n",
560            scanner_model->model, ntohs (init_resp.motor_param_normal),
561            ntohs (init_resp.motor_param_max));
562     }
563 
564   if (info)
565     {
566       *info = malloc (sizeof (struct scanner_info));
567       if (!*info)
568         {
569           DBG (DBG_err, "Memory allocation failed\n");
570           return SANE_STATUS_NO_MEM;
571         }
572       memset (*info, 0, sizeof (struct scanner_info));
573 
574       (*info)->max_dpi_x = ntohs (init_resp.max_dpi_x);
575       (*info)->max_dpi_y = ntohs (init_resp.max_dpi_y);
576       (*info)->max_pixels_x = ntohs (init_resp.max_pixels_x) - 1;
577       (*info)->max_pixels_y = ntohs (init_resp.max_pixels_y) + 1;
578       (*info)->max_size_x = (*info)->max_pixels_x * 1.0 / (*info)->max_dpi_x;
579       (*info)->max_size_y = (*info)->max_pixels_y * 1.0 / (*info)->max_dpi_y;
580       (*info)->features = FEATURE_NONE;
581       if (init_resp.flags & INIT_FLAG_LCD)
582         (*info)->features |= FEATURE_LCD;
583       if (init_resp.flags & INIT_FLAG_ADF)
584         (*info)->features |= FEATURE_ADF;
585       if (init_resp.flags & INIT_FLAG_TMA)
586         (*info)->features |= FEATURE_TMA;
587       if (scanner_model)
588         {
589           (*info)->model = scanner_model->model;
590           (*info)->kind = scanner_model->kind;
591         }
592     }
593 
594   ret = hp5590_get_status (dn, proto_flags);
595   if (ret != SANE_STATUS_GOOD)
596     {
597       DBG (DBG_err, "%s: scanner reports non-zero status: %s\n",
598            __func__, sane_strstatus (ret));
599       return ret;
600     }
601   DBG (DBG_cmds, "%s: scanner status OK\n", __func__);
602 
603   return SANE_STATUS_GOOD;
604 }
605 
606 /******************************************************************************/
607 static SANE_Status
hp5590_read_eeprom(SANE_Int dn, enum proto_flags proto_flags, unsigned int addr, unsigned char *data, unsigned int size)608 hp5590_read_eeprom (SANE_Int dn,
609                     enum proto_flags proto_flags,
610                     unsigned int addr,
611                     unsigned char *data, unsigned int size)
612 {
613   uint8_t eeprom_addr = addr;
614   SANE_Status ret;
615 
616   hp5590_cmds_assert (data != NULL);
617   hp5590_cmds_assert (sizeof (eeprom_addr) == 1);
618 
619   DBG (DBG_proc, "%s\n", __func__);
620   DBG (DBG_proc, "Reading EEPROM: addr %04x, size %u\n", addr, size);
621 
622   ret = hp5590_cmd (dn,
623                     proto_flags,
624                     CMD_VERIFY,
625                     CMD_EEPROM_ADDR,
626                     (unsigned char *) &eeprom_addr,
627                     sizeof (eeprom_addr), CORE_NONE);
628   if (ret != SANE_STATUS_GOOD)
629     return ret;
630 
631   ret = hp5590_cmd (dn,
632                     proto_flags,
633                     CMD_IN | CMD_VERIFY,
634                     CMD_EEPROM_READ, data, size, CORE_NONE);
635   if (ret != SANE_STATUS_GOOD)
636     return ret;
637 
638   return SANE_STATUS_GOOD;
639 }
640 
641 /******************************************************************************/
642 static SANE_Status
hp5590_write_eeprom(SANE_Int dn, enum proto_flags proto_flags, unsigned int addr, unsigned char *data, unsigned int size)643 hp5590_write_eeprom (SANE_Int dn,
644                      enum proto_flags proto_flags,
645                      unsigned int addr,
646                      unsigned char *data, unsigned int size)
647 {
648   uint8_t eeprom_addr = addr;
649   SANE_Status ret;
650 
651   hp5590_cmds_assert (data != NULL);
652   hp5590_cmds_assert (sizeof (eeprom_addr) == 1);
653 
654   DBG (DBG_proc, "%s\n", __func__);
655   DBG (DBG_proc, "Writing EEPROM: addr %04x, size: %u\n", addr, size);
656 
657   ret = hp5590_cmd (dn,
658                     proto_flags,
659                     CMD_VERIFY,
660                     CMD_EEPROM_ADDR,
661                     (unsigned char *) &eeprom_addr,
662                     sizeof (eeprom_addr), CORE_NONE);
663   if (ret != SANE_STATUS_GOOD)
664     return ret;
665 
666   ret = hp5590_cmd (dn,
667                     proto_flags,
668                     CMD_VERIFY,
669                     CMD_EEPROM_WRITE, data, size, CORE_DATA);
670   if (ret != SANE_STATUS_GOOD)
671     return ret;
672 
673   return SANE_STATUS_GOOD;
674 }
675 
676 /******************************************************************************/
677 static SANE_Status
hp5590_read_scan_count(SANE_Int dn, enum proto_flags proto_flags, unsigned int *count)678 hp5590_read_scan_count (SANE_Int dn,
679                         enum proto_flags proto_flags,
680                         unsigned int *count)
681 {
682   uint32_t scan_count;
683   SANE_Status ret;
684 
685   hp5590_cmds_assert (count != NULL);
686   hp5590_cmds_assert (sizeof (scan_count) == 4);
687 
688   DBG (DBG_proc, "%s\n", __func__);
689   DBG (DBG_proc, "Reading scan count\n");
690 
691   ret = hp5590_read_eeprom (dn,
692                             proto_flags,
693                             0x00,
694                             (unsigned char *) &scan_count,
695                             sizeof (scan_count));
696 
697   if (ret != SANE_STATUS_GOOD)
698     return ret;
699 
700   /* Host order */
701   *count = scan_count;
702 
703   DBG (DBG_proc, "Scan count %u\n", *count);
704 
705   return SANE_STATUS_GOOD;
706 }
707 
708 /******************************************************************************/
709 static SANE_Status
hp5590_inc_scan_count(SANE_Int dn, enum proto_flags proto_flags)710 hp5590_inc_scan_count (SANE_Int dn,
711                        enum proto_flags proto_flags)
712 {
713   uint32_t scan_count;
714   uint32_t count;
715   uint32_t new_count;
716   SANE_Status ret;
717 
718   DBG (DBG_proc, "%s\n", __func__);
719   hp5590_cmds_assert (sizeof (scan_count) == 4);
720 
721   ret = hp5590_read_scan_count (dn, proto_flags, &count);
722   if (ret != SANE_STATUS_GOOD)
723     return ret;
724 
725   scan_count = ++count;
726   DBG (DBG_verbose, "Scan count = %u\n", scan_count);
727 
728   ret = hp5590_write_eeprom (dn,
729                              proto_flags,
730                              0x00,
731                              (unsigned char *) &scan_count,
732                              sizeof (scan_count));
733   if (ret != SANE_STATUS_GOOD)
734     return ret;
735 
736   /* Verify its setting */
737   ret = hp5590_read_scan_count (dn, proto_flags, &new_count);
738   if (ret != SANE_STATUS_GOOD)
739     return ret;
740 
741   if (count != new_count)
742     {
743       DBG (DBG_err, "Scan count wasn't set\n");
744       return SANE_STATUS_IO_ERROR;
745     }
746 
747   return SANE_STATUS_GOOD;
748 }
749 
750 /******************************************************************************/
751 static SANE_Status
hp5590_read_max_scan_count(SANE_Int dn, enum proto_flags proto_flags, unsigned int *max_count)752 hp5590_read_max_scan_count (SANE_Int dn,
753                             enum proto_flags proto_flags,
754                             unsigned int *max_count)
755 {
756   uint8_t max_scan_count[3];
757   SANE_Status ret;
758 
759   hp5590_cmds_assert (max_count != NULL);
760   hp5590_cmds_assert (sizeof (max_scan_count) == 3);
761 
762   DBG (DBG_proc, "%s\n", __func__);
763   DBG (DBG_proc, "Reading max scan count\n");
764 
765   ret = hp5590_read_eeprom (dn,
766                             proto_flags,
767                             0x10,
768                             (unsigned char *) max_scan_count,
769                             sizeof (max_scan_count));
770   if (ret != SANE_STATUS_GOOD)
771     return ret;
772 
773   /* Host order */
774   *max_count = 0;
775   memcpy (max_count, max_scan_count, sizeof (max_scan_count));
776 
777   DBG (DBG_proc, "Max scan count %u\n", *max_count);
778 
779   return SANE_STATUS_GOOD;
780 }
781 
782 /***************************************************************************
783  *
784  * EEPROM contents:
785  *
786  * 0000: 6A 11 00 00 FF FF FF FF FF FF FF FF 09 0E 0F 00  j...............
787  * 0010: 0C 13 0F 00 00 3A 00 FF FF FF 4E 35 39 45 54 52  ..........N59ETR
788  * 0020: 31 52 4D 00 FF FF 00 16 00 0A 00 0D 00 11 00 10  1RM.............
789  * 0030: FF FF FF FF FF FF FF FF FF 00 FF FF FF FF FF FF  ................
790  * 0040: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ................
791  * 0050: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ................
792  * 0060: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ................
793  * 0070: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ................
794  * 0080: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ................
795  * 0090: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ................
796  * 00A0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ................
797  * 00B0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ................
798  * 00C0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ................
799  * 00D0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ................
800  * 00E0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ................
801  * 00F0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF     ...............
802  *
803  * Addr 0x00, len: 0x04 - scan count (little-endian)
804  * Addr 0x1A, len: 0x0A - part number (w/o first 'CN' letters)
805  * Addr 0x10, len: 0x03 - max scan count (little-endian) (0C 13 0F)
806  *
807  */
808 
809 /******************************************************************************/
810 static __sane_unused__ SANE_Status
hp5590_read_eeprom_all_cmd(SANE_Int dn, enum proto_flags proto_flags)811 hp5590_read_eeprom_all_cmd (SANE_Int dn,
812                             enum proto_flags proto_flags)
813 {
814   uint8_t eeprom[255];
815   SANE_Status ret;
816 
817   DBG (DBG_proc, "%s\n", __func__);
818 
819   ret = hp5590_read_eeprom (dn,
820                             proto_flags,
821                             0x00,
822                             (unsigned char *) eeprom,
823                             sizeof (eeprom));
824   if (ret != SANE_STATUS_GOOD)
825     return ret;
826 
827   DBG (DBG_verbose, "hp5590_read_eeprom_all_cmd: rc = %d\n", ret);
828   {
829     const int LEN = 4096;
830     char buf[LEN];
831     char* p = buf;
832     for (size_t i = 0; i < sizeof(eeprom); ++i) {
833       if (i % 16 == 0) {
834         int n = sprintf(p, "\n%04x ", (int)i);
835         if (n < 0) {
836           break;
837         }
838         p += n;
839       }
840       int n = sprintf(p, " %02x", eeprom[i]);
841       if (n < 0 ) {
842         break;
843       }
844       p += n;
845     }
846     *p = '\0';
847     DBG (DBG_verbose, "dump:%s\n", buf);
848   }
849 
850   return SANE_STATUS_GOOD;
851 }
852 
853 /******************************************************************************/
854 static SANE_Status
hp5590_read_part_number(SANE_Int dn, enum proto_flags proto_flags)855 hp5590_read_part_number (SANE_Int dn,
856                          enum proto_flags proto_flags)
857 {
858   unsigned int part_number_len = PART_NUMBER_LEN;
859   unsigned char part_number[PART_NUMBER_LEN + 1];
860   SANE_Status ret;
861 
862   DBG (DBG_proc, "%s\n", __func__);
863 
864   memset (part_number, 0, sizeof (part_number));
865   ret = hp5590_read_eeprom (dn,
866                             proto_flags,
867                             0x1a,
868                             part_number, part_number_len);
869   if (ret != SANE_STATUS_GOOD)
870     return ret;
871 
872   DBG (DBG_cmds, "Part number: '%s'\n", part_number);
873 
874   return SANE_STATUS_GOOD;
875 }
876 
877 /******************************************************************************/
878 static SANE_Status
hp5590_is_data_available(SANE_Int dn, enum proto_flags proto_flags)879 hp5590_is_data_available (SANE_Int dn,
880                           enum proto_flags proto_flags)
881 {
882   uint8_t data_status;
883   SANE_Status ret;
884   SANE_Bool data_available;
885 
886   DBG (DBG_proc, "%s\n", __func__);
887 
888   hp5590_cmds_assert (sizeof (data_status) == 1);
889   data_available = SANE_FALSE;
890 
891   ret = hp5590_cmd (dn,
892                     proto_flags,
893                     CMD_IN | CMD_VERIFY,
894                     CMD_DATA_STATUS,
895                     (unsigned char *) &data_status,
896                     sizeof (data_status), CORE_DATA);
897   if (ret != SANE_STATUS_GOOD)
898     return ret;
899 
900   DBG (DBG_cmds, "%s: Data status: %02x\n", __func__, data_status);
901 
902   if (data_status == 0x40)
903     data_available = SANE_TRUE;
904 
905   DBG (DBG_cmds, "%s: Data is %s\n",
906        __func__,
907        data_available == SANE_TRUE ? "available" : "not available");
908 
909   return data_available == SANE_TRUE ? SANE_STATUS_GOOD : SANE_STATUS_NO_DOCS;
910 }
911 
912 /******************************************************************************/
913 static SANE_Status
hp5590_stop_scan(SANE_Int dn, enum proto_flags proto_flags)914 hp5590_stop_scan (SANE_Int dn,
915                   enum proto_flags proto_flags)
916 {
917   uint8_t reg_011b = 0x40;
918   SANE_Status ret;
919 
920   DBG (DBG_proc, "%s\n", __func__);
921 
922   hp5590_cmds_assert (sizeof (reg_011b) == 1);
923 
924   ret = hp5590_cmd (dn,
925                     proto_flags,
926                     CMD_VERIFY,
927                     CMD_STOP_SCAN,
928                     (unsigned char *) &reg_011b,
929                     sizeof (reg_011b), CORE_NONE);
930   if (ret != SANE_STATUS_GOOD)
931     return ret;
932 
933   /* FIXME */
934 
935   return SANE_STATUS_GOOD;
936 }
937 
938 /******************************************************************************/
939 static SANE_Status
hp5590_turnon_lamp(SANE_Int dn, enum proto_flags proto_flags, enum hp5590_lamp_state state)940 hp5590_turnon_lamp (SANE_Int dn,
941                     enum proto_flags proto_flags,
942                     enum hp5590_lamp_state state)
943 {
944   struct lamp_state lamp_state;
945   SANE_Status ret;
946 
947   DBG (DBG_proc, "%s\n", __func__);
948 
949   hp5590_cmds_assert (sizeof (lamp_state) == 4);
950 
951   if (state == LAMP_STATE_TURNON)
952     {
953       /* Turn on lamp */
954       lamp_state.unk1 = 0x02;
955       lamp_state.flag = 0x01;
956       lamp_state.turnoff_time = htons (0x0a0a);
957       DBG (DBG_cmds, "%s: turning lamp on\n", __func__);
958     }
959 
960   if (state == LAMP_STATE_TURNOFF)
961     {
962       /* Turn off lamp */
963       lamp_state.unk1 = 0x02;
964       lamp_state.flag = 0x02;
965       lamp_state.turnoff_time = htons (0x0a0a);
966       DBG (DBG_cmds, "%s: turning lamp off\n", __func__);
967     }
968 
969   if (state == LAMP_STATE_SET_TURNOFF_TIME)
970     {
971       /* Turn on lamp */
972       lamp_state.unk1 = 0x02;
973       lamp_state.flag = 0x03;
974       lamp_state.turnoff_time = htons (0x0336);
975       DBG (DBG_cmds, "%s: setting turnoff time\n", __func__);
976     }
977 
978   if (state == LAMP_STATE_SET_TURNOFF_TIME_LONG)
979     {
980       /* Turn on lamp */
981       lamp_state.unk1 = 0x02;
982       lamp_state.flag = 0x03;
983       lamp_state.turnoff_time = htons (0x0f36);
984       DBG (DBG_cmds, "%s: setting long turnoff time\n", __func__);
985     }
986 
987   ret = hp5590_cmd (dn,
988                     proto_flags,
989                     CMD_VERIFY,
990                     CMD_CONTROL_LAMP,
991                     (unsigned char *) &lamp_state,
992                     sizeof (lamp_state), CORE_DATA);
993   if (ret != SANE_STATUS_GOOD)
994     return ret;
995 
996   if (state == LAMP_STATE_TURNON)
997     {
998       ret = hp5590_init_scanner (dn, proto_flags, NULL, SCANNER_NONE);
999       if (ret != SANE_STATUS_GOOD)
1000         return ret;
1001     }
1002 
1003   return SANE_STATUS_GOOD;
1004 }
1005 
1006 /******************************************************************************/
1007 static SANE_Status
hp5590_power_status(SANE_Int dn, enum proto_flags proto_flags)1008 hp5590_power_status (SANE_Int dn,
1009                      enum proto_flags proto_flags)
1010 {
1011   struct power_resp power_resp;
1012   SANE_Status ret;
1013 
1014   DBG (DBG_proc, "%s\n", __func__);
1015 
1016   hp5590_cmds_assert (sizeof (power_resp) == 3);
1017 
1018   ret = hp5590_cmd (dn,
1019                     proto_flags,
1020                     CMD_IN | CMD_VERIFY,
1021                     CMD_POWER_STATUS,
1022                     (unsigned char *) &power_resp,
1023                     sizeof (power_resp), CORE_NONE);
1024   if (ret != SANE_STATUS_GOOD)
1025     return ret;
1026 
1027   DBG (DBG_cmds, "Power status: %s (%02x)\n",
1028        power_resp.flags & POWER_FLAG_ON ? "on" : "off", power_resp.flags);
1029 
1030   if (!(power_resp.flags & POWER_FLAG_ON))
1031     {
1032       DBG (DBG_cmds, "Turning lamp on\n");
1033       ret = hp5590_turnon_lamp (dn, proto_flags, LAMP_STATE_TURNON);
1034       if (ret != SANE_STATUS_GOOD)
1035         return ret;
1036     }
1037 
1038   return SANE_STATUS_GOOD;
1039 }
1040 
1041 /******************************************************************************/
1042 static SANE_Status
hp5590_read_error_code(SANE_Int dn, enum proto_flags proto_flags, unsigned int *adf_flags)1043 hp5590_read_error_code (SANE_Int dn,
1044                         enum proto_flags proto_flags,
1045                         unsigned int *adf_flags)
1046 {
1047   struct reg_03 reg_03;
1048   SANE_Status   ret;
1049 
1050   DBG (DBG_proc, "%s\n", __func__);
1051 
1052   hp5590_cmds_assert (sizeof (reg_03) == 3);
1053   hp5590_cmds_assert (adf_flags != NULL);
1054 
1055   memset (&reg_03, 0, sizeof (reg_03));
1056   *adf_flags = 0;
1057   ret = hp5590_cmd (dn,
1058                     proto_flags,
1059                     CMD_IN,
1060                     CMD_MISC_STATUS,
1061                     (unsigned char *) &reg_03,
1062                     sizeof (reg_03), CORE_NONE);
1063 
1064   if (ret != SANE_STATUS_GOOD)
1065     return ret;
1066 
1067   DBG (DBG_cmds, "%s: adf_flags: %04x\n", __func__, reg_03.adf_flags);
1068   DBG (DBG_cmds, "%s: unk1     : %04x\n", __func__, reg_03.unk1);
1069   DBG (DBG_cmds, "%s: unk2     : %04x\n", __func__, reg_03.unk2);
1070 
1071   *adf_flags = reg_03.adf_flags;
1072 
1073   return SANE_STATUS_GOOD;
1074 }
1075 
1076 /******************************************************************************/
1077 static SANE_Status
hp5590_reset_scan_head(SANE_Int dn, enum proto_flags proto_flags)1078 hp5590_reset_scan_head (SANE_Int dn,
1079                         enum proto_flags proto_flags)
1080 {
1081   SANE_Status   ret;
1082 
1083   DBG (DBG_proc, "%s\n", __func__);
1084 
1085   ret = hp5590_turnon_lamp (dn, proto_flags, LAMP_STATE_TURNOFF);
1086   if (ret != SANE_STATUS_GOOD)
1087     return ret;
1088 
1089   usleep (100 * 1000);
1090 
1091   ret = hp5590_turnon_lamp (dn, proto_flags, LAMP_STATE_TURNON);
1092   if (ret != SANE_STATUS_GOOD)
1093     return ret;
1094 
1095   return SANE_STATUS_GOOD;
1096 }
1097 
1098 /******************************************************************************/
1099 static SANE_Status
hp5590_select_source_and_wakeup(SANE_Int dn, enum proto_flags proto_flags, enum scan_sources source, SANE_Bool extend_lamp_timeout)1100 hp5590_select_source_and_wakeup (SANE_Int dn,
1101                                  enum proto_flags proto_flags,
1102                                  enum scan_sources source,
1103                                  SANE_Bool extend_lamp_timeout)
1104 {
1105   uint8_t       reg_d6 = 0x04;
1106   SANE_Status   ret;
1107   unsigned int  adf_flags;
1108 
1109   DBG (DBG_proc, "%s\n", __func__);
1110 
1111   hp5590_cmds_assert (sizeof (reg_d6) == 1);
1112 
1113   if (source == SOURCE_TMA_SLIDES || source == SOURCE_TMA_NEGATIVES)
1114     {
1115       ret = hp5590_turnon_lamp (dn, proto_flags, LAMP_STATE_TURNOFF);
1116       if (ret != SANE_STATUS_GOOD)
1117         return ret;
1118     }
1119   else
1120     {
1121       ret = hp5590_turnon_lamp (dn,
1122                                 proto_flags,
1123                                 extend_lamp_timeout == SANE_TRUE ?
1124                                 LAMP_STATE_SET_TURNOFF_TIME_LONG :
1125                                 LAMP_STATE_SET_TURNOFF_TIME);
1126       if (ret != SANE_STATUS_GOOD)
1127         return ret;
1128     }
1129 
1130   switch (source)
1131     {
1132       case SOURCE_ADF:
1133       case SOURCE_ADF_DUPLEX:
1134         reg_d6 = 0x03;
1135         break;
1136       case SOURCE_FLATBED:
1137         reg_d6 = 0x04;
1138         break;
1139       case SOURCE_TMA_SLIDES:
1140         reg_d6 = 0x02;
1141         break;
1142       case SOURCE_TMA_NEGATIVES:
1143         reg_d6 = 0x01;
1144         break;
1145       case SOURCE_NONE:
1146         DBG (DBG_err, "Scan source not selected\n");
1147         return SANE_STATUS_INVAL;
1148       default:
1149         DBG (DBG_err, "Unknown scan source: %u\n", source);
1150         return SANE_STATUS_INVAL;
1151     }
1152 
1153   DBG (DBG_cmds, "Scan source: %u\n", reg_d6);
1154 
1155   ret = hp5590_cmd (dn,
1156                     proto_flags,
1157                     CMD_VERIFY,
1158                     CMD_SELECT_SOURCE,
1159                     (unsigned char *) &reg_d6,
1160                     sizeof (reg_d6), CORE_NONE);
1161 
1162   if (ret != SANE_STATUS_GOOD && ret != SANE_STATUS_DEVICE_BUSY)
1163     return ret;
1164 
1165   ret = hp5590_read_error_code (dn, proto_flags, &adf_flags);
1166   if (ret != SANE_STATUS_GOOD)
1167     return ret;
1168 
1169   if (adf_flags & FLAG_ADF_EMPTY)
1170     {
1171       DBG (DBG_cmds, "ADF empty\n");
1172       return SANE_STATUS_NO_DOCS;
1173     }
1174 
1175   return SANE_STATUS_GOOD;
1176 }
1177 
1178 /******************************************************************************/
1179 static SANE_Status
hp5590_lock_unlock_scanner(SANE_Int dn, enum proto_flags proto_flags)1180 hp5590_lock_unlock_scanner (SANE_Int dn,
1181                             enum proto_flags proto_flags)
1182 {
1183   uint8_t       reg_00 = 0x01;
1184   SANE_Status   ret;
1185   unsigned int  adf_flags;
1186   unsigned int  waiting;
1187 
1188   DBG (DBG_proc, "%s\n", __func__);
1189   hp5590_cmds_assert (sizeof (reg_00) == 1);
1190 
1191   for (waiting = 0; waiting < WAKEUP_TIMEOUT; waiting++, sleep (1))
1192     {
1193       ret = hp5590_cmd (dn,
1194                         proto_flags,
1195                         CMD_VERIFY,
1196                         CMD_LOCK_UNLOCK,
1197                         (unsigned char *) &reg_00,
1198                         sizeof (reg_00), CORE_NONE);
1199       if (ret == SANE_STATUS_GOOD)
1200         break;
1201 
1202       if (ret != SANE_STATUS_DEVICE_BUSY)
1203         return ret;
1204 
1205       DBG (DBG_cmds, "Waiting for scanner...\n");
1206       ret = hp5590_read_error_code (dn, proto_flags, &adf_flags);
1207       if (ret != SANE_STATUS_GOOD)
1208         return ret;
1209 
1210       if (adf_flags & FLAG_ADF_EMPTY)
1211         {
1212           DBG (DBG_cmds, "ADF empty\n");
1213           return SANE_STATUS_NO_DOCS;
1214         }
1215     }
1216 
1217   if (waiting == WAKEUP_TIMEOUT)
1218     return SANE_STATUS_DEVICE_BUSY;
1219 
1220   return SANE_STATUS_GOOD;
1221 }
1222 
1223 /******************************************************************************/
1224 static SANE_Status
hp5590_set_base_dpi(SANE_Int dn, enum proto_flags proto_flags, struct scanner_info *scanner_info, unsigned int base_dpi)1225 hp5590_set_base_dpi (SANE_Int dn,
1226                      enum proto_flags proto_flags,
1227                      struct scanner_info *scanner_info,
1228                      unsigned int base_dpi)
1229 {
1230   uint16_t _base_dpi;
1231   SANE_Status ret;
1232 
1233   DBG (DBG_proc, "%s\n", __func__);
1234 
1235   hp5590_cmds_assert (scanner_info != NULL);
1236   hp5590_cmds_assert (base_dpi != 0);
1237   hp5590_cmds_assert (sizeof (_base_dpi) == 2);
1238 
1239   if (base_dpi > scanner_info->max_dpi_x
1240       || base_dpi > scanner_info->max_dpi_y)
1241     {
1242       DBG (DBG_err, "Base DPI too large "
1243            "(given: %u, max X DPI: %u, max Y DPI: %u)\n",
1244            base_dpi,
1245            scanner_info->max_dpi_x,
1246            scanner_info->max_dpi_y);
1247       return SANE_STATUS_INVAL;
1248     }
1249 
1250   _base_dpi = htons (base_dpi);
1251 
1252   ret = hp5590_cmd (dn,
1253                     proto_flags,
1254                     CMD_VERIFY,
1255                     CMD_SET_BASE_DPI,
1256                     (unsigned char *) &_base_dpi,
1257                     sizeof (_base_dpi), CORE_DATA);
1258   if (ret != SANE_STATUS_GOOD)
1259     return ret;
1260 
1261   return SANE_STATUS_GOOD;
1262 }
1263 
1264 /******************************************************************************/
1265 static SANE_Status
hp5590_set_color_map(SANE_Int dn, enum proto_flags proto_flags, unsigned int base_dpi)1266 hp5590_set_color_map (SANE_Int dn,
1267                       enum proto_flags proto_flags,
1268                       unsigned int base_dpi)
1269 {
1270   struct color_map color_map;
1271   SANE_Status ret;
1272 
1273   DBG (DBG_proc, "%s\n", __func__);
1274 
1275   hp5590_cmds_assert (sizeof (color_map) == 18);
1276   hp5590_cmds_assert (base_dpi != 0);
1277 
1278   memset (&color_map, 0, sizeof (color_map));
1279   if (base_dpi < 2400)
1280     {
1281       color_map.color1[4] = 0x01;
1282       color_map.color2[4] = 0x01;
1283       color_map.color3[4] = 0x01;
1284     }
1285   else
1286     {
1287       if (0) {
1288         /* Does not work with hp5590 and 2400 dpi. */
1289         color_map.color1[2] = 0xff;
1290         color_map.color1[3] = 0x01;
1291         color_map.color1[4] = 0x04;
1292         color_map.color1[5] = 0x02;
1293 
1294         color_map.color2[2] = 0xff;
1295         color_map.color2[3] = 0x01;
1296         color_map.color2[4] = 0x04;
1297         color_map.color2[5] = 0x02;
1298 
1299         color_map.color3[2] = 0xff;
1300         color_map.color3[3] = 0x01;
1301         color_map.color3[4] = 0x04;
1302         color_map.color3[5] = 0x02;
1303 
1304       } else {
1305         /* Needs documentation. */
1306         color_map.color1[2] = 0x00;
1307         color_map.color1[3] = 0x00;
1308         color_map.color1[4] = 0x01;
1309         color_map.color1[5] = 0x00;
1310 
1311         color_map.color2[2] = 0x00;
1312         color_map.color2[3] = 0x00;
1313         color_map.color2[4] = 0x01;
1314         color_map.color2[5] = 0x00;
1315 
1316         color_map.color3[2] = 0x00;
1317         color_map.color3[3] = 0x00;
1318         color_map.color3[4] = 0x01;
1319         color_map.color3[5] = 0x00;
1320       }
1321     }
1322 
1323   ret = hp5590_cmd (dn,
1324                     proto_flags,
1325                     CMD_VERIFY,
1326                     CMD_SET_COLOR_MAP,
1327                     (unsigned char *) &color_map,
1328                     sizeof (color_map), CORE_DATA);
1329   if (ret != SANE_STATUS_GOOD)
1330     return ret;
1331 
1332   return SANE_STATUS_GOOD;
1333 }
1334 
1335 /******************************************************************************
1336  * Calculate base DPI
1337  * Base DPI is what image dimensions are calculated on (top X,Y; bottom X,Y)
1338  * Calculated according the following rules:
1339  * Base DPI is 150 when   0 <  DPI < 150;
1340  * Base DPI is 300 when 150 <= DPI <= 300;
1341  * Base DPI is 600 when 300 < DPI <= 600;
1342  * Base DPI is 1200 when 600 < DPI;
1343  */
1344 static SANE_Status
calc_base_dpi(unsigned int dpi, unsigned int *base_dpi)1345 calc_base_dpi (unsigned int dpi, unsigned int *base_dpi)
1346 {
1347 
1348   DBG (DBG_proc, "%s\n", __func__);
1349 
1350   hp5590_cmds_assert (base_dpi != NULL);
1351   hp5590_cmds_assert (dpi != 0);
1352 
1353   *base_dpi = 0;
1354 
1355   if (dpi < 150)
1356     {
1357       *base_dpi = 150;
1358       return SANE_STATUS_GOOD;
1359     }
1360 
1361   if (dpi >= 150 && dpi <= 300)
1362     {
1363       *base_dpi = 300;
1364       return SANE_STATUS_GOOD;
1365     }
1366 
1367   if (dpi > 300 && dpi <= 600)
1368     {
1369       *base_dpi = 600;
1370       return SANE_STATUS_GOOD;
1371     }
1372 
1373   if (dpi > 600 && dpi <= 1200)
1374     {
1375       *base_dpi = 1200;
1376       return SANE_STATUS_GOOD;
1377     }
1378 
1379   if (dpi > 1200 && dpi <= 2400)
1380     {
1381       *base_dpi = 2400;
1382       return SANE_STATUS_GOOD;
1383     }
1384 
1385   DBG (DBG_err, "Error calculating base DPI (given DPI: %u)\n", dpi);
1386   return SANE_STATUS_INVAL;
1387 }
1388 
1389 /******************************************************************************/
1390 static SANE_Status
calc_scanner_dpi(unsigned int dpi, unsigned int *scanner_dpi)1391 calc_scanner_dpi (unsigned int dpi, unsigned int *scanner_dpi)
1392 {
1393   DBG (DBG_proc, "%s\n", __func__);
1394 
1395   hp5590_cmds_assert (scanner_dpi != NULL);
1396   hp5590_cmds_assert (dpi != 0);
1397 
1398   if (dpi <= 100)
1399     {
1400       *scanner_dpi = 100;
1401       return SANE_STATUS_GOOD;
1402     }
1403 
1404   if (dpi > 100 && dpi <= 200)
1405     {
1406       *scanner_dpi = 200;
1407       return SANE_STATUS_GOOD;
1408     }
1409 
1410   if (dpi == 300)
1411     {
1412       *scanner_dpi = 300;
1413       return SANE_STATUS_GOOD;
1414     }
1415 
1416   if (dpi > 300 && dpi <= 600)
1417     {
1418       *scanner_dpi = 600;
1419       return SANE_STATUS_GOOD;
1420     }
1421 
1422   if (dpi > 600 && dpi <= 1200)
1423     {
1424       *scanner_dpi = 1200;
1425       return SANE_STATUS_GOOD;
1426     }
1427 
1428   if (dpi > 1200 && dpi <= 2400)
1429     {
1430       *scanner_dpi = 2400;
1431       return SANE_STATUS_GOOD;
1432     }
1433 
1434   DBG (DBG_err, "Error calculating scanner DPI (given DPI: %u)\n", dpi);
1435   return SANE_STATUS_INVAL;
1436 }
1437 
1438 /******************************************************************************/
1439 static SANE_Status
hp5590_calc_pixel_bits(unsigned int dpi, enum color_depths color_depth, unsigned int *pixel_bits)1440 hp5590_calc_pixel_bits (unsigned int dpi, enum color_depths color_depth,
1441                         unsigned int *pixel_bits)
1442 {
1443   unsigned int scanner_dpi;
1444   SANE_Status ret;
1445 
1446   DBG (DBG_proc, "%s\n", __func__);
1447 
1448   hp5590_cmds_assert (pixel_bits != NULL);
1449   hp5590_cmds_assert (dpi != 0);
1450 
1451   ret = calc_scanner_dpi (dpi, &scanner_dpi);
1452   if (ret != SANE_STATUS_GOOD)
1453     return ret;
1454 
1455   if (color_depth == DEPTH_COLOR_48)
1456     {
1457       *pixel_bits = 48;
1458       return SANE_STATUS_GOOD;
1459     }
1460 
1461   if (color_depth == DEPTH_COLOR_24)
1462     {
1463       *pixel_bits = 24;
1464       return SANE_STATUS_GOOD;
1465     }
1466 
1467   if (color_depth == DEPTH_GRAY)
1468     {
1469       *pixel_bits = 8;
1470       return SANE_STATUS_GOOD;
1471     }
1472 
1473   if (color_depth == DEPTH_BW)
1474     {
1475       if (dpi == scanner_dpi)
1476         *pixel_bits = 1;
1477       else
1478         *pixel_bits = 8;
1479       return SANE_STATUS_GOOD;
1480     }
1481 
1482   DBG (DBG_err, "Error calculating pixel bits (given DPI: %u)\n", dpi);
1483   return SANE_STATUS_INVAL;
1484 }
1485 
1486 /******************************************************************************/
1487 static SANE_Status
hp5590_set_scan_area(SANE_Int dn, enum proto_flags proto_flags, struct scanner_info *scanner_info, unsigned int top_x, unsigned int top_y, unsigned int width, unsigned int height, unsigned int dpi, enum color_depths color_depth, enum scan_modes scan_mode, enum scan_sources scan_source)1488 hp5590_set_scan_area (SANE_Int dn,
1489                       enum proto_flags proto_flags,
1490                       struct scanner_info *scanner_info,
1491                       unsigned int top_x, unsigned int top_y,
1492                       unsigned int width, unsigned int height,
1493                       unsigned int dpi, enum color_depths color_depth,
1494                       enum scan_modes scan_mode,
1495                       enum scan_sources scan_source)
1496 {
1497   struct scan_params    scan_params;
1498   unsigned int          scanner_top_x;
1499   unsigned int          scanner_top_y;
1500   unsigned int          scanner_pixels_x;
1501   unsigned int          scanner_pixels_y;
1502   unsigned int          base_dpi;
1503   unsigned int          scanner_dpi;
1504   unsigned int          pixel_bits;
1505   unsigned int          scanner_line_width;
1506   unsigned int          max_pixels_x_current_dpi;
1507   unsigned int          max_pixels_y_current_dpi;
1508   unsigned int          pixels_x;
1509   unsigned int          pixels_y;
1510   SANE_Status           ret;
1511 
1512   DBG (DBG_proc, "%s\n", __func__);
1513 
1514   hp5590_cmds_assert (sizeof (scan_params) == 37);
1515   hp5590_cmds_assert (dpi != 0);
1516   hp5590_cmds_assert (scanner_info != NULL);
1517 
1518   memset (&scan_params, 0, sizeof (scan_params));
1519 
1520   scan_params.source = SCAN_PARAMS_SOURCE_SIMPLEX;
1521   if (scan_source == SOURCE_ADF)
1522     scan_params.source |= SCAN_PARAMS_SOURCE_ADF;
1523   if (scan_source == SOURCE_ADF_DUPLEX)
1524     scan_params.source |= SCAN_PARAMS_SOURCE_ADF | SCAN_PARAMS_SOURCE_DUPLEX;
1525   if (scan_source == SOURCE_FLATBED)
1526     scan_params.source |= SCAN_PARAMS_SOURCE_FLATBED;
1527   if (scan_source == SOURCE_TMA_SLIDES)
1528     scan_params.source |= SCAN_PARAMS_SOURCE_TMA_SLIDES;
1529   if (scan_source == SOURCE_TMA_NEGATIVES)
1530     scan_params.source |= SCAN_PARAMS_SOURCE_TMA_NEGATIVES;
1531 
1532   DBG (DBG_cmds, "Scan params. source : 0x%04x\n", scan_params.source);
1533 
1534   DBG (DBG_cmds, "DPI: %u\n", dpi);
1535   if (dpi > scanner_info->max_dpi_x || dpi > scanner_info->max_dpi_y)
1536     {
1537       DBG (DBG_err, "DPI too large "
1538            "(given: %u, max X DPI: %u, max Y DPI: %u)\n",
1539            dpi, scanner_info->max_dpi_x, scanner_info->max_dpi_y);
1540       return SANE_STATUS_INVAL;
1541     }
1542 
1543   ret = calc_base_dpi (dpi, &base_dpi);
1544   if (ret != SANE_STATUS_GOOD)
1545     return ret;
1546   DBG (DBG_cmds, "Base DPI: %u\n", base_dpi);
1547 
1548   ret = calc_scanner_dpi (dpi, &scanner_dpi);
1549   if (ret != SANE_STATUS_GOOD)
1550     return ret;
1551   DBG (DBG_cmds, "Scanner DPI: %u\n", scanner_dpi);
1552 
1553   scan_params.dpi_x = htons (scanner_dpi);
1554   scan_params.dpi_y = htons (scanner_dpi);
1555 
1556   DBG (DBG_cmds, "DPI X: 0x%04x\n", scanner_dpi);
1557   DBG (DBG_cmds, "DPI Y: 0x%04x\n", scanner_dpi);
1558 
1559   ret = hp5590_calc_pixel_bits (dpi, color_depth, &pixel_bits);
1560   if (ret != SANE_STATUS_GOOD)
1561     return ret;
1562 
1563   DBG (DBG_cmds, "Pixel bits: %u\n", pixel_bits);
1564 
1565   scan_params.pixel_bits = pixel_bits;
1566 
1567   scan_params.bw_gray_flag = 0;
1568   if (color_depth == DEPTH_BW || color_depth == DEPTH_GRAY)
1569     scan_params.bw_gray_flag = htons (0x40);
1570 
1571   scan_params.flags = htons (0xe840);
1572   if (dpi > 300 && dpi <= 1200)
1573     scan_params.flags = htons (0xc840);
1574   if (dpi > 1200)
1575     scan_params.flags = htons (0xc040);
1576 
1577   scan_params.motor_param1 = htons (100);
1578   scan_params.motor_param2 = htons (100);
1579   scan_params.motor_param3 = htons (100);
1580   if (scan_source == SOURCE_TMA_NEGATIVES)
1581     {
1582       scan_params.motor_param2 = htons (200);
1583       scan_params.motor_param3 = htons (400);
1584     }
1585 
1586   scan_params.unk1 = htons (0x80);
1587 
1588   scan_params.mode = 0;
1589   if (scan_mode == MODE_PREVIEW)
1590     scan_params.mode = 0x04;
1591 
1592   max_pixels_x_current_dpi = (float) scanner_info->max_size_x * dpi;
1593   max_pixels_y_current_dpi = (float) scanner_info->max_size_y * dpi;
1594   if (   scan_source == SOURCE_TMA_NEGATIVES
1595       || scan_source == SOURCE_TMA_SLIDES)
1596     {
1597       max_pixels_x_current_dpi = (float) (TMA_MAX_X_INCHES * dpi);
1598       max_pixels_y_current_dpi = (float) (TMA_MAX_Y_INCHES * dpi);
1599     }
1600   /* In ADF mode the device can scan up to ADF_MAX_Y_INCHES, which is usually
1601    * bigger than what scanner reports back during initialization
1602    */
1603   if ( scan_source == SOURCE_ADF )
1604     max_pixels_y_current_dpi = (float) (ADF_MAX_Y_INCHES * dpi);
1605 
1606   /* Allow two times of max pixels for ADF Duplex mode */
1607   if (scan_source == SOURCE_ADF_DUPLEX)
1608     max_pixels_y_current_dpi *= 2;
1609 
1610   pixels_x = width;
1611   pixels_y = height;
1612 
1613   scanner_top_x = (float) (top_x * (1.0 * base_dpi / dpi));
1614   scanner_top_y = (float) (top_y * (1.0 * base_dpi / dpi));
1615   scanner_pixels_x = (float) (pixels_x * (1.0 * base_dpi / dpi));
1616   scanner_pixels_y = (float) (pixels_y * (1.0 * base_dpi / dpi));
1617 
1618   DBG (DBG_cmds, "Top X: %u, top Y: %u, size X: %u, size Y: %u\n",
1619        top_x, top_y, pixels_x, pixels_y);
1620   DBG (DBG_cmds, "Scanner top X: %u, top Y: %u, size X: %u, size Y: %u\n",
1621        scanner_top_x, scanner_top_y,
1622        scanner_pixels_x, scanner_pixels_y);
1623 
1624   if (top_x + pixels_x > max_pixels_x_current_dpi)
1625     {
1626       DBG (DBG_err, "Top X (%u) + pixels X (%u) exceeds max X %u\n",
1627            top_x, pixels_x, max_pixels_x_current_dpi);
1628       return SANE_STATUS_INVAL;
1629     }
1630 
1631   if (top_y + pixels_y > max_pixels_y_current_dpi)
1632     {
1633       DBG (DBG_err, "Top Y (%u) + pixels Y (%u) exceeds max Y %u\n",
1634            top_y, pixels_y, max_pixels_y_current_dpi);
1635       return SANE_STATUS_INVAL;
1636     }
1637 
1638   scan_params.top_x = htons (scanner_top_x);
1639   scan_params.top_y = htons (scanner_top_y);
1640   scan_params.size_x = htons (scanner_pixels_x);
1641   scan_params.size_y = htons (scanner_pixels_y);
1642 
1643   scanner_line_width = (float) (pixels_x
1644                                 * (1.0 * scanner_dpi / dpi) / 8 * pixel_bits);
1645 
1646   /* Scanner hangs at scan command if line width less than 18 */
1647   if (scanner_line_width < 18)
1648     {
1649       DBG (DBG_err, "Line width too small, extending to minimum\n");
1650       scanner_line_width = 18;
1651     }
1652   scan_params.line_width = htons (scanner_line_width);
1653   DBG (DBG_cmds, "Line width: %u\n", scanner_line_width);
1654 
1655   ret = hp5590_cmd (dn,
1656                     proto_flags,
1657                     CMD_VERIFY,
1658                     CMD_SET_SCAN_PARAMS,
1659                     (unsigned char *) &scan_params,
1660                     sizeof (scan_params), CORE_DATA);
1661   if (ret != SANE_STATUS_GOOD)
1662     return ret;
1663 
1664   return SANE_STATUS_GOOD;
1665 }
1666 
1667 /******************************************************************************/
1668 static SANE_Status
hp5590_read_image_params(SANE_Int dn, enum proto_flags proto_flags)1669 hp5590_read_image_params (SANE_Int dn,
1670                           enum proto_flags proto_flags)
1671 {
1672   struct image_params image_params;
1673   SANE_Status ret;
1674 
1675   DBG (DBG_proc, "%s\n", __func__);
1676 
1677   hp5590_cmds_assert (sizeof (image_params) == 16);
1678 
1679   memset (&image_params, 0, sizeof (image_params));
1680 
1681   ret = hp5590_cmd (dn,
1682                     proto_flags,
1683                     CMD_IN | CMD_VERIFY,
1684                     CMD_GET_IMAGE_PARAMS,
1685                     (unsigned char *) &image_params,
1686                     sizeof (image_params), CORE_NONE);
1687   if (ret != SANE_STATUS_GOOD)
1688     return ret;
1689 
1690   if (image_params.signature != 0xc0)
1691     {
1692       DBG (DBG_err, "Wrong signature for image parameters structure "
1693            "received (needed 0xc0, got %02x)\n", image_params.signature);
1694       return SANE_STATUS_IO_ERROR;
1695     }
1696   DBG (DBG_cmds, "Received image params:\n");
1697   DBG (DBG_cmds, "Signature %02x\n", image_params.signature);
1698   DBG (DBG_cmds, "Image size %lu (%04lx)\n",
1699        (unsigned long) ntohl (image_params.image_size),
1700        (unsigned long) ntohl (image_params.image_size));
1701   DBG (DBG_cmds, "Line width: %u (%02x)\n", ntohs (image_params.line_width),
1702        ntohs (image_params.line_width));
1703   DBG (DBG_cmds, "Actual size Y: %u (%02x)\n",
1704        ntohs (image_params.real_size_y), ntohs (image_params.real_size_y));
1705 
1706   return SANE_STATUS_GOOD;
1707 }
1708 
1709 /******************************************************************************/
1710 static SANE_Status
hp5590_set_scan_params(SANE_Int dn, enum proto_flags proto_flags, struct scanner_info * scanner_info, unsigned int top_x, unsigned int top_y, unsigned int width, unsigned int height, unsigned int dpi, enum color_depths color_depth, enum scan_modes scan_mode, enum scan_sources scan_source)1711 hp5590_set_scan_params (SANE_Int dn,
1712                         enum proto_flags proto_flags,
1713                         struct scanner_info * scanner_info,
1714                         unsigned int top_x, unsigned int top_y,
1715                         unsigned int width, unsigned int height,
1716                         unsigned int dpi, enum color_depths color_depth,
1717                         enum scan_modes scan_mode,
1718                         enum scan_sources scan_source)
1719 {
1720   unsigned int base_dpi;
1721   SANE_Status ret;
1722 
1723   DBG (DBG_proc, "%s\n", __func__);
1724 
1725   hp5590_cmds_assert (scanner_info != NULL);
1726   hp5590_cmds_assert (dpi != 0);
1727 
1728   /* Lock scanner */
1729   ret = hp5590_lock_unlock_scanner (dn, proto_flags);
1730   if (ret != SANE_STATUS_GOOD)
1731     return ret;
1732 
1733   /* Set base DPI */
1734   ret = calc_base_dpi (dpi, &base_dpi);
1735   if (ret != SANE_STATUS_GOOD)
1736     {
1737       /* Unlock scanner */
1738       hp5590_lock_unlock_scanner (dn, proto_flags);
1739       return ret;
1740     }
1741 
1742   DBG (DBG_cmds, "Set base DPI: %u\n", base_dpi);
1743   ret = hp5590_set_base_dpi (dn, proto_flags, scanner_info, base_dpi);
1744   if (ret != SANE_STATUS_GOOD)
1745     {
1746       /* Unlock scanner */
1747       hp5590_lock_unlock_scanner (dn, proto_flags);
1748       return ret;
1749     }
1750 
1751   /* Set color map */
1752   ret = hp5590_set_color_map (dn, proto_flags, base_dpi);
1753   if (ret != SANE_STATUS_GOOD)
1754     {
1755       /* Unlock scanner */
1756       hp5590_lock_unlock_scanner (dn, proto_flags);
1757       return ret;
1758     }
1759 
1760   ret = hp5590_set_scan_area (dn,
1761                               proto_flags,
1762                               scanner_info,
1763                               top_x, top_y,
1764                               width, height,
1765                               dpi, color_depth, scan_mode, scan_source);
1766   if (ret != SANE_STATUS_GOOD)
1767     {
1768       /* Unlock scanner */
1769       hp5590_lock_unlock_scanner (dn, proto_flags);
1770       return ret;
1771     }
1772 
1773   ret = hp5590_read_image_params (dn, proto_flags);
1774   if (ret != SANE_STATUS_GOOD)
1775     {
1776       /* Unlock scanner */
1777       hp5590_lock_unlock_scanner (dn, proto_flags);
1778       return ret;
1779     }
1780 
1781   /* Unlock scanner */
1782   ret = hp5590_lock_unlock_scanner (dn, proto_flags);
1783   if (ret != SANE_STATUS_GOOD)
1784     return ret;
1785 
1786   return SANE_STATUS_GOOD;
1787 }
1788 
1789 /******************************************************************************/
1790 static SANE_Status
hp5590_send_reverse_calibration_map(SANE_Int dn, enum proto_flags proto_flags)1791 hp5590_send_reverse_calibration_map (SANE_Int dn,
1792                                      enum proto_flags proto_flags)
1793 {
1794   unsigned int reverse_map_size = REVERSE_MAP_LEN;
1795   uint16_t reverse_map[REVERSE_MAP_LEN];
1796   unsigned int i;
1797   uint16_t val;
1798   unsigned int len;
1799   SANE_Status ret;
1800 
1801   DBG (DBG_proc, "%s\n", __func__);
1802   DBG (DBG_proc, "Preparing reverse calibration map\n");
1803   val = 0xffff;
1804   len = reverse_map_size / 4;
1805   for (i = 0; i < len; i++)
1806     {
1807       reverse_map[i] = htons (val);
1808       val -= 1;
1809     }
1810 
1811   for (i = len; i < len * 2; i++)
1812     {
1813       reverse_map[i] = htons (val);
1814       val -= 1;
1815     }
1816 
1817   for (i = len * 2; i < len * 3; i++)
1818     {
1819       reverse_map[i] = htons (val);
1820       val -= 1;
1821     }
1822 
1823   for (i = len * 3; i < len * 4; i++)
1824     {
1825       if (1) {
1826         reverse_map[i] = htons (0xffff);
1827       } else {
1828         reverse_map[i] = htons (val);
1829         val -= 1;
1830       }
1831     }
1832 
1833   DBG (DBG_proc, "Done preparing reverse calibration map. n=%u, bytes_per_entry=%zu\n", reverse_map_size, sizeof(uint16_t));
1834 
1835   ret = hp5590_bulk_write (dn,
1836                            proto_flags,
1837                            0x2b,
1838                            (unsigned char *) reverse_map,
1839                            reverse_map_size * sizeof (uint16_t));
1840   if (ret != SANE_STATUS_GOOD)
1841     return ret;
1842 
1843   return SANE_STATUS_GOOD;
1844 }
1845 
1846 /******************************************************************************/
1847 static SANE_Status
hp5590_send_forward_calibration_maps(SANE_Int dn, enum proto_flags proto_flags)1848 hp5590_send_forward_calibration_maps (SANE_Int dn,
1849                                       enum proto_flags proto_flags)
1850 {
1851   unsigned int forward_map_size = FORWARD_MAP_LEN;
1852   uint16_t forward_map[FORWARD_MAP_LEN];
1853   SANE_Status ret;
1854   unsigned int i;
1855   uint16_t val;
1856 
1857   DBG (DBG_proc, "%s\n", __func__);
1858   DBG (DBG_proc, "Preparing forward calibration map\n");
1859   val = 0x0000;
1860   for (i = 0; i < forward_map_size; i++)
1861     {
1862       forward_map[i] = htons (val);
1863       if (val < 0xffff)
1864         val += 1;
1865     }
1866   DBG (DBG_proc, "Done preparing forward calibration map. n=%u, bytes_per_entry=%zu\n", forward_map_size, sizeof(uint16_t));
1867 
1868   ret = hp5590_bulk_write (dn,
1869                            proto_flags,
1870                            0x012a,
1871                            (unsigned char *) forward_map,
1872                            forward_map_size * sizeof (uint16_t));
1873   if (ret != SANE_STATUS_GOOD)
1874     return ret;
1875 
1876   ret = hp5590_bulk_write (dn,
1877                            proto_flags,
1878                            0x022a,
1879                            (unsigned char *) forward_map,
1880                            forward_map_size * sizeof (uint16_t));
1881   if (ret != SANE_STATUS_GOOD)
1882     return ret;
1883 
1884   ret = hp5590_bulk_write (dn,
1885                            proto_flags,
1886                            0x032a,
1887                            (unsigned char *) forward_map,
1888                            forward_map_size * sizeof (uint16_t));
1889   if (ret != SANE_STATUS_GOOD)
1890     return ret;
1891 
1892   return SANE_STATUS_GOOD;
1893 }
1894 
1895 /******************************************************************************/
1896 static SANE_Status
hp5590_read(SANE_Int dn, enum proto_flags proto_flags, unsigned char *bytes, unsigned int size, void *state)1897 hp5590_read (SANE_Int dn,
1898              enum proto_flags proto_flags,
1899              unsigned char *bytes, unsigned int size,
1900              void *state)
1901 {
1902   SANE_Status ret;
1903 
1904   DBG (DBG_proc, "%s\n", __func__);
1905 
1906   hp5590_cmds_assert (bytes != NULL);
1907   hp5590_cmds_assert (state != NULL);
1908 
1909   ret = hp5590_bulk_read (dn, proto_flags, bytes, size, state);
1910   if (ret != SANE_STATUS_GOOD)
1911     return ret;
1912 
1913   return SANE_STATUS_GOOD;
1914 }
1915 
1916 /******************************************************************************/
1917 static SANE_Status
hp5590_start_scan(SANE_Int dn, enum proto_flags proto_flags)1918 hp5590_start_scan (SANE_Int dn,
1919                    enum proto_flags proto_flags)
1920 {
1921   uint8_t reg_051b = 0x40;
1922   SANE_Status ret;
1923 
1924   DBG (DBG_proc, "%s\n", __func__);
1925 
1926   hp5590_cmds_assert (sizeof (reg_051b) == 1);
1927 
1928   ret = hp5590_cmd (dn,
1929                     proto_flags,
1930                     CMD_VERIFY,
1931                     CMD_START_SCAN,
1932                     (unsigned char *) &reg_051b,
1933                     sizeof (reg_051b), CORE_NONE);
1934   if (ret != SANE_STATUS_GOOD)
1935     return ret;
1936 
1937   return SANE_STATUS_GOOD;
1938 }
1939 
1940 /******************************************************************************/
1941 static SANE_Status
hp5590_read_buttons(SANE_Int dn, enum proto_flags proto_flags, enum button_status * status)1942 hp5590_read_buttons (SANE_Int dn,
1943                      enum proto_flags proto_flags,
1944                      enum button_status * status)
1945 {
1946   uint16_t button_status;
1947   SANE_Status ret;
1948 
1949   DBG (DBG_proc, "%s\n", __func__);
1950 
1951   hp5590_cmds_assert (status != NULL);
1952   hp5590_cmds_assert (sizeof (button_status) == 2);
1953 
1954   ret = hp5590_cmd (dn,
1955                     proto_flags,
1956                     CMD_IN | CMD_VERIFY,
1957                     CMD_BUTTON_STATUS,
1958                     (unsigned char *) &button_status,
1959                     sizeof (button_status), CORE_NONE);
1960   if (ret != SANE_STATUS_GOOD)
1961     return ret;
1962 
1963   *status = BUTTON_NONE;
1964 
1965   /* Network order */
1966   button_status = ntohs (button_status);
1967   DBG (DBG_cmds, "Button status: %04x\n", button_status);
1968   DBG (DBG_cmds, "Power: %s, Scan: %s, Collect: %s, File: %s, Email: %s, Copy: %s, "
1969        "Up: %s, Down: %s, Mode: %s, Cancel: %s\n",
1970        button_status & BUTTON_FLAG_POWER ? " on" : "off",
1971        button_status & BUTTON_FLAG_SCAN ? " on" : "off",
1972        button_status & BUTTON_FLAG_COLLECT ? " on" : "off",
1973        button_status & BUTTON_FLAG_FILE ? " on" : "off",
1974        button_status & BUTTON_FLAG_EMAIL ? " on" : "off",
1975        button_status & BUTTON_FLAG_COPY ? " on" : "off",
1976        button_status & BUTTON_FLAG_UP ? " on" : "off",
1977        button_status & BUTTON_FLAG_DOWN ? " on" : "off",
1978        button_status & BUTTON_FLAG_MODE ? " on" : "off",
1979        button_status & BUTTON_FLAG_CANCEL ? " on" : "off");
1980 
1981   if (button_status & BUTTON_FLAG_POWER)
1982     *status = BUTTON_POWER;
1983 
1984   if (button_status & BUTTON_FLAG_SCAN)
1985     *status = BUTTON_SCAN;
1986 
1987   if (button_status & BUTTON_FLAG_COLLECT)
1988     *status = BUTTON_COLLECT;
1989 
1990   if (button_status & BUTTON_FLAG_FILE)
1991     *status = BUTTON_FILE;
1992 
1993   if (button_status & BUTTON_FLAG_EMAIL)
1994     *status = BUTTON_EMAIL;
1995 
1996   if (button_status & BUTTON_FLAG_COPY)
1997     *status = BUTTON_COPY;
1998 
1999   if (button_status & BUTTON_FLAG_UP)
2000     *status = BUTTON_UP;
2001 
2002   if (button_status & BUTTON_FLAG_DOWN)
2003     *status = BUTTON_DOWN;
2004 
2005   if (button_status & BUTTON_FLAG_MODE)
2006     *status = BUTTON_MODE;
2007 
2008   if (button_status & BUTTON_FLAG_CANCEL)
2009     *status = BUTTON_CANCEL;
2010 
2011   return SANE_STATUS_GOOD;
2012 }
2013 
2014 /******************************************************************************/
2015 static SANE_Status
hp5590_read_lcd_and_led(SANE_Int dn, enum proto_flags proto_flags, SANE_Int * lcd_counter, enum color_led_status * color_led)2016 hp5590_read_lcd_and_led (SANE_Int dn,
2017                      enum proto_flags proto_flags,
2018                      SANE_Int * lcd_counter,
2019                      enum color_led_status * color_led)
2020 {
2021   SANE_Status ret;
2022 
2023   DBG (DBG_proc, "%s\n", __func__);
2024 
2025   hp5590_cmds_assert (lcd_counter != NULL);
2026   hp5590_cmds_assert (color_led != NULL);
2027 
2028   /*
2029    * Read LCD status bytes and get current value of counter and
2030    * state of color/black_white LED.
2031    * data[0x29]: LCD counter value, data[0x2a]: 1=color / 2=black_white.
2032    */
2033   uint8_t data[0x30];
2034   ret = hp5590_cmd (dn,
2035                     proto_flags,
2036                     CMD_IN | CMD_VERIFY,
2037                     CMD_LCD_STATUS,
2038                     (unsigned char *) &data,
2039                     sizeof (data), CORE_NONE);
2040   if (ret != SANE_STATUS_GOOD)
2041     return ret;
2042 
2043   *lcd_counter = data[0x29];
2044   if (data[0x2a] == 2) {
2045     *color_led = LED_BLACKWHITE;
2046   } else {
2047     *color_led = LED_COLOR;
2048   }
2049   DBG (DBG_cmds, "LCD and LED values: lcd=%d, led=%s\n", *lcd_counter,
2050        *color_led == LED_BLACKWHITE ? "black_white" : "color");
2051 
2052   return SANE_STATUS_GOOD;
2053 }
2054 
2055 /* SET SCAN PARAMETERS
2056 ==================== 50 =======================
2057 BW 50 (425 x 585)
2058 18 00 64 00 64 00 00 00 00 04 f8 06 db 00 80 00
2059 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2060 00 00 00 03 50
2061 
2062 BW 50 reduced top left (261 x 469)
2063 18 00 64 00 64 00 00 00 00 03 0c 05 7f 00 80 00
2064 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2065 00 00 00 02 08
2066 
2067 BW 50 reduced top right (302 x 498)
2068 18 00 64 00 64 01 6e 00 00 03 8a 05 d6 00 80 00
2069 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2070 00 00 00 02 5c
2071 
2072 BW 50 X 0, small width (16 x 585)
2073 18 00 64 00 64 00 00 00 00 00 30 06 db 00 80 00
2074 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2075 00 00 00 00 20
2076 
2077 BW 50 X large, small width (24 x 585)
2078 18 00 64 00 64 04 b0 00 00 00 48 06 db 00 80 00
2079 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2080 00 00 00 00 30
2081 
2082 BW 50 Y 0, small height (425 x 21)
2083 18 00 64 00 64 00 00 00 00 04 f8 00 3f 00 80 00
2084 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2085 00 00 00 03 50
2086 
2087 BW 50 Y large, small height (425 x 21)
2088 18 00 64 00 64 00 00 06 99 04 f8 00 3f 00 80 00
2089 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2090 00 00 00 03 50
2091 
2092 GRAY 50
2093 18 00 64 00 64 00 00 00 00 04 f8 06 db 00 80 00
2094 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2095 00 00 00 03 50
2096 
2097 COLOR 50
2098 18 00 64 00 64 00 00 00 00 04 f8 06 db 00 80 00
2099 00 18 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2100 00 00 00 09 f0
2101 
2102 ==================== 75 =======================
2103 BW 75
2104 18 00 64 00 64 00 00 00 00 04 f8 06 da 00 80 00
2105 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2106 00 00 00 03 50
2107 
2108 GRAY 75
2109 18 00 64 00 64 00 00 00 00 04 f8 06 da 00 80 00
2110 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2111 00 00 00 03 50
2112 
2113 COLOR 75
2114 18 00 64 00 64 00 00 00 00 04 f8 06 da 00 80 00
2115 00 18 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2116 00 00 00 09 f0
2117 
2118 COLOR 75 48 bit
2119 18 00 64 00 64 00 00 00 00 04 f8 06 db 00 80 00
2120 00 30 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2121 04 00 00 13 e0
2122 
2123 =================== 100 =======================
2124 BW 100
2125 18 00 64 00 64 00 00 00 00 04 f8 06 db 00 80 00
2126 40 01 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2127 00 00 00 00 6a
2128 
2129 GRAY 100
2130 18 00 64 00 64 00 00 00 00 04 f8 06 db 00 80 00
2131 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2132 00 00 00 03 50
2133 
2134 COLOR 100
2135 18 00 64 00 64 00 00 00 00 04 f8 06 db 00 80 00
2136 00 18 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2137 00 00 00 09 f0
2138 
2139 COLOR 100 48bit, preview
2140 18 00 64 00 64 00 00 00 00 04 f8 06 db 00 80 00
2141 00 30 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2142 04 00 00 13 e0
2143 
2144 COLOR 100 48bit
2145 18 00 64 00 64 00 00 00 00 04 f2 06 db 00 80 00
2146 00 30 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2147 00 00 00 13 c8
2148 
2149 COLOR 100 48bit, TMA negatives
2150 11 00 64 00 64 00 00 00 00 00 fc 03 84 00 80 00
2151 00 30 e8 40 00 64 00 c8 01 90 00 00 00 00 00 00
2152 00 00 00 03 f0
2153 
2154 COLOR 100 48bit, TMA slides
2155 12 00 64 00 64 00 00 00 00 00 fc 03 84 00 80 00
2156 00 30 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2157 00 00 00 03 f0
2158 
2159 =================== 150 =======================
2160 BW 150
2161 18 00 c8 00 c8 00 00 00 00 09 f6 0d b6 00 80 00
2162 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2163 00 00 00 06 a4
2164 
2165 GRAY 150
2166 18 00 c8 00 c8 00 00 00 00 09 f6 0d b6 00 80 00
2167 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2168 00 00 00 06 a4
2169 
2170 COLOR 150
2171 18 00 c8 00 c8 00 00 00 00 09 f6 0d b6 00 80 00
2172 00 18 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2173 00 00 00 13 ec
2174 
2175 COLOR 150 48 bit
2176 18 00 c8 00 c8 00 00 00 00 09 ea 0d b6 00 80 00
2177 00 30 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2178 00 00 00 27 a8
2179 
2180 =================== 200 =======================
2181 BW 200
2182 18 00 c8 00 c8 00 00 00 00 09 f0 0d b6 00 80 00
2183 40 01 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2184 00 00 00 00 d4
2185 
2186 GRAY 200
2187 18 00 c8 00 c8 00 00 00 00 09 f6 0d b6 00 80 00
2188 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2189 00 00 00 06 a4
2190 
2191 COLOR 200
2192 18 00 c8 00 c8 00 00 00 00 09 f6 0d b6 00 80 00
2193 00 18 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2194 00 00 00 13 ec
2195 
2196 COLOR 200 48 bit
2197 18 00 c8 00 c8 00 00 00 00 09 f6 0d aa 00 80 00
2198 00 30 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2199 00 00 00 27 d8
2200 
2201 =================== 300 =======================
2202 BW 300
2203 18 01 2c 01 2c 00 00 00 00 09 f0 0d b6 00 80 00
2204 40 01 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2205 00 00 00 01 3e
2206 
2207 GRAY 300
2208 18 01 2c 01 2c 00 00 00 00 09 f4 0d b6 00 80 00
2209 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2210 00 00 00 09 f4
2211 
2212 COLOR 300
2213 18 01 2c 01 2c 00 00 00 00 09 f4 0d b6 00 80 00
2214 00 18 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2215 00 00 00 1d dc
2216 
2217 COLOR 300 48bit, TMA negatives
2218 11 01 2c 01 2c 00 00 00 06 01 fc 07 02 00 80 00
2219 00 30 e8 40 00 64 00 c8 01 90 00 00 00 00 00 00
2220 00 00 00 0b e8
2221 
2222 COLOR 300 48bit, TMA slides
2223 12 01 2c 01 2c 00 00 00 00 01 fc 07 08 00 80 00
2224 00 30 e8 40 00 64 00 64 00 64 00 00 00 00 00 00
2225 00 00 00 0b e8
2226 
2227 ==================== 400 ======================
2228 BW 400
2229 18 02 58 02 58 00 00 00 00 13 ec 1b 6c 00 80 00
2230 40 08 c8 40 00 64 00 64 00 64 00 00 00 00 00 00
2231 00 00 00 13 ec
2232 
2233 GRAY 400
2234 18 02 58 02 58 00 00 00 00 13 ec 1b 6c 00 80 00
2235 40 08 c8 40 00 64 00 64 00 64 00 00 00 00 00 00
2236 00 00 00 13 ec
2237 
2238 COLOR 400
2239 18 02 58 02 58 00 00 00 00 13 ec 1b 6c 00 80 00
2240 00 18 c8 40 00 64 00 64 00 64 00 00 00 00 00 00
2241 00 00 00 3b c4
2242 
2243 ==================== 600 ======================
2244 BW 600
2245 18 02 58 02 58 00 00 00 00 13 e8 1b 6c 00 80 00
2246 40 01 c8 40 00 64 00 64 00 64 00 00 00 00 00 00
2247 00 00 00 02 7d
2248 
2249 GRAY 600
2250 18 02 58 02 58 00 00 00 00 13 ec 1b 6c 00 80 00
2251 40 08 c8 40 00 64 00 64 00 64 00 00 00 00 00 00
2252 00 00 00 13 ec
2253 
2254 COLOR 600
2255 18 02 58 02 58 00 00 00 00 13 ec 1b 6c 00 80 00
2256 00 18 c8 40 00 64 00 64 00 64 00 00 00 00 00 00
2257 00 00 00 3b c4
2258 
2259 ==================== 1200 =====================
2260 BW 1200
2261 
2262 18 04 b0 04 b0 00 00 00 00 27 a8 36 d8 00 80 00
2263 40 01 c8 40 00 64 00 64 00 64 00 00 00 00 00 00
2264 00 00 00 04 f5
2265 */
2266 
2267 /* READ SCAN PARAMETERS
2268 ====================== 50 =====================
2269 BW 50
2270 c0 00 00 0f 23 a0 00 00 03 50 04 92 00 00 00 00
2271 
2272 GRAY 50
2273 c0 00 00 0f 23 a0 00 00 03 50 04 92 00 00 00 00
2274 
2275 COLOR 50
2276 c0 00 00 2d 6a e0 00 00 09 f0 04 92 00 00 00 00
2277 
2278 ====================== 75 =====================
2279 BW 75
2280 c0 00 00 0f 20 50 00 00 03 50 04 91 00 00 00 00
2281 
2282 GRAY 75
2283 c0 00 00 0f 20 50 00 00 03 50 04 91 00 00 00 00
2284 
2285 COLOR 75
2286 c0 00 00 2d 60 f0 00 00 09 f0 04 91 00 00 00 00
2287 
2288 COLOR 75 48 bit
2289 c0 00 00 5a 86 40 00 00 13 e0 04 8e 00 00 00 00
2290 
2291 ===================== 100 =====================
2292 BW 100
2293 c0 00 00 01 e4 74 00 00 00 6a 04 92 00 00 00 00
2294 
2295 GRAY 100
2296 c0 00 00 0f 23 a0 00 00 03 50 04 92 00 00 00 00
2297 
2298 COLOR 100
2299 c0 00 00 2d 6a e0 00 00 09 f0 04 92 00 00 00 00
2300 
2301 COLOR 100, 48 bit preview
2302 c0 00 00 5a d5 c0 00 00 13 e0 04 92 00 00 00 00
2303 
2304 COLOR 100, 48 bit
2305 c0 00 00 5a 68 10 00 00 13 c8 04 92 00 00 00 00
2306 
2307 ===================== 150 =====================
2308 BW 150
2309 c0 00 00 3c b3 10 00 00 06 a4 09 24 00 00 00 00
2310 
2311 GRAY 150
2312 c0 00 00 3c b3 10 00 00 06 a4 09 24 00 00 00 00
2313 
2314 COLOR 150
2315 c0 00 00 b6 19 30 00 00 13 ec 09 24 00 00 00 00
2316 
2317 COLOR 150 48bit
2318 c0 00 01 6a 7b a0 00 00 27 a8 09 24 00 00 00 00
2319 
2320 ===================== 200 =====================
2321 BW 200
2322 c0 00 00 07 91 d0 00 00 00 d4 09 24 00 00 00 00
2323 
2324 GRAY 200
2325 c0 00 00 3c b3 10 00 00 06 a4 09 24 00 00 00 00
2326 
2327 COLOR 200
2328 c0 00 00 b6 19 30 00 00 13 ec 09 24 00 00 00 00
2329 
2330 COLOR 200 48 bit
2331 c0 00 01 6a f3 a0 00 00 27 d8 09 1c 00 00 00 00
2332 
2333 ===================== 300 =====================
2334 BW 300
2335 c0 00 00 11 08 14 00 00 01 3e 0d b6 00 00 00 00
2336 
2337 GRAY 300
2338 c0 00 00 88 77 78 00 00 09 f4 0d b6 00 00 00 00
2339 
2340 COLOR 300
2341 c0 00 01 99 66 68 00 00 1d dc 0d b6 00 00 00 00
2342 
2343 ===================== 400 =====================
2344 BW 400
2345 c0 00 02 22 4b 90 00 00 13 ec 1b 6c 00 00 00 00
2346 
2347 GRAY 400
2348 c0 00 02 22 4b 90 00 00 13 ec 1b 6c 00 00 00 00
2349 
2350 COLOR 400
2351 c0 00 06 66 e2 b0 00 00 3b c4 1b 6c 00 00 00 00
2352 
2353 ===================== 600 =====================
2354 BW 600
2355 c0 00 00 44 3b bc 00 00 02 7d 1b 6c 00 00 00 00
2356 
2357 GRAY 600
2358 c0 00 02 22 4b 90 00 00 13 ec 1b 6c 00 00 00 00
2359 
2360 COLOR 600
2361 c0 00 06 66 e2 b0 00 00 3b c4 1b 6c 00 00 00 00
2362 */
2363 /* vim: sw=2 ts=8
2364  */
2365