1 /* sane - Scanner Access Now Easy.
2
3 Copyright (C) 2007-2013 stef.dev@free.fr
4
5 This file is part of the SANE package.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <https://www.gnu.org/licenses/>.
19
20 As a special exception, the authors of SANE give permission for
21 additional uses of the libraries contained in this release of SANE.
22
23 The exception is that, if you link a SANE library with other files
24 to produce an executable, this does not by itself cause the
25 resulting executable to be covered by the GNU General Public
26 License. Your use of that executable is in no way restricted on
27 account of linking the SANE library code into it.
28
29 This exception does not, however, invalidate any other reasons why
30 the executable file might be covered by the GNU General Public
31 License.
32
33 If you submit changes to SANE to the maintainers to be included in
34 a subsequent release, you agree by submitting the changes that
35 those changes may be distributed with this exception intact.
36
37 If you write modifications of your own for SANE, it is your choice
38 whether to permit this exception to apply to your modifications.
39 If you do not wish that, delete this exception notice.
40
41 --------------------------------------------------------------------------
42
43 SANE FLOW DIAGRAM
44
45 - sane_init() : initialize backend, attach scanners
46 . - sane_get_devices() : query list of scanner devices
47 . - sane_open() : open a particular scanner device, adding a handle
48 to the opened device
49 . . - sane_set_io_mode : set blocking mode
50 . . - sane_get_select_fd : get scanner fd
51 . . - sane_get_option_descriptor() : get option information
52 . . - sane_control_option() : change option values
53 . .
54 . . - sane_start() : start image acquisition
55 . . - sane_get_parameters() : returns actual scan parameters
56 . . - sane_read() : read image data
57 . .
58 . . - sane_cancel() : cancel operation
59 . - sane_close() : close opened scanner device, freeing scanner handle
60 - sane_exit() : terminate use of backend, freeing all resources for attached
61 devices
62
63 BACKEND USB locking policy
64 - interface is released at the end of sane_open() to allow
65 multiple usage by fronteds
66 - if free, interface is claimed at sane_start(), and held until
67 sane_cancel() is called
68 - if free interface is claimed then released just during the access
69 to buttons registers
70 */
71
72 /* ------------------------------------------------------------------------- */
73
74 #include "../include/sane/config.h"
75
76 #include <errno.h>
77 #include <fcntl.h>
78 #include <limits.h>
79 #include <math.h>
80 #include <signal.h>
81 #include <stdio.h>
82 #include <stdlib.h>
83 #include <string.h>
84 #include <ctype.h>
85 #include <time.h>
86
87 #include <sys/types.h>
88 #include <unistd.h>
89 #ifdef HAVE_LIBC_H
90 # include <libc.h>
91 #endif
92
93 #include "../include/sane/sane.h"
94 #include "../include/sane/sanei_usb.h"
95 #include "../include/sane/saneopts.h"
96 #include "../include/sane/sanei_config.h"
97 #include "../include/sane/sanei_backend.h"
98
99 #define DARK_TARGET 3.1 /* 3.5 target average for dark calibration */
100 #define DARK_MARGIN 0.3 /* acceptable margin for dark average */
101
102 #define OFFSET_TARGET 3.5 /* target average for offset calibration */
103 #define OFFSET_MARGIN 0.3 /* acceptable margin for offset average */
104
105 #define RED_GAIN_TARGET 170 /* target average for gain calibration for blue color */
106 #define GREEN_GAIN_TARGET 170 /* target average for gain calibration for blue color */
107 #define BLUE_GAIN_TARGET 180 /* target average for gain calibration for blue color */
108 #define GAIN_MARGIN 2 /* acceptable margin for gain average */
109
110 #define MARGIN_LEVEL 128 /* white level for margin detection */
111
112 /* width used for calibration */
113 #define CALIBRATION_WIDTH 637
114
115 /* data size for calibration: one RGB line*/
116 #define CALIBRATION_SIZE CALIBRATION_WIDTH*3
117
118 /* #define FAST_INIT 1 */
119
120 #define BUILD 2401
121
122 #define MOVE_DPI 100
123
124 #include "rts8891.h"
125 #include "rts88xx_lib.h"
126 #include "rts8891_low.c"
127 #include "rts8891_devices.c"
128
129
130 #define DEEP_DEBUG 1
131
132 /**
133 * Pointer to the first Rts8891_Session in the linked list of
134 * opened device. Sessions are inserted here on sane_open() and
135 * removed on sane_close().
136 */
137 static Rts8891_Session *first_handle = NULL;
138
139
140 /* pointer to the first device attached to the backend
141 * the same device may be opened several time
142 * entry are inserted here by attach_rts8891 */
143 static Rts8891_Device *first_device = NULL;
144 static SANE_Int num_devices = 0;
145
146 /*
147 * needed by sane_get_devices
148 */
149 static const SANE_Device **devlist = 0;
150
151
152 static SANE_String_Const mode_list[] = {
153 SANE_VALUE_SCAN_MODE_COLOR,
154 SANE_VALUE_SCAN_MODE_GRAY,
155 SANE_VALUE_SCAN_MODE_LINEART,
156 0
157 };
158
159 static SANE_Range x_range = {
160 SANE_FIX (0.0), /* minimum */
161 SANE_FIX (216.0), /* maximum */
162 SANE_FIX (0.0) /* quantization */
163 };
164
165 static SANE_Range y_range = {
166 SANE_FIX (0.0), /* minimum */
167 SANE_FIX (299.0), /* maximum */
168 SANE_FIX (0.0) /* no quantization */
169 };
170
171 /* model number ranges from 0 to 2, must be changed if
172 * Rts8891_USB_Device_Entry changes */
173 static const SANE_Range model_range = {
174 0, /* minimum */
175 2, /* maximum */
176 0 /* no quantization */
177 };
178
179 /* sensor number ranges from 0 to SENSOR_TYPE_MAX, must be changed if */
180 static const SANE_Range sensor_range = {
181 0, /* minimum */
182 SENSOR_TYPE_MAX, /* maximum */
183 0 /* no quantization */
184 };
185
186 static const SANE_Range u8_range = {
187 0, /* minimum */
188 255, /* maximum */
189 0 /* no quantization */
190 };
191
192 static const SANE_Range threshold_percentage_range = {
193 SANE_FIX (0), /* minimum */
194 SANE_FIX (100), /* maximum */
195 SANE_FIX (1) /* quantization */
196 };
197
198 static size_t
max_string_size(const SANE_String_Const strings[])199 max_string_size (const SANE_String_Const strings[])
200 {
201 size_t size, max_size = 0;
202 SANE_Int i;
203
204 for (i = 0; strings[i]; ++i)
205 {
206 size = strlen (strings[i]) + 1;
207 if (size > max_size)
208 max_size = size;
209 }
210 return max_size;
211 }
212
213 /**> placeholders for decoded configuration values */
214 static Rts8891_Config rtscfg;
215
216 /* ------------------------------------------------------------------------- */
217 static SANE_Status probe_rts8891_devices (void);
218 static SANE_Status config_attach_rts8891 (SANEI_Config * config,
219 const char *devname, void *data);
220 static SANE_Status attach_rts8891 (const char *name);
221 static SANE_Status set_lamp_brightness (struct Rts8891_Device *dev,
222 int level);
223 static SANE_Status init_options (struct Rts8891_Session *session);
224 #ifndef FAST_INIT
225 static SANE_Status init_device (struct Rts8891_Device *dev);
226 #else
227 static SANE_Status detect_device (struct Rts8891_Device *dev);
228 static SANE_Status initialize_device (struct Rts8891_Device *dev);
229 #endif
230 static SANE_Status init_lamp (struct Rts8891_Device *dev);
231 static SANE_Status find_origin (struct Rts8891_Device *dev,
232 SANE_Bool * changed);
233 static SANE_Status find_margin (struct Rts8891_Device *dev);
234 static SANE_Status dark_calibration (struct Rts8891_Device *dev, int mode,
235 int light);
236 static SANE_Status gain_calibration (struct Rts8891_Device *dev, int mode,
237 int light);
238 static SANE_Status offset_calibration (struct Rts8891_Device *dev, int mode,
239 int light);
240 static SANE_Status shading_calibration (struct Rts8891_Device *dev,
241 SANE_Bool color, int mode, int light);
242 static SANE_Status send_calibration_data (struct Rts8891_Session *session);
243 static SANE_Status write_scan_registers (struct Rts8891_Session *session);
244 static SANE_Status read_data (struct Rts8891_Session *session,
245 SANE_Byte * dest, SANE_Int length);
246 static SANE_Status compute_parameters (struct Rts8891_Session *session);
247 static SANE_Status move_to_scan_area (struct Rts8891_Session *session);
248 static SANE_Status park_head (struct Rts8891_Device *dev, SANE_Bool wait);
249 static SANE_Status update_button_status (struct Rts8891_Session *session);
250 static SANE_Status set_lamp_state (struct Rts8891_Session *session, int on);
251
252
253 /* ------------------------------------------------------------------------- */
254 /* writes gray data to a pnm file */
255 static void
write_gray_data(unsigned char *image, char *name, SANE_Int width, SANE_Int height)256 write_gray_data (unsigned char *image, char *name, SANE_Int width,
257 SANE_Int height)
258 {
259 FILE *fdbg = NULL;
260
261 fdbg = fopen (name, "wb");
262 if (fdbg == NULL)
263 return;
264 fprintf (fdbg, "P5\n%d %d\n255\n", width, height);
265 fwrite (image, width, height, fdbg);
266 fclose (fdbg);
267 }
268
269 /* ------------------------------------------------------------------------- */
270 /* writes rgb data to a pnm file */
271 static void
write_rgb_data(char *name, unsigned char *image, SANE_Int width, SANE_Int height)272 write_rgb_data (char *name, unsigned char *image, SANE_Int width,
273 SANE_Int height)
274 {
275 FILE *fdbg = NULL;
276
277 fdbg = fopen (name, "wb");
278 if (fdbg == NULL)
279 return;
280 fprintf (fdbg, "P6\n%d %d\n255\n", width, height);
281 fwrite (image, width * 3, height, fdbg);
282 fclose (fdbg);
283 }
284
285 /* ------------------------------------------------------------------------- */
286
287 /*
288 * SANE Interface
289 */
290
291
292 /**
293 * Called by SANE initially.
294 *
295 * From the SANE spec:
296 * This function must be called before any other SANE function can be
297 * called. The behavior of a SANE backend is undefined if this
298 * function is not called first. The version code of the backend is
299 * returned in the value pointed to by version_code. If that pointer
300 * is NULL, no version code is returned. Argument authorize is either
301 * a pointer to a function that is invoked when the backend requires
302 * authentication for a specific resource or NULL if the frontend does
303 * not support authentication.
304 */
305 SANE_Status
sane_init(SANE_Int * version_code, SANE_Auth_Callback authorize)306 sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
307 {
308 SANE_Status status;
309
310 (void) authorize; /* get rid of compiler warning */
311
312 /* init ASIC libraries */
313 sanei_rts88xx_lib_init ();
314 rts8891_low_init ();
315
316 /* init backend debug */
317 DBG_INIT ();
318 DBG (DBG_info, "SANE Rts8891 backend version %d.%d-%d\n",
319 SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD);
320 DBG (DBG_proc, "sane_init: start\n");
321
322 if (version_code)
323 *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD);
324
325 /* cold-plugging case : probe for already plugged devices */
326 status = probe_rts8891_devices ();
327
328 DBG (DBG_proc, "sane_init: exit\n");
329 return status;
330 }
331
332
333 /**
334 * Called by SANE to find out about supported devices.
335 *
336 * From the SANE spec:
337 * This function can be used to query the list of devices that are
338 * available. If the function executes successfully, it stores a
339 * pointer to a NULL terminated array of pointers to SANE_Device
340 * structures in *device_list. The returned list is guaranteed to
341 * remain unchanged and valid until (a) another call to this function
342 * is performed or (b) a call to sane_exit() is performed. This
343 * function can be called repeatedly to detect when new devices become
344 * available. If argument local_only is true, only local devices are
345 * returned (devices directly attached to the machine that SANE is
346 * running on). If it is false, the device list includes all remote
347 * devices that are accessible to the SANE library.
348 *
349 * SANE does not require that this function is called before a
350 * sane_open() call is performed. A device name may be specified
351 * explicitly by a user which would make it unnecessary and
352 * undesirable to call this function first.
353 */
354 SANE_Status
sane_get_devices(const SANE_Device *** device_list, SANE_Bool local_only)355 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
356 {
357 SANE_Int dev_num;
358 struct Rts8891_Device *device;
359 SANE_Device *sane_device;
360 int i;
361
362 DBG (DBG_proc, "sane_get_devices: start: local_only = %s\n",
363 local_only == SANE_TRUE ? "true" : "false");
364
365 /* hot-plugging case : probe for devices plugged since sane_init called */
366 probe_rts8891_devices ();
367
368 /* reset devlist first if needed */
369 if (devlist)
370 {
371 for (i = 0; i < num_devices; i++)
372 free ((char *) devlist[i]);
373 free (devlist);
374 devlist = NULL;
375 }
376 devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
377 if (!devlist)
378 return SANE_STATUS_NO_MEM;
379
380 *device_list = devlist;
381
382 dev_num = 0;
383
384 /* we build a list of SANE_Device from the list of attached devices */
385 for (device = first_device; dev_num < num_devices; device = device->next)
386 {
387 sane_device = malloc (sizeof (*sane_device));
388 if (!sane_device)
389 return SANE_STATUS_NO_MEM;
390 sane_device->name = device->file_name;
391 sane_device->vendor = device->model->vendor;
392 sane_device->model = device->model->product;
393 sane_device->type = device->model->type;
394 devlist[dev_num++] = sane_device;
395 }
396 devlist[dev_num++] = 0;
397
398 *device_list = devlist;
399
400 DBG (DBG_proc, "sane_get_devices: exit\n");
401
402 return SANE_STATUS_GOOD;
403 }
404
405
406 /**
407 * Called to establish connection with the session. This function will
408 * also establish meaningful defaults and initialize the options.
409 *
410 * From the SANE spec:
411 * This function is used to establish a connection to a particular
412 * device. The name of the device to be opened is passed in argument
413 * name. If the call completes successfully, a handle for the device
414 * is returned in *h. As a special case, specifying a zero-length
415 * string as the device requests opening the first available device
416 * (if there is such a device).
417 * TODO handle SANE_STATUS_BUSY
418 */
419 SANE_Status
sane_open(SANE_String_Const name, SANE_Handle * handle)420 sane_open (SANE_String_Const name, SANE_Handle * handle)
421 {
422 struct Rts8891_Session *session = NULL;
423 struct Rts8891_Device *device = NULL;
424 SANE_Status status;
425
426 DBG (DBG_proc, "sane_open: start (devicename=%s)\n", name);
427 if (name[0] == 0 || strncmp (name, "rts8891", 7) == 0)
428 {
429 DBG (DBG_info, "sane_open: no device requested, using default\n");
430 if (first_device)
431 {
432 device = first_device;
433 DBG (DBG_info, "sane_open: device %s used as default device\n",
434 device->file_name);
435 }
436 }
437 else
438 {
439 DBG (DBG_info, "sane_open: device %s requested\n", name);
440 /* walk the device list until we find a matching name */
441 device = first_device;
442 while (device && strcmp (device->file_name, name) != 0)
443 {
444 DBG (DBG_info, "sane_open: device %s doesn't match\n",
445 device->file_name);
446 device = device->next;
447 }
448 }
449
450 /* check whether we have found a match or reach the end of the device list */
451 if (!device)
452 {
453 DBG (DBG_info, "sane_open: no device found\n");
454 return SANE_STATUS_INVAL;
455 }
456
457 /* now we have a device, duplicate it and return it in handle */
458 DBG (DBG_info, "sane_open: device %s found\n", name);
459
460 if (device->model->flags & RTS8891_FLAG_UNTESTED)
461 {
462 DBG (DBG_error0,
463 "WARNING: Your scanner is not fully supported or at least \n");
464 DBG (DBG_error0,
465 " had only limited testing. Please be careful and \n");
466 DBG (DBG_error0, " report any failure/success to \n");
467 DBG (DBG_error0,
468 " sane-devel@alioth-lists.debian.net. Please provide as many\n");
469 DBG (DBG_error0,
470 " details as possible, e.g. the exact name of your\n");
471 DBG (DBG_error0, " scanner and what does (not) work.\n");
472
473 }
474
475 /* open USB link */
476 status = sanei_usb_open (device->file_name, &device->devnum);
477 if (status != SANE_STATUS_GOOD)
478 {
479 DBG (DBG_warn, "sane_open: couldn't open device `%s': %s\n",
480 device->file_name, sane_strstatus (status));
481 return status;
482 }
483
484 /* device initialization */
485 if (device->initialized == SANE_FALSE)
486 {
487 #ifdef FAST_INIT
488 status = detect_device (device);
489 if (status != SANE_STATUS_GOOD)
490 {
491 DBG (DBG_error, "sane_open: detect_device failed\n");
492 DBG (DBG_proc, "sane_open: exit on error\n");
493 return status;
494 }
495 status = initialize_device (device);
496 if (status != SANE_STATUS_GOOD)
497 {
498 DBG (DBG_error, "sane_open: initialize_device failed\n");
499 DBG (DBG_proc, "sane_open: exit on error\n");
500 return status;
501 }
502 #else
503 status = init_device (device);
504 if (status != SANE_STATUS_GOOD)
505 {
506 DBG (DBG_error, "sane_open: init_device failed\n");
507 DBG (DBG_proc, "sane_open: exit on error\n");
508 return status;
509 }
510 device->initialized = SANE_TRUE;
511 #endif
512 }
513
514 /* prepare handle to return */
515 session = (Rts8891_Session *) malloc (sizeof (Rts8891_Session));
516
517 session->scanning = SANE_FALSE;
518 session->dev = device;
519
520 init_options (session);
521 session->scanning = SANE_FALSE;
522 session->non_blocking = SANE_FALSE;
523 *handle = session;
524
525 /* add the handle to the list */
526 session->next = first_handle;
527 first_handle = session;
528
529 /* release the interface to allow device sharing */
530 if (session->dev->conf.allowsharing == SANE_TRUE)
531 {
532 sanei_usb_release_interface (device->devnum, 0);
533 }
534
535 DBG (DBG_proc, "sane_open: exit\n");
536 return SANE_STATUS_GOOD;
537 }
538
539
540 /**
541 * Set non blocking mode. In this mode, read return immediately when
542 * no data is available, instead of polling the scanner.
543 */
544 SANE_Status
sane_set_io_mode(SANE_Handle handle, SANE_Bool non_blocking)545 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
546 {
547 Rts8891_Session *session = (Rts8891_Session *) handle;
548
549 DBG (DBG_proc, "sane_set_io_mode: start\n");
550 if (session->scanning != SANE_TRUE)
551 {
552 DBG (DBG_error, "sane_set_io_mode: called out of a scan\n");
553 return SANE_STATUS_INVAL;
554 }
555 session->non_blocking = non_blocking;
556 DBG (DBG_warn, "sane_set_io_mode: I/O mode set to %sblocking.\n",
557 non_blocking ? "non " : " ");
558 DBG (DBG_proc, "sane_set_io_mode: exit\n");
559 return SANE_STATUS_GOOD;
560 }
561
562
563 /**
564 * An advanced method we don't support but have to define.
565 */
566 SANE_Status
sane_get_select_fd(SANE_Handle handle, SANE_Int * fdp)567 sane_get_select_fd (SANE_Handle handle, SANE_Int * fdp)
568 {
569
570 DBG (DBG_proc, "sane_get_select_fd: start\n");
571 if(handle==0 || fdp==NULL)
572 {
573 return SANE_STATUS_INVAL;
574 }
575 DBG (DBG_warn, "sane_get_select_fd: unsupported ...\n");
576 DBG (DBG_proc, "sane_get_select_fd: exit\n");
577 return SANE_STATUS_UNSUPPORTED;
578 }
579
580
581 /**
582 * Returns the options we know.
583 *
584 * From the SANE spec:
585 * This function is used to access option descriptors. The function
586 * returns the option descriptor for option number n of the device
587 * represented by handle h. Option number 0 is guaranteed to be a
588 * valid option. Its value is an integer that specifies the number of
589 * options that are available for device handle h (the count includes
590 * option 0). If n is not a valid option index, the function returns
591 * NULL. The returned option descriptor is guaranteed to remain valid
592 * (and at the returned address) until the device is closed.
593 */
594 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)595 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
596 {
597 struct Rts8891_Session *session = handle;
598
599 DBG (DBG_proc, "sane_get_option_descriptor: start\n");
600
601 if ((unsigned) option >= NUM_OPTIONS)
602 return NULL;
603
604 DBG (DBG_info, "sane_get_option_descriptor: \"%s\"\n",
605 session->opt[option].name);
606
607 DBG (DBG_proc, "sane_get_option_descriptor: exit\n");
608 return &(session->opt[option]);
609 }
610
611 /**
612 * sets automatic value for an option , called by sane_control_option after
613 * all checks have been done */
614 static SANE_Status
set_automatic_value(Rts8891_Session * s, int option, SANE_Int * myinfo)615 set_automatic_value (Rts8891_Session * s, int option, SANE_Int * myinfo)
616 {
617 SANE_Status status = SANE_STATUS_GOOD;
618 SANE_Int i, min;
619 const SANE_Word *dpi_list;
620
621 switch (option)
622 {
623 case OPT_TL_X:
624 s->val[OPT_TL_X].w = x_range.min;
625 *myinfo |= SANE_INFO_RELOAD_PARAMS;
626 break;
627 case OPT_TL_Y:
628 s->val[OPT_TL_Y].w = y_range.min;
629 *myinfo |= SANE_INFO_RELOAD_PARAMS;
630 break;
631 case OPT_BR_X:
632 s->val[OPT_BR_X].w = x_range.max;
633 *myinfo |= SANE_INFO_RELOAD_PARAMS;
634 break;
635 case OPT_BR_Y:
636 s->val[OPT_BR_Y].w = y_range.max;
637 *myinfo |= SANE_INFO_RELOAD_PARAMS;
638 break;
639 case OPT_RESOLUTION:
640 /* we set up to the lowest available dpi value */
641 dpi_list = s->opt[OPT_RESOLUTION].constraint.word_list;
642 min = 65536;
643 for (i = 1; i < dpi_list[0]; i++)
644 {
645 if (dpi_list[i] < min)
646 min = dpi_list[i];
647 }
648 s->val[OPT_RESOLUTION].w = min;
649 *myinfo |= SANE_INFO_RELOAD_PARAMS;
650 break;
651 case OPT_THRESHOLD:
652 s->val[OPT_THRESHOLD].w = SANE_FIX (50);
653 break;
654 case OPT_PREVIEW:
655 s->val[OPT_PREVIEW].w = SANE_FALSE;
656 *myinfo |= SANE_INFO_RELOAD_PARAMS;
657 break;
658 case OPT_MODE:
659 if (s->val[OPT_MODE].s)
660 free (s->val[OPT_MODE].s);
661 s->val[OPT_MODE].s = strdup (mode_list[0]);
662 *myinfo |= SANE_INFO_RELOAD_OPTIONS;
663 *myinfo |= SANE_INFO_RELOAD_PARAMS;
664 break;
665 case OPT_CUSTOM_GAMMA:
666 s->val[option].b = SANE_FALSE;
667 DISABLE (OPT_GAMMA_VECTOR);
668 DISABLE (OPT_GAMMA_VECTOR_R);
669 DISABLE (OPT_GAMMA_VECTOR_G);
670 DISABLE (OPT_GAMMA_VECTOR_B);
671 break;
672 case OPT_GAMMA_VECTOR:
673 case OPT_GAMMA_VECTOR_R:
674 case OPT_GAMMA_VECTOR_G:
675 case OPT_GAMMA_VECTOR_B:
676 if (s->dev->model->gamma != s->val[option].wa)
677 free (s->val[option].wa);
678 s->val[option].wa = s->dev->model->gamma;
679 break;
680 default:
681 DBG (DBG_warn, "set_automatic_value: can't set unknown option %d\n",
682 option);
683 }
684
685 return status;
686 }
687
688 /**
689 * sets an option , called by sane_control_option after all
690 * checks have been done */
691 static SANE_Status
set_option_value(Rts8891_Session * s, int option, void *val, SANE_Int * myinfo)692 set_option_value (Rts8891_Session * s, int option, void *val,
693 SANE_Int * myinfo)
694 {
695 SANE_Status status = SANE_STATUS_GOOD;
696 SANE_Int i;
697 SANE_Word tmpw;
698
699 switch (option)
700 {
701 case OPT_TL_X:
702 case OPT_TL_Y:
703 case OPT_BR_X:
704 case OPT_BR_Y:
705 s->val[option].w = *(SANE_Word *) val;
706 /* we ensure geometry is coherent */
707 /* this happens when user drags TL corner right or below the BR point */
708 if (s->val[OPT_BR_Y].w < s->val[OPT_TL_Y].w)
709 {
710 tmpw = s->val[OPT_BR_Y].w;
711 s->val[OPT_BR_Y].w = s->val[OPT_TL_Y].w;
712 s->val[OPT_TL_Y].w = tmpw;
713 }
714 if (s->val[OPT_BR_X].w < s->val[OPT_TL_X].w)
715 {
716 tmpw = s->val[OPT_BR_X].w;
717 s->val[OPT_BR_X].w = s->val[OPT_TL_X].w;
718 s->val[OPT_TL_X].w = tmpw;
719 }
720
721 *myinfo |= SANE_INFO_RELOAD_PARAMS;
722 break;
723
724 case OPT_RESOLUTION:
725 case OPT_THRESHOLD:
726 case OPT_PREVIEW:
727 s->val[option].w = *(SANE_Word *) val;
728 *myinfo |= SANE_INFO_RELOAD_PARAMS;
729 break;
730
731 case OPT_MODE:
732 if (s->val[option].s)
733 free (s->val[option].s);
734 s->val[option].s = strdup (val);
735 if (strcmp (s->val[option].s, LINEART_MODE) == 0)
736 {
737 ENABLE (OPT_THRESHOLD);
738 }
739 else
740 {
741 DISABLE (OPT_THRESHOLD);
742 }
743
744 /* if custom gamma, toggle gamma table options according to the mode */
745 if (s->val[OPT_CUSTOM_GAMMA].b == SANE_TRUE)
746 {
747 if (strcmp (s->val[option].s, COLOR_MODE) == 0)
748 {
749 DISABLE (OPT_GAMMA_VECTOR);
750 ENABLE (OPT_GAMMA_VECTOR_R);
751 ENABLE (OPT_GAMMA_VECTOR_G);
752 ENABLE (OPT_GAMMA_VECTOR_B);
753 }
754 else
755 {
756 ENABLE (OPT_GAMMA_VECTOR);
757 DISABLE (OPT_GAMMA_VECTOR_R);
758 DISABLE (OPT_GAMMA_VECTOR_G);
759 DISABLE (OPT_GAMMA_VECTOR_B);
760 }
761 }
762 *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
763 break;
764
765 case OPT_CUSTOM_GAMMA:
766 *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
767 s->val[OPT_CUSTOM_GAMMA].b = *(SANE_Bool *) val;
768
769 if (s->val[OPT_CUSTOM_GAMMA].b == SANE_TRUE)
770 {
771 if (strcmp (s->val[OPT_MODE].s, COLOR_MODE) == 0)
772 {
773 DISABLE (OPT_GAMMA_VECTOR);
774 ENABLE (OPT_GAMMA_VECTOR_R);
775 ENABLE (OPT_GAMMA_VECTOR_G);
776 ENABLE (OPT_GAMMA_VECTOR_B);
777 }
778 else
779 {
780 ENABLE (OPT_GAMMA_VECTOR);
781 DISABLE (OPT_GAMMA_VECTOR_R);
782 DISABLE (OPT_GAMMA_VECTOR_G);
783 DISABLE (OPT_GAMMA_VECTOR_B);
784 }
785 }
786 else
787 {
788 DISABLE (OPT_GAMMA_VECTOR);
789 DISABLE (OPT_GAMMA_VECTOR_R);
790 DISABLE (OPT_GAMMA_VECTOR_G);
791 DISABLE (OPT_GAMMA_VECTOR_B);
792 }
793 break;
794
795 case OPT_GAMMA_VECTOR:
796 case OPT_GAMMA_VECTOR_R:
797 case OPT_GAMMA_VECTOR_G:
798 case OPT_GAMMA_VECTOR_B:
799 /* sanity checks */
800 for (i = 0; i < (int) (s->opt[option].size / sizeof (SANE_Word)); i++)
801 {
802 /* avoid 0xaa values since they will be problematic */
803 if (((SANE_Int *) val)[i] == 0xaa)
804 ((SANE_Int *) val)[i] = 0xab;
805 }
806
807 /* free memory from previous set */
808 if (s->dev->model->gamma != s->val[option].wa)
809 free (s->val[option].wa);
810
811 /* then alloc memory */
812 s->val[option].wa = (SANE_Word *) malloc (256 * sizeof (SANE_Word));
813 if (s->val[option].wa == NULL)
814 {
815 s->val[option].wa = s->dev->model->gamma;
816 DBG (DBG_error0,
817 "set_option_value: not enough memory for %lu bytes!\n",
818 (u_long) (256 * sizeof (SANE_Word)));
819 return SANE_STATUS_NO_MEM;
820 }
821
822 /* data copy */
823 memcpy (s->val[option].wa, val, s->opt[option].size);
824 break;
825
826 case OPT_LAMP_ON:
827 return set_lamp_state (s, 1);
828 break;
829
830 case OPT_LAMP_OFF:
831 return set_lamp_state (s, 0);
832 break;
833
834 default:
835 DBG (DBG_warn, "set_option_value: can't set unknown option %d\n",
836 option);
837 }
838 return status;
839 }
840
841 /**
842 * gets an option , called by sane_control_option after all checks
843 * have been done */
844 static SANE_Status
get_option_value(Rts8891_Session * s, int option, void *val)845 get_option_value (Rts8891_Session * s, int option, void *val)
846 {
847 switch (option)
848 {
849 /* word or word equivalent options: */
850 case OPT_NUM_OPTS:
851 case OPT_RESOLUTION:
852 case OPT_PREVIEW:
853 case OPT_TL_X:
854 case OPT_TL_Y:
855 case OPT_BR_X:
856 case OPT_BR_Y:
857 case OPT_THRESHOLD:
858 case OPT_CUSTOM_GAMMA:
859 *(SANE_Word *) val = s->val[option].w;
860 break;
861 case OPT_BUTTON_1:
862 case OPT_BUTTON_2:
863 case OPT_BUTTON_3:
864 case OPT_BUTTON_4:
865 case OPT_BUTTON_5:
866 case OPT_BUTTON_6:
867 case OPT_BUTTON_7:
868 case OPT_BUTTON_8:
869 case OPT_BUTTON_9:
870 case OPT_BUTTON_10:
871 case OPT_BUTTON_11:
872 /* no button pressed by default */
873 *(SANE_Word *) val = SANE_FALSE;
874 if (option - OPT_BUTTON_1 > s->dev->model->buttons)
875 {
876 DBG (DBG_warn,
877 "get_option_value: invalid button option %d\n", option);
878 }
879 else
880 {
881 update_button_status (s);
882 /* copy the button state */
883 *(SANE_Word *) val = s->val[option].w;
884 /* clear the button state */
885 s->val[option].w = SANE_FALSE;
886 DBG (DBG_io,
887 "get_option_value: button option %d=%d\n", option,
888 *(SANE_Word *) val);
889 }
890 break;
891 /* string options: */
892 case OPT_MODE:
893 strcpy (val, s->val[option].s);
894 break;
895 case OPT_GAMMA_VECTOR:
896 case OPT_GAMMA_VECTOR_R:
897 case OPT_GAMMA_VECTOR_G:
898 case OPT_GAMMA_VECTOR_B:
899 memcpy (val, s->val[option].wa, s->opt[option].size);
900 break;
901 default:
902 DBG (DBG_warn, "get_option_value: can't get unknown option %d\n",
903 option);
904 }
905 return SANE_STATUS_GOOD;
906 }
907
908 /**
909 * Gets or sets an option value.
910 *
911 * From the SANE spec:
912 * This function is used to set or inquire the current value of option
913 * number n of the device represented by handle h. The manner in which
914 * the option is controlled is specified by parameter action. The
915 * possible values of this parameter are described in more detail
916 * below. The value of the option is passed through argument val. It
917 * is a pointer to the memory that holds the option value. The memory
918 * area pointed to by v must be big enough to hold the entire option
919 * value (determined by member size in the corresponding option
920 * descriptor).
921 *
922 * The only exception to this rule is that when setting the value of a
923 * string option, the string pointed to by argument v may be shorter
924 * since the backend will stop reading the option value upon
925 * encountering the first NUL terminator in the string. If argument i
926 * is not NULL, the value of *i will be set to provide details on how
927 * well the request has been met.
928 * action is SANE_ACTION_GET_VALUE, SANE_ACTION_SET_VALUE or SANE_ACTION_SET_AUTO
929 */
930 SANE_Status
sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info)931 sane_control_option (SANE_Handle handle, SANE_Int option,
932 SANE_Action action, void *val, SANE_Int * info)
933 {
934 Rts8891_Session *s = handle;
935 SANE_Status status;
936 SANE_Word cap;
937 SANE_Int myinfo = 0;
938
939 DBG (DBG_io2,
940 "sane_control_option: start: action = %s, option = %s (%d)\n",
941 (action == SANE_ACTION_GET_VALUE) ? "get" : (action ==
942 SANE_ACTION_SET_VALUE) ?
943 "set" : (action == SANE_ACTION_SET_AUTO) ? "set_auto" : "unknown",
944 s->opt[option].name, option);
945
946 if (info)
947 *info = 0;
948
949 /* do checks before trying to apply action */
950
951 if (s->scanning)
952 {
953 DBG (DBG_warn, "sane_control_option: don't call this function while "
954 "scanning (option = %s (%d))\n", s->opt[option].name, option);
955 return SANE_STATUS_DEVICE_BUSY;
956 }
957
958 /* option must be within existing range */
959 if (option >= NUM_OPTIONS || option < 0)
960 {
961 DBG (DBG_warn,
962 "sane_control_option: option %d >= NUM_OPTIONS || option < 0\n",
963 option);
964 return SANE_STATUS_INVAL;
965 }
966
967 /* don't access an inactive option */
968 cap = s->opt[option].cap;
969 if (!SANE_OPTION_IS_ACTIVE (cap))
970 {
971 DBG (DBG_warn, "sane_control_option: option %d is inactive\n", option);
972 return SANE_STATUS_INVAL;
973 }
974
975 /* now checks have been done, apply action */
976 switch (action)
977 {
978 case SANE_ACTION_GET_VALUE:
979 status = get_option_value (s, option, val);
980 break;
981
982 case SANE_ACTION_SET_VALUE:
983 if (!SANE_OPTION_IS_SETTABLE (cap))
984 {
985 DBG (DBG_warn, "sane_control_option: option %d is not settable\n",
986 option);
987 return SANE_STATUS_INVAL;
988 }
989
990 status = sanei_constrain_value (s->opt + option, val, &myinfo);
991 if (status != SANE_STATUS_GOOD)
992 {
993 DBG (DBG_warn,
994 "sane_control_option: sanei_constrain_value returned %s\n",
995 sane_strstatus (status));
996 return status;
997 }
998
999 /* return immediately if no change */
1000 if (s->opt[option].type == SANE_TYPE_INT
1001 && *(SANE_Word *) val == s->val[option].w)
1002 {
1003 status = SANE_STATUS_GOOD;
1004 }
1005 else
1006 { /* apply change */
1007 status = set_option_value (s, option, val, &myinfo);
1008 }
1009 break;
1010
1011 case SANE_ACTION_SET_AUTO:
1012 /* sets automatic values */
1013 if (!(cap & SANE_CAP_AUTOMATIC))
1014 {
1015 DBG (DBG_warn,
1016 "sane_control_option: option %d is not autosettable\n",
1017 option);
1018 return SANE_STATUS_INVAL;
1019 }
1020
1021 status = set_automatic_value (s, option, &myinfo);
1022 break;
1023
1024 default:
1025 DBG (DBG_error, "sane_control_option: invalid action %d\n", action);
1026 status = SANE_STATUS_INVAL;
1027 break;
1028 }
1029
1030 if (info)
1031 *info = myinfo;
1032
1033 DBG (DBG_io2, "sane_control_option: exit\n");
1034 return status;
1035 }
1036
1037 /**
1038 * returns the name of the sensor
1039 * @param sensor sensor numnber
1040 * @return string holding the name of the sensor
1041 */
sensor_name(int sensor)1042 static char *sensor_name (int sensor)
1043 {
1044 switch (sensor)
1045 {
1046 case SENSOR_TYPE_BARE:
1047 return "SENSOR_TYPE_BARE";
1048 case SENSOR_TYPE_XPA:
1049 return "SENSOR_TYPE_XPA";
1050 case SENSOR_TYPE_4400:
1051 return "SENSOR_TYPE_4400";
1052 case SENSOR_TYPE_4400_BARE:
1053 return "SENSOR_TYPE_4400_BARE";
1054 default:
1055 return "BOGUS";
1056 }
1057 }
1058
1059 /**
1060 * Called by SANE when a page acquisition operation is to be started.
1061 * @param handle opaque handle to a frontend session
1062 * @return SANE_STATUS_GOOD on success, SANE_STATUS_BUSY if the device is
1063 * in use by another session or SANE_STATUS_WARMING_UP if the device is
1064 * warming up. In this case the fronted as to call sane_start again until
1065 * warming up is done. Any other values returned are error status.
1066 */
1067 SANE_Status
sane_start(SANE_Handle handle)1068 sane_start (SANE_Handle handle)
1069 {
1070 struct Rts8891_Session *session = handle;
1071 int light, mode;
1072 struct Rts8891_Device *dev = session->dev;
1073 SANE_Status status;
1074 SANE_Bool changed;
1075 #ifdef HAVE_SYS_TIME_H
1076 struct timeval current;
1077 #endif
1078
1079 DBG (DBG_proc, "sane_start: start\n");
1080
1081 /* if already scanning, tell we're busy */
1082 if (session->scanning == SANE_TRUE)
1083 {
1084 DBG (DBG_warn, "sane_start: device is already scanning\n");
1085 return SANE_STATUS_DEVICE_BUSY;
1086 }
1087
1088 /* claim the interface reserve device */
1089 if (dev->conf.allowsharing == SANE_TRUE)
1090 {
1091 status = sanei_usb_claim_interface (dev->devnum, 0);
1092 if (status != SANE_STATUS_GOOD)
1093 {
1094 DBG (DBG_warn, "sane_start: cannot claim usb interface\n");
1095 return SANE_STATUS_DEVICE_BUSY;
1096 }
1097 }
1098
1099 /* check if we need warming-up */
1100 sanei_rts88xx_get_lamp_status (dev->devnum, dev->regs);
1101 if ((dev->regs[0x8e] & 0x60) != 0x60)
1102 {
1103 DBG (DBG_info, "sane_start: lamp needs warming (0x%02x)\n",
1104 dev->regs[0x8e]);
1105 dev->needs_warming = SANE_TRUE;
1106 #ifdef HAVE_SYS_TIME_H
1107 dev->start_time.tv_sec = current.tv_sec;
1108 dev->last_scan.tv_sec = current.tv_sec;
1109 #endif
1110 }
1111
1112 #ifdef HAVE_SYS_TIME_H
1113 /* if last scan time is more than 10 minutes ago, scanner also needs
1114 * warming-up */
1115 gettimeofday (¤t, NULL);
1116 if ((current.tv_sec - dev->last_scan.tv_sec) / 60 > 10)
1117 {
1118 DBG (DBG_info,
1119 "sane_start: more than 10 minutes without scanning, lamp needs warming\n");
1120 dev->needs_warming = SANE_TRUE;
1121 dev->start_time.tv_sec = current.tv_sec;
1122 dev->last_scan.tv_sec = current.tv_sec;
1123 }
1124 #endif
1125
1126 /* if parking, wait for head to stop */
1127 if(dev->parking==SANE_TRUE)
1128 {
1129 rts8891_wait_for_home (dev, dev->regs);
1130 }
1131
1132 /* reinit registers to start values */
1133 rts8891_set_default_regs (dev->regs);
1134
1135 /* step 0: light up */
1136 init_lamp (dev);
1137
1138 /* do warming up if needed: just detected or at sane_open() */
1139 if (dev->needs_warming == SANE_TRUE)
1140 {
1141 DBG (DBG_info, "sane_start: warming lamp ...\n");
1142 #ifdef HAVE_SYS_TIME_H
1143 /* check if current time is >15s after warming-up start */
1144 gettimeofday (¤t, NULL);
1145 if ((current.tv_sec - dev->start_time.tv_sec) < 15)
1146 {
1147 #ifdef SANE_STATUS_WARMING_UP
1148 if (dev->conf.allowsharing == SANE_TRUE)
1149 {
1150 sanei_usb_release_interface (dev->devnum, 0);
1151 }
1152 return SANE_STATUS_WARMING_UP;
1153 #else
1154 DBG (DBG_info,
1155 "sane_start: waiting to let lamp get warm enough ...\n");
1156 sleep (15 - (current.tv_sec - dev->start_time.tv_sec));
1157 #endif
1158 }
1159 #else
1160 DBG (DBG_info,
1161 "sane_start: waiting 15s to let lamp get warm enough ...\n");
1162 sleep (15);
1163 #endif
1164 }
1165 dev->needs_warming = SANE_FALSE;
1166
1167 /* restore default brightness */
1168 dev->regs[LAMP_BRIGHT_REG] = 0xA7;
1169 sanei_rts88xx_write_reg (dev->devnum, LAMP_BRIGHT_REG,
1170 dev->regs + LAMP_BRIGHT_REG);
1171 DBG (DBG_info, "sane_start: sensor initial type is %s (%d)\n",
1172 sensor_name (dev->sensor), dev->sensor);
1173
1174 /* step 1: locate scan area by doing a scan, then goto calibration area */
1175 /* we also detect if the sensor type is inadequate and then change it */
1176 do
1177 {
1178 changed = SANE_FALSE;
1179 status = find_origin (dev, &changed);
1180 if (status != SANE_STATUS_GOOD)
1181 {
1182 if (dev->conf.allowsharing == SANE_TRUE)
1183 {
1184 sanei_usb_release_interface (dev->devnum, 0);
1185 }
1186 DBG (DBG_error, "sane_start: failed to find origin!\n");
1187 return status;
1188 }
1189
1190 /* in case find_origin detected we need to change sensor */
1191 if (changed)
1192 {
1193 /* for a sensor 'pair', we switch */
1194 switch (dev->sensor)
1195 {
1196 case SENSOR_TYPE_BARE:
1197 DBG (DBG_info,
1198 "sane_start: sensor changed to type 'SENSOR_TYPE_XPA'!\n");
1199 dev->sensor = SENSOR_TYPE_XPA;
1200 break;
1201 case SENSOR_TYPE_XPA:
1202 DBG (DBG_info,
1203 "sane_start: sensor changed to type 'SENSOR_TYPE_BARE'!\n");
1204 dev->sensor = SENSOR_TYPE_BARE;
1205 break;
1206 case SENSOR_TYPE_4400:
1207 DBG (DBG_info,
1208 "sane_start: sensor changed to type '4400 SENSOR_TYPE_4400_BARE'!\n");
1209 dev->sensor = SENSOR_TYPE_4400_BARE;
1210 break;
1211 case SENSOR_TYPE_4400_BARE:
1212 DBG (DBG_info,
1213 "sane_start: sensor changed to type 'SENSOR_TYPE_4400'!\n");
1214 dev->sensor = SENSOR_TYPE_4400;
1215 break;
1216 }
1217 }
1218 }
1219 while (changed);
1220
1221 /* light source to use */
1222 switch (dev->sensor)
1223 {
1224 case SENSOR_TYPE_XPA:
1225 light = 0x3f;
1226 mode = 0x20;
1227 break;
1228 case SENSOR_TYPE_BARE:
1229 light = 0x3b;
1230 mode = 0x20;
1231 break;
1232 case SENSOR_TYPE_4400:
1233 case SENSOR_TYPE_4400_BARE:
1234 light = 0x2a;
1235 mode = 0x10;
1236 break;
1237 default:
1238 light = 0x3b;
1239 mode = 0x20;
1240 break;
1241 }
1242 DBG (DBG_info, "sane_start: sensor final type is %s (%d)\n",
1243 sensor_name (dev->sensor), dev->sensor);
1244 DBG (DBG_info, "sane_start: mode=0x%02x, light=0x%02x\n", mode, light);
1245
1246 /* step 2: dark calibration */
1247 status = dark_calibration (dev, mode, light);
1248 if (status != SANE_STATUS_GOOD)
1249 {
1250 if (dev->conf.allowsharing == SANE_TRUE)
1251 {
1252 sanei_usb_release_interface (dev->devnum, 0);
1253 }
1254 DBG (DBG_error, "sane_start: failed to do dark calibration!\n");
1255 return status;
1256 }
1257
1258 /* step 3: find left margin */
1259 status = find_margin (dev);
1260 if (status != SANE_STATUS_GOOD)
1261 {
1262 if (dev->conf.allowsharing == SANE_TRUE)
1263 {
1264 sanei_usb_release_interface (dev->devnum, 0);
1265 }
1266 DBG (DBG_error, "sane_start: failed find left margin!\n");
1267 return status;
1268 }
1269
1270 /* restore brightness */
1271 dev->regs[LAMP_BRIGHT_REG] = 0xA7;
1272 sanei_rts88xx_write_reg (dev->devnum, LAMP_BRIGHT_REG,
1273 dev->regs + LAMP_BRIGHT_REG);
1274
1275 /* step 4: gain calibration */
1276 status = gain_calibration (dev, mode, light);
1277 if (status != SANE_STATUS_GOOD)
1278 {
1279 if (dev->conf.allowsharing == SANE_TRUE)
1280 {
1281 sanei_usb_release_interface (dev->devnum, 0);
1282 }
1283 DBG (DBG_error, "sane_start: failed to do gain calibration!\n");
1284 return status;
1285 }
1286
1287 /* step 5: fine offset calibration */
1288 status = offset_calibration (dev, mode, light);
1289 if (status != SANE_STATUS_GOOD)
1290 {
1291 if (dev->conf.allowsharing == SANE_TRUE)
1292 {
1293 sanei_usb_release_interface (dev->devnum, 0);
1294 }
1295 DBG (DBG_error, "sane_start: failed to do offset calibration!\n");
1296 return status;
1297 }
1298
1299 /* we compute all the scan parameters so that */
1300 /* we will be able to set up the registers correctly */
1301 compute_parameters (session);
1302
1303 /* allocate buffer and compute start pointer */
1304 if (dev->scanned_data != NULL)
1305 free (dev->scanned_data);
1306 dev->scanned_data =
1307 (SANE_Byte *) malloc (dev->data_size + dev->lds_max + dev->ripple);
1308 dev->start = dev->scanned_data + dev->lds_max + dev->ripple;
1309
1310 /* computes data end pointer */
1311 dev->end = dev->start + dev->data_size;
1312
1313 /* no bytes sent yet to frontend */
1314 session->sent = 0;
1315
1316 sanei_rts88xx_set_offset (dev->regs, dev->red_offset, dev->green_offset,
1317 dev->blue_offset);
1318 sanei_rts88xx_set_gain (dev->regs, dev->red_gain, dev->green_gain,
1319 dev->blue_gain);
1320
1321 /* step 6: shading calibration */
1322 status =
1323 shading_calibration (dev, session->params.format == SANE_FRAME_RGB
1324 || session->emulated_gray == SANE_TRUE, mode, light);
1325 if (status != SANE_STATUS_GOOD)
1326 {
1327 if (dev->conf.allowsharing == SANE_TRUE)
1328 {
1329 sanei_usb_release_interface (dev->devnum, 0);
1330 }
1331 DBG (DBG_error, "sane_start: failed to do shading calibration!\n");
1332 return status;
1333 }
1334
1335 /* step 6b: move at dev->model->min_ydpi to target area */
1336 if (dev->ydpi > dev->model->min_ydpi
1337 && (dev->ystart * MOVE_DPI) / dev->ydpi > 150)
1338 {
1339 status = move_to_scan_area (session);
1340 if (status != SANE_STATUS_GOOD)
1341 {
1342 if (dev->conf.allowsharing == SANE_TRUE)
1343 {
1344 sanei_usb_release_interface (dev->devnum, 0);
1345 }
1346 DBG (DBG_error, "sane_start: failed to move to scan area!\n");
1347 return status;
1348 }
1349 }
1350
1351 /* step 7: effective scan start */
1352 /* build register set and send it */
1353 status = write_scan_registers (session);
1354 if (status != SANE_STATUS_GOOD)
1355 {
1356 if (dev->conf.allowsharing == SANE_TRUE)
1357 {
1358 sanei_usb_release_interface (dev->devnum, 0);
1359 }
1360 DBG (DBG_error, "sane_start: failed to write scan registers!\n");
1361 return status;
1362 }
1363
1364 /* step 8: send calibration data */
1365 status = send_calibration_data (session);
1366 if (status != SANE_STATUS_GOOD)
1367 {
1368 if (dev->conf.allowsharing == SANE_TRUE)
1369 {
1370 sanei_usb_release_interface (dev->devnum, 0);
1371 }
1372 DBG (DBG_error, "sane_start: failed to send calibration data!\n");
1373 return status;
1374 }
1375
1376 /* commit the scan */
1377 /* TODO send_calibration seems to embbed its commit */
1378 sanei_rts88xx_cancel (dev->devnum);
1379 sanei_rts88xx_write_control (dev->devnum, 0x08);
1380 status = sanei_rts88xx_write_control (dev->devnum, 0x08);
1381
1382 session->scanning = SANE_TRUE;
1383
1384 DBG (DBG_proc, "sane_start: exit\n");
1385 return status;
1386 }
1387
1388 /**
1389 * This function computes two set of parameters. The one for the SANE's standard
1390 * and the other for the hardware. Among these parameters are the bit depth, total
1391 * number of lines, total number of columns, extra line to read for data reordering...
1392 */
1393 static SANE_Status
compute_parameters(Rts8891_Session * session)1394 compute_parameters (Rts8891_Session * session)
1395 {
1396 Rts8891_Device *dev = session->dev;
1397 SANE_Int dpi; /* dpi for scan */
1398 SANE_String mode;
1399 SANE_Status status = SANE_STATUS_GOOD;
1400 SANE_Int yshift;
1401 SANE_Int xshift;
1402
1403 int tl_x, tl_y, br_x, br_y;
1404
1405 mode = session->val[OPT_MODE].s;
1406 dpi = session->val[OPT_RESOLUTION].w;
1407
1408 /* scan coordinates */
1409 tl_x = SANE_UNFIX (session->val[OPT_TL_X].w);
1410 tl_y = SANE_UNFIX (session->val[OPT_TL_Y].w);
1411 br_x = SANE_UNFIX (session->val[OPT_BR_X].w);
1412 br_y = SANE_UNFIX (session->val[OPT_BR_Y].w);
1413
1414 /* only single pass scanning supported */
1415 session->params.last_frame = SANE_TRUE;
1416 session->emulated_gray = SANE_FALSE;
1417
1418 /* gray modes */
1419 dev->threshold = (255 * SANE_UNFIX (session->val[OPT_THRESHOLD].w)) / 100;
1420 if (strcmp (mode, GRAY_MODE) == 0 || strcmp (mode, LINEART_MODE) == 0)
1421 {
1422 session->params.format = SANE_FRAME_GRAY;
1423 if (dev->model->flags & RTS8891_FLAG_EMULATED_GRAY_MODE)
1424 session->emulated_gray = SANE_TRUE;
1425 }
1426 else
1427 {
1428 /* Color */
1429 session->params.format = SANE_FRAME_RGB;
1430 }
1431
1432 /* SANE level values */
1433 session->params.lines = ((br_y - tl_y) * dpi) / MM_PER_INCH;
1434 if (session->params.lines == 0)
1435 session->params.lines = 1;
1436 session->params.pixels_per_line = ((br_x - tl_x) * dpi) / MM_PER_INCH;
1437 if (session->params.pixels_per_line == 0)
1438 session->params.pixels_per_line = 1;
1439
1440 DBG (DBG_data, "compute_parameters: pixels_per_line =%d\n",
1441 session->params.pixels_per_line);
1442
1443 if (strcmp (mode, LINEART_MODE) == 0)
1444 {
1445 session->params.depth = 1;
1446 /* in lineart, having pixels multiple of 8 avoids a costly test */
1447 /* at each bit to see we must go to the next byte */
1448 /* TODO : implement this requirement in sane_control_option */
1449 session->params.pixels_per_line =
1450 ((session->params.pixels_per_line + 7) / 8) * 8;
1451 }
1452 else
1453 session->params.depth = 8;
1454
1455 /* width needs to be even */
1456 if (session->params.pixels_per_line & 1)
1457 session->params.pixels_per_line++;
1458
1459 /* Hardware settings : they can differ from the ones at SANE level */
1460 /* for instance the effective DPI used by a sensor may be higher */
1461 /* than the one needed for the SANE scan parameters */
1462 dev->lines = session->params.lines;
1463 dev->pixels = session->params.pixels_per_line;
1464
1465 /* motor and sensor DPI */
1466 dev->xdpi = dpi;
1467 dev->ydpi = dpi;
1468
1469 /* handle bounds of motor's dpi range */
1470 if (dev->ydpi > dev->model->max_ydpi)
1471 {
1472 dev->ydpi = dev->model->max_ydpi;
1473 dev->lines = (dev->lines * dev->model->max_ydpi) / dpi;
1474 if (dev->lines == 0)
1475 dev->lines = 1;
1476
1477 /* round number of lines */
1478 session->params.lines =
1479 (session->params.lines / dev->lines) * dev->lines;
1480 if (session->params.lines == 0)
1481 session->params.lines = 1;
1482 }
1483 if (dev->ydpi < dev->model->min_ydpi)
1484 {
1485 dev->ydpi = dev->model->min_ydpi;
1486 dev->lines = (dev->lines * dev->model->min_ydpi) / dpi;
1487 }
1488
1489 /* hardware values */
1490 dev->xstart =
1491 ((SANE_UNFIX (dev->model->x_offset) + tl_x) * dev->xdpi) / MM_PER_INCH;
1492 dev->ystart =
1493 ((SANE_UNFIX (dev->model->y_offset) + tl_y) * dev->ydpi) / MM_PER_INCH;
1494
1495 /* xstart needs to be even */
1496 if (dev->xstart & 1)
1497 dev->xstart++;
1498
1499 /* computes bytes per line */
1500 session->params.bytes_per_line = session->params.pixels_per_line;
1501 dev->bytes_per_line = dev->pixels;
1502 if (session->params.format == SANE_FRAME_RGB
1503 || session->emulated_gray == SANE_TRUE)
1504 {
1505 if (session->emulated_gray != SANE_TRUE)
1506 {
1507 session->params.bytes_per_line *= 3;
1508 }
1509 dev->bytes_per_line *= 3;
1510 }
1511 session->to_send = session->params.bytes_per_line * session->params.lines;
1512
1513 /* in lineart mode we adjust bytes_per_line needed by frontend */
1514 /* we do that here because we needed sent/to_send to be as if */
1515 /* there was no lineart */
1516 if (session->params.depth == 1)
1517 {
1518 session->params.bytes_per_line =
1519 (session->params.bytes_per_line + 7) / 8;
1520 }
1521
1522 /* compute how many extra bytes we need to reorder data */
1523 dev->ripple = 0;
1524 if (session->params.format == SANE_FRAME_RGB
1525 || session->emulated_gray == SANE_TRUE)
1526 {
1527 dev->lds_r
1528 = ((dev->model->ld_shift_r * dev->ydpi) / dev->model->max_ydpi)
1529 * dev->bytes_per_line;
1530 dev->lds_g
1531 = ((dev->model->ld_shift_g * dev->ydpi) / dev->model->max_ydpi)
1532 * dev->bytes_per_line;
1533 dev->lds_b
1534 = ((dev->model->ld_shift_b * dev->ydpi) / dev->model->max_ydpi)
1535 * dev->bytes_per_line;
1536 if (dev->xdpi == dev->model->max_xdpi)
1537 {
1538 dev->ripple = 2 * dev->bytes_per_line;
1539 }
1540 }
1541 else
1542 {
1543 dev->lds_r = 0;
1544 dev->lds_g = 0;
1545 dev->lds_b = 0;
1546 }
1547
1548 /* pick max lds value */
1549 dev->lds_max = dev->lds_r;
1550 if (dev->lds_g > dev->lds_max)
1551 dev->lds_max = dev->lds_g;
1552 if (dev->lds_b > dev->lds_max)
1553 dev->lds_max = dev->lds_b;
1554
1555 /* since the extra lines for reordering are before data */
1556 /* we subtract lds_max */
1557 dev->lds_r -= dev->lds_max;
1558 dev->lds_g -= dev->lds_max;
1559 dev->lds_b -= dev->lds_max;
1560
1561 /* we need to add extra line to handle line distance reordering */
1562 /* highest correction value is the blue one for our case */
1563 /* decrease y start to take these extra lines into account */
1564 dev->lines += (dev->lds_max + dev->ripple) / dev->bytes_per_line;
1565
1566 /* shading calibration is always 66 lines regardless of ydpi, so */
1567 /* we take this into account to compute ystart */
1568 if (dev->ydpi > dev->model->min_ydpi)
1569 {
1570 /* no that clean, but works ... */
1571 switch (dev->ydpi)
1572 {
1573 case 300:
1574 yshift = 0;
1575 break;
1576 case 600:
1577 yshift = 33;
1578 break;
1579 default:
1580 yshift = 0;
1581 }
1582 dev->ystart += yshift;
1583 }
1584 dev->ystart -= (dev->lds_max + dev->ripple) / dev->bytes_per_line;
1585
1586 /* 1200 and 600 dpi scans seems to have other timings that
1587 * need their own xstart */
1588 /* no that clean, but works ... */
1589 switch (dev->xdpi)
1590 {
1591 case 600:
1592 xshift = -38;
1593 break;
1594 case 1200:
1595 xshift = -76;
1596 break;
1597 default:
1598 xshift = 0;
1599 }
1600 dev->xstart += xshift;
1601
1602 dev->read = 0;
1603 dev->to_read = dev->lines * dev->bytes_per_line;
1604
1605 /* compute best size for scanned data buffer */
1606 /* we must have a round number of lines, with */
1607 /* enough space to handle line distance shift */
1608 if (dev->xdpi < dev->model->max_ydpi)
1609 {
1610 dev->data_size =
1611 (PREFERED_BUFFER_SIZE / dev->bytes_per_line) * (dev->bytes_per_line);
1612 }
1613 else
1614 {
1615 dev->data_size =
1616 (((PREFERED_BUFFER_SIZE / 2) - dev->lds_max -
1617 dev->ripple) / dev->bytes_per_line) * dev->bytes_per_line;
1618 }
1619
1620 /* 32 lines minimum in buffer */
1621 if (dev->data_size < 32 * dev->bytes_per_line)
1622 dev->data_size = 32 * dev->bytes_per_line;
1623
1624 /* buffer must be smaller than total amount to read from session */
1625 if (dev->data_size > dev->to_read)
1626 dev->data_size = dev->to_read;
1627
1628 DBG (DBG_data, "compute_parameters: bytes_per_line =%d\n",
1629 session->params.bytes_per_line);
1630 DBG (DBG_data, "compute_parameters: depth =%d\n",
1631 session->params.depth);
1632 DBG (DBG_data, "compute_parameters: lines =%d\n",
1633 session->params.lines);
1634 DBG (DBG_data, "compute_parameters: pixels_per_line =%d\n",
1635 session->params.pixels_per_line);
1636 DBG (DBG_data, "compute_parameters: image size =%d\n",
1637 session->to_send);
1638
1639 DBG (DBG_data, "compute_parameters: xstart =%d\n", dev->xstart);
1640 DBG (DBG_data, "compute_parameters: ystart =%d\n", dev->ystart);
1641 DBG (DBG_data, "compute_parameters: dev lines =%d\n", dev->lines);
1642 DBG (DBG_data, "compute_parameters: dev extra lines =%d\n",
1643 (dev->lds_max + dev->ripple) / dev->bytes_per_line);
1644 DBG (DBG_data, "compute_parameters: dev bytes per line=%d\n",
1645 dev->bytes_per_line);
1646 DBG (DBG_data, "compute_parameters: dev pixels =%d\n", dev->pixels);
1647 DBG (DBG_data, "compute_parameters: data size =%d\n",
1648 dev->data_size);
1649 DBG (DBG_data, "compute_parameters: to read =%d\n", dev->to_read);
1650 DBG (DBG_data, "compute_parameters: threshold =%d\n",
1651 dev->threshold);
1652
1653 return status;
1654 }
1655
1656
1657 /**
1658 * Called by SANE to retrieve information about the type of data
1659 * that the current scan will return.
1660 *
1661 * From the SANE spec:
1662 * This function is used to obtain the current scan parameters. The
1663 * returned parameters are guaranteed to be accurate between the time
1664 * a scan has been started (sane_start() has been called) and the
1665 * completion of that request. Outside of that window, the returned
1666 * values are best-effort estimates of what the parameters will be
1667 * when sane_start() gets invoked.
1668 *
1669 * Calling this function before a scan has actually started allows,
1670 * for example, to get an estimate of how big the scanned image will
1671 * be. The parameters passed to this function are the handle of the
1672 * device for which the parameters should be obtained and a pointer
1673 * to a parameter structure.
1674 */
1675 SANE_Status
sane_get_parameters(SANE_Handle handle, SANE_Parameters * params)1676 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
1677 {
1678 SANE_Status status;
1679 struct Rts8891_Session *session = (struct Rts8891_Session *) handle;
1680
1681 DBG (DBG_proc, "sane_get_parameters: start\n");
1682
1683 /* call parameters computing function */
1684 status = compute_parameters (session);
1685 if (status == SANE_STATUS_GOOD && params)
1686 *params = session->params;
1687
1688 DBG (DBG_proc, "sane_get_parameters: exit\n");
1689 return status;
1690 }
1691
1692
1693 /**
1694 * Called by SANE to read data.
1695 *
1696 * From the SANE spec:
1697 * This function is used to read image data from the device
1698 * represented by handle h. Argument buf is a pointer to a memory
1699 * area that is at least maxlen bytes long. The number of bytes
1700 * returned is stored in *len. A backend must set this to zero when
1701 * the call fails (i.e., when a status other than SANE_STATUS_GOOD is
1702 * returned).
1703 *
1704 * When the call succeeds, the number of bytes returned can be
1705 * anywhere in the range from 0 to maxlen bytes.
1706 */
1707 SANE_Status
sane_read(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len)1708 sane_read (SANE_Handle handle, SANE_Byte * buf,
1709 SANE_Int max_len, SANE_Int * len)
1710 {
1711 struct Rts8891_Session *session;
1712 struct Rts8891_Device *dev;
1713 SANE_Status status;
1714 SANE_Int length;
1715 SANE_Int data_size;
1716 SANE_Byte val = 0;
1717 SANE_Int bit;
1718
1719 DBG (DBG_proc, "sane_read: start\n");
1720 DBG (DBG_io, "sane_read: up to %d bytes required by frontend\n", max_len);
1721
1722 /* some sanity checks first to protect from would be buggy frontends */
1723 if (!handle)
1724 {
1725 DBG (DBG_error, "sane_read: handle is null!\n");
1726 return SANE_STATUS_INVAL;
1727 }
1728
1729 session = (struct Rts8891_Session *) handle;
1730 if (!session)
1731 {
1732 DBG (DBG_error, "sane_read: session is null!\n");
1733 return SANE_STATUS_INVAL;
1734 }
1735 dev = session->dev;
1736
1737 if (!buf)
1738 {
1739 DBG (DBG_error, "sane_read: buf is null!\n");
1740 return SANE_STATUS_INVAL;
1741 }
1742
1743 if (!len)
1744 {
1745 DBG (DBG_error, "sane_read: len is null!\n");
1746 return SANE_STATUS_INVAL;
1747 }
1748
1749 /* no data read yet */
1750 *len = 0;
1751 buf[*len] = 0;
1752
1753 /* check if session is scanning */
1754 if (!session->scanning)
1755 {
1756 DBG (DBG_warn,
1757 "sane_read: scan was cancelled, is over or has not been initiated yet\n");
1758 return SANE_STATUS_CANCELLED;
1759 }
1760
1761 /* check for EOF, must be done before any physical read */
1762 if (session->sent >= session->to_send)
1763 {
1764 DBG (DBG_io, "sane_read: end of scan reached\n");
1765
1766 /* signal end of scanning */
1767 session->scanning=SANE_FALSE;
1768
1769 /* send asynchronous head parking command then return */
1770 park_head (session->dev, SANE_FALSE);
1771 return SANE_STATUS_EOF;
1772 }
1773
1774 dev->regs[LAMP_REG] = 0xad;
1775 sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, &(dev->regs[LAMP_REG]));
1776
1777 /* byte length for high dpi mode */
1778 length = (session->params.bytes_per_line * 8) / session->params.depth;
1779
1780 /* checks if buffer has been pre filled with the extra data needed for */
1781 /* line distance reordering */
1782 if (dev->read == 0
1783 && (session->params.format == SANE_FRAME_RGB
1784 || session->emulated_gray == SANE_TRUE))
1785 {
1786 /* the data need if the size of the highest line distance shift */
1787 /* we must only read what's needed */
1788 data_size = dev->data_size + dev->lds_max + dev->ripple;
1789 if (dev->to_read - dev->read < data_size)
1790 data_size = dev->to_read - dev->read;
1791
1792 status = read_data (session, dev->scanned_data, data_size);
1793 if (status == SANE_STATUS_DEVICE_BUSY)
1794 {
1795 DBG (DBG_io, "sane_read: no data currently available\n");
1796 return SANE_STATUS_GOOD;
1797 }
1798 if (status != SANE_STATUS_GOOD)
1799 {
1800 DBG (DBG_error, "sane_read: failed to read data from scanner\n");
1801 return status;
1802 }
1803
1804 /* now buffer is filled with data and an extra amount for line reordering */
1805 dev->current = dev->start;
1806 }
1807
1808 /* if all buffer has been used, get the next block of data from scanner */
1809 if (dev->read == 0 || dev->current >= dev->end)
1810 {
1811 /* effective buffer filling */
1812 /* we must only read what's needed */
1813 data_size = dev->data_size;
1814 if (dev->to_read - dev->read < data_size)
1815 data_size = dev->to_read - dev->read;
1816
1817 status = read_data (session, dev->start, data_size);
1818 if (status == SANE_STATUS_DEVICE_BUSY)
1819 {
1820 DBG (DBG_io, "sane_read: no data currently available\n");
1821 return SANE_STATUS_GOOD;
1822 }
1823 if (status != SANE_STATUS_GOOD)
1824 {
1825 DBG (DBG_error, "sane_read: failed to read data from scanner\n");
1826 return status;
1827 }
1828
1829 /* reset current pointer */
1830 dev->current = dev->start;
1831 }
1832
1833 dev->regs[LAMP_REG] = 0x8d;
1834 sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, &(dev->regs[LAMP_REG]));
1835
1836 /* it seems there is no gray or lineart hardware mode for the rts8891 */
1837 if (session->params.format == SANE_FRAME_GRAY
1838 && session->emulated_gray == SANE_FALSE)
1839 {
1840 DBG (DBG_error0, "sane_read: unimplemented native gray scanning\n");
1841 return SANE_STATUS_INVAL;
1842 }
1843 else /* hardware data is 3 bytes/per pixels */
1844 {
1845 /* we return as much data as possible from current buffer */
1846 /* if buffer is smaller than what is asked, we only return */
1847
1848 /* here we have made sure there is something to read from data buffers */
1849 /* data from scanner is in R,G,B format, but we have to cope with line */
1850 /* distance correction. We also take care that motor resolution may be */
1851 /* higher than the scan resolution asked for some modes. */
1852 /* We also handle emulated color mode */
1853
1854 /* we loop until we reach max_len or end of data buffer */
1855 /* or we sent what we advised to frontend */
1856 while (dev->current < dev->end && *len < max_len
1857 && session->sent < session->to_send)
1858 {
1859 /* data is received in RGB format */
1860 /* these switches are there to handle reads not aligned
1861 * on pixels that are allowed by the SANE standard */
1862 if (dev->xdpi == dev->model->max_xdpi)
1863 { /* at max xdpi, data received is distorted and ydpi is half of xdpi */
1864 if (session->emulated_gray == SANE_TRUE)
1865 {
1866 /* in emulated gray mode we are always reading 3 bytes of raw data */
1867 /* at a time */
1868 switch (((session->sent * 3) % dev->bytes_per_line) % 6)
1869 {
1870 case 0:
1871 case 1:
1872 case 2:
1873 val = dev->current[dev->lds_g];
1874 break;
1875 case 3:
1876 case 4:
1877 case 5:
1878 val = dev->current[dev->lds_g - dev->ripple];
1879 break;
1880 }
1881
1882 if (session->params.depth == 1)
1883 {
1884 bit = 7 - (session->sent) % 8;
1885 if (val <= dev->threshold)
1886 {
1887 buf[*len] |= 1 << bit;
1888 }
1889 if (bit == 0)
1890 {
1891 (*len)++;
1892 buf[*len] = 0;
1893 }
1894 }
1895 else
1896 {
1897 buf[*len] = val;
1898 (*len)++;
1899 }
1900 session->sent++;
1901 dev->current += 3;
1902 }
1903 else
1904 {
1905 switch ((session->sent % dev->bytes_per_line) % 6)
1906 {
1907 case 0:
1908 buf[*len] = dev->current[dev->lds_r];
1909 break;
1910 case 1:
1911 buf[*len] = dev->current[dev->lds_g];
1912 break;
1913 case 2:
1914 buf[*len] = dev->current[dev->lds_b];
1915 break;
1916 case 3:
1917 buf[*len] = dev->current[dev->lds_r - dev->ripple];
1918 break;
1919 case 4:
1920 buf[*len] = dev->current[dev->lds_g - dev->ripple];
1921 break;
1922 case 5:
1923 buf[*len] = dev->current[dev->lds_b - dev->ripple];
1924 break;
1925 }
1926 (*len)++;
1927 session->sent++;
1928 dev->current++;
1929 }
1930
1931 /* we currently double lines to have match xdpy */
1932 /* so we logically rewind for each odd line */
1933 /* we test at start of a scanned picture line */
1934 if (((session->sent / length) % 2 == 1)
1935 && (session->sent % length == 0))
1936 {
1937 DBG (DBG_io,
1938 "sane_read: rewind by %d bytes after %d bytes sent\n",
1939 dev->bytes_per_line, session->sent);
1940 dev->current -= dev->bytes_per_line;
1941 }
1942 }
1943 else if (dev->ydpi == session->val[OPT_RESOLUTION].w)
1944 {
1945 if (session->emulated_gray == SANE_TRUE)
1946 {
1947 /* in emulated gray mode we are always reading 3 bytes of raw data */
1948 /* at a time, so we know where we are */
1949 val = dev->current[dev->lds_g];
1950 if (session->params.depth == 1)
1951 {
1952 bit = 7 - (session->sent) % 8;
1953 if (val <= dev->threshold)
1954 {
1955 buf[*len] |= 1 << bit;
1956 }
1957 else
1958 {
1959 buf[*len] &= ~(1 << bit);
1960 }
1961 if (bit == 0)
1962 {
1963 (*len)++;
1964 }
1965 }
1966 else
1967 {
1968 buf[*len] = val;
1969 (*len)++;
1970 }
1971 session->sent++;
1972 dev->current += 3;
1973 }
1974 else
1975 {
1976 switch ((dev->current - dev->start) % 3)
1977 {
1978 case 0:
1979 buf[*len] = dev->current[dev->lds_r];
1980 break;
1981 case 1:
1982 buf[*len] = dev->current[dev->lds_g];
1983 break;
1984 case 2:
1985 buf[*len] = dev->current[dev->lds_b];
1986 break;
1987 }
1988 (*len)++;
1989 session->sent++;
1990 dev->current++;
1991 }
1992 }
1993 else
1994 {
1995 /* we currently handle ydi=2*dpi */
1996 if (session->emulated_gray == SANE_TRUE)
1997 {
1998 /* in emulated gray mode we are always reading 3 bytes of raw data */
1999 /* at a time, so we know where we are */
2000 val = (dev->current[dev->lds_g]
2001 + dev->current[dev->lds_g +
2002 dev->bytes_per_line]) / 2;
2003 if (session->params.depth == 1)
2004 {
2005 bit = 7 - (session->sent) % 8;
2006 if (val <= dev->threshold)
2007 {
2008 buf[*len] |= 1 << bit;
2009 }
2010 else
2011 {
2012 buf[*len] &= ~(1 << bit);
2013 }
2014 if (bit == 0)
2015 {
2016 (*len)++;
2017 }
2018 }
2019 else
2020 {
2021 buf[*len] = val;
2022 (*len)++;
2023 }
2024 dev->current += 3;
2025 }
2026 else
2027 {
2028 switch ((dev->current - dev->start) % 3)
2029 {
2030 case 0:
2031 buf[*len] = (dev->current[dev->lds_r]
2032 + dev->current[dev->lds_r +
2033 dev->bytes_per_line]) / 2;
2034 break;
2035 case 1:
2036 buf[*len] = (dev->current[dev->lds_g]
2037 + dev->current[dev->lds_g +
2038 dev->bytes_per_line]) / 2;
2039 break;
2040 case 2:
2041 buf[*len] = (dev->current[dev->lds_b]
2042 + dev->current[dev->lds_b +
2043 dev->bytes_per_line]) / 2;
2044 break;
2045 }
2046 (*len)++;
2047 dev->current++;
2048 }
2049 session->sent++;
2050
2051 /* at the end of each line, we must count another one because */
2052 /* 2 lines are used to produce one */
2053 if ((dev->current - dev->start) % dev->bytes_per_line == 0)
2054 dev->current += dev->bytes_per_line;
2055 }
2056 }
2057 }
2058
2059 /* if we exhausted data buffer, we prepare for the next read */
2060 /* in color mode, we need to copy the remainder of the */
2061 /* buffer because of line distance handling, when blue data */
2062 /* is exhausted, read and green haven't been fully read yet */
2063 if (dev->current >= dev->end
2064 && (session->params.format == SANE_FRAME_RGB
2065 || session->emulated_gray == SANE_TRUE))
2066 {
2067 memcpy (dev->scanned_data, dev->end - (dev->lds_max + dev->ripple),
2068 dev->lds_max + dev->ripple);
2069 }
2070
2071 status = SANE_STATUS_GOOD;
2072 DBG (DBG_io, "sane_read: sent %d bytes to frontend\n", *len);
2073 DBG (DBG_proc, "sane_read: exit\n");
2074 return status;
2075 }
2076
2077
2078 /**
2079 * Cancels a scan.
2080 *
2081 * From the SANE spec:
2082 * This function is used to immediately or as quickly as possible
2083 * cancel the currently pending operation of the device represented by
2084 * handle h. This function can be called at any time (as long as
2085 * handle h is a valid handle) but usually affects long-running
2086 * operations only (such as image is acquisition). It is safe to call
2087 * this function asynchronously (e.g., from within a signal handler).
2088 * It is important to note that completion of this operation does not
2089 * imply that the currently pending operation has been cancelled. It
2090 * only guarantees that cancellation has been initiated. Cancellation
2091 * completes only when the cancelled call returns (typically with a
2092 * status value of SANE_STATUS_CANCELLED). Since the SANE API does
2093 * not require any other operations to be re-entrant, this implies
2094 * that a frontend must not call any other operation until the
2095 * cancelled operation has returned.
2096 */
2097 void
sane_cancel(SANE_Handle handle)2098 sane_cancel (SANE_Handle handle)
2099 {
2100 Rts8891_Session *session = handle;
2101 struct Rts8891_Device *dev = session->dev;
2102 #ifdef HAVE_SYS_TIME_H
2103 struct timeval current;
2104 #endif
2105
2106 DBG (DBG_proc, "sane_cancel: start\n");
2107
2108 #ifdef HAVE_SYS_TIME_H
2109 /* store last scan time for the device */
2110 gettimeofday (¤t, NULL);
2111 dev->last_scan.tv_sec = current.tv_sec;
2112 #endif
2113
2114 /* if scanning, abort and park head */
2115 if (session->scanning == SANE_TRUE)
2116 {
2117 /* canceling while all data hasn't bee read */
2118 if (dev->read < dev->to_read)
2119 {
2120 sanei_rts88xx_cancel (dev->devnum);
2121 usleep (500000);
2122 sanei_rts88xx_cancel (dev->devnum);
2123 }
2124 session->scanning = SANE_FALSE;
2125
2126 /* head parking */
2127 if (park_head (dev, SANE_FALSE) != SANE_STATUS_GOOD)
2128 {
2129 DBG (DBG_error, "sane_cancel: failed to park head!\n");
2130 }
2131 }
2132
2133 /* free resources used by scanning */
2134 if (dev->scanned_data != NULL)
2135 {
2136 free (dev->scanned_data);
2137 dev->scanned_data = NULL;
2138 }
2139 if (dev->shading_data != NULL)
2140 {
2141 free (dev->shading_data);
2142 dev->shading_data = NULL;
2143 }
2144
2145 /* release the interface to allow device sharing */
2146 if (dev->conf.allowsharing == SANE_TRUE)
2147 {
2148 sanei_usb_release_interface (dev->devnum, 0);
2149 }
2150
2151 DBG (DBG_proc, "sane_cancel: exit\n");
2152 }
2153
2154
2155 /**
2156 * Ends use of the session.
2157 *
2158 * From the SANE spec:
2159 * This function terminates the association between the device handle
2160 * passed in argument h and the device it represents. If the device is
2161 * presently active, a call to sane_cancel() is performed first. After
2162 * this function returns, handle h must not be used anymore.
2163 *
2164 * Handle resources are free'd before disposing the handle. But devices
2165 * resources must not be mdofied, since it could be used or reused until
2166 * sane_exit() is called.
2167 */
2168 void
sane_close(SANE_Handle handle)2169 sane_close (SANE_Handle handle)
2170 {
2171 Rts8891_Session *prev, *session;
2172 Rts8891_Device *dev;
2173 int i;
2174
2175 DBG (DBG_proc, "sane_close: start\n");
2176
2177 /* remove handle from list of open handles: */
2178 prev = NULL;
2179 for (session = first_handle; session; session = session->next)
2180 {
2181 if (session == handle)
2182 break;
2183 prev = session;
2184 }
2185 if (!session)
2186 {
2187 DBG (DBG_error, "close: invalid handle %p\n", handle);
2188 return; /* oops, not a handle we know about */
2189 }
2190
2191 dev=session->dev;
2192
2193 /* cancel any active scan */
2194 if (session->scanning == SANE_TRUE)
2195 {
2196 sane_cancel (handle);
2197 }
2198 /* if head is parking, wait for completion */
2199 if(dev->parking==SANE_TRUE)
2200 {
2201 rts8891_wait_for_home (dev, dev->regs);
2202 }
2203 set_lamp_brightness (dev, 0);
2204
2205
2206 if (prev)
2207 prev->next = session->next;
2208 else
2209 first_handle = session->next;
2210
2211 /* switch off lamp and close usb */
2212 if (dev->conf.allowsharing == SANE_TRUE)
2213 {
2214 SANE_Status status = sanei_usb_claim_interface (dev->devnum, 0);
2215 if (status != SANE_STATUS_GOOD)
2216 {
2217 DBG (DBG_warn, "sane_close: cannot claim usb interface: %s\n",
2218 sane_strstatus(status));
2219 DBG (DBG_warn, "sane_close: continuing anyway\n");
2220 }
2221 }
2222 set_lamp_state (session, 0);
2223 sanei_usb_close (dev->devnum);
2224
2225 /* free per session data */
2226 if (session->dev->model->gamma != session->val[OPT_GAMMA_VECTOR].wa)
2227 free (session->val[OPT_GAMMA_VECTOR].wa);
2228 if (session->dev->model->gamma != session->val[OPT_GAMMA_VECTOR_R].wa)
2229 free (session->val[OPT_GAMMA_VECTOR_R].wa);
2230 if (session->dev->model->gamma != session->val[OPT_GAMMA_VECTOR_G].wa)
2231 free (session->val[OPT_GAMMA_VECTOR_G].wa);
2232 if (session->dev->model->gamma != session->val[OPT_GAMMA_VECTOR_B].wa)
2233 free (session->val[OPT_GAMMA_VECTOR_B].wa);
2234 free (session->val[OPT_MODE].s);
2235 free ((void *) session->opt[OPT_RESOLUTION].constraint.word_list);
2236 for (i = OPT_BUTTON_1; i <= OPT_BUTTON_11; i++)
2237 {
2238 free ((void *) session->opt[i].name);
2239 free ((void *) session->opt[i].title);
2240 }
2241
2242 free (session);
2243
2244 DBG (DBG_proc, "sane_close: exit\n");
2245 }
2246
2247
2248 /**
2249 * Terminates the backend.
2250 *
2251 * From the SANE spec:
2252 * This function must be called to terminate use of a backend. The
2253 * function will first close all device handles that still might be
2254 * open (it is recommended to close device handles explicitly through
2255 * a call to sane_close(), but backends are required to release all
2256 * resources upon a call to this function). After this function
2257 * returns, no function other than sane_init() may be called
2258 * (regardless of the status value returned by sane_exit(). Neglecting
2259 * to call this function may result in some resources not being
2260 * released properly.
2261 */
2262 void
sane_exit(void)2263 sane_exit (void)
2264 {
2265 struct Rts8891_Session *session, *next;
2266 struct Rts8891_Device *dev, *nextdev;
2267 int i;
2268
2269 DBG (DBG_proc, "sane_exit: start\n");
2270
2271 /* free session structs */
2272 for (session = first_handle; session; session = next)
2273 {
2274 next = session->next;
2275 sane_close ((SANE_Handle *) session);
2276 free (session);
2277 }
2278 first_handle = NULL;
2279
2280 /* free devices structs */
2281 for (dev = first_device; dev; dev = nextdev)
2282 {
2283 nextdev = dev->next;
2284 free (dev->file_name);
2285 free (dev);
2286 }
2287 first_device = NULL;
2288
2289 /* now list of devices */
2290 if (devlist)
2291 {
2292 for (i = 0; i < num_devices; i++)
2293 {
2294 free ((SANE_Device *) devlist[i]);
2295 }
2296 free (devlist);
2297 devlist = NULL;
2298 }
2299 num_devices = 0;
2300
2301 DBG (DBG_proc, "sane_exit: exit\n");
2302 }
2303
2304
2305 /** This function tries to find plugged relevant devices
2306 */
2307 static SANE_Status
probe_rts8891_devices(void)2308 probe_rts8891_devices (void)
2309 {
2310 /**> configuration structure used during attach */
2311 SANEI_Config config;
2312 /**> list of configuration options */
2313 SANE_Option_Descriptor *options[NUM_CFG_OPTIONS];
2314 /**> placeholders pointers for option values */
2315 void *values[NUM_CFG_OPTIONS];
2316 int i;
2317 SANE_Status status;
2318
2319 DBG (DBG_proc, "probe_rts8891_devices: start\n");
2320
2321 /* sharing is off by default and no model option */
2322 rtscfg.allowsharing = SANE_FALSE;
2323 rtscfg.modelnumber = -1;
2324 rtscfg.sensornumber = -1;
2325
2326 /* initialize configuration options */
2327 options[CFG_MODEL_NUMBER] =
2328 (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor));
2329 options[CFG_MODEL_NUMBER]->name = "modelnumber";
2330 options[CFG_MODEL_NUMBER]->desc =
2331 "user provided scanner's internal model number";
2332 options[CFG_MODEL_NUMBER]->type = SANE_TYPE_INT;
2333 options[CFG_MODEL_NUMBER]->unit = SANE_UNIT_NONE;
2334 options[CFG_MODEL_NUMBER]->size = sizeof (SANE_Word);
2335 options[CFG_MODEL_NUMBER]->cap = SANE_CAP_SOFT_SELECT;
2336 options[CFG_MODEL_NUMBER]->constraint_type = SANE_CONSTRAINT_RANGE;
2337 options[CFG_MODEL_NUMBER]->constraint.range = &model_range;
2338 values[CFG_MODEL_NUMBER] = &rtscfg.modelnumber;
2339
2340 options[CFG_ALLOW_SHARING] =
2341 (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor));
2342 options[CFG_ALLOW_SHARING]->name = "allowsharing";
2343 options[CFG_ALLOW_SHARING]->desc =
2344 "allow sharing of the scanner by several frontends";
2345 options[CFG_ALLOW_SHARING]->type = SANE_TYPE_BOOL;
2346 options[CFG_ALLOW_SHARING]->unit = SANE_UNIT_NONE;
2347 options[CFG_ALLOW_SHARING]->size = sizeof (SANE_Bool);
2348 options[CFG_ALLOW_SHARING]->cap = SANE_CAP_SOFT_SELECT;
2349 options[CFG_ALLOW_SHARING]->constraint_type = SANE_CONSTRAINT_NONE;
2350 values[CFG_ALLOW_SHARING] = &rtscfg.allowsharing;
2351
2352 /* sensor type override */
2353 options[CFG_SENSOR_NUMBER] =
2354 (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor));
2355 options[CFG_SENSOR_NUMBER]->name = "sensornumber";
2356 options[CFG_SENSOR_NUMBER]->desc =
2357 "user provided scanner's internal sensor number";
2358 options[CFG_SENSOR_NUMBER]->type = SANE_TYPE_INT;
2359 options[CFG_SENSOR_NUMBER]->unit = SANE_UNIT_NONE;
2360 options[CFG_SENSOR_NUMBER]->size = sizeof (SANE_Word);
2361 options[CFG_SENSOR_NUMBER]->cap = SANE_CAP_SOFT_SELECT;
2362 options[CFG_SENSOR_NUMBER]->constraint_type = SANE_CONSTRAINT_RANGE;
2363 options[CFG_SENSOR_NUMBER]->constraint.range = &sensor_range;
2364 values[CFG_SENSOR_NUMBER] = &rtscfg.sensornumber;
2365
2366 /* set configuration options structure */
2367 config.descriptors = options;
2368 config.values = values;
2369 config.count = NUM_CFG_OPTIONS;
2370
2371 /* init usb use */
2372 sanei_usb_init ();
2373
2374 /* generic configure and attach function */
2375 status = sanei_configure_attach (RTS8891_CONFIG_FILE, &config,
2376 config_attach_rts8891, NULL);
2377 /* free allocated options */
2378 for (i = 0; i < NUM_CFG_OPTIONS; i++)
2379 {
2380 free (options[i]);
2381 }
2382
2383 DBG (DBG_proc, "probe_rts8891_devices: end\n");
2384 return status;
2385 }
2386
2387 /** This function is called by sanei_configure_attach to try
2388 * to attach the backend to a device specified by the configuration file.
2389 *
2390 * @param config configuration structure filled with values read
2391 * from configuration file
2392 * @param devname name of the device to try to attach to, it is
2393 * the unprocessed line of the configuration file
2394 *
2395 * @return status SANE_STATUS_GOOD if no errors (even if no matching
2396 * devices found)
2397 * SANE_STATUS_INVAL in case of error
2398 */
2399 static SANE_Status
config_attach_rts8891(SANEI_Config * config, const char *devname, void __sane_unused__ *data)2400 config_attach_rts8891 (SANEI_Config * config, const char *devname,
2401 void __sane_unused__ *data)
2402 {
2403 /* currently, the config is a global variable so config is useless here */
2404 /* the correct thing would be to have a generic sanei_attach_matching_devices
2405 * using an attach function with a config parameter */
2406 if(config==NULL)
2407 {
2408 return SANE_STATUS_INVAL;
2409 }
2410
2411 /* the devname has been processed and is ready to be used
2412 * directly. Since the backend is an USB only one, we can
2413 * call sanei_usb_attach_matching_devices straight */
2414 sanei_usb_attach_matching_devices (devname, attach_rts8891);
2415
2416 return SANE_STATUS_GOOD;
2417 }
2418
2419 /**
2420 * The attach tries to open the given usb device and match it
2421 * with devices handled by the backend. The configuration parameter
2422 * contains the values of the already parsed configuration options
2423 * from the conf file.
2424 * @param config configuration structure filled with values read
2425 * from configuration file
2426 * @param devicename name of the device to try to attach to, it is
2427 * the unprocessed line of the configuration file
2428 *
2429 * @return status SANE_STATUS_GOOD if no errors (even if no matching
2430 * devices found)
2431 * SANE_STATUS_NOM_MEM if there isn't enough memory to allocate the
2432 * device structure
2433 * SANE_STATUS_UNSUPPORTED if the device if unknown by the backend
2434 * SANE_STATUS_INVAL in case of other error
2435 */
2436 static SANE_Status
attach_rts8891(const char *devicename)2437 attach_rts8891 (const char *devicename)
2438 {
2439 struct Rts8891_Device *device;
2440 SANE_Int dn, vendor, product;
2441 SANE_Status status;
2442
2443 DBG (DBG_proc, "attach_rts8891(%s): start\n", devicename);
2444
2445 /* search if we already have it attached */
2446 for (device = first_device; device; device = device->next)
2447 {
2448 if (strcmp (device->file_name, devicename) == 0)
2449 {
2450 DBG (DBG_warn,
2451 "attach_rts8891: device already attached (is ok)!\n");
2452 DBG (DBG_proc, "attach_rts8891: exit\n");
2453 return SANE_STATUS_GOOD;
2454 }
2455 }
2456
2457 /* open usb device */
2458 status = sanei_usb_open (devicename, &dn);
2459 if (status != SANE_STATUS_GOOD)
2460 {
2461 DBG (DBG_error, "attach_rts8891: couldn't open device `%s': %s\n",
2462 devicename, sane_strstatus (status));
2463 return status;
2464 }
2465 else
2466 {
2467 DBG (DBG_info, "attach_rts8891: device `%s' successfully opened\n",
2468 devicename);
2469 }
2470
2471 /* get vendor and product id */
2472 status = sanei_usb_get_vendor_product (dn, &vendor, &product);
2473 if (status != SANE_STATUS_GOOD)
2474 {
2475 DBG (DBG_error,
2476 "attach_rts8891: couldn't get vendor and product ids of device `%s': %s\n",
2477 devicename, sane_strstatus (status));
2478 sanei_usb_close (dn);
2479 DBG (DBG_proc, "attach_rts8891: exit\n");
2480 return status;
2481 }
2482 sanei_usb_close (dn);
2483
2484 /* get the index of the device in the device description table */
2485 /* if the value is provided by configuration option, just use it */
2486 if (rtscfg.modelnumber < 0)
2487 {
2488 /* walk the list of devices to find matching entry */
2489 dn = 0;
2490 while ((vendor != rts8891_usb_device_list[dn].vendor_id
2491 || product != rts8891_usb_device_list[dn].product_id)
2492 && (rts8891_usb_device_list[dn].vendor_id != 0))
2493 dn++;
2494 /* if we reach the list termination entry, the device is unknown */
2495 if (rts8891_usb_device_list[dn].vendor_id == 0)
2496 {
2497 DBG (DBG_info,
2498 "attach_rts8891: unknown device `%s': 0x%04x:0x%04x\n",
2499 devicename, vendor, product);
2500 DBG (DBG_proc, "attach_rts8891: exit\n");
2501 return SANE_STATUS_UNSUPPORTED;
2502 }
2503 }
2504 else
2505 {
2506 /* user provided value */
2507 dn = rtscfg.modelnumber;
2508 }
2509
2510 /* allocate device struct */
2511 device = malloc (sizeof (*device));
2512 if (device == NULL)
2513 {
2514 return SANE_STATUS_NO_MEM;
2515 }
2516 memset (device, 0, sizeof (*device));
2517
2518 /* struct describing low lvel device */
2519 device->model = rts8891_usb_device_list[dn].model;
2520
2521 /* name of the device */
2522 device->file_name = strdup (devicename);
2523
2524 DBG (DBG_info, "attach_rts8891: found %s %s %s at %s\n",
2525 device->model->vendor,
2526 device->model->product, device->model->type, device->file_name);
2527
2528 /* we insert new device at start of the chained list */
2529 /* head of the list becomes the next, and start is replaced */
2530 /* with the new session struct */
2531 num_devices++;
2532 device->next = first_device;
2533 first_device = device;
2534
2535 device->reg_count = 244;
2536 /* initialization is done at sane_open */
2537 device->initialized = SANE_FALSE;
2538 device->needs_warming = SANE_TRUE;
2539 device->parking = SANE_FALSE;
2540 #ifdef HAVE_SYS_TIME_H
2541 device->last_scan.tv_sec = 0;
2542 device->start_time.tv_sec = 0;
2543 #endif
2544
2545 /* in case autodection au sensor doesn't work, use the given override */
2546 device->sensor = rtscfg.sensornumber;
2547
2548 /* copy configuration settings to device */
2549 device->conf.modelnumber = dn;
2550 device->conf.allowsharing = rtscfg.allowsharing;
2551
2552 DBG (DBG_proc, "attach_rts8891: exit\n");
2553 return SANE_STATUS_GOOD;
2554 }
2555
2556
2557 /* set initial value for the scanning options */
2558 static SANE_Status
init_options(struct Rts8891_Session *session)2559 init_options (struct Rts8891_Session *session)
2560 {
2561 SANE_Int option, count, i, min, idx;
2562 SANE_Word *dpi_list;
2563 Rts8891_Model *model = session->dev->model;
2564
2565 DBG (DBG_proc, "init_options: start\n");
2566
2567 /* we first initialize each options with a default value */
2568 memset (session->opt, 0, sizeof (session->opt));
2569 memset (session->val, 0, sizeof (session->val));
2570
2571 for (option = 0; option < NUM_OPTIONS; option++)
2572 {
2573 session->opt[option].size = sizeof (SANE_Word);
2574 session->opt[option].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
2575 }
2576
2577 /* we set up all the options listed in the Rts8891_Option enum */
2578
2579 /* last option / end of list marker */
2580 session->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS;
2581 session->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
2582 session->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
2583 session->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
2584 session->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
2585 session->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
2586
2587 /* "Standard" group: */
2588 session->opt[OPT_STANDARD_GROUP].title = SANE_TITLE_STANDARD;
2589 session->opt[OPT_STANDARD_GROUP].name = SANE_NAME_STANDARD;
2590 session->opt[OPT_STANDARD_GROUP].desc = SANE_DESC_STANDARD;
2591 session->opt[OPT_STANDARD_GROUP].type = SANE_TYPE_GROUP;
2592 session->opt[OPT_STANDARD_GROUP].size = 0;
2593 session->opt[OPT_STANDARD_GROUP].cap = 0;
2594 session->opt[OPT_STANDARD_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2595
2596 /* scan mode */
2597 session->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
2598 session->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
2599 session->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
2600 session->opt[OPT_MODE].type = SANE_TYPE_STRING;
2601 session->opt[OPT_MODE].cap |= SANE_CAP_AUTOMATIC;
2602 session->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2603 session->opt[OPT_MODE].size = max_string_size (mode_list);
2604 session->opt[OPT_MODE].constraint.string_list = mode_list;
2605 session->val[OPT_MODE].s = strdup (mode_list[0]);
2606
2607 /* preview */
2608 session->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
2609 session->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
2610 session->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
2611 session->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL;
2612 session->opt[OPT_PREVIEW].cap |= SANE_CAP_AUTOMATIC;
2613 session->opt[OPT_PREVIEW].unit = SANE_UNIT_NONE;
2614 session->opt[OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE;
2615 session->val[OPT_PREVIEW].w = SANE_FALSE;
2616
2617 /* build resolution list */
2618 /* TODO we build it from xdpi, one could prefer building it from
2619 * ydpi list, or even allow for independent X and Y dpi (with 2 options then)
2620 */
2621 for (count = 0; model->xdpi_values[count] != 0; count++);
2622 dpi_list = malloc ((count + 1) * sizeof (SANE_Word));
2623 if (!dpi_list)
2624 return SANE_STATUS_NO_MEM;
2625 dpi_list[0] = count;
2626 for (count = 0; model->xdpi_values[count] != 0; count++)
2627 dpi_list[count + 1] = model->xdpi_values[count];
2628
2629 session->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
2630 session->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
2631 session->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
2632 session->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
2633 session->opt[OPT_RESOLUTION].cap |= SANE_CAP_AUTOMATIC;
2634 session->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
2635 session->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
2636 session->opt[OPT_RESOLUTION].constraint.word_list = dpi_list;
2637
2638 /* initial value is lowest available dpi */
2639 min = 65536;
2640 for (i = 1; i < count; i++)
2641 {
2642 if (dpi_list[i] < min)
2643 min = dpi_list[i];
2644 }
2645 session->val[OPT_RESOLUTION].w = min;
2646
2647 /* "Geometry" group: */
2648 session->opt[OPT_GEOMETRY_GROUP].title = SANE_TITLE_GEOMETRY;
2649 session->opt[OPT_GEOMETRY_GROUP].name = SANE_NAME_GEOMETRY;
2650 session->opt[OPT_GEOMETRY_GROUP].desc = SANE_DESC_GEOMETRY;
2651 session->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
2652 session->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
2653 session->opt[OPT_GEOMETRY_GROUP].size = 0;
2654 session->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2655
2656 /* adapt the constraint range to the detected model */
2657 x_range.max = model->x_size;
2658 y_range.max = model->y_size;
2659
2660 /* top-left x */
2661 session->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
2662 session->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
2663 session->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
2664 session->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
2665 session->opt[OPT_TL_X].cap |= SANE_CAP_AUTOMATIC;
2666 session->opt[OPT_TL_X].unit = SANE_UNIT_MM;
2667 session->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
2668 session->opt[OPT_TL_X].constraint.range = &x_range;
2669 session->val[OPT_TL_X].w = 0;
2670
2671 /* top-left y */
2672 session->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
2673 session->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
2674 session->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
2675 session->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
2676 session->opt[OPT_TL_Y].cap |= SANE_CAP_AUTOMATIC;
2677 session->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
2678 session->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
2679 session->opt[OPT_TL_Y].constraint.range = &y_range;
2680 session->val[OPT_TL_Y].w = 0;
2681
2682 /* bottom-right x */
2683 session->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
2684 session->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
2685 session->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
2686 session->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
2687 session->opt[OPT_BR_X].cap |= SANE_CAP_AUTOMATIC;
2688 session->opt[OPT_BR_X].unit = SANE_UNIT_MM;
2689 session->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
2690 session->opt[OPT_BR_X].constraint.range = &x_range;
2691 session->val[OPT_BR_X].w = x_range.max;
2692
2693 /* bottom-right y */
2694 session->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
2695 session->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
2696 session->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
2697 session->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
2698 session->opt[OPT_BR_Y].cap |= SANE_CAP_AUTOMATIC;
2699 session->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
2700 session->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
2701 session->opt[OPT_BR_Y].constraint.range = &y_range;
2702 session->val[OPT_BR_Y].w = y_range.max;
2703
2704 /* "Enhancement" group: */
2705 session->opt[OPT_ENHANCEMENT_GROUP].title = SANE_TITLE_ENHANCEMENT;
2706 session->opt[OPT_ENHANCEMENT_GROUP].name = SANE_NAME_ENHANCEMENT;
2707 session->opt[OPT_ENHANCEMENT_GROUP].desc = SANE_DESC_ENHANCEMENT;
2708 session->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
2709 session->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED;
2710 session->opt[OPT_ENHANCEMENT_GROUP].size = 0;
2711 session->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2712
2713 /* BW threshold */
2714 session->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
2715 session->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
2716 session->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
2717 session->opt[OPT_THRESHOLD].type = SANE_TYPE_FIXED;
2718 session->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT;
2719 session->opt[OPT_THRESHOLD].cap |=
2720 SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC | SANE_CAP_EMULATED;
2721 session->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
2722 session->opt[OPT_THRESHOLD].constraint.range = &threshold_percentage_range;
2723 session->val[OPT_THRESHOLD].w = SANE_FIX (50);
2724
2725 /* custom-gamma table */
2726 session->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA;
2727 session->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA;
2728 session->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA;
2729 session->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL;
2730 session->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_ADVANCED;
2731 session->val[OPT_CUSTOM_GAMMA].b = SANE_FALSE;
2732
2733 /* grayscale gamma vector */
2734 session->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR;
2735 session->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR;
2736 session->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR;
2737 session->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT;
2738 session->opt[OPT_GAMMA_VECTOR].cap |=
2739 SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC | SANE_CAP_ADVANCED;
2740 session->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE;
2741 session->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word);
2742 session->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE;
2743 session->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range;
2744 session->val[OPT_GAMMA_VECTOR].wa = model->gamma;
2745
2746 /* red gamma vector */
2747 session->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R;
2748 session->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R;
2749 session->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R;
2750 session->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT;
2751 session->opt[OPT_GAMMA_VECTOR_R].cap |=
2752 SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC | SANE_CAP_ADVANCED;
2753 session->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE;
2754 session->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word);
2755 session->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE;
2756 session->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range;
2757 session->val[OPT_GAMMA_VECTOR_R].wa = model->gamma;
2758
2759 /* green gamma vector */
2760 session->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G;
2761 session->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G;
2762 session->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G;
2763 session->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT;
2764 session->opt[OPT_GAMMA_VECTOR_G].cap |=
2765 SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC | SANE_CAP_ADVANCED;
2766 session->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE;
2767 session->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word);
2768 session->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE;
2769 session->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range;
2770 session->val[OPT_GAMMA_VECTOR_G].wa = model->gamma;
2771
2772 /* blue gamma vector */
2773 session->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B;
2774 session->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B;
2775 session->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B;
2776 session->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT;
2777 session->opt[OPT_GAMMA_VECTOR_B].cap |=
2778 SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC | SANE_CAP_ADVANCED;
2779 session->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE;
2780 session->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word);
2781 session->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE;
2782 session->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range;
2783 session->val[OPT_GAMMA_VECTOR_B].wa = model->gamma;
2784
2785 /* "Sensors" group */
2786 session->opt[OPT_SENSOR_GROUP].title = SANE_TITLE_SENSORS;
2787 session->opt[OPT_SENSOR_GROUP].name = SANE_NAME_SENSORS;
2788 session->opt[OPT_SENSOR_GROUP].desc = SANE_DESC_SENSORS;
2789 session->opt[OPT_SENSOR_GROUP].type = SANE_TYPE_GROUP;
2790 session->opt[OPT_SENSOR_GROUP].cap = SANE_CAP_ADVANCED;
2791 session->opt[OPT_SENSOR_GROUP].size = 0;
2792 session->opt[OPT_SENSOR_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2793
2794 /* scanner buttons */
2795 for (i = OPT_BUTTON_1; i <= OPT_BUTTON_11; i++)
2796 {
2797 char name[39];
2798 char title[64];
2799
2800 idx = i - OPT_BUTTON_1;
2801
2802 if (idx < model->buttons)
2803 {
2804 sprintf (name, "button-%s", model->button_name[idx]);
2805 sprintf (title, "%s", model->button_title[idx]);
2806
2807 session->opt[i].name = strdup (name);
2808 session->opt[i].title = strdup (title);
2809 session->opt[i].desc = SANE_I18N ("This option reflects the status "
2810 "of a scanner button.");
2811 session->opt[i].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
2812 }
2813 else
2814 {
2815 session->opt[i].name = strdup ("unused");
2816 session->opt[i].title = strdup ("unused button");
2817 session->opt[i].cap |= SANE_CAP_INACTIVE;
2818 }
2819
2820 session->opt[i].type = SANE_TYPE_BOOL;
2821 session->opt[i].unit = SANE_UNIT_NONE;
2822 session->opt[i].size = sizeof (SANE_Bool);
2823 session->opt[i].constraint_type = SANE_CONSTRAINT_NONE;
2824 session->opt[i].constraint.range = 0;
2825 session->val[i].w = SANE_FALSE;
2826 }
2827
2828 update_button_status (session);
2829
2830 /* "Advanced" group: */
2831 session->opt[OPT_ADVANCED_GROUP].title = SANE_I18N ("Advanced");
2832 session->opt[OPT_ADVANCED_GROUP].desc = "";
2833 session->opt[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP;
2834 session->opt[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED;
2835 session->opt[OPT_ADVANCED_GROUP].size = 0;
2836 session->opt[OPT_ADVANCED_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2837
2838 /* lamp on */
2839 session->opt[OPT_LAMP_ON].name = "lamp-on";
2840 session->opt[OPT_LAMP_ON].title = SANE_I18N ("Lamp on");
2841 session->opt[OPT_LAMP_ON].desc = SANE_I18N ("Turn on scanner lamp");
2842 session->opt[OPT_LAMP_ON].type = SANE_TYPE_BUTTON;
2843 session->opt[OPT_LAMP_ON].cap |= SANE_CAP_ADVANCED;
2844 session->opt[OPT_LAMP_ON].unit = SANE_UNIT_NONE;
2845 session->opt[OPT_LAMP_ON].size = 0;
2846 session->opt[OPT_LAMP_ON].constraint_type = SANE_CONSTRAINT_NONE;
2847 session->val[OPT_LAMP_ON].w = 0;
2848
2849 /* lamp off */
2850 session->opt[OPT_LAMP_OFF].name = "lamp-off";
2851 session->opt[OPT_LAMP_OFF].title = SANE_I18N ("Lamp off");
2852 session->opt[OPT_LAMP_OFF].desc = SANE_I18N ("Turn off scanner lamp");
2853 session->opt[OPT_LAMP_OFF].type = SANE_TYPE_BUTTON;
2854 session->opt[OPT_LAMP_OFF].cap |= SANE_CAP_ADVANCED;
2855 session->opt[OPT_LAMP_OFF].unit = SANE_UNIT_NONE;
2856 session->opt[OPT_LAMP_OFF].size = 0;
2857 session->opt[OPT_LAMP_OFF].constraint_type = SANE_CONSTRAINT_NONE;
2858 session->val[OPT_LAMP_OFF].w = 0;
2859
2860 DBG (DBG_proc, "init_options: exit\n");
2861 return SANE_STATUS_GOOD;
2862 }
2863
2864 /**
2865 * average scanned rgb data, returns the global average. Each channel avearge is also
2866 * returned.
2867 */
2868 static float
average_area(int color, SANE_Byte * data, int width, int height, float *ra, float *ga, float *ba)2869 average_area (int color, SANE_Byte * data, int width, int height,
2870 float *ra, float *ga, float *ba)
2871 {
2872 int x, y;
2873 float global, pixels;
2874 float rc, gc, bc;
2875 pixels = width * height;
2876 *ra = 0;
2877 *ga = 0;
2878 *ba = 0;
2879 rc = 0;
2880 gc = 0;
2881 bc = 0;
2882 if (color == SANE_TRUE)
2883 {
2884 for (y = 0; y < height; y++)
2885 {
2886 for (x = 0; x < width; x++)
2887 {
2888 rc += data[3 * width * y + x];
2889 gc += data[3 * width * y + x + 1];
2890 bc += data[3 * width * y + x + 2];
2891 }
2892 }
2893 global = (rc + gc + bc) / (3 * pixels);
2894 *ra = rc / pixels;
2895 *ga = gc / pixels;
2896 *ba = bc / pixels;
2897 }
2898 else
2899 {
2900 for (y = 0; y < height; y++)
2901 {
2902 for (x = 0; x < width; x++)
2903 {
2904 gc += data[width * y + x];
2905 }
2906 }
2907 global = gc / pixels;
2908 *ga = gc / pixels;
2909 }
2910 DBG (7, "average_area: global=%.2f, red=%.2f, green=%.2f, blue=%.2f\n",
2911 global, *ra, *ga, *ba);
2912 return global;
2913 }
2914
2915
2916 /**
2917 * Sets lamp brightness (hum, maybe some timing before light off)
2918 */
2919 static SANE_Status
set_lamp_brightness(struct Rts8891_Device *dev, int level)2920 set_lamp_brightness (struct Rts8891_Device *dev, int level)
2921 {
2922 SANE_Status status = SANE_STATUS_GOOD;
2923 SANE_Byte reg;
2924
2925 reg = 0xA0 | (level & 0x0F);
2926 sanei_rts88xx_write_reg (dev->devnum, LAMP_BRIGHT_REG, ®);
2927 switch (level)
2928 {
2929 case 0:
2930 reg = 0x8d;
2931 break;
2932 case 7:
2933 reg = 0x82;
2934 break;
2935 default:
2936 reg = 0x8d;
2937 break;
2938 }
2939 sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®);
2940 reg = (reg & 0xF0) | 0x20 | ((~reg) & 0x0F);
2941 dev->regs[LAMP_REG] = reg;
2942 sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®);
2943 sanei_rts88xx_write_control (dev->devnum, 0x00);
2944 sanei_rts88xx_write_control (dev->devnum, 0x00);
2945 sanei_rts88xx_get_status (dev->devnum, dev->regs);
2946 DBG (DBG_io, "set_lamp_brightness: status=0x%02x 0x%02x\n", dev->regs[0x10],
2947 dev->regs[0x11]);
2948 if (dev->sensor != SENSOR_TYPE_4400)
2949 {
2950 dev->regs[0x10] = 0x28;
2951 dev->regs[0x11] = 0x3f;
2952 }
2953 else
2954 {
2955 dev->regs[0x10] = 0x10;
2956 dev->regs[0x11] = 0x2f;
2957 }
2958 reg = dev->regs[LAMP_REG];
2959 sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®);
2960 status = sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, ®);
2961 if (reg != 0x00)
2962 {
2963 DBG (DBG_warn,
2964 "set_lamp_brightness: unexpected CONTROL_REG value, 0x%02x instead of 0x00\n",
2965 reg);
2966 }
2967 return status;
2968 }
2969
2970
2971 /**
2972 * Sets the lamp to half brightness and standard parameters
2973 */
2974 static SANE_Status
init_lamp(struct Rts8891_Device *dev)2975 init_lamp (struct Rts8891_Device *dev)
2976 {
2977 SANE_Byte reg;
2978
2979 sanei_rts88xx_write_control (dev->devnum, 0x01);
2980 sanei_rts88xx_write_control (dev->devnum, 0x01);
2981 sanei_rts88xx_write_control (dev->devnum, 0x00);
2982 sanei_rts88xx_write_control (dev->devnum, 0x00);
2983 sanei_rts88xx_cancel (dev->devnum);
2984 dev->regs[0x12] = 0xff;
2985 dev->regs[0x13] = 0x20;
2986 sanei_rts88xx_write_regs (dev->devnum, 0x12, dev->regs + 0x12, 2);
2987 /* 0xF8/0x28 expected */
2988 sanei_rts88xx_write_regs (dev->devnum, 0x14, dev->regs + 0x14, 2);
2989 sanei_rts88xx_write_control (dev->devnum, 0x00);
2990 sanei_rts88xx_write_control (dev->devnum, 0x00);
2991 if (dev->sensor != SENSOR_TYPE_4400 && dev->sensor != SENSOR_TYPE_4400_BARE)
2992 {
2993 sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x3f);
2994 dev->regs[0x11] = 0x3f;
2995 }
2996 else
2997 {
2998 sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x10, 0x22);
2999 dev->regs[0x11] = 0x22;
3000 }
3001 reg = 0x8d;
3002 sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®);
3003 dev->regs[LAMP_REG] = 0xa2;
3004 dev->regs[LAMP_BRIGHT_REG] = 0xa0;
3005 rts8891_write_all (dev->devnum, dev->regs, dev->reg_count);
3006 return set_lamp_brightness (dev, 7);
3007 }
3008
3009 /**
3010 * This function detects physical start of scanning area find finding a black area below the "roof"
3011 * if during scan we detect that sensor is inadequate, changed is set to SANE_TRUE
3012 */
3013 static SANE_Status
find_origin(struct Rts8891_Device *dev, SANE_Bool * changed)3014 find_origin (struct Rts8891_Device *dev, SANE_Bool * changed)
3015 {
3016 SANE_Status status = SANE_STATUS_GOOD;
3017 SANE_Byte control, reg;
3018 unsigned int max = 0;
3019 unsigned char *image = NULL;
3020 unsigned char *data = NULL;
3021 SANE_Word total;
3022 int startx = 300;
3023 int width = 1200;
3024 int x, y, sum, current;
3025 int starty = 18;
3026 int height = 180;
3027 int timing;
3028
3029 DBG (DBG_proc, "find_origin: start\n");
3030
3031 /* check if head is at home
3032 * once sensor is correctly set up, we are always park here,
3033 * but in case sensor has just changed, we are not so we park head */
3034 sanei_rts88xx_read_reg (dev->devnum, CONTROLER_REG, ®);
3035 if ((reg & 0x02) == 0)
3036 {
3037 if (park_head (dev, SANE_TRUE) != SANE_STATUS_GOOD)
3038 {
3039 DBG (DBG_error, "find_origin: failed to park head!\n");
3040 return SANE_STATUS_IO_ERROR;
3041 }
3042 DBG (DBG_info, "find_origin: head parked\n");
3043 }
3044
3045 sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control);
3046 if (control != 0)
3047 {
3048 DBG (DBG_warn, "find_origin: unexpected control value 0x%02x\n",
3049 control);
3050 }
3051 sanei_rts88xx_reset_lamp (dev->devnum, dev->regs);
3052 sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control);
3053 if (control != 0)
3054 {
3055 DBG (DBG_warn, "find_origin: unexpected control value 0x%02x\n",
3056 control);
3057 }
3058 sanei_rts88xx_reset_lamp (dev->devnum, dev->regs);
3059
3060 /* set lamp to standard settings */
3061 init_lamp (dev);
3062
3063 /* set scan parameters */
3064 dev->regs[0x00] = 0xe5;
3065 dev->regs[0x32] = 0x80;
3066 dev->regs[0x33] = 0x81;
3067 dev->regs[0x39] = 0x02;
3068 dev->regs[0x64] = 0x01;
3069 dev->regs[0x65] = 0x20;
3070 dev->regs[0x79] = 0x20;
3071 dev->regs[0x7a] = 0x01;
3072 dev->regs[0x90] = 0x1c;
3073
3074 dev->regs[0x35] = 0x1b;
3075 dev->regs[0x36] = 0x29;
3076 dev->regs[0x3a] = 0x1b;
3077 timing=0x32;
3078 dev->regs[0x85] = 0x00;
3079 dev->regs[0x86] = 0x06;
3080 dev->regs[0x87] = 0x00;
3081 dev->regs[0x88] = 0x06;
3082 dev->regs[0x8d] = 0x80;
3083 dev->regs[0x8e] = 0x68;
3084
3085 dev->regs[0xb2] = 0x02; /* 0x04 -> no data */
3086
3087 dev->regs[0xc0] = 0xff;
3088 dev->regs[0xc1] = 0x0f;
3089 dev->regs[0xc3] = 0xff;
3090 dev->regs[0xc4] = 0xff;
3091 dev->regs[0xc5] = 0xff;
3092 dev->regs[0xc6] = 0xff;
3093 dev->regs[0xc7] = 0xff;
3094 dev->regs[0xc8] = 0xff;
3095 dev->regs[0xc9] = 0x00;
3096 dev->regs[0xca] = 0x0e;
3097 dev->regs[0xcb] = 0x00;
3098 dev->regs[0xcd] = 0xf0;
3099 dev->regs[0xce] = 0xff;
3100 dev->regs[0xcf] = 0xf5;
3101 dev->regs[0xd0] = 0xf7;
3102 dev->regs[0xd1] = 0xea;
3103 dev->regs[0xd2] = 0x0b;
3104 dev->regs[0xd3] = 0x03;
3105 dev->regs[0xd4] = 0x05;
3106 dev->regs[0xd6] = 0xab;
3107 dev->regs[0xd7] = 0x30;
3108 dev->regs[0xd8] = 0xf6;
3109 dev->regs[0xe2] = 0x01;
3110 dev->regs[0xe3] = 0x00;
3111 dev->regs[0xe4] = 0x00;
3112 SET_DOUBLE (dev->regs, EXPOSURE_REG, 4124);
3113 /* dev->regs[0xe5] = 0x1c;
3114 dev->regs[0xe6] = 0x10; 101c=4124 */
3115 dev->regs[0xe7] = 0x00;
3116 dev->regs[0xe8] = 0x00;
3117 dev->regs[0xe9] = 0x00;
3118
3119 if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400)
3120 {
3121 dev->regs[0xc3] = 0x00;
3122 dev->regs[0xc4] = 0xf0;
3123 dev->regs[0xc7] = 0x0f;
3124 dev->regs[0xc8] = 0x00;
3125 dev->regs[0xc9] = 0xff;
3126 dev->regs[0xca] = 0xf1;
3127 dev->regs[0xcb] = 0xff;
3128 dev->regs[0xd7] = 0x10;
3129 }
3130 if (dev->sensor == SENSOR_TYPE_4400 || dev->sensor == SENSOR_TYPE_4400_BARE)
3131 {
3132 /* 4400 values / 'XPA' values */
3133 dev->regs[0x13] = 0x39; /* 0x20 */
3134 dev->regs[0x14] = 0xf0; /* 0xf8 */
3135 dev->regs[0x15] = 0x29; /* 0x28 */
3136 dev->regs[0x16] = 0x0f; /* 0x07 */
3137 dev->regs[0x17] = 0x10; /* 0x00 */
3138
3139 dev->regs[0x23] = 0x00; /* 0xff */
3140
3141 dev->regs[0x39] = 0x00; /* 0x02 */
3142 }
3143 if (dev->sensor == SENSOR_TYPE_4400_BARE)
3144 {
3145 dev->regs[0xc3] = 0xff; /* 0x00 */
3146 dev->regs[0xc4] = 0xff; /* 0xf0 */
3147 dev->regs[0xc7] = 0xff; /* 0x0f */
3148 dev->regs[0xc8] = 0xff; /* 0x00 */
3149 dev->regs[0xc9] = 0x00; /* 0xff */
3150 dev->regs[0xca] = 0x0e; /* 0xf1 */
3151 dev->regs[0xcb] = 0x00; /* 0xff */
3152 dev->regs[0xd7] = 0x30; /* 0x10 */
3153 dev->regs[0xda] = 0xa7; /* 0xa0 */
3154 }
3155 SET_DOUBLE (dev->regs, TIMING_REG, timing);
3156 SET_DOUBLE (dev->regs, TIMING1_REG, timing+1);
3157 SET_DOUBLE (dev->regs, TIMING2_REG, timing+2);
3158
3159
3160 /* allocate memory for the data */
3161 total = width * height;
3162 data = (unsigned char *) malloc (total);
3163 if (data == NULL)
3164 {
3165 DBG (DBG_error, "find_origin: failed to allocate %d bytes\n", total);
3166 return SANE_STATUS_NO_MEM;
3167 }
3168 image = (unsigned char *) malloc (total);
3169 if (image == NULL)
3170 {
3171 free(data);
3172 DBG (DBG_error, "find_origin: failed to allocate %d bytes\n", total);
3173 return SANE_STATUS_NO_MEM;
3174 }
3175
3176 /* set vertical and horizontal start/end positions */
3177 sanei_rts88xx_set_scan_area (dev->regs, starty, starty + height, startx,
3178 startx + width);
3179 sanei_rts88xx_set_offset (dev->regs, 0x7f, 0x7f, 0x7f);
3180 sanei_rts88xx_set_gain (dev->regs, 0x10, 0x10, 0x10);
3181
3182 /* gray level scan */
3183 dev->regs[LAMP_REG] = 0xad;
3184 sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, dev->regs + LAMP_REG);
3185 if (dev->sensor != SENSOR_TYPE_4400
3186 && (dev->sensor != SENSOR_TYPE_4400_BARE))
3187 {
3188 sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x20, 0x3b);
3189 }
3190 else
3191 {
3192 sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x10, 0x22);
3193 }
3194
3195 status =
3196 rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, 0x03,
3197 total, data);
3198 if (status != SANE_STATUS_GOOD)
3199 {
3200 free(image);
3201 free(data);
3202 DBG (DBG_error, "find_origin: failed to scan\n");
3203 return status;
3204 }
3205
3206 if (DBG_LEVEL > DBG_io2)
3207 {
3208 write_gray_data (data, "find_origin.pnm", width, height);
3209 }
3210
3211 /* now we have the data, search for the black area so that we can */
3212 /* deduce start of scan area */
3213 /* we apply an Y direction sobel filter to get reliable edge detection */
3214 /* Meanwhile we check that picture is correct, if not, sensor needs to */
3215 /* be changed . */
3216 /* TODO possibly check for insufficient warming */
3217 for (y = 1; y < height - 1; y++)
3218 for (x = 1; x < width - 1; x++)
3219 {
3220 /* if sensor is wrong, picture is black, so max will be low */
3221 if (data[y * width + x] > max)
3222 max = data[y * width + x];
3223
3224 /* sobel y filter */
3225 current =
3226 -data[(y - 1) * width + x + 1] - 2 * data[(y - 1) * width + x] -
3227 data[(y - 1) * width + x - 1] + data[(y + 1) * width + x + 1] +
3228 2 * data[(y + 1) * width + x] + data[(y + 1) * width + x - 1];
3229 if (current < 0)
3230 current = -current;
3231 image[y * width + x] = current;
3232 }
3233 if (DBG_LEVEL > DBG_io2)
3234 {
3235 write_gray_data (image, "find_origin_ysobel.pnm", width, height);
3236 }
3237
3238 /* sensor test */
3239 if (max < 10)
3240 {
3241 DBG (DBG_info,
3242 "find_origin: sensor type needs to be changed (max=%d)\n", max);
3243 *changed = SANE_TRUE;
3244 }
3245 else
3246 {
3247 *changed = SANE_FALSE;
3248 }
3249
3250 /* the edge will be where the white area stops */
3251 /* we average y position of white->black transition on each column */
3252 sum = 0;
3253 for (x = 1; x < width - 1; x++)
3254 {
3255 for (y = 1; y < height - 2; y++)
3256 {
3257 /* edge detection on each line */
3258 if (image[x + (y + 1) * width] - image[x + y * width] >= 20)
3259 {
3260 sum += y;
3261 break;
3262 }
3263 }
3264 }
3265 sum /= width;
3266 DBG (DBG_info, "find_origin: scan area offset=%d lines\n", sum);
3267
3268 /* convert the detected value into max ydpi */
3269 dev->top_offset = (48 * dev->model->max_ydpi) / 300;
3270
3271 /* no we're done */
3272 free (image);
3273 free (data);
3274
3275 /* safe guard test against moving to far toward the top */
3276 if (sum > 11)
3277 {
3278 /* now go back to the white area so that calibration can work on it */
3279 dev->regs[0x35] = 0x0e;
3280 dev->regs[0x3a] = 0x0e;
3281
3282 dev->regs[0xb2] = 0x06; /* no data (0x04) */
3283
3284 if (dev->sensor == SENSOR_TYPE_4400)
3285 {
3286 dev->regs[0x36] = 0x21; /* direction reverse (& ~0x08) */
3287
3288 dev->regs[0xe2] = 0x03; /* 0x01 */
3289
3290 /* dev->regs[0xe5] = 0x0d; 0x1c
3291 dev->regs[0xe6] = 0x08; 0x10 080d=2061=1030*2+1 */
3292 SET_DOUBLE (dev->regs, EXPOSURE_REG, 2061);
3293 }
3294 else
3295 {
3296 dev->regs[0x11] = 0x3f; /* 0x3b */
3297
3298 dev->regs[0x36] = 0x24; /* direction reverse (& ~0x08) */
3299
3300 dev->regs[0xe2] = 0x07;
3301
3302 /*
3303 dev->regs[0xe5] = 0x06;
3304 dev->regs[0xe6] = 0x04; 406=1030 */
3305 SET_DOUBLE (dev->regs, EXPOSURE_REG, 1030);
3306 }
3307
3308 /* move by a fixed amount relative to the 'top' of the scanner */
3309 sanei_rts88xx_set_scan_area (dev->regs, height - sum + 10,
3310 height - sum + 11, 637, 893);
3311 rts8891_write_all (dev->devnum, dev->regs, dev->reg_count);
3312 rts8891_commit (dev->devnum, 0x03);
3313
3314 /* wait for the motor to stop */
3315 do
3316 {
3317 status = sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, ®);
3318 }
3319 while ((reg & 0x08) == 0x08);
3320 }
3321
3322 DBG (DBG_proc, "find_origin: exit\n");
3323 return status;
3324 }
3325
3326 /**
3327 * This function detects the left margin (ie x offset of scanning area) by doing
3328 * a grey scan of the very beginning of the sensor and finding the start of the
3329 * white area of calibration zone, which is start of usable pixels.
3330 */
3331 static SANE_Status
find_margin(struct Rts8891_Device *dev)3332 find_margin (struct Rts8891_Device *dev)
3333 {
3334 SANE_Status status = SANE_STATUS_GOOD;
3335 unsigned char *data = NULL;
3336 SANE_Word total;
3337 int startx = 33;
3338 int width = 250;
3339 int x;
3340 int starty = 1;
3341 int height = 1;
3342 SANE_Byte reg = 0xa2;
3343 int timing=0;
3344
3345 DBG (DBG_proc, "find_margin: start\n");
3346
3347 /* increase brightness to have better margin detection */
3348 sanei_rts88xx_write_reg (dev->devnum, LAMP_BRIGHT_REG, ®);
3349
3350 /* maximum gain, offsets untouched */
3351 if (dev->sensor == SENSOR_TYPE_4400 || dev->sensor == SENSOR_TYPE_4400_BARE)
3352 {
3353 sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x10, 0x23);
3354 }
3355 else
3356 {
3357 sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x3b);
3358 }
3359
3360 sanei_rts88xx_set_gain (dev->regs, 0x3f, 0x3f, 0x3f);
3361
3362 /* set scan parameters */
3363 dev->regs[0x33] = 0x01;
3364 dev->regs[0x34] = 0x10;
3365 dev->regs[0x35] = 0x1b;
3366 dev->regs[0x3a] = 0x1b;
3367
3368 dev->regs[0x72] = 0x3a;
3369 dev->regs[0x73] = 0x15;
3370 dev->regs[0x74] = 0x62;
3371
3372 timing=0;
3373
3374 dev->regs[0xc0] = 0xff;
3375 dev->regs[0xc1] = 0xff;
3376 dev->regs[0xc2] = 0xff;
3377 dev->regs[0xc3] = 0x00;
3378 dev->regs[0xc4] = 0xf0;
3379 dev->regs[0xc7] = 0x0f;
3380 dev->regs[0xc8] = 0x00;
3381 dev->regs[0xcb] = 0xe0;
3382 dev->regs[0xcc] = 0xff;
3383 dev->regs[0xcd] = 0xff;
3384 dev->regs[0xce] = 0xff;
3385 dev->regs[0xcf] = 0xe9;
3386 dev->regs[0xd0] = 0xeb;
3387 dev->regs[0xd3] = 0x0c;
3388 dev->regs[0xd4] = 0x0e;
3389 dev->regs[0xd6] = 0xab;
3390 dev->regs[0xd7] = 0x14;
3391 dev->regs[0xd8] = 0xf6;
3392
3393 dev->regs[0xda] = 0xa7; /* XXX STEF XXX à l'origine, pas 'bare' */
3394
3395 dev->regs[0xe2] = 0x01;
3396
3397 /* dev->regs[0xe5] = 0x7b;
3398 dev->regs[0xe6] = 0x15; 157b=5499 */
3399 SET_DOUBLE (dev->regs, EXPOSURE_REG, 5499);
3400
3401 dev->regs[0xe7] = 0x00;
3402 dev->regs[0xe8] = 0x00;
3403 dev->regs[0xe9] = 0x00;
3404 dev->regs[0xea] = 0x00;
3405 dev->regs[0xeb] = 0x00;
3406 dev->regs[0xec] = 0x00;
3407 dev->regs[0xed] = 0x00;
3408 dev->regs[0xef] = 0x00;
3409 dev->regs[0xf0] = 0x00;
3410 dev->regs[0xf2] = 0x00;
3411 if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400)
3412 {
3413 dev->regs[0xc0] = 0x00;
3414 dev->regs[0xc1] = 0xf8;
3415 dev->regs[0xc2] = 0x7f;
3416 dev->regs[0xc4] = 0xf8;
3417 dev->regs[0xc5] = 0x7f;
3418 dev->regs[0xc6] = 0x00;
3419 dev->regs[0xc7] = 0xf8;
3420 dev->regs[0xc8] = 0x7f;
3421 dev->regs[0xc9] = 0xff;
3422 dev->regs[0xca] = 0xff;
3423 dev->regs[0xcb] = 0x8f;
3424 dev->regs[0xcd] = 0x07;
3425 dev->regs[0xce] = 0x80;
3426 dev->regs[0xcf] = 0xea;
3427 dev->regs[0xd0] = 0xec;
3428 dev->regs[0xd1] = 0xf7;
3429 dev->regs[0xd2] = 0x00;
3430 dev->regs[0xd3] = 0x10;
3431 dev->regs[0xd4] = 0x12;
3432 dev->regs[0xd7] = 0x31;
3433 }
3434 if (dev->sensor == SENSOR_TYPE_4400_BARE)
3435 {
3436 dev->regs[0x13] = 0x39; /* 0x20 */
3437 dev->regs[0x14] = 0xf0; /* 0xf8 */
3438 dev->regs[0x15] = 0x29; /* 0x28 */
3439 dev->regs[0x16] = 0x0f; /* 0x07 */
3440 dev->regs[0x17] = 0x10; /* 0x00 */
3441 dev->regs[0x23] = 0x00; /* 0xff */
3442 dev->regs[0x39] = 0x00; /* 0x02 */
3443 dev->regs[0x85] = 0x46; /* 0x00 */
3444 dev->regs[0x86] = 0x0b; /* 0x06 */
3445 dev->regs[0x87] = 0x8c; /* 0x00 */
3446 dev->regs[0x88] = 0x10; /* 0x06 */
3447 dev->regs[0x8d] = 0x3b; /* 0x00 */
3448 timing=0x00b0;
3449 }
3450 SET_DOUBLE (dev->regs, TIMING_REG, timing);
3451 SET_DOUBLE (dev->regs, TIMING1_REG, timing+1);
3452 SET_DOUBLE (dev->regs, TIMING2_REG, timing+2);
3453
3454 /* set vertical and horizontal start/end positions */
3455 sanei_rts88xx_set_scan_area (dev->regs, starty, starty + height, startx,
3456 startx + width);
3457
3458 /* allocate memory for the data */
3459 total = width * height;
3460 data = (unsigned char *) malloc (total);
3461 if (data == NULL)
3462 {
3463 DBG (DBG_error, "find_margin: failed to allocate %d bytes\n", total);
3464 return SANE_STATUS_NO_MEM;
3465 }
3466
3467 /* gray level scan */
3468 status =
3469 rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, 0x0c,
3470 total, data);
3471 if (status != SANE_STATUS_GOOD)
3472 {
3473 free(data);
3474 DBG (DBG_error, "find_margin: failed to scan\n");
3475 return status;
3476 }
3477
3478 if (DBG_LEVEL > DBG_io2)
3479 {
3480 write_gray_data (data, "find_margin.pnm", width, height);
3481 }
3482
3483 /* we search from left to right the first white pixel */
3484 x = 0;
3485 while (x < width && data[x] < MARGIN_LEVEL)
3486 x++;
3487 if (x == width)
3488 {
3489 DBG (DBG_warn, "find_margin: failed to find left margin!\n");
3490 DBG (DBG_warn, "find_margin: using default...\n");
3491 x = 48 + 40;
3492 }
3493 DBG (DBG_info, "find_margin: scan area margin=%d pixels\n", x);
3494
3495 /* convert the detected value into max ydpi */
3496 dev->left_offset = ((x - 40) * dev->model->max_xdpi) / 150;
3497 DBG (DBG_info, "find_margin: left_offset=%d pixels\n", x);
3498
3499 /* no we're done */
3500 free (data);
3501
3502 DBG (DBG_proc, "find_margin: exit\n");
3503 return status;
3504 }
3505
3506 #ifdef FAST_INIT
3507 /*
3508 * This function initializes the device:
3509 * - initial registers values
3510 * - test if at home
3511 * - head parking if needed
3512 */
3513 static SANE_Status
initialize_device(struct Rts8891_Device *dev)3514 initialize_device (struct Rts8891_Device *dev)
3515 {
3516 SANE_Status status;
3517 SANE_Byte reg, control;
3518
3519 DBG (DBG_proc, "initialize_device: start\n");
3520 if (dev->initialized == SANE_TRUE)
3521 return SANE_STATUS_GOOD;
3522
3523 sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x20, 0x28);
3524 sanei_rts88xx_write_control (dev->devnum, 0x01);
3525 sanei_rts88xx_write_control (dev->devnum, 0x01);
3526 sanei_rts88xx_write_control (dev->devnum, 0x00);
3527 sanei_rts88xx_write_control (dev->devnum, 0x00);
3528
3529 sanei_rts88xx_read_reg (dev->devnum, 0xb0, &control);
3530 DBG (DBG_io, "initialize_device: reg[0xb0]=0x%02x\n", control);
3531
3532 /* we expect to get 0x80 */
3533 if (control != 0x80)
3534 {
3535 DBG (DBG_warn,
3536 "initialize_device: expected reg[0xb0]=0x80, got 0x%02x\n",
3537 control);
3538 /* TODO fail here ??? */
3539 }
3540
3541 /* get lamp status */
3542 status = sanei_rts88xx_get_lamp_status (dev->devnum, dev->regs);
3543 if (status != SANE_STATUS_GOOD)
3544 {
3545 DBG (DBG_error, "initialize_device: failed to read lamp status!\n");
3546 return SANE_STATUS_IO_ERROR;
3547 }
3548 DBG (DBG_io, "initialize_device: lamp status=0x%02x\n", dev->regs[0x8e]);
3549
3550 /* sensor type the one for 4470c sold with XPA is slightly different
3551 * than those sold bare, for this model we always start with xpa type sensor,
3552 * and change it later if we detect black scans in find_origin(). In case the
3553 * attach function set up the sensor type, we don't modify it */
3554 if (dev->sensor == -1)
3555 {
3556 dev->sensor = device->model->sensor;
3557 }
3558 DBG (DBG_info, "initialize_device: initial sensor type is %d\n", dev->sensor);
3559 DBG (DBG_info, "initialize_device: reg[8e]=0x%02x\n", dev->regs[0x8e]);
3560
3561 /* detects if warming up is needed */
3562 if ((dev->regs[0x8e] & 0x60) != 0x60)
3563 {
3564 DBG (DBG_info, "initialize_device: lamp needs warming\n");
3565 dev->needs_warming = SANE_TRUE;
3566 }
3567 else
3568 {
3569 dev->needs_warming = SANE_FALSE;
3570 }
3571
3572 sanei_rts88xx_read_reg (dev->devnum, LAMP_REG, ®);
3573
3574 sanei_rts88xx_write_control (dev->devnum, 0x00);
3575 sanei_rts88xx_write_control (dev->devnum, 0x00);
3576
3577 /* read scanner present register */
3578 sanei_rts88xx_read_reg (dev->devnum, LINK_REG, &control);
3579 if (control != 0x00 && control != 0x01)
3580 {
3581 DBG (DBG_warn,
3582 "initialize_device: unexpected LINK_REG=0x%02x\n", control);
3583 }
3584
3585 /* head parking if needed */
3586 sanei_rts88xx_read_reg (dev->devnum, CONTROLER_REG, &control);
3587 if (!(control & 0x02))
3588 {
3589 if (park_head (dev, SANE_TRUE) != SANE_STATUS_GOOD)
3590 {
3591 DBG (DBG_error, "initialize_device: failed to park head!\n");
3592 return SANE_STATUS_IO_ERROR;
3593 }
3594 }
3595
3596 /* writes initial register set */
3597 dev->regs[0x00] = 0xe5; /* 0xf5 */
3598 dev->regs[0x02] = 0x1f; /* 0x00 */
3599 dev->regs[0x03] = 0x1f; /* 0x00 */
3600 dev->regs[0x04] = 0x1f; /* 0x00 */
3601 dev->regs[0x05] = 0x1f; /* 0x00 */
3602 dev->regs[0x06] = 0x1f; /* 0x00 */
3603 dev->regs[0x07] = 0x1f; /* 0x00 */
3604 dev->regs[0x08] = 0x0a; /* 0x00 */
3605 dev->regs[0x09] = 0x0a; /* 0x00 */
3606 dev->regs[0x0a] = 0x0a; /* 0x00 */
3607 dev->regs[0x10] = 0x28; /* 0x60 */
3608 dev->regs[0x11] = 0x28; /* 0x1b */
3609 dev->regs[0x13] = 0x20; /* 0x3e */
3610 dev->regs[0x14] = 0xf8; /* 0x00 */
3611 dev->regs[0x15] = 0x28; /* 0x00 */
3612 dev->regs[0x16] = 0x07; /* 0xff */
3613 dev->regs[0x17] = 0x00; /* 0x3e */
3614 dev->regs[0x18] = 0xff; /* 0x00 */
3615 dev->regs[0x1d] = 0x20; /* 0x22 */
3616
3617 /* LCD display */
3618 dev->regs[0x20] = 0x3a; /* 0x00 */
3619 dev->regs[0x21] = 0xf2; /* 0x00 */
3620 dev->regs[0x24] = 0xff; /* 0x00 */
3621 dev->regs[0x25] = 0x00; /* 0xff */
3622
3623 dev->regs[0x30] = 0x00; /* 0x01 */
3624 dev->regs[0x31] = 0x00; /* 0x42 */
3625 dev->regs[0x36] = 0x07; /* 0x00 */
3626 dev->regs[0x39] = 0x00; /* 0x02 */
3627 dev->regs[0x40] = 0x20; /* 0x80 */
3628 dev->regs[0x44] = 0x8c; /* 0x18 */
3629 dev->regs[0x45] = 0x76; /* 0x00 */
3630 dev->regs[0x50] = 0x00; /* 0x20 */
3631 dev->regs[0x51] = 0x00; /* 0x24 */
3632 dev->regs[0x52] = 0x00; /* 0x04 */
3633 dev->regs[0x64] = 0x00; /* 0x10 */
3634 dev->regs[0x68] = 0x00; /* 0x10 */
3635 dev->regs[0x6a] = 0x00; /* 0x01 */
3636 dev->regs[0x70] = 0x00; /* 0x20 */
3637 dev->regs[0x71] = 0x00; /* 0x20 */
3638 dev->regs[0x72] = 0xe1; /* 0x00 */
3639 dev->regs[0x73] = 0x14; /* 0x00 */
3640 dev->regs[0x74] = 0x18; /* 0x00 */
3641 dev->regs[0x75] = 0x15; /* 0x00 */
3642 dev->regs[0x76] = 0x00; /* 0x20 */
3643 dev->regs[0x77] = 0x00; /* 0x01 */
3644 dev->regs[0x79] = 0x00; /* 0x02 */
3645 dev->regs[0x81] = 0x00; /* 0x41 */
3646 dev->regs[0x83] = 0x00; /* 0x10 */
3647 dev->regs[0x84] = 0x00; /* 0x21 */
3648 dev->regs[0x85] = 0x00; /* 0x20 */
3649 dev->regs[0x87] = 0x00; /* 0x20 */
3650 dev->regs[0x88] = 0x00; /* 0x81 */
3651 dev->regs[0x89] = 0x00; /* 0x20 */
3652 dev->regs[0x8a] = 0x00; /* 0x01 */
3653 dev->regs[0x8b] = 0x00; /* 0x01 */
3654 dev->regs[0x8d] = 0x80; /* 0x22 */
3655 dev->regs[0x8e] = 0x68; /* 0x00 */
3656 dev->regs[0x8f] = 0x00; /* 0x40 */
3657 dev->regs[0x90] = 0x00; /* 0x05 */
3658 dev->regs[0x93] = 0x02; /* 0x01 */
3659 dev->regs[0x94] = 0x0e; /* 0x1e */
3660 dev->regs[0xb0] = 0x00; /* 0x80 */
3661 dev->regs[0xb2] = 0x02; /* 0x06 */
3662 dev->regs[0xc0] = 0xff; /* 0x00 */
3663 dev->regs[0xc1] = 0x0f; /* 0x00 */
3664 dev->regs[0xc3] = 0xff; /* 0x00 */
3665 dev->regs[0xc4] = 0xff; /* 0x00 */
3666 dev->regs[0xc5] = 0xff; /* 0x00 */
3667 dev->regs[0xc6] = 0xff; /* 0x00 */
3668 dev->regs[0xc7] = 0xff; /* 0x00 */
3669 dev->regs[0xc8] = 0xff; /* 0x00 */
3670 dev->regs[0xca] = 0x0e; /* 0x00 */
3671 dev->regs[0xcd] = 0xf0; /* 0x00 */
3672 dev->regs[0xce] = 0xff; /* 0x00 */
3673 dev->regs[0xcf] = 0xf5; /* 0x00 */
3674 dev->regs[0xd0] = 0xf7; /* 0x00 */
3675 dev->regs[0xd1] = 0xea; /* 0x00 */
3676 dev->regs[0xd2] = 0x0b; /* 0x00 */
3677 dev->regs[0xd3] = 0x03; /* 0x00 */
3678 dev->regs[0xd4] = 0x05; /* 0x01 */
3679 dev->regs[0xd5] = 0x86; /* 0x06 */
3680 dev->regs[0xd7] = 0x30; /* 0x10 */
3681 dev->regs[0xd8] = 0xf6; /* 0x7a */
3682 dev->regs[0xd9] = 0x80; /* 0x00 */
3683 dev->regs[0xda] = 0x00; /* 0x15 */
3684 dev->regs[0xe2] = 0x01; /* 0x00 */
3685 /* dev->regs[0xe5] = 0x14; 0x0f */
3686 SET_DOUBLE (dev->regs, EXPOSURE_REG, 20);
3687
3688 status = rts8891_write_all (dev->devnum, dev->regs, dev->reg_count);
3689
3690 DBG (DBG_proc, "initialize_device: exit\n");
3691 dev->initialized = SANE_TRUE;
3692
3693 return status;
3694 }
3695 #else /* FAST_INIT */
3696
3697 static SANE_Status
init_registers(struct Rts8891_Device *dev)3698 init_registers (struct Rts8891_Device *dev)
3699 {
3700 int i;
3701
3702 /* initial set written to scanner
3703 * 0xe5 0x41 0x1f 0x1f 0x1f 0x1f 0x1f 0x1f 0x0a 0x0a 0x0a 0x70 0x00 0x00 0x00 0x00 0x60 0x1b 0x08 0x20 0x00 0x20 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x20 0x00 0x00 0x3a 0xf2 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x10 0x00 0x07 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x20 0x00 0x00 0x00 0x8c 0x76 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x68 0x00 0x00 0x00 0x00 0x02 0x0e 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xcc 0x27 0x64 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 ---- 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xe0 0x00 0x00 0x00 0x00 0x86 0x1b 0x00 0xff 0x00 0x27 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x00 0x00 0x14 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
3704 */
3705 /* lengthy set up to make register content obvious, may be some day I will
3706 * group corresponding values between models */
3707 switch (dev->sensor)
3708 {
3709 case SENSOR_TYPE_BARE:
3710 case SENSOR_TYPE_XPA:
3711 dev->regs[0x01] = 0x41;
3712 dev->regs[0x0b] = 0x70;
3713 dev->regs[0x0c] = 0x00;
3714 dev->regs[0x0d] = 0x00;
3715 dev->regs[0x0e] = 0x00;
3716 dev->regs[0x0f] = 0x00;
3717
3718 dev->regs[0x12] = 0x00;
3719 dev->regs[0x13] = 0x20;
3720 dev->regs[0x14] = 0x00;
3721 dev->regs[0x15] = 0x20;
3722 dev->regs[0x16] = 0x00;
3723 dev->regs[0x17] = 0x00;
3724 dev->regs[0x18] = 0x00;
3725 dev->regs[0x19] = 0x00;
3726 dev->regs[0x1a] = 0x00;
3727 dev->regs[0x1b] = 0x00;
3728 dev->regs[0x1c] = 0x00;
3729 dev->regs[0x1d] = 0x20;
3730 dev->regs[0x1e] = 0x00;
3731 dev->regs[0x1f] = 0x00;
3732
3733 /* LCD display */
3734 dev->regs[0x20] = 0x3a;
3735 dev->regs[0x21] = 0xf2;
3736 dev->regs[0x22] = 0x00;
3737
3738 dev->regs[0x23] = 0x00;
3739 dev->regs[0x24] = 0x00;
3740 dev->regs[0x25] = 0x00;
3741 dev->regs[0x26] = 0x00;
3742 dev->regs[0x27] = 0x00;
3743 dev->regs[0x28] = 0x00;
3744 dev->regs[0x29] = 0x00;
3745 dev->regs[0x2a] = 0x00;
3746 dev->regs[0x2b] = 0x00;
3747 dev->regs[0x2c] = 0x00;
3748 dev->regs[0x2d] = 0x00;
3749 dev->regs[0x2e] = 0x00;
3750 dev->regs[0x2f] = 0x00;
3751 dev->regs[0x30] = 0x00;
3752 dev->regs[0x31] = 0x00;
3753 dev->regs[0x32] = 0x00;
3754 dev->regs[0x33] = 0x00;
3755 dev->regs[0x34] = 0x10;
3756 dev->regs[0x35] = 0x00;
3757 dev->regs[0x36] = 0x07;
3758 dev->regs[0x37] = 0x00;
3759 dev->regs[0x38] = 0x00;
3760 dev->regs[0x39] = 0x00;
3761 dev->regs[0x3a] = 0x00;
3762 dev->regs[0x3b] = 0x00;
3763 dev->regs[0x3c] = 0x00;
3764 dev->regs[0x3d] = 0x00;
3765 dev->regs[0x3e] = 0x00;
3766 dev->regs[0x3f] = 0x00;
3767 dev->regs[0x40] = 0x20;
3768 dev->regs[0x41] = 0x00;
3769 dev->regs[0x42] = 0x00;
3770 dev->regs[0x43] = 0x00;
3771 dev->regs[0x44] = 0x8c;
3772 dev->regs[0x45] = 0x76;
3773 dev->regs[0x46] = 0x00;
3774 dev->regs[0x47] = 0x00;
3775 dev->regs[0x48] = 0x00;
3776 dev->regs[0x49] = 0x00;
3777 dev->regs[0x4a] = 0x00;
3778 dev->regs[0x4b] = 0x00;
3779 dev->regs[0x4c] = 0x00;
3780 dev->regs[0x4d] = 0x00;
3781 dev->regs[0x4e] = 0x00;
3782 dev->regs[0x4f] = 0x00;
3783 dev->regs[0x50] = 0x00;
3784 dev->regs[0x51] = 0x00;
3785 dev->regs[0x52] = 0x00;
3786 dev->regs[0x53] = 0x00;
3787 dev->regs[0x54] = 0x00;
3788 dev->regs[0x55] = 0x00;
3789 dev->regs[0x56] = 0x00;
3790 dev->regs[0x57] = 0x00;
3791 dev->regs[0x58] = 0x00;
3792 dev->regs[0x59] = 0x00;
3793 dev->regs[0x5a] = 0x00;
3794 dev->regs[0x5b] = 0x00;
3795 dev->regs[0x5c] = 0x00;
3796 dev->regs[0x5d] = 0x00;
3797 dev->regs[0x5e] = 0x00;
3798 dev->regs[0x5f] = 0x00;
3799 dev->regs[0x64] = 0x00;
3800 dev->regs[0x65] = 0x00;
3801 dev->regs[0x66] = 0x00;
3802 dev->regs[0x67] = 0x00;
3803 dev->regs[0x68] = 0x00;
3804 dev->regs[0x69] = 0x00;
3805 dev->regs[0x6a] = 0x00;
3806 dev->regs[0x6b] = 0x00;
3807 dev->regs[0x6e] = 0x00;
3808 dev->regs[0x6f] = 0x00;
3809 dev->regs[0x70] = 0x00;
3810 dev->regs[0x71] = 0x00;
3811 dev->regs[0x72] = 0x00;
3812 dev->regs[0x73] = 0x00;
3813 dev->regs[0x74] = 0x00;
3814 dev->regs[0x75] = 0x00;
3815 dev->regs[0x76] = 0x00;
3816 dev->regs[0x77] = 0x00;
3817 dev->regs[0x78] = 0x00;
3818 dev->regs[0x79] = 0x00;
3819 dev->regs[0x7a] = 0x00;
3820 dev->regs[0x7b] = 0x00;
3821 dev->regs[0x7c] = 0x00;
3822 dev->regs[0x7d] = 0x00;
3823 dev->regs[0x7e] = 0x00;
3824 dev->regs[0x7f] = 0x00;
3825 dev->regs[0x80] = 0x00;
3826 dev->regs[0x81] = 0x00;
3827 dev->regs[0x82] = 0x00;
3828 dev->regs[0x83] = 0x00;
3829 dev->regs[0x84] = 0x00;
3830 dev->regs[0x85] = 0x00;
3831 dev->regs[0x86] = 0x00;
3832 dev->regs[0x87] = 0x00;
3833 dev->regs[0x88] = 0x00;
3834 dev->regs[0x89] = 0x00;
3835 dev->regs[0x8a] = 0x00;
3836 dev->regs[0x8b] = 0x00;
3837 dev->regs[0x8c] = 0x00;
3838 dev->regs[0x8d] = 0x80;
3839 dev->regs[0x8e] = 0x68;
3840 dev->regs[0x8f] = 0x00;
3841 dev->regs[0x90] = 0x00;
3842 dev->regs[0x91] = 0x00;
3843 dev->regs[0x92] = 0x00;
3844 dev->regs[0x93] = 0x02;
3845 dev->regs[0x94] = 0x0e;
3846 dev->regs[0x95] = 0x00;
3847 dev->regs[0x96] = 0x00;
3848 dev->regs[0x97] = 0x00;
3849 dev->regs[0x98] = 0x00;
3850 dev->regs[0x99] = 0x00;
3851 dev->regs[0x9a] = 0x00;
3852 dev->regs[0x9b] = 0x00;
3853 dev->regs[0x9c] = 0x00;
3854 dev->regs[0x9d] = 0x00;
3855 dev->regs[0x9e] = 0x00;
3856 dev->regs[0x9f] = 0x00;
3857 dev->regs[0xa0] = 0x00;
3858 dev->regs[0xa1] = 0x00;
3859 dev->regs[0xa2] = 0x00;
3860 dev->regs[0xa3] = 0xcc;
3861 dev->regs[0xa4] = 0x27;
3862 dev->regs[0xa5] = 0x64;
3863 dev->regs[0xa6] = 0x00;
3864 dev->regs[0xa7] = 0x00;
3865 dev->regs[0xa8] = 0x00;
3866 dev->regs[0xa9] = 0x00;
3867 dev->regs[0xaa] = 0x00;
3868 dev->regs[0xab] = 0x00;
3869 dev->regs[0xac] = 0x00;
3870 dev->regs[0xad] = 0x00;
3871 dev->regs[0xae] = 0x00;
3872 dev->regs[0xaf] = 0x00;
3873 dev->regs[0xb0] = 0x00;
3874 dev->regs[0xb1] = 0x00;
3875 dev->regs[0xb2] = 0x02;
3876 dev->regs[0xb4] = 0x00;
3877 dev->regs[0xb5] = 0x00;
3878 dev->regs[0xb6] = 0x00;
3879 dev->regs[0xb7] = 0x00;
3880 dev->regs[0xb8] = 0x00;
3881 dev->regs[0xb9] = 0x00;
3882 dev->regs[0xba] = 0x00;
3883 dev->regs[0xbb] = 0x00;
3884 dev->regs[0xbc] = 0x00;
3885 dev->regs[0xbd] = 0x00;
3886 dev->regs[0xbe] = 0x00;
3887 dev->regs[0xbf] = 0x00;
3888 dev->regs[0xc0] = 0x00;
3889 dev->regs[0xc1] = 0x00;
3890 dev->regs[0xc2] = 0x00;
3891 dev->regs[0xc3] = 0x00;
3892 dev->regs[0xc4] = 0x00;
3893 dev->regs[0xc5] = 0x00;
3894 dev->regs[0xc6] = 0x00;
3895 dev->regs[0xc7] = 0x00;
3896 dev->regs[0xc8] = 0x00;
3897 dev->regs[0xc9] = 0x00;
3898 dev->regs[0xca] = 0x00;
3899 dev->regs[0xcb] = 0x00;
3900 dev->regs[0xcc] = 0x00;
3901 dev->regs[0xcd] = 0x00;
3902 dev->regs[0xce] = 0x00;
3903 dev->regs[0xcf] = 0x00;
3904 dev->regs[0xd0] = 0x00;
3905 dev->regs[0xd1] = 0x00;
3906 dev->regs[0xd2] = 0x00;
3907 dev->regs[0xd3] = 0x00;
3908 dev->regs[0xd4] = 0x00;
3909 dev->regs[0xd5] = 0x86;
3910 dev->regs[0xd6] = 0x1b;
3911 dev->regs[0xd7] = 0x00;
3912 dev->regs[0xd8] = 0xff;
3913 dev->regs[0xd9] = 0x00;
3914 dev->regs[0xda] = 0x27;
3915 dev->regs[0xdb] = 0x00;
3916 dev->regs[0xdc] = 0x00;
3917 dev->regs[0xdd] = 0x00;
3918 dev->regs[0xde] = 0x00;
3919 dev->regs[0xdf] = 0x00;
3920 dev->regs[0xe0] = 0x00;
3921 dev->regs[0xe1] = 0x00;
3922 dev->regs[0xe2] = 0x01;
3923 dev->regs[0xe3] = 0x00;
3924 dev->regs[0xe4] = 0x00;
3925
3926 /*dev->regs[0xe5] = 0x14;
3927 dev->regs[0xe6] = 0x00; 14=20 */
3928 SET_DOUBLE (dev->regs, EXPOSURE_REG, 20);
3929
3930 dev->regs[0xe7] = 0x00;
3931 dev->regs[0xe8] = 0x00;
3932 dev->regs[0xe9] = 0x00;
3933 dev->regs[0xea] = 0x00;
3934 dev->regs[0xeb] = 0x00;
3935 dev->regs[0xec] = 0x00;
3936 dev->regs[0xed] = 0x00;
3937 dev->regs[0xee] = 0x00;
3938 dev->regs[0xef] = 0x00;
3939 dev->regs[0xf0] = 0x00;
3940 dev->regs[0xf1] = 0x00;
3941 dev->regs[0xf2] = 0x00;
3942 dev->regs[0xf3] = 0x00;
3943 break;
3944 case SENSOR_TYPE_4400:
3945 case SENSOR_TYPE_4400_BARE:
3946 for (i = 0; i < dev->reg_count; i++)
3947 dev->regs[i] = 0x00;
3948 /* 2d may be 0x20 or 0x22: signals something */
3949 dev->regs[0x00] = 0xf5;
3950 dev->regs[0x01] = 0x41;
3951 dev->regs[0x0b] = 0x70;
3952 dev->regs[0x10] = 0x50;
3953 dev->regs[0x11] = 0x03;
3954 dev->regs[0x12] = 0xff;
3955 dev->regs[0x13] = 0x3e;
3956 dev->regs[0x16] = 0xff;
3957 dev->regs[0x17] = 0x3e;
3958 dev->regs[0x1d] = 0x22;
3959 dev->regs[0x22] = 0x01;
3960 dev->regs[0x23] = 0xff;
3961 dev->regs[0x25] = 0xfe;
3962 dev->regs[0x34] = 0x10;
3963 dev->regs[0x39] = 0x02;
3964 dev->regs[0x40] = 0x80;
3965 dev->regs[0x44] = 0x8c;
3966 dev->regs[0x45] = 0x76;
3967 dev->regs[0x50] = 0x20;
3968 dev->regs[0x8b] = 0xff;
3969 dev->regs[0x8c] = 0x3f;
3970 dev->regs[0x8d] = 0x80;
3971 dev->regs[0x8e] = 0x68;
3972 dev->regs[0x93] = 0x01;
3973 dev->regs[0x94] = 0x1e;
3974 dev->regs[0xa3] = 0xcc;
3975 dev->regs[0xa4] = 0x27;
3976 dev->regs[0xa5] = 0x64;
3977 dev->regs[0xb0] = 0x80;
3978 dev->regs[0xb1] = 0x01;
3979 dev->regs[0xb2] = 0x06;
3980 dev->regs[0xd4] = 0x01;
3981 dev->regs[0xd5] = 0x06;
3982 dev->regs[0xd6] = 0x1b;
3983 dev->regs[0xd7] = 0x10;
3984 dev->regs[0xd8] = 0x7a;
3985 dev->regs[0xda] = 0xa7;
3986 dev->regs[0xe5] = 0x0f;
3987 if (dev->sensor == SENSOR_TYPE_4400_BARE)
3988 {
3989 dev->regs[0x30] = 0x40; /* 0x00 */
3990 dev->regs[0x31] = 0x80; /* 0x00 */
3991 dev->regs[0x44] = 0x00; /* 0x8c */
3992 dev->regs[0x45] = 0x00; /* 0x76 */
3993 dev->regs[0x52] = 0x04; /* 0x00 */
3994 dev->regs[0x69] = 0x01; /* 0x00 */
3995 dev->regs[0x6a] = 0x10; /* 0x00 */
3996 dev->regs[0x6e] = 0x08; /* 0x00 */
3997 dev->regs[0x70] = 0x40; /* 0x00 */
3998 dev->regs[0x71] = 0x08; /* 0x00 */
3999 dev->regs[0x78] = 0x08; /* 0x00 */
4000 dev->regs[0x79] = 0x11; /* 0x00 */
4001 dev->regs[0x82] = 0x40; /* 0x00 */
4002 dev->regs[0x83] = 0x30; /* 0x00 */
4003 dev->regs[0x84] = 0x45; /* 0x00 */
4004 dev->regs[0x87] = 0x02; /* 0x00 */
4005 dev->regs[0x88] = 0x05; /* 0x00 */
4006 dev->regs[0x8b] = 0x01; /* 0xff */
4007 dev->regs[0x8c] = 0x80; /* 0x3f */
4008 dev->regs[0x8d] = 0x04; /* 0x80 */
4009 dev->regs[0x8e] = 0x10; /* 0x68 */
4010 dev->regs[0x8f] = 0x01; /* 0x00 */
4011 dev->regs[0x90] = 0x80; /* 0x00 */
4012 }
4013 break;
4014 }
4015 return SANE_STATUS_GOOD;
4016 }
4017
4018 /*
4019 * This function initializes the device:
4020 * - initial registers values
4021 * - test if at home
4022 * - head parking if needed
4023 */
4024 static SANE_Status
init_device(struct Rts8891_Device *dev)4025 init_device (struct Rts8891_Device *dev)
4026 {
4027 SANE_Status status = SANE_STATUS_GOOD;
4028 SANE_Byte control, reg, id;
4029 SANE_Int i, page;
4030 SANE_Byte buffer[2072];
4031 char message[256 * 6];
4032 SANE_Int val;
4033
4034 /* these commands are used to access NVRAM through a serial manner */
4035 /* we ignore NVRAM settingsd for now */
4036 SANE_Byte nv_cmd1[21] =
4037 { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x28, 0x38,
4038 0x08, 0x18, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x08
4039 };
4040 SANE_Byte nv_cmd2[21] =
4041 { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x28, 0x38,
4042 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x08
4043 };
4044 SANE_Byte nv_cmd3[21] =
4045 { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x28, 0x38,
4046 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x28, 0x38, 0x08
4047 };
4048 SANE_Byte nv_cmd4[21] =
4049 { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18,
4050 0x08, 0x18, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x08
4051 };
4052 SANE_Byte nv_cmd5[21] =
4053 { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18,
4054 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x08
4055 };
4056 SANE_Byte nv_cmd6[21] =
4057 { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18,
4058 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x28, 0x38, 0x08
4059 };
4060 SANE_Byte nv_cmd7[21] =
4061 { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18,
4062 0x28, 0x38, 0x08, 0x18, 0x08, 0x18, 0x08, 0x18, 0x08
4063 };
4064
4065 DBG (DBG_proc, "init_device: start\n");
4066 if (dev->initialized == SANE_TRUE)
4067 return SANE_STATUS_GOOD;
4068
4069 /* read control register, if busy, something will have to be done ... */
4070 sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control);
4071 DBG (DBG_io, "init_device: control=0x%02x\n", control);
4072
4073 /* when just plugged, we expect to get 0x04 */
4074 if (control != 0x04)
4075 {
4076 DBG (DBG_warn, "init_device: expected control=0x04, got 0x%02x\n",
4077 control);
4078 }
4079
4080 /* then read "link" register */
4081 sanei_rts88xx_read_reg (dev->devnum, 0xb0, &control);
4082 DBG (DBG_io, "init_device: link=0x%02x\n", control);
4083
4084 /* we expect to get 0x80 */
4085 if (control != 0x80)
4086 {
4087 DBG (DBG_warn, "init_device: expected link=0x80, got 0x%02x\n",
4088 control);
4089 }
4090
4091 /* reads scanner status */
4092 sanei_rts88xx_get_status (dev->devnum, dev->regs);
4093 DBG (DBG_io, "init_device: status=0x%02x 0x%02x\n", dev->regs[0x10],
4094 dev->regs[0x11]);
4095
4096 /* reads lamp status and sensor information */
4097 sanei_rts88xx_get_lamp_status (dev->devnum, dev->regs);
4098 DBG (DBG_io, "init_device: lamp status=0x%02x\n", dev->regs[0x8e]);
4099
4100 /* initialize sensor with default from model */
4101 dev->sensor = dev->model->sensor;
4102 DBG (DBG_info, "init_device: reg[8e]=0x%02x\n", dev->regs[0x8e]);
4103
4104 /* reset lamp */
4105 sanei_rts88xx_reset_lamp (dev->devnum, dev->regs);
4106 if ((dev->regs[0x8e] & 0x60) != 0x60)
4107 {
4108 DBG (DBG_info, "init_device: lamp needs warming\n");
4109 dev->needs_warming = SANE_TRUE;
4110 }
4111 else
4112 {
4113 dev->needs_warming = SANE_FALSE;
4114 }
4115
4116 /* reads lcd panel status */
4117 sanei_rts88xx_get_lcd (dev->devnum, dev->regs);
4118 DBG (DBG_io, "init_device: lcd panel=0x%02x 0x%02x 0x%02x\n",
4119 dev->regs[0x20], dev->regs[0x21], dev->regs[0x22]);
4120
4121 /* read mainboard ID/scanner present register */
4122 sanei_rts88xx_read_reg (dev->devnum, LINK_REG, &id);
4123 DBG (DBG_io, "init_device: link=0x%02x\n", id);
4124
4125 /* only known ID is currently 0x00 or 0x01 */
4126 if (id != 0x00 && id != 0x01)
4127 {
4128 DBG (DBG_warn, "init_device: expected id=0x00 or 0x01, got 0x%02x\n",
4129 id);
4130 }
4131
4132 /* write 0x00 twice to control */
4133 control = 0x00;
4134 sanei_rts88xx_write_control (dev->devnum, control);
4135 sanei_rts88xx_write_control (dev->devnum, control);
4136
4137 /* read initial register set */
4138 sanei_rts88xx_read_regs (dev->devnum, 0, dev->regs, dev->reg_count);
4139 if (DBG_LEVEL > DBG_io2)
4140 {
4141 sprintf (message, "init_device: initial register settings: ");
4142 for (i = 0; i < dev->reg_count; i++)
4143 sprintf (message + strlen (message), "0x%02x ", dev->regs[i]);
4144
4145 DBG (DBG_io2, "%s\n", message);
4146 }
4147
4148 /* initial sensor guess */
4149 val = dev->regs[0x44] + 256 * dev->regs[0x45];
4150 DBG (DBG_io, "init_device: R44/45=0x%04x\n", val);
4151 if (dev->sensor == SENSOR_TYPE_4400)
4152 {
4153 if(val != 0x00)
4154 {
4155 DBG (DBG_info, "init_device: SENSOR_TYPE_4400 detected\n");
4156 }
4157 else
4158 {
4159 DBG (DBG_info, "init_device: SENSOR_TYPE_4400_BARE detected\n");
4160 dev->sensor = SENSOR_TYPE_4400_BARE;
4161 }
4162 }
4163
4164 init_registers(dev);
4165
4166 sanei_rts88xx_set_offset (dev->regs, 31, 31, 31);
4167 sanei_rts88xx_set_gain (dev->regs, 10, 10, 10);
4168 dev->regs[0] = dev->regs[0] & 0xef;
4169
4170 rts8891_write_all (dev->devnum, dev->regs, dev->reg_count);
4171 /* now read button status read_reg(0x1a,2)=0x00 0x00 */
4172 sanei_rts88xx_read_regs (dev->devnum, 0x1a, dev->regs + 0x1a, 2);
4173 /* we expect 0x00 0x00 here */
4174 DBG (DBG_io, "init_device: 0x%02x 0x%02x\n", dev->regs[0x1a],
4175 dev->regs[0x1b]);
4176
4177 dev->regs[0xcf] = 0x00;
4178 dev->regs[0xd0] = 0xe0;
4179 rts8891_write_all (dev->devnum, dev->regs, dev->reg_count);
4180 sanei_rts88xx_read_regs (dev->devnum, 0x1a, dev->regs + 0x1a, 2);
4181 /* we expect 0x08 0x00 here */
4182 DBG (DBG_io, "init_device: 0x%02x 0x%02x\n", dev->regs[0x1a],
4183 dev->regs[0x1b]);
4184
4185 sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x20, 0x28);
4186 sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x28);
4187 sanei_rts88xx_cancel (dev->devnum);
4188 sanei_rts88xx_read_reg (dev->devnum, LAMP_REG, &control);
4189 sanei_rts88xx_write_control (dev->devnum, 0x00);
4190 sanei_rts88xx_write_control (dev->devnum, 0x00);
4191 sanei_rts88xx_read_reg (dev->devnum, LINK_REG, &id);
4192 if (id != 0x00 && id != 0x01)
4193 {
4194 DBG (DBG_warn, "init_device: got unexpected id 0x%02x\n", id);
4195 }
4196
4197
4198 dev->regs[0x12] = 0xff;
4199 dev->regs[0x14] = 0xf8;
4200 dev->regs[0x15] = 0x28;
4201 dev->regs[0x16] = 0x07;
4202 dev->regs[0x18] = 0xff;
4203 dev->regs[0x23] = 0xff;
4204 dev->regs[0x24] = 0xff;
4205
4206 dev->regs[0x72] = 0xe1;
4207 dev->regs[0x73] = 0x14;
4208 dev->regs[0x74] = 0x18;
4209 dev->regs[0x75] = 0x15;
4210 dev->regs[0xc0] = 0xff;
4211 dev->regs[0xc1] = 0x0f;
4212 dev->regs[0xc3] = 0xff;
4213 dev->regs[0xc4] = 0xff;
4214 dev->regs[0xc5] = 0xff;
4215 dev->regs[0xc6] = 0xff;
4216 dev->regs[0xc7] = 0xff;
4217 dev->regs[0xc8] = 0xff;
4218 dev->regs[0xca] = 0x0e;
4219 dev->regs[0xcd] = 0xf0;
4220 dev->regs[0xce] = 0xff;
4221 dev->regs[0xcf] = 0xf5;
4222 dev->regs[0xd0] = 0xf7;
4223 dev->regs[0xd1] = 0xea;
4224 dev->regs[0xd2] = 0x0b;
4225 dev->regs[0xd3] = 0x03;
4226 dev->regs[0xd4] = 0x05;
4227 dev->regs[0xd7] = 0x30;
4228 dev->regs[0xd8] = 0xf6;
4229 dev->regs[0xd9] = 0x80;
4230 rts8891_write_all (dev->devnum, dev->regs, dev->reg_count);
4231
4232 /* now we are writing and reading back from memory, it is surely a memory test since the written data
4233 * don't look useful at first glance
4234 */
4235 reg = 0x06;
4236 sanei_rts88xx_write_reg (dev->devnum, 0x93, ®);
4237 for (i = 0; i < 2072; i++)
4238 {
4239 buffer[i] = i % 97;
4240 }
4241 sanei_rts88xx_set_mem (dev->devnum, 0x81, 0x00, 2072, buffer);
4242 sanei_rts88xx_get_mem (dev->devnum, 0x81, 0x00, 2072, buffer);
4243 /* check the data returned */
4244 for (i = 0; i < 2072; i++)
4245 {
4246 if (buffer[i] != id)
4247 {
4248 DBG (DBG_error,
4249 "init_device: memory at %d is not 0x%02d (0x%02x)\n", i, id,
4250 buffer[i]);
4251 /* XXX STEF XXX return SANE_STATUS_IO_ERROR; */
4252 }
4253 }
4254 DBG (DBG_info, "init_device: memory set #1 passed\n");
4255
4256 /* now test (or set?) #2 */
4257 reg = 0x02;
4258 sanei_rts88xx_write_reg (dev->devnum, 0x93, ®);
4259 for (i = 0; i < 2072; i++)
4260 {
4261 buffer[i] = i % 97;
4262 }
4263 sanei_rts88xx_set_mem (dev->devnum, 0x81, 0x00, 2072, buffer);
4264 sanei_rts88xx_get_mem (dev->devnum, 0x81, 0x00, 2072, buffer);
4265 /* check the data returned */
4266 for (i = 0; i < 970; i++)
4267 {
4268 if (buffer[i] != (i + 0x36) % 97)
4269 {
4270 DBG (DBG_error,
4271 "init_device: memory at %d is not 0x%02x (0x%02x)\n", i,
4272 (i + 0x36) % 97, buffer[i]);
4273 /* XXX STEF XXX return SANE_STATUS_IO_ERROR; */
4274 }
4275 }
4276 for (i = 993; i < 2072; i++)
4277 {
4278 if (buffer[i] != i % 97)
4279 {
4280 DBG (DBG_error,
4281 "init_device: memory at %d is invalid 0x%02x, instead of 0x%02x\n",
4282 i, buffer[i], i % 97);
4283 /* XXX STEF XXX return SANE_STATUS_IO_ERROR; */
4284 }
4285 }
4286 DBG (DBG_info, "init_device: memory set #2 passed\n");
4287
4288
4289 /* now test (or set?) #3 */
4290 reg = 0x01;
4291 sanei_rts88xx_write_reg (dev->devnum, 0x93, ®);
4292 for (i = 0; i < 2072; i++)
4293 {
4294 buffer[i] = i % 97;
4295 }
4296 sanei_rts88xx_set_mem (dev->devnum, 0x81, 0x00, 2072, buffer);
4297 sanei_rts88xx_get_mem (dev->devnum, 0x81, 0x00, 2072, buffer);
4298 /* check the data returned */
4299 for (i = 0; i < 2072; i++)
4300 {
4301 if (buffer[i] != i % 97)
4302 {
4303 DBG (DBG_error,
4304 "init_device: memory at %d is invalid 0x%02x, instead of 0x%02x\n",
4305 i, buffer[i], i % 97);
4306 return SANE_STATUS_IO_ERROR;
4307 }
4308 }
4309 DBG (DBG_info, "init_device: memory set #3 passed\n");
4310
4311 /* we are writing page after page the same pattern, and reading at page 0 until we find we have 'wrapped' */
4312 /* this is surely some memory amount/number pages detection */
4313 dev->regs[0x91] = 0x00; /* page 0 ? */
4314 dev->regs[0x92] = 0x00;
4315 dev->regs[0x93] = 0x01;
4316 rts8891_write_all (dev->devnum, dev->regs, dev->reg_count);
4317
4318 /* write pattern at page 0 */
4319 for (i = 0; i < 32; i += 2)
4320 {
4321 buffer[i] = i;
4322 buffer[i + 1] = 0x00;
4323 }
4324 sanei_rts88xx_set_mem (dev->devnum, 0x00, 0x00, 32, buffer);
4325
4326 page = 0;
4327 do
4328 {
4329 /* next page */
4330 page++;
4331
4332 /* fill buffer with pattern for page */
4333 for (i = 0; i < 32; i += 2)
4334 {
4335 buffer[i] = i;
4336 buffer[i + 1] = page;
4337 }
4338 /* write it to memory */
4339 sanei_rts88xx_set_mem (dev->devnum, 0x00, page * 16, 32, buffer);
4340 /* read memory from page 0 */
4341 sanei_rts88xx_get_mem (dev->devnum, 0x00, 0x00, 32, buffer);
4342 for (i = 0; i < 32; i += 2)
4343 {
4344 if (buffer[i] != i)
4345 {
4346 DBG (DBG_error,
4347 "init_device: memory at %d is invalid: 0x%02x instead of 0x%02x\n",
4348 i, buffer[i], i);
4349 return SANE_STATUS_IO_ERROR;
4350 }
4351 if (buffer[i + 1] != page && buffer[i + 1] != 0)
4352 {
4353 DBG (DBG_error,
4354 "init_device: page %d, memory at %d is invalid: 0x%02x instead of 0x%02x\n",
4355 page, i + 1, buffer[i + 1], 0);
4356 return SANE_STATUS_IO_ERROR;
4357 }
4358 }
4359 }
4360 while (buffer[1] == 0);
4361 DBG (DBG_info, "init_device: %d pages detected\n", page - 1);
4362
4363 sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control);
4364 sanei_rts88xx_read_reg (dev->devnum, CONTROLER_REG, &control);
4365 if (!(control & 0x02))
4366 {
4367 if (park_head (dev, SANE_TRUE) != SANE_STATUS_GOOD)
4368 {
4369 DBG (DBG_error, "init_device: failed to park head!\n");
4370 return SANE_STATUS_IO_ERROR;
4371 }
4372 }
4373 reg = 0x80;
4374 sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®);
4375 reg = 0xad;
4376 sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®);
4377 sanei_rts88xx_read_regs (dev->devnum, 0x14, dev->regs + 0x14, 2);
4378 /* we expect 0xF8 0x28 here */
4379 dev->regs[0x14] = dev->regs[0x14] & 0x7F;
4380 sanei_rts88xx_write_regs (dev->devnum, 0x14, dev->regs + 0x14, 2);
4381
4382 /* reads scanner status */
4383 sanei_rts88xx_get_status (dev->devnum, dev->regs);
4384 DBG (DBG_io, "init_device: status=0x%02x 0x%02x\n", dev->regs[0x10],
4385 dev->regs[0x11]);
4386 sanei_rts88xx_read_reg (dev->devnum, LINK_REG, &control);
4387 DBG (DBG_io, "init_device: link=0x%02x\n", control);
4388 sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control);
4389 sanei_rts88xx_reset_lamp (dev->devnum, dev->regs);
4390 reg = 0x8d;
4391 sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®);
4392 reg = 0xad;
4393 sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®);
4394
4395 /* here, we are in iddle state */
4396
4397 /* check link status (scanner still plugged) */
4398 sanei_rts88xx_read_reg (dev->devnum, LINK_REG, &control);
4399 DBG (DBG_io, "init_device: link=0x%02x\n", control);
4400
4401 /* this block appears twice */
4402 sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control);
4403 if (control != 0)
4404 {
4405 DBG (DBG_warn, "init_device: unexpected control value 0x%02x\n",
4406 control);
4407 }
4408 sanei_rts88xx_reset_lamp (dev->devnum, dev->regs);
4409 sanei_rts88xx_read_reg (dev->devnum, 0x40, ®);
4410 reg |= 0x80;
4411 sanei_rts88xx_read_reg (dev->devnum, 0x40, ®);
4412 sanei_rts88xx_read_reg (dev->devnum, 0x10, ®);
4413 sanei_rts88xx_read_reg (dev->devnum, 0x14, ®);
4414 reg = 0x78;
4415 sanei_rts88xx_write_reg (dev->devnum, 0x10, ®);
4416 reg = 0x38;
4417 sanei_rts88xx_write_reg (dev->devnum, 0x14, ®);
4418 reg = 0x78;
4419 sanei_rts88xx_write_reg (dev->devnum, 0x10, ®);
4420 reg = 0x01;
4421 sanei_rts88xx_write_reg (dev->devnum, CONTROLER_REG, ®);
4422
4423 /* now we init nvram */
4424 /* this is highly dangerous and thus deactivated
4425 * in sanei_rts88xx_setup_nvram (HAZARDOUS_EXPERIMENT #define) */
4426 sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd1);
4427 sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd2);
4428 sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd3);
4429 sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x28);
4430
4431 /* second occurrence of this block */
4432 sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control);
4433 if (control != 0)
4434 {
4435 DBG (DBG_warn, "init_device: unexpected control value 0x%02x\n",
4436 control);
4437 }
4438 sanei_rts88xx_reset_lamp (dev->devnum, dev->regs);
4439 sanei_rts88xx_read_reg (dev->devnum, 0x40, ®);
4440 reg |= 0x80;
4441 sanei_rts88xx_read_reg (dev->devnum, 0x40, ®);
4442 sanei_rts88xx_read_reg (dev->devnum, 0x10, ®);
4443 sanei_rts88xx_read_reg (dev->devnum, 0x14, ®);
4444 reg = 0x78;
4445 sanei_rts88xx_write_reg (dev->devnum, 0x10, ®);
4446 reg = 0x38;
4447 sanei_rts88xx_write_reg (dev->devnum, 0x14, ®);
4448 reg = 0x78;
4449 sanei_rts88xx_write_reg (dev->devnum, 0x10, ®);
4450 reg = 0x01;
4451 sanei_rts88xx_write_reg (dev->devnum, CONTROLER_REG, ®);
4452
4453 /* nvram again */
4454 /* this is highly dangerous and commented out in rts88xx_lib */
4455 sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd4);
4456 sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd5);
4457 sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd6);
4458 sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd7);
4459
4460 sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x28);
4461
4462 /* then we do a simple scan to detect a black zone to locate scan area */
4463 sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control);
4464 if (control != 0)
4465 {
4466 DBG (DBG_warn, "init_device: unexpected control value 0x%02x\n",
4467 control);
4468 }
4469 sanei_rts88xx_reset_lamp (dev->devnum, dev->regs);
4470 sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control);
4471 if (control != 0)
4472 {
4473 DBG (DBG_warn, "init_device: unexpected control value 0x%02x\n",
4474 control);
4475 }
4476 sanei_rts88xx_write_control (dev->devnum, 0x01);
4477 sanei_rts88xx_write_control (dev->devnum, 0x01);
4478 sanei_rts88xx_write_control (dev->devnum, 0x00);
4479 sanei_rts88xx_write_control (dev->devnum, 0x00);
4480 dev->regs[0x12] = 0xff;
4481 dev->regs[0x13] = 0x20;
4482 sanei_rts88xx_write_regs (dev->devnum, 0x12, dev->regs + 0x12, 2);
4483 dev->regs[0x14] = 0xf8;
4484 dev->regs[0x15] = 0x28;
4485 sanei_rts88xx_write_regs (dev->devnum, 0x14, dev->regs + 0x14, 2);
4486 reg = 0;
4487 sanei_rts88xx_write_control (dev->devnum, 0x00);
4488 sanei_rts88xx_write_control (dev->devnum, 0x00);
4489 sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x28);
4490 reg = 0x80;
4491 sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®);
4492
4493 dev->regs[0x8b] = 0xff;
4494 dev->regs[0x8c] = 0x3f;
4495 dev->regs[LAMP_REG] = 0xad;
4496 rts8891_write_all (dev->devnum, dev->regs, dev->reg_count);
4497
4498 set_lamp_brightness (dev, 0);
4499 dev->initialized = SANE_TRUE;
4500 DBG (DBG_proc, "init_device: exit\n");
4501 return status;
4502 }
4503 #endif /* FAST_INIT */
4504
4505 #ifdef FAST_INIT
4506 /*
4507 * This function detects the scanner
4508 */
4509 static SANE_Status
detect_device(struct Rts8891_Device *dev)4510 detect_device (struct Rts8891_Device *dev)
4511 {
4512 /*
4513 --- 5 74945 bulk_out len 4 wrote 0x80 0xb0 0x00 0x01
4514 --- 6 74946 bulk_in len 1 read 0x80
4515 --- 7 74947 bulk_out len 4 wrote 0x80 0xb3 0x00 0x01
4516 --- 8 74948 bulk_in len 1 read 0x04
4517 --- 9 74949 bulk_out len 4 wrote 0x80 0xb1 0x00 0x01
4518 --- 10 74950 bulk_in len 1 read 0x00
4519 --- 11 74951 bulk_out len 5 wrote 0x88 0xb3 0x00 0x01 0x00
4520 --- 12 74952 bulk_out len 5 wrote 0x88 0xb3 0x00 0x01 0x00
4521 --- 13 74953 bulk_out len 4 wrote 0x80 0x00 0x00 0xf4
4522 --- 14 74954 bulk_in len 192 read 0xf5 0x41 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x70 0x00 0x00 0x00 0x00 0x60 0x1b 0xff 0x3e 0x00 0x00 0xff 0x3e 0x00 0x00 0x00 0x00 0x00 0x22 0x00 0x00 0x00 0x00 0x00 0xff 0x00 0xff 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x42 0x00 0x00 0x10 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x00 0x00 0x00 0x18 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x20 0x24 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x10 0x00 0x80 0x00 0x10 0x00 0x01 0x00 0x00 0x10 0x00 0x00 0x20 0x20 0x00 0x00 0x00 0x00 0x20 0x01 0x00 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x41 0x00 0x10 0x21 0x20 0x00 0x20 0x81 0x20 0x01 0x01 0x00 0x22 0x00 0x40 0x05 0x00 0x00 0x01 0x1e 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xcc 0x27 0x64 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x00 0x06 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
4523 --- 15 74955 bulk_in len 52 read 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x06 0x1b 0x10 0x7a 0x00 0x15 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
4524 */
4525 SANE_Status status = SANE_STATUS_GOOD;
4526 SANE_Byte control;
4527 char message[256 * 5];
4528 int i;
4529
4530 DBG (DBG_proc, "detect_device: start\n");
4531
4532 /* read "b0" register */
4533 sanei_rts88xx_read_reg (dev->devnum, 0xb0, &control);
4534 DBG (DBG_io, "detect_device: reg[b0]=0x%02x\n", control);
4535
4536 /* we expect to get 0x80 */
4537 if (control != 0x80)
4538 {
4539 DBG (DBG_warn, "detect_device: expected reg[b0]=0x80, got 0x%02x\n",
4540 control);
4541 /* TODO : fail here ? */
4542 }
4543
4544 /* read control register, if busy, something will have to be done ... */
4545 sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control);
4546
4547 /* when just plugged, we expect to get 0x04 */
4548 if (control != 0x04)
4549 {
4550 DBG (DBG_warn, "detect_device: expected control=0x04, got 0x%02x\n",
4551 control);
4552 /* TODO ok if re-run without plugging */
4553 }
4554
4555 /* read "LINK" register */
4556 sanei_rts88xx_read_reg (dev->devnum, LINK_REG, &control);
4557 DBG (DBG_io, "detect_device: LINK_REG=0x%02x\n", control);
4558
4559 /* we expect to get 0x00 */
4560 if (control != 0x00)
4561 {
4562 DBG (DBG_warn, "detect_device: expected LINK_REG=0x00, got 0x%02x\n",
4563 control);
4564 }
4565
4566 /* write 0x00 twice to control: cancel/stop ? */
4567 control = 0x00;
4568 sanei_rts88xx_write_control (dev->devnum, control);
4569 sanei_rts88xx_write_control (dev->devnum, control);
4570
4571 /* read initial register set */
4572 sanei_rts88xx_read_regs (dev->devnum, 0, dev->regs, dev->reg_count);
4573 if (DBG_LEVEL >= DBG_io2)
4574 {
4575 sprintf (message, "init_device: initial register settings: ");
4576 for (i = 0; i < dev->reg_count; i++)
4577 sprintf (message + strlen (message), "0x%02x ", dev->regs[i]);
4578 sprintf (message + strlen (message), "\n");
4579 DBG (DBG_io2, message);
4580 }
4581
4582 /* initial sensor guess */
4583 val = dev->regs[0x44] + 256 * dev->regs[0x45];
4584 DBG (DBG_io, "detect_device: R44/45=0x%04x\n", val);
4585 if (dev->sensor == SENSOR_TYPE_4400 && val == 0x00)
4586 {
4587 dev->sensor = SENSOR_TYPE_4400_BARE;
4588 DBG (DBG_info, "detect_device: changing to SENSOR_TYPE_4400_BARE\n");
4589 }
4590
4591 DBG (DBG_io, "detect_device: status=0x%02x 0x%02x\n", dev->regs[0x10],
4592 dev->regs[0x11]);
4593 DBG (DBG_io, "detect_device: lamp status=0x%02x\n", dev->regs[0x8e]);
4594
4595 dev->initialized = SANE_FALSE;
4596 DBG (DBG_proc, "detect_device: exit\n");
4597 return status;
4598 }
4599 #endif
4600
4601 /**
4602 * Do dark calibration. We scan a well defined area until average pixel value
4603 * of the black area is about 0x03 for each color channel. This calibration is
4604 * currently done at 75 dpi regardless of the final scan dpi.
4605 */
4606 static SANE_Status
dark_calibration(struct Rts8891_Device *dev, int mode, int light)4607 dark_calibration (struct Rts8891_Device *dev, int mode, int light)
4608 {
4609 SANE_Status status = SANE_STATUS_GOOD;
4610 /* red, green and blue offset, within a 't'op and 'b'ottom value */
4611 int ro = 250, tro = 250, bro = 0;
4612 int bo = 250, tbo = 250, bbo = 0;
4613 int go = 250, tgo = 250, bgo = 0;
4614 unsigned char image[CALIBRATION_SIZE];
4615 float global, ra, ga, ba;
4616 int num = 0;
4617 char name[32];
4618
4619 DBG (DBG_proc, "dark_calibration: start\n");
4620
4621 /* set up sensor specific bottom values */
4622 if (dev->sensor == SENSOR_TYPE_4400)
4623 {
4624 bro = 128;
4625 bgo = 128;
4626 bbo = 128;
4627 }
4628
4629 /* set up starting values */
4630 sanei_rts88xx_set_gain (dev->regs, 0, 0, 0);
4631 sanei_rts88xx_set_scan_area (dev->regs, 1, 2, 4, 4 + CALIBRATION_WIDTH);
4632
4633 sanei_rts88xx_set_status (dev->devnum, dev->regs, mode, light);
4634
4635 dev->regs[0x00] = 0xe5; /* scan */
4636 dev->regs[0x32] = 0x00;
4637 dev->regs[0x33] = 0x03;
4638 dev->regs[0x35] = 0x45;
4639 dev->regs[0x36] = 0x22;
4640 dev->regs[0x3a] = 0x43;
4641
4642 dev->regs[0x8d] = 0x00;
4643 dev->regs[0x8e] = 0x60;
4644
4645 dev->regs[0xb2] = 0x02;
4646
4647 dev->regs[0xc0] = 0x06;
4648 dev->regs[0xc1] = 0xe6;
4649 dev->regs[0xc2] = 0x67;
4650 dev->regs[0xc9] = 0x07;
4651 dev->regs[0xca] = 0x00;
4652 dev->regs[0xcb] = 0xfe;
4653 dev->regs[0xcc] = 0xf9;
4654 dev->regs[0xcd] = 0x19;
4655 dev->regs[0xce] = 0x98;
4656 dev->regs[0xcf] = 0xe8;
4657 dev->regs[0xd0] = 0xea;
4658 dev->regs[0xd1] = 0xf3;
4659 dev->regs[0xd2] = 0x14;
4660 dev->regs[0xd3] = 0x02;
4661 dev->regs[0xd4] = 0x04;
4662 dev->regs[0xd6] = 0x0f;
4663 dev->regs[0xd8] = 0x52;
4664 dev->regs[0xe2] = 0x1f;
4665
4666 /*dev->regs[0xe5] = 0x28; 28=40
4667 dev->regs[0xe6] = 0x00; */
4668 SET_DOUBLE (dev->regs, EXPOSURE_REG, 40);
4669
4670 dev->regs[0xe7] = 0x75;
4671 dev->regs[0xe8] = 0x01;
4672 dev->regs[0xe9] = 0x0b;
4673 dev->regs[0xea] = 0x54;
4674 dev->regs[0xeb] = 0x01;
4675 dev->regs[0xec] = 0x04;
4676 dev->regs[0xed] = 0xb8;
4677 dev->regs[0xef] = 0x03;
4678 dev->regs[0xf0] = 0x70;
4679 dev->regs[0xf2] = 0x01;
4680
4681 /* handling of different sensors */
4682 if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400)
4683 {
4684 dev->regs[0xc0] = 0x67;
4685 dev->regs[0xc1] = 0x06;
4686 dev->regs[0xc2] = 0xe6;
4687 dev->regs[0xc3] = 0x98;
4688 dev->regs[0xc4] = 0xf9;
4689 dev->regs[0xc5] = 0x19;
4690 dev->regs[0xc6] = 0x67;
4691 dev->regs[0xc7] = 0x06;
4692 dev->regs[0xc8] = 0xe6;
4693 dev->regs[0xc9] = 0x01;
4694 dev->regs[0xca] = 0xf8;
4695 dev->regs[0xcb] = 0xff;
4696 dev->regs[0xcc] = 0x98;
4697 dev->regs[0xcd] = 0xf9;
4698 dev->regs[0xce] = 0x19;
4699 dev->regs[0xcf] = 0xe0;
4700 dev->regs[0xd0] = 0xe2;
4701 dev->regs[0xd1] = 0xeb;
4702 dev->regs[0xd2] = 0x0c;
4703 dev->regs[0xd7] = 0x10;
4704 dev->regs[0xda] = 0xa7;
4705 }
4706 if (dev->sensor == SENSOR_TYPE_4400)
4707 {
4708 dev->regs[0x13] = 0x39; /* 0x20 */
4709 dev->regs[0x14] = 0xf0; /* 0xf8 */
4710 dev->regs[0x15] = 0x29; /* 0x28 */
4711 dev->regs[0x16] = 0x0f; /* 0x07 */
4712 dev->regs[0x17] = 0x10; /* 0x00 */
4713 dev->regs[0x23] = 0x00; /* 0xff */
4714 dev->regs[0x35] = 0x48; /* 0x45 */
4715 dev->regs[0x39] = 0x00; /* 0x02 */
4716 dev->regs[0xe2] = 0x0f; /* 0x1f */
4717 /* dev->regs[0xe5] = 0x52; 0x28 */
4718 SET_DOUBLE (dev->regs, EXPOSURE_REG, 82); /* 2*40+2 */
4719 dev->regs[0xe7] = 0x0e; /* 0x75 */
4720 dev->regs[0xe9] = 0x0a; /* 0x0b */
4721 dev->regs[0xea] = 0xc2; /* 0x54 */
4722 dev->regs[0xed] = 0xf6; /* 0xb8 */
4723 dev->regs[0xef] = 0x02; /* 0x03 */
4724 dev->regs[0xf0] = 0xa8; /* 0x70 */
4725 }
4726 if (dev->sensor == SENSOR_TYPE_4400_BARE)
4727 {
4728 dev->regs[0x13] = 0x39; /* 0x20 */
4729 dev->regs[0x14] = 0xf0; /* 0xf8 */
4730 dev->regs[0x15] = 0x29; /* 0x28 */
4731 dev->regs[0x16] = 0x0f; /* 0x07 */
4732 dev->regs[0x17] = 0x10; /* 0x00 */
4733 dev->regs[0x23] = 0x00; /* 0xff */
4734 dev->regs[0x35] = 0x48; /* 0x45 */
4735 dev->regs[0x39] = 0x00; /* 0x02 */
4736 dev->regs[0xda] = 0xa7; /* 0xa0 */
4737 dev->regs[0xe2] = 0x0f; /* 0x1f */
4738 SET_DOUBLE (dev->regs, EXPOSURE_REG, 82);
4739 dev->regs[0xe7] = 0x0e; /* 0x75 */
4740 dev->regs[0xe9] = 0x0a; /* 0x0b */
4741 dev->regs[0xea] = 0xc2; /* 0x54 */
4742 dev->regs[0xed] = 0xf6; /* 0xb8 */
4743 dev->regs[0xef] = 0x02; /* 0x03 */
4744 dev->regs[0xf0] = 0xa8; /* 0x70 */
4745 }
4746
4747 /* we loop scanning a 637 (1911 bytes) pixels wide area in color mode
4748 * until each black average reaches the desired value */
4749 sanei_rts88xx_set_status (dev->devnum, dev->regs, mode, light);
4750 do
4751 {
4752 /* set scan with the values to try */
4753 sanei_rts88xx_set_offset (dev->regs, ro, go, bo);
4754 DBG (DBG_info, "dark_calibration: trying offsets=(%d,%d,%d)\n", ro, go,
4755 bo);
4756
4757 /* do scan */
4758 status =
4759 rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, 0x02,
4760 CALIBRATION_SIZE, image);
4761 if (status != SANE_STATUS_GOOD)
4762 {
4763 DBG (DBG_error, "dark_calibration: failed to scan\n");
4764 return status;
4765 }
4766
4767 /* save scanned picture for data debugging */
4768 if (DBG_LEVEL >= DBG_io2)
4769 {
4770 sprintf (name, "dark%03d.pnm", num);
4771 write_rgb_data (name, image, CALIBRATION_WIDTH, 1);
4772 num++;
4773 }
4774
4775 /* we now compute the average of red pixels from the first 15 pixels */
4776 global = average_area (SANE_TRUE, image, 15, 1, &ra, &ga, &ba);
4777 DBG (DBG_info,
4778 "dark_calibration: global=%.2f, channels=(%.2f,%.2f,%.2f)\n",
4779 global, ra, ga, ba);
4780
4781 /* dichotomie ... */
4782 if (fabs (ra - DARK_TARGET) < DARK_MARGIN)
4783 {
4784 /* offset is OK */
4785 tro = ro;
4786 bro = ro;
4787 }
4788 else
4789 { /* NOK */
4790 if (ra > DARK_TARGET)
4791 {
4792 tro = ro;
4793 ro = (tro + bro) / 2;
4794 }
4795 if (ra < DARK_TARGET)
4796 {
4797 bro = ro;
4798 ro = (tro + bro + 1) / 2;
4799 }
4800
4801 }
4802
4803 /* same for blue channel */
4804 if (fabs (ba - DARK_TARGET) < DARK_MARGIN)
4805 {
4806 bbo = bo;
4807 tbo = bo;
4808 }
4809 else
4810 { /* NOK */
4811 if (ba > DARK_TARGET)
4812 {
4813 tbo = bo;
4814 bo = (tbo + bbo) / 2;
4815 }
4816 if (ba < DARK_TARGET)
4817 {
4818 bbo = bo;
4819 bo = (tbo + bbo + 1) / 2;
4820 }
4821
4822 }
4823
4824 /* and for green channel */
4825 if (fabs (ga - DARK_TARGET) < DARK_MARGIN)
4826 {
4827 tgo = go;
4828 bgo = go;
4829 }
4830 else
4831 { /* NOK */
4832 if (ga > DARK_TARGET)
4833 {
4834 tgo = go;
4835 go = (tgo + bgo) / 2;
4836 }
4837 if (ga < DARK_TARGET)
4838 {
4839 bgo = go;
4840 go = (tgo + bgo + 1) / 2;
4841 }
4842 }
4843 }
4844 while ((tro != bro) || (tgo != bgo) || (tbo != bbo));
4845
4846 /* store detected values in device struct */
4847 dev->red_offset = bro;
4848 dev->green_offset = bgo;
4849 dev->blue_offset = bbo;
4850
4851 DBG (DBG_info, "dark_calibration: final offsets=(%d,%d,%d)\n", bro, bgo,
4852 bbo);
4853 DBG (DBG_proc, "dark_calibration: exit\n");
4854 return status;
4855 }
4856
4857 /*
4858 * do gain calibration. We do scans until averaged values of the area match
4859 * the target code. We're doing a dichotomy again.
4860 */
4861 static SANE_Status
gain_calibration(struct Rts8891_Device *dev, int mode, int light)4862 gain_calibration (struct Rts8891_Device *dev, int mode, int light)
4863 {
4864 SANE_Status status = SANE_STATUS_GOOD;
4865 float global, ra, ga, ba;
4866 /* previous values */
4867 int xrg, xbg, xgg;
4868 /* current gains */
4869 int rg, bg, gg;
4870 /* intervals for dichotomy */
4871 int trg, tbg, tgg, bgg, brg, bbg;
4872 int num = 0;
4873 char name[32];
4874 int width = CALIBRATION_WIDTH;
4875 int length = CALIBRATION_SIZE;
4876 unsigned char image[CALIBRATION_SIZE];
4877 int pass = 0;
4878 int timing=0;
4879
4880 int xstart = (dev->left_offset * 75) / dev->model->max_xdpi;
4881
4882 DBG (DBG_proc, "gain_calibration: start\n");
4883
4884 /* set up starting values */
4885 sanei_rts88xx_set_scan_area (dev->regs, 1, 2, xstart, xstart + width);
4886 sanei_rts88xx_set_offset (dev->regs, dev->red_offset, dev->green_offset,
4887 dev->blue_offset);
4888
4889 /* same register set than dark calibration */
4890 dev->regs[0x32] = 0x00;
4891 dev->regs[0x33] = 0x03;
4892 dev->regs[0x35] = 0x45;
4893 dev->regs[0x36] = 0x22;
4894 dev->regs[0x3a] = 0x43;
4895
4896 dev->regs[0x8d] = 0x00;
4897 dev->regs[0x8e] = 0x60;
4898
4899 dev->regs[0xb2] = 0x02;
4900
4901 dev->regs[0xc0] = 0x06;
4902 dev->regs[0xc1] = 0xe6;
4903 dev->regs[0xc2] = 0x67;
4904 dev->regs[0xc9] = 0x07;
4905 dev->regs[0xca] = 0x00;
4906 dev->regs[0xcb] = 0xfe;
4907 dev->regs[0xcc] = 0xf9;
4908 dev->regs[0xcd] = 0x19;
4909 dev->regs[0xce] = 0x98;
4910 dev->regs[0xcf] = 0xe8;
4911 dev->regs[0xd0] = 0xea;
4912 dev->regs[0xd1] = 0xf3;
4913 dev->regs[0xd2] = 0x14;
4914 dev->regs[0xd3] = 0x02;
4915 dev->regs[0xd4] = 0x04;
4916 dev->regs[0xd6] = 0x0f;
4917 dev->regs[0xd8] = 0x52;
4918 dev->regs[0xe2] = 0x1f;
4919
4920 /* dev->regs[0xe5] = 0x28;
4921 dev->regs[0xe6] = 0x00; 28=40 */
4922 SET_DOUBLE (dev->regs, EXPOSURE_REG, 40);
4923
4924 dev->regs[0xe7] = 0x75;
4925 dev->regs[0xe8] = 0x01;
4926 dev->regs[0xe9] = 0x0b;
4927 dev->regs[0xea] = 0x54;
4928 dev->regs[0xeb] = 0x01;
4929 dev->regs[0xec] = 0x04;
4930 dev->regs[0xed] = 0xb8;
4931 dev->regs[0xef] = 0x03;
4932 dev->regs[0xf0] = 0x70;
4933 dev->regs[0xf2] = 0x01;
4934
4935 dev->regs[0x72] = 0xe1;
4936 dev->regs[0x73] = 0x14;
4937 dev->regs[0x74] = 0x18;
4938
4939 dev->regs[0xc3] = 0xff;
4940 dev->regs[0xc4] = 0xff;
4941 dev->regs[0xc7] = 0xff;
4942 dev->regs[0xc8] = 0xff;
4943
4944 dev->regs[0xd7] = 0x30;
4945
4946 if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400)
4947 {
4948 dev->regs[0xc0] = 0x67;
4949 dev->regs[0xc1] = 0x06;
4950 dev->regs[0xc2] = 0xe6;
4951 dev->regs[0xc3] = 0x98;
4952 dev->regs[0xc4] = 0xf9;
4953 dev->regs[0xc5] = 0x19;
4954 dev->regs[0xc6] = 0x67;
4955 dev->regs[0xc7] = 0x06;
4956 dev->regs[0xc8] = 0xe6;
4957 dev->regs[0xc9] = 0x01;
4958 dev->regs[0xca] = 0xf8;
4959 dev->regs[0xcb] = 0xff;
4960 dev->regs[0xcc] = 0x98;
4961 dev->regs[0xcd] = 0xf9;
4962 dev->regs[0xce] = 0x19;
4963 dev->regs[0xcf] = 0xe0;
4964 dev->regs[0xd0] = 0xe2;
4965 dev->regs[0xd1] = 0xeb;
4966 dev->regs[0xd2] = 0x0c;
4967 dev->regs[0xd3] = 0x02;
4968 dev->regs[0xd4] = 0x04;
4969 dev->regs[0xd6] = 0x0f;
4970 dev->regs[0xd7] = 0x10;
4971 dev->regs[0xd8] = 0x52;
4972 dev->regs[0xe2] = 0x1f;
4973 /* dev->regs[0xe5] = 0x28; 0028 -> 40
4974 dev->regs[0xe6] = 0x00; */
4975 SET_DOUBLE (dev->regs, EXPOSURE_REG, 40);
4976 dev->regs[0xe7] = 0x75;
4977 dev->regs[0xe8] = 0x01;
4978 dev->regs[0xe9] = 0x0b;
4979 dev->regs[0xea] = 0x54;
4980 dev->regs[0xeb] = 0x01;
4981 dev->regs[0xec] = 0x04;
4982 dev->regs[0xed] = 0xb8;
4983 dev->regs[0xef] = 0x03;
4984 dev->regs[0xf0] = 0x70;
4985 dev->regs[0xf2] = 0x01;
4986 }
4987 if (dev->sensor == SENSOR_TYPE_4400)
4988 {
4989 dev->regs[0x35] = 0x48; /* 0x45 */
4990 /* c5, c6 ? : untouched from previous scan ... */
4991 dev->regs[0xe2] = 0x0f; /* 0x1f */
4992 /* dev->regs[0xe5] = 0x52; */
4993 SET_DOUBLE (dev->regs, EXPOSURE_REG, 82); /* 2*40+2 */
4994 dev->regs[0xe7] = 0x0e; /* 0x75 */
4995 dev->regs[0xe9] = 0x0a; /* 0x0b */
4996 dev->regs[0xea] = 0xc2; /* 0x54 */
4997 dev->regs[0xed] = 0xf6; /* 0xb8 */
4998 dev->regs[0xef] = 0x02; /* 0x03 */
4999 dev->regs[0xf0] = 0xa8; /* 0x70 */
5000 }
5001 if (dev->sensor == SENSOR_TYPE_4400_BARE)
5002 {
5003 dev->regs[0x13] = 0x39;
5004 dev->regs[0x14] = 0xf0;
5005 dev->regs[0x15] = 0x29;
5006 dev->regs[0x16] = 0x0f;
5007 dev->regs[0x17] = 0x10;
5008 dev->regs[0x23] = 0x00;
5009 dev->regs[0x35] = 0x48;
5010 dev->regs[0x39] = 0x00;
5011 dev->regs[0xe2] = 0x0f;
5012 SET_DOUBLE (dev->regs, EXPOSURE_REG, 82);
5013 dev->regs[0xe7] = 0x0e;
5014 dev->regs[0xe9] = 0x0a;
5015 dev->regs[0xea] = 0xc2;
5016 dev->regs[0xed] = 0xf6;
5017 dev->regs[0xef] = 0x02;
5018 dev->regs[0xf0] = 0xa8;
5019
5020 timing=0x32;
5021 dev->regs[0x85] = 0x00;
5022 dev->regs[0x86] = 0x06;
5023 dev->regs[0x87] = 0x00;
5024 dev->regs[0x88] = 0x06;
5025 }
5026 SET_DOUBLE (dev->regs, TIMING_REG, timing);
5027 SET_DOUBLE (dev->regs, TIMING1_REG, timing+1);
5028 SET_DOUBLE (dev->regs, TIMING2_REG, timing+2);
5029
5030
5031 /* we loop scanning a 637 (1911 bytes) pixels wide area in color mode until each white average
5032 * reaches the desired value, doing a dichotomy */
5033 rg = 0x1f;
5034 bg = 0x1f;
5035 gg = 0x1f;
5036 /* dichotomy interval */
5037 /* bottom values */
5038 brg = 0;
5039 bgg = 0;
5040 bbg = 0;
5041 /* top values */
5042 trg = 0x1f;
5043 tgg = 0x1f;
5044 tbg = 0x1f;
5045
5046 /* loop on gain calibration until we find until we find stable value
5047 * or we do more than 20 tries */
5048 do
5049 {
5050 /* store current values as previous */
5051 xrg = rg;
5052 xbg = bg;
5053 xgg = gg;
5054
5055 /* set up for scan */
5056 DBG (DBG_info,
5057 "gain_calibration: trying gains=(0x%02x,0x%02x,0x%02x)\n", rg, gg,
5058 bg);
5059 sanei_rts88xx_set_gain (dev->regs, rg, gg, bg);
5060 sanei_rts88xx_set_status (dev->devnum, dev->regs, mode, light);
5061
5062 /* scan on line in RGB */
5063 status =
5064 rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, 0x02,
5065 length, image);
5066 if (status != SANE_STATUS_GOOD)
5067 {
5068 DBG (DBG_error, "gain_calibration: failed scan data\n");
5069 return status;
5070 }
5071
5072 /* save scanned picture for data debugging */
5073 if (DBG_LEVEL >= DBG_io2)
5074 {
5075 sprintf (name, "gain%03d.pnm", num);
5076 write_rgb_data (name, image, width, 1);
5077 num++;
5078 }
5079
5080 /* we now compute the average pixel value on the scanned line */
5081 /* TODO use computed left margin */
5082 global = average_area (SANE_TRUE, image, width, 1, &ra, &ga, &ba);
5083 DBG (DBG_info,
5084 "gain_calibration: global=%.2f, channels=(%.2f,%.2f,%.2f)\n",
5085 global, ra, ga, ba);
5086
5087 /* dichotomy again ... */
5088 if (fabs (ra - RED_GAIN_TARGET) < GAIN_MARGIN)
5089 {
5090 /* gain is OK, it is whitin the tolerance margin */
5091 trg = rg;
5092 brg = rg;
5093 }
5094 else
5095 { /* average is higher than the desired value */
5096 if (ra > RED_GAIN_TARGET)
5097 {
5098 /* changing gain for another channel alters other output */
5099 /* a stable value is shown by top value == bottom value */
5100 if (trg == brg)
5101 {
5102 brg--;
5103 rg = brg;
5104 }
5105 else
5106 {
5107 /* since we'ra above target value, current gain becomes top value */
5108 trg = rg;
5109 rg = (trg + brg) / 2;
5110 }
5111 }
5112 else /* below target value */
5113 {
5114 if (trg == brg)
5115 {
5116 trg++;
5117 rg = trg;
5118 }
5119 else
5120 {
5121 /* since we are below target, current value is assigned to bottom value */
5122 brg = rg;
5123 rg = (trg + brg + 1) / 2;
5124 }
5125 }
5126 }
5127
5128 /* same for blue channel */
5129 if (fabs (ba - BLUE_GAIN_TARGET) < GAIN_MARGIN)
5130 {
5131 bbg = bg;
5132 tbg = bg;
5133 }
5134 else
5135 { /* NOK */
5136 if (ba > BLUE_GAIN_TARGET)
5137 {
5138 if (tbg == bbg)
5139 {
5140 bbg--;
5141 bg = bbg;
5142 }
5143 else
5144 {
5145 tbg = bg;
5146 bg = (tbg + bbg) / 2;
5147 }
5148 }
5149 else
5150 {
5151 if (tbg == bbg)
5152 {
5153 tbg++;
5154 bg = tbg;
5155 }
5156 else
5157 {
5158 bbg = bg;
5159 bg = (tbg + bbg + 1) / 2;
5160 }
5161 }
5162 }
5163
5164 /* and for green channel */
5165 if (fabs (ga - GREEN_GAIN_TARGET) < GAIN_MARGIN)
5166 {
5167 tgg = gg;
5168 bgg = gg;
5169 }
5170 else
5171 { /* NOK */
5172 if (ga > GREEN_GAIN_TARGET)
5173 {
5174 if (tgg == bgg)
5175 {
5176 bgg--;
5177 gg = bgg;
5178 }
5179 else
5180 {
5181 tgg = gg;
5182 gg = (tgg + bgg) / 2;
5183 }
5184 }
5185 else
5186 {
5187 if (tgg == bgg)
5188 {
5189 tgg++;
5190 gg = tgg;
5191 }
5192 else
5193 {
5194 bgg = gg;
5195 gg = (tgg + bgg + 1) / 2;
5196 }
5197 }
5198 }
5199 pass++;
5200 }
5201 while ((pass < 20)
5202 && ((trg != brg && xrg != rg)
5203 || (tgg != bgg && xgg != gg) || (tbg != bbg && xbg != bg)));
5204
5205 /* store detected values in device struct */
5206 dev->red_gain = brg;
5207 dev->green_gain = bgg;
5208 dev->blue_gain = bbg;
5209 DBG (DBG_info, "gain_calibration: gain=(0x%02x,0x%02x,0x%02x)\n", brg, bgg,
5210 bbg);
5211
5212 DBG (DBG_proc, "gain_calibration: exit\n");
5213 return status;
5214 }
5215
5216 /**
5217 * Do fine offset calibration. Scans are done with gains from gain calibration
5218 * at 75 dpi regardless of the dpi of the final scan. We loop scanning a 637
5219 * (1911 bytes) pixels wide area in color mode until each black average
5220 * reaches the desired value (OFFSET_TARGET).
5221 */
5222 static SANE_Status
offset_calibration(struct Rts8891_Device *dev, int mode, int light)5223 offset_calibration (struct Rts8891_Device *dev, int mode, int light)
5224 {
5225
5226 SANE_Status status = SANE_STATUS_GOOD;
5227 /* red, green and blue offset, within a 't'op and 'b'ottom value */
5228 int ro = 250, tro = 250, bro = 123;
5229 int go = 250, tgo = 250, bgo = 123;
5230 int bo = 250, tbo = 250, bbo = 123;
5231 unsigned char image[CALIBRATION_SIZE];
5232 float global, ra, ga, ba;
5233 int num = 0;
5234 char name[32];
5235
5236 DBG (DBG_proc, "offset_calibration: start\n");
5237
5238 /* set up starting values */
5239 /* gains from previous step are a little higher than the one used */
5240 sanei_rts88xx_set_gain (dev->regs, dev->red_gain, dev->green_gain,
5241 dev->blue_gain);
5242 sanei_rts88xx_set_scan_area (dev->regs, 1, 2, 4, 4 + CALIBRATION_WIDTH);
5243
5244 dev->regs[0x32] = 0x00;
5245 dev->regs[0x33] = 0x03;
5246 dev->regs[0x35] = 0x45;
5247 dev->regs[0x36] = 0x22;
5248 dev->regs[0x3a] = 0x43;
5249
5250 dev->regs[0x8d] = 0x00;
5251 dev->regs[0x8e] = 0x60;
5252 dev->regs[0xb2] = 0x02;
5253 dev->regs[0xc0] = 0x06;
5254 dev->regs[0xc1] = 0xe6;
5255 dev->regs[0xc2] = 0x67;
5256 dev->regs[0xc9] = 0x07;
5257 dev->regs[0xca] = 0x00;
5258 dev->regs[0xcb] = 0xfe;
5259 dev->regs[0xcc] = 0xf9;
5260 dev->regs[0xcd] = 0x19;
5261 dev->regs[0xce] = 0x98;
5262 dev->regs[0xcf] = 0xe8;
5263 dev->regs[0xd0] = 0xea;
5264 dev->regs[0xd1] = 0xf3;
5265 dev->regs[0xd2] = 0x14;
5266 dev->regs[0xd3] = 0x02;
5267 dev->regs[0xd4] = 0x04;
5268 dev->regs[0xd6] = 0x0f;
5269 dev->regs[0xd8] = 0x52;
5270 dev->regs[0xe2] = 0x1f;
5271 /* dev->regs[0xe5] = 0x28;
5272 dev->regs[0xe6] = 0x00; 0x0028=40 */
5273 SET_DOUBLE (dev->regs, EXPOSURE_REG, 40);
5274 dev->regs[0xe7] = 0x75;
5275 dev->regs[0xe8] = 0x01;
5276 dev->regs[0xe9] = 0x0b;
5277 dev->regs[0xea] = 0x54;
5278 dev->regs[0xeb] = 0x01;
5279 dev->regs[0xec] = 0x04;
5280 dev->regs[0xed] = 0xb8;
5281 dev->regs[0xef] = 0x03;
5282 dev->regs[0xf0] = 0x70;
5283 dev->regs[0xf2] = 0x01;
5284 if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400)
5285 {
5286 dev->regs[0x72] = 0xe1;
5287 dev->regs[0x73] = 0x14;
5288 dev->regs[0x74] = 0x18;
5289
5290 dev->regs[0xc0] = 0x67;
5291 dev->regs[0xc1] = 0x06;
5292 dev->regs[0xc2] = 0xe6;
5293 dev->regs[0xc3] = 0x98;
5294 dev->regs[0xc4] = 0xf9;
5295 dev->regs[0xc5] = 0x19;
5296 dev->regs[0xc6] = 0x67;
5297 dev->regs[0xc7] = 0x06;
5298 dev->regs[0xc8] = 0xe6;
5299 dev->regs[0xc9] = 0x01;
5300 dev->regs[0xca] = 0xf8;
5301 dev->regs[0xcb] = 0xff;
5302 dev->regs[0xcc] = 0x98;
5303 dev->regs[0xcd] = 0xf9;
5304 dev->regs[0xce] = 0x19;
5305 dev->regs[0xcf] = 0xe0;
5306 dev->regs[0xd0] = 0xe2;
5307 dev->regs[0xd1] = 0xeb;
5308 dev->regs[0xd2] = 0x0c;
5309 dev->regs[0xd7] = 0x10;
5310 }
5311 if (dev->sensor == SENSOR_TYPE_4400)
5312 {
5313 dev->regs[0x35] = 0x48; /* 0x45 */
5314 /* c5,c6 ?? */
5315 dev->regs[0xe2] = 0x0f; /* 0x1f */
5316 /* dev->regs[0xe5] = 0x52; 0x28 */
5317 SET_DOUBLE (dev->regs, EXPOSURE_REG, 82); /* 2*40+2 */
5318 dev->regs[0xe7] = 0x0e; /* 0x75 */
5319 dev->regs[0xe9] = 0x0a; /* 0x0b */
5320 dev->regs[0xea] = 0xc2; /* 0x54 */
5321 dev->regs[0xed] = 0xf6; /* 0xb8 */
5322 dev->regs[0xef] = 0x02; /* 0x03 */
5323 dev->regs[0xf0] = 0xa8; /* 0x70 */
5324 }
5325 if (dev->sensor == SENSOR_TYPE_4400_BARE)
5326 {
5327 dev->regs[0x13] = 0x39; /* 0x20 */
5328 dev->regs[0x14] = 0xf0; /* 0xf8 */
5329 dev->regs[0x15] = 0x29; /* 0x28 */
5330 dev->regs[0x16] = 0x0f; /* 0x07 */
5331 dev->regs[0x17] = 0x10; /* 0x00 */
5332 dev->regs[0x23] = 0x00; /* 0xff */
5333 dev->regs[0x35] = 0x48; /* 0x45 */
5334 dev->regs[0x39] = 0x00; /* 0x02 */
5335 dev->regs[0xe2] = 0x0f; /* 0x1f */
5336 SET_DOUBLE (dev->regs, EXPOSURE_REG, 82); /* 2*40+2 */
5337 dev->regs[0xe7] = 0x0e; /* 0x75 */
5338 dev->regs[0xe9] = 0x0a; /* 0x0b */
5339 dev->regs[0xea] = 0xc2; /* 0x54 */
5340 dev->regs[0xed] = 0xf6; /* 0xb8 */
5341 dev->regs[0xef] = 0x02; /* 0x03 */
5342 dev->regs[0xf0] = 0xa8; /* 0x70 */
5343 }
5344
5345 /* we loop scanning a 637 (1911 bytes) pixels wide area in color mode until each black average
5346 * reaches the desired value */
5347 do
5348 {
5349 DBG (DBG_info, "offset_calibration: trying offsets=(%d,%d,%d) ...\n",
5350 ro, go, bo);
5351 sanei_rts88xx_set_offset (dev->regs, ro, go, bo);
5352 sanei_rts88xx_set_status (dev->devnum, dev->regs, mode, light);
5353 rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, 0x02,
5354 CALIBRATION_SIZE, image);
5355
5356 /* save scanned picture for data debugging */
5357 if (DBG_LEVEL >= DBG_io2)
5358 {
5359 sprintf (name, "offset%03d.pnm", num);
5360 write_rgb_data (name, image, CALIBRATION_WIDTH, 1);
5361 num++;
5362 }
5363
5364 /* we now compute the average of red pixels from the first 15 pixels */
5365 global = average_area (SANE_TRUE, image, 15, 1, &ra, &ga, &ba);
5366 DBG (DBG_info,
5367 "offset_calibration: global=%.2f, channels=(%.2f,%.2f,%.2f)\n",
5368 global, ra, ga, ba);
5369
5370 /* dichotomie ... */
5371 if (fabs (ra - OFFSET_TARGET) < OFFSET_MARGIN)
5372 {
5373 /* offset is OK */
5374 tro = ro;
5375 bro = ro;
5376 }
5377 else
5378 { /* NOK */
5379 if (ra > OFFSET_TARGET)
5380 {
5381 tro = ro;
5382 ro = (tro + bro) / 2;
5383 }
5384 if (ra < OFFSET_TARGET)
5385 {
5386 bro = ro;
5387 ro = (tro + bro + 1) / 2;
5388 }
5389
5390 }
5391
5392 /* same for blue channel */
5393 if (fabs (ba - OFFSET_TARGET) < OFFSET_MARGIN)
5394 {
5395 bbo = bo;
5396 tbo = bo;
5397 }
5398 else
5399 {
5400 if (ba > OFFSET_TARGET)
5401 {
5402 tbo = bo;
5403 bo = (tbo + bbo) / 2;
5404 }
5405 if (ba < OFFSET_TARGET)
5406 {
5407 bbo = bo;
5408 bo = (tbo + bbo + 1) / 2;
5409 }
5410
5411 }
5412
5413 /* and for green channel */
5414 if (fabs (ga - OFFSET_TARGET) < OFFSET_MARGIN)
5415 {
5416 tgo = go;
5417 bgo = go;
5418 }
5419 else
5420 {
5421 if (ga > OFFSET_TARGET)
5422 {
5423 tgo = go;
5424 go = (tgo + bgo) / 2;
5425 }
5426 if (ga < OFFSET_TARGET)
5427 {
5428 bgo = go;
5429 go = (tgo + bgo + 1) / 2;
5430 }
5431 }
5432 }
5433 while ((tro != bro) || (tgo != bgo) || (tbo != bbo));
5434
5435 /* store detected values in device struct */
5436 dev->red_offset = bro;
5437 dev->green_offset = bgo;
5438 dev->blue_offset = bbo;
5439
5440 DBG (DBG_proc, "offset_calibration: exit\n");
5441 return status;
5442 }
5443
5444 /*
5445 * do shading calibration
5446 * We scan a 637 pixels by 66 linesxoffset=24 , xend=661, pixels=637
5447 y offset=1 , yend=67, lines =66
5448 */
5449 static SANE_Status
setup_shading_calibration(struct Rts8891_Device *dev, int mode, int *light, int *status1, SANE_Byte * regs)5450 setup_shading_calibration (struct Rts8891_Device *dev, int mode, int *light, int *status1, SANE_Byte * regs)
5451 {
5452 SANE_Status status = SANE_STATUS_GOOD;
5453 int lines = 66;
5454 int exposure=0;
5455 int timing=0;
5456
5457 DBG (DBG_proc, "setup_shading_calibration: start\n");
5458 DBG (DBG_info, "setup_shading_calibration: sensor type is %s (%d)\n", sensor_name (dev->sensor), dev->sensor);
5459
5460 /* set up registers */
5461 /* 0x20/0x28 0x3b/0x3f seen in logs */
5462 *status1 = mode;
5463 if (dev->xdpi > 300)
5464 {
5465 *status1 |= 0x08;
5466 }
5467
5468 /* we default to 75 dpi then override needed registers */
5469 timing=0x00b0;
5470 regs[0x32] = 0x20;
5471 regs[0x33] = 0x83;
5472 regs[0x35] = 0x0e;
5473 regs[0x36] = 0x2c;
5474 regs[0x3a] = 0x0e;
5475
5476 regs[0xe2] = 0x05;
5477 regs[0xe7] = 0x00;
5478 regs[0xe8] = 0x00;
5479 regs[0xe9] = 0x00;
5480 regs[0xea] = 0x00;
5481 regs[0xeb] = 0x00;
5482 regs[0xec] = 0x00;
5483 regs[0xed] = 0x00;
5484 regs[0xef] = 0x00;
5485 regs[0xf0] = 0x00;
5486 regs[0xf2] = 0x00;
5487 /* regs[0xe5] = 0xdd; */
5488
5489 exposure=221;
5490 if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400)
5491 {
5492 regs[0xc0] = 0x67;
5493 regs[0xc1] = 0x06;
5494 regs[0xc2] = 0xe6;
5495 regs[0xc3] = 0x98;
5496 regs[0xc4] = 0xf9;
5497 regs[0xc5] = 0x19;
5498 regs[0xc6] = 0x67;
5499 regs[0xc7] = 0x06;
5500 regs[0xc8] = 0xe6;
5501 regs[0xc9] = 0x01;
5502 regs[0xca] = 0xf8;
5503 regs[0xcb] = 0xff;
5504 regs[0xcc] = 0x98;
5505 regs[0xcd] = 0xf9;
5506 regs[0xce] = 0x19;
5507 regs[0xcf] = 0xe0;
5508 regs[0xd0] = 0xe2;
5509
5510 regs[0xd1] = 0xeb;
5511 regs[0xd2] = 0x0c;
5512
5513 regs[0xd7] = 0x10;
5514 }
5515 if (dev->sensor == SENSOR_TYPE_4400)
5516 {
5517 *light &= 0xf7; /* clear bit 3 */
5518 regs[0x36] = 0x29; /* 0x2c */
5519 timing=0x0032;
5520 regs[0x85] = 0x00; /* 0x8c */
5521 regs[0x86] = 0x06; /* 0x10 */
5522 regs[0x87] = 0x00; /* 0x18 */
5523 regs[0x88] = 0x06; /* 0x1b */
5524 regs[0x8d] = 0x00; /* 0x77 */
5525 /* c5,c6 ?? */
5526 /* regs[0xd3] = 0x02; 0x0e */
5527 regs[0xd4] = 0x04; /* 0x10 */
5528 regs[0xe2] = 0x02; /* 0x05 */
5529 /* regs[0xe5] = 0xbb;
5530 regs[0xe6] = 0x01; 1bb =443 */
5531 exposure=443;
5532 }
5533 if (dev->sensor == SENSOR_TYPE_4400_BARE)
5534 {
5535 regs[0x13] = 0x39; /* 0x20 */
5536 regs[0x14] = 0xf0; /* 0xf8 */
5537 regs[0x15] = 0x29; /* 0x28 */
5538 regs[0x16] = 0x0f; /* 0x07 */
5539 regs[0x17] = 0x10; /* 0x00 */
5540 regs[0x23] = 0x00; /* 0xff */
5541 regs[0x36] = 0x29; /* 0x2c */
5542 regs[0x39] = 0x00; /* 0x02 */
5543 regs[0xe2] = 0x02; /* 0x05 */
5544 exposure=443;
5545 }
5546
5547 switch (dev->xdpi)
5548 {
5549 case 75:
5550 break;
5551
5552 case 150:
5553 /* X resolution related registers */
5554 switch (dev->sensor)
5555 {
5556 case SENSOR_TYPE_XPA:
5557 DBG (DBG_io,
5558 "setup_shading_calibration: setting up SENSOR_TYPE_XPA for 150 dpi\n");
5559 timing=0x022b;
5560 regs[0x85] = 0x18;
5561 regs[0x86] = 0x1b;
5562 regs[0x87] = 0x30;
5563 regs[0x88] = 0x30;
5564 regs[0x8d] = 0xef;
5565 regs[0xc0] = 0x00;
5566 regs[0xc1] = 0x8e;
5567 regs[0xc2] = 0xff;
5568 regs[0xc3] = 0xff;
5569 regs[0xc4] = 0x71;
5570 regs[0xc5] = 0x00;
5571 regs[0xc6] = 0x00;
5572 regs[0xc7] = 0x8e;
5573 regs[0xc8] = 0xff;
5574 regs[0xc9] = 0xff;
5575 regs[0xca] = 0xff;
5576 regs[0xcb] = 0x1f;
5577 regs[0xcc] = 0xff;
5578 regs[0xcd] = 0x71;
5579 regs[0xce] = 0x00;
5580 regs[0xcf] = 0xe6;
5581 regs[0xd0] = 0xe8;
5582 regs[0xd1] = 0xf6;
5583 regs[0xd2] = 0x17;
5584 /* regs[0xd3] = 0x0b; */
5585 regs[0xd4] = 0x0d;
5586 /* regs[0xe5] = 0xe4; */
5587 exposure=228;
5588 break;
5589 case SENSOR_TYPE_BARE:
5590 DBG (DBG_io,
5591 "setup_shading_calibration: setting up SENSOR_TYPE_BARE for 150 dpi\n");
5592 timing=0x012e;
5593 regs[0x85] = 0x8c;
5594 regs[0x86] = 0x10;
5595 regs[0x87] = 0x18;
5596 regs[0x88] = 0x1b;
5597 regs[0x8d] = 0x77;
5598 regs[0xc0] = 0x80;
5599 regs[0xc1] = 0x87;
5600 regs[0xc2] = 0x7f;
5601 regs[0xc9] = 0x00;
5602 regs[0xcb] = 0x78;
5603 regs[0xcc] = 0x7f;
5604 regs[0xcd] = 0x78;
5605 regs[0xce] = 0x80;
5606 regs[0xcf] = 0xe6;
5607 regs[0xd0] = 0xe8;
5608
5609 regs[0xd1] = 0xf7;
5610 regs[0xd2] = 0x00;
5611
5612 /* regs[0xd3] = 0x0e; */
5613 regs[0xd4] = 0x10;
5614
5615 /* regs[0xe5] = 0xe4; */
5616 exposure=228;
5617 break;
5618 case SENSOR_TYPE_4400:
5619 DBG (DBG_io,
5620 "setup_shading_calibration: setting up SENSOR_TYPE_4400 for 150 dpi\n");
5621 timing=0x012e;
5622 regs[0x85] = 0x8c;
5623 regs[0x86] = 0x10;
5624 regs[0x87] = 0x18;
5625 regs[0x88] = 0x1b;
5626 regs[0x8d] = 0x77;
5627 regs[0xc0] = 0x00;
5628 regs[0xc1] = 0x8e;
5629 regs[0xc2] = 0xff;
5630 regs[0xc3] = 0xff;
5631 regs[0xc4] = 0x71;
5632 regs[0xc5] = 0x00;
5633 regs[0xc6] = 0x00;
5634 regs[0xc7] = 0x8e;
5635 regs[0xc8] = 0xff;
5636 regs[0xc9] = 0xff;
5637 regs[0xca] = 0xff;
5638 regs[0xcb] = 0x1f;
5639 regs[0xcc] = 0xff;
5640 regs[0xcd] = 0x71;
5641 regs[0xce] = 0x00;
5642 regs[0xcf] = 0xe6;
5643 regs[0xd0] = 0xe8;
5644 regs[0xd1] = 0xf6;
5645 regs[0xd2] = 0x17;
5646 /* regs[0xd3] = 0x0b; */
5647 regs[0xd4] = 0x0d;
5648 exposure=457;
5649 break;
5650 case SENSOR_TYPE_4400_BARE:
5651 DBG (DBG_io,
5652 "setup_shading_calibration: setting up SENSOR_TYPE_4400_BARE for 150 dpi\n");
5653 regs[0x13] = 0x39; /* 0x20 */
5654 regs[0x14] = 0xf0; /* 0xf8 */
5655 regs[0x15] = 0x29; /* 0x28 */
5656 regs[0x16] = 0x0f; /* 0x07 */
5657 regs[0x17] = 0x10; /* 0x00 */
5658 regs[0x23] = 0x00; /* 0xff */
5659 regs[0x36] = 0x29; /* 0x2c */
5660 regs[0x39] = 0x00; /* 0x02 */
5661 timing=0x00b0;
5662 regs[0x85] = 0x46; /* 0x00 */
5663 regs[0x86] = 0x0b; /* 0x06 */
5664 regs[0x87] = 0x8c; /* 0x00 */
5665 regs[0x88] = 0x10; /* 0x06 */
5666 regs[0x8d] = 0x3b; /* 0x00 */
5667 regs[0xc0] = 0xff; /* 0x06 */
5668 regs[0xc1] = 0x0f; /* 0xe6 */
5669 regs[0xc2] = 0x00; /* 0x67 */
5670 regs[0xc9] = 0x00; /* 0x07 */
5671 regs[0xca] = 0x0e; /* 0x00 */
5672 regs[0xcb] = 0x00; /* 0xfe */
5673 regs[0xcc] = 0x00; /* 0xf9 */
5674 regs[0xcd] = 0xf0; /* 0x19 */
5675 regs[0xce] = 0xff; /* 0x98 */
5676 regs[0xcf] = 0xf5; /* 0xe8 */
5677 regs[0xd0] = 0xf7; /* 0xea */
5678 regs[0xd1] = 0xea; /* 0xf3 */
5679 regs[0xd2] = 0x0b; /* 0x14 */
5680 /* regs[0xd3] = 0x17; 0x02 */
5681 regs[0xd4] = 0x01; /* 0x04 */
5682 regs[0xe2] = 0x02; /* 0x05 */
5683 /* regs[0xe5] = 0x93; regs[0xe6] = 0x03; */
5684 exposure=915;
5685 break;
5686 }
5687 break;
5688
5689 case 300:
5690 switch (dev->sensor)
5691 {
5692 case SENSOR_TYPE_XPA:
5693 DBG (DBG_io,
5694 "setup_shading_calibration: setting up SENSOR_TYPE_XPA for 300 dpi\n");
5695 timing=0x00b0;
5696 regs[0x85] = 0x46;
5697 regs[0x86] = 0x0b;
5698 regs[0x87] = 0x8c;
5699 regs[0x88] = 0x10;
5700 regs[0x8d] = 0x3b;
5701 regs[0xc0] = 0x00;
5702 regs[0xc1] = 0xff;
5703 regs[0xc2] = 0x0f;
5704 regs[0xc3] = 0xff;
5705 regs[0xc4] = 0x00;
5706 regs[0xc5] = 0xf0;
5707 regs[0xc6] = 0x00;
5708 regs[0xc7] = 0xff;
5709 regs[0xc8] = 0x0f;
5710 regs[0xc9] = 0xff;
5711 regs[0xca] = 0xff;
5712 regs[0xcb] = 0xf1;
5713 regs[0xcc] = 0xff;
5714 regs[0xcd] = 0x00;
5715 regs[0xce] = 0xf0;
5716 regs[0xcf] = 0xed;
5717 regs[0xd0] = 0xef;
5718 regs[0xd1] = 0xe2;
5719 regs[0xd2] = 0x03;
5720 /* regs[0xd3] = 0x17; */
5721 regs[0xd4] = 0x01;
5722 /* regs[0xe5] = 0xc9;
5723 regs[0xe6] = 0x01; 0x01c9=457 */
5724 exposure=457;
5725 break;
5726 case SENSOR_TYPE_BARE:
5727 DBG (DBG_io,
5728 "setup_shading_calibration: setting up SENSOR_TYPE_BARE for 300 dpi\n");
5729 timing=0x012e;
5730 regs[0x85] = 0x8c;
5731 regs[0x86] = 0x10;
5732 regs[0x87] = 0x18;
5733 regs[0x88] = 0x1b;
5734
5735 regs[0x8d] = 0xde;
5736 regs[0x8e] = 0x61; /* low nibble of 8e and 8d are proportional to
5737 the scanned width 1de => 5100 wide scan */
5738
5739 regs[0xc0] = 0xff;
5740 regs[0xc1] = 0x0f;
5741 regs[0xc2] = 0x00;
5742 regs[0xc9] = 0x00;
5743 regs[0xca] = 0x0e;
5744 regs[0xcb] = 0x00;
5745 regs[0xcc] = 0x00;
5746 regs[0xcd] = 0xf0;
5747 regs[0xce] = 0xff;
5748 regs[0xcf] = 0xf5;
5749 regs[0xd0] = 0xf7;
5750
5751 regs[0xd1] = 0xea;
5752 regs[0xd2] = 0x0b;
5753
5754 /* regs[0xd3] = 0x17; */
5755 regs[0xd4] = 0x01;
5756 /* regs[0xe5] = 0xc9;
5757 regs[0xe6] = 0x01; 0x1c9=457 */
5758 exposure=457;
5759 break;
5760 case SENSOR_TYPE_4400:
5761 DBG (DBG_io,
5762 "setup_shading_calibration: setting up SENSOR_TYPE_4400 for 300 dpi\n");
5763 timing=0x022b;
5764 regs[0x85] = 0x18;
5765 regs[0x86] = 0x1b;
5766 regs[0x87] = 0x30;
5767 regs[0x88] = 0x30;
5768 regs[0x8d] = 0xef;
5769 regs[0xc0] = 0x00;
5770 regs[0xc1] = 0xff;
5771 regs[0xc2] = 0x0f;
5772 regs[0xc3] = 0xff;
5773 regs[0xc4] = 0x00;
5774 regs[0xc5] = 0xf0;
5775 regs[0xc6] = 0x00;
5776 regs[0xc7] = 0xff;
5777 regs[0xc8] = 0x0f;
5778 regs[0xc9] = 0xff;
5779 regs[0xca] = 0xff;
5780 regs[0xcb] = 0xf1;
5781 regs[0xcc] = 0xff;
5782 regs[0xcd] = 0x00;
5783 regs[0xce] = 0xf0;
5784 regs[0xcf] = 0xed;
5785 regs[0xd0] = 0xef;
5786 regs[0xd1] = 0xe2;
5787 regs[0xd2] = 0x03;
5788 /* regs[0xd3] = 0x17; */
5789 regs[0xd4] = 0x01;
5790 /* 0x0393 = 915 = 2*457+1 */
5791 exposure=915;
5792 break;
5793
5794 case SENSOR_TYPE_4400_BARE:
5795 DBG (DBG_io,
5796 "setup_shading_calibration: setting up SENSOR_TYPE_4400_BARE for 300 dpi\n");
5797 return SANE_STATUS_INVAL;
5798 break;
5799 }
5800 break;
5801
5802 case 600:
5803 switch (dev->sensor)
5804 {
5805 case SENSOR_TYPE_BARE:
5806 DBG (DBG_io,
5807 "setup_shading_calibration: setting up SENSOR_TYPE_BARE for 600 dpi\n");
5808 regs[0x34] = 0x10;
5809
5810 regs[0x72] = 0x3a;
5811 regs[0x73] = 0x15;
5812 regs[0x74] = 0x62;
5813
5814 timing=0x022b;
5815
5816 regs[0x85] = 0x18;
5817 regs[0x86] = 0x1b;
5818
5819 regs[0x87] = 0x30;
5820 regs[0x88] = 0x30;
5821
5822 regs[0x8d] = 0xde;
5823 regs[0x8e] = 0x61; /* low nibble of 8e and 8d are proportional to
5824 the scanned width 1de => 5100 wide scan */
5825 regs[0xc0] = 0xff;
5826 regs[0xc1] = 0xff;
5827 regs[0xc2] = 0xff;
5828 regs[0xc3] = 0x00;
5829 regs[0xc4] = 0xf0;
5830 regs[0xc7] = 0x0f;
5831 regs[0xc8] = 0x00;
5832 regs[0xcb] = 0xe0;
5833 regs[0xcc] = 0xff;
5834 regs[0xcd] = 0xff;
5835 regs[0xce] = 0xff;
5836 regs[0xcf] = 0xe9;
5837 regs[0xd0] = 0xeb;
5838
5839 regs[0xd7] = 0x14;
5840
5841 /* regs[0xe5] = 0x93;
5842 regs[0xe6] = 0x03; 0x393=915 = 457*2+1 */
5843 exposure=915;
5844 break;
5845
5846 case SENSOR_TYPE_XPA:
5847 DBG (DBG_io,
5848 "setup_shading_calibration: setting up SENSOR_TYPE_XPA for 600 dpi\n");
5849 *light &= 0xfb; /* clear bit 2 */
5850 regs[0x16] = 0x07;
5851 regs[0x33] = 0x83; /* 0x86 */
5852 regs[0x34] = 0x10;
5853 regs[0x50] = 0x00; /* 0x18 */
5854 regs[0x64] = 0x01; /* 0x02 */
5855 regs[0x65] = 0x20; /* 0x10 */
5856
5857 regs[0x72] = 0x3a;
5858 regs[0x73] = 0x15;
5859 regs[0x74] = 0x62;
5860
5861 regs[0x85] = 0x00;
5862 regs[0x86] = 0x06;
5863
5864 regs[0x87] = 0x00;
5865 regs[0x88] = 0x06;
5866
5867 regs[0x8d] = 0x00;
5868 regs[0x8e] = 0x60; /* XXX STEF XXX */
5869
5870 regs[0xc0] = 0xf8;
5871 regs[0xc1] = 0x7f;
5872 regs[0xc2] = 0x00;
5873 regs[0xc3] = 0xf8;
5874 regs[0xc4] = 0x7f;
5875 regs[0xc5] = 0x00;
5876 regs[0xc6] = 0xf8;
5877 regs[0xc7] = 0x7f;
5878 regs[0xc8] = 0x00;
5879 regs[0xc9] = 0xff;
5880 regs[0xca] = 0x8f;
5881 regs[0xcb] = 0xff;
5882 regs[0xcc] = 0x07;
5883 regs[0xcd] = 0x80;
5884 regs[0xce] = 0xff;
5885 regs[0xcf] = 0xf2;
5886 regs[0xd0] = 0xf4;
5887 regs[0xd1] = 0xe7;
5888 regs[0xd2] = 0x08;
5889 regs[0xd3] = 0x0e;
5890 regs[0xd4] = 0x10;
5891 regs[0xd7] = 0x31;
5892
5893 timing=0x0032;
5894 exposure=915;
5895 break;
5896
5897 case SENSOR_TYPE_4400:
5898 DBG (DBG_io,
5899 "setup_shading_calibration: setting up SENSOR_TYPE_4400 for 600 dpi\n");
5900 *light = 0x23;
5901
5902 regs[0x13] = 0x39;
5903 regs[0x14] = 0xf0;
5904 regs[0x15] = 0x29;
5905 regs[0x16] = 0x0f;
5906 regs[0x17] = 0x10;
5907 regs[0x23] = 0x00;
5908 regs[0x34] = 0xf0;
5909 regs[0x36] = 0x29;
5910 regs[0x39] = 0x00;
5911 regs[0x72] = 0x3a;
5912 regs[0x73] = 0x15;
5913 regs[0x74] = 0x62;
5914 timing=0x0426;
5915 regs[0x85] = 0x30;
5916 regs[0x86] = 0x30;
5917 regs[0x87] = 0x60;
5918 regs[0x88] = 0x5a;
5919 regs[0x8d] = 0xde;
5920 regs[0x8e] = 0x61;
5921 regs[0xc0] = 0xf8;
5922 regs[0xc1] = 0x7f;
5923 regs[0xc2] = 0x00;
5924 regs[0xc3] = 0xf8;
5925 regs[0xc4] = 0x7f;
5926 regs[0xc5] = 0x00;
5927 regs[0xc6] = 0xf8;
5928 regs[0xc7] = 0x7f;
5929 regs[0xc8] = 0x00;
5930 regs[0xc9] = 0xff;
5931 regs[0xca] = 0x8f;
5932 regs[0xcb] = 0xff;
5933 regs[0xcc] = 0x07;
5934 regs[0xcd] = 0x80;
5935 regs[0xce] = 0xff;
5936 regs[0xcf] = 0xf2;
5937 regs[0xd0] = 0xf4;
5938 regs[0xd1] = 0xe7;
5939 regs[0xd2] = 0x08;
5940 regs[0xd3] = 0x0e;
5941 regs[0xd4] = 0x10;
5942 regs[0xd7] = 0x31;
5943 regs[0xe2] = 0x02;
5944 exposure=1832;
5945
5946 break;
5947
5948 case SENSOR_TYPE_4400_BARE:
5949 DBG (DBG_io,
5950 "setup_shading_calibration: setting up SENSOR_TYPE_4400_BARE for 600 dpi\n");
5951 return SANE_STATUS_INVAL;
5952 break;
5953 }
5954 break;
5955
5956 case 1200:
5957 switch (dev->sensor)
5958 {
5959 case SENSOR_TYPE_BARE:
5960 DBG (DBG_io,
5961 "setup_shading_calibration: setting up SENSOR_TYPE_BARE for 1200 dpi\n");
5962 regs[0x34] = 0xf0;
5963 regs[0x40] = 0xa0;
5964
5965 timing=0x0426;
5966
5967 regs[0x85] = 0x30;
5968 regs[0x86] = 0x30;
5969
5970 regs[0x87] = 0x60;
5971 regs[0x88] = 0x5a;
5972
5973 regs[0x8d] = 0xbd;
5974 regs[0x8e] = 0x63;
5975
5976 regs[0xc0] = 0xff;
5977 regs[0xc1] = 0xff;
5978 regs[0xc2] = 0xff;
5979 regs[0xc4] = 0x0f;
5980 regs[0xc5] = 0x00;
5981 regs[0xc6] = 0x00;
5982 regs[0xc7] = 0xf0;
5983 regs[0xc9] = 0x00;
5984 regs[0xca] = 0x0e;
5985 regs[0xcb] = 0x00;
5986 regs[0xcc] = 0xff;
5987 regs[0xcd] = 0xff;
5988 regs[0xce] = 0xff;
5989 regs[0xcf] = 0xf5;
5990 regs[0xd0] = 0xf7;
5991 regs[0xd1] = 0xea;
5992 regs[0xd2] = 0x0b;
5993 /* regs[0xd3] = 0x17; */
5994 regs[0xd4] = 0xc1;
5995 regs[0xd7] = 0x14;
5996 regs[0xd8] = 0xa4;
5997 /* regs[0xe5] = 0x28;
5998 regs[0xe6] = 0x07; 0x728=1832=915*2+2 */
5999 exposure=1832;
6000 break;
6001 case SENSOR_TYPE_XPA:
6002 DBG (DBG_io,
6003 "setup_shading_calibration: setting up SENSOR_TYPE_XPA for 1200 dpi\n");
6004 regs[0x34] = 0x10;
6005 regs[0x40] = 0xa0;
6006
6007 timing=0x00b0;
6008 exposure=1832;
6009
6010 /* XXX STEF XXX */
6011 regs[0x85] = 0x46;
6012 regs[0x86] = 0x0b;
6013
6014 regs[0x87] = 0x8c;
6015 regs[0x88] = 0x10;
6016
6017 regs[0x8e] = 0x3b;
6018 regs[0x8d] = 0x60;
6019
6020 regs[0xc1] = 0xff;
6021 regs[0xce] = 0xff;
6022 regs[0xcf] = 0xf5;
6023 regs[0xd0] = 0xf7;
6024 regs[0x33] = 0x83;
6025 regs[0x50] = 0x00;
6026 regs[0x64] = 0x01;
6027 regs[0x65] = 0x20;
6028 regs[0x8d] = 0xbc;
6029 regs[0xc0] = 0xe0;
6030 regs[0xc2] = 0x01;
6031 regs[0xc3] = 0x1f;
6032 regs[0xc4] = 0x00;
6033 regs[0xc5] = 0xfe;
6034 regs[0xc6] = 0xff;
6035 regs[0xc7] = 0xff;
6036 regs[0xc8] = 0x00;
6037 regs[0xc9] = 0x3f;
6038 regs[0xca] = 0xfe;
6039 regs[0xcb] = 0xff;
6040 regs[0xcc] = 0x00;
6041 regs[0xcd] = 0x00;
6042 regs[0xd1] = 0xec;
6043 regs[0xd2] = 0x0d;
6044 regs[0xd3] = 0x05;
6045 regs[0xd4] = 0x67;
6046 regs[0xd7] = 0x10;
6047 regs[0xd8] = 0x52;
6048 break;
6049
6050 case SENSOR_TYPE_4400:
6051 DBG (DBG_io,
6052 "setup_shading_calibration: setting up SENSOR_TYPE_4400 for 1200 dpi\n");
6053 regs[0x13] = 0x39;
6054 regs[0x14] = 0xf0;
6055 regs[0x15] = 0x29;
6056 regs[0x16] = 0x0f;
6057 regs[0x17] = 0x10;
6058 regs[0x23] = 0x00;
6059 regs[0x34] = 0xf0;
6060 regs[0x36] = 0x29;
6061 regs[0x39] = 0x00;
6062 regs[0x40] = 0xa0;
6063 timing=0x0426;
6064 regs[0x85] = 0x30;
6065 regs[0x86] = 0x30;
6066 regs[0x87] = 0x60;
6067 regs[0x88] = 0x5a;
6068 regs[0x8d] = 0xde;
6069 regs[0x8e] = 0x61;
6070 regs[0xc0] = 0xe0;
6071 regs[0xc1] = 0xff;
6072 regs[0xc2] = 0x01;
6073 regs[0xc3] = 0x1f;
6074 regs[0xc4] = 0x00;
6075 regs[0xc5] = 0xfe;
6076 regs[0xc6] = 0xff;
6077 regs[0xc7] = 0xff;
6078 regs[0xc8] = 0x00;
6079 regs[0xc9] = 0x3f;
6080 regs[0xca] = 0xfe;
6081 regs[0xcb] = 0xff;
6082 regs[0xcc] = 0x00;
6083 regs[0xcd] = 0x00;
6084 regs[0xce] = 0xff;
6085 regs[0xcf] = 0xf5;
6086 regs[0xd0] = 0xf7;
6087 regs[0xd1] = 0xec;
6088 regs[0xd2] = 0x0d;
6089 /* regs[0xd3] = 0x05; */
6090 regs[0xd4] = 0x67;
6091 regs[0xd7] = 0x10;
6092 regs[0xd8] = 0x52;
6093 regs[0xe2] = 0x02;
6094 *light = 0x23;
6095 exposure=3665;
6096 break;
6097
6098 case SENSOR_TYPE_4400_BARE:
6099 DBG (DBG_io,
6100 "setup_shading_calibration: setting up SENSOR_TYPE_4400_BARE for 1200 dpi\n");
6101 return SANE_STATUS_INVAL;
6102 break;
6103 }
6104 break;
6105 }
6106
6107 /* apply computed settings */
6108 SET_DOUBLE (regs, EXPOSURE_REG, exposure);
6109 SET_DOUBLE (regs, TIMING_REG, timing);
6110 SET_DOUBLE (regs, TIMING1_REG, timing+1);
6111 SET_DOUBLE (regs, TIMING2_REG, timing+2);
6112
6113 /* in logs, the driver use the computed offset minus 2 */
6114 sanei_rts88xx_set_offset (regs, dev->red_offset, dev->green_offset, dev->blue_offset);
6115 sanei_rts88xx_set_gain (regs, dev->red_gain, dev->green_gain, dev->blue_gain);
6116 sanei_rts88xx_set_scan_area (regs, 1, 1 + lines, dev->xstart, dev->xstart + dev->pixels);
6117
6118 DBG (DBG_proc, "setup_shading_calibration: exit\n");
6119 return status;
6120 }
6121
6122 /*
6123 * do shading calibration
6124 * We scan a 637 pixels by 66 linesxoffset=24 , xend=661, pixels=637
6125 y offset=1 , yend=67, lines =66
6126 */
6127 static SANE_Status
shading_calibration(struct Rts8891_Device *dev, SANE_Bool color, int mode, int light)6128 shading_calibration (struct Rts8891_Device *dev, SANE_Bool color, int mode, int light)
6129 {
6130 SANE_Status status = SANE_STATUS_GOOD;
6131 int width;
6132 int lines = 66;
6133 SANE_Byte format;
6134 int size;
6135 int status1;
6136 int x, y, sum;
6137 SANE_Byte *image = NULL;
6138 FILE *dbg = NULL;
6139
6140 DBG (DBG_proc, "shading_calibration: start\n");
6141 DBG (DBG_info, "shading_calibration: sensor type is %s (%d)\n",
6142 sensor_name (dev->sensor), dev->sensor);
6143
6144 width = dev->pixels;
6145 size = lines * dev->bytes_per_line;
6146
6147 image = (SANE_Byte *) malloc (size);
6148 if (image == NULL)
6149 {
6150 DBG (DBG_error,
6151 "shading_calibration: failed to allocate memory for image\n");
6152 return SANE_STATUS_NO_MEM;
6153 }
6154 if (dev->shading_data != NULL)
6155 free (dev->shading_data);
6156 dev->shading_data = (unsigned char *) malloc (dev->bytes_per_line);
6157 if (dev->shading_data == NULL)
6158 {
6159 free (image);
6160 DBG (DBG_error,
6161 "shading_calibration: failed to allocate memory for data\n");
6162 return SANE_STATUS_NO_MEM;
6163 }
6164
6165 /* set up registers */
6166 status=setup_shading_calibration(dev, mode, &light, &status1, dev->regs);
6167 if (status != SANE_STATUS_GOOD)
6168 {
6169 DBG (DBG_error, "shading_calibration: failed to set up registers\n");
6170 free (dev->shading_data);
6171 dev->shading_data = NULL;
6172 free (image);
6173 return status;
6174 }
6175
6176 /* scan shading area */
6177 sanei_rts88xx_set_status (dev->devnum, dev->regs, status1, light);
6178 format = rts8891_data_format (dev->xdpi, dev->sensor);
6179 status = rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, format, size, image);
6180 if (status != SANE_STATUS_GOOD)
6181 {
6182 DBG (DBG_error, "shading_calibration: failed scan shading area\n");
6183 free (dev->shading_data);
6184 dev->shading_data = NULL;
6185 free (image);
6186 return status;
6187 }
6188
6189 if (DBG_LEVEL >= DBG_io2)
6190 {
6191 dbg = fopen ("shading.pnm", "wb");
6192 if (color)
6193 {
6194 fprintf (dbg, "P6\n%d %d\n255\n", width, lines);
6195 fwrite (image, width * 3, lines, dbg);
6196 }
6197 else
6198 {
6199 fprintf (dbg, "P5\n%d %d\n255\n", width, lines);
6200 fwrite (image, width, lines, dbg);
6201 }
6202 fclose (dbg);
6203 }
6204
6205 /* now we can compute shading calibration data */
6206 /* we average each row */
6207 /* we take the maximum of each row */
6208 /* we skip first 3 lines and last 10 lines due to some bugs */
6209 if (color)
6210 {
6211 width = width * 3;
6212 }
6213 for (x = 0; x < width; x++)
6214 {
6215 sum = 0;
6216 for (y = 3; y < lines - 10; y++)
6217 {
6218 sum += image[x + y * width];
6219 }
6220 dev->shading_data[x] = sum / (lines - 13);
6221 }
6222 if (DBG_LEVEL >= DBG_io2)
6223 {
6224 dbg = fopen ("shading_data.pnm", "wb");
6225 if (color)
6226 {
6227 fprintf (dbg, "P6\n%d %d\n255\n", width / 3, 1);
6228 fwrite (dev->shading_data, width, 1, dbg);
6229 }
6230 else
6231 {
6232 fprintf (dbg, "P5\n%d %d\n255\n", width, 1);
6233 fwrite (dev->shading_data, width, 1, dbg);
6234 }
6235 fclose (dbg);
6236 }
6237
6238 free (image);
6239 DBG (DBG_proc, "shading_calibration: exit\n");
6240 return status;
6241 }
6242
6243 static void
fill_gamma(SANE_Byte * calibration, int *idx, SANE_Word * gamma)6244 fill_gamma (SANE_Byte * calibration, int *idx, SANE_Word * gamma)
6245 {
6246 int i;
6247
6248 calibration[*idx] = 0;
6249 (*idx)++;
6250 for (i = 0; i < 255; i++)
6251 {
6252 calibration[*idx] = gamma[i];
6253 /* escape 0xaa with 0 */
6254 if (calibration[*idx] == 0xaa)
6255 {
6256 (*idx)++;
6257 calibration[*idx] = 0;
6258 }
6259 (*idx)++;
6260 calibration[*idx] = gamma[i];
6261 /* escape 0xaa with 0 */
6262 if (calibration[*idx] == 0xaa)
6263 {
6264 (*idx)++;
6265 calibration[*idx] = 0;
6266 }
6267 (*idx)++;
6268 }
6269 calibration[*idx] = 0xff;
6270 (*idx)++;
6271 }
6272
6273 /*
6274 * build and send calibration data which contains gamma table and
6275 * shading correction coefficient
6276 *
6277 */
6278 static SANE_Status
send_calibration_data(struct Rts8891_Session *session)6279 send_calibration_data (struct Rts8891_Session *session)
6280 {
6281 SANE_Status status = SANE_STATUS_GOOD;
6282 int size, width, data_size;
6283 SANE_Byte *calibration = NULL, format, val;
6284 struct Rts8891_Device *dev = session->dev;
6285 int i, idx;
6286 unsigned int value, red_code, blue_code, green_code;
6287 FILE *calib = NULL;
6288 SANE_Word *gamma_r, *gamma_g, *gamma_b;
6289
6290 DBG (DBG_proc, "send_calibration_data: start\n");
6291
6292 /* 675 pixels at 75 DPI, 16 bits values, 3 color channels */
6293 /* 5400 pixels at max sensor 600 dpi */
6294 /* 3 16bits 256 value gamma tables plus start/end markers */
6295 /* must multiple of 32 */
6296 data_size = (675 * dev->xdpi) / 75;
6297
6298 width = dev->pixels;
6299
6300 /* effective data calibration size */
6301 size = data_size * 2 * 3 + 3 * (512 + 2);
6302 size = ((size + 31) / 32) * 32;
6303
6304 DBG (DBG_io, "send_calibration_data: size=%d\n", size);
6305
6306 /*
6307 * FORMAT:
6308 * 00
6309 * 512 bytes gamma table (256 16 bit entry)
6310 * FF
6311 * 00
6312 * 512 bytes gamma table (256 16 bit entry)
6313 * FF
6314 * 00
6315 * 512 bytes gamma table (256 16 bit entry)
6316 * FF
6317 * 5400 max shading coefficients at 600 dpi repeated 3 times
6318 * overall size rounded at 32 bytes multiple
6319 * 675 CCD elements at 75 DPI. 16 bit per element. 1 or 3 channels.
6320 * there is a 0xFF marker at end of each coefficients row.
6321 * a gamma table comes first
6322 * 75 DPI: 5600=1542+(675)*2*3+8 ->size rounded to 'upper 32'
6323 * 150 DPI: 9664=675*2*2*3=1542+(675*2)*2*3+22
6324 * 17760 4 +18
6325 * 33952 8 +10
6326 * 65472+896=66368= 16 +26
6327 *
6328 * COEFFICIENT 16 bit value
6329 * first is 00, 0x40, 0x80 or 0xC0 => 10 significant bit
6330 * coeff*average=K => coeff=K/average
6331 */
6332
6333 calibration = (SANE_Byte *) malloc (size);
6334 if (calibration == NULL)
6335 {
6336 DBG (DBG_error,
6337 "send_calibration_data: failed to allocate memory for calibration data\n");
6338 return SANE_STATUS_NO_MEM;
6339 }
6340 memset (calibration, 0x00, size);
6341
6342 /* fill gamma tables first, markers and static gamma table */
6343 idx = 0;
6344
6345 /* select red gamma table */
6346 if (session->params.format == SANE_FRAME_RGB)
6347 {
6348 /* 3 different gamma table */
6349 gamma_r = session->val[OPT_GAMMA_VECTOR_R].wa;
6350 gamma_g = session->val[OPT_GAMMA_VECTOR_G].wa;
6351 gamma_b = session->val[OPT_GAMMA_VECTOR_B].wa;
6352 }
6353 else
6354 {
6355 /* 3 time the same gamma table */
6356 gamma_r = session->val[OPT_GAMMA_VECTOR].wa;
6357 gamma_g = session->val[OPT_GAMMA_VECTOR].wa;
6358 gamma_b = session->val[OPT_GAMMA_VECTOR].wa;
6359 }
6360
6361 fill_gamma (calibration, &idx, gamma_r);
6362 fill_gamma (calibration, &idx, gamma_g);
6363 fill_gamma (calibration, &idx, gamma_b);
6364
6365 /* compute calibration coefficients */
6366 /* real width != 675 --> 637
6367 * shading data calibration starts at 1542. There are 3 rows of 16 bits values
6368 * first row is green calibration
6369 */
6370
6371 /* to avoid problems with 0xaa values which must be escaped, we change them
6372 * into 0xab values, which unnoticeable on scans */
6373 for (i = 0; i < width; i++)
6374 {
6375 /* average TARGET CODE 3431046 */
6376 /* #define RED_SHADING_TARGET_CODE 3000000
6377 #define GREEN_SHADING_TARGET_CODE 300000
6378 #define BLUE_SHADING_TARGET_CODE 2800000*/
6379 #define RED_SHADING_TARGET_CODE 2800000
6380 #define GREEN_SHADING_TARGET_CODE 2800000
6381 #define BLUE_SHADING_TARGET_CODE 2700000
6382
6383 red_code = RED_SHADING_TARGET_CODE;
6384 green_code = GREEN_SHADING_TARGET_CODE;
6385 blue_code = BLUE_SHADING_TARGET_CODE;
6386
6387 /* target code debug, will be removed for the release */
6388 if (getenv ("RED_CODE") != NULL)
6389 {
6390 red_code = atoi (getenv ("RED_CODE"));
6391 }
6392 if (getenv ("GREEN_CODE") != NULL)
6393 {
6394 blue_code = atoi (getenv ("GREEN_CODE"));
6395 }
6396 if (getenv ("BLUE_CODE") != NULL)
6397 {
6398 green_code = atoi (getenv ("BLUE_CODE"));
6399 }
6400
6401 /* correction coefficient is target code divided by average scanned value
6402 * but it is put in a 16 bits number. Only 10 first bits are significants.
6403 */
6404 /* first color component red data */
6405 if (gamma_r[dev->shading_data[i * 3]] < 5)
6406 value = 0x8000;
6407 else
6408 value = red_code / gamma_r[dev->shading_data[i * 3]];
6409 val = (SANE_Byte) (value / 256);
6410 if (val == 0xaa)
6411 val++;
6412 calibration[idx + i * 2 + 1] = val;
6413 calibration[idx + i * 2] = (SANE_Byte) (value % 256) & 0xC0;
6414
6415 /* second color component: green data */
6416 if (gamma_r[dev->shading_data[i * 3 + 1]] < 5)
6417 value = 0x8000;
6418 else
6419 value = green_code / gamma_g[dev->shading_data[i * 3 + 1]];
6420 val = (SANE_Byte) (value / 256);
6421 if (val == 0xaa)
6422 val++;
6423 calibration[idx + data_size * 2 + i * 2 + 1] = val;
6424 calibration[idx + data_size * 2 + i * 2] =
6425 (SANE_Byte) (value % 256) & 0xC0;
6426
6427 /* third color component: blue data */
6428 if (gamma_r[dev->shading_data[i * 3 + 2]] < 5)
6429 value = 0x8000;
6430 else
6431 value = blue_code / gamma_b[dev->shading_data[i * 3 + 2]];
6432 val = (SANE_Byte) (value / 256);
6433 if (val == 0xaa)
6434 val++;
6435 calibration[idx + data_size * 4 + i * 2 + 1] = val;
6436 calibration[idx + data_size * 4 + i * 2] =
6437 (SANE_Byte) (value % 256) & 0xC0;
6438 }
6439
6440 /* DEEP TRACING */
6441 if (DBG_LEVEL >= DBG_io2)
6442 {
6443 calib = fopen ("calibration.hex", "wb");
6444 fprintf (calib, "shading_data(%d)=", width);
6445 for (i = 0; i < width * 3; i++)
6446 {
6447 fprintf (calib, "%02x ", dev->shading_data[i]);
6448 }
6449 fprintf (calib, "\n");
6450 fprintf (calib, "write_mem(0x00,%d)=", size);
6451 for (i = 0; i < size; i++)
6452 {
6453 fprintf (calib, "%02x ", calibration[i]);
6454 }
6455 fclose (calib);
6456 }
6457
6458 /* signals color format/divisor from hardware */
6459 format = rts8891_data_format (dev->xdpi, dev->sensor);
6460 status = sanei_rts88xx_write_reg (dev->devnum, 0xd3, &format);
6461
6462 /* for some reason, we have to add 6 to the size for the first write */
6463 /* related to the 6 0xaa in gamma table ? */
6464 if (size > RTS88XX_MAX_XFER_SIZE)
6465 {
6466 status =
6467 sanei_rts88xx_write_mem (dev->devnum, RTS88XX_MAX_XFER_SIZE, 6,
6468 calibration);
6469 if (status != SANE_STATUS_GOOD)
6470 {
6471 DBG (DBG_error,
6472 "send_calibration_data: failed to write calibration data (part 1)\n");
6473 return status;
6474 }
6475 size -= RTS88XX_MAX_XFER_SIZE;
6476 status =
6477 sanei_rts88xx_write_mem (dev->devnum, size, 0,
6478 calibration + RTS88XX_MAX_XFER_SIZE);
6479 if (status != SANE_STATUS_GOOD)
6480 {
6481 DBG (DBG_error,
6482 "send_calibration_data: failed to write calibration data (part 2)\n");
6483 return status;
6484 }
6485 }
6486 else
6487 {
6488 status = sanei_rts88xx_write_mem (dev->devnum, size, 6, calibration);
6489 if (status != SANE_STATUS_GOOD)
6490 {
6491 DBG (DBG_error,
6492 "send_calibration_data: failed to write calibration data\n");
6493 return status;
6494 }
6495 }
6496
6497 /* set mem start */
6498 dev->regs[0x91] = 0x00;
6499 dev->regs[0x92] = 0x00;
6500 sanei_rts88xx_write_regs (dev->devnum, 0x91, dev->regs + 0x91, 2);
6501
6502 free (calibration);
6503 DBG (DBG_proc, "send_calibration_data: exit\n");
6504 return status;
6505 }
6506
6507 /* move at dev->model->min_ydpi dpi up to the scanning area. Which speeds
6508 * up scanning
6509 */
6510 static SANE_Status
move_to_scan_area(struct Rts8891_Session *session)6511 move_to_scan_area (struct Rts8891_Session *session)
6512 {
6513 SANE_Status status = SANE_STATUS_GOOD;
6514 SANE_Byte control;
6515 SANE_Byte regs[RTS8891_MAX_REGISTERS];
6516 struct Rts8891_Device *dev = session->dev;
6517 SANE_Int distance;
6518
6519 DBG (DBG_proc, "move_to_scan_area: start\n");
6520
6521 /* compute line number to move and fix scan values */
6522 distance = ((dev->ystart - 1) * MOVE_DPI) / dev->ydpi;
6523 dev->ystart = dev->ystart - (distance * dev->ydpi) / MOVE_DPI;
6524 /* extra lines to let head stop */
6525 distance -= 30;
6526
6527 DBG (DBG_proc, "move_to_scan_area: distance=%d, ystart=%d\n", distance,
6528 dev->ystart);
6529
6530 /* then send move command */
6531 rts8891_move (dev, regs, distance, SANE_TRUE);
6532
6533 /* wait for completion */
6534 do
6535 {
6536 sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control);
6537 }
6538 while ((control & 0x08) == 0x08);
6539
6540 DBG (DBG_proc, "move_to_scan_area: exit\n");
6541 return status;
6542 }
6543
6544 /* set up the shadow registers for scan, depending on scan parameters */
6545 /* the ultimate goal is to have no direct access to registers, but to */
6546 /* set them through helper functions */
6547 /* NOTE : I couldn't manage to get scans that really uses gray settings. */
6548 /* The windows driver is always scanning in color, so we do the same. */
6549 /* For now, the only mode that could be done would be 300 dpi gray scan, */
6550 /* based on the register settings of find_origin() */
6551 static SANE_Status
setup_scan_registers(struct Rts8891_Session *session, SANE_Byte *status1, SANE_Byte *status2, SANE_Byte *regs)6552 setup_scan_registers (struct Rts8891_Session *session, SANE_Byte *status1, SANE_Byte *status2, SANE_Byte *regs)
6553 {
6554 SANE_Status status = SANE_STATUS_GOOD;
6555 struct Rts8891_Device *dev = session->dev;
6556 int exposure=0;
6557 int timing=0;
6558
6559 /* only software gray modes for now */
6560 if (session->params.format == SANE_FRAME_GRAY
6561 && (session->dev->model->flags & RTS8891_FLAG_EMULATED_GRAY_MODE) == 0)
6562 {
6563 DBG (DBG_warn,
6564 "setup_scan_registers: native gray modes not implemented for this model, failure expected\n");
6565 }
6566 sanei_rts88xx_set_scan_area (regs, dev->ystart, dev->ystart + dev->lines, dev->xstart, dev->xstart + dev->pixels);
6567 DBG (DBG_info, "setup_scan_registers: xstart=%d, pixels=%d\n", dev->xstart, dev->pixels);
6568 DBG (DBG_info, "setup_scan_registers: ystart=%d, lines =%d\n", dev->ystart, dev->lines);
6569
6570 /* this is full register set from a color preview */
6571 regs[0x00] = regs[0x00] & 0xef;
6572 regs[0x01] = 0x41;
6573
6574 sanei_rts88xx_set_offset (regs, dev->red_offset, dev->green_offset, dev->blue_offset);
6575 sanei_rts88xx_set_gain (regs, dev->red_gain, dev->green_gain, dev->blue_gain);
6576
6577 switch (dev->sensor)
6578 {
6579 case SENSOR_TYPE_4400:
6580 case SENSOR_TYPE_4400_BARE:
6581 *status1 = 0x10;
6582 *status2 = 0x2a;
6583 break;
6584 case SENSOR_TYPE_XPA:
6585 *status1 = 0x20;
6586 *status2 = 0x3f;
6587 break;
6588 default:
6589 *status1 = 0x20;
6590 *status2 = 0x3b;
6591 }
6592
6593 /* default to 75 dpi color scan */
6594 regs[0x0b] = 0x70;
6595 regs[0x0c] = 0x00;
6596 regs[0x0d] = 0x00;
6597 regs[0x0e] = 0x00;
6598 regs[0x0f] = 0x00;
6599
6600 regs[0x12] = 0xff;
6601 regs[0x13] = 0x20;
6602 regs[0x14] = 0xf8;
6603 regs[0x15] = 0x28;
6604 regs[0x16] = 0x01;
6605 regs[0x17] = 0x00;
6606 regs[0x18] = 0xff;
6607 regs[0x19] = 0x00;
6608 regs[0x1a] = 0x00;
6609 regs[0x1b] = 0x00;
6610 regs[0x1c] = 0x00;
6611 regs[0x1d] = 0x20;
6612 regs[0x1e] = 0x00;
6613 regs[0x1f] = 0x00;
6614
6615 /* LCD display */
6616 regs[0x20] = 0x3a;
6617 regs[0x21] = 0xf2;
6618 regs[0x22] = 0x00;
6619
6620 regs[0x23] = 0x80;
6621 regs[0x24] = 0xff;
6622 regs[0x25] = 0x00;
6623 regs[0x26] = 0x00;
6624 regs[0x27] = 0x00;
6625 regs[0x28] = 0x00;
6626 regs[0x29] = 0x00;
6627 regs[0x2a] = 0x00;
6628 regs[0x2b] = 0x00;
6629 regs[0x2c] = 0x00;
6630 regs[0x2d] = 0x00;
6631 regs[0x2e] = 0x00;
6632 regs[0x2f] = 0x00;
6633 regs[0x30] = 0x00;
6634 regs[0x31] = 0x00;
6635 regs[0x32] = 0x20;
6636 regs[0x33] = 0x83;
6637 regs[0x34] = 0x10;
6638 regs[0x35] = 0x47;
6639 regs[0x36] = 0x2c;
6640 regs[0x37] = 0x00;
6641 regs[0x38] = 0x00;
6642 regs[0x39] = 0x02;
6643 regs[0x3a] = 0x43;
6644 regs[0x3b] = 0x00;
6645 regs[0x3c] = 0x00;
6646 regs[0x3d] = 0x00;
6647 regs[0x3e] = 0x00;
6648 regs[0x3f] = 0x00;
6649 regs[0x40] = 0x2c; /* 0x0c -> use shading data */
6650 regs[0x41] = 0x00;
6651 regs[0x42] = 0x00;
6652 regs[0x43] = 0x00;
6653 regs[0x44] = 0x8c;
6654 regs[0x45] = 0x76;
6655 regs[0x46] = 0x00;
6656 regs[0x47] = 0x00;
6657 regs[0x48] = 0x00;
6658 regs[0x49] = 0x00;
6659 regs[0x4a] = 0x00;
6660 regs[0x4b] = 0x00;
6661 regs[0x4c] = 0x00;
6662 regs[0x4d] = 0x00;
6663 regs[0x4e] = 0x00;
6664 regs[0x4f] = 0x00;
6665 regs[0x50] = 0x00;
6666 regs[0x51] = 0x00;
6667 regs[0x52] = 0x00;
6668 regs[0x53] = 0x00;
6669 regs[0x54] = 0x00;
6670 regs[0x55] = 0x00;
6671 regs[0x56] = 0x00;
6672 regs[0x57] = 0x00;
6673 regs[0x58] = 0x00;
6674 regs[0x59] = 0x00;
6675 regs[0x5a] = 0x00;
6676 regs[0x5b] = 0x00;
6677 regs[0x5c] = 0x00;
6678 regs[0x5d] = 0x00;
6679 regs[0x5e] = 0x00;
6680 regs[0x5f] = 0x00;
6681
6682 regs[0x64] = 0x01;
6683 regs[0x65] = 0x20;
6684
6685 regs[0x68] = 0x00;
6686 regs[0x69] = 0x00;
6687 regs[0x6a] = 0x00;
6688 regs[0x6b] = 0x00;
6689
6690 regs[0x6e] = 0x00;
6691 regs[0x6f] = 0x00;
6692 regs[0x70] = 0x00;
6693 regs[0x71] = 0x00;
6694
6695 regs[0x72] = 0xe1;
6696 regs[0x73] = 0x14;
6697 regs[0x74] = 0x18;
6698 regs[0x75] = 0x15;
6699
6700 regs[0x76] = 0x00;
6701 regs[0x77] = 0x00;
6702 regs[0x78] = 0x00;
6703 regs[0x79] = 0x20;
6704 regs[0x7a] = 0x01;
6705 regs[0x7b] = 0x00;
6706 regs[0x7c] = 0x00;
6707 regs[0x7d] = 0x00;
6708 regs[0x7e] = 0x00;
6709 regs[0x7f] = 0x00;
6710 timing=0x00af;
6711 regs[0x84] = 0x00;
6712 regs[0x85] = 0x46;
6713 regs[0x86] = 0x0b;
6714 regs[0x87] = 0x8c;
6715 regs[0x88] = 0x10;
6716 regs[0x8b] = 0xff;
6717 regs[0x8c] = 0x3f;
6718 regs[0x8d] = 0x3b;
6719
6720 regs[0x8e] = 0x60;
6721 regs[0x8f] = 0x00;
6722 regs[0x90] = 0x18; /* 0x1c when shading calibration */
6723
6724 /* overwritten when calibration data is sent */
6725 regs[0x91] = 0x00;
6726 regs[0x92] = 0x00;
6727
6728 regs[0x93] = 0x01;
6729
6730 regs[0x94] = 0x0e;
6731 regs[0x95] = 0x00;
6732 regs[0x96] = 0x00;
6733 regs[0x97] = 0x00;
6734 regs[0x98] = 0x00;
6735 regs[0x99] = 0x00;
6736 regs[0x9a] = 0x00;
6737 regs[0x9b] = 0x00;
6738 regs[0x9c] = 0x00;
6739 regs[0x9d] = 0x00;
6740 regs[0x9e] = 0x00;
6741 regs[0x9f] = 0x00;
6742 regs[0xa0] = 0x00;
6743 regs[0xa1] = 0x00;
6744 regs[0xa2] = 0x00;
6745 regs[0xa3] = 0xcc;
6746 regs[0xa4] = 0x27;
6747 regs[0xa5] = 0x64;
6748 regs[0xa6] = 0x00;
6749 regs[0xa7] = 0x00;
6750 regs[0xa8] = 0x00;
6751 regs[0xa9] = 0x00;
6752 regs[0xaa] = 0x00;
6753 regs[0xab] = 0x00;
6754 regs[0xac] = 0x00;
6755 regs[0xad] = 0x00;
6756 regs[0xae] = 0x00;
6757 regs[0xaf] = 0x00;
6758 regs[0xb0] = 0x00;
6759 regs[0xb1] = 0x00;
6760 regs[0xb2] = 0x02;
6761
6762 regs[0xb4] = 0x00;
6763 regs[0xb5] = 0x00;
6764 regs[0xb6] = 0x00;
6765 regs[0xb7] = 0x00;
6766 regs[0xb8] = 0x00;
6767 regs[0xb9] = 0x00;
6768 regs[0xba] = 0x00;
6769 regs[0xbb] = 0x00;
6770 regs[0xbc] = 0x00;
6771 regs[0xbd] = 0x00;
6772 regs[0xbe] = 0x00;
6773 regs[0xbf] = 0x00;
6774 regs[0xc0] = 0x06;
6775 regs[0xc1] = 0xe6;
6776 regs[0xc2] = 0x67;
6777 regs[0xc3] = 0xff;
6778 regs[0xc4] = 0xff;
6779 regs[0xc5] = 0xff;
6780 regs[0xc6] = 0xff;
6781 regs[0xc7] = 0xff;
6782 regs[0xc8] = 0xff;
6783 regs[0xc9] = 0x07;
6784 regs[0xca] = 0x00;
6785 regs[0xcb] = 0xfe;
6786 regs[0xcc] = 0xf9;
6787 regs[0xcd] = 0x19;
6788 regs[0xce] = 0x98;
6789 regs[0xcf] = 0xe8;
6790 regs[0xd0] = 0xea;
6791
6792 regs[0xd1] = 0xf3;
6793 regs[0xd2] = 0x14;
6794
6795 regs[0xd3] = 0x02;
6796 regs[0xd4] = 0x04;
6797 regs[0xd5] = 0x86;
6798
6799 regs[0xd6] = 0x0f;
6800 regs[0xd7] = 0x30; /* 12303 */
6801
6802 regs[0xd8] = 0x52; /* 0x5230=21040 */
6803
6804 regs[0xd9] = 0xad;
6805 regs[0xda] = 0xa7;
6806 regs[0xdb] = 0x00;
6807 regs[0xdc] = 0x00;
6808 regs[0xdd] = 0x00;
6809 regs[0xde] = 0x00;
6810 regs[0xdf] = 0x00;
6811 regs[0xe0] = 0x00;
6812 regs[0xe1] = 0x00;
6813 regs[0xe2] = 0x0f;
6814 regs[0xe3] = 0x85;
6815 regs[0xe4] = 0x03;
6816
6817 /* regs[0xe5] = 0x52;
6818 regs[0xe6] = 0x00; exposure time 0x0052=82 */
6819 exposure=82;
6820
6821 regs[0xe7] = 0x75;
6822 regs[0xe8] = 0x01;
6823 regs[0xe9] = 0x0b;
6824 regs[0xea] = 0x54;
6825 regs[0xeb] = 0x01;
6826 regs[0xec] = 0x04;
6827 regs[0xed] = 0xb8;
6828 regs[0xee] = 0x00;
6829 regs[0xef] = 0x03;
6830 regs[0xf0] = 0x70;
6831 regs[0xf1] = 0x00;
6832 regs[0xf2] = 0x01;
6833 regs[0xf3] = 0x00;
6834 if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400)
6835 {
6836 regs[0xc0] = 0x67;
6837 regs[0xc1] = 0x06;
6838 regs[0xc2] = 0xe6;
6839 regs[0xc3] = 0x98;
6840 regs[0xc4] = 0xf9;
6841 regs[0xc5] = 0x19;
6842 regs[0xc6] = 0x67;
6843 regs[0xc7] = 0x06;
6844 regs[0xc8] = 0xe6;
6845 regs[0xc9] = 0x01;
6846 regs[0xca] = 0xf8;
6847 regs[0xcb] = 0xff;
6848 regs[0xcc] = 0x98;
6849 regs[0xcd] = 0xf9;
6850 regs[0xce] = 0x19;
6851 regs[0xcf] = 0xe0;
6852 regs[0xd0] = 0xe2;
6853
6854 regs[0xd1] = 0xeb;
6855 regs[0xd2] = 0x0c;
6856
6857 regs[0xd7] = 0x10;
6858 }
6859 if (dev->sensor == SENSOR_TYPE_4400)
6860 {
6861 regs[0x13] = 0x39; /* 0x20 */
6862 regs[0x14] = 0xf0; /* 0xf8 */
6863 regs[0x15] = 0x29; /* 0x28 */
6864 regs[0x16] = 0x00; /* 0x01 */
6865 regs[0x17] = 0x10; /* 0x00 */
6866 regs[0x23] = 0x00; /* 0x80 */
6867 regs[0x35] = 0x47; /* 0x45 */
6868 regs[0x36] = 0x29; /* 0x2c */
6869 regs[0x39] = 0x00; /* 0x02 */
6870 timing=0x00af;
6871 regs[0x85] = 0x46; /* 0x8c */
6872 regs[0x86] = 0x0b; /* 0x10 */
6873 regs[0x87] = 0x8c; /* 0x18 */
6874 regs[0x88] = 0x10; /* 0x1b */
6875 regs[0x8d] = 0x3b; /* 0x77 */
6876
6877 regs[0xd3] = 0x02; /* 0x0e */
6878 regs[0xd4] = 0x04; /* 0x10 */
6879 regs[0xe2] = 0x07; /* 0x0f */
6880 regs[0xe3] = 0x84; /* 0x87 */
6881 /*regs[0xe5] = 0xa5; 0x54 */
6882 exposure=165;
6883 regs[0xe7] = 0x0e; /* 0xa8 */
6884 regs[0xe8] = 0x01; /* 0x00 */
6885 regs[0xe9] = 0x0a; /* 0x0b */
6886 regs[0xea] = 0xc2; /* 0x56 */
6887 regs[0xed] = 0xf6; /* 0xba */
6888 regs[0xef] = 0x02; /* 0x03 */
6889 regs[0xf0] = 0xa8; /* 0x72 */
6890 }
6891 if (dev->sensor == SENSOR_TYPE_4400_BARE)
6892 {
6893 regs[0x13] = 0x39; /* 0x20 */
6894 regs[0x14] = 0xf0; /* 0xf8 */
6895 regs[0x15] = 0x29; /* 0x28 */
6896 regs[0x16] = 0x00; /* 0x07 */
6897 regs[0x17] = 0x10; /* 0x00 */
6898 regs[0x23] = 0x00; /* 0xff */
6899 regs[0x35] = 0x47; /* 0x0e */
6900 regs[0x36] = 0x29; /* 0x2c */
6901 regs[0x39] = 0x00; /* 0x02 */
6902 regs[0x3a] = 0x43; /* 0x0e */
6903 regs[0x40] = 0x2c; /* 0x20 */
6904 regs[0x85] = 0x46; /* 0x00 */
6905 regs[0x86] = 0x0b; /* 0x06 */
6906 regs[0x87] = 0x8c; /* 0x00 */
6907 regs[0x88] = 0x10; /* 0x06 */
6908 regs[0x8d] = 0x3b; /* 0x00 */
6909 regs[0x90] = 0x18; /* 0x1c */
6910 regs[0xe2] = 0x07; /* 0x05 */
6911 regs[0xe3] = 0x84; /* 0x00 */
6912 regs[0xe4] = 0x03; /* 0x00 */
6913 timing=0x00af;
6914 exposure=165;
6915 regs[0xe7] = 0x0e; /* 0x00 */
6916 regs[0xe8] = 0x01; /* 0x00 */
6917 regs[0xe9] = 0x0a; /* 0x00 */
6918 regs[0xea] = 0xc2; /* 0x00 */
6919 regs[0xeb] = 0x01; /* 0x00 */
6920 regs[0xec] = 0x04; /* 0x00 */
6921 regs[0xed] = 0xf6; /* 0x00 */
6922 regs[0xef] = 0x02; /* 0x00 */
6923 regs[0xf0] = 0xa8; /* 0x00 */
6924 regs[0xf2] = 0x01; /* 0x00 */
6925 }
6926 switch (dev->xdpi)
6927 {
6928 case 75:
6929 break;
6930 case 150:
6931 regs[0x35] = 0x45;
6932
6933
6934 regs[0x85] = 0x8c;
6935 regs[0x86] = 0x10;
6936
6937 regs[0x87] = 0x18;
6938 regs[0x88] = 0x1b;
6939
6940 regs[0x8d] = 0x77;
6941
6942 regs[0xe3] = 0x87;
6943
6944 /* regs[0xe5] = 0x54;
6945 regs[0xe6] = 0x00; exposure time 0x0054=84 */
6946 exposure=84;
6947 timing=0x012e;
6948
6949 regs[0xe7] = 0xa8;
6950 regs[0xe8] = 0x00;
6951 regs[0xea] = 0x56;
6952 regs[0xed] = 0xba;
6953
6954 regs[0xf0] = 0x72;
6955 switch (dev->sensor)
6956 {
6957 case SENSOR_TYPE_XPA:
6958 DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_XPA for 150 dpi\n");
6959 regs[0xc0] = 0x00;
6960 regs[0xc1] = 0x8e;
6961 regs[0xc2] = 0xff;
6962 regs[0xc3] = 0xff;
6963 regs[0xc4] = 0x71;
6964 regs[0xc5] = 0x00;
6965 regs[0xc6] = 0x00;
6966 regs[0xc7] = 0x8e;
6967 regs[0xc8] = 0xff;
6968 regs[0xc9] = 0xff;
6969 regs[0xca] = 0xff;
6970 regs[0xcb] = 0x1f;
6971 regs[0xcc] = 0xff;
6972 regs[0xcd] = 0x71;
6973 regs[0xce] = 0x00;
6974 regs[0xcf] = 0xe6;
6975 regs[0xd0] = 0xe8;
6976 regs[0xd1] = 0xf6;
6977 regs[0xd2] = 0x17;
6978 regs[0xd3] = 0x0b;
6979 regs[0xd4] = 0x0d;
6980 break;
6981 case SENSOR_TYPE_BARE:
6982 DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_BARE for 150 dpi\n");
6983 regs[0xc0] = 0x80;
6984 regs[0xc1] = 0x87;
6985 regs[0xc2] = 0x7f;
6986 regs[0xc9] = 0x00;
6987 regs[0xcb] = 0x78;
6988 regs[0xcc] = 0x7f;
6989 regs[0xcd] = 0x78;
6990 regs[0xce] = 0x80;
6991 regs[0xcf] = 0xe6;
6992 regs[0xd0] = 0xe8;
6993
6994 regs[0xd1] = 0xf7;
6995 regs[0xd2] = 0x00;
6996
6997 regs[0xd3] = 0x0e;
6998 regs[0xd4] = 0x10;
6999 break;
7000 case SENSOR_TYPE_4400:
7001 DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400 for 150 dpi\n");
7002 regs[0x35] = 0x47;
7003
7004 exposure=170;
7005 timing=0x012e;
7006 regs[0x85] = 0x8c;
7007 regs[0x86] = 0x10;
7008 regs[0x87] = 0x18;
7009 regs[0x88] = 0x1b;
7010 regs[0x8d] = 0x77;
7011 regs[0xc0] = 0x00;
7012 regs[0xc1] = 0x8e;
7013 regs[0xc2] = 0xff;
7014 regs[0xc3] = 0xff;
7015 regs[0xc4] = 0x71;
7016 regs[0xc5] = 0x00;
7017 regs[0xc6] = 0x00;
7018 regs[0xc7] = 0x8e;
7019 regs[0xc8] = 0xff;
7020 regs[0xc9] = 0xff;
7021 regs[0xca] = 0xff;
7022 regs[0xcb] = 0x1f;
7023 regs[0xcc] = 0xff;
7024 regs[0xcd] = 0x71;
7025 regs[0xce] = 0x00;
7026 regs[0xcf] = 0xe6;
7027 regs[0xd0] = 0xe8;
7028 regs[0xd1] = 0xf6;
7029 regs[0xd2] = 0x17;
7030 regs[0xd3] = 0x0b;
7031 regs[0xd4] = 0x0d;
7032 regs[0xe3] = 0x86;
7033 regs[0xe7] = 0x00;
7034 regs[0xe8] = 0x1c;
7035 regs[0xe9] = 0x01;
7036 regs[0xea] = 0x0a;
7037 regs[0xeb] = 0xc4;
7038 regs[0xec] = 0x01;
7039 regs[0xed] = 0x04;
7040 regs[0xee] = 0xf8;
7041 regs[0xef] = 0x00;
7042 regs[0xf0] = 0x02;
7043 regs[0xf2] = 0x00;
7044 break;
7045 }
7046 break;
7047
7048 case 300:
7049 switch (dev->sensor)
7050 {
7051 case SENSOR_TYPE_XPA:
7052 DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_XPA for 300 dpi\n");
7053 regs[0x35] = 0x0e; /* fast ? */
7054 regs[0x3a] = 0x0e;
7055
7056
7057 regs[0x85] = 0x18;
7058 regs[0x86] = 0x1b;
7059
7060 regs[0x87] = 0x30;
7061 regs[0x88] = 0x30;
7062
7063 regs[0xe7] = 0x00;
7064 regs[0xe8] = 0x00;
7065 regs[0xe9] = 0x00;
7066 regs[0xea] = 0x00;
7067 regs[0xeb] = 0x00;
7068 regs[0xec] = 0x00;
7069 regs[0xed] = 0x00;
7070 regs[0xef] = 0x00;
7071 regs[0xf0] = 0x00;
7072 regs[0x8d] = 0xef;
7073 regs[0xc0] = 0x00;
7074 regs[0xc1] = 0xff;
7075 regs[0xc2] = 0x0f;
7076 regs[0xc3] = 0xff;
7077 regs[0xc4] = 0x00;
7078 regs[0xc5] = 0xf0;
7079 regs[0xc6] = 0x00;
7080 regs[0xc7] = 0xff;
7081 regs[0xc8] = 0x0f;
7082 regs[0xc9] = 0xff;
7083 regs[0xca] = 0xff;
7084 regs[0xcb] = 0xf1;
7085 regs[0xcc] = 0xff;
7086 regs[0xcd] = 0x00;
7087 regs[0xce] = 0xf0;
7088 regs[0xcf] = 0xed;
7089 regs[0xd0] = 0xef;
7090 regs[0xd1] = 0xe2;
7091 regs[0xd2] = 0x03;
7092 regs[0xd3] = 0x17;
7093 regs[0xd4] = 0x01;
7094 regs[0xe2] = 0x07;
7095 regs[0xe3] = 0x00;
7096 regs[0xe4] = 0x00;
7097 timing=0x022b;
7098 exposure=342;
7099 regs[0xf2] = 0x00;
7100 break;
7101 case SENSOR_TYPE_BARE:
7102 DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_BARE for 300 dpi\n");
7103 regs[0x35] = 0x0e; /* fast ? */
7104 regs[0x3a] = 0x0e;
7105
7106 timing=0x022b;
7107
7108 regs[0x85] = 0x18;
7109 regs[0x86] = 0x1b;
7110
7111 regs[0x87] = 0x30;
7112 regs[0x88] = 0x30;
7113
7114 regs[0xe7] = 0x00;
7115 regs[0xe8] = 0x00;
7116 regs[0xe9] = 0x00;
7117 regs[0xea] = 0x00;
7118 regs[0xeb] = 0x00;
7119 regs[0xec] = 0x00;
7120 regs[0xed] = 0x00;
7121 regs[0xef] = 0x00;
7122 regs[0xf0] = 0x00;
7123 regs[0x8d] = 0xf0;
7124 regs[0x8e] = 0x60; /* low nibble of 8e and 8d are proportional to
7125 the scanned width 1de => 5100 wide scan */
7126
7127 regs[0xc0] = 0xff;
7128 regs[0xc1] = 0x0f;
7129 regs[0xc2] = 0x00;
7130 regs[0xc9] = 0x00;
7131 regs[0xca] = 0x0e;
7132 regs[0xcb] = 0x00;
7133 regs[0xcc] = 0x00;
7134 regs[0xcd] = 0xf0;
7135 regs[0xce] = 0xff;
7136 regs[0xcf] = 0xf5;
7137 regs[0xd0] = 0xf7;
7138 regs[0xd1] = 0xea;
7139 regs[0xd2] = 0x0b;
7140
7141 regs[0xd3] = 0x17;
7142 regs[0xd4] = 0x01;
7143
7144 regs[0xe2] = 0x07;
7145 regs[0xe3] = 0x00;
7146 regs[0xe4] = 0x00;
7147
7148 exposure=342;
7149 break;
7150 case SENSOR_TYPE_4400:
7151 DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400 for 300 dpi\n");
7152 regs[0x11] = 0x22;
7153 regs[0x35] = 0x0e;
7154 regs[0x3a] = 0x0e;
7155 regs[0x85] = 0x18;
7156 regs[0x86] = 0x1b;
7157 regs[0x87] = 0x30;
7158 regs[0x88] = 0x30;
7159 regs[0x8d] = 0xef;
7160 regs[0xc0] = 0x00;
7161 regs[0xc1] = 0xff;
7162 regs[0xc2] = 0x0f;
7163 regs[0xc3] = 0xff;
7164 regs[0xc4] = 0x00;
7165 regs[0xc5] = 0xf0;
7166 regs[0xc6] = 0x00;
7167 regs[0xc7] = 0xff;
7168 regs[0xc8] = 0x0f;
7169 regs[0xc9] = 0xff;
7170 regs[0xca] = 0xff;
7171 regs[0xcb] = 0xf1;
7172 regs[0xcc] = 0xff;
7173 regs[0xcd] = 0x00;
7174 regs[0xce] = 0xf0;
7175 regs[0xcf] = 0xed;
7176 regs[0xd0] = 0xef;
7177 regs[0xd1] = 0xe2;
7178 regs[0xd2] = 0x03;
7179 regs[0xd3] = 0x17;
7180 regs[0xd4] = 0x01;
7181 regs[0xe2] = 0x03;
7182 regs[0xe3] = 0x00;
7183 regs[0xe4] = 0x00;
7184 timing=0x022b;
7185 exposure=686;
7186 regs[0xe7] = 0x00;
7187 regs[0xe8] = 0x00;
7188 regs[0xe9] = 0x00;
7189 regs[0xea] = 0x00;
7190 regs[0xeb] = 0x00;
7191 regs[0xec] = 0x00;
7192 regs[0xed] = 0x00;
7193 regs[0xef] = 0x00;
7194 regs[0xf0] = 0x00;
7195 regs[0xf2] = 0x00;
7196 break;
7197 }
7198 break;
7199 case 600:
7200 *status1 = 0x28;
7201 switch (dev->sensor)
7202 {
7203 case SENSOR_TYPE_BARE:
7204 DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_BARE for 600 dpi\n");
7205
7206 regs[0x34] = 0xf0;
7207 regs[0x35] = 0x1b;
7208 regs[0x36] = 0x29;
7209 regs[0x3a] = 0x1b;
7210
7211 regs[0x72] = 0x3a;
7212 regs[0x73] = 0x15;
7213 regs[0x74] = 0x62;
7214
7215 timing=0x0425;
7216 regs[0x85] = 0x30;
7217 regs[0x86] = 0x30;
7218 regs[0x87] = 0x60;
7219 regs[0x88] = 0x5a;
7220
7221 regs[0x8d] = 0xde;
7222 regs[0x8e] = 0x61; /* low nibble of 8e and 8d are proportional to
7223 the scanned width 1de => 5100 wide scan */
7224
7225 regs[0xc0] = 0xff;
7226 regs[0xc1] = 0xff;
7227 regs[0xc2] = 0xff;
7228 regs[0xc3] = 0x00;
7229 regs[0xc4] = 0xf0;
7230 regs[0xc7] = 0x0f;
7231 regs[0xc8] = 0x00;
7232 regs[0xcb] = 0xe0;
7233 regs[0xcc] = 0xff;
7234 regs[0xcd] = 0xff;
7235 regs[0xce] = 0xff;
7236 regs[0xcf] = 0xe9;
7237 regs[0xd0] = 0xeb;
7238
7239 regs[0xd7] = 0x14;
7240
7241 regs[0xe2] = 0x01;
7242 regs[0xe3] = 0x00;
7243 regs[0xe4] = 0x00;
7244 /* regs[0xe5] = 0xbd;
7245 regs[0xe6] = 0x0a; exposure time = 0x0abd=2749 (5500/2-1) */
7246 exposure=2749;
7247 regs[0xe7] = 0x00;
7248 regs[0xe8] = 0x00;
7249 regs[0xe9] = 0x00;
7250 regs[0xea] = 0x00;
7251 regs[0xeb] = 0x00;
7252 regs[0xec] = 0x00;
7253 regs[0xed] = 0x00;
7254 regs[0xef] = 0x00;
7255 regs[0xf0] = 0x00;
7256 regs[0xf2] = 0x00;
7257 break;
7258 case SENSOR_TYPE_XPA:
7259 DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_XPA for 600 dpi\n");
7260
7261 *status2 = 0x3b;
7262 regs[0x33] = 0x83; /* 0x86 */
7263 regs[0x34] = 0xf0;
7264 regs[0x35] = 0x1b;
7265 regs[0x36] = 0x29;
7266 regs[0x3a] = 0x1b;
7267 regs[0x40] = 0x2c; /* 0x24 */
7268 regs[0x50] = 0x00; /* 0x18 */
7269
7270 regs[0x64] = 0x01; /* 0x02 */
7271 regs[0x65] = 0x20; /* 0x10 */
7272
7273 regs[0x72] = 0x3a;
7274 regs[0x73] = 0x15;
7275 regs[0x74] = 0x62;
7276
7277
7278 regs[0x85] = 0x30;
7279 regs[0x86] = 0x30;
7280
7281 regs[0x87] = 0x60;
7282 regs[0x88] = 0x5a;
7283
7284 regs[0x8d] = 0xde;
7285 regs[0x8e] = 0x61; /* 25054 */
7286
7287 regs[0xc0] = 0xf8;
7288 regs[0xc1] = 0x7f;
7289 regs[0xc2] = 0x00;
7290 regs[0xc3] = 0xf8;
7291 regs[0xc4] = 0x7f;
7292 regs[0xc5] = 0x00;
7293 regs[0xc6] = 0xf8;
7294 regs[0xc7] = 0x7f;
7295 regs[0xc8] = 0x00;
7296 regs[0xc9] = 0xff;
7297 regs[0xca] = 0x8f;
7298 regs[0xcb] = 0xff;
7299 regs[0xcc] = 0x07;
7300 regs[0xcd] = 0x80;
7301 regs[0xce] = 0xff;
7302 regs[0xcf] = 0xf2;
7303 regs[0xd0] = 0xf4;
7304 regs[0xd1] = 0xe7;
7305 regs[0xd2] = 0x08;
7306 regs[0xd3] = 0x02;
7307 regs[0xd4] = 0x10;
7308 regs[0xd7] = 0x31;
7309 regs[0xe2] = 0x01;
7310 regs[0xe3] = 0x00;
7311 regs[0xe4] = 0x00;
7312 regs[0xe7] = 0x00;
7313 regs[0xe8] = 0x00;
7314 regs[0xe9] = 0x00;
7315 regs[0xea] = 0x00;
7316 regs[0xeb] = 0x00;
7317 regs[0xec] = 0x00;
7318 regs[0xed] = 0x00;
7319 regs[0xef] = 0x00;
7320 regs[0xf0] = 0x00;
7321 regs[0xf2] = 0x00;
7322 exposure=2749;
7323 timing=0x0425;
7324 break;
7325
7326 case SENSOR_TYPE_4400:
7327 DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400 for 600 dpi\n");
7328 *status1 = 0x10;
7329 *status2 = 0x23;
7330
7331 regs[0x13] = 0x39;
7332 regs[0x14] = 0xf0;
7333 regs[0x15] = 0x29;
7334 regs[0x16] = 0x00;
7335 regs[0x17] = 0x10;
7336 regs[0x23] = 0x00;
7337 regs[0x34] = 0xf0;
7338 regs[0x35] = 0x1b;
7339 regs[0x36] = 0x29;
7340 regs[0x39] = 0x00;
7341 regs[0x3a] = 0x1b;
7342 regs[0x72] = 0x3a;
7343 regs[0x73] = 0x15;
7344 regs[0x74] = 0x62;
7345 regs[0x85] = 0x30;
7346 regs[0x86] = 0x30;
7347 regs[0x87] = 0x60;
7348 regs[0x88] = 0x5a;
7349 regs[0x8d] = 0xde;
7350 regs[0x8e] = 0x61;
7351 regs[0xc0] = 0xf8;
7352 regs[0xc1] = 0x7f;
7353 regs[0xc2] = 0x00;
7354 regs[0xc3] = 0xf8;
7355 regs[0xc4] = 0x7f;
7356 regs[0xc5] = 0x00;
7357 regs[0xc6] = 0xf8;
7358 regs[0xc7] = 0x7f;
7359 regs[0xc8] = 0x00;
7360 regs[0xc9] = 0xff;
7361 regs[0xca] = 0x8f;
7362 regs[0xcb] = 0xff;
7363 regs[0xcc] = 0x07;
7364 regs[0xcd] = 0x80;
7365 regs[0xce] = 0xff;
7366 regs[0xcf] = 0xf2;
7367 regs[0xd0] = 0xf4;
7368 regs[0xd1] = 0xe7;
7369 regs[0xd2] = 0x08;
7370 regs[0xd3] = 0x0e;
7371 regs[0xd4] = 0x10;
7372 regs[0xd7] = 0x31;
7373 regs[0xe2] = 0x01;
7374 regs[0xe3] = 0x00;
7375 regs[0xe4] = 0x00;
7376 regs[0xe7] = 0x00;
7377 regs[0xe8] = 0x00;
7378 regs[0xe9] = 0x00;
7379 regs[0xea] = 0x00;
7380 regs[0xeb] = 0x00;
7381 regs[0xec] = 0x00;
7382 regs[0xed] = 0x00;
7383 regs[0xef] = 0x00;
7384 regs[0xf0] = 0x00;
7385 regs[0xf2] = 0x00;
7386 timing=0x0425;
7387 exposure=2749;
7388 break;
7389
7390 case SENSOR_TYPE_4400_BARE:
7391 DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400_BARE for 600 dpi\n");
7392 return SANE_STATUS_INVAL;
7393 break;
7394 }
7395 break;
7396 case 1200:
7397 *status1 = 0x28;
7398 switch (dev->sensor)
7399 {
7400 case SENSOR_TYPE_BARE:
7401 DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_BARE for 1200 dpi\n");
7402
7403 regs[0x34] = 0xf0;
7404 regs[0x35] = 0x1b;
7405 regs[0x36] = 0x29;
7406 regs[0x3a] = 0x1b;
7407 regs[0x40] = 0xac;
7408 timing=0x081a;
7409 regs[0x85] = 0x60;
7410 regs[0x86] = 0x5a;
7411 regs[0x87] = 0xc0;
7412 regs[0x88] = 0xae;
7413
7414 regs[0x8d] = 0xbd; /* about twice the 600 dpi values */
7415 regs[0x8e] = 0x63; /* low nibble of 8e and 8d are proportional to
7416 the scanned width 3b5 => 10124 wide scan */
7417 regs[0xc0] = 0xff;
7418 regs[0xc1] = 0xff;
7419 regs[0xc2] = 0xff;
7420 regs[0xc4] = 0x0f;
7421 regs[0xc5] = 0x00;
7422 regs[0xc6] = 0x00;
7423 regs[0xc7] = 0xf0;
7424 regs[0xc9] = 0x00;
7425 regs[0xca] = 0x0e;
7426 regs[0xcb] = 0x00;
7427 regs[0xcc] = 0xff;
7428 regs[0xcd] = 0xff;
7429 regs[0xce] = 0xff;
7430 regs[0xcf] = 0xf5;
7431 regs[0xd0] = 0xf7;
7432 regs[0xd1] = 0xea;
7433 regs[0xd2] = 0x0b;
7434 regs[0xd3] = 0x17;
7435 regs[0xd4] = 0xc1;
7436
7437 regs[0xd7] = 0x14;
7438 regs[0xd8] = 0xa4;
7439
7440 regs[0xe2] = 0x01;
7441 regs[0xe3] = 0x00;
7442 regs[0xe4] = 0x00;
7443 /* regs[0xe5] = 0x7b;
7444 regs[0xe6] = 0x15; exposure time = 0x157b=5499 */
7445 exposure=5499;
7446 regs[0xe7] = 0x00;
7447 regs[0xe8] = 0x00;
7448 regs[0xe9] = 0x00;
7449 regs[0xea] = 0x00;
7450 regs[0xeb] = 0x00;
7451 regs[0xec] = 0x00;
7452 regs[0xed] = 0x00;
7453 regs[0xef] = 0x00;
7454 regs[0xf0] = 0x00;
7455 regs[0xf2] = 0x00;
7456 break;
7457 case SENSOR_TYPE_XPA:
7458 DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_XPA for 1200 dpi\n");
7459 *status2 = 0x3f;
7460
7461 regs[0x34] = 0xf0;
7462 regs[0x35] = 0x1b;
7463 regs[0x36] = 0x29;
7464 regs[0x3a] = 0x1b;
7465 regs[0x85] = 0x60;
7466 regs[0x86] = 0x5a;
7467 regs[0x87] = 0xc0;
7468 regs[0x8a] = 0x08; /* 81c=2076 */
7469
7470 regs[0xc1] = 0xff;
7471 regs[0xce] = 0xff;
7472 regs[0xcf] = 0xf5;
7473 regs[0xd0] = 0xf7;
7474
7475 regs[0xe2] = 0x01;
7476 regs[0xe3] = 0x00;
7477 regs[0xe4] = 0x00;
7478 timing=0x081a;
7479 exposure=5499;
7480 regs[0xe7] = 0x00;
7481 regs[0xe8] = 0x00;
7482 regs[0xe9] = 0x00;
7483 regs[0xea] = 0x00;
7484 regs[0xeb] = 0x00;
7485 regs[0xec] = 0x00;
7486 regs[0xed] = 0x00;
7487 regs[0xef] = 0x00;
7488 regs[0xf0] = 0x00;
7489 regs[0xf2] = 0x00;
7490 regs[0x33] = 0x83;
7491 regs[0x40] = 0xac;
7492 regs[0x50] = 0x00;
7493 regs[0x64] = 0x01;
7494 regs[0x65] = 0x20;
7495 regs[0x88] = 0xae;
7496 regs[0x8d] = 0xbc;
7497 regs[0x8e] = 0x63;
7498 regs[0xc0] = 0xe0;
7499 regs[0xc2] = 0x01;
7500 regs[0xc3] = 0x1f;
7501 regs[0xc4] = 0x00;
7502 regs[0xc5] = 0xfe;
7503 regs[0xc6] = 0xff;
7504 regs[0xc7] = 0xff;
7505 regs[0xc8] = 0x00;
7506 regs[0xc9] = 0x3f;
7507 regs[0xca] = 0xfe;
7508 regs[0xcb] = 0xff;
7509 regs[0xcc] = 0x00;
7510 regs[0xcd] = 0x00;
7511 regs[0xd1] = 0xec;
7512 regs[0xd2] = 0x0d;
7513 regs[0xd3] = 0x05;
7514 regs[0xd4] = 0x67;
7515 regs[0xd7] = 0x10;
7516 regs[0xd8] = 0x52;
7517 break;
7518
7519 case SENSOR_TYPE_4400:
7520 DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400 for 1200 dpi\n");
7521 regs[0x13] = 0x39;
7522 regs[0x14] = 0xf0;
7523 regs[0x15] = 0x29;
7524 regs[0x16] = 0x00;
7525 regs[0x17] = 0x10;
7526 regs[0x23] = 0x00;
7527 regs[0x33] = 0x86;
7528 regs[0x34] = 0xf0;
7529 regs[0x35] = 0x0e;
7530 regs[0x39] = 0x00;
7531 regs[0x3a] = 0x0e;
7532 regs[0x40] = 0xac;
7533 regs[0x64] = 0x02;
7534 regs[0x65] = 0x10;
7535 timing=0x081a;
7536 regs[0x85] = 0x60;
7537 regs[0x86] = 0x5a;
7538 regs[0x87] = 0xc0;
7539 regs[0x88] = 0xae;
7540 regs[0x8d] = 0xbc;
7541 regs[0x8e] = 0x63;
7542 regs[0xc0] = 0xe0;
7543 regs[0xc1] = 0xff;
7544 regs[0xc2] = 0x01;
7545 regs[0xc3] = 0x1f;
7546 regs[0xc4] = 0x00;
7547 regs[0xc5] = 0xfe;
7548 regs[0xc6] = 0xff;
7549 regs[0xc7] = 0xff;
7550 regs[0xc8] = 0x00;
7551 regs[0xc9] = 0x3f;
7552 regs[0xca] = 0xfe;
7553 regs[0xcb] = 0xff;
7554 regs[0xcc] = 0x00;
7555 regs[0xcd] = 0x00;
7556 regs[0xce] = 0xff;
7557 regs[0xcf] = 0xf5;
7558 regs[0xd0] = 0xf7;
7559 regs[0xd1] = 0xec;
7560 regs[0xd2] = 0x0d;
7561 regs[0xd3] = 0x05;
7562 regs[0xd4] = 0x67;
7563 regs[0xd7] = 0x10;
7564 regs[0xd8] = 0x52;
7565 regs[0xe2] = 0x00;
7566 regs[0xe3] = 0x00;
7567 regs[0xe4] = 0x00;
7568 regs[0xe7] = 0x00;
7569 regs[0xe8] = 0x00;
7570 regs[0xe9] = 0x00;
7571 regs[0xea] = 0x00;
7572 regs[0xeb] = 0x00;
7573 regs[0xec] = 0x00;
7574 regs[0xed] = 0x00;
7575 regs[0xef] = 0x00;
7576 regs[0xf0] = 0x00;
7577 regs[0xf2] = 0x00;
7578 exposure=10999;
7579 *status1 = 0x10;
7580 *status2 = 0x23;
7581 break;
7582
7583 case SENSOR_TYPE_4400_BARE:
7584 DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400_BARE for 1200 dpi\n");
7585 return SANE_STATUS_INVAL;
7586 break;
7587 }
7588 break;
7589 }
7590
7591 /* apply computed settings */
7592 SET_DOUBLE (regs, EXPOSURE_REG, exposure);
7593 SET_DOUBLE (regs, TIMING_REG, timing);
7594 SET_DOUBLE (regs, TIMING1_REG, timing+1);
7595 SET_DOUBLE (regs, TIMING2_REG, timing+2);
7596
7597 /* sets divisor */
7598 regs[0xd3] = rts8891_data_format (dev->xdpi, dev->sensor);
7599
7600 /* toggle front panel light to signal gray scan */
7601 if (session->params.format == SANE_FRAME_GRAY)
7602 {
7603 *status1 = (*status1 & 0x0F) | 0x10;
7604 }
7605
7606 return status;
7607 }
7608
7609 /* set up the shadow registers for scan, depending on scan parameters */
7610 /* the ultimate goal is to have no direct access to registers, but to */
7611 /* set them through helper functions */
7612 /* NOTE : I couldn't manage to get scans that really uses gray settings. */
7613 /* The windows driver is always scanning in color, so we do the same. */
7614 /* For now, the only mode that could be done would be 300 dpi gray scan, */
7615 /* based on the register settings of find_origin() */
7616 static SANE_Status
write_scan_registers(struct Rts8891_Session *session)7617 write_scan_registers (struct Rts8891_Session *session)
7618 {
7619 SANE_Status status = SANE_STATUS_GOOD;
7620 SANE_Byte control;
7621 SANE_Byte status1, status2;
7622 struct Rts8891_Device *dev = session->dev;
7623
7624 /* setup registers for scan */
7625 status=setup_scan_registers (session, &status1, &status2, dev->regs);
7626 if (status != SANE_STATUS_GOOD)
7627 {
7628 DBG (DBG_error0, "write_scan_registers: failed to setup registers\n");
7629 return status;
7630 }
7631
7632 /* check if session is idle */
7633 control = 0x00;
7634 sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control);
7635 if (control != 0)
7636 {
7637 DBG (DBG_error0, "write_scan_registers: scanner is not idle!\n");
7638 return SANE_STATUS_IO_ERROR;
7639 }
7640
7641 /* effective write of register set for scan */
7642 status = rts8891_write_all (dev->devnum, dev->regs, dev->reg_count);
7643 if (status != SANE_STATUS_GOOD)
7644 {
7645 DBG (DBG_error0, "write_scan_registers: failed to write registers\n");
7646 }
7647 return status;
7648 }
7649
7650 /**
7651 * This function parks head relying by moving head backward by a
7652 * very large amount without scanning
7653 */
7654 static SANE_Status
park_head(struct Rts8891_Device *dev, SANE_Bool wait)7655 park_head (struct Rts8891_Device *dev, SANE_Bool wait)
7656 {
7657 SANE_Status status;
7658 SANE_Byte reg, control;
7659 /* the hammer way : set all regs */
7660 SANE_Byte regs[244];
7661
7662 DBG (DBG_proc, "park_head: start\n");
7663
7664 reg = 0x8d;
7665 sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®);
7666 reg = 0xad;
7667 sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®);
7668
7669 status = sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control);
7670
7671 reg = 0xff;
7672 sanei_rts88xx_write_reg (dev->devnum, 0x23, ®);
7673
7674 /* TODO create write_double_reg */
7675 if (dev->sensor != SENSOR_TYPE_4400)
7676 {
7677 dev->regs[0x16] = 0x07;
7678 dev->regs[0x17] = 0x00;
7679 }
7680 else
7681 {
7682 dev->regs[0x16] = 0x0f;
7683 dev->regs[0x17] = 0x10;
7684 }
7685 sanei_rts88xx_write_regs (dev->devnum, 0x16, dev->regs + 0x16, 2);
7686
7687 reg = 0x8d;
7688 sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®);
7689 reg = 0xad;
7690 sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®);
7691
7692 /* 0x20 expected */
7693 sanei_rts88xx_read_reg (dev->devnum, CONTROLER_REG, ®);
7694 if (reg != 0x20)
7695 {
7696 DBG (DBG_warn, "park_head: unexpected controller value 0x%02x\n", reg);
7697 }
7698
7699 /* head parking */
7700 status = rts8891_park (dev, regs, wait);
7701 if (status != SANE_STATUS_GOOD)
7702 {
7703 DBG (DBG_error, "park_head: failed to park head!\n");
7704 }
7705
7706 DBG (DBG_proc, "park_head: end\n");
7707 return status;
7708 }
7709
7710 /* update button status
7711 * button access is allowed during scan, which is useful for 'cancel' button
7712 */
7713 static SANE_Status
update_button_status(struct Rts8891_Session *session)7714 update_button_status (struct Rts8891_Session *session)
7715 {
7716 SANE_Int mask = 0, i;
7717 SANE_Status status = SANE_STATUS_GOOD;
7718 SANE_Bool lock = SANE_FALSE;
7719
7720 /* while scanning, interface is reserved, so don't claim/release it */
7721 if (session->scanning != SANE_TRUE)
7722 {
7723 lock = SANE_TRUE;
7724
7725 /* claim the interface to reserve device */
7726 if (session->dev->conf.allowsharing == SANE_TRUE)
7727 {
7728 status = sanei_usb_claim_interface (session->dev->devnum, 0);
7729 if (status != SANE_STATUS_GOOD)
7730 {
7731 DBG (DBG_warn,
7732 "update_button_status: cannot claim usb interface\n");
7733 return SANE_STATUS_DEVICE_BUSY;
7734 }
7735 }
7736 }
7737
7738 /* effective button reading */
7739 status = rts8891_read_buttons (session->dev->devnum, &mask);
7740
7741 /* release interface if needed */
7742 if (lock == SANE_TRUE)
7743 {
7744 if (session->dev->conf.allowsharing == SANE_TRUE)
7745 {
7746 sanei_usb_release_interface (session->dev->devnum, 0);
7747 }
7748 }
7749
7750 for (i = 0; i < session->dev->model->buttons; i++)
7751 {
7752 if (mask & (1 << i))
7753 {
7754 session->val[OPT_BUTTON_1 + i].w = SANE_TRUE;
7755 DBG (DBG_io2, "update_button_status: setting button %d to TRUE\n",
7756 i + 1);
7757 }
7758 }
7759 return status;
7760 }
7761
7762 /* set lamp status, 0 for lamp off
7763 * other values set lamp on */
7764 static SANE_Status
set_lamp_state(struct Rts8891_Session *session, int on)7765 set_lamp_state (struct Rts8891_Session *session, int on)
7766 {
7767 SANE_Status status = SANE_STATUS_GOOD;
7768 SANE_Byte reg;
7769
7770 /* claim the interface reserve device */
7771 if (session->dev->conf.allowsharing == SANE_TRUE)
7772 {
7773 status = sanei_usb_claim_interface (session->dev->devnum, 0);
7774 if (status != SANE_STATUS_GOOD)
7775 {
7776 DBG (DBG_warn, "set_lamp_state: cannot claim usb interface\n");
7777 return SANE_STATUS_DEVICE_BUSY;
7778 }
7779 }
7780
7781 status = sanei_rts88xx_read_reg (session->dev->devnum, LAMP_REG, ®);
7782 if (on)
7783 {
7784 DBG (DBG_info, "set_lamp_state: lamp on\n");
7785 reg = session->dev->regs[LAMP_REG] | 0x80;
7786 }
7787 else
7788 {
7789 DBG (DBG_info, "set_lamp_state: lamp off\n");
7790 reg = session->dev->regs[LAMP_REG] & 0x7F;
7791 #ifdef HAVE_SYS_TIME_H
7792 /* if lamp is switched off, warming up will be needed */
7793 session->dev->last_scan.tv_sec = 0;
7794 #endif
7795 }
7796 status = sanei_rts88xx_write_reg (session->dev->devnum, LAMP_REG, ®);
7797
7798 /* release interface and return status from lamp setting */
7799 if (session->dev->conf.allowsharing == SANE_TRUE)
7800 {
7801 sanei_usb_release_interface (session->dev->devnum, 0);
7802 }
7803 return status;
7804 }
7805
7806 /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
7807