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 (&current, 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 (&current, 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 (&current, 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, &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, &reg);
2940   reg = (reg & 0xF0) | 0x20 | ((~reg) & 0x0F);
2941   dev->regs[LAMP_REG] = reg;
2942   sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, &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, &reg);
2960   status = sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &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, &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, &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, &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, &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, &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, &reg);
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, &reg);
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, &reg);
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, &reg);
4375   reg = 0xad;
4376   sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, &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, &reg);
4392   reg = 0xad;
4393   sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, &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, &reg);
4410   reg |= 0x80;
4411   sanei_rts88xx_read_reg (dev->devnum, 0x40, &reg);
4412   sanei_rts88xx_read_reg (dev->devnum, 0x10, &reg);
4413   sanei_rts88xx_read_reg (dev->devnum, 0x14, &reg);
4414   reg = 0x78;
4415   sanei_rts88xx_write_reg (dev->devnum, 0x10, &reg);
4416   reg = 0x38;
4417   sanei_rts88xx_write_reg (dev->devnum, 0x14, &reg);
4418   reg = 0x78;
4419   sanei_rts88xx_write_reg (dev->devnum, 0x10, &reg);
4420   reg = 0x01;
4421   sanei_rts88xx_write_reg (dev->devnum, CONTROLER_REG, &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, &reg);
4440   reg |= 0x80;
4441   sanei_rts88xx_read_reg (dev->devnum, 0x40, &reg);
4442   sanei_rts88xx_read_reg (dev->devnum, 0x10, &reg);
4443   sanei_rts88xx_read_reg (dev->devnum, 0x14, &reg);
4444   reg = 0x78;
4445   sanei_rts88xx_write_reg (dev->devnum, 0x10, &reg);
4446   reg = 0x38;
4447   sanei_rts88xx_write_reg (dev->devnum, 0x14, &reg);
4448   reg = 0x78;
4449   sanei_rts88xx_write_reg (dev->devnum, 0x10, &reg);
4450   reg = 0x01;
4451   sanei_rts88xx_write_reg (dev->devnum, CONTROLER_REG, &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, &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, &reg);
7666   reg = 0xad;
7667   sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, &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, &reg);
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, &reg);
7689   reg = 0xad;
7690   sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, &reg);
7691 
7692   /* 0x20 expected */
7693   sanei_rts88xx_read_reg (dev->devnum, CONTROLER_REG, &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, &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, &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