1 /* sane - Scanner Access Now Easy.
2 
3    ScanMaker 3840 Backend
4    Copyright (C) 2005 Earle F. Philhower, III
5    earle@ziplabel.com - http://www.ziplabel.com
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 #include <stdio.h>
44 #include <stdarg.h>
45 #include "sm3840_lib.h"
46 
47 #ifndef BACKENDNAME
48 static void setup_scan (p_usb_dev_handle udev, SM3840_Params * p,
49 			char *stname, int raw, int nohead);
50 #else
51 static void setup_scan (p_usb_dev_handle udev, SM3840_Params * p);
52 #endif
53 
54 
55 #ifndef BACKENDNAME
56 
57 #include "sm3840_lib.c"
58 
59 int
main(int argc, char *argv[])60 main (int argc, char *argv[])
61 {
62   int i;
63 
64   int gray = 0;
65   int dpi = 1200;
66   int bpp16 = 0;
67   int raw = 0;
68   int nohead = 0;
69   double gain = 3.5;
70   int offset = 1800;
71   usb_dev_handle *udev;
72 
73   char *stname;
74   double topin, botin, leftin, rightin;
75   int topline, scanlines, leftpix, scanpix;
76 
77   stname = NULL;
78   topin = 0.0;
79   botin = 11.7;
80   leftin = 0.0;
81   rightin = 8.5;
82   for (i = 1; i < argc; i++)
83     {
84       if (!strcmp (argv[i], "-300"))
85 	dpi = 300;
86       else if (!strcmp (argv[i], "-600"))
87 	dpi = 600;
88       else if (!strcmp (argv[i], "-1200"))
89 	dpi = 1200;
90       else if (!strcmp (argv[i], "-150"))
91 	dpi = 150;
92       else if (!strcmp (argv[i], "-top"))
93 	topin = atof (argv[++i]);
94       else if (!strcmp (argv[i], "-bot"))
95 	botin = atof (argv[++i]);
96       else if (!strcmp (argv[i], "-left"))
97 	leftin = atof (argv[++i]);
98       else if (!strcmp (argv[i], "-right"))
99 	rightin = atof (argv[++i]);
100       else if (!strcmp (argv[i], "-gain"))
101 	gain = atof (argv[++i]);
102       else if (!strcmp (argv[i], "-offset"))
103 	offset = atoi (argv[++i]);
104       else if (!strcmp (argv[i], "-gray"))
105 	gray = 1;
106       else if (!strcmp (argv[i], "-16bpp"))
107 	bpp16 = 1;
108       else if (!strcmp (argv[i], "-raw"))
109 	raw = 1;
110       else if (!strcmp (argv[i], "-nohead"))
111 	nohead = 1;
112       else
113 	stname = argv[i];
114     }
115 
116   SM3840_Params params;
117   params.gray = gray;
118   params.dpi = dpi;
119   params.bpp = bpp16 ? 16 : 8;
120   params.gain = gain;
121   params.offset = offset;
122   params.lamp = 15;
123   params.top = topin;
124   params.left = leftin;
125   params.height = botin - topin;
126   params.width = rightin - leftin;
127 
128   prepare_params (&params);
129   udev = find_device (0x05da, 0x30d4); /* 3840 */
130   if (!udev)
131     udev = find_device (0x05da, 0x30cf); /* 4800 */
132   if (!udev)
133     fprintf (stderr, "Unable to open scanner.\n");
134   else
135     setup_scan (udev, &params, stname, raw, nohead);
136 
137   return 0;
138 }
139 #endif
140 
141 #ifndef BACKENDNAME
142 static void
setup_scan(p_usb_dev_handle udev, SM3840_Params * p, char *stname, int raw, int nohead)143 setup_scan (p_usb_dev_handle udev, SM3840_Params * p,
144 	    char *stname, int raw, int nohead)
145 #else
146 static void
147 setup_scan (p_usb_dev_handle udev, SM3840_Params * p)
148 #endif
149 {
150   int gray = p->gray ? 1 : 0;
151   int dpi = p->dpi;
152   int bpp16 = (p->bpp == 16) ? 1 : 0;
153   double gain = p->gain;
154   int offset = p->offset;
155   int topline = p->topline;
156   int scanlines = p->scanlines;
157   int leftpix = p->leftpix;
158   int scanpix = p->scanpix;
159   unsigned char hello[2] = { 0x55, 0xaa };
160   unsigned char howdy[3];
161   unsigned short *whitebalance;
162   int whitebalancesize = (dpi == 1200) ? 12672 : 6528;
163   unsigned short *whitemap;
164   int whitemapsize = (dpi == 1200) ? 29282 : 14642;
165   unsigned short *whitescan;
166   unsigned short *lightmap;
167   unsigned int topreg, botreg;
168   int redreg, greenreg, bluereg, donered, donegreen, doneblue;
169   int rgreg = 0x00;
170   int ggreg = 0x00;
171   int bgreg = 0x00;
172   int i, j;
173   int red, green, blue;
174   unsigned char rd_byte;
175   unsigned short GRAYMASK = 0xc000;
176 
177 
178 #ifndef BACKENDNAME
179   char fname[64];
180   char head[128];
181 
182   usb_set_configuration (udev, 1);
183   usb_claim_interface (udev, 0);
184   usb_clear_halt (udev, 1);
185   usb_clear_halt (udev, 2);
186   usb_clear_halt (udev, 3);
187 #endif
188   DBG (2, "params.gray = %d;\n", p->gray);
189   DBG (2, "params.dpi = %d\n", p->dpi);
190   DBG (2, "params.bpp = %d\n", p->bpp);
191   DBG (2, "params.gain = %f\n", p->gain);
192   DBG (2, "params.offset = %d\n", p->offset);
193   DBG (2, "params.lamp = %d\n", p->lamp);
194   DBG (2, "params.top = %f\n", p->top);
195   DBG (2, "params.left = %f\n", p->left);
196   DBG (2, "params.height = %f\n", p->height);
197   DBG (2, "params.width = %f\n", p->width);
198 
199   DBG (2, "params.topline = %d\n", p->topline);
200   DBG (2, "params.scanlines = %d\n", p->scanlines);
201   DBG (2, "params.leftpix = %d\n", p->leftpix);
202   DBG (2, "params.scanpix = %d\n", p->scanpix);
203 
204   DBG (2, "params.linelen = %d\n", p->linelen);
205 
206   reset_scanner (udev);
207 
208   idle_ab (udev);
209   write_regs (udev, 4, 0x83, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0x97, 0x0a);
210   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
211   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
212   write_regs (udev, 1, 0x97, 0x0b);
213   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
214   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
215   write_regs (udev, 1, 0x97, 0x0f);
216   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
217   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
218   write_regs (udev, 1, 0x97, 0x05);
219   write_vctl (udev, 0x0b, 0x0004, 0x008b, 0x00);
220   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
221   write_regs (udev, 7, 0xa8, 0x80, 0x83, 0xa2, 0x85, 0x01, 0x83, 0x82, 0x85,
222 	      0x00, 0x83, 0x00, 0x93, 0x00);
223   write_regs (udev, 1, 0xa8, 0x80);
224   write_regs (udev, 4, 0x83, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0x97, 0x0a);
225   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
226   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
227   write_regs (udev, 1, 0x97, 0x0b);
228   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
229   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
230   write_regs (udev, 1, 0x97, 0x0f);
231   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
232   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
233   write_regs (udev, 1, 0x97, 0x05);
234   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
235   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
236   write_regs (udev, 4, 0x83, 0x20, 0x8d, 0xfe, 0x83, 0x00, 0x8d, 0xff);
237   write_regs (udev, 1, 0x97, 0x00);
238   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
239   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
240   write_regs (udev, 8, 0x80, 0x00, 0x84, 0x00, 0xbe, 0x00, 0xc0, 0x00, 0x86,
241 	      0x00, 0x89, 0x00, 0x94, 0x00, 0x01, 0x02);
242   write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00);
243   write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00);
244   write_regs (udev, 1, 0x94, 0x51);
245   write_regs (udev, 1, 0xb0, 0x00);
246   write_regs (udev, 1, 0xb1, 0x00);
247   write_regs (udev, 1, 0xb2, 0x00);
248   write_regs (udev, 1, 0xb3, 0x00);
249   write_regs (udev, 1, 0xb4, 0x10);
250   write_regs (udev, 1, 0xb5, 0x1f);
251   write_regs (udev, 1, 0xb0, 0x00);
252   write_regs (udev, 1, 0xb1, 0x00);
253   write_regs (udev, 1, 0xb2, 0x00);
254   write_vctl (udev, 0x0c, 0x0002, 0x0002, 0x00);
255   usb_bulk_write (udev, 2, hello, 2, wr_timeout);
256   write_regs (udev, 1, 0xb0, 0x00);
257   write_regs (udev, 1, 0xb1, 0x00);
258   write_regs (udev, 1, 0xb2, 0x00);
259   write_vctl (udev, 0x0c, 0x0003, 0x0003, 0x00);
260   usb_bulk_read (udev, 1, howdy, 3, rd_timeout);
261   write_regs (udev, 4, 0x83, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0x97, 0x0a);
262   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
263   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
264   write_regs (udev, 1, 0x97, 0x0b);
265   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
266   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
267   write_regs (udev, 1, 0x97, 0x0f);
268   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
269   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
270   write_regs (udev, 1, 0x97, 0x05);
271   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
272   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
273   write_regs (udev, 4, 0x83, 0x20, 0x8d, 0xfe, 0x83, 0x00, 0x8d, 0xff);
274   write_regs (udev, 1, 0x97, 0x00);
275   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
276   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
277   write_regs (udev, 8, 0x80, 0x00, 0x84, 0x00, 0xbe, 0x00, 0xc0, 0x00, 0x86,
278 	      0x00, 0x89, 0x00, 0x94, 0x00, 0x01, 0x02);
279   write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00);
280   write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00);
281   write_regs (udev, 16, 0xbe, 0x18, 0x80, 0x00, 0x84, 0x00, 0x89, 0x00, 0x88,
282 	      0x00, 0x86, 0x00, 0x90, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
283 	      0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xc8,
284 	      0x00, 0xc0, 0x00);
285   write_regs (udev, 4, 0x83, 0x20, 0x8d, 0xff, 0x83, 0x00, 0x8d, 0xff);
286   write_regs (udev, 5, 0x83, 0x00, 0xa3, 0xff, 0xa4, 0xff, 0xa1, 0xff, 0xa2,
287 	      0xf7);
288   write_regs (udev, 4, 0x83, 0x22, 0x87, 0x01, 0x83, 0x02, 0x87, 0x16);
289   write_regs (udev, 11, 0xa0, 0x00, 0x9c, 0x00, 0x9f, 0x00, 0x9d, 0x00, 0x9e,
290 	      0x00, 0xa0, 0x00, 0xce, 0x0c, 0x83, 0x20, 0xa5, 0x00, 0xa6,
291 	      0x00, 0xa7, 0x00);
292 
293   set_gain_black (udev, 0x01, 0x01, 0x01, 0xaa, 0xaa, 0xaa);
294 
295   write_regs (udev, 16, 0x9b, 0x00, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b,
296 	      0x01, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b, 0x02, 0x98,
297 	      0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b, 0x03, 0x98, 0x00, 0x99,
298 	      0x00, 0x9a, 0x00);
299   write_regs (udev, 4, 0x83, 0xa2, 0x85, 0x98, 0x83, 0x82, 0x85, 0x3a);
300   write_regs (udev, 1, 0x9d, 0x80);
301   write_regs (udev, 1, 0x9d, 0x00);
302 
303   if (dpi == 1200)
304     write_regs (udev, 1, 0x94, 0x51);
305   else
306     write_regs (udev, 1, 0x94, 0x61);
307 
308   whitemap = (unsigned short *) malloc (whitemapsize);
309 
310   set_lightmap_white (whitemap, dpi, 0);
311   if (dpi == 1200)
312     write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x80, 0xb2, 0x06, 0xb3, 0xff, 0xb4,
313 		0xff, 0xb5, 0x06);
314   else
315     write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x40, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
316 		0x7f, 0xb5, 0x07);
317   write_vctl (udev, 0x0c, 0x0002, whitemapsize, 0x00);
318   usb_bulk_write (udev, 2, (unsigned char *) whitemap, whitemapsize,
319                   wr_timeout);
320 
321   set_lightmap_white (whitemap, dpi, 1);
322   if (dpi == 1200)
323     write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
324 		0x7f, 0xb5, 0x07);
325   else
326     write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x80, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
327 		0xbf, 0xb5, 0x07);
328   write_vctl (udev, 0x0c, 0x0002, whitemapsize, 0x00);
329   usb_bulk_write (udev, 2, (unsigned char *) whitemap, whitemapsize,
330                   wr_timeout);
331 
332   set_lightmap_white (whitemap, dpi, 2);
333   if (dpi == 1200)
334     write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x80, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
335 		0xff, 0xb5, 0x07);
336   else
337     write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0xc0, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
338 		0xff, 0xb5, 0x07);
339   write_vctl (udev, 0x0c, 0x0002, whitemapsize, 0x00);
340   usb_bulk_write (udev, 2, (unsigned char *) whitemap, whitemapsize,
341                   wr_timeout);
342 
343   free (whitemap);
344 
345   /* Move to head... */
346   idle_ab (udev);
347   write_regs (udev, 1, 0x97, 0x00);
348   idle_ab (udev);
349   write_regs (udev, 16, 0xbe, 0x18, 0x80, 0x00, 0x84, 0x00, 0x89, 0x00, 0x88,
350 	      0x00, 0x86, 0x00, 0x90, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
351 	      0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xc8,
352 	      0x00, 0xc0, 0x00);
353   idle_ab (udev);
354   write_regs (udev, 16, 0x84, 0x94, 0x80, 0xd1, 0x80, 0xc1, 0x82, 0x7f, 0xcf,
355 	      0x04, 0xc1, 0x02, 0xc2, 0x00, 0xc3, 0x06, 0xc4, 0xff, 0xc5,
356 	      0x40, 0xc6, 0x8c, 0xc7, 0xdc, 0xc8, 0x20, 0xc0, 0x72, 0x89,
357 	      0xff, 0x86, 0xff);
358   poll1 (udev);
359 
360   write_regs (udev, 4, 0x83, 0xa2, 0x85, 0x01, 0x83, 0x82, 0x85, 0x00);
361   write_regs (udev, 1, 0x9d, 0x80);
362   write_regs (udev, 1, 0x9d, 0x00);
363   if (dpi == 1200)
364     write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
365 		0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8, 0x77,
366 		0xb9, 0x1e);
367   else
368     write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
369 		0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8, 0x3b,
370 		0xb9, 0x1f);
371   write_regs (udev, 5, 0xc0, 0x00, 0x84, 0x00, 0x80, 0xa1, 0xcf, 0x04, 0x82,
372 	      0x00);
373   if (dpi == 1200)
374     write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x02, 0x83, 0x82, 0x85, 0x00,
375 		0xbc, 0x01, 0xbd, 0x01, 0x88, 0xa4, 0xc1, 0x02, 0xc2, 0x00,
376 		0xc3, 0x02, 0xc4, 0x01, 0xc5, 0x01, 0xc6, 0xa3, 0xc7, 0xa4,
377 		0xc8, 0x04, 0xc0, 0xd2, 0x89, 0x05, 0x86, 0x00);
378   else
379     write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x04, 0x83, 0x82, 0x85, 0x00,
380 		0xbc, 0x01, 0xbd, 0x01, 0x88, 0xd0, 0xc1, 0x01, 0xc2, 0x00,
381 		0xc3, 0x04, 0xc4, 0x01, 0xc5, 0x01, 0xc6, 0xcf, 0xc7, 0xd0,
382 		0xc8, 0x14, 0xc0, 0xd1, 0x89, 0x0a, 0x86, 0x00);
383   write_regs (udev, 8, 0xbb, 0x01, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80, 0xbf,
384 	      0x00, 0x90, 0x40, 0x91, 0x00, 0x83, 0x82);
385   write_regs (udev, 1, 0xbe, 0x0d);
386   write_vctl (udev, 0x0c, 0x0003, 0x0001, 0x00);
387   whitebalance = (unsigned short *) malloc (whitebalancesize);
388   usb_bulk_read (udev, 1, &rd_byte, 1, rd_timeout);
389   write_vctl (udev, 0x0c, 0x0001, 0x0000, 0x00);
390   usb_bulk_read (udev, 1, (unsigned char *) whitebalance, whitebalancesize,
391                  rd_timeout);
392   write_regs (udev, 2, 0xbe, 0x00, 0x84, 0x00);
393   write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00);
394   write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00);
395   redreg = greenreg = bluereg = 0x80;
396   red = green = blue = 0;
397   donered = donegreen = doneblue = 0;
398   DBG (2, "setting blackpoint\n");
399   for (j = 0; (j < 16) && !(donered && donegreen && doneblue); j++)
400     {
401       set_gain_black (udev, 0x01, 0x01, 0x01, redreg, greenreg, bluereg);
402 
403       if (dpi == 1200)
404 	write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
405 		    0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8,
406 		    0x77, 0xb9, 0x1e);
407       else
408 	write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
409 		    0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8,
410 		    0x3b, 0xb9, 0x1f);
411       write_regs (udev, 8, 0xbb, 0x01, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
412 		  0xbf, 0x00, 0x90, 0x40, 0x91, 0x00, 0x83, 0x82);
413       write_regs (udev, 1, 0xbe, 0x0d);
414       write_vctl (udev, 0x0c, 0x0003, 0x0001, 0x00);
415       usb_bulk_read (udev, 1, &rd_byte, 1, rd_timeout);
416       write_vctl (udev, 0x0c, 0x0001, 0x0000, 0x00);
417       usb_bulk_read (udev, 1, (unsigned char *) whitebalance,
418                      whitebalancesize, rd_timeout);
419       fix_endian_short (whitebalance, whitebalancesize/2);
420       if (!donered)
421 	{
422 	  red = (whitebalance[0] + whitebalance[3] + whitebalance[6]) / 3;
423 	  if (red > 0x1000)
424 	    redreg += 0x10;
425 	  else if (red > 0x500)
426 	    redreg += 0x08;
427 	  else if (red > 0x0010)
428 	    redreg++;
429 	  else
430 	    donered = 1;
431 	}
432       if (!donegreen)
433 	{
434 	  green = (whitebalance[1] + whitebalance[4] + whitebalance[7]) / 3;
435 	  if (green > 0x1000)
436 	    greenreg += 0x10;
437 	  else if (green > 0x0500)
438 	    greenreg += 0x08;
439 	  else if (green > 0x0010)
440 	    greenreg++;
441 	  else
442 	    donegreen = 1;
443 	}
444       if (!doneblue)
445 	{
446 	  blue = (whitebalance[2] + whitebalance[5] + whitebalance[8]) / 3;
447 	  if (blue > 0x1000)
448 	    bluereg += 0x10;
449 	  else if (blue > 0x0500)
450 	    bluereg += 0x08;
451 	  else if (blue > 0x0010)
452 	    bluereg++;
453 	  else
454 	    doneblue = 1;
455 	}
456       DBG (2, "red=%d(%d)%02x, green=%d(%d)%02x, blue=%d(%d)%02x\n",
457 	   red, donered, redreg, green, donegreen, greenreg,
458 	   blue, doneblue, bluereg);
459       write_regs (udev, 2, 0xbe, 0x00, 0x84, 0x00);
460       write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00);
461       write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00);
462     }
463   DBG (2, "setting whitepoint\n");
464   donegreen = donered = doneblue = 0;
465   for (j = 0; (j < 16) && !(donered && donegreen && doneblue); j++)
466     {
467       set_gain_black (udev, rgreg, ggreg, bgreg, redreg, greenreg, bluereg);
468 
469       if (dpi == 1200)
470 	idle_ab (udev);
471       write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
472 		  0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8, 0x3b,
473 		  0xb9, 0x1f);
474       if (dpi == 1200)
475 	idle_ab (udev);
476       write_regs (udev, 8, 0xbb, 0x01, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
477 		  0xbf, 0x00, 0x90, 0x40, 0x91, 0x00, 0x83, 0x82);
478       write_regs (udev, 1, 0xbe, 0x0d);
479       write_vctl (udev, 0x0c, 0x0003, 0x0001, 0x00);
480       usb_bulk_read (udev, 1, &rd_byte, 1, rd_timeout);
481       write_vctl (udev, 0x0c, 0x0001, 0x0000, 0x00);
482       usb_bulk_read (udev, 1, (unsigned char *) whitebalance,
483                      whitebalancesize, rd_timeout);
484       fix_endian_short (whitebalance, whitebalancesize/2);
485       if (!donered)
486 	{
487 	  red =
488 	    (whitebalance[180 * 3 + 0] + whitebalance[180 * 3 + 3] +
489 	     whitebalance[180 * 3 + 6]) / 3;
490 	  if (red < 0x5000)
491 	    rgreg += 0x02;
492 	  else if (red < 0x8000)
493 	    rgreg += 0x01;
494 	  else
495 	    donered = 1;
496 	}
497       if (!donegreen)
498 	{
499 	  green =
500 	    (whitebalance[180 * 3 + 1] + whitebalance[180 * 3 + 4] +
501 	     whitebalance[180 * 3 + 7]) / 3;
502 	  if (green < 0x5000)
503 	    ggreg += 0x02;
504 	  else if (green < 0x8000)
505 	    ggreg += 0x01;
506 	  else
507 	    donegreen = 1;
508 	}
509       if (!doneblue)
510 	{
511 	  blue =
512 	    (whitebalance[180 * 3 + 2] + whitebalance[180 * 3 + 5] +
513 	     whitebalance[180 * 3 + 8]) / 3;
514 	  if (blue < 0x5000)
515 	    bgreg += 0x02;
516 	  else if (blue < 0x8000)
517 	    bgreg += 0x01;
518 	  else
519 	    doneblue = 1;
520 	}
521       DBG (2, "red=%d(%d)%02x, green=%d(%d)%02x, blue=%d(%d)%02x\n",
522 	   red, donered, rgreg, green, donegreen, ggreg, blue, doneblue,
523 	   bgreg);
524       write_regs (udev, 2, 0xbe, 0x00, 0x84, 0x00);
525       write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00);
526       write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00);
527     }
528   free (whitebalance);
529 
530   /* One step down for optimal contrast... */
531   if (rgreg)
532     rgreg--;
533   if (bgreg)
534     bgreg--;
535   if (ggreg)
536     ggreg--;
537 
538 
539   write_regs (udev, 8, 0x80, 0x00, 0x84, 0x00, 0xbe, 0x00, 0xc0, 0x00, 0x86,
540 	      0x00, 0x89, 0x00, 0x94, 0x00, 0x01, 0x02);
541   write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00);
542   write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00);
543   write_regs (udev, 16, 0xbe, 0x18, 0x80, 0x00, 0x84, 0x00, 0x89, 0x00, 0x88,
544 	      0x00, 0x86, 0x00, 0x90, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
545 	      0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xc8,
546 	      0x00, 0xc0, 0x00);
547   write_regs (udev, 4, 0x83, 0x20, 0x8d, 0xff, 0x83, 0x00, 0x8d, 0xff);
548   write_regs (udev, 5, 0x83, 0x00, 0xa3, 0xff, 0xa4, 0xff, 0xa1, 0xff, 0xa2,
549 	      0xf7);
550   write_regs (udev, 4, 0x83, 0x22, 0x87, 0x01, 0x83, 0x02, 0x87, 0x16);
551   write_regs (udev, 11, 0xa0, 0x00, 0x9c, 0x00, 0x9f, 0x00, 0x9d, 0x00, 0x9e,
552 	      0x00, 0xa0, 0x00, 0xce, 0x0c, 0x83, 0x20, 0xa5, 0x00, 0xa6,
553 	      0x00, 0xa7, 0x00);
554   set_gain_black (udev, rgreg, ggreg, bgreg, redreg, greenreg, bluereg);
555 
556   write_regs (udev, 16, 0x9b, 0x00, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b,
557 	      0x01, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b, 0x02, 0x98,
558 	      0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b, 0x03, 0x98, 0x00, 0x99,
559 	      0x00, 0x9a, 0x00);
560   write_regs (udev, 4, 0x83, 0xa2, 0x85, 0x98, 0x83, 0x82, 0x85, 0x3a);
561   write_regs (udev, 1, 0x9d, 0x80);
562   write_regs (udev, 1, 0x9d, 0x00);
563   if (dpi == 1200)
564     write_regs (udev, 1, 0x94, 0x71);
565   else
566     write_regs (udev, 1, 0x94, 0x61);
567 
568   write_regs (udev, 4, 0x83, 0xa2, 0x85, 0x01, 0x83, 0x82, 0x85, 0x00);
569   write_regs (udev, 1, 0x9d, 0x80);
570   write_regs (udev, 1, 0x9d, 0x00);
571   if (dpi == 1200)
572     write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
573 		0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8, 0xbf,
574 		0xb9, 0x17);
575   else
576     write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
577 		0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8, 0xdf,
578 		0xb9, 0x1b);
579   write_regs (udev, 6, 0xc0, 0x00, 0x84, 0x00, 0x84, 0xb4, 0x80, 0xe1, 0xcf,
580 	      0x04, 0x82, 0x00);
581   if (dpi == 1200)
582     write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x02, 0x83, 0x82, 0x85, 0x00,
583 		0xbc, 0x20, 0xbd, 0x08, 0x88, 0xa4, 0xc1, 0x02, 0xc2, 0x00,
584 		0xc3, 0x02, 0xc4, 0x20, 0xc5, 0x08, 0xc6, 0x96, 0xc7, 0xa4,
585 		0xc8, 0x06, 0xc0, 0xd2, 0x89, 0x24, 0x86, 0x01);
586   else
587     write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x04, 0x83, 0x82, 0x85, 0x00,
588 		0xbc, 0x20, 0xbd, 0x10, 0x88, 0xd0, 0xc1, 0x01, 0xc2, 0x00,
589 		0xc3, 0x04, 0xc4, 0x20, 0xc5, 0x10, 0xc6, 0xc3, 0xc7, 0xd0,
590 		0xc8, 0x1c, 0xc0, 0xd1, 0x89, 0x24, 0x86, 0x01);
591   write_regs (udev, 8, 0xbb, 0x05, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80, 0xbf,
592 	      0x00, 0x90, 0x40, 0x91, 0x00, 0x83, 0x82);
593   write_regs (udev, 1, 0xbe, 0x1d);
594   write_vctl (udev, 0x0c, 0x0003, 0x0001, 0x00);
595   usb_bulk_read (udev, 1, &rd_byte, 1, rd_timeout);
596   write_vctl (udev, 0x0c, 0x0001, 0x0000, 0x00);
597   record_mem (udev, (unsigned char **) (void *)&whitescan,
598 	      (5632 * 2 * 3 * (dpi == 1200 ? 2 : 1)) * 4);
599   fix_endian_short (whitescan, (5632 * 2 * 3 * (dpi == 1200 ? 2 : 1)) * 2);
600   write_regs (udev, 5, 0x83, 0x00, 0xa3, 0xff, 0xa4, 0xff, 0xa1, 0xff, 0xa2,
601 	      0xff);
602   write_vctl (udev, 0x0c, 0x0001, 0x0000, 0x00);
603   write_regs (udev, 2, 0xbe, 0x00, 0x84, 0x00);
604   write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00);
605   write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00);
606   write_regs (udev, 4, 0x83, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0x97, 0x0a);
607   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
608   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
609   write_regs (udev, 1, 0x97, 0x0b);
610   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
611   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
612   write_regs (udev, 1, 0x97, 0x0f);
613   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
614   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
615   write_regs (udev, 1, 0x97, 0x05);
616   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
617   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
618   write_regs (udev, 4, 0x83, 0x20, 0x8d, 0xff, 0x83, 0x00, 0x8d, 0xff);
619   write_regs (udev, 1, 0x97, 0x00);
620   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
621   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
622   write_regs (udev, 1, 0x97, 0x00);
623   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
624   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
625   write_regs (udev, 16, 0xbe, 0x18, 0x80, 0x00, 0x84, 0x00, 0x89, 0x00, 0x88,
626 	      0x00, 0x86, 0x00, 0x90, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
627 	      0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xc8,
628 	      0x00, 0xc0, 0x00);
629   write_regs (udev, 16, 0x84, 0x94, 0x80, 0xd1, 0x80, 0xc1, 0x82, 0x7f, 0xcf,
630 	      0x04, 0xc1, 0x02, 0xc2, 0x00, 0xc3, 0x06, 0xc4, 0xff, 0xc5,
631 	      0x40, 0xc6, 0x8c, 0xc7, 0xdc, 0xc8, 0x20, 0xc0, 0x72, 0x89,
632 	      0xff, 0x86, 0xff);
633   poll1 (udev);
634 
635   /* ready scan position */
636   /* 1/3" of unscannable area at top... */
637   if (dpi == 300)
638     topreg = 120 * 4;
639   else if (dpi == 600)
640     topreg = 139 * 4;
641   else if (dpi == 1200)
642     topreg = 152 * 4;
643   else				/*if (dpi == 150) */
644     topreg = 120 * 4;
645   topreg += topline * (1200 / dpi);
646 
647   write_regs (udev, 16, 0xbe, 0x18, 0x80, 0x00, 0x84, 0x00, 0x89, 0x00, 0x88,
648 	      0x00, 0x86, 0x00, 0x90, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
649 	      0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xc8,
650 	      0x00, 0xc0, 0x00);
651   write_regs (udev, 14, 0x84, 0xb4, 0x80, 0xe1, 0xcf, 0x04, 0xc1, 0x02, 0xc2,
652 	      0x00, 0xc3, 0x07, 0xc4, 0xff, 0xc5, 0x40, 0xc6, 0x8c, 0xc7,
653 	      0xdc, 0xc8, 0x20, 0xc0, 0x72, 0x89, topreg & 255, 0x86,
654 	      255 & (topreg >> 8));
655   write_regs (udev, 1, 0x97, 0x00);
656   poll2 (udev);
657 
658   write_regs (udev, 8, 0x80, 0x00, 0x84, 0x00, 0xbe, 0x00, 0xc0, 0x00, 0x86,
659 	      0x00, 0x89, 0x00, 0x94, 0x00, 0x01, 0x02);
660   write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00);
661   write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00);
662   write_regs (udev, 16, 0xbe, 0x18, 0x80, 0x00, 0x84, 0x00, 0x89, 0x00, 0x88,
663 	      0x00, 0x86, 0x00, 0x90, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
664 	      0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xc8,
665 	      0x00, 0xc0, 0x00);
666   if (dpi == 1200)
667     write_regs (udev, 4, 0x83, 0x20, 0x8d, 0x24, 0x83, 0x00, 0x8d, 0xff);
668   else
669     write_regs (udev, 4, 0x83, 0x20, 0x8d, 0xff, 0x83, 0x00, 0x8d, 0xff);
670   if (dpi != 1200)
671     write_regs (udev, 5, 0x83, 0x00, 0xa3, 0xff, 0xa4, 0xff, 0xa1, 0xff, 0xa2,
672 		0xf7);
673   if (dpi == 1200)
674     write_regs (udev, 4, 0x83, 0x22, 0x87, 0x01, 0x83, 0x02, 0x87, 0x2c);
675   else
676     write_regs (udev, 4, 0x83, 0x22, 0x87, 0x01, 0x83, 0x02, 0x87, 0x16);
677   if (dpi == 1200)
678     write_regs (udev, 11, 0xa0, 0x00, 0x9c, 0x00, 0x9f, 0x40, 0x9d, 0x00,
679 		0x9e, 0x00, 0xa0, 0x00, 0xce, 0x0c, 0x83, 0x20, 0xa5, 0x00,
680 		0xa6, 0x00, 0xa7, 0x00);
681   else
682     write_regs (udev, 11, 0xa0, 0x00, 0x9c, 0x00, 0x9f, 0x00, 0x9d, 0x00,
683 		0x9e, 0x00, 0xa0, 0x00, 0xce, 0x0c, 0x83, 0x20, 0xa5, 0x00,
684 		0xa6, 0x00, 0xa7, 0x00);
685 
686   set_gain_black (udev, rgreg, ggreg, bgreg, redreg, greenreg, bluereg);
687   if (!bpp16)
688     {
689       if (dpi == 1200)
690 	write_regs (udev, 16, 0x9b, 0x00, 0x98, 0xc7, 0x99, 0x99, 0x9a, 0xd5,
691 		    0x9b, 0x01, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b,
692 		    0x02, 0x98, 0xc8, 0x99, 0x99, 0x9a, 0xd3, 0x9b, 0x03,
693 		    0x98, 0x00, 0x99, 0x00, 0x9a, 0x00);
694       else if (dpi == 150)
695 	write_regs (udev, 16, 0x9b, 0x00, 0x98, 0x94, 0x99, 0x67, 0x9a, 0x83,
696 		    0x9b, 0x01, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b,
697 		    0x02, 0x98, 0x7e, 0x99, 0x5d, 0x9a, 0x7d, 0x9b, 0x03,
698 		    0x98, 0x00, 0x99, 0x00, 0x9a, 0x00);
699       else
700 	write_regs (udev, 16, 0x9b, 0x00, 0x98, 0xb3, 0x99, 0x72, 0x9a, 0x9d,
701 		    0x9b, 0x01, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b,
702 		    0x02, 0x98, 0xa3, 0x99, 0x6f, 0x9a, 0x94, 0x9b, 0x03,
703 		    0x98, 0x00, 0x99, 0x00, 0x9a, 0x00);
704     }
705   else
706     {
707       if (dpi == 1200)
708 	write_regs (udev, 16, 0x9b, 0x00, 0x98, 0xb9, 0x99, 0x7a, 0x9a, 0xd6,
709 		    0x9b, 0x01, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b,
710 		    0x02, 0x98, 0xbc, 0x99, 0x7c, 0x9a, 0xd3, 0x9b, 0x03,
711 		    0x98, 0x00, 0x99, 0x00, 0x9a, 0x00);
712       else if (dpi == 150)
713 	write_regs (udev, 16, 0x9b, 0x00, 0x98, 0x9c, 0x99, 0x5f, 0x9a, 0x87,
714 		    0x9b, 0x01, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b,
715 		    0x02, 0x98, 0x97, 0x99, 0x58, 0x9a, 0x81, 0x9b, 0x03,
716 		    0x98, 0x00, 0x99, 0x00, 0x9a, 0x00);
717       else
718 	write_regs (udev, 16, 0x9b, 0x00, 0x98, 0x9d, 0x99, 0x79, 0x9a, 0x8e,
719 		    0x9b, 0x01, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b,
720 		    0x02, 0x98, 0x89, 0x99, 0x71, 0x9a, 0x80, 0x9b, 0x03,
721 		    0x98, 0x00, 0x99, 0x00, 0x9a, 0x00);
722     }
723   write_regs (udev, 4, 0x83, 0xa2, 0x85, 0x98, 0x83, 0x82, 0x85, 0x3a);
724   write_regs (udev, 1, 0x9d, 0x80);
725   write_regs (udev, 1, 0x9d, 0x00);
726   if (!bpp16)
727     {
728       if (dpi == 1200)
729 	write_regs (udev, 1, 0x94, 0x51);
730       else
731 	write_regs (udev, 1, 0x94, 0x41);
732     }
733   else
734     {
735       if (dpi == 1200)
736 	write_regs (udev, 1, 0x94, 0x71);
737       else
738 	write_regs (udev, 1, 0x94, 0x61);
739     }
740   lightmap = (unsigned short *) malloc (whitemapsize);
741   calc_lightmap (whitescan, lightmap, 0, dpi, gain, offset);
742   select_pixels (lightmap, dpi, leftpix, scanpix);
743   if (dpi == 1200)
744     write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x80, 0xb2, 0x06, 0xb3, 0xff, 0xb4,
745 		0xff, 0xb5, 0x06);
746   else
747     write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x40, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
748 		0x7f, 0xb5, 0x07);
749   write_vctl (udev, 0x0c, 0x0002, whitemapsize, 0x00);
750   usb_bulk_write (udev, 2, (unsigned char *) lightmap, whitemapsize,
751                   wr_timeout);
752 
753   calc_lightmap (whitescan, lightmap, 1, dpi, gain, offset);
754   if (dpi == 1200)
755     write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
756 		0x7f, 0xb5, 0x07);
757   else
758     write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x80, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
759 		0xbf, 0xb5, 0x07);
760   write_vctl (udev, 0x0c, 0x0002, whitemapsize, 0x00);
761   fix_endian_short (&GRAYMASK, 1);
762   if (gray)
763     for (i = 0; i < whitemapsize / 2; i++)
764       lightmap[i] |= GRAYMASK;
765   usb_bulk_write (udev, 2, (unsigned char *) lightmap, whitemapsize,
766                   wr_timeout);
767 
768   calc_lightmap (whitescan, lightmap, 2, dpi, gain, offset);
769   if (dpi == 1200)
770     write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x80, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
771 		0xff, 0xb5, 0x07);
772   else
773     write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0xc0, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
774 		0xff, 0xb5, 0x07);
775   write_vctl (udev, 0x0c, 0x0002, whitemapsize, 0x00);
776   usb_bulk_write (udev, 2, (unsigned char *) lightmap, whitemapsize,
777                   wr_timeout);
778 
779   free (whitescan);
780   free (lightmap);
781 
782   if (!bpp16)
783     download_lut8 (udev, dpi, gray ? 0 : 1);
784 
785   write_regs (udev, 4, 0x83, 0xa2, 0x85, 0x01, 0x83, 0x82, 0x85, 0x00);
786   write_regs (udev, 1, 0x9d, 0x80);
787   write_regs (udev, 1, 0x9d, 0x00);
788 
789   if (!bpp16)
790     {
791       if (dpi == 1200)
792 	write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
793 		    0xb4, 0x1f, 0xb5, 0x06, 0xb6, 0x01, 0xb7, 0x00, 0xb8,
794 		    0x43, 0xb9, 0x2d);
795       else if (dpi == 150)
796 	write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
797 		    0xb4, 0x0f, 0xb5, 0x07, 0xb6, 0x01, 0xb7, 0x00, 0xb8,
798 		    0xe0, 0xb9, 0x37);
799       else
800 	write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
801 		    0xb4, 0x0f, 0xb5, 0x07, 0xb6, 0x01, 0xb7, 0x00, 0xb8,
802 		    0x90, 0xb9, 0x37);
803     }
804   else
805     {
806       if (dpi == 1200)
807 	write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
808 		    0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8,
809 		    0x87, 0xb9, 0x18);
810       else if (dpi == 150)
811 	write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
812 		    0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8,
813 		    0xc1, 0xb9, 0x1e);
814       else
815 	write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
816 		    0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8,
817 		    0x21, 0xb9, 0x1e);
818     }
819 
820   /* [86,89] controls number of 300dpi steps to scan */
821   botreg = scanlines * (1200 / dpi) + 400;
822   write_regs (udev, 6, 0xc0, 0x00, 0x84, 0x00, 0x84, 0xb4, 0x80, 0xe1, 0xcf,
823 	      0x04, 0x82, 0x00);
824 
825   if (!bpp16)
826     {
827       if (dpi == 300)
828 	write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x04, 0x83, 0x82, 0x85, 0x00,
829 		    0xbc, 0x20, 0xbd, 0x10, 0x88, 0xd0, 0xc1, 0x01, 0xc2,
830 		    0x00, 0xc3, 0x04, 0xc4, 0x20, 0xc5, 0x10, 0xc6, 0xc3,
831 		    0xc7, 0xd0, 0xc8, 0x12, 0xc0, 0xd1, 0x89, botreg & 255,
832 		    0x86, 255 & (botreg >> 8));
833       else if (dpi == 600)
834 	write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x04, 0x83, 0x82, 0x85, 0x00,
835 		    0xbc, 0x20, 0xbd, 0x10, 0x88, 0xd0, 0xc1, 0x01, 0xc2,
836 		    0x00, 0xc3, 0x04, 0xc4, 0x20, 0xc5, 0x10, 0xc6, 0xc3,
837 		    0xc7, 0xd0, 0xc8, 0x16, 0xc0, 0xd1, 0x89, botreg & 255,
838 		    0x86, 255 & (botreg >> 8));
839       else if (dpi == 1200)
840 	write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x02, 0x83, 0x82, 0x85, 0x00,
841 		    0xbc, 0x20, 0xbd, 0x08, 0x88, 0xa4, 0xc1, 0x02, 0xc2,
842 		    0x00, 0xc3, 0x02, 0xc4, 0x20, 0xc5, 0x08, 0xc6, 0x96,
843 		    0xc7, 0xa4, 0xc8, 0x06, 0xc0, 0xd2, 0x89, botreg & 255,
844 		    0x86, 255 & (botreg >> 8));
845       else if (dpi == 150)
846 	write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x06, 0x83, 0x82, 0x85, 0x00,
847 		    0xbc, 0x1c, 0xbd, 0x08, 0x88, 0xe0, 0xc1, 0x01, 0xc2,
848 		    0x00, 0xc3, 0x03, 0xc4, 0x1c, 0xc5, 0x08, 0xc6, 0xd7,
849 		    0xc7, 0xe0, 0xc8, 0x11, 0xc0, 0xd1, 0x89, botreg & 255,
850 		    0x86, 255 & (botreg >> 8));
851 
852       if (dpi == 300)
853 	write_regs (udev, 8, 0xbb, 0x01, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
854 		    0xbf, 0x00, 0x90, 0x20, 0x91, 0x00, 0x83, 0x82);
855       else if (dpi == 600)
856 	write_regs (udev, 8, 0xbb, 0x02, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
857 		    0xbf, 0x00, 0x90, 0x20, 0x91, 0x00, 0x83, 0x82);
858       else if (dpi == 1200)
859 	write_regs (udev, 8, 0xbb, 0x02, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
860 		    0xbf, 0x00, 0x90, 0x20, 0x91, 0x00, 0x83, 0x82);
861       else if (dpi == 150)
862 	write_regs (udev, 8, 0xbb, 0x00, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
863 		    0xbf, 0x00, 0x90, 0x20, 0x91, 0x00, 0x83, 0x82);
864     }
865   else
866     {
867       if (dpi == 300)
868 	write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x04, 0x83, 0x82, 0x85, 0x00,
869 		    0xbc, 0x20, 0xbd, 0x10, 0x88, 0xd0, 0xc1, 0x01, 0xc2,
870 		    0x00, 0xc3, 0x04, 0xc4, 0x20, 0xc5, 0x10, 0xc6, 0xc3,
871 		    0xc7, 0xd0, 0xc8, 0x13, 0xc0, 0xd1, 0x89, botreg & 255,
872 		    0x86, 255 & (botreg >> 8));
873       else if (dpi == 150)
874 	write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x06, 0x83, 0x82, 0x85, 0x00,
875 		    0xbc, 0x1c, 0xbd, 0x08, 0x88, 0xe0, 0xc1, 0x01, 0xc2,
876 		    0x00, 0xc3, 0x03, 0xc4, 0x1c, 0xc5, 0x08, 0xc6, 0xd7,
877 		    0xc7, 0xe0, 0xc8, 0x12, 0xc0, 0xd1, 0x89, botreg & 255,
878 		    0x86, 255 & (botreg >> 8));
879       else if (dpi == 1200)
880 	write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x02, 0x83, 0x82, 0x85, 0x00,
881 		    0xbc, 0x20, 0xbd, 0x08, 0x88, 0xa4, 0xc1, 0x02, 0xc2,
882 		    0x00, 0xc3, 0x02, 0xc4, 0x20, 0xc5, 0x08, 0xc6, 0x96,
883 		    0xc7, 0xa4, 0xc8, 0x0c, 0xc0, 0xd2, 0x89, botreg & 255,
884 		    0x86, 255 & (botreg >> 8));
885       else if (dpi == 600)
886 	write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x04, 0x83, 0x82, 0x85, 0x00,
887 		    0xbc, 0x20, 0xbd, 0x10, 0x88, 0xd0, 0xc1, 0x01, 0xc2,
888 		    0x00, 0xc3, 0x04, 0xc4, 0x20, 0xc5, 0x10, 0xc6, 0xc3,
889 		    0xc7, 0xd0, 0xc8, 0x1a, 0xc0, 0xd1, 0x89, botreg & 255,
890 		    0x86, 255 & (botreg >> 8));
891 
892       if (dpi == 300)
893 	write_regs (udev, 8, 0xbb, 0x02, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
894 		    0xbf, 0x00, 0x90, 0x70, 0x91, 0x00, 0x83, 0x82);
895       else if (dpi == 150)
896 	write_regs (udev, 8, 0xbb, 0x01, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
897 		    0xbf, 0x00, 0x90, 0x70, 0x91, 0x00, 0x83, 0x82);
898       else if (dpi == 1200)
899 	write_regs (udev, 8, 0xbb, 0x05, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
900 		    0xbf, 0x00, 0x90, 0x70, 0x91, 0x00, 0x83, 0x82);
901       else if (dpi == 600)
902 	write_regs (udev, 8, 0xbb, 0x04, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
903 		    0xbf, 0x00, 0x90, 0x70, 0x91, 0x00, 0x83, 0x82);
904 
905 
906     }
907 
908   if (gray)
909     write_regs (udev, 1, 0xbe, 0x05);
910   else
911     write_regs (udev, 1, 0xbe, 0x0d);
912   write_vctl (udev, 0x0c, 0x0003, 0x0001, 0x00);
913   usb_bulk_read (udev, 1, &rd_byte, 1, rd_timeout);
914   write_vctl (udev, 0x0c, 0x0001, 0x0000, 0x00);
915 
916 #ifndef BACKENDNAME
917   sprintf (fname, "%d.%s", dpi, gray ? "pgm" : "ppm");
918   if (stname)
919     strcpy (fname, stname);
920   sprintf (head, "P%d\n%d %d\n%d\n", gray ? 5 : 6, scanpix, scanlines,
921 	   bpp16 ? 65535 : 255);
922   if (nohead)
923     head[0] = 0;
924   if (!raw)
925     record_image (udev, fname, dpi, scanpix, scanlines, gray, head, bpp16);
926   else
927     record_head (udev, fname,
928 		 scanpix * (gray ? 1 : 3) * (bpp16 ? 2 : 1) * scanlines, "");
929 
930   reset_scanner (udev);
931   idle_ab (udev);
932   set_lamp_timer (udev, 5);
933 #endif
934 }
935