• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  * SANE - Scanner Access Now Easy.
3 
4    microtek.c
5 
6    This file Copyright 2002 Matthew Marjanovic
7 
8    This file is part of the SANE package.
9 
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2 of the
13    License, or (at your option) any later version.
14 
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <https://www.gnu.org/licenses/>.
22 
23    As a special exception, the authors of SANE give permission for
24    additional uses of the libraries contained in this release of SANE.
25 
26    The exception is that, if you link a SANE library with other files
27    to produce an executable, this does not by itself cause the
28    resulting executable to be covered by the GNU General Public
29    License.  Your use of that executable is in no way restricted on
30    account of linking the SANE library code into it.
31 
32    This exception does not, however, invalidate any other reasons why
33    the executable file might be covered by the GNU General Public
34    License.
35 
36    If you submit changes to SANE to the maintainers to be included in
37    a subsequent release, you agree by submitting the changes that
38    those changes may be distributed with this exception intact.
39 
40    If you write modifications of your own for SANE, it is your choice
41    whether to permit this exception to apply to your modifications.
42    If you do not wish that, delete this exception notice.
43 
44  ***************************************************************************
45 
46    This file implements a SANE backend for Microtek scanners.
47 
48    (feedback to:  mtek-bugs@mir.com)
49    (for latest info:  http://www.mir.com/mtek/)
50 
51  ***************************************************************************/
52 
53 
54 #define MICROTEK_MAJOR 0
55 #define MICROTEK_MINOR 13
56 #define MICROTEK_PATCH 1
57 
58 #include "../include/sane/config.h"
59 
60 #include <stdarg.h>
61 #include <stdlib.h>
62 #include <string.h>
63 #include <unistd.h>
64 #include <fcntl.h>
65 #include <math.h>
66 
67 #include "../include/_stdint.h"
68 
69 #include "../include/sane/sane.h"
70 #include "../include/sane/sanei.h"
71 #include "../include/sane/sanei_config.h"
72 #include "../include/sane/sanei_scsi.h"
73 #include "../include/sane/saneopts.h"
74 
75 #define BACKEND_NAME microtek
76 #include "../include/sane/sanei_backend.h"
77 
78 #include "microtek.h"
79 
80 
81 #define MICROTEK_CONFIG_FILE "microtek.conf"
82 
83 #ifndef PATH_MAX
84 # define PATH_MAX	1024
85 #endif
86 
87 
88 #define SCSI_BUFF_SIZE sanei_scsi_max_request_size
89 
90 
91 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
92 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
93 
94 static int num_devices = 0;
95 static Microtek_Device *first_dev = NULL;     /* list of known devices */
96 static Microtek_Scanner *first_handle = NULL; /* list of open scanners */
97 static const SANE_Device **devlist = NULL;    /* sane_get_devices() */
98 
99 
100 static SANE_Bool inhibit_clever_precal = SANE_FALSE;
101 static SANE_Bool inhibit_real_calib = SANE_FALSE;
102 
103 
104 #define M_GSS_WAIT 5 /* seconds */
105 
106 #define M_LINEART  SANE_VALUE_SCAN_MODE_LINEART
107 #define M_HALFTONE SANE_VALUE_SCAN_MODE_HALFTONE
108 #define M_GRAY     SANE_VALUE_SCAN_MODE_GRAY
109 #define M_COLOR    SANE_VALUE_SCAN_MODE_COLOR
110 
111 #define M_OPAQUE   "Opaque/Normal"
112 #define M_TRANS    "Transparency"
113 #define M_AUTOFEED "AutoFeeder"
114 
115 #define M_NONE   "None"
116 #define M_SCALAR "Scalar"
117 #define M_TABLE  "Table"
118 
119 static SANE_String_Const gamma_mode_list[4] = {
120   M_NONE,
121   M_SCALAR,
122   M_TABLE,
123   NULL
124 };
125 
126 
127 /* These are for the E6.  Does this hold for other models? */
128 static SANE_String_Const halftone_mode_list[13] = {
129   " 1 53-dot screen (53 gray levels)",
130   " 2 Horiz. screen (65 gray levels)",
131   " 3 Vert. screen (65 gray levels)",
132   " 4 Mixed page (33 gray levels)",
133   " 5 71-dot screen (29 gray levels)",
134   " 6 60-dot #1 (26 gray levels)",
135   " 7 60-dot #2 (26 gray levels)",
136   " 8 Fine detail #1 (17 gray levels)",
137   " 9 Fine detail #2 (17 gray levels)",
138   "10 Slant line (17 gray levels)",
139   "11 Posterizing (10 gray levels)",
140   "12 High Contrast (5 gray levels)",
141   NULL
142 };
143 
144 
145 
146 static SANE_Range speed_range = {1, 7, 1};
147 
148 static SANE_Range brightness_range = {-100, 100, 1};
149 /*static SANE_Range brightness_range = {0, 255, 1};*/
150 /*static SANE_Range exposure_range = {-18, 21, 3};*/
151 /*static SANE_Range contrast_range = {-42, 49, 7};*/
152 static SANE_Range u8_range = {0, 255, 1};
153 static SANE_Range analog_gamma_range =
154 { SANE_FIX(0.1), SANE_FIX(4.0), SANE_FIX(0) };
155 
156 
157 
158 
159 #define MAX_MDBG_LENGTH 1024
160 static char _mdebug_string[MAX_MDBG_LENGTH];
161 
MDBG_INIT(const char * format,...)162 static void MDBG_INIT(const char *format, ...)
163 {
164   va_list ap;
165   va_start(ap, format);
166   vsnprintf(_mdebug_string, MAX_MDBG_LENGTH, format, ap);
167   va_end(ap);
168 }
169 
MDBG_ADD(const char * format,...)170 static void MDBG_ADD(const char *format, ...)
171 {
172   int len = strlen(_mdebug_string);
173   va_list ap;
174   va_start(ap, format);
175   vsnprintf(_mdebug_string+len, MAX_MDBG_LENGTH-len, format, ap);
176   va_end(ap);
177 }
178 
MDBG_FINISH(int dbglvl)179 static void MDBG_FINISH(int dbglvl)
180 {
181   DBG(dbglvl, "%s\n", _mdebug_string);
182 }
183 
184 
185 
186 /********************************************************************/
187 /********************************************************************/
188 /*** Utility Functions **********************************************/
189 /********************************************************************/
190 /********************************************************************/
191 
max_string_size(const SANE_String_Const strings[])192 static size_t max_string_size (const SANE_String_Const strings[])
193 {
194   size_t size, max_size = 0;
195   int i;
196 
197   for (i = 0; strings[i]; ++i) {
198     size = strlen(strings[i]) + 1;
199     if (size > max_size) max_size = size;
200   }
201   return max_size;
202 }
203 
204 
205 
206 /********************************************************************/
207 /* Allocate/create a new ring buffer                                */
208 /********************************************************************/
209 static ring_buffer *
ring_alloc(size_t initial_size,size_t bpl,size_t ppl)210 ring_alloc (size_t initial_size, size_t bpl, size_t ppl)
211 {
212   ring_buffer *rb;
213   uint8_t *buff;
214 
215   if ((rb = (ring_buffer *)malloc(sizeof(*rb))) == NULL)
216     return NULL;
217   if ((buff = (uint8_t *)malloc(initial_size * sizeof(*buff))) == NULL) {
218     free(rb);
219     return NULL;
220   }
221   rb->base = buff;
222   rb->size = initial_size;
223   rb->initial_size = initial_size;
224 
225   rb->bpl = bpl;
226   rb->ppl = ppl;
227 
228   rb->tail_red   = 0;
229   rb->tail_green = 1;
230   rb->tail_blue  = 2;
231   rb->head_complete = 0;
232 
233   rb->red_extra   = 0;
234   rb->green_extra = 0;
235   rb->blue_extra  = 0;
236   rb->complete_count = 0;
237 
238   return rb;
239 }
240 
241 
242 /********************************************************************/
243 /* Enlarge an existing ring buffer                                  */
244 /********************************************************************/
245 static SANE_Status
ring_expand(ring_buffer * rb,size_t amount)246 ring_expand (ring_buffer *rb, size_t amount)
247 {
248   uint8_t *buff;
249   size_t oldsize;
250 
251   if (rb == NULL) return SANE_STATUS_INVAL;
252   buff = (uint8_t *)realloc(rb->base, (rb->size + amount) * sizeof(*buff));
253   if (buff == NULL) return SANE_STATUS_NO_MEM;
254 
255   rb->base = buff;
256   oldsize = rb->size;
257   rb->size += amount;
258 
259   DBG(23, "ring_expand:  old, new, inc size:  %lu, %lu, %lu\n",
260       (u_long)oldsize, (u_long)rb->size, (u_long)amount);
261   DBG(23, "ring_expand:  old  tr: %lu  tg: %lu  tb: %lu  hc: %lu\n",
262       (u_long)rb->tail_red, (u_long)rb->tail_green,
263       (u_long)rb->tail_blue, (u_long)rb->head_complete);
264   /* if necessary, move data and fix up them pointers */
265   /* (will break subtly if ring is filled with G or B bytes,
266      and tail_g or tail_b have rolled over...) */
267   if (((rb->complete_count) ||
268        (rb->red_extra) ||
269        (rb->green_extra) ||
270        (rb->blue_extra)) && ((rb->tail_red <= rb->head_complete) ||
271 			     (rb->tail_green <= rb->head_complete) ||
272 			     (rb->tail_blue <= rb->head_complete))) {
273     memmove(rb->base + rb->head_complete + amount,
274 	    rb->base + rb->head_complete,
275 	    oldsize - rb->head_complete);
276     if ((rb->tail_red > rb->head_complete) ||
277 	((rb->tail_red == rb->head_complete) &&
278 	 !(rb->complete_count) && !(rb->red_extra)))
279       rb->tail_red += amount;
280     if ((rb->tail_green > rb->head_complete) ||
281 	((rb->tail_green == rb->head_complete) &&
282 	 !(rb->complete_count) && !(rb->green_extra)))
283       rb->tail_green += amount;
284     if ((rb->tail_blue > rb->head_complete) ||
285 	((rb->tail_blue == rb->head_complete) &&
286 	 !(rb->complete_count) && !(rb->blue_extra)))
287       rb->tail_blue += amount;
288     rb->head_complete += amount;
289   }
290   DBG(23, "ring_expand:  new  tr: %lu  tg: %lu  tb: %lu  hc: %lu\n",
291       (u_long)rb->tail_red, (u_long)rb->tail_green,
292       (u_long)rb->tail_blue, (u_long)rb->head_complete);
293   return SANE_STATUS_GOOD;
294 }
295 
296 
297 /********************************************************************/
298 /* Deallocate a ring buffer                                         */
299 /********************************************************************/
300 static void
ring_free(ring_buffer * rb)301 ring_free (ring_buffer *rb)
302 {
303   free(rb->base);
304   free(rb);
305 }
306 
307 
308 
309 /********************************************************************/
310 /********************************************************************/
311 /*** Basic SCSI Commands ********************************************/
312 /********************************************************************/
313 /********************************************************************/
314 
315 
316 /********************************************************************/
317 /* parse sense from scsi error                                      */
318 /*  (even though microtek sense codes are non-standard and          */
319 /*   typically misinterpreted/munged by the low-level scsi driver)  */
320 /********************************************************************/
321 static SANE_Status
sense_handler(int scsi_fd,u_char * sense,void * arg)322 sense_handler (int scsi_fd, u_char *sense, void *arg)
323 {
324   int *sense_flags = (int *)arg;
325   SANE_Status stat;
326 
327   DBG(10, "SENSE!  fd = %d\n", scsi_fd);
328   DBG(10, "sense = %02x %02x %02x %02x.\n",
329             sense[0], sense[1], sense[2], sense[3]);
330   switch(sense[0]) {
331   case 0x00:
332     return SANE_STATUS_GOOD;
333   case 0x81:           /* COMMAND/DATA ERROR */
334     stat = SANE_STATUS_GOOD;
335     if (sense[1] & 0x01) {
336       if ((sense_flags != NULL) && (*sense_flags & MS_SENSE_IGNORE))
337 	DBG(10, "sense:  ERR_SCSICMD -- ignored\n");
338       else {
339 	DBG(10, "sense:  ERR_SCSICMD\n");
340 	stat = SANE_STATUS_IO_ERROR;
341       }
342     }
343     if (sense[1] & 0x02) {
344       DBG(10, "sense:  ERR_TOOMANY\n");
345       stat = SANE_STATUS_IO_ERROR;
346     }
347     return stat;
348   case 0x82 :           /* SCANNER HARDWARE ERROR */
349     if (sense[1] & 0x01) DBG(10, "sense:  ERR_CPURAMFAIL\n");
350     if (sense[1] & 0x02) DBG(10, "sense:  ERR_SYSRAMFAIL\n");
351     if (sense[1] & 0x04) DBG(10, "sense:  ERR_IMGRAMFAIL\n");
352     if (sense[1] & 0x10) DBG(10, "sense:  ERR_CALIBRATE\n");
353     if (sense[1] & 0x20) DBG(10, "sense:  ERR_LAMPFAIL\n");
354     if (sense[1] & 0x40) DBG(10, "sense:  ERR_MOTORFAIL\n");
355     if (sense[1] & 0x80) DBG(10, "sense:  ERR_FEEDERFAIL\n");
356     if (sense[2] & 0x01) DBG(10, "sense:  ERR_POWERFAIL\n");
357     if (sense[2] & 0x02) DBG(10, "sense:  ERR_ILAMPFAIL\n");
358     if (sense[2] & 0x04) DBG(10, "sense:  ERR_IMOTORFAIL\n");
359     if (sense[2] & 0x08) DBG(10, "sense:  ERR_PAPERFAIL\n");
360     if (sense[2] & 0x10) DBG(10, "sense:  ERR_FILTERFAIL\n");
361     return SANE_STATUS_IO_ERROR;
362   case 0x83 :           /* OPERATION ERROR */
363     if (sense[1] & 0x01) DBG(10, "sense:  ERR_ILLGRAIN\n");
364     if (sense[1] & 0x02) DBG(10, "sense:  ERR_ILLRES\n");
365     if (sense[1] & 0x04) DBG(10, "sense:  ERR_ILLCOORD\n");
366     if (sense[1] & 0x10) DBG(10, "sense:  ERR_ILLCNTR\n");
367     if (sense[1] & 0x20) DBG(10, "sense:  ERR_ILLLENGTH\n");
368     if (sense[1] & 0x40) DBG(10, "sense:  ERR_ILLADJUST\n");
369     if (sense[1] & 0x80) DBG(10, "sense:  ERR_ILLEXPOSE\n");
370     if (sense[2] & 0x01) DBG(10, "sense:  ERR_ILLFILTER\n");
371     if (sense[2] & 0x02) DBG(10, "sense:  ERR_NOPAPER\n");
372     if (sense[2] & 0x04) DBG(10, "sense:  ERR_ILLTABLE\n");
373     if (sense[2] & 0x08) DBG(10, "sense:  ERR_ILLOFFSET\n");
374     if (sense[2] & 0x10) DBG(10, "sense:  ERR_ILLBPP\n");
375     return SANE_STATUS_IO_ERROR;
376   default :
377     DBG(10, "sense: unknown error\n");
378     return SANE_STATUS_IO_ERROR;
379   }
380   return SANE_STATUS_GOOD;
381 }
382 
383 
384 
385 /********************************************************************/
386 /* wait (via polling) until scanner seems "ready"                   */
387 /********************************************************************/
388 static SANE_Status
wait_ready(Microtek_Scanner * ms)389 wait_ready(Microtek_Scanner *ms)
390 {
391   uint8_t comm[6] = { 0, 0, 0, 0, 0, 0 };
392   SANE_Status status;
393   int retry = 0;
394 
395   DBG(23, ".wait_ready %d...\n", ms->sfd);
396   while ((status = sanei_scsi_cmd(ms->sfd, comm, 6, 0, 0))
397 	 != SANE_STATUS_GOOD) {
398     DBG(23, "wait_ready failed (%d)\n", retry);
399     if (retry > 5) return SANE_STATUS_IO_ERROR; /* XXXXXXXX */
400     retry++;
401     sleep(3);
402   }
403   return SANE_STATUS_GOOD;
404 }
405 
406 
407 /********************************************************************/
408 /* send scan region coordinates                                     */
409 /********************************************************************/
410 static SANE_Status
scanning_frame(Microtek_Scanner * ms)411 scanning_frame(Microtek_Scanner *ms)
412 {
413   uint8_t *data, comm[15] = { 0x04, 0, 0, 0, 0x09, 0 };
414   int x1, y1, x2, y2;
415 
416   DBG(23, ".scanning_frame...\n");
417 
418   x1 = ms->x1;
419   x2 = ms->x2;
420   y1 = ms->y1;
421   y2 = ms->y2;
422   /* E6 weirdness (other models too?) */
423   if (ms->unit_type == MS_UNIT_18INCH) {
424     x1 /= 2;
425     x2 /= 2;
426     y1 /= 2;
427     y2 /= 2;
428   }
429 
430   DBG(23, ".scanning_frame:  in- %d,%d  %d,%d\n",
431       ms->x1, ms->y1, ms->x2, ms->y2);
432   DBG(23, ".scanning_frame: out- %d,%d  %d,%d\n", x1, y1, x2, y2);
433   data = comm + 6;
434   data[0] =
435     ((ms->unit_type == MS_UNIT_PIXELS) ? 0x08 : 0 ) |
436     ((ms->mode == MS_MODE_HALFTONE) ? 0x01 : 0 );
437   data[1] = x1 & 0xFF;
438   data[2] = (x1 >> 8) & 0xFF;
439   data[3] = y1 & 0xFF;
440   data[4] = (y1 >> 8) & 0xFF;
441   data[5] = x2 & 0xFF;
442   data[6] = (x2 >> 8) & 0xFF;
443   data[7] = y2 & 0xFF;
444   data[8] = (y2 >> 8) & 0xFF;
445   if (DBG_LEVEL >= 192) {
446     int i;
447 #if 0
448     fprintf(stderr, "SF: ");
449     for (i=0;i<6+0x09;i++) fprintf(stderr, "%2x ", comm[i]);
450     fprintf(stderr, "\n");
451 #endif
452     MDBG_INIT("SF: ");
453     for (i=0;i<6+0x09;i++) MDBG_ADD("%2x ", comm[i]);
454     MDBG_FINISH(192);
455   }
456   return sanei_scsi_cmd(ms->sfd, comm, 6 + 0x09, 0, 0);
457 }
458 
459 
460 
461 /********************************************************************/
462 /* send "mode_select"                                               */
463 /********************************************************************/
464 static SANE_Status
mode_select(Microtek_Scanner * ms)465 mode_select(Microtek_Scanner *ms)
466 {
467   uint8_t *data, comm[19] = { 0x15, 0, 0, 0, 0, 0 };
468 
469   DBG(23, ".mode_select %d...\n", ms->sfd);
470   data = comm + 6;
471   data[0] =
472     0x81 |
473     ((ms->unit_type == MS_UNIT_18INCH) ? 0 : 0x08) |
474     ((ms->res_type == MS_RES_5PER) ? 0 : 0x02);
475   data[1] = ms->resolution_code;
476   data[2] = ms->exposure;
477   data[3] = ms->contrast;
478   data[4] = ms->pattern;
479   data[5] = ms->velocity;
480   data[6] = ms->shadow;
481   data[7] = ms->highlight;
482   DBG(23, ".mode_select:  pap_len: %d\n", ms->paper_length);
483   data[8] = ms->paper_length & 0xFF;
484   data[9] = (ms->paper_length >> 8) & 0xFF;
485   data[10] = ms->midtone;
486   /* set command/data length */
487   comm[4] = (ms->midtone_support) ? 0x0B : 0x0A;
488 
489   if (DBG_LEVEL >= 192) {
490     int i;
491 #if 0
492     fprintf(stderr, "MSL: ");
493     for (i=0;i<6+comm[4];i++) fprintf(stderr, "%2x ", comm[i]);
494     fprintf(stderr, "\n");
495 #endif
496     MDBG_INIT("MSL: ");
497     for (i=0;i<6+comm[4];i++) MDBG_ADD("%2x ", comm[i]);
498     MDBG_FINISH(192);
499   }
500   return sanei_scsi_cmd(ms->sfd, comm, 6 + comm[4], 0, 0);
501 }
502 
503 
504 
505 /********************************************************************/
506 /* send "mode_select_1"                                             */
507 /********************************************************************/
508 static SANE_Status
mode_select_1(Microtek_Scanner * ms)509 mode_select_1(Microtek_Scanner *ms)
510 {
511   uint8_t *data, comm[16] = { 0x16, 0, 0, 0, 0x0A, 0,
512                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
513 
514   DBG(23, ".mode_select_1 %d...\n", ms->sfd);
515   data = comm + 6;
516   data[1] = ms->bright_r;
517   data[3] = ((ms->allow_calibrate) ? 0 : 0x02); /* | 0x01; */
518 
519   if (DBG_LEVEL >= 192) {
520     int i;
521 #if 0
522     fprintf(stderr, "MSL1: ");
523     for (i=0;i<6+0x0A;i++) fprintf(stderr, "%2x ", comm[i]);
524     fprintf(stderr, "\n");
525 #endif
526     MDBG_INIT("MSL1: ");
527     for (i=0;i<6+0x0A;i++) MDBG_ADD("%2x ", comm[i]);
528     MDBG_FINISH(192);
529   }
530   return sanei_scsi_cmd(ms->sfd, comm, 6 + 0x0A, 0, 0);
531 }
532 
533 
534 
535 /********************************************************************/
536 /* record mode_sense results in the mode_sense buffer               */
537 /*  (this is to tell if something catastrophic has happened         */
538 /*   to the scanner in-between scans)                               */
539 /********************************************************************/
540 static SANE_Status
save_mode_sense(Microtek_Scanner * ms)541 save_mode_sense(Microtek_Scanner *ms)
542 {
543   uint8_t data[20], comm[6] = { 0x1A, 0, 0, 0, 0, 0};
544   size_t lenp;
545   SANE_Status status;
546   int i;
547 
548   DBG(23, ".save_mode_sense %d...\n", ms->sfd);
549   if (ms->onepass) comm[4] = 0x13;
550   else if (ms->midtone_support) comm[4] = 0x0B;
551   else comm[4] = 0x0A;
552   lenp = comm[4];
553 
554   status = sanei_scsi_cmd(ms->sfd, comm, 6, data, &lenp);
555   for (i=0; i<10; i++) ms->mode_sense_cache[i] = data[i];
556 
557   if (DBG_LEVEL >= 192) {
558     unsigned int i;
559 #if 0
560     fprintf(stderr, "SMS: ");
561     for (i=0;i<lenp;i++) fprintf(stderr, "%2x ", data[i]);
562     fprintf(stderr, "\n");
563 #endif
564     MDBG_INIT("SMS: ");
565     for (i=0;i<lenp;i++) MDBG_ADD("%2x ", data[i]);
566     MDBG_FINISH(192);
567   }
568 
569   return status;
570 }
571 
572 
573 /********************************************************************/
574 /* read mode_sense and compare to what we saved before              */
575 /********************************************************************/
576 static SANE_Status
compare_mode_sense(Microtek_Scanner * ms,int * match)577 compare_mode_sense(Microtek_Scanner *ms, int *match)
578 {
579   uint8_t data[20], comm[6] = { 0x1A, 0, 0, 0, 0, 0};
580   size_t lenp;
581   SANE_Status status;
582   int i;
583 
584   DBG(23, ".compare_mode_sense %d...\n", ms->sfd);
585   if (ms->onepass) comm[4] = 0x13;
586   else if (ms->midtone_support) comm[4] = 0x0B;
587   else comm[4] = 0x0A;
588   lenp = comm[4];
589 
590   status = sanei_scsi_cmd(ms->sfd, comm, 6, data, &lenp);
591   *match = 1;
592   for (i=0; i<10; i++)
593     *match = *match && (ms->mode_sense_cache[i] == data[i]);
594 
595   if (DBG_LEVEL >= 192) {
596     unsigned int i;
597 #if 0
598     fprintf(stderr, "CMS: ");
599     for (i=0;i<lenp;i++) fprintf(stderr, "%2x(%2x) ",
600 				 data[i],
601 				 ms->mode_sense_cache[i]);
602     fprintf(stderr, "\n");
603 #endif
604     MDBG_INIT("CMS: ");
605     for (i=0;i<lenp;i++) MDBG_ADD("%2x(%2x) ",
606 				  data[i],
607 				  ms->mode_sense_cache[i]);
608     MDBG_FINISH(192);
609   }
610 
611   return status;
612 }
613 
614 /********************************************************************/
615 /* send mode_sense_1, and upset every scsi driver known to mankind  */
616 /********************************************************************/
617 #if 0
618 static SANE_Status
619 mode_sense_1(Microtek_Scanner *ms)
620 {
621   uint8_t *data, comm[36] = { 0x19, 0, 0, 0, 0x1E, 0 };
622 
623   DBG(23, ".mode_sense_1...\n");
624   data = comm + 6;
625   memset(data, 0, 30);
626   data[1] = ms->bright_r;
627   data[2] = ms->bright_g;
628   data[3] = ms->bright_b;
629   if (DBG_LEVEL >= 192) {
630     int i;
631     fprintf(stderr, "MS1: ");
632     for (i=0;i<6+0x1E;i++) fprintf(stderr, "%2x ", comm[i]);
633     fprintf(stderr, "\n");
634   }
635   return sanei_scsi_cmd(ms->sfd, comm, 6 + 0x1E, 0, 0);
636 }
637 #endif
638 
639 
640 
641 /********************************************************************/
642 /* send "accessory" command                                         */
643 /********************************************************************/
644 static SANE_Status
accessory(Microtek_Scanner * ms)645 accessory(Microtek_Scanner *ms)
646 {
647   uint8_t comm[6] = { 0x10, 0, 0, 0, 0, 0 };
648 
649   DBG(23, ".accessory...\n");
650   comm[4] =
651     ((ms->useADF) ? 0x41 : 0x40) |
652     ((ms->prescan) ? 0x18 : 0x10) |
653     ((ms->transparency) ? 0x24 : 0x20) |
654     ((ms->allowbacktrack) ? 0x82 : 0x80);
655 
656   if (DBG_LEVEL >= 192) {
657     int i;
658 #if 0
659     fprintf(stderr, "AC: ");
660     for (i=0;i<6;i++) fprintf(stderr, "%2x ", comm[i]);
661     fprintf(stderr, "\n");
662 #endif
663     MDBG_INIT("AC: ");
664     for (i=0;i<6;i++) MDBG_ADD("%2x ", comm[i]);
665     MDBG_FINISH(192);
666   }
667   return sanei_scsi_cmd(ms->sfd, comm, 6, 0, 0);
668 }
669 
670 
671 
672 /********************************************************************/
673 /* start the scanner a-scannin'                                     */
674 /********************************************************************/
675 static SANE_Status
start_scan(Microtek_Scanner * ms)676 start_scan(Microtek_Scanner *ms)
677 {
678   uint8_t comm[6] = { 0x1B, 0, 0, 0, 0, 0 };
679 
680   DBG(23, ".start_scan...\n");
681   comm[4] =
682     0x01 |  /* "start" */
683     ((ms->expandedresolution) ? 0x80 : 0) |
684     ((ms->multibit) ? 0x40 : 0) |
685     ((ms->onepasscolor) ? 0x20 : 0) |
686     ((ms->reversecolors) ? 0x04 : 0) |
687     ((ms->fastprescan) ? 0x02 : 0) |
688     ((ms->filter == MS_FILT_RED) ? 0x08 : 0) |
689     ((ms->filter == MS_FILT_GREEN) ? 0x10 : 0) |
690     ((ms->filter == MS_FILT_BLUE) ? 0x18 : 0) ;
691 
692   if (DBG_LEVEL >= 192) {
693     int i;
694 #if 0
695     fprintf(stderr, "SS: ");
696     for (i=0;i<6;i++) fprintf(stderr, "%2x ", comm[i]);
697     fprintf(stderr, "\n");
698 #endif
699     MDBG_INIT("SS: ");
700     for (i=0;i<6;i++) MDBG_ADD("%2x ", comm[i]);
701     MDBG_FINISH(192);
702   }
703   return sanei_scsi_cmd(ms->sfd, comm, 6, 0, 0);
704 }
705 
706 
707 
708 /********************************************************************/
709 /* stop the scanner a-scannin'                                      */
710 /********************************************************************/
711 static SANE_Status
stop_scan(Microtek_Scanner * ms)712 stop_scan(Microtek_Scanner *ms)
713 {
714   uint8_t comm[6] = { 0x1B, 0, 0, 0, 0, 0 };
715 
716   DBG(23, ".stop_scan...\n");
717   if (DBG_LEVEL >= 192) {
718     int i;
719 #if 0
720     fprintf(stderr, "SPS:");
721     for (i=0;i<6;i++) fprintf(stderr, "%2x ", comm[i]);
722     fprintf(stderr, "\n");
723 #endif
724     MDBG_INIT("SPS:");
725     for (i=0;i<6;i++) MDBG_ADD("%2x ", comm[i]);
726     MDBG_FINISH(192);
727   }
728   return sanei_scsi_cmd(ms->sfd, comm, 6, 0, 0);
729 }
730 
731 
732 
733 /********************************************************************/
734 /* get scan status                                                  */
735 /********************************************************************/
736 static SANE_Status
get_scan_status(Microtek_Scanner * ms,SANE_Int * busy,SANE_Int * bytes_per_line,SANE_Int * lines)737 get_scan_status(Microtek_Scanner *ms,
738 		SANE_Int *busy,
739 		SANE_Int *bytes_per_line,
740 		SANE_Int *lines)
741 {
742   uint8_t data[6], comm[6] = { 0x0F, 0, 0, 0, 0x06, 0 };
743   SANE_Status status;
744   size_t lenp;
745   int retry = 0;
746 
747   DBG(23, ".get_scan_status %d...\n", ms->sfd);
748 
749   do {
750     lenp = 6;
751     /* do some retry stuff in here, too */
752     status = sanei_scsi_cmd(ms->sfd, comm, 6, data, &lenp);
753     if (status != SANE_STATUS_GOOD) {
754       DBG(20, "get_scan_status:  scsi error\n");
755       return status;
756     }
757     *busy = data[0];
758     *bytes_per_line = (data[1]) + (data[2] << 8);
759     *lines = (data[3]) + (data[4] << 8) + (data[5] << 16);
760 
761     DBG(20, "get_scan_status(%lu): %d, %d, %d  -> #%d\n",
762 	(u_long) lenp, *busy, *bytes_per_line, *lines, retry);
763     DBG(20, "> %2x %2x %2x %2x %2x %2x\n",
764 	    data[0], data[1], data[2], data[3], data[4], data[5]);
765     if (*busy != 0) {
766       retry++;
767       DBG(23, "get_scan_status:  busy, retry in %d...\n",
768 	  M_GSS_WAIT * retry);
769       sleep(M_GSS_WAIT * retry);
770     }
771   } while ((*busy != 0) && (retry < 4));
772 
773   if (*busy == 0) return status;
774   else return SANE_STATUS_IO_ERROR;
775 }
776 
777 
778 
779 /********************************************************************/
780 /* get scanlines from scanner                                       */
781 /********************************************************************/
782 static SANE_Status
read_scan_data(Microtek_Scanner * ms,int lines,uint8_t * buffer,size_t * bufsize)783 read_scan_data(Microtek_Scanner *ms,
784 	       int lines,
785 	       uint8_t *buffer,
786 	       size_t *bufsize)
787 {
788   uint8_t comm[6] = { 0x08, 0, 0, 0, 0, 0 };
789 
790   DBG(23, ".read_scan_data...\n");
791   comm[2] = (lines >> 16) & 0xFF;
792   comm[3] = (lines >> 8) & 0xFF;
793   comm[4] = (lines) & 0xFF;
794 
795   return sanei_scsi_cmd(ms->sfd, comm, 6, buffer, bufsize);
796 }
797 
798 
799 
800 /********************************************************************/
801 /* download color LUT to scanner (if it takes one)                  */
802 /********************************************************************/
803 static SANE_Status
download_gamma(Microtek_Scanner * ms)804 download_gamma(Microtek_Scanner *ms)
805 {
806   uint8_t *data, *comm; /* commbytes[10] = { 0x55, 0, 0x27, 0, 0,
807 						0, 0,    0, 0, 0 };*/
808   int i, pl;
809   int commsize;
810   int bit_depth = 8; /* hard-code for now, should match bpp XXXXXXX */
811   int max_entry;
812   SANE_Status status;
813 
814   DBG(23, ".download_gamma...\n");
815   /* skip if scanner doesn't take 'em */
816   if (!(ms->gamma_entries)) {
817     DBG(23, ".download_gamma:  no entries; skipping\n");
818     return SANE_STATUS_GOOD;
819   }
820   if ((ms->gamma_entry_size != 1) && (ms->gamma_entry_size != 2)) {
821     DBG(23, ".download_gamma:  entry size %d?!?!?\n", ms->gamma_entry_size);
822     return SANE_STATUS_INVAL; /* XXXXXXXxx */
823   }
824 
825   max_entry = (1 << bit_depth) - 1;
826 
827   DBG(23, ".download_gamma:  %d entries of %d bytes, max %d\n",
828       ms->gamma_entries, ms->gamma_entry_size, max_entry);
829   commsize = 10 + (ms->gamma_entries * ms->gamma_entry_size);
830   comm = calloc(commsize, sizeof(uint8_t));
831   if (comm == NULL) {
832     DBG(23, ".download_gamma:  couldn't allocate %d bytes for comm buffer!\n",
833 	commsize);
834     return SANE_STATUS_NO_MEM;
835   }
836   data = comm + 10;
837 
838   comm[0] = 0x55;
839   comm[1] = 0;
840   comm[2] = 0x27;
841   comm[3] = 0;
842   comm[4] = 0;
843   comm[5] = 0;
844   comm[6] = 0;
845   comm[7] = ((ms->gamma_entries * ms->gamma_entry_size) >> 8) & 0xFF;
846   comm[8] = (ms->gamma_entries * ms->gamma_entry_size) & 0xFF;
847   comm[9] = (ms->gamma_entry_size == 2) ? 1 : 0;
848 
849   if (!(strcmp(ms->val[OPT_CUSTOM_GAMMA].s, M_TABLE))) {
850     /***** Gamma by TABLE *****/
851     int table_shift = (ms->gamma_bit_depth - bit_depth);
852 
853     DBG(23, ".download_gamma: by table (%d bpe, %d shift)\n",
854 	ms->gamma_bit_depth, table_shift);
855 
856     if (ms->val[OPT_GAMMA_BIND].w == SANE_TRUE) {
857       for (i=0; i<ms->gamma_entries; i++) {
858 	int val = ms->gray_lut[i] >> table_shift;
859 	switch (ms->gamma_entry_size) {
860 	case 1:
861 	  data[i] = (uint8_t) val;
862 	  break;
863 	case 2:
864 	  data[i*2] =  val & 0xFF;
865 	  data[(i*2)+1] = (val>>8) & 0xFF;
866 	  break;
867 	}
868       }
869       status = sanei_scsi_cmd(ms->sfd, comm, commsize, 0, 0);
870     } else {
871       pl = 1;
872       do {
873 	SANE_Int *pl_lut;
874 	switch (pl) {
875 	case 1: pl_lut = ms->red_lut;   break;
876 	case 2: pl_lut = ms->green_lut; break;
877 	case 3: pl_lut = ms->blue_lut;  break;
878 	default:
879 	  DBG(23, ".download_gamma:  uh, exceeded pl bound!\n");
880 	  free(comm);
881 	  return SANE_STATUS_INVAL; /* XXXXXXXxx */
882 	  break;
883 	}
884 	for (i=0; i<ms->gamma_entries; i++) {
885 	  int val = pl_lut[i] >> table_shift;
886 	  switch (ms->gamma_entry_size) {
887 	  case 1:
888 	    data[i] = (uint8_t) val;
889 	    break;
890 	  case 2:
891 	    data[i*2] =  val & 0xFF;
892 	    data[(i*2)+1] =  (val>>8) & 0xFF;
893 	    break;
894 	  }
895 	}
896 	/* XXXXXXX */
897 	comm[9] = (comm[9] & 0x3F) | (pl << 6);
898 	status = sanei_scsi_cmd(ms->sfd, comm, commsize, 0, 0);
899 	pl++;
900       } while ((pl < 4) && (status == SANE_STATUS_GOOD));
901     }
902   } else if (!(strcmp(ms->val[OPT_CUSTOM_GAMMA].s, M_SCALAR))) {
903     /***** Gamma by SCALAR *****/
904     DBG(23, ".download_gamma: by scalar\n");
905     if (ms->val[OPT_GAMMA_BIND].w == SANE_TRUE) {
906       double gamma = SANE_UNFIX(ms->val[OPT_ANALOG_GAMMA].w);
907       for (i=0; i<ms->gamma_entries; i++) {
908 	int val =  (max_entry *
909 		    pow((double) i / ((double) ms->gamma_entries - 1.0),
910 			1.0 / gamma));
911 	switch (ms->gamma_entry_size) {
912 	case 1:
913 	  data[i] = (uint8_t) val;
914 	  break;
915 	case 2:
916 	  data[i*2] = val & 0xFF;
917 	  data[(i*2)+1] = (val>>8) & 0xFF;
918 	  break;
919 	}
920       }
921       status = sanei_scsi_cmd(ms->sfd, comm, commsize, 0, 0);
922     } else {
923       double gamma;
924       pl = 1;
925       do {
926 	switch (pl) {
927 	case 1: gamma = SANE_UNFIX(ms->val[OPT_ANALOG_GAMMA_R].w); break;
928 	case 2: gamma = SANE_UNFIX(ms->val[OPT_ANALOG_GAMMA_G].w); break;
929 	case 3: gamma = SANE_UNFIX(ms->val[OPT_ANALOG_GAMMA_B].w); break;
930 	default: gamma = 1.0; break; /* should never happen */
931 	}
932 	for (i=0; i<ms->gamma_entries; i++) {
933 	  int val =  (max_entry *
934 		      pow((double) i / ((double) ms->gamma_entries - 1.0),
935 			  1.0 / gamma));
936 	  switch (ms->gamma_entry_size) {
937 	    case 1:
938 	      data[i] = (uint8_t) val;
939 	      break;
940 	  case 2:
941 	    data[i*2] = val & 0xFF;
942 	    data[(i*2)+1] = (val>>8) & 0xFF;
943 	    break;
944 	  }
945 	}
946 	comm[9] = (comm[9] & 0x3F) | (pl << 6);
947 	status = sanei_scsi_cmd(ms->sfd, comm, commsize, 0, 0);
948 	pl++;
949       } while ((pl < 4) && (status == SANE_STATUS_GOOD));
950     }
951   } else {
952     /***** No custom Gamma *****/
953     DBG(23, ".download_gamma: by default\n");
954     for (i=0; i<ms->gamma_entries; i++) {
955       /*      int val =  (((double) max_entry * (double) i /
956 	      ((double) ms->gamma_entries - 1.0)) + 0.5);     ROUNDING????*/
957       int val =
958 	(double) max_entry * (double) i /
959 	((double) ms->gamma_entries - 1.0);
960       switch (ms->gamma_entry_size) {
961       case 1:
962 	data[i] = (uint8_t) val;
963 	break;
964       case 2:
965 	data[i*2] = val & 0xFF;
966 	data[(i*2)+1] = (val >> 8) & 0xFF;
967 	break;
968       }
969     }
970     status = sanei_scsi_cmd(ms->sfd, comm, commsize, 0, 0);
971   }
972   free(comm);
973   return status;
974 }
975 
976 
977 /********************************************************************/
978 /* magic command to start calibration                               */
979 /********************************************************************/
980 static SANE_Status
start_calibration(Microtek_Scanner * ms)981 start_calibration(Microtek_Scanner *ms)
982 {
983   uint8_t comm[8] = { 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x0a };
984 
985   DBG(23, ".start_calibrate...\n");
986   if (DBG_LEVEL >= 192) {
987     int i;
988 #if 0
989     fprintf(stderr, "STCal:");
990     for (i=0;i<8;i++) fprintf(stderr, "%2x ", comm[i]);
991     fprintf(stderr, "\n");
992 #endif
993     MDBG_INIT("STCal:");
994     for (i=0;i<8;i++) MDBG_ADD("%2x ", comm[i]);
995     MDBG_FINISH(192);
996   }
997   return sanei_scsi_cmd(ms->sfd, comm, 8, 0, 0);
998 }
999 
1000 
1001 
1002 /********************************************************************/
1003 /* magic command to download calibration values                     */
1004 /********************************************************************/
1005 static SANE_Status
download_calibration(Microtek_Scanner * ms,uint8_t * comm,uint8_t letter,int linewidth)1006 download_calibration(Microtek_Scanner *ms, uint8_t *comm,
1007 		     uint8_t letter, int linewidth)
1008 {
1009   DBG(23, ".download_calibration... %c %d\n", letter, linewidth);
1010 
1011   comm[0] = 0x0c;
1012   comm[1] = 0x00;
1013   comm[2] = 0x00;
1014   comm[3] = (linewidth >> 8) & 0xFF;
1015   comm[4] = linewidth & 0xFF;
1016   comm[5] = 0x00;
1017 
1018   comm[6] = 0x00;
1019   switch (letter) {
1020   case 'R': comm[7] = 0x40; break;
1021   case 'G': comm[7] = 0x80; break;
1022   case 'B': comm[7] = 0xc0; break;
1023   default: /* XXXXXXX */ break;
1024   }
1025 
1026   return sanei_scsi_cmd(ms->sfd, comm, 6 + linewidth, 0, 0);
1027 }
1028 
1029 
1030 
1031 /********************************************************************/
1032 /********************************************************************/
1033 /*                                                                  */
1034 /* Myriad of internal functions                                     */
1035 /*                                                                  */
1036 /********************************************************************/
1037 /********************************************************************/
1038 
1039 
1040 
1041 /********************************************************************/
1042 /* Initialize the options registry                                  */
1043 /********************************************************************/
1044 static SANE_Status
init_options(Microtek_Scanner * ms)1045 init_options(Microtek_Scanner *ms)
1046 {
1047   int i;
1048   SANE_Option_Descriptor *sod = ms->sod;
1049   Option_Value *val = ms->val;
1050 
1051   DBG(15, "init_options...\n");
1052 
1053   memset(ms->sod, 0, sizeof(ms->sod));
1054   memset(ms->val, 0, sizeof(ms->val));
1055   /* default:  software selectable word options... */
1056   for (i=0; i<NUM_OPTIONS; i++) {
1057     sod[i].size = sizeof(SANE_Word);
1058     sod[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
1059   }
1060 
1061   sod[OPT_NUM_OPTS].name =   SANE_NAME_NUM_OPTIONS;
1062   sod[OPT_NUM_OPTS].title =  SANE_TITLE_NUM_OPTIONS;
1063   sod[OPT_NUM_OPTS].desc =   SANE_DESC_NUM_OPTIONS;
1064   sod[OPT_NUM_OPTS].type =   SANE_TYPE_INT;
1065   sod[OPT_NUM_OPTS].unit =   SANE_UNIT_NONE;
1066   sod[OPT_NUM_OPTS].size =   sizeof (SANE_Word);
1067   sod[OPT_NUM_OPTS].cap =    SANE_CAP_SOFT_DETECT;
1068   sod[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE;
1069 
1070   /* The Scan Mode Group */
1071   sod[OPT_MODE_GROUP].name  = "";
1072   sod[OPT_MODE_GROUP].title = "Scan Mode";
1073   sod[OPT_MODE_GROUP].desc  = "";
1074   sod[OPT_MODE_GROUP].type  = SANE_TYPE_GROUP;
1075   sod[OPT_MODE_GROUP].cap   = 0;
1076   sod[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
1077 
1078   sod[OPT_MODE].name = SANE_NAME_SCAN_MODE;
1079   sod[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
1080   sod[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
1081   sod[OPT_MODE].type = SANE_TYPE_STRING;
1082   sod[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1083   {
1084     SANE_String_Const *mode_list;
1085     mode_list = (SANE_String_Const *) malloc(5 * sizeof(SANE_String_Const));
1086     if (mode_list == NULL) return SANE_STATUS_NO_MEM;
1087     i = 0;
1088     if (ms->dev->info.modes & MI_MODES_COLOR)    mode_list[i++] = M_COLOR;
1089     if (ms->dev->info.modes & MI_MODES_GRAY)     mode_list[i++] = M_GRAY;
1090     if (ms->dev->info.modes & MI_MODES_HALFTONE) mode_list[i++] = M_HALFTONE;
1091     if (ms->dev->info.modes & MI_MODES_LINEART)  mode_list[i++] = M_LINEART;
1092     mode_list[i] = NULL;
1093     sod[OPT_MODE].constraint.string_list = mode_list;
1094     sod[OPT_MODE].size                   = max_string_size(mode_list);
1095     val[OPT_MODE].s = strdup(mode_list[0]);
1096   }
1097 
1098   sod[OPT_RESOLUTION].name  = SANE_NAME_SCAN_RESOLUTION;
1099   sod[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
1100   sod[OPT_RESOLUTION].desc  = SANE_DESC_SCAN_RESOLUTION;
1101   sod[OPT_RESOLUTION].type  = SANE_TYPE_FIXED;
1102   sod[OPT_RESOLUTION].unit  = SANE_UNIT_DPI;
1103   sod[OPT_RESOLUTION].constraint_type  = SANE_CONSTRAINT_RANGE;
1104   {
1105     SANE_Int maxres = ms->dev->info.base_resolution;
1106 
1107     ms->res_range.max = SANE_FIX(maxres);
1108     ms->exp_res_range.max = SANE_FIX(2 * maxres);
1109     if (ms->dev->info.res_step & MI_RESSTEP_1PER) {
1110       DBG(23, "init_options:  quant yes\n");
1111       ms->res_range.min = SANE_FIX( maxres / 100 );
1112       ms->res_range.quant = ms->res_range.min;
1113       ms->exp_res_range.min = SANE_FIX(2 * maxres / 100);
1114       ms->exp_res_range.quant = ms->exp_res_range.min;
1115     } else {
1116       /* XXXXXXXXXXX */
1117       DBG(23, "init_options:  quant no\n");
1118       ms->res_range.quant = SANE_FIX( 0 );
1119     }
1120     sod[OPT_RESOLUTION].constraint.range = &(ms->res_range);
1121   }
1122   val[OPT_RESOLUTION].w     = SANE_FIX(100);
1123 
1124   sod[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN;
1125   sod[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN;
1126   sod[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN;
1127   sod[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING;
1128   sod[OPT_HALFTONE_PATTERN].size = max_string_size(halftone_mode_list);
1129   sod[OPT_HALFTONE_PATTERN].cap  |= SANE_CAP_INACTIVE;
1130   sod[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1131   sod[OPT_HALFTONE_PATTERN].constraint.string_list = halftone_mode_list;
1132   val[OPT_HALFTONE_PATTERN].s = strdup(halftone_mode_list[0]);
1133 
1134   sod[OPT_NEGATIVE].name  = SANE_NAME_NEGATIVE;
1135   sod[OPT_NEGATIVE].title = SANE_TITLE_NEGATIVE;
1136   sod[OPT_NEGATIVE].desc  = SANE_DESC_NEGATIVE;
1137   sod[OPT_NEGATIVE].type  = SANE_TYPE_BOOL;
1138   sod[OPT_NEGATIVE].cap   |=
1139     (ms->dev->info.modes & MI_MODES_NEGATIVE) ? 0 : SANE_CAP_INACTIVE;
1140   val[OPT_NEGATIVE].w     = SANE_FALSE;
1141 
1142   sod[OPT_SPEED].name  = SANE_NAME_SCAN_SPEED;
1143   sod[OPT_SPEED].title = SANE_TITLE_SCAN_SPEED;
1144   /*  sod[OPT_SPEED].desc  = SANE_DESC_SCAN_SPEED;*/
1145   sod[OPT_SPEED].desc  = "Scan speed throttle -- higher values are *slower*.";
1146   sod[OPT_SPEED].type  = SANE_TYPE_INT;
1147   sod[OPT_SPEED].cap   |= SANE_CAP_ADVANCED;
1148   sod[OPT_SPEED].unit  = SANE_UNIT_NONE;
1149   sod[OPT_SPEED].size  = sizeof(SANE_Word);
1150   sod[OPT_SPEED].constraint_type = SANE_CONSTRAINT_RANGE;
1151   sod[OPT_SPEED].constraint.range = &speed_range;
1152   val[OPT_SPEED].w     = 1;
1153 
1154   sod[OPT_SOURCE].name  = SANE_NAME_SCAN_SOURCE;
1155   sod[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
1156   sod[OPT_SOURCE].desc  = SANE_DESC_SCAN_SOURCE;
1157   sod[OPT_SOURCE].type  = SANE_TYPE_STRING;
1158   sod[OPT_SOURCE].unit  = SANE_UNIT_NONE;
1159   sod[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1160   {
1161     SANE_String_Const *source_list;
1162     source_list = (SANE_String_Const *) malloc(4 * sizeof(SANE_String_Const));
1163     if (source_list == NULL) return SANE_STATUS_NO_MEM;
1164     i = 0;
1165     source_list[i++] = M_OPAQUE;
1166     if (ms->dev->info.source_options & MI_SRC_HAS_TRANS)
1167       source_list[i++] = M_TRANS;
1168     if (ms->dev->info.source_options & MI_SRC_HAS_FEED)
1169       source_list[i++] = M_AUTOFEED;
1170     source_list[i] = NULL;
1171     sod[OPT_SOURCE].constraint.string_list = source_list;
1172     sod[OPT_SOURCE].size                   = max_string_size(source_list);
1173     if (i < 2)
1174       sod[OPT_SOURCE].cap |= SANE_CAP_INACTIVE;
1175     val[OPT_SOURCE].s = strdup(source_list[0]);
1176   }
1177 
1178   sod[OPT_PREVIEW].name  = SANE_NAME_PREVIEW;
1179   sod[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
1180   sod[OPT_PREVIEW].desc  = SANE_DESC_PREVIEW;
1181   sod[OPT_PREVIEW].type  = SANE_TYPE_BOOL;
1182   sod[OPT_PREVIEW].unit  = SANE_UNIT_NONE;
1183   sod[OPT_PREVIEW].size  = sizeof(SANE_Word);
1184   val[OPT_PREVIEW].w     = SANE_FALSE;
1185 
1186 
1187   sod[OPT_GEOMETRY_GROUP].name  = "";
1188   sod[OPT_GEOMETRY_GROUP].title = "Geometry";
1189   sod[OPT_GEOMETRY_GROUP].desc  = "";
1190   sod[OPT_GEOMETRY_GROUP].type  = SANE_TYPE_GROUP;
1191   sod[OPT_GEOMETRY_GROUP].cap   = SANE_CAP_ADVANCED;
1192   sod[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
1193 
1194 
1195   sod[OPT_TL_X].name  = SANE_NAME_SCAN_TL_X;
1196   sod[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
1197   sod[OPT_TL_X].desc  = SANE_DESC_SCAN_TL_X;
1198   sod[OPT_TL_X].type  = SANE_TYPE_FIXED;
1199   sod[OPT_TL_X].unit  = SANE_UNIT_MM;
1200   sod[OPT_TL_X].size  = sizeof(SANE_Word);
1201   sod[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
1202 
1203   sod[OPT_TL_Y].name  = SANE_NAME_SCAN_TL_Y;
1204   sod[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
1205   sod[OPT_TL_Y].desc  = SANE_DESC_SCAN_TL_Y;
1206   sod[OPT_TL_Y].type  = SANE_TYPE_FIXED;
1207   sod[OPT_TL_Y].unit  = SANE_UNIT_MM;
1208   sod[OPT_TL_Y].size  = sizeof(SANE_Word);
1209   sod[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
1210 
1211   sod[OPT_BR_X].name  = SANE_NAME_SCAN_BR_X;
1212   sod[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
1213   sod[OPT_BR_X].desc  = SANE_DESC_SCAN_BR_X;
1214   sod[OPT_BR_X].type  = SANE_TYPE_FIXED;
1215   sod[OPT_BR_X].unit  = SANE_UNIT_MM;
1216   sod[OPT_BR_X].size  = sizeof(SANE_Word);
1217   sod[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
1218 
1219   sod[OPT_BR_Y].name  = SANE_NAME_SCAN_BR_Y;
1220   sod[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
1221   sod[OPT_BR_Y].desc  = SANE_DESC_SCAN_BR_Y;
1222   sod[OPT_BR_Y].type  = SANE_TYPE_FIXED;
1223   sod[OPT_BR_Y].unit  = SANE_UNIT_MM;
1224   sod[OPT_BR_Y].size  = sizeof(SANE_Word);
1225   sod[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
1226 
1227   sod[OPT_TL_X].constraint.range =
1228     sod[OPT_BR_X].constraint.range = &(ms->dev->info.doc_x_range);
1229   sod[OPT_TL_Y].constraint.range =
1230     sod[OPT_BR_Y].constraint.range = &(ms->dev->info.doc_y_range);
1231 
1232   /* set default scan region to be maximum size */
1233   val[OPT_TL_X].w     = sod[OPT_TL_X].constraint.range->min;
1234   val[OPT_TL_Y].w     = sod[OPT_TL_Y].constraint.range->min;
1235   val[OPT_BR_X].w     = sod[OPT_BR_X].constraint.range->max;
1236   val[OPT_BR_Y].w     = sod[OPT_BR_Y].constraint.range->max;
1237 
1238   sod[OPT_ENHANCEMENT_GROUP].name  = "";
1239   sod[OPT_ENHANCEMENT_GROUP].title = "Enhancement";
1240   sod[OPT_ENHANCEMENT_GROUP].desc  = "";
1241   sod[OPT_ENHANCEMENT_GROUP].type  = SANE_TYPE_GROUP;
1242   sod[OPT_ENHANCEMENT_GROUP].cap   = 0;
1243   sod[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
1244 
1245   sod[OPT_EXPOSURE].name  = "exposure";
1246   sod[OPT_EXPOSURE].title = "Exposure";
1247   sod[OPT_EXPOSURE].desc  = "Analog exposure control";
1248   sod[OPT_EXPOSURE].type  = SANE_TYPE_INT;
1249   sod[OPT_EXPOSURE].unit  = SANE_UNIT_PERCENT;
1250   sod[OPT_EXPOSURE].size  = sizeof(SANE_Word);
1251   sod[OPT_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE;
1252   ms->exposure_range.min = ms->dev->info.min_exposure;
1253   ms->exposure_range.max = ms->dev->info.max_exposure;
1254   ms->exposure_range.quant = 3;
1255   sod[OPT_EXPOSURE].constraint.range      = &(ms->exposure_range);
1256   val[OPT_EXPOSURE].w     = 0;
1257 
1258   sod[OPT_BRIGHTNESS].name  = SANE_NAME_BRIGHTNESS;
1259   sod[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
1260   sod[OPT_BRIGHTNESS].desc  = SANE_DESC_BRIGHTNESS;
1261   sod[OPT_BRIGHTNESS].type  = SANE_TYPE_INT;
1262   sod[OPT_BRIGHTNESS].unit  = SANE_UNIT_PERCENT;
1263   sod[OPT_BRIGHTNESS].size  = sizeof(SANE_Word);
1264   sod[OPT_BRIGHTNESS].cap   |=
1265     ((ms->dev->info.extra_cap & MI_EXCAP_OFF_CTL) ? 0: SANE_CAP_INACTIVE);
1266   sod[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
1267   sod[OPT_BRIGHTNESS].constraint.range      = &brightness_range;
1268   val[OPT_BRIGHTNESS].w     = 0;
1269 
1270   sod[OPT_CONTRAST].name  = SANE_NAME_CONTRAST;
1271   sod[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
1272   sod[OPT_CONTRAST].desc  = SANE_DESC_CONTRAST;
1273   sod[OPT_CONTRAST].type  = SANE_TYPE_INT;
1274   sod[OPT_CONTRAST].unit  = SANE_UNIT_PERCENT;
1275   sod[OPT_CONTRAST].size  = sizeof(SANE_Word);
1276   sod[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
1277   ms->contrast_range.min = ms->dev->info.min_contrast;
1278   ms->contrast_range.max = ms->dev->info.max_contrast;
1279   ms->contrast_range.quant = 7;
1280   sod[OPT_CONTRAST].constraint.range      = &(ms->contrast_range);
1281   val[OPT_CONTRAST].w     = 0;
1282 
1283 
1284   sod[OPT_HIGHLIGHT].name  = SANE_NAME_WHITE_LEVEL;
1285   sod[OPT_HIGHLIGHT].title = SANE_TITLE_WHITE_LEVEL;
1286   sod[OPT_HIGHLIGHT].desc  = SANE_DESC_WHITE_LEVEL;
1287   sod[OPT_HIGHLIGHT].type  = SANE_TYPE_INT;
1288   sod[OPT_HIGHLIGHT].unit  = SANE_UNIT_NONE;
1289   sod[OPT_HIGHLIGHT].size  = sizeof(SANE_Word);
1290   sod[OPT_HIGHLIGHT].constraint_type = SANE_CONSTRAINT_RANGE;
1291   sod[OPT_HIGHLIGHT].constraint.range      = &u8_range;
1292   val[OPT_HIGHLIGHT].w     = 255;
1293 
1294   sod[OPT_SHADOW].name  = SANE_NAME_BLACK_LEVEL;
1295   sod[OPT_SHADOW].title = SANE_TITLE_BLACK_LEVEL;
1296   sod[OPT_SHADOW].desc  = SANE_DESC_BLACK_LEVEL;
1297   sod[OPT_SHADOW].type  = SANE_TYPE_INT;
1298   sod[OPT_SHADOW].unit  = SANE_UNIT_NONE;
1299   sod[OPT_SHADOW].size  = sizeof(SANE_Word);
1300   sod[OPT_SHADOW].constraint_type = SANE_CONSTRAINT_RANGE;
1301   sod[OPT_SHADOW].constraint.range      = &u8_range;
1302   val[OPT_SHADOW].w     = 0;
1303 
1304   if (ms->dev->info.enhance_cap & MI_ENH_CAP_SHADOW) {
1305     sod[OPT_HIGHLIGHT].cap |= SANE_CAP_ADVANCED;
1306     sod[OPT_SHADOW].cap    |= SANE_CAP_ADVANCED;
1307   } else {
1308     sod[OPT_HIGHLIGHT].cap |= SANE_CAP_INACTIVE;
1309     sod[OPT_SHADOW].cap    |= SANE_CAP_INACTIVE;
1310   }
1311 
1312   sod[OPT_MIDTONE].name  = "midtone";
1313   sod[OPT_MIDTONE].title = "Midtone Level";
1314   sod[OPT_MIDTONE].desc  = "Midtone Level";
1315   sod[OPT_MIDTONE].type  = SANE_TYPE_INT;
1316   sod[OPT_MIDTONE].unit  = SANE_UNIT_NONE;
1317   sod[OPT_MIDTONE].size  = sizeof(SANE_Word);
1318   sod[OPT_MIDTONE].constraint_type = SANE_CONSTRAINT_RANGE;
1319   sod[OPT_MIDTONE].constraint.range      = &u8_range;
1320   val[OPT_MIDTONE].w     = 128;
1321   if (ms->midtone_support) {
1322     sod[OPT_MIDTONE].cap   |= SANE_CAP_ADVANCED;
1323   } else {
1324     sod[OPT_MIDTONE].cap   |= SANE_CAP_INACTIVE;
1325   }
1326   /* XXXXXXXX is this supported by all scanners??
1327   if ((strcmp(M_COLOR, val[OPT_MODE].s)) &&
1328       (strcmp(M_GRAY, val[OPT_MODE].s))) {
1329     sod[OPT_HIGHLIGHT].cap |= SANE_CAP_INACTIVE;
1330     sod[OPT_SHADOW].cap    |= SANE_CAP_INACTIVE;
1331     sod[OPT_MIDTONE].cap   |= SANE_CAP_INACTIVE;
1332   }
1333   */
1334 
1335   sod[OPT_GAMMA_GROUP].name  = "";
1336   sod[OPT_GAMMA_GROUP].title = "Gamma Control";
1337   sod[OPT_GAMMA_GROUP].desc  = "";
1338   sod[OPT_GAMMA_GROUP].type  = SANE_TYPE_GROUP;
1339   if (!(ms->gamma_entries))
1340     sod[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE;
1341   sod[OPT_GAMMA_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
1342 
1343   sod[OPT_CUSTOM_GAMMA].name  = "gamma-mode";
1344   sod[OPT_CUSTOM_GAMMA].title = "Gamma Control Mode";
1345   sod[OPT_CUSTOM_GAMMA].desc  = "How to specify gamma correction, if at all";
1346   sod[OPT_CUSTOM_GAMMA].type  = SANE_TYPE_STRING;
1347   sod[OPT_CUSTOM_GAMMA].size  = max_string_size(gamma_mode_list);
1348   sod[OPT_CUSTOM_GAMMA].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1349   sod[OPT_CUSTOM_GAMMA].constraint.string_list = gamma_mode_list;
1350   if (!(ms->gamma_entries))
1351     sod[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE;
1352   val[OPT_CUSTOM_GAMMA].s = strdup(gamma_mode_list[0]);
1353 
1354   sod[OPT_GAMMA_BIND].name  = SANE_NAME_ANALOG_GAMMA_BIND;
1355   sod[OPT_GAMMA_BIND].title = SANE_TITLE_ANALOG_GAMMA_BIND;
1356   sod[OPT_GAMMA_BIND].desc  = SANE_DESC_ANALOG_GAMMA_BIND;
1357   sod[OPT_GAMMA_BIND].type  = SANE_TYPE_BOOL;
1358   sod[OPT_GAMMA_BIND].cap   |= SANE_CAP_INACTIVE;
1359   val[OPT_GAMMA_BIND].w     = SANE_TRUE;
1360 
1361   sod[OPT_ANALOG_GAMMA].name  = SANE_NAME_ANALOG_GAMMA;
1362   sod[OPT_ANALOG_GAMMA].title = SANE_TITLE_ANALOG_GAMMA;
1363   sod[OPT_ANALOG_GAMMA].desc  = SANE_DESC_ANALOG_GAMMA;
1364   sod[OPT_ANALOG_GAMMA].type  = SANE_TYPE_FIXED;
1365   sod[OPT_ANALOG_GAMMA].unit  = SANE_UNIT_NONE;
1366   sod[OPT_ANALOG_GAMMA].size  = sizeof(SANE_Word);
1367   sod[OPT_ANALOG_GAMMA].cap   |= SANE_CAP_INACTIVE;
1368   sod[OPT_ANALOG_GAMMA].constraint_type = SANE_CONSTRAINT_RANGE;
1369   sod[OPT_ANALOG_GAMMA].constraint.range      = &analog_gamma_range;
1370   val[OPT_ANALOG_GAMMA].w     = SANE_FIX(1.0);
1371 
1372   sod[OPT_ANALOG_GAMMA_R].name  = SANE_NAME_ANALOG_GAMMA_R;
1373   sod[OPT_ANALOG_GAMMA_R].title = SANE_TITLE_ANALOG_GAMMA_R;
1374   sod[OPT_ANALOG_GAMMA_R].desc  = SANE_DESC_ANALOG_GAMMA_R;
1375   sod[OPT_ANALOG_GAMMA_R].type  = SANE_TYPE_FIXED;
1376   sod[OPT_ANALOG_GAMMA_R].unit  = SANE_UNIT_NONE;
1377   sod[OPT_ANALOG_GAMMA_R].size  = sizeof(SANE_Word);
1378   sod[OPT_ANALOG_GAMMA_R].cap   |= SANE_CAP_INACTIVE;
1379   sod[OPT_ANALOG_GAMMA_R].constraint_type = SANE_CONSTRAINT_RANGE;
1380   sod[OPT_ANALOG_GAMMA_R].constraint.range      = &analog_gamma_range;
1381   val[OPT_ANALOG_GAMMA_R].w     = SANE_FIX(1.0);
1382 
1383   sod[OPT_ANALOG_GAMMA_G].name  = SANE_NAME_ANALOG_GAMMA_G;
1384   sod[OPT_ANALOG_GAMMA_G].title = SANE_TITLE_ANALOG_GAMMA_G;
1385   sod[OPT_ANALOG_GAMMA_G].desc  = SANE_DESC_ANALOG_GAMMA_G;
1386   sod[OPT_ANALOG_GAMMA_G].type  = SANE_TYPE_FIXED;
1387   sod[OPT_ANALOG_GAMMA_G].unit  = SANE_UNIT_NONE;
1388   sod[OPT_ANALOG_GAMMA_G].size  = sizeof(SANE_Word);
1389   sod[OPT_ANALOG_GAMMA_G].cap   |= SANE_CAP_INACTIVE;
1390   sod[OPT_ANALOG_GAMMA_G].constraint_type = SANE_CONSTRAINT_RANGE;
1391   sod[OPT_ANALOG_GAMMA_G].constraint.range      = &analog_gamma_range;
1392   val[OPT_ANALOG_GAMMA_G].w     = SANE_FIX(1.0);
1393 
1394   sod[OPT_ANALOG_GAMMA_B].name  = SANE_NAME_ANALOG_GAMMA_B;
1395   sod[OPT_ANALOG_GAMMA_B].title = SANE_TITLE_ANALOG_GAMMA_B;
1396   sod[OPT_ANALOG_GAMMA_B].desc  = SANE_DESC_ANALOG_GAMMA_B;
1397   sod[OPT_ANALOG_GAMMA_B].type  = SANE_TYPE_FIXED;
1398   sod[OPT_ANALOG_GAMMA_B].unit  = SANE_UNIT_NONE;
1399   sod[OPT_ANALOG_GAMMA_B].size  = sizeof(SANE_Word);
1400   sod[OPT_ANALOG_GAMMA_B].cap   |= SANE_CAP_INACTIVE;
1401   sod[OPT_ANALOG_GAMMA_B].constraint_type = SANE_CONSTRAINT_RANGE;
1402   sod[OPT_ANALOG_GAMMA_B].constraint.range      = &analog_gamma_range;
1403   val[OPT_ANALOG_GAMMA_B].w     = SANE_FIX(1.0);
1404 
1405   sod[OPT_GAMMA_VECTOR].name  = SANE_NAME_GAMMA_VECTOR;
1406   sod[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR;
1407   sod[OPT_GAMMA_VECTOR].desc  = SANE_DESC_GAMMA_VECTOR;
1408   sod[OPT_GAMMA_VECTOR].type  = SANE_TYPE_INT;
1409   sod[OPT_GAMMA_VECTOR].unit  = SANE_UNIT_NONE;
1410   sod[OPT_GAMMA_VECTOR].size  = ms->gamma_entries * sizeof(SANE_Word);
1411   sod[OPT_GAMMA_VECTOR].cap   |= SANE_CAP_INACTIVE;
1412   sod[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE;
1413   sod[OPT_GAMMA_VECTOR].constraint.range      = &(ms->gamma_entry_range);
1414   val[OPT_GAMMA_VECTOR].wa     = ms->gray_lut;
1415 
1416   sod[OPT_GAMMA_VECTOR_R].name  = SANE_NAME_GAMMA_VECTOR_R;
1417   sod[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R;
1418   sod[OPT_GAMMA_VECTOR_R].desc  = SANE_DESC_GAMMA_VECTOR_R;
1419   sod[OPT_GAMMA_VECTOR_R].type  = SANE_TYPE_INT;
1420   sod[OPT_GAMMA_VECTOR_R].unit  = SANE_UNIT_NONE;
1421   sod[OPT_GAMMA_VECTOR_R].size  = ms->gamma_entries * sizeof(SANE_Word);
1422   sod[OPT_GAMMA_VECTOR_R].cap   |= SANE_CAP_INACTIVE;
1423   sod[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE;
1424   sod[OPT_GAMMA_VECTOR_R].constraint.range      = &(ms->gamma_entry_range);
1425   val[OPT_GAMMA_VECTOR_R].wa     = ms->red_lut;
1426 
1427   sod[OPT_GAMMA_VECTOR_G].name  = SANE_NAME_GAMMA_VECTOR_G;
1428   sod[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G;
1429   sod[OPT_GAMMA_VECTOR_G].desc  = SANE_DESC_GAMMA_VECTOR_G;
1430   sod[OPT_GAMMA_VECTOR_G].type  = SANE_TYPE_INT;
1431   sod[OPT_GAMMA_VECTOR_G].unit  = SANE_UNIT_NONE;
1432   sod[OPT_GAMMA_VECTOR_G].size  = ms->gamma_entries * sizeof(SANE_Word);
1433   sod[OPT_GAMMA_VECTOR_G].cap   |= SANE_CAP_INACTIVE;
1434   sod[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE;
1435   sod[OPT_GAMMA_VECTOR_G].constraint.range      = &(ms->gamma_entry_range);
1436   val[OPT_GAMMA_VECTOR_G].wa     = ms->green_lut;
1437 
1438   sod[OPT_GAMMA_VECTOR_B].name  = SANE_NAME_GAMMA_VECTOR_B;
1439   sod[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B;
1440   sod[OPT_GAMMA_VECTOR_B].desc  = SANE_DESC_GAMMA_VECTOR_B;
1441   sod[OPT_GAMMA_VECTOR_B].type  = SANE_TYPE_INT;
1442   sod[OPT_GAMMA_VECTOR_B].unit  = SANE_UNIT_NONE;
1443   sod[OPT_GAMMA_VECTOR_B].size  = ms->gamma_entries * sizeof(SANE_Word);
1444   sod[OPT_GAMMA_VECTOR_B].cap   |= SANE_CAP_INACTIVE;
1445   sod[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE;
1446   sod[OPT_GAMMA_VECTOR_B].constraint.range      = &(ms->gamma_entry_range);
1447   val[OPT_GAMMA_VECTOR_B].wa     = ms->blue_lut;
1448 
1449   sod[OPT_EXP_RES].name  = "exp_res";
1450   sod[OPT_EXP_RES].title = "Expanded Resolution";
1451   sod[OPT_EXP_RES].desc  = "Enable double-resolution scans";
1452   sod[OPT_EXP_RES].type  = SANE_TYPE_BOOL;
1453   sod[OPT_EXP_RES].cap   |= SANE_CAP_ADVANCED;
1454   if (!(ms->dev->info.expanded_resolution))
1455     sod[OPT_EXP_RES].cap |= SANE_CAP_INACTIVE;
1456   val[OPT_EXP_RES].w     = SANE_FALSE;
1457 
1458   sod[OPT_CALIB_ONCE].name  = "calib_once";
1459   sod[OPT_CALIB_ONCE].title = "Calibrate Only Once";
1460   sod[OPT_CALIB_ONCE].desc  = "Avoid CCD calibration on every scan" \
1461     "(toggle off/on to cause calibration on next scan)";
1462   sod[OPT_CALIB_ONCE].type  = SANE_TYPE_BOOL;
1463   sod[OPT_CALIB_ONCE].cap   |= SANE_CAP_ADVANCED;
1464   if (!(ms->do_real_calib)) {
1465     sod[OPT_CALIB_ONCE].cap |= SANE_CAP_INACTIVE;
1466     val[OPT_CALIB_ONCE].w     = SANE_FALSE;
1467   } else
1468     val[OPT_CALIB_ONCE].w     = SANE_TRUE;
1469 
1470   /*
1471   sod[OPT_].name  = SANE_NAME_;
1472   sod[OPT_].title = SANE_TITLE_;
1473   sod[OPT_].desc  = SANE_DESC_;
1474   sod[OPT_].type  = SANE_TYPE_;
1475   sod[OPT_].unit  = SANE_UNIT_NONE;
1476   sod[OPT_].size  = sizeof(SANE_Word);
1477   sod[OPT_].cap   = 0;
1478   sod[OPT_].constraint_type = SANE_CONSTRAINT_NONE;
1479   sod[OPT_].constraint      = ;
1480   val[OPT_].w     = ;
1481   */
1482 
1483   DBG(15, "init_options:  done.\n");
1484   return SANE_STATUS_GOOD;
1485 }
1486 
1487 
1488 /********************************************************************/
1489 /* Parse an INQUIRY information block, as returned by scanner       */
1490 /********************************************************************/
1491 static SANE_Status
parse_inquiry(Microtek_Info * mi,unsigned char * result)1492 parse_inquiry(Microtek_Info *mi, unsigned char *result)
1493 {
1494 #if 0
1495   unsigned char result[0x60] = {
1496     0x06,0x31,0x23,0x01,0x5b,0x00,0x00,0x00,0x41,0x47,0x46,0x41,0x20,0x20,0x20,0x20,
1497     0x53,0x74,0x75,0x64,0x69,0x6f,0x53,0x63,0x61,0x6e,0x20,0x49,0x49,0x20,0x20,0x20,
1498     0x32,0x2e,0x33,0x30,0x53,0x43,0x53,0x49,0x20,0x46,0x2f,0x57,0x56,0x33,0x2e,0x31,
1499     0x20,0x43,0x54,0x4c,0x35,0x33,0x38,0x30,0x03,0x4f,0x8c,0xc5,0x00,0xee,0x5b,0x43,
1500     0x01,0x01,0x02,0x00,0x00,0x03,0x00,0x01,0x00,0x4a,0x01,0x04,0x00,0x00,0x00,0x00,
1501     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff
1502   };
1503 #endif
1504   DBG(15, "parse_inquiry...\n");
1505   snprintf(mi->vendor_id,      8 + 1, "%.*s",  8, (char *)&result[8]);
1506   snprintf(mi->model_name,    16 + 1, "%.*s", 16, (char *)&result[16]);
1507   snprintf(mi->revision_num,   4 + 1, "%.*s",  4, (char *)&result[32]);
1508   snprintf(mi->vendor_string, 20 + 1, "%.*s", 20, (char *)&result[36]);
1509 
1510   mi->device_type                = (SANE_Byte)(result[0] & 0x1f);
1511   mi->SCSI_firmware_ver_major    = (SANE_Byte)((result[1] & 0xf0) >> 4);
1512   mi->SCSI_firmware_ver_minor    = (SANE_Byte)(result[1] & 0x0f);
1513   mi->scanner_firmware_ver_major = (SANE_Byte)((result[2] & 0xf0) >> 4);
1514   mi->scanner_firmware_ver_minor = (SANE_Byte)(result[2] & 0x0f);
1515   mi->response_data_format       = (SANE_Byte)(result[3]);
1516 
1517   mi->res_step                   = (SANE_Byte)(result[56] & 0x03);
1518   mi->modes                      = (SANE_Byte)(result[57]);
1519   mi->pattern_count              = (SANE_Int)(result[58] & 0x7f);
1520   mi->pattern_dwnld              = (SANE_Byte)(result[58] & 0x80) > 0;
1521   mi->feed_type                  = (SANE_Byte)(result[59] & 0x0F);
1522   mi->compress_type              = (SANE_Byte)(result[59] & 0x30);
1523   mi->unit_type                  = (SANE_Byte)(result[59] & 0xC0);
1524 
1525   mi->doc_size_code              = (SANE_Byte)result[60];
1526   /* we'll compute the max sizes after we know base resolution... */
1527 
1528   /* why are these things set in two places (and probably wrong anyway)? */
1529   mi->cont_settings              = (SANE_Int)((result[61] & 0xf0) >> 4);
1530   if ((SANE_Int)(result[72]))
1531     mi->cont_settings            = (SANE_Int)(result[72]);
1532   mi->min_contrast = -42;
1533   mi->max_contrast = (mi->cont_settings * 7) - 49;
1534 
1535   mi->exp_settings               = (SANE_Int)(result[61] & 0x0f);
1536   if ((SANE_Int)(result[73]))
1537     mi->exp_settings             = (SANE_Int)(result[73]);
1538   mi->min_exposure  = -18;
1539   mi->max_exposure  = (mi->exp_settings * 3) - 21;
1540 #if 0
1541   mi->contrast_vals              = (SANE_Int)(result[72]);
1542   mi->min_contrast = -42;
1543   mi->max_contrast =  49;
1544   if (mi->contrast_vals)
1545     mi->max_contrast = (mi->contrast_vals * 7) - 49;
1546 
1547   mi->exposure_vals              = (SANE_Int)(result[73]);
1548   mi->min_exposure  = -18;
1549   mi->max_exposure  =  21;
1550   if (mi->exposure_vals)
1551     mi->max_exposure  = (mi->exposure_vals * 3) - 21;
1552 #endif
1553 
1554   mi->model_code                 = (SANE_Byte)(result[62]);
1555   switch (mi->model_code) {
1556   case 0x16: /* the other ScanMaker 600ZS */
1557   case 0x50: /* ScanMaker II/IIXE */
1558   case 0x54: /* ScanMaker IISP    */
1559   case 0x55: /* ScanMaker IIER    */
1560   case 0x58: /* ScanMaker IIG     */
1561   case 0x5a: /* Agfa StudioScan (untested!)    */
1562   case 0x5f: /* ScanMaker E3      */
1563   case 0x56: /* ScanMaker A3t     */
1564   case 0x64: /* ScanMaker E2 (,Vobis RealScan) */
1565   case 0x65: /* Color PageWiz */
1566   case 0xC8: /* ScanMaker 600ZS */
1567     mi->base_resolution = 300;
1568     break;
1569   case 0x5b: /* Agfa StudioScan II/IIsi (untested!) */
1570     mi->base_resolution = 400;
1571     break;
1572   case 0x57: /* ScanMaker IIHR    */
1573   case 0x59: /* ScanMaker III     */
1574   case 0x5c: /* Agfa Arcus II     */
1575   case 0x5e: /* Agfa StudioStar   */
1576   case 0x63: /* ScanMaker E6      */
1577   case 0x66: /* ScanMaker E6 (new)*/
1578     mi->base_resolution = 600;
1579     break;
1580   case 0x51: /* ScanMaker 45t     */
1581   case 0x5d: /* Agfa DuoScan      */
1582     mi->base_resolution = 1000;
1583     break;
1584   case 0x52: /* ScanMaker 35t     */
1585     mi->base_resolution = 1828;
1586     break;
1587   case 0x62: /* ScanMaker 35t+, Polaroid 35/LE    */
1588     mi->base_resolution = 1950;
1589     break;
1590   default:
1591     mi->base_resolution = 300;
1592     DBG(15, "parse_inquiry:  Unknown base resolution for 0x%x!\n",
1593 	mi->model_code);
1594     break;
1595   }
1596 
1597   /* Our max_x,y is in pixels. `Some scanners think in 1/8", though.' */
1598   /* max pixel is, of course, total - 1                               */
1599   switch (mi->doc_size_code) {
1600   case 0x00:
1601     mi->max_x = 8.5 * mi->base_resolution - 1;
1602     mi->max_y = 14.0 * mi->base_resolution - 1;
1603     break;
1604   case 0x01:
1605     mi->max_x = 8.5 * mi->base_resolution - 1;
1606     mi->max_y = 11.0 * mi->base_resolution - 1;
1607     break;
1608   case 0x02:
1609     mi->max_x = 8.5 * mi->base_resolution - 1;
1610     mi->max_y = 11.69 * mi->base_resolution - 1;
1611     break;
1612   case 0x03:
1613     mi->max_x = 8.5 * mi->base_resolution - 1;
1614     mi->max_y = 13.0 * mi->base_resolution - 1;
1615     break;
1616   case 0x04:
1617     mi->max_x = 8.0 * mi->base_resolution - 1;
1618     mi->max_y = 10.0 * mi->base_resolution - 1;
1619     break;
1620   case 0x05:
1621     mi->max_x = 8.3 * mi->base_resolution - 1;
1622     mi->max_y = 14.0 * mi->base_resolution - 1;
1623     break;
1624   case 0x06:
1625     mi->max_x = 8.3 * mi->base_resolution - 1;
1626     mi->max_y = 13.5 * mi->base_resolution - 1;
1627     break;
1628   case 0x07:
1629     mi->max_x = 8.0 * mi->base_resolution - 1;
1630     mi->max_y = 14.0 * mi->base_resolution - 1;
1631     break;
1632   case 0x80:
1633     /* Slide format, size is mm */
1634     mi->max_x = (35.0 / MM_PER_INCH) * mi->base_resolution - 1;
1635     mi->max_y = (35.0 / MM_PER_INCH) * mi->base_resolution - 1;
1636     break;
1637   case 0x81:
1638     mi->max_x = 5.0 * mi->base_resolution - 1;
1639     mi->max_y = 5.0 * mi->base_resolution - 1;
1640     break;
1641   case 0x82:
1642     /* Slide format, size is mm */
1643     mi->max_x = (36.0 / MM_PER_INCH) * mi->base_resolution - 1;
1644     mi->max_y = (36.0 / MM_PER_INCH) * mi->base_resolution - 1;
1645     break;
1646   default:
1647     /* Undefined document format code */
1648       mi->max_x = mi->max_y = 0;
1649       DBG(15, "parse_inquiry:  Unknown doc_size_code!  0x%x\n",
1650 	  mi->doc_size_code);
1651   }
1652 
1653   /* create the proper range constraints, given the doc size */
1654   {
1655     /* we need base resolution in dots-per-millimeter... */
1656     float base_res_dpmm = (float) mi->base_resolution / MM_PER_INCH;
1657     mi->doc_x_range.min = SANE_FIX(0);
1658     mi->doc_x_range.max = SANE_FIX((float)mi->max_x / base_res_dpmm);
1659     mi->doc_x_range.quant = SANE_FIX(0);
1660     mi->doc_y_range.min = SANE_FIX(0);
1661     mi->doc_y_range.max = SANE_FIX((float)mi->max_y / base_res_dpmm);
1662     mi->doc_y_range.quant = SANE_FIX(0);
1663   }
1664 
1665   mi->source_options             = (SANE_Byte)(result[63]);
1666 
1667   mi->expanded_resolution        = (result[64] & 0x01);
1668   /* my E6 reports exp-res capability incorrectly */
1669   if ((mi->model_code == 0x66) || (mi->model_code == 0x63)) {
1670     mi->expanded_resolution = 0xFF;
1671     DBG(4, "parse_inquiry:  E6 falsely denies expanded resolution.\n");
1672   }
1673   /* the StudioScan II(si) does the expanded-mode aspect correction
1674      within the scanner... (do others too?) */
1675   if (mi->model_code == 0x5b) {
1676     DBG(4, "parse_inquiry:  does expanded-mode expansion internally.\n");
1677     mi->does_expansion = 1;
1678   } else
1679     mi->does_expansion = 0;
1680 
1681   mi->enhance_cap                = (result[65] & 0x03);
1682 
1683   /*
1684   switch (result[66] & 0x0F) {
1685   case 0x00: mi->max_lookup_size =     0; break;
1686   case 0x01: mi->max_lookup_size =   256; break;
1687   case 0x03: mi->max_lookup_size =  1024; break;
1688   case 0x05: mi->max_lookup_size =  4096; break;
1689   case 0x09: mi->max_lookup_size = 65536; break;
1690   default:
1691     mi->max_lookup_size = 0;
1692     DBG(15, "parse_inquiry:  Unknown gamma LUT size!  0x%x\n",
1693 	result[66]);
1694   }
1695   */
1696 
1697   /* This is not how the vague documentation specifies this register.
1698      We're going to take it literally here -- i.e. if the bit is
1699      set, the scanner supports the value, otherwise it doesn't.
1700      (The docs say all lower values are always supported.  This is
1701      not the case for the StudioScan IIsi, at least, which only
1702      specifies 0x02==1024-byte table, and only supports that, too.)
1703 
1704      All-in-all, it doesn't matter, since we take the largest
1705      allowed LUT size anyway.
1706   */
1707   if (result[66] & 0x08)
1708     mi->max_lookup_size = 65536;
1709   else if (result[66] & 0x04)
1710     mi->max_lookup_size = 4096;
1711   else if (result[66] & 0x02)
1712     mi->max_lookup_size = 1024;
1713   else if (result[66] & 0x01)
1714     mi->max_lookup_size = 256;
1715   else
1716     mi->max_lookup_size = 0;
1717 
1718   /* my E6 reports incorrectly */
1719   if ((mi->model_code == 0x66) || (mi->model_code == 0x63)) {
1720     mi->max_lookup_size = 1024;
1721     DBG(4, "parse_inquiry:  E6 falsely denies 1024-byte LUT.\n");
1722   }
1723 
1724   /*
1725   switch (result[66] >> 5) {
1726   case 0x00: mi->max_gamma_val =   255;  mi->gamma_size = 1;  break;
1727   case 0x01: mi->max_gamma_val =  1023;  mi->gamma_size = 2;  break;
1728   case 0x02: mi->max_gamma_val =  4095;  mi->gamma_size = 2;  break;
1729   case 0x03: mi->max_gamma_val = 65535;  mi->gamma_size = 2;  break;
1730   default:
1731     mi->max_gamma_val =     0;  mi->gamma_size = 0;
1732     DBG(15, "parse_inquiry:  Unknown gamma max val!  0x%x\n",
1733 	result[66]);
1734   }
1735   */
1736   switch (result[66] >> 5) {
1737   case 0x00: mi->max_gamma_bit_depth =  8;  mi->gamma_size = 1;  break;
1738   case 0x01: mi->max_gamma_bit_depth = 10;  mi->gamma_size = 2;  break;
1739   case 0x02: mi->max_gamma_bit_depth = 12;  mi->gamma_size = 2;  break;
1740   case 0x03: mi->max_gamma_bit_depth = 16;  mi->gamma_size = 2;  break;
1741   default:
1742     mi->max_gamma_bit_depth =  0;  mi->gamma_size = 0;
1743     DBG(15, "parse_inquiry:  Unknown gamma max val!  0x%x\n",
1744 	result[66]);
1745   }
1746 
1747   mi->fast_color_preview         = (SANE_Byte)(result[67] & 0x01);
1748   mi->xfer_format_select         = (SANE_Byte)(result[68] & 0x01);
1749   mi->color_sequence             = (SANE_Byte)(result[69] & 0x7f);
1750   mi->does_3pass                 = (SANE_Byte)(!(result[69] & 0x80));
1751   mi->does_mode1                 = (SANE_Byte)(result[71] & 0x01);
1752 
1753   mi->bit_formats                = (SANE_Byte)(result[74] & 0x0F);
1754   mi->extra_cap                  = (SANE_Byte)(result[75] & 0x07);
1755 
1756   /* XXXXXX a quick hack to disable any [pre/real]cal stuff for
1757      anything but an E6... */
1758   if (!((mi->model_code == 0x66) || (mi->model_code == 0x63))) {
1759     mi->extra_cap &= ~MI_EXCAP_DIS_RECAL;
1760     DBG(4, "parse_inquiry:  Not an E6 -- pretend recal cannot be disabled.\n");
1761   }
1762 
1763   /* The E2 lies... */
1764   if (mi->model_code == 0x64) {
1765     DBG(4, "parse_inquiry:  The E2 lies about it's 3-pass heritage.\n");
1766     mi->does_3pass = 1;
1767     mi->modes &= ~MI_MODES_ONEPASS;
1768   }
1769 
1770   return SANE_STATUS_GOOD;
1771 }
1772 
1773 
1774 
1775 /********************************************************************/
1776 /* Dump all we know about scanner to stderr                         */
1777 /********************************************************************/
1778 static SANE_Status
dump_inquiry(Microtek_Info * mi,unsigned char * result)1779 dump_inquiry(Microtek_Info *mi, unsigned char *result)
1780 {
1781   int i;
1782 
1783   DBG(15, "dump_inquiry...\n");
1784   DBG(1, " === SANE/Microtek backend v%d.%d.%d ===\n",
1785 	  MICROTEK_MAJOR, MICROTEK_MINOR, MICROTEK_PATCH);
1786   DBG(1, "========== Scanner Inquiry Block ========mm\n");
1787   for (i=0; i<96; ) {
1788     if (!(i % 16)) MDBG_INIT("");
1789     MDBG_ADD("%02x ", (int)result[i++]);
1790     if (!(i % 16)) MDBG_FINISH(1);
1791   }
1792   DBG(1, "========== Scanner Inquiry Report ==========\n");
1793   DBG(1, "===== Scanner ID...\n");
1794   DBG(1, "Device Type Code: 0x%02x\n", mi->device_type);
1795   DBG(1, "Model Code: 0x%02x\n", mi->model_code);
1796   DBG(1, "Vendor Name: '%s'   Model Name: '%s'\n",
1797 	  mi->vendor_id, mi->model_name);
1798   DBG(1, "Vendor Specific String: '%s'\n", mi->vendor_string);
1799   DBG(1, "Firmware Rev: '%s'\n", mi->revision_num);
1800   DBG(1,
1801 	  "SCSI F/W version: %1d.%1d     Scanner F/W version: %1d.%1d\n",
1802 	  mi->SCSI_firmware_ver_major, mi->SCSI_firmware_ver_minor,
1803 	  mi->scanner_firmware_ver_major, mi->scanner_firmware_ver_minor);
1804   DBG(1, "Response data format: 0x%02x\n", mi->response_data_format);
1805 
1806   DBG(1, "===== Imaging Capabilities...\n");
1807   DBG(1, "Modes:  %s%s%s%s%s%s%s\n",
1808 	  (mi->modes & MI_MODES_LINEART) ? "Lineart " : "",
1809 	  (mi->modes & MI_MODES_HALFTONE) ? "Halftone " : "",
1810 	  (mi->modes & MI_MODES_GRAY) ? "Gray " : "",
1811 	  (mi->modes & MI_MODES_COLOR) ? "Color " : "",
1812 	  (mi->modes & MI_MODES_TRANSMSV) ? "(X-msv) " : "",
1813 	  (mi->modes & MI_MODES_ONEPASS) ? "(OnePass) " : "",
1814 	  (mi->modes & MI_MODES_NEGATIVE) ? "(Negative) " : "");
1815   DBG(1,
1816 	  "Resolution Step Sizes: %s%s    Expanded Resolution Support? %s%s\n",
1817 	  (mi->res_step & MI_RESSTEP_1PER) ? "1% " : "",
1818 	  (mi->res_step & MI_RESSTEP_5PER) ? "5%" : "",
1819 	  (mi->expanded_resolution) ? "yes" : "no",
1820 	  (mi->expanded_resolution == 0xFF) ? "(but says no)" : "");
1821   DBG(1, "Supported Bits Per Sample: %s8 %s%s%s\n",
1822 	  (mi->bit_formats & MI_FMT_CAP_4BPP) ? "4 " : "",
1823 	  (mi->bit_formats & MI_FMT_CAP_10BPP) ? "10 " : "",
1824 	  (mi->bit_formats & MI_FMT_CAP_12BPP) ? "12 " : "",
1825 	  (mi->bit_formats & MI_FMT_CAP_16BPP) ? "16 " : "");
1826   DBG(1, "Max. document size code: 0x%02x\n",
1827 	  mi->doc_size_code);
1828   DBG(1, "Max. document size:  %d x %d pixels\n",
1829 	  mi->max_x, mi->max_y);
1830   DBG(1, "Frame units:  %s%s\n",
1831 	  (mi->unit_type & MI_UNIT_PIXELS) ? "pixels  " : "",
1832 	  (mi->unit_type & MI_UNIT_8TH_INCH) ? "1/8\"'s " : "");
1833   DBG(1, "# of built-in halftones: %d   Downloadable patterns? %s\n",
1834 	  mi->pattern_count, (mi->pattern_dwnld) ? "Yes" : "No");
1835 
1836   DBG(1, "Data Compression: %s%s\n",
1837 	  (mi->compress_type & MI_COMPRSS_HUFF) ? "huffman " : "",
1838 	  (mi->compress_type & MI_COMPRSS_RD) ? "read-data " : "");
1839   DBG(1, "Contrast Settings: %d   Exposure Settings: %d\n",
1840 	  mi->cont_settings, mi->exp_settings);
1841   DBG(1, "Adjustable Shadow/Highlight? %s   Adjustable Midtone? %s\n",
1842 	  (mi->enhance_cap & MI_ENH_CAP_SHADOW) ? "yes" : "no ",
1843 	  (mi->enhance_cap & MI_ENH_CAP_MIDTONE) ? "yes" : "no ");
1844   DBG(1, "Digital brightness/offset? %s\n",
1845 	  (mi->extra_cap & MI_EXCAP_OFF_CTL) ? "yes" : "no");
1846   /*
1847   fprintf(stderr,
1848 	  "Gamma Table Size: %d entries of %d bytes (max. value: %d)\n",
1849 	  mi->max_lookup_size, mi->gamma_size, mi->max_gamma_val);
1850   */
1851   DBG(1,
1852 	  "Gamma Table Size: %d entries of %d bytes (max. depth: %d)\n",
1853 	  mi->max_lookup_size, mi->gamma_size, mi->max_gamma_bit_depth);
1854 
1855   DBG(1, "===== Source Options...\n");
1856   DBG(1, "Feed type:  %s%s   ADF support? %s\n",
1857 	  (mi->feed_type & MI_FEED_FLATBED) ? "flatbed " : "",
1858 	  (mi->feed_type & MI_FEED_EDGEFEED) ? "edge-feed " : "",
1859 	  (mi->feed_type & MI_FEED_AUTOSUPP) ? "yes" : "no");
1860   DBG(1, "Document Feeder Support? %s   Feeder Backtracking? %s\n",
1861 	  (mi->source_options & MI_SRC_FEED_SUPP) ? "yes" : "no ",
1862 	  (mi->source_options & MI_SRC_FEED_BT) ? "yes" : "no ");
1863   DBG(1, "Feeder Installed? %s          Feeder Ready? %s\n",
1864 	  (mi->source_options & MI_SRC_HAS_FEED) ? "yes" : "no ",
1865 	  (mi->source_options & MI_SRC_FEED_RDY) ? "yes" : "no ");
1866   DBG(1, "Transparency Adapter Installed? %s\n",
1867 	  (mi->source_options & MI_SRC_HAS_TRANS) ? "yes" : "no ");
1868   /* GET_TRANS GET_FEED XXXXXXXXX */
1869   /* mt_SWslct ???? XXXXXXXXXXX */
1870   /*#define DOC_ON_FLATBED 0x00
1871     #define DOC_IN_FEEDER  0x01
1872     #define TRANSPARENCY   0x10
1873     */
1874   DBG(1, "Fast Color Prescan? %s\n",
1875 	  (mi->fast_color_preview) ? "yes" : "no");
1876   DBG(1, "Selectable Transfer Format? %s\n",
1877 	  (mi->xfer_format_select) ? "yes" : "no");
1878   MDBG_INIT("Color Transfer Sequence: ");
1879   switch (mi->color_sequence) {
1880   case MI_COLSEQ_PLANE:
1881     MDBG_ADD("plane-by-plane (3-pass)"); break;
1882   case MI_COLSEQ_PIXEL:
1883     MDBG_ADD("pixel-by-pixel RGB"); break;
1884   case MI_COLSEQ_RGB:
1885     MDBG_ADD("line-by-line, R-G-B sequence"); break;
1886   case MI_COLSEQ_NONRGB:
1887     MDBG_ADD("line-by-line, non-sequential with headers"); break;
1888   case MI_COLSEQ_2PIXEL:
1889     MDBG_ADD("2pixel-by-2pixel RRGGBB"); break;
1890   default:
1891     MDBG_ADD("UNKNOWN CODE (0x%02x)", mi->color_sequence);
1892   }
1893   MDBG_FINISH(1);
1894   /*  if (mi->modes & MI_MODES_ONEPASS) XXXXXXXXXXX */
1895   DBG(1, "Three pass scan support? %s\n",
1896 	  (mi->does_3pass ? "yes" : "no"));
1897   DBG(1, "ModeSelect-1 and ModeSense-1 Support? %s\n",
1898 	  (mi->does_mode1) ? "yes" : "no");
1899   DBG(1, "Can Disable Linearization Table? %s\n",
1900 	  (mi->extra_cap & MI_EXCAP_DIS_LNTBL) ? "yes" : "no");
1901   DBG(1, "Can Disable Start-of-Scan Recalibration? %s\n",
1902 	  (mi->extra_cap & MI_EXCAP_DIS_RECAL) ? "yes" : "no");
1903 
1904   DBG(1, "Internal expanded expansion? %s\n",
1905 	  mi->does_expansion ? "yes" : "no");
1906   /*
1907     fprintf(stderr, "cntr_vals = %d, min_cntr = %d, max_cntr = %d\n",
1908     cntr_vals, min_cntr, max_cntr);
1909     fprintf(stderr, "exp_vals = %d, min_exp = %d, max_exp = %d\n",
1910     exp_vals, min_exp, max_exp);
1911     */
1912   DBG(1, "====== End of Scanner Inquiry Report =======\n");
1913   return SANE_STATUS_GOOD;
1914 }
1915 
1916 
1917 /********************************************************************/
1918 /* Dump all we know about some unknown scanner to stderr            */
1919 /********************************************************************/
1920 static SANE_Status
dump_suspect_inquiry(unsigned char * result)1921 dump_suspect_inquiry(unsigned char *result)
1922 {
1923   int i;
1924   char vendor_id[9], model_name[17], revision_num[5];
1925   SANE_Byte device_type, model_code;
1926   SANE_Byte SCSI_firmware_ver_major, SCSI_firmware_ver_minor;
1927   SANE_Byte scanner_firmware_ver_major, scanner_firmware_ver_minor;
1928   SANE_Byte response_data_format;
1929 
1930   DBG(15, "dump_suspect_inquiry...\n");
1931   DBG(1, " === SANE/Microtek backend v%d.%d.%d ===\n",
1932 	  MICROTEK_MAJOR, MICROTEK_MINOR, MICROTEK_PATCH);
1933   DBG(1, "========== Scanner Inquiry Block ========mm\n");
1934   for (i=0; i<96; ) {
1935     if (!(i % 16)) MDBG_INIT("");
1936     MDBG_ADD("%02x ", (int)result[i++]);
1937     if (!(i % 16)) MDBG_FINISH(1);
1938   }
1939 #if 0
1940   for (i=0; i<96; i++) {
1941     if (!(i % 16) && (i)) fprintf(stderr, "\n");
1942     fprintf(stderr, "%02x ", (int)result[i]);
1943   }
1944   fprintf(stderr, "\n\n");
1945 #endif
1946   snprintf(vendor_id,     8 + 1, "%.*s",  8, (char *)&result[8]);
1947   snprintf(model_name,   16 + 1, "%.*s", 16, (char *)&result[16]);
1948   snprintf(revision_num,  4 + 1, "%.*s",  4, (char *)&result[32]);
1949   device_type                = (SANE_Byte)(result[0] & 0x1f);
1950   SCSI_firmware_ver_major    = (SANE_Byte)((result[1] & 0xf0) >> 4);
1951   SCSI_firmware_ver_minor    = (SANE_Byte)(result[1] & 0x0f);
1952   scanner_firmware_ver_major = (SANE_Byte)((result[2] & 0xf0) >> 4);
1953   scanner_firmware_ver_minor = (SANE_Byte)(result[2] & 0x0f);
1954   response_data_format       = (SANE_Byte)(result[3]);
1955   model_code                 = (SANE_Byte)(result[62]);
1956 
1957   DBG(1, "========== Scanner Inquiry Report ==========\n");
1958   DBG(1, "===== Scanner ID...\n");
1959   DBG(1, "Device Type Code: 0x%02x\n", device_type);
1960   DBG(1, "Model Code: 0x%02x\n", model_code);
1961   DBG(1, "Vendor Name: '%s'   Model Name: '%s'\n",
1962 	  vendor_id, model_name);
1963   DBG(1, "Firmware Rev: '%s'\n", revision_num);
1964   DBG(1,
1965 	  "SCSI F/W version: %1d.%1d     Scanner F/W version: %1d.%1d\n",
1966 	  SCSI_firmware_ver_major, SCSI_firmware_ver_minor,
1967 	  scanner_firmware_ver_major, scanner_firmware_ver_minor);
1968   DBG(1, "Response data format: 0x%02x\n", response_data_format);
1969   DBG(1, "====== End of Scanner Inquiry Report =======\n");
1970   return SANE_STATUS_GOOD;
1971 }
1972 
1973 
1974 /********************************************************************/
1975 /* Determine if device is a Microtek Scanner (from INQUIRY info)    */
1976 /********************************************************************/
1977 static SANE_Status
id_microtek(uint8_t * result,char ** model_string)1978 id_microtek(uint8_t *result, char **model_string)
1979 {
1980   SANE_Byte device_type, response_data_format;
1981   int forcewarn = 0;
1982 
1983   DBG(15, "id_microtek...\n");
1984   /* check device type first... */
1985   device_type = (SANE_Byte)(result[0] & 0x1f);
1986   if (device_type != 0x06) {
1987     DBG(15, "id_microtek:  not even a scanner:  dev_type = %d\n",
1988 	device_type);
1989     return SANE_STATUS_INVAL;
1990   }
1991   if (!(strncmp("MICROTEK", (char *)&(result[8]), 8)) ||
1992       !(strncmp("MII SC31", (char *)&(result[8]), 8)) ||  /* the IISP */
1993       !(strncmp("MII SC21", (char *)&(result[8]), 8)) ||  /* the 600ZS */
1994       !(strncmp("MII SC23", (char *)&(result[8]), 8)) ||  /* the other 600ZS */
1995       !(strncmp("MII SC25", (char *)&(result[8]), 8)) ||  /* some other 600GS */
1996       !(strncmp("AGFA    ", (char *)&(result[8]), 8)) ||  /* Arcus II */
1997       !(strncmp("Microtek", (char *)&(result[8]), 8)) ||  /* some 35t+'s */
1998       !(strncmp("Polaroid", (char *)&(result[8]), 8)) ||  /* SprintScan 35LE */
1999       !(strncmp("        ", (char *)&(result[8]), 8)) ) {
2000     switch (result[62]) {
2001     case 0x16 :
2002       *model_string = "ScanMaker 600ZS";    break;
2003     case 0x50 :
2004       *model_string = "ScanMaker II/IIXE";  break;
2005     case 0x51 :
2006       *model_string = "ScanMaker 45t";      break;
2007     case 0x52 :
2008       *model_string = "ScanMaker 35t";      break;
2009     case 0x54 :
2010       *model_string = "ScanMaker IISP";     break;
2011     case 0x55 :
2012       *model_string = "ScanMaker IIER";     break;
2013     case 0x56 :
2014       *model_string = "ScanMaker A3t";      break;
2015     case 0x57 :
2016       *model_string = "ScanMaker IIHR";     break;
2017     case 0x58 :
2018       *model_string = "ScanMaker IIG";      break;
2019     case 0x59 :
2020       *model_string = "ScanMaker III";      break;
2021     case 0x5A :
2022       *model_string = "Agfa StudioScan";    break;
2023     case 0x5B :
2024       *model_string = "Agfa StudioScan II"; break;
2025     case 0x5C :
2026       *model_string = "Agfa Arcus II";      break;
2027     case 0x5f :
2028       *model_string = "ScanMaker E3";       break;
2029     case 0x62 :
2030       if (!(strncmp("Polaroid", (char *)&(result[8]), 8)))
2031 	*model_string = "Polaroid SprintScan 35/LE";
2032       else
2033 	*model_string = "ScanMaker 35t+";
2034       break;
2035     case 0x63 :
2036     case 0x66 :
2037       *model_string = "ScanMaker E6";       break;
2038     case 0x64 : /* and "Vobis RealScan" */
2039       *model_string = "ScanMaker E2";       break;
2040     case 0x65:
2041       *model_string = "Color PageWiz";      break;
2042     case 0xC8:
2043       *model_string = "ScanMaker 600ZS";    break;
2044       /* the follow are listed in the docs, but are otherwise a mystery... */
2045     case 0x5D:
2046       *model_string = "Agfa DuoScan";  forcewarn = 1; break;
2047     case 0x5E:
2048       *model_string = "SS3";      forcewarn = 1; break;
2049     case 0x60:
2050       *model_string = "HR1";      forcewarn = 1; break;
2051     case 0x61:
2052       *model_string = "45T+";     forcewarn = 1; break;
2053     case 0x67:
2054       *model_string = "TR3";      forcewarn = 1; break;
2055     default :
2056       /* this might be a newer scanner, which uses the SCSI II command set. */
2057       /* that's unfortunate, but we'll warn the user anyway....             */
2058       response_data_format = (SANE_Byte)(result[3]);
2059       if (response_data_format == 0x02) {
2060 	DBG(15, "id_microtek:  (uses new SCSI II command set)\n");
2061 	if (DBG_LEVEL >= 15) {
2062 	  DBG(1, "\n");
2063 	  DBG(1, "\n");
2064 	  DBG(1, "\n");
2065 	  DBG(1, "========== Congratulations! ==========\n");
2066 	  DBG(1, "You appear to be the proud owner of a \n");
2067 	  DBG(1, "brand-new Microtek scanner, which uses\n");
2068 	  DBG(1, "a new SCSI II command set.            \n");
2069 	  DBG(1, "\n");
2070 	  DBG(1, "Try the `microtek2' backend instead.  \n");
2071 	  DBG(1, "\n");
2072 	  DBG(1, "\n");
2073 	  DBG(1, "\n");
2074 	}
2075       }
2076       return SANE_STATUS_INVAL;
2077     }
2078     if (forcewarn) {
2079       /* force debugging on, to encourage user to send in a report */
2080 #ifndef NDEBUG
2081       DBG_LEVEL = 1;
2082 #endif
2083       DBG(1, "\n");
2084       DBG(1, "\n");
2085       DBG(1, "\n");
2086       DBG(1, "========== Congratulations! ==========\n");
2087       DBG(1, "Your scanner appears to be supported  \n");
2088       DBG(1, "by the microtek backend.  However, it \n");
2089       DBG(1, "has never been tried before, and some \n");
2090       DBG(1, "parameters are bound to be wrong.     \n");
2091       DBG(1, "\n");
2092       DBG(1, "Please send the scanner inquiry log in\n");
2093       DBG(1, "its entirety to mtek-bugs@mir.com and \n");
2094       DBG(1, "include a description of the scanner, \n");
2095       DBG(1, "including the base optical resolution.\n");
2096       DBG(1, "\n");
2097       DBG(1, "You'll find complete instructions for \n");
2098       DBG(1, "submitting an error/debug log in the  \n");
2099       DBG(1, "'sane-microtek' man-page.             \n");
2100       DBG(1, "\n");
2101       DBG(1, "\n");
2102       DBG(1, "\n");
2103     }
2104     return SANE_STATUS_GOOD;
2105   }
2106   DBG(15, "id_microtek:  not microtek:  %d, %d, %d\n",
2107       strncmp("MICROTEK", (char *)&(result[8]), 8),
2108       strncmp("        ", (char *)&(result[8]), 8),
2109       result[62]);
2110   return SANE_STATUS_INVAL;
2111 }
2112 
2113 
2114 
2115 /********************************************************************/
2116 /* Try to attach a device as a Microtek scanner                     */
2117 /********************************************************************/
2118 static SANE_Status
attach_scanner(const char * devicename,Microtek_Device ** devp)2119 attach_scanner(const char *devicename, Microtek_Device **devp)
2120 {
2121   Microtek_Device *dev;
2122   int sfd;
2123   size_t size;
2124   unsigned char result[0x60];
2125   SANE_Status status;
2126   char *model_string;
2127   uint8_t inquiry[] = { 0x12, 0, 0, 0, 0x60, 0 };
2128 
2129   DBG(15,"attach_scanner:  %s\n", devicename);
2130   /* check if device is already known... */
2131   for (dev = first_dev; dev; dev = dev->next) {
2132     if (strcmp(dev->sane.name, devicename) == 0) {
2133       if (devp) *devp = dev;
2134       return SANE_STATUS_GOOD;
2135     }
2136   }
2137 
2138   /* open scsi device... */
2139   DBG(20, "attach_scanner:  opening %s\n", devicename);
2140   if (sanei_scsi_open(devicename, &sfd, sense_handler, NULL) != 0) {
2141     DBG(20, "attach_scanner:  open failed\n");
2142     return SANE_STATUS_INVAL;
2143   }
2144 
2145   /* say hello... */
2146   DBG(20, "attach_scanner:  sending INQUIRY\n");
2147   size = sizeof(result);
2148   status = sanei_scsi_cmd(sfd, inquiry, sizeof(inquiry), result, &size);
2149   sanei_scsi_close (sfd);
2150   if (status != SANE_STATUS_GOOD || size != 0x60) {
2151     DBG(20, "attach_scanner:  inquiry failed (%s)\n", sane_strstatus (status));
2152     return status;
2153   }
2154 
2155   if (id_microtek(result, &model_string) != SANE_STATUS_GOOD) {
2156       DBG(15, "attach_scanner:  device doesn't look like a Microtek scanner.");
2157       if (DBG_LEVEL >= 5) dump_suspect_inquiry(result);
2158       return SANE_STATUS_INVAL;
2159   }
2160 
2161   dev=malloc(sizeof(*dev));
2162   if (!dev) return SANE_STATUS_NO_MEM;
2163   memset(dev, 0, sizeof(*dev));
2164 
2165   parse_inquiry(&(dev->info), result);
2166   if (DBG_LEVEL > 0) dump_inquiry(&(dev->info), result);
2167 
2168   /* initialize dev structure */
2169   dev->sane.name   = strdup(devicename);
2170   dev->sane.vendor = "Microtek";
2171   dev->sane.model  = strdup(model_string);
2172   dev->sane.type   = "flatbed scanner";
2173 
2174   /* link into device list... */
2175   ++num_devices;
2176   dev->next = first_dev;
2177   first_dev = dev;
2178   if (devp) *devp = dev;
2179 
2180   DBG(15, "attach_scanner:  happy.\n");
2181 
2182   return SANE_STATUS_GOOD;
2183 }
2184 
2185 
2186 /********************************************************************/
2187 /* Attach a scanner (convenience wrapper for find_scanners...)      */
2188 /********************************************************************/
2189 static SANE_Status
attach_one(const char * dev)2190 attach_one (const char *dev)
2191 {
2192   attach_scanner (dev, 0);
2193   return SANE_STATUS_GOOD;
2194 }
2195 
2196 
2197 
2198 
2199 /********************************************************************/
2200 /* End a scan, and clean up afterwards                              */
2201 /********************************************************************/
end_scan(Microtek_Scanner * s,SANE_Status ostat)2202 static SANE_Status end_scan(Microtek_Scanner *s, SANE_Status ostat)
2203 {
2204   SANE_Status status;
2205 
2206   DBG(15, "end_scan...\n");
2207   if (s->scanning) {
2208     s->scanning = SANE_FALSE;
2209     /* stop the scanner */
2210     if (s->scan_started) {
2211       status = stop_scan(s);
2212       if (status != SANE_STATUS_GOOD)
2213 	DBG(23, "end_scan:  OY! on stop_scan\n");
2214       s->scan_started = SANE_FALSE;
2215     }
2216     /* close the SCSI device */
2217     if (s->sfd != -1) {
2218       sanei_scsi_close(s->sfd);
2219       s->sfd = -1;
2220     }
2221     /* free the buffers we malloc'ed */
2222     if (s->scsi_buffer != NULL) {
2223       free(s->scsi_buffer);
2224       s->scsi_buffer = NULL;
2225     }
2226     if (s->rb != NULL) {
2227       ring_free(s->rb);
2228       s->rb = NULL;
2229     }
2230   }
2231   /* if this -was- pass 3, or cancel, then we must be done */
2232   if ((s->this_pass == 3) || (s->cancel))
2233     s->this_pass = 0;
2234   return ostat;
2235 }
2236 
2237 
2238 
2239 /********************************************************************/
2240 /********************************************************************/
2241 /***** Scan-time operations                                     *****/
2242 /********************************************************************/
2243 /********************************************************************/
2244 
2245 
2246 /* number of lines of calibration data returned by scanner */
2247 #define STRIPS 12  /* well, that's what it seems to be for the E6 */
2248 
2249 
2250 /* simple comparison for the qsort below */
2251 
comparo(const void * a,const void * b)2252 static int comparo(const void *a, const void *b)
2253 {
2254   return (*(const int *)a - *(const int *)b);
2255 }
2256 
2257 
2258 /* extract values from scanlines and sort */
2259 
sort_values(int * result,uint8_t * scanline[],int pix)2260 static void sort_values(int *result, uint8_t *scanline[], int pix)
2261 {
2262   int i;
2263   for (i=0; i<STRIPS; i++) result[i] = (scanline[i])[pix];
2264   qsort(result, STRIPS, sizeof(result[0]), comparo);
2265 }
2266 
2267 
2268 /********************************************************************/
2269 /* Calculate the calibration data.                                  */
2270 /*  This seems to be, for each pixel of each R/G/B ccd, the average */
2271 /*  of the STRIPS# values read by the scanner, presumably off some  */
2272 /*  blank spot under the cover.                                     */
2273 /*  The raw scanner data does indeed resemble the intensity profile */
2274 /*  of a lamp.                                                      */
2275 /*  The sort is used to calc the median, which is used to remove    */
2276 /*  outliers in the data; maybe from dust under the cover?          */
2277 /********************************************************************/
2278 
2279 
calc_calibration(uint8_t * caldata,uint8_t * scanline[],int pixels)2280 static void calc_calibration(uint8_t *caldata, uint8_t *scanline[],
2281 			     int pixels)
2282 {
2283   int i,j;
2284   int sorted[STRIPS];
2285 
2286   DBG(23, ".calc_calibration...\n");
2287   for (i=0; i<pixels; i++) {
2288     int q1, q3;
2289     int bot, top;
2290     int sum = 0;
2291     int count = 0;
2292 
2293     sort_values(sorted, scanline, i);
2294     q1 = sorted[STRIPS / 4];       /* first quartile */
2295     q3 = sorted[STRIPS * 3 / 4];   /* third quartile */
2296     bot = q1 - 3 * (q3 - q1) / 2;  /* quick'n'easy bounds */
2297     top = q3 + 3 * (q3 - q1) / 2;
2298 
2299     for (j=0; j<STRIPS; j++) {
2300       if ((sorted[j] >= bot) && (sorted[j] <= top)) {
2301 	sum += sorted[j];
2302 	count++;
2303       }
2304     }
2305     if (count)
2306       caldata[i] = (sum + (count / 2)) / count;
2307     else {
2308       DBG(23, "zero: i=%d b/t=%d/%d ", i, bot, top);
2309       if (DBG_LEVEL >= 23) {
2310 	MDBG_INIT("");
2311 	for (j=0; j<STRIPS; j++) MDBG_ADD(" %3d", sorted[j]);
2312 	MDBG_FINISH(23);
2313       }
2314       caldata[i] = 0;
2315     }
2316   }
2317 }
2318 
2319 
2320 
2321 /********************************************************************/
2322 /* Calibrate scanner CCD, the "real" way.                           */
2323 /*  This stuff is not documented in the command set, but this is    */
2324 /*  what Microtek's TWAIN driver seems to do, more or less, on an   */
2325 /*  E6 at least.  What other scanners will do this???               */
2326 /********************************************************************/
2327 
2328 
do_real_calibrate(Microtek_Scanner * s)2329 static SANE_Status do_real_calibrate(Microtek_Scanner *s)
2330 {
2331   SANE_Status status, statusA;
2332   SANE_Int busy, linewidth, lines;
2333   size_t buffsize;
2334   uint8_t *input, *scanline[STRIPS], *combuff;
2335   uint8_t letter;
2336   int i, spot;
2337   int nmax, ntoget, nleft;
2338 
2339   DBG(10, "do_real_calibrate...\n");
2340 
2341   /* tell scanner to read it's little chart */
2342   if ((status = start_calibration(s)) != SANE_STATUS_GOOD) return status;
2343   if ((status = get_scan_status(s, &busy, &linewidth, &lines))
2344       != SANE_STATUS_GOOD) {
2345     DBG(23, "do_real_cal:  get_scan_status failed!\n");
2346     return status;
2347   }
2348   /* make room for data in and data out */
2349   input = calloc(STRIPS * 3 * linewidth, sizeof(input[0]));
2350   combuff = calloc(linewidth + 6, sizeof(combuff[0]));
2351   if ((input == NULL) || (combuff == NULL)) {
2352     DBG(23, "do_real_cal:  bad calloc %p %p\n",
2353         (void *) input, (void *) combuff);
2354     free(input);
2355     free(combuff);
2356     return SANE_STATUS_NO_MEM;
2357   }
2358   /* read STRIPS lines of R, G, B ccd data */
2359   nmax = SCSI_BUFF_SIZE / (3 * linewidth);
2360   DBG(23, "do_real_cal:  getting data (max=%d)\n", nmax);
2361   for (nleft = STRIPS, spot=0;
2362        nleft > 0;
2363        nleft -= ntoget, spot += buffsize) {
2364     ntoget = (nleft > nmax) ? nmax : nleft;
2365     buffsize = ntoget * 3 * linewidth;
2366     DBG(23, "...nleft %d  toget %d  size %lu  spot %d  input+spot %p\n",
2367         nleft, ntoget, (u_long) buffsize, spot, (void *) (input+spot));
2368     if ((statusA = read_scan_data(s, ntoget, input+spot, &buffsize))
2369 	!= SANE_STATUS_GOOD) {
2370       DBG(23, "...read scan failed\n");
2371       break;
2372     }
2373   }
2374   status = stop_scan(s);
2375   if ((statusA != SANE_STATUS_GOOD) || (status != SANE_STATUS_GOOD)) {
2376     free(input);
2377     free(combuff);
2378     return ((statusA != SANE_STATUS_GOOD) ? statusA : status);
2379   }
2380   /* calculate calibration data for each element and download */
2381   for (letter = 'R'; letter != 'X'; ) {
2382     DBG(23, "do_real_calibrate:  working on %c\n", letter);
2383     for (spot=0, i=0; spot < linewidth * STRIPS * 3; spot += linewidth) {
2384       if (input[spot+1] == letter) {
2385 	DBG(23, "   found %d (at %d)\n", i, spot);
2386 	if (i >= STRIPS) {
2387 	  DBG(23, "WHOA!!!  %i have already been found!\n", i);
2388 	  break;
2389 	}
2390 	scanline[i] = &(input[spot+2]);
2391 	i++;
2392       }
2393     }
2394     calc_calibration(combuff + 8, scanline, linewidth - 2);
2395     if ((status = download_calibration(s, combuff, letter, linewidth))
2396 	!= SANE_STATUS_GOOD) {
2397       DBG(23, "...download_calibration failed\n");
2398       free(input);
2399       free(combuff);
2400       return status;
2401     }
2402     switch (letter) {
2403     case 'R': letter = 'G'; break;
2404     case 'G': letter = 'B'; break;
2405     case 'B':
2406     default:  letter = 'X'; break;
2407     }
2408   }
2409   /* clean up */
2410   free(input);
2411   free(combuff);
2412   return SANE_STATUS_GOOD;
2413 }
2414 
2415 
2416 
2417 
2418 /********************************************************************/
2419 /* Cause scanner to calibrate, but don't really scan anything       */
2420 /*           (i.e. do everything but read data)                     */
2421 /********************************************************************/
do_precalibrate(SANE_Handle handle)2422 static SANE_Status do_precalibrate(SANE_Handle handle)
2423 {
2424   Microtek_Scanner *s = handle;
2425   SANE_Status status, statusA;
2426   SANE_Int busy, linewidth, lines;
2427 
2428   DBG(10, "do_precalibrate...\n");
2429 
2430   if ((status = wait_ready(s)) != SANE_STATUS_GOOD) return status;
2431   {
2432     SANE_Int y1 = s->y1;
2433     SANE_Int y2 = s->y2;
2434     /* some small range, but large enough to cause the scanner
2435        to think it'll scan *something*... */
2436     s->y1 = 0;
2437     s->y2 =
2438       (s->resolution > s->dev->info.base_resolution) ?
2439       4 : 4 * s->dev->info.base_resolution / s->resolution;
2440     status = scanning_frame(s);
2441     s->y1 = y1;
2442     s->y2 = y2;
2443     if (status != SANE_STATUS_GOOD) return status;
2444   }
2445 
2446   if (s->dev->info.source_options &
2447       (MI_SRC_FEED_BT | MI_SRC_HAS_TRANS |
2448        MI_SRC_FEED_SUPP | MI_SRC_HAS_FEED)) { /* ZZZZZZZZZZZ */
2449     if ((status = accessory(s)) != SANE_STATUS_GOOD) return status;
2450   }
2451   if ((status = mode_select(s)) != SANE_STATUS_GOOD) return status;
2452   /* why would we even try if this were not true?... */
2453   /*if (s->dev->info.extra_cap & MI_EXCAP_DIS_RECAL) */
2454   {
2455     SANE_Bool allow_calibrate = s->allow_calibrate;
2456     s->allow_calibrate = SANE_TRUE;
2457     status = mode_select_1(s);
2458     s->allow_calibrate = allow_calibrate;
2459     if (status != SANE_STATUS_GOOD) return status;
2460   }
2461 
2462   if ((status = wait_ready(s)) != SANE_STATUS_GOOD) return status;
2463   if ((status = start_scan(s))     != SANE_STATUS_GOOD) return status;
2464   if ((statusA = get_scan_status(s, &busy,
2465 				&linewidth, &lines)) != SANE_STATUS_GOOD) {
2466     DBG(10, "do_precalibrate:  get_scan_status fails\n");
2467   }
2468   if ((status = stop_scan(s)) != SANE_STATUS_GOOD) return status;
2469   if ((status = wait_ready(s)) != SANE_STATUS_GOOD) return status;
2470   DBG(10, "do_precalibrate done.\n");
2471   if (statusA != SANE_STATUS_GOOD)
2472     return statusA;
2473   else
2474     return SANE_STATUS_GOOD;
2475 }
2476 
2477 
2478 /********************************************************************/
2479 /* Calibrate scanner, if necessary; record results               */
2480 /********************************************************************/
finagle_precal(SANE_Handle handle)2481 static SANE_Status finagle_precal(SANE_Handle handle)
2482 {
2483   Microtek_Scanner *s = handle;
2484   SANE_Status status;
2485   int match;
2486 
2487   /* try to check if scanner has been reset  */
2488   /* if so, calibrate it
2489      (either for real, or via a fake scan, with calibration */
2490   /* (but only bother if you *could* disable calibration) */
2491   DBG(23, "finagle_precal...\n");
2492   if ((s->do_clever_precal) || (s->do_real_calib)) {
2493     if ((status = compare_mode_sense(s, &match)) != SANE_STATUS_GOOD)
2494       return status;
2495     if (((s->do_real_calib) && (!s->calib_once)) || /* user want recal */
2496 	(!match) ||                             /* or, possible reset  */
2497 	((s->mode == MS_MODE_COLOR) &&          /* or, other weirdness */
2498 	 (s->precal_record < MS_PRECAL_COLOR)) ||
2499 	((s->mode == MS_MODE_COLOR) &&
2500 	 (s->expandedresolution) &&
2501 	 (s->precal_record < MS_PRECAL_EXP_COLOR))) {
2502       DBG(23, "finagle_precal:  must precalibrate!\n");
2503       s->precal_record = MS_PRECAL_NONE;
2504       if (s->do_real_calib) {    /* do a real calibration if allowed */
2505 	if ((status = do_real_calibrate(s)) != SANE_STATUS_GOOD)
2506 	  return status;
2507       } else if (s->do_clever_precal) {/* otherwise do the fake-scan version */
2508 	if ((status = do_precalibrate(s)) != SANE_STATUS_GOOD)
2509 	  return status;
2510       }
2511       if (s->mode == MS_MODE_COLOR) {
2512 	if (s->expandedresolution)
2513 	  s->precal_record = MS_PRECAL_EXP_COLOR;
2514 	else
2515 	  s->precal_record = MS_PRECAL_COLOR;
2516       } else
2517 	s->precal_record = MS_PRECAL_GRAY;
2518     } else
2519       DBG(23, "finagle_precal:  no precalibrate necessary.\n");
2520   }
2521   return SANE_STATUS_GOOD;
2522 }
2523 
2524 
2525 
2526 /********************************************************************/
2527 /* Set pass-dependent parameters (for 3-pass color scans)           */
2528 /********************************************************************/
2529 static void
set_pass_parameters(SANE_Handle handle)2530 set_pass_parameters (SANE_Handle handle)
2531 {
2532   Microtek_Scanner *s = handle;
2533 
2534   if (s->threepasscolor) {
2535     s->this_pass += 1;
2536     DBG(23, "set_pass_parameters:  three-pass, on %d\n", s->this_pass);
2537     switch (s->this_pass) {
2538     case 1:
2539       s->filter = MS_FILT_RED;
2540       s->params.format = SANE_FRAME_RED;
2541       s->params.last_frame = SANE_FALSE;
2542       break;
2543     case 2:
2544       s->filter = MS_FILT_GREEN;
2545       s->params.format = SANE_FRAME_GREEN;
2546       s->params.last_frame = SANE_FALSE;
2547       break;
2548     case 3:
2549       s->filter = MS_FILT_BLUE;
2550       s->params.format = SANE_FRAME_BLUE;
2551       s->params.last_frame = SANE_TRUE;
2552       break;
2553     default:
2554       s->filter = MS_FILT_CLEAR;
2555       DBG(23, "set_pass_parameters:  What?!? pass %d = filter?\n",
2556 	  s->this_pass);
2557       break;
2558     }
2559   } else
2560     s->this_pass = 0;
2561 }
2562 
2563 
2564 
2565 /********************************************************************/
2566 /********************************************************************/
2567 /***** Packing functions                                        *****/
2568 /*****    ...process raw scanner bytes, and shove into          *****/
2569 /*****        the ring buffer                                   *****/
2570 /********************************************************************/
2571 /********************************************************************/
2572 
2573 
2574 /********************************************************************/
2575 /* Process flat (byte-by-byte) data                                 */
2576 /********************************************************************/
pack_flat_data(Microtek_Scanner * s,size_t nlines)2577 static SANE_Status pack_flat_data(Microtek_Scanner *s, size_t nlines)
2578 {
2579   SANE_Status status;
2580   ring_buffer *rb = s->rb;
2581   size_t nbytes = nlines * rb->bpl;
2582 
2583   size_t start = (rb->head_complete + rb->complete_count) % rb->size;
2584   size_t max_xfer =
2585     (start < rb->head_complete) ?
2586     (rb->head_complete - start) :
2587     (rb->size - start + rb->head_complete);
2588   size_t length = MIN(nbytes, max_xfer);
2589 
2590   if (nbytes > max_xfer) {
2591     DBG(23, "pack_flat: must expand ring, %lu + %lu\n",
2592 	(u_long)rb->size, (u_long)(nbytes - max_xfer));
2593     status = ring_expand(rb, (nbytes - max_xfer));
2594     if (status != SANE_STATUS_GOOD) return status;
2595   }
2596 
2597   if (s->doexpansion) {
2598     unsigned int line, bit;
2599     SANE_Byte *sb, *db, byte;
2600 
2601     size_t pos;
2602 
2603     sb = s->scsi_buffer;
2604     db = rb->base;
2605     pos = start;
2606 
2607     if (!(s->multibit)) {
2608       for (line=0; line<nlines; line++) {
2609 	size_t i;
2610 	double x1, x2, n1, n2;
2611 	for (i = 0, x1 = 0.0, x2 = s->exp_aspect, n1 = 0.0, n2 = floor(x2);
2612 	     i < rb->bpl;
2613 	     i++) {
2614 	  byte = 0;
2615 	  for (bit=0;
2616 	       bit < 8;
2617 	       bit++, x1 = x2, n1 = n2, x2 += s->exp_aspect, n2 = floor(x2)) {
2618 	    /* #define getbit(byte, index) (((byte)>>(index))&1) */
2619 	    byte |=
2620 	      ((
2621 		(x2 == n2) ?
2622 		(((sb[(int)n1 / 8])>>(7 - ((int)n1) % 8))&1) :
2623 		(((double)(((sb[(int)n1/8])>>(7-(int)n1%8))&1) * (n2 - x1) +
2624 		  (double)(((sb[(int)n2/8])>>(7-(int)n2%8))&1) * (x2 - n2)
2625 		  ) / s->exp_aspect)
2626 		) > 0.5) << (7 - bit);
2627 	  }
2628 	  db[pos] = byte;
2629 	  if (++pos >= rb->size) pos = 0;
2630 	}
2631 	sb += s->pixel_bpl;
2632       }
2633     } else { /* multibit scan (8 is assumed!) */
2634       for (line=0; line<nlines; line++) {
2635 	double x1, x2, n1, n2;
2636 	int i;
2637 	for (i = 0, x1 = 0.0, x2 = s->exp_aspect, n1 = 0.0, n2 = floor(x2);
2638 	     i < s->dest_ppl;
2639 	     i++, x1 = x2, n1 = n2, x2 += s->exp_aspect, n2 = floor(x2)) {
2640 	  db[pos] =
2641 	    (x2 == n2) ?
2642 	    sb[(int)n1] :
2643 	    (int)(((double)sb[(int)n1] * (n2 - x1) +
2644 		   (double)sb[(int)n2] * (x2 - n2)) / s->exp_aspect);
2645 	  if (++pos >= rb->size) pos = 0;
2646 	}
2647 	sb += s->pixel_bpl;
2648       }
2649     }
2650   } else {
2651     /* adjust for rollover!!! */
2652     if ((start + length) < rb->size) {
2653       memcpy(rb->base + start, s->scsi_buffer, length);
2654     } else {
2655       size_t chunk1 = rb->size - start;
2656       size_t chunk2 = length - chunk1;
2657       memcpy(rb->base + start, s->scsi_buffer, chunk1);
2658       memcpy(rb->base, s->scsi_buffer + chunk1, chunk2);
2659     }
2660   }
2661   rb->complete_count += length;
2662   return SANE_STATUS_GOOD;
2663 }
2664 
2665 
2666 /********************************************************************/
2667 /* Process sequential R-G-B scan lines (who uses this??? )          */
2668 /********************************************************************/
2669 static SANE_Status
pack_seqrgb_data(Microtek_Scanner * s,size_t nlines)2670 pack_seqrgb_data (Microtek_Scanner *s, size_t nlines)
2671 {
2672   ring_buffer *rb = s->rb;
2673   unsigned int seg;
2674   SANE_Byte *db = rb->base;
2675   SANE_Byte *sb = s->scsi_buffer;
2676   size_t completed;
2677   size_t spot;
2678   SANE_Byte id;
2679 
2680   {
2681     size_t ar, ag, ab; /* allowed additions */
2682     size_t dr, dg, db; /* additions which will occur */
2683     SANE_Status status;
2684 
2685     dr = dg = db = nlines * rb->bpl;
2686     ar = rb->size - (rb->complete_count + rb->red_extra * 3);
2687     ag = rb->size - (rb->complete_count + rb->green_extra * 3);
2688     ab = rb->size - (rb->complete_count + rb->blue_extra * 3);
2689     DBG(23, "pack_seq:  dr/ar: %lu/%lu  dg/ag: %lu/%lu  db/ab: %lu/%lu\n",
2690 	(u_long)dr, (u_long)ar,
2691 	(u_long)dg, (u_long)ag,
2692 	(u_long)db, (u_long)ab);
2693     if ((dr > ar) ||
2694 	(dg > ag) ||
2695 	(db > ab)) {
2696       size_t increase = 0;
2697       if (dr > ar) increase = (dr - ar);
2698       if (dg > ag) increase = MAX(increase, (dg - ag));
2699       if (db > ab) increase = MAX(increase, (db - ab));
2700       DBG(23, "pack_seq: must expand ring, %lu + %lu\n",
2701 	  (u_long)rb->size, (u_long)increase);
2702       status = ring_expand(rb, increase);
2703       if (status != SANE_STATUS_GOOD) return status;
2704     }
2705   }
2706 
2707   for (seg = 0, id = 0; seg < nlines * 3; seg++, id = (id+1)%3) {
2708     switch (id) {
2709     case 0: spot = rb->tail_red;  break;
2710     case 1: spot = rb->tail_green;  break;
2711     case 2: spot = rb->tail_blue;  break;
2712     default:
2713       DBG(18, "pack_seq:  missing scanline RGB header!\n");
2714       return SANE_STATUS_IO_ERROR;
2715     }
2716 
2717     if (s->doexpansion) {
2718       int i;
2719       double x1, x2, n1, n2;
2720       for (i = 0, x1 = 0.0, x2 = s->exp_aspect, n1 = 0.0, n2 = floor(x2);
2721 	   i < s->dest_ppl;
2722 	   i++, x1 = x2, n1 = n2, x2 += s->exp_aspect, n2 = floor(x2)) {
2723 	db[spot] =
2724 	  (x2 == n2) ?
2725 	  sb[(int)n1] :
2726 	  (int)(((double)sb[(int)n1] * (n2 - x1) +
2727 		 (double)sb[(int)n2] * (x2 - n2)) / s->exp_aspect);
2728 	if ((spot += 3) >= rb->size) spot -= rb->size;
2729       }
2730       sb += s->ppl;
2731     } else {
2732       size_t i;
2733       for (i=0; i < rb->ppl; i++) {
2734 	db[spot] = *sb;
2735 	sb++;
2736 	if ((spot += 3) >= rb->size) spot -= rb->size;
2737       }
2738     }
2739 
2740     switch (id) {
2741     case 0: rb->tail_red   = spot; rb->red_extra   += rb->ppl; break;
2742     case 1: rb->tail_green = spot; rb->green_extra += rb->ppl; break;
2743     case 2: rb->tail_blue  = spot; rb->blue_extra  += rb->ppl; break;
2744     }
2745   }
2746 
2747   completed = MIN(rb->red_extra, MIN(rb->green_extra, rb->blue_extra));
2748   rb->complete_count += completed * 3;  /* 3 complete bytes per pixel! */
2749   rb->red_extra   -= completed;
2750   rb->green_extra -= completed;
2751   rb->blue_extra  -= completed;
2752 
2753   DBG(18, "pack_seq:  extra r: %lu  g: %lu  b: %lu\n",
2754       (u_long)rb->red_extra,
2755       (u_long)rb->green_extra,
2756       (u_long)rb->blue_extra);
2757   DBG(18, "pack_seq:  completed: %lu  complete: %lu\n",
2758       (u_long)completed, (u_long)rb->complete_count);
2759 
2760   return SANE_STATUS_GOOD;
2761 }
2762 
2763 
2764 /********************************************************************/
2765 /* Process non-sequential R,G, and B scan-lines                     */
2766 /********************************************************************/
2767 static SANE_Status
pack_goofyrgb_data(Microtek_Scanner * s,size_t nlines)2768 pack_goofyrgb_data(Microtek_Scanner *s, size_t nlines)
2769 {
2770   ring_buffer *rb = s->rb;
2771   unsigned int seg; /* , i;*/
2772   SANE_Byte *db;
2773   SANE_Byte *sb = s->scsi_buffer;
2774   size_t completed;
2775   size_t spot;
2776   SANE_Byte id;
2777 
2778   /* prescan to decide if ring should be expanded */
2779   {
2780     size_t ar, ag, ab; /* allowed additions */
2781     size_t dr, dg, db; /* additions which will occur */
2782     SANE_Status status;
2783     SANE_Byte *pt;
2784 
2785     for (dr = dg = db = 0, seg = 0, pt = s->scsi_buffer + 1;
2786 	 seg < nlines * 3;
2787 	 seg++, pt += s->ppl + 2) {
2788       switch (*pt) {
2789       case 'R': dr += rb->bpl;  break;
2790       case 'G': dg += rb->bpl;  break;
2791       case 'B': db += rb->bpl;  break;
2792       }
2793     }
2794     ar = rb->size - (rb->complete_count + rb->red_extra * 3);
2795     ag = rb->size - (rb->complete_count + rb->green_extra * 3);
2796     ab = rb->size - (rb->complete_count + rb->blue_extra * 3);
2797     DBG(23, "pack_goofy:  dr/ar: %lu/%lu  dg/ag: %lu/%lu  db/ab: %lu/%lu\n",
2798 	(u_long)dr, (u_long)ar,
2799 	(u_long)dg, (u_long)ag,
2800 	(u_long)db, (u_long)ab);
2801     /* >, or >= ???????? */
2802     if ((dr > ar) ||
2803 	(dg > ag) ||
2804 	(db > ab)) {
2805       size_t increase = 0;
2806       if (dr > ar) increase = (dr - ar);
2807       if (dg > ag) increase = MAX(increase, (dg - ag));
2808       if (db > ab) increase = MAX(increase, (db - ab));
2809       DBG(23, "pack_goofy: must expand ring, %lu + %lu\n",
2810 	  (u_long)rb->size, (u_long)increase);
2811       status = ring_expand(rb, increase);
2812       if (status != SANE_STATUS_GOOD) return status;
2813     }
2814   }
2815 
2816   db = rb->base;
2817   for (seg = 0; seg < nlines * 3; seg++) {
2818     sb++; /* skip first byte in line (two byte header) */
2819     id = *sb;
2820     switch (id) {
2821     case 'R': spot = rb->tail_red;  break;
2822     case 'G': spot = rb->tail_green;  break;
2823     case 'B': spot = rb->tail_blue;  break;
2824     default:
2825       DBG(18, "pack_goofy:  missing scanline RGB header!\n");
2826       return SANE_STATUS_IO_ERROR;
2827     }
2828     sb++; /* skip the other header byte */
2829 
2830     if (s->doexpansion) {
2831       int i;
2832       double x1, x2, n1, n2;
2833       for (i = 0, x1 = 0.0, x2 = s->exp_aspect, n1 = 0.0, n2 = floor(x2);
2834 	   i < s->dest_ppl;
2835 	   i++, x1 = x2, n1 = n2, x2 += s->exp_aspect, n2 = floor(x2)) {
2836 	db[spot] =
2837 	  (x2 == n2) ?
2838 	  sb[(int)n1] :
2839 	  (int)(((double)sb[(int)n1] * (n2 - x1) +
2840 		 (double)sb[(int)n2] * (x2 - n2)) / s->exp_aspect);
2841 	if ((spot += 3) >= rb->size) spot -= rb->size;
2842       }
2843       sb += s->ppl;
2844     } else {
2845       unsigned int i;
2846       for (i=0; i < rb->ppl; i++) {
2847 	db[spot] = *sb;
2848 	sb++;
2849 	if ((spot += 3) >= rb->size) spot -= rb->size;
2850       }
2851     }
2852     switch (id) {
2853     case 'R': rb->tail_red   = spot; rb->red_extra   += rb->ppl; break;
2854     case 'G': rb->tail_green = spot; rb->green_extra += rb->ppl; break;
2855     case 'B': rb->tail_blue  = spot; rb->blue_extra  += rb->ppl; break;
2856     }
2857   }
2858 
2859   completed = MIN(rb->red_extra, MIN(rb->green_extra, rb->blue_extra));
2860   rb->complete_count += completed * 3;  /* 3 complete bytes per pixel! */
2861   rb->red_extra   -= completed;
2862   rb->green_extra -= completed;
2863   rb->blue_extra  -= completed;
2864 
2865   DBG(18, "pack_goofy:  extra r: %lu  g: %lu  b: %lu\n",
2866       (u_long)rb->red_extra,
2867       (u_long)rb->green_extra,
2868       (u_long)rb->blue_extra);
2869   DBG(18, "pack_goofy:  completed: %lu  complete: %lu\n",
2870       (u_long)completed, (u_long)rb->complete_count);
2871 
2872   return SANE_STATUS_GOOD;
2873 }
2874 
2875 
2876 
2877 /********************************************************************/
2878 /* Process R1R2-G1G2-B1B2 double pixels (AGFA StudioStar)           */
2879 /********************************************************************/
2880 
2881 static SANE_Status
pack_seq2r2g2b_data(Microtek_Scanner * s,size_t nlines)2882 pack_seq2r2g2b_data(Microtek_Scanner *s, size_t nlines)
2883 {
2884   SANE_Status status;
2885   ring_buffer *rb = s->rb;
2886   size_t nbytes = nlines * rb->bpl;
2887 
2888   size_t start = (rb->head_complete + rb->complete_count) % rb->size;
2889   size_t max_xfer =
2890     (start < rb->head_complete) ?
2891     (rb->head_complete - start) :
2892     (rb->size - start + rb->head_complete);
2893   size_t length = MIN(nbytes, max_xfer);
2894 
2895   if (nbytes > max_xfer) {
2896     DBG(23, "pack_2r2g2b: must expand ring, %lu + %lu\n",
2897 	(u_long)rb->size, (u_long)(nbytes - max_xfer));
2898     status = ring_expand(rb, (nbytes - max_xfer));
2899     if (status != SANE_STATUS_GOOD) return status;
2900   }
2901   {
2902     unsigned int line;
2903     int p;
2904     size_t pos = start;
2905     SANE_Byte *sb = s->scsi_buffer;
2906     SANE_Byte *db = rb->base;
2907 
2908     for (line = 0; line < nlines; line++) {
2909       for (p = 0; p < s->dest_ppl; p += 2){
2910 	/* first pixel */
2911 	db[pos] = sb[0];
2912 	if (++pos >= rb->size) pos = 0; /* watch out for ringbuff end? */
2913 	db[pos] = sb[2];
2914 	if (++pos >= rb->size) pos = 0;
2915 	db[pos] = sb[4];
2916 	if (++pos >= rb->size) pos = 0;
2917 	/* second pixel */
2918 	db[pos] = sb[1];
2919 	if (++pos >= rb->size) pos = 0;
2920 	db[pos] = sb[3];
2921 	if (++pos >= rb->size) pos = 0;
2922 	db[pos] = sb[5];
2923 	if (++pos >= rb->size) pos = 0;
2924 	sb += 6;
2925       }
2926     }
2927   }
2928   rb->complete_count += length;
2929   return SANE_STATUS_GOOD;
2930 }
2931 
2932 
2933 
2934 /********************************************************************/
2935 /********************************************************************/
2936 /***** the basic scanning chunks for sane_read()                *****/
2937 /********************************************************************/
2938 /********************************************************************/
2939 
2940 
2941 /********************************************************************/
2942 /* Request bytes from scanner (and put in scsi_buffer)              */
2943 /********************************************************************/
2944 static SANE_Status
read_from_scanner(Microtek_Scanner * s,int * nlines)2945 read_from_scanner (Microtek_Scanner *s, int *nlines)
2946 {
2947   SANE_Status status;
2948   SANE_Int busy, linewidth, remaining;
2949   size_t buffsize;
2950 
2951   DBG(23, "read_from_scanner...\n");
2952   if (s->unscanned_lines > 0) {
2953     status = get_scan_status(s, &busy, &linewidth, &remaining);
2954     if (status != SANE_STATUS_GOOD) {
2955       DBG(18, "read_from_scanner:  bad get_scan_status!\n");
2956       return status;
2957     }
2958     DBG(18, "read_from_scanner: gss busy, linewidth, remaining:  %d, %d, %d\n",
2959 	busy, linewidth, remaining);
2960   } else {
2961     DBG(18, "read_from_scanner: no gss/no unscanned\n");
2962     remaining = 0;
2963   }
2964 
2965   *nlines = MIN(remaining, s->max_scsi_lines);
2966   DBG(18, "sane_read:  max_scsi: %d, rem: %d, nlines: %d\n",
2967       s->max_scsi_lines, remaining, *nlines);
2968 
2969   /* grab them bytes! (only if the scanner still has bytes to give...) */
2970   if (*nlines > 0) {
2971     buffsize = *nlines * (s->pixel_bpl + s->header_bpl);/* == "* linewidth" */
2972     status = read_scan_data(s, *nlines, s->scsi_buffer, &buffsize);
2973     if (status != SANE_STATUS_GOOD) {
2974       DBG(18, "sane_read:  bad read_scan_data!\n");
2975       return status;
2976     }
2977     s->unscanned_lines -= *nlines;
2978     DBG(18, "sane_read:  buffsize: %lu,  unscanned: %d\n",
2979         (u_long) buffsize, s->unscanned_lines);
2980   }
2981   return SANE_STATUS_GOOD;
2982 }
2983 
2984 
2985 
2986 /********************************************************************/
2987 /* Process scanner bytes, and shove in ring_buffer                  */
2988 /********************************************************************/
2989 static SANE_Status
pack_into_ring(Microtek_Scanner * s,int nlines)2990 pack_into_ring(Microtek_Scanner *s, int nlines)
2991 {
2992   SANE_Status status;
2993 
2994   DBG(23, "pack_into_ring...\n");
2995   switch (s->line_format) {
2996   case MS_LNFMT_FLAT:
2997     status = pack_flat_data(s, nlines);  break;
2998   case MS_LNFMT_SEQ_RGB:
2999     status = pack_seqrgb_data(s, nlines); break;
3000   case MS_LNFMT_GOOFY_RGB:
3001     status = pack_goofyrgb_data(s, nlines); break;
3002   case MS_LNFMT_SEQ_2R2G2B:
3003     status = pack_seq2r2g2b_data(s, nlines); break;
3004   default:
3005     status = SANE_STATUS_JAMMED;
3006   }
3007   return status;
3008 }
3009 
3010 
3011 
3012 /********************************************************************/
3013 /* Pack processed image bytes into frontend destination buffer      */
3014 /********************************************************************/
3015 static SANE_Int
pack_into_dest(SANE_Byte * dest_buffer,size_t dest_length,ring_buffer * rb)3016 pack_into_dest(SANE_Byte *dest_buffer, size_t dest_length, ring_buffer *rb)
3017 {
3018   size_t ret_length = MIN(rb->complete_count, dest_length);
3019 
3020   DBG(23, "pack_into_dest...\n");
3021   DBG(23, "pack_into_dest:  rl: %lu  sz: %lu  hc: %lu\n",
3022       (u_long)ret_length, (u_long)rb->size, (u_long)rb->head_complete);
3023   /* adjust for rollover!!! */
3024   if ((rb->head_complete + ret_length) < rb->size) {
3025     memcpy(dest_buffer, rb->base + rb->head_complete, ret_length);
3026     rb->head_complete += ret_length;
3027   } else {
3028     size_t chunk1  = rb->size - rb->head_complete;
3029     size_t chunk2 = ret_length - chunk1;
3030     memcpy(dest_buffer, rb->base + rb->head_complete, chunk1);
3031     memcpy(dest_buffer + chunk1, rb->base, chunk2);
3032     rb->head_complete = chunk2;
3033   }
3034   rb->complete_count -= ret_length;
3035   return ret_length;
3036 }
3037 
3038 
3039 
3040 /********************************************************************/
3041 /********************************************************************/
3042 /****** "Registered" SANE API Functions *****************************/
3043 /********************************************************************/
3044 /********************************************************************/
3045 
3046 
3047 /********************************************************************/
3048 /* sane_init()                                                      */
3049 /********************************************************************/
3050 SANE_Status
sane_init(SANE_Int * version_code,SANE_Auth_Callback authorize)3051 sane_init(SANE_Int *version_code, SANE_Auth_Callback authorize)
3052 {
3053   char dev_name[PATH_MAX];
3054   size_t len;
3055   FILE *fp;
3056 
3057   (void) authorize;
3058   DBG_INIT();
3059   DBG(1, "sane_init:  MICROTEK says hello! (v%d.%d.%d)\n",
3060       MICROTEK_MAJOR, MICROTEK_MINOR, MICROTEK_PATCH);
3061   /* return the SANE version we got compiled under */
3062   if (version_code)
3063     *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0);
3064 
3065   /* parse config file */
3066   fp = sanei_config_open (MICROTEK_CONFIG_FILE);
3067   if (!fp) {
3068     /* default to /dev/scanner instead of insisting on config file */
3069     DBG(1, "sane_init:  missing config file '%s'\n", MICROTEK_CONFIG_FILE);
3070     attach_scanner("/dev/scanner", 0);
3071     return SANE_STATUS_GOOD;
3072   }
3073   while (sanei_config_read(dev_name, sizeof (dev_name), fp)) {
3074     DBG(23, "sane_init:  config-> %s\n", dev_name);
3075     if (dev_name[0] == '#') continue;	/* ignore comments */
3076     if (!(strncmp("noprecal", dev_name, 8))) {
3077       DBG(23,
3078 	  "sane_init:  Clever Precalibration will be forcibly disabled...\n");
3079       inhibit_clever_precal = SANE_TRUE;
3080       continue;
3081     }
3082     if (!(strncmp("norealcal", dev_name, 9))) {
3083       DBG(23,
3084 	  "sane_init:  Real calibration will be forcibly disabled...\n");
3085       inhibit_real_calib = SANE_TRUE;
3086       continue;
3087     }
3088     len = strlen (dev_name);
3089     if (!len) continue;			/* ignore empty lines */
3090     sanei_config_attach_matching_devices (dev_name, attach_one);
3091     }
3092   fclose (fp);
3093   return SANE_STATUS_GOOD;
3094 }
3095 
3096 
3097 
3098 /********************************************************************/
3099 /* sane_get_devices                                                 */
3100 /********************************************************************/
3101 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)3102 sane_get_devices(const SANE_Device ***device_list,
3103 		 SANE_Bool local_only)
3104 {
3105   Microtek_Device *dev;
3106   int i;
3107 
3108   (void) local_only;
3109   DBG(10, "sane_get_devices\n");
3110   /* we keep an internal copy */
3111   if (devlist)
3112     free(devlist);  /* hmm, free it if we want a new one, I guess.  YYYYY*/
3113 
3114   devlist = malloc((num_devices + 1) * sizeof(devlist[0]));
3115   if (!devlist) return SANE_STATUS_NO_MEM;
3116 
3117   for (i=0, dev=first_dev; i < num_devices; dev = dev->next)
3118     devlist[i++] = &dev->sane;
3119   devlist[i++] = 0;
3120 
3121   *device_list = devlist;
3122   return SANE_STATUS_GOOD;
3123 }
3124 
3125 
3126 
3127 /********************************************************************/
3128 /* sane_open                                                        */
3129 /********************************************************************/
3130 SANE_Status
sane_open(SANE_String_Const devicename,SANE_Handle * handle)3131 sane_open(SANE_String_Const devicename,
3132 	  SANE_Handle *handle)
3133 {
3134   Microtek_Scanner *scanner;
3135   Microtek_Device *dev;
3136   SANE_Status status;
3137 
3138   DBG(10, "sane_open\n");
3139   /* find device... */
3140   DBG(23, "sane_open:  find device...\n");
3141   if (devicename[0]) {
3142     for (dev = first_dev; dev; dev = dev->next) {
3143       if (strcmp(dev->sane.name, devicename) == 0)
3144 	break;
3145     }
3146     if (!dev) {  /* not in list, try manually... */
3147       status = attach_scanner(devicename, &dev);
3148       if (status != SANE_STATUS_GOOD) return status;
3149     }
3150   } else {  /* no device specified, so use first */
3151     dev = first_dev;
3152   }
3153   if (!dev) return SANE_STATUS_INVAL;
3154 
3155   /* create a scanner... */
3156   DBG(23, "sane_open:  create scanner...\n");
3157   scanner = malloc(sizeof(*scanner));
3158   if (!scanner) return SANE_STATUS_NO_MEM;
3159   memset(scanner, 0, sizeof(*scanner));
3160 
3161   /* initialize scanner dependent stuff */
3162   DBG(23, "sane_open:  initialize scanner dependent stuff...\n");
3163   /* ZZZZZZZZZZZZZZ */
3164   scanner->unit_type =
3165     (dev->info.unit_type & MI_UNIT_PIXELS) ? MS_UNIT_PIXELS : MS_UNIT_18INCH;
3166   scanner->res_type =
3167     (dev->info.res_step & MI_RESSTEP_1PER) ? MS_RES_1PER : MS_RES_5PER;
3168   scanner->midtone_support =
3169     (dev->info.enhance_cap & MI_ENH_CAP_MIDTONE) ? SANE_TRUE : SANE_FALSE;
3170   scanner->paper_length =
3171     (scanner->unit_type == MS_UNIT_PIXELS) ?
3172     dev->info.max_y :
3173     (SANE_Int)((double)dev->info.max_y * 8.0 /
3174 	       (double)dev->info.base_resolution);
3175   /*
3176     (SANE_Int)(SANE_UNFIX(dev->info.max_y) * dev->info.base_resolution) :
3177     (SANE_Int)(SANE_UNFIX(dev->info.max_y) * 8);
3178     ZZZZZZZ */
3179   scanner->bright_r = 0;
3180   scanner->bright_g = 0;
3181   scanner->bright_b = 0;
3182 
3183   /* calibration shenanigans */
3184   if ((dev->info.extra_cap & MI_EXCAP_DIS_RECAL) &&
3185       (!(inhibit_real_calib))) {
3186     DBG(23, "sane_open:  Real calibration enabled.\n");
3187     scanner->allow_calibrate = SANE_FALSE;
3188     scanner->do_real_calib = SANE_TRUE;
3189     scanner->do_clever_precal = SANE_FALSE;
3190   } else if ((dev->info.extra_cap & MI_EXCAP_DIS_RECAL) &&
3191 	     (!(inhibit_clever_precal))) {
3192     DBG(23, "sane_open:  Clever precalibration enabled.\n");
3193     scanner->allow_calibrate = SANE_FALSE;
3194     scanner->do_real_calib = SANE_FALSE;
3195     scanner->do_clever_precal = SANE_TRUE;
3196   } else {
3197     DBG(23, "sane_open:  All calibration routines disabled.\n");
3198     scanner->allow_calibrate = SANE_TRUE;
3199     scanner->do_real_calib = SANE_FALSE;
3200     scanner->do_clever_precal = SANE_FALSE;
3201   }
3202 
3203   scanner->onepass = (dev->info.modes & MI_MODES_ONEPASS);
3204   scanner->allowbacktrack = SANE_TRUE;  /* ??? XXXXXXX */
3205   scanner->reversecolors = SANE_FALSE;
3206   scanner->fastprescan = SANE_FALSE;
3207   scanner->bits_per_color = 8;
3208 
3209   /* init gamma tables */
3210   if (dev->info.max_lookup_size) {
3211     int j, v, max_entry;
3212     DBG(23, "sane_open:  init gamma tables...\n");
3213     scanner->gamma_entries = dev->info.max_lookup_size;
3214     scanner->gamma_entry_size = dev->info.gamma_size;
3215     scanner->gamma_bit_depth = dev->info.max_gamma_bit_depth;
3216     max_entry = (1 << scanner->gamma_bit_depth) - 1;
3217     scanner->gamma_entry_range.min = 0;
3218     scanner->gamma_entry_range.max = max_entry;
3219     scanner->gamma_entry_range.quant = 1;
3220 
3221     scanner->gray_lut  = calloc(scanner->gamma_entries,
3222 			       sizeof(scanner->gray_lut[0]));
3223     scanner->red_lut   = calloc(scanner->gamma_entries,
3224 			       sizeof(scanner->red_lut[0]));
3225     scanner->green_lut = calloc(scanner->gamma_entries,
3226 			       sizeof(scanner->green_lut[0]));
3227     scanner->blue_lut  = calloc(scanner->gamma_entries,
3228 			       sizeof(scanner->blue_lut[0]));
3229     if ((scanner->gray_lut == NULL) ||
3230 	(scanner->red_lut == NULL) ||
3231 	(scanner->green_lut == NULL) ||
3232 	(scanner->blue_lut == NULL)) {
3233       DBG(23, "sane_open:  unable to allocate space for %d-entry LUT's;\n",
3234 	  scanner->gamma_entries);
3235       DBG(23, "            so, gamma tables now DISABLED.\n");
3236       free(scanner->gray_lut);
3237       free(scanner->red_lut);
3238       free(scanner->green_lut);
3239       free(scanner->blue_lut);
3240     }
3241     for (j=0; j<scanner->gamma_entries; j += scanner->gamma_entry_size) {
3242       v = (SANE_Int)
3243 	((double) j * (double) max_entry /
3244 	 ((double) scanner->gamma_entries - 1.0) + 0.5);
3245       scanner->gray_lut[j] = v;
3246       scanner->red_lut[j] = v;
3247       scanner->green_lut[j] = v;
3248       scanner->blue_lut[j] = v;
3249     }
3250   } else {
3251     DBG(23, "sane_open:  NO gamma tables.  (max size = %lu)\n",
3252 	(u_long)dev->info.max_lookup_size);
3253     scanner->gamma_entries = 0;
3254     scanner->gray_lut  = NULL;
3255     scanner->red_lut   = NULL;
3256     scanner->green_lut = NULL;
3257     scanner->blue_lut  = NULL;
3258   }
3259 
3260   DBG(23, "sane_open:  init pass-time variables...\n");
3261   scanner->scanning = SANE_FALSE;
3262   scanner->this_pass = 0;
3263   scanner->sfd = -1;
3264   scanner->dev = dev;
3265   scanner->sense_flags = 0;
3266   scanner->scan_started = SANE_FALSE;
3267   scanner->woe = SANE_FALSE;
3268   scanner->cancel = SANE_FALSE;
3269 
3270   DBG(23, "sane_open:  init clever cache...\n");
3271   /* clear out that clever cache, so it doesn't match anything */
3272   {
3273     int j;
3274     for (j=0; j<10; j++)
3275       scanner->mode_sense_cache[j] = 0;
3276     scanner->precal_record = MS_PRECAL_NONE;
3277   }
3278 
3279   DBG(23, "sane_open:  initialize options:  \n");
3280   if ((status = init_options(scanner)) != SANE_STATUS_GOOD) return status;
3281 
3282   scanner->next = first_handle;
3283   first_handle = scanner;
3284   *handle = scanner;
3285   return SANE_STATUS_GOOD;
3286 }
3287 
3288 
3289 
3290 /********************************************************************/
3291 /* sane_close                                                       */
3292 /********************************************************************/
3293 void
sane_close(SANE_Handle handle)3294 sane_close (SANE_Handle handle)
3295 {
3296   Microtek_Scanner *ms = handle;
3297 
3298   DBG(10, "sane_close...\n");
3299   /* free malloc'ed stuff (strdup counts too!) */
3300   free((void *) ms->sod[OPT_MODE].constraint.string_list);
3301   free((void *) ms->sod[OPT_SOURCE].constraint.string_list);
3302   free(ms->val[OPT_MODE].s);
3303   free(ms->val[OPT_HALFTONE_PATTERN].s);
3304   free(ms->val[OPT_SOURCE].s);
3305   free(ms->val[OPT_CUSTOM_GAMMA].s);
3306   free(ms->gray_lut);
3307   free(ms->red_lut);
3308   free(ms->green_lut);
3309   free(ms->blue_lut);
3310   /* remove Scanner from linked list */
3311   if (first_handle == ms)
3312     first_handle = ms->next;
3313   else {
3314     Microtek_Scanner *ts = first_handle;
3315     while ((ts != NULL) && (ts->next != ms)) ts = ts->next;
3316     ts->next = ts->next->next; /* == ms->next */
3317   }
3318   /* finally, say goodbye to the Scanner */
3319   free(ms);
3320 }
3321 
3322 
3323 
3324 /********************************************************************/
3325 /* sane_get_option_descriptor                                       */
3326 /********************************************************************/
3327 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle,SANE_Int option)3328 sane_get_option_descriptor (SANE_Handle handle,
3329 			    SANE_Int option)
3330 {
3331   Microtek_Scanner *scanner = handle;
3332 
3333   DBG(96, "sane_get_option_descriptor (%d)...\n", option);
3334   if ((unsigned)option >= NUM_OPTIONS) return NULL;
3335   return &(scanner->sod[option]);
3336 }
3337 
3338 
3339 
3340 /********************************************************************/
3341 /* sane_control_option                                              */
3342 /********************************************************************/
3343 SANE_Status
sane_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * value,SANE_Int * info)3344 sane_control_option (SANE_Handle handle,
3345 		     SANE_Int option,
3346 		     SANE_Action action,
3347 		     void *value,
3348 		     SANE_Int *info)
3349 {
3350   Microtek_Scanner *scanner = handle;
3351   SANE_Option_Descriptor *sod;
3352   Option_Value  *val;
3353   SANE_Status status;
3354 
3355   DBG(96, "sane_control_option (opt=%d,act=%d,val=%p,info=%p)\n",
3356       option, action, value, (void*) info);
3357 
3358   sod = scanner->sod;
3359   val = scanner->val;
3360 
3361   /* no changes while in mid-pass! */
3362   if (scanner->scanning) return SANE_STATUS_DEVICE_BUSY;
3363   /* and... no changes while in middle of three-pass series! */
3364   if (scanner->this_pass != 0) return SANE_STATUS_DEVICE_BUSY;
3365 
3366   if ( ((option >= NUM_OPTIONS) || (option < 0)) ||
3367        (!SANE_OPTION_IS_ACTIVE(scanner->sod[option].cap)) )
3368     return SANE_STATUS_INVAL;
3369 
3370   if (info) *info = 0;
3371 
3372   /* choose by action */
3373   switch (action) {
3374 
3375   case SANE_ACTION_GET_VALUE:
3376     switch (option) {
3377       /* word options... */
3378     case OPT_RESOLUTION:
3379     case OPT_SPEED:
3380     case OPT_BACKTRACK:
3381     case OPT_NEGATIVE:
3382     case OPT_PREVIEW:
3383     case OPT_TL_X:
3384     case OPT_TL_Y:
3385     case OPT_BR_X:
3386     case OPT_BR_Y:
3387     case OPT_EXPOSURE:
3388     case OPT_BRIGHTNESS:
3389     case OPT_CONTRAST:
3390     case OPT_HIGHLIGHT:
3391     case OPT_SHADOW:
3392     case OPT_MIDTONE:
3393     case OPT_GAMMA_BIND:
3394     case OPT_ANALOG_GAMMA:
3395     case OPT_ANALOG_GAMMA_R:
3396     case OPT_ANALOG_GAMMA_G:
3397     case OPT_ANALOG_GAMMA_B:
3398     case OPT_EXP_RES:
3399     case OPT_CALIB_ONCE:
3400       *(SANE_Word *)value = val[option].w;
3401       return SANE_STATUS_GOOD;
3402       /* word-array options... */
3403       /*    case OPT_HALFTONE_PATTERN:*/
3404     case OPT_GAMMA_VECTOR:
3405     case OPT_GAMMA_VECTOR_R:
3406     case OPT_GAMMA_VECTOR_G:
3407     case OPT_GAMMA_VECTOR_B:
3408       memcpy(value, val[option].wa, sod[option].size);
3409       return SANE_STATUS_GOOD;
3410       /* string options... */
3411     case OPT_MODE:
3412     case OPT_HALFTONE_PATTERN:
3413     case OPT_CUSTOM_GAMMA:
3414     case OPT_SOURCE:
3415       strcpy(value, val[option].s);
3416       return SANE_STATUS_GOOD;
3417       /* others.... */
3418     case OPT_NUM_OPTS:
3419       *(SANE_Word *) value = NUM_OPTIONS;
3420       return SANE_STATUS_GOOD;
3421     default:
3422       return SANE_STATUS_INVAL;
3423     }
3424     break;
3425 
3426   case SANE_ACTION_SET_VALUE: {
3427     status = sanei_constrain_value(sod + option, value, info);
3428     if (status != SANE_STATUS_GOOD)
3429       return status;
3430 
3431     switch (option) {
3432       /* set word options... */
3433     case OPT_TL_X:
3434     case OPT_TL_Y:
3435     case OPT_BR_X:
3436     case OPT_BR_Y:
3437     case OPT_RESOLUTION:
3438       if (info)
3439 	*info |= SANE_INFO_RELOAD_PARAMS;
3440       // fall through
3441     case OPT_SPEED:
3442     case OPT_PREVIEW:
3443     case OPT_BACKTRACK:
3444     case OPT_NEGATIVE:
3445     case OPT_EXPOSURE:
3446     case OPT_BRIGHTNESS:
3447     case OPT_CONTRAST:
3448     case OPT_ANALOG_GAMMA:
3449     case OPT_ANALOG_GAMMA_R:
3450     case OPT_ANALOG_GAMMA_G:
3451     case OPT_ANALOG_GAMMA_B:
3452       val[option].w = *(SANE_Word *)value;
3453       return SANE_STATUS_GOOD;
3454 
3455     case OPT_HIGHLIGHT:
3456     case OPT_SHADOW:
3457     case OPT_MIDTONE:
3458       val[option].w = *(SANE_Word *)value;
3459       /* we need to (silently) make sure shadow <= midtone <= highlight */
3460       if (scanner->midtone_support) {
3461 	if (val[OPT_SHADOW].w > val[OPT_MIDTONE].w) {
3462 	  if (option == OPT_SHADOW)
3463 	    val[OPT_SHADOW].w = val[OPT_MIDTONE].w;
3464 	  else
3465 	    val[OPT_MIDTONE].w = val[OPT_SHADOW].w;
3466 	}
3467 	if (val[OPT_HIGHLIGHT].w < val[OPT_MIDTONE].w) {
3468 	  if (option == OPT_HIGHLIGHT)
3469 	    val[OPT_HIGHLIGHT].w = val[OPT_MIDTONE].w;
3470 	  else
3471 	    val[OPT_MIDTONE].w = val[OPT_HIGHLIGHT].w;
3472 	}
3473       } else {
3474 	if (val[OPT_SHADOW].w > val[OPT_HIGHLIGHT].w) {
3475 	  if (option == OPT_SHADOW)
3476 	    val[OPT_SHADOW].w = val[OPT_HIGHLIGHT].w;
3477 	  else
3478 	    val[OPT_HIGHLIGHT].w = val[OPT_SHADOW].w;
3479 	}
3480       }
3481       return SANE_STATUS_GOOD;
3482 
3483     case OPT_EXP_RES:
3484       if (val[option].w != *(SANE_Word *) value) {
3485 	val[option].w = *(SANE_Word *)value;
3486 	if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
3487 	if (val[OPT_EXP_RES].w) {
3488 	  sod[OPT_RESOLUTION].constraint.range = &(scanner->exp_res_range);
3489 	  val[OPT_RESOLUTION].w *= 2;
3490 	} else {
3491 	  sod[OPT_RESOLUTION].constraint.range = &(scanner->res_range);
3492 	  val[OPT_RESOLUTION].w /= 2;
3493 	}
3494       }
3495       return SANE_STATUS_GOOD;
3496 
3497     case OPT_CALIB_ONCE:
3498       val[option].w = *(SANE_Word *)value;
3499       /* toggling off and on should force a recalibration... */
3500       if (!(val[option].w)) scanner->precal_record = MS_PRECAL_NONE;
3501       return SANE_STATUS_GOOD;
3502 
3503     case OPT_GAMMA_BIND:
3504     case OPT_CUSTOM_GAMMA:
3505       if (option == OPT_GAMMA_BIND) {
3506 	if (val[option].w != *(SANE_Word *) value)
3507 	  if (info) *info |= SANE_INFO_RELOAD_OPTIONS;
3508 	val[option].w = *(SANE_Word *) value;
3509       } else if (option == OPT_CUSTOM_GAMMA) {
3510 	if (val[option].s) {
3511 	  if (strcmp(value, val[option].s))
3512 	    if (info) *info |= SANE_INFO_RELOAD_OPTIONS;
3513 	  free(val[option].s);
3514 	}
3515 	val[option].s = strdup(value);
3516       }
3517       if ( !(strcmp(val[OPT_CUSTOM_GAMMA].s, M_NONE)) ||
3518 	   !(strcmp(val[OPT_CUSTOM_GAMMA].s, M_SCALAR)) ) {
3519 	sod[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE;
3520 	sod[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
3521 	sod[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
3522 	sod[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
3523       }
3524       if ( !(strcmp(val[OPT_CUSTOM_GAMMA].s, M_NONE)) ||
3525 	   !(strcmp(val[OPT_CUSTOM_GAMMA].s, M_TABLE)) ) {
3526 	sod[OPT_ANALOG_GAMMA].cap |= SANE_CAP_INACTIVE;
3527 	sod[OPT_ANALOG_GAMMA_R].cap |= SANE_CAP_INACTIVE;
3528 	sod[OPT_ANALOG_GAMMA_G].cap |= SANE_CAP_INACTIVE;
3529 	sod[OPT_ANALOG_GAMMA_B].cap |= SANE_CAP_INACTIVE;
3530       }
3531       if (!(strcmp(val[OPT_CUSTOM_GAMMA].s, M_SCALAR))) {
3532 	if (val[OPT_GAMMA_BIND].w == SANE_TRUE) {
3533 	  sod[OPT_ANALOG_GAMMA].cap &= ~SANE_CAP_INACTIVE;
3534 	  sod[OPT_ANALOG_GAMMA_R].cap |= SANE_CAP_INACTIVE;
3535 	  sod[OPT_ANALOG_GAMMA_G].cap |= SANE_CAP_INACTIVE;
3536 	  sod[OPT_ANALOG_GAMMA_B].cap |= SANE_CAP_INACTIVE;
3537 	} else {
3538 	  sod[OPT_ANALOG_GAMMA].cap |= SANE_CAP_INACTIVE;
3539 	  sod[OPT_ANALOG_GAMMA_R].cap &= ~SANE_CAP_INACTIVE;
3540 	  sod[OPT_ANALOG_GAMMA_G].cap &= ~SANE_CAP_INACTIVE;
3541 	  sod[OPT_ANALOG_GAMMA_B].cap &= ~SANE_CAP_INACTIVE;
3542 	}
3543       }
3544       if (!(strcmp(val[OPT_CUSTOM_GAMMA].s, M_TABLE))) {
3545 	if (val[OPT_GAMMA_BIND].w == SANE_TRUE) {
3546 	  sod[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE;
3547 	  sod[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
3548 	  sod[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
3549 	  sod[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
3550 	} else {
3551 	  sod[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE;
3552 	  sod[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE;
3553 	  sod[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE;
3554 	  sod[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE;
3555 	}
3556       }
3557       if (!(strcmp(val[OPT_CUSTOM_GAMMA].s, M_NONE)))
3558 	sod[OPT_GAMMA_BIND].cap |= SANE_CAP_INACTIVE;
3559       else if (!(strcmp(val[OPT_MODE].s, M_COLOR)))
3560 	sod[OPT_GAMMA_BIND].cap &= ~SANE_CAP_INACTIVE;
3561       return SANE_STATUS_GOOD;
3562 
3563 
3564     case OPT_MODE:
3565       if (val[option].s) {
3566 	if (strcmp(val[option].s, value))
3567 	  if (info)
3568 	    *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
3569 	free(val[option].s);
3570       }
3571       val[option].s = strdup(value);
3572       if (strcmp(val[option].s, M_HALFTONE)) {
3573 	sod[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
3574       } else {
3575 	sod[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE;
3576       }
3577       if (strcmp(val[option].s, M_COLOR)) { /* not color */
3578         /*val[OPT_GAMMA_BIND].w = SANE_TRUE;*/
3579 	DBG(23, "FLIP ma LID!  bind is %d\n", val[OPT_GAMMA_BIND].w);
3580 	{
3581 	  SANE_Bool Trueness = SANE_TRUE;
3582 	  SANE_Status status;
3583 	  status = sane_control_option(handle,
3584 				       OPT_GAMMA_BIND,
3585 				       SANE_ACTION_SET_VALUE,
3586 				       &Trueness,
3587 				       NULL);
3588 	  DBG(23, "stat is: %d\n", status);
3589 	}
3590 	DBG(23, "LID be FLIPPED!  bind is %d\n", val[OPT_GAMMA_BIND].w);
3591 	sod[OPT_GAMMA_BIND].cap |= SANE_CAP_INACTIVE;
3592 	/*	sod[OPT_FORCE_3PASS].cap |= SANE_CAP_INACTIVE;*/
3593       } else {
3594 	sod[OPT_GAMMA_BIND].cap &= ~SANE_CAP_INACTIVE;
3595 	/*	if (scanner->dev->info.modes & MI_MODES_ONEPASS)
3596 	  sod[OPT_FORCE_3PASS].cap &= ~SANE_CAP_INACTIVE;*/
3597       }
3598       return SANE_STATUS_GOOD;
3599 
3600     case OPT_HALFTONE_PATTERN:
3601     case OPT_SOURCE:
3602       if (val[option].s) free(val[option].s);
3603       val[option].s = strdup(value);
3604       return SANE_STATUS_GOOD;
3605     case OPT_GAMMA_VECTOR:
3606     case OPT_GAMMA_VECTOR_R:
3607     case OPT_GAMMA_VECTOR_G:
3608     case OPT_GAMMA_VECTOR_B:
3609       memcpy(val[option].wa, value, sod[option].size);
3610       return SANE_STATUS_GOOD;
3611     default:
3612       return SANE_STATUS_INVAL;
3613     }
3614   }
3615   break;
3616 
3617   case SANE_ACTION_SET_AUTO:
3618     return SANE_STATUS_UNSUPPORTED;	/* We are DUMB. */
3619   }
3620   return SANE_STATUS_GOOD;
3621 }
3622 
3623 
3624 
3625 /********************************************************************/
3626 /* sane_get_parameters                                              */
3627 /********************************************************************/
3628 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)3629 sane_get_parameters (SANE_Handle handle,
3630 		     SANE_Parameters *params)
3631 {
3632   Microtek_Scanner *s = handle;
3633 
3634   DBG(23, "sane_get_parameters...\n");
3635 
3636   if (!s->scanning) {
3637     /* decipher scan mode */
3638     if (!(strcmp(s->val[OPT_MODE].s, M_LINEART)))
3639       s->mode = MS_MODE_LINEART;
3640     else if (!(strcmp(s->val[OPT_MODE].s, M_HALFTONE)))
3641       s->mode = MS_MODE_HALFTONE;
3642     else if (!(strcmp(s->val[OPT_MODE].s, M_GRAY)))
3643       s->mode = MS_MODE_GRAY;
3644     else if (!(strcmp(s->val[OPT_MODE].s, M_COLOR)))
3645       s->mode = MS_MODE_COLOR;
3646 
3647     if (s->mode == MS_MODE_COLOR) {
3648       if (s->onepass) {
3649 	/* regular one-pass */
3650 	DBG(23, "sane_get_parameters:  regular 1-pass color\n");
3651 	s->threepasscolor = SANE_FALSE;
3652 	s->onepasscolor = SANE_TRUE;
3653 	s->color_seq = s->dev->info.color_sequence;
3654       } else { /* 3-pass scanner */
3655 	DBG(23, "sane_get_parameters:  regular 3-pass color\n");
3656 	s->threepasscolor = SANE_TRUE;
3657 	s->onepasscolor = SANE_FALSE;
3658 	s->color_seq = s->dev->info.color_sequence;
3659       }
3660     } else { /* not color! */
3661 	DBG(23, "sane_get_parameters:  non-color\n");
3662 	s->threepasscolor = SANE_FALSE;
3663 	s->onepasscolor = SANE_FALSE;
3664 	s->color_seq = s->dev->info.color_sequence;
3665     }
3666 
3667     s->transparency = !(strcmp(s->val[OPT_SOURCE].s, M_TRANS));
3668     s->useADF = !(strcmp(s->val[OPT_SOURCE].s, M_AUTOFEED));
3669     /* disallow exp. res. during preview scan XXXXXXXXXXX */
3670     /*s->expandedresolution =
3671       (s->val[OPT_EXP_RES].w) && !(s->val[OPT_PREVIEW].w);*/
3672     s->expandedresolution = (s->val[OPT_EXP_RES].w);
3673     s->doexpansion = (s->expandedresolution && !(s->dev->info.does_expansion));
3674 
3675     if (s->res_type == MS_RES_1PER) {
3676       s->resolution = (SANE_Int)(SANE_UNFIX(s->val[OPT_RESOLUTION].w));
3677       s->resolution_code =
3678 	0xFF & ((s->resolution * 100) /
3679 		s->dev->info.base_resolution /
3680 		(s->expandedresolution ? 2 : 1));
3681       DBG(23, "sane_get_parameters:  res_code = %d (%2x)\n",
3682 	      s->resolution_code, s->resolution_code);
3683     } else {
3684       DBG(23, "sane_get_parameters:  5 percent!!!\n");
3685       /* XXXXXXXXXXXXX */
3686     }
3687 
3688     s->calib_once = s->val[OPT_CALIB_ONCE].w;
3689 
3690     s->reversecolors = s->val[OPT_NEGATIVE].w;
3691     s->prescan = s->val[OPT_PREVIEW].w;
3692     s->exposure = (s->val[OPT_EXPOSURE].w / 3) + 7;
3693     s->contrast = (s->val[OPT_CONTRAST].w / 7) + 7;
3694     s->velocity  = s->val[OPT_SPEED].w;
3695     s->shadow    = s->val[OPT_SHADOW].w;
3696     s->highlight = s->val[OPT_HIGHLIGHT].w;
3697     s->midtone   = s->val[OPT_MIDTONE].w;
3698     if (SANE_OPTION_IS_ACTIVE(s->sod[OPT_BRIGHTNESS].cap)) {
3699 #if 1  /* this is _not_ what the docs specify! */
3700       if (s->val[OPT_BRIGHTNESS].w >= 0)
3701 	s->bright_r = (SANE_Byte) (s->val[OPT_BRIGHTNESS].w);
3702       else
3703 	s->bright_r = (SANE_Byte) (0x80 | (- s->val[OPT_BRIGHTNESS].w));
3704 #else
3705       s->bright_r = (SANE_Byte) (s->val[OPT_BRIGHTNESS].w);
3706 #endif
3707       s->bright_g = s->bright_b = s->bright_r;
3708       DBG(23, "bright_r of %d set to 0x%0x\n",
3709 	  s->val[OPT_BRIGHTNESS].w, s->bright_r);
3710     } else {
3711       s->bright_r = s->bright_g = s->bright_b = 0;
3712     }
3713     /* figure out halftone pattern selection... */
3714     if (s->mode == MS_MODE_HALFTONE) {
3715       int i = 0;
3716       while ((halftone_mode_list[i] != NULL) &&
3717 	     (strcmp(halftone_mode_list[i], s->val[OPT_HALFTONE_PATTERN].s)))
3718 	i++;
3719       s->pattern = ((i < s->dev->info.pattern_count) ? i : 0);
3720     } else
3721       s->pattern = 0;
3722 
3723 
3724 
3725     {
3726       /* need to 'round' things properly!  XXXXXXXX */
3727       SANE_Int widthpix;
3728       double dots_per_mm = s->resolution / MM_PER_INCH;
3729       double units_per_mm =
3730 	(s->unit_type == MS_UNIT_18INCH) ?
3731 	(8.0 / MM_PER_INCH) :                       /* 1/8 inches */
3732 	(s->dev->info.base_resolution / MM_PER_INCH);   /* pixels     */
3733 
3734       DBG(23, "sane_get_parameters:  dots_per_mm:  %f\n", dots_per_mm);
3735       DBG(23, "sane_get_parameters:  units_per_mm:  %f\n", units_per_mm);
3736 
3737       /* calculate frame coordinates...
3738        *  scanner coords are in 'units' -- pixels or 1/8"
3739        *  option coords are MM
3740        */
3741       s->x1 = (SANE_Int)(SANE_UNFIX(s->val[OPT_TL_X].w) * units_per_mm + 0.5);
3742       s->y1 = (SANE_Int)(SANE_UNFIX(s->val[OPT_TL_Y].w) * units_per_mm + 0.5);
3743       s->x2 = (SANE_Int)(SANE_UNFIX(s->val[OPT_BR_X].w) * units_per_mm + 0.5);
3744       s->y2 = (SANE_Int)(SANE_UNFIX(s->val[OPT_BR_Y].w) * units_per_mm + 0.5);
3745       /* bug out if length or width is <= zero... */
3746       if ((s->x1 >= s->x2) || (s->y1 >= s->y2))
3747 	return SANE_STATUS_INVAL;
3748 
3749       /* these are just an estimate... (but *should* be completely accurate)
3750        * real values come from scanner after sane_start.
3751        */
3752       if (s->unit_type == MS_UNIT_18INCH) {
3753 	/* who *knows* what happens */
3754 	widthpix =
3755 	  (SANE_Int)((double)(s->x2 - s->x1 + 1) / 8.0 *
3756 		     (double)s->resolution);
3757 	s->params.lines =
3758 	  (SANE_Int)((double)(s->y2 - s->y1 + 1) / 8.0 *
3759 		     (double)s->resolution);
3760       } else {
3761 	/* calculate pixels per scanline returned by scanner... */
3762 	/* scanner (E6 at least) always seems to return
3763 	   an -even- number of -bytes- */
3764 	if (s->resolution <= s->dev->info.base_resolution)
3765 	  widthpix =
3766 	    (SANE_Int)((double)(s->x2 - s->x1 + 1) *
3767 		       (double)(s->resolution) /
3768 		       (double)(s->dev->info.base_resolution));
3769 	else
3770 	  widthpix = (s->x2 - s->x1 + 1);
3771 	if ((s->mode == MS_MODE_LINEART) ||
3772 	    (s->mode == MS_MODE_HALFTONE)) {
3773 	  DBG(23, "WIDTHPIX:  before: %d", widthpix);
3774 	  widthpix = ((widthpix / 8) & ~0x1) * 8;
3775 	  DBG(23, "after: %d", widthpix);
3776 	} else {
3777 	  widthpix = widthpix & ~0x1;
3778 	}
3779 	DBG(23, "WIDTHPIX:  before exp: %d\n", widthpix);
3780 	/* ok, now fix up expanded-mode conversions */
3781 	if (s->resolution > s->dev->info.base_resolution)
3782 	  widthpix = (SANE_Int) ((double)widthpix *
3783 				 (double)s->resolution /
3784 				 (double)s->dev->info.base_resolution);
3785 	s->params.pixels_per_line = widthpix;
3786 	s->params.lines =
3787 	  (SANE_Int)((double)(s->y2 - s->y1 + 1) *
3788 		     (double)(s->resolution) /
3789 		     (double)(s->dev->info.base_resolution));
3790       }
3791     }
3792 
3793     switch (s->mode) {
3794     case MS_MODE_LINEART:
3795     case MS_MODE_HALFTONE:
3796       s->multibit = SANE_FALSE;
3797       s->params.format = SANE_FRAME_GRAY;
3798       s->params.depth = 1;
3799       s->filter = MS_FILT_CLEAR;
3800       s->params.bytes_per_line = s->params.pixels_per_line / 8;
3801       break;
3802     case MS_MODE_GRAY:
3803       s->multibit = SANE_TRUE;
3804       s->params.format = SANE_FRAME_GRAY;
3805       s->params.depth = s->bits_per_color;
3806       s->filter = MS_FILT_CLEAR;
3807       s->params.bytes_per_line = s->params.pixels_per_line;
3808       break;
3809     case MS_MODE_COLOR:
3810       s->multibit = SANE_TRUE;
3811       if (s->onepasscolor) { /* a single-pass color scan */
3812 	s->params.format = SANE_FRAME_RGB;
3813 	s->params.depth = s->bits_per_color;
3814 	s->filter = MS_FILT_CLEAR;
3815 	s->params.bytes_per_line = s->params.pixels_per_line * 3;
3816       } else { /* a three-pass color scan */
3817 	s->params.depth = s->bits_per_color;
3818 	/* this will be correctly set in sane_start */
3819 	s->params.format = SANE_FRAME_RED;
3820 	s->params.bytes_per_line = s->params.pixels_per_line;
3821       }
3822       break;
3823     }
3824 
3825     DBG(23, "sane_get_parameters:  lines: %d  ppl: %d  bpl: %d\n",
3826 	s->params.lines, s->params.pixels_per_line, s->params.bytes_per_line);
3827 
3828     /* also fixed in sane_start for multi-pass scans */
3829     s->params.last_frame = SANE_TRUE;  /* ?? XXXXXXXX */
3830   }
3831 
3832   if (params)
3833     *params = s->params;
3834 
3835   return SANE_STATUS_GOOD;
3836 }
3837 
3838 
3839 
3840 /********************************************************************/
3841 /* sane_start                                                       */
3842 /********************************************************************/
3843 static SANE_Status
sane_start_guts(SANE_Handle handle)3844 sane_start_guts (SANE_Handle handle)
3845 {
3846   Microtek_Scanner *s = handle;
3847   SANE_Status status;
3848   SANE_Int busy, linewidth;
3849 
3850   DBG(10, "sane_start...\n");
3851 
3852   if (s->sfd != -1) {
3853     DBG(23, "sane_start:  sfd already set!\n");
3854     return SANE_STATUS_DEVICE_BUSY;
3855   }
3856 
3857   if ((status = sane_get_parameters(s, 0)) != SANE_STATUS_GOOD)
3858     return end_scan(s, status);
3859   set_pass_parameters(s);
3860 
3861   s->scanning = SANE_TRUE;
3862   s->cancel = SANE_FALSE;
3863 
3864   status = sanei_scsi_open(s->dev->sane.name,
3865 			   &(s->sfd),
3866 			   sense_handler,
3867 			   &(s->sense_flags));
3868   if (status != SANE_STATUS_GOOD) {
3869     DBG(10, "sane_start: open of %s failed: %s\n",
3870 	s->dev->sane.name, sane_strstatus (status));
3871     s->sfd = -1;
3872     return end_scan(s, status);
3873   }
3874 
3875   if ((status = wait_ready(s)) != SANE_STATUS_GOOD) return end_scan(s, status);
3876 
3877   if ((status = finagle_precal(s)) != SANE_STATUS_GOOD)
3878     return end_scan(s, status);
3879 
3880   if ((status = scanning_frame(s)) != SANE_STATUS_GOOD) return end_scan(s, status);
3881   if (s->dev->info.source_options &
3882       (MI_SRC_FEED_BT | MI_SRC_HAS_TRANS |
3883        MI_SRC_FEED_SUPP | MI_SRC_HAS_FEED)) { /* ZZZZZZZZZZZ */
3884     if ((status = accessory(s)) != SANE_STATUS_GOOD) return end_scan(s, status);
3885     /* if SWslct ????  XXXXXXXXXXXXXXX */
3886   }
3887   if ((status = download_gamma(s)) != SANE_STATUS_GOOD)
3888     return end_scan(s, status);
3889   if ((status = mode_select(s)) != SANE_STATUS_GOOD)
3890     return end_scan(s, status);
3891   if (s->dev->info.does_mode1) {
3892     if ((status = mode_select_1(s)) != SANE_STATUS_GOOD)
3893       return end_scan(s, status);
3894   }
3895   if ((s->do_clever_precal) || (s->do_real_calib)) {
3896     if ((status = save_mode_sense(s)) != SANE_STATUS_GOOD)
3897       return end_scan(s, status);
3898   }
3899   if ((status = wait_ready(s)) != SANE_STATUS_GOOD) return end_scan(s, status);
3900   s->scan_started = SANE_TRUE;
3901   if ((status = start_scan(s)) != SANE_STATUS_GOOD) return end_scan(s, status);
3902   if ((status = get_scan_status(s, &busy,
3903 				&linewidth, &(s->unscanned_lines))) !=
3904       SANE_STATUS_GOOD) {
3905     DBG(10, "sane_start:  get_scan_status fails\n");
3906     return end_scan(s, status);
3907   }
3908   /* check for a bizarre linecount */
3909   if ((s->unscanned_lines < 0) ||
3910       (s->unscanned_lines >
3911        (s->params.lines * 2 * (s->expandedresolution ? 2 : 1)))) {
3912     DBG(10, "sane_start:  get_scan_status returns weird line count %d\n",
3913 	s->unscanned_lines);
3914     return end_scan(s, SANE_STATUS_DEVICE_BUSY);
3915   }
3916 
3917 
3918   /* figure out image format parameters */
3919   switch (s->mode) {
3920   case MS_MODE_LINEART:
3921   case MS_MODE_HALFTONE:
3922     s->pixel_bpl = linewidth;
3923     s->header_bpl = 0;
3924     s->ppl = linewidth * 8;
3925     s->planes = 1;
3926     s->line_format = MS_LNFMT_FLAT;
3927     break;
3928   case MS_MODE_GRAY:
3929     if (s->bits_per_color < 8) {
3930       s->pixel_bpl = linewidth;
3931       s->ppl = linewidth * (8 / s->bits_per_color);
3932     }	else {
3933       s->pixel_bpl = linewidth * ((s->bits_per_color + 7) / 8);
3934       s->ppl = linewidth;
3935     }
3936     s->header_bpl = 0;
3937     s->planes = 1;
3938     s->line_format = MS_LNFMT_FLAT;
3939     break;
3940   case MS_MODE_COLOR:
3941     switch (s->color_seq) {
3942     case MI_COLSEQ_PLANE:
3943       s->pixel_bpl = linewidth * ((s->bits_per_color + 7) / 8);
3944       s->ppl = linewidth;
3945       s->header_bpl = 0;
3946       s->planes = 1;
3947       s->line_format = MS_LNFMT_FLAT;
3948       break;
3949     case MI_COLSEQ_NONRGB:
3950       s->pixel_bpl = (linewidth - 2) * 3 * ((s->bits_per_color + 7) / 8);
3951       s->ppl = linewidth - 2;
3952       s->header_bpl = 2 * 3;
3953       s->planes = 3;
3954       s->line_format = MS_LNFMT_GOOFY_RGB;
3955       break;
3956     case MI_COLSEQ_PIXEL:
3957       s->pixel_bpl = linewidth * 3 * ((s->bits_per_color + 7) / 8);
3958       s->ppl = linewidth;
3959       s->header_bpl = 0;
3960       s->planes = 3;
3961       s->line_format = MS_LNFMT_FLAT;
3962       break;
3963     case MI_COLSEQ_2PIXEL:
3964       s->pixel_bpl = linewidth * 3 * ((s->bits_per_color + 7) / 8);
3965       s->ppl = linewidth;
3966       s->header_bpl = 0;
3967       s->planes = 3;
3968       s->line_format = MS_LNFMT_SEQ_2R2G2B;
3969       break;
3970     case MI_COLSEQ_RGB:
3971       s->pixel_bpl = linewidth * 3 * ((s->bits_per_color + 7) / 8);
3972       s->ppl = linewidth;
3973       s->header_bpl = 0;
3974       s->planes = 3;
3975       s->line_format = MS_LNFMT_SEQ_RGB;
3976       break;
3977     default:
3978       DBG(10, "sane_start:  Unknown color_sequence: %d\n",
3979 	  s->dev->info.color_sequence);
3980       return end_scan(s, SANE_STATUS_INVAL);
3981     }
3982     break;
3983   default:
3984     DBG(10, "sane_start:  Unknown scan mode: %d\n", s->mode);
3985     return end_scan(s, SANE_STATUS_INVAL);
3986   }
3987 
3988   if ((s->doexpansion) &&
3989       (s->resolution > s->dev->info.base_resolution)) {
3990     s->dest_ppl = (int) ((double)s->ppl *
3991 			 (double)s->resolution /
3992 			 (double)s->dev->info.base_resolution);
3993     /*+ 0.5 XXXXXX */
3994     s->exp_aspect = (double)s->ppl / (double)s->dest_ppl;
3995     s->dest_pixel_bpl = (int) ceil((double)s->pixel_bpl / s->exp_aspect);
3996     /*s->exp_aspect =
3997       (double) s->dev->info.base_resolution / (double) s->resolution;*/
3998     /* s->dest_pixel_bpl = s->pixel_bpl / s->exp_aspect;
3999        s->dest_ppl = s->ppl / s->exp_aspect;*/
4000     /*s->dest_ppl = s->ppl / s->exp_aspect;
4001       s->dest_pixel_bpl = (int) ceil((double)s->dest_ppl *
4002       (double)s->pixel_bpl /
4003       (double)s->ppl);*/
4004   } else {
4005     s->exp_aspect = 1.0;
4006     s->dest_pixel_bpl = s->pixel_bpl;
4007     s->dest_ppl = s->ppl;
4008   }
4009 
4010   s->params.lines = s->unscanned_lines;
4011   s->params.pixels_per_line = s->dest_ppl;
4012   s->params.bytes_per_line = s->dest_pixel_bpl;
4013 
4014   /* calculate maximum line capacity of SCSI buffer */
4015   s->max_scsi_lines = SCSI_BUFF_SIZE / (s->pixel_bpl + s->header_bpl);
4016   if (s->max_scsi_lines < 1) {
4017     DBG(10, "sane_start:  SCSI buffer smaller that one scan line!\n");
4018     return end_scan(s, SANE_STATUS_NO_MEM);
4019   }
4020 
4021   s->scsi_buffer = (uint8_t *) malloc(SCSI_BUFF_SIZE * sizeof(uint8_t));
4022   if (s->scsi_buffer == NULL) return SANE_STATUS_NO_MEM;
4023 
4024   /* what's a good initial size for this? */
4025   s->rb = ring_alloc(s->max_scsi_lines * s->dest_pixel_bpl,
4026       s->dest_pixel_bpl, s->dest_ppl);
4027 
4028   s->undelivered_bytes = s->unscanned_lines * s->dest_pixel_bpl;
4029 
4030   DBG(23, "Scan Param:\n");
4031   DBG(23, "pix bpl: %d    hdr bpl: %d   ppl: %d\n",
4032       s->pixel_bpl, s->header_bpl, s->ppl);
4033   DBG(23, "undel bytes: %d   unscan lines: %d   planes: %d\n",
4034       s->undelivered_bytes, s->unscanned_lines, s->planes);
4035   DBG(23, "dest bpl: %d   dest ppl: %d  aspect: %f\n",
4036       s->dest_pixel_bpl, s->dest_ppl, s->exp_aspect);
4037 
4038   return SANE_STATUS_GOOD;
4039 }
4040 
4041 
4042 SANE_Status
sane_start(SANE_Handle handle)4043 sane_start (SANE_Handle handle)
4044 {
4045   Microtek_Scanner *s = handle;
4046   SANE_Status status;
4047 
4048   s->woe = SANE_TRUE;
4049   status = sane_start_guts(handle);
4050   s->woe = SANE_FALSE;
4051   return status;
4052 }
4053 
4054 
4055 
4056 /********************************************************************/
4057 /* sane_read                                                        */
4058 /********************************************************************/
4059 static SANE_Status
sane_read_guts(SANE_Handle handle,SANE_Byte * dest_buffer,SANE_Int dest_length,SANE_Int * ret_length)4060 sane_read_guts (SANE_Handle handle, SANE_Byte *dest_buffer,
4061 		SANE_Int dest_length, SANE_Int *ret_length)
4062 {
4063   Microtek_Scanner *s = handle;
4064   SANE_Status status;
4065   int nlines;
4066   ring_buffer *rb = s->rb;
4067 
4068   DBG(10, "sane_read...\n");
4069 
4070   *ret_length = 0; /* default: no data */
4071   /* we have been cancelled... */
4072   if (s->cancel) return end_scan(s, SANE_STATUS_CANCELLED);
4073   /* we're not really scanning!... */
4074   if (!(s->scanning)) return SANE_STATUS_INVAL;
4075   /* we are done scanning... */
4076   if (s->undelivered_bytes <= 0) return end_scan(s, SANE_STATUS_EOF);
4077 
4078   /* get more bytes if our ring is empty... */
4079   while (rb->complete_count == 0) {
4080     if ((status = read_from_scanner(s, &nlines)) != SANE_STATUS_GOOD) {
4081       DBG(18, "sane_read:  read_from_scanner failed.\n");
4082       return end_scan(s, status);
4083     }
4084     if ((status = pack_into_ring(s, nlines)) != SANE_STATUS_GOOD) {
4085       DBG(18, "sane_read:  pack_into_ring failed.\n");
4086       return end_scan(s, status);
4087     }
4088   }
4089   /* return some data to caller */
4090   *ret_length = pack_into_dest(dest_buffer, dest_length, rb);
4091   s->undelivered_bytes -= *ret_length;
4092 
4093   if (s->cancel) return end_scan(s, SANE_STATUS_CANCELLED);
4094 
4095   return SANE_STATUS_GOOD;
4096 }
4097 
4098 
4099 SANE_Status
sane_read(SANE_Handle handle,SANE_Byte * dest_buffer,SANE_Int dest_length,SANE_Int * ret_length)4100 sane_read (SANE_Handle handle, SANE_Byte *dest_buffer,
4101 	   SANE_Int dest_length, SANE_Int *ret_length)
4102 {
4103   Microtek_Scanner *s = handle;
4104   SANE_Status status;
4105 
4106   s->woe = SANE_TRUE;
4107   status = sane_read_guts(handle, dest_buffer, dest_length, ret_length);
4108   s->woe = SANE_FALSE;
4109   return status;
4110 }
4111 
4112 
4113 
4114 /********************************************************************/
4115 /* sane_exit                                                        */
4116 /********************************************************************/
4117 void
sane_exit(void)4118 sane_exit (void)
4119 {
4120   Microtek_Device *next;
4121 
4122   DBG(10, "sane_exit...\n");
4123   /* close all leftover Scanners */
4124   /*(beware of how sane_close interacts with linked list) */
4125   while (first_handle != NULL)
4126     sane_close(first_handle);
4127   /* free up device list */
4128   while (first_dev != NULL) {
4129     next = first_dev->next;
4130     free((void *) first_dev->sane.name);
4131     free((void *) first_dev->sane.model);
4132     free(first_dev);
4133     first_dev = next;
4134   }
4135   /* the devlist allocated by sane_get_devices */
4136   free(devlist);
4137   DBG(10, "sane_exit:  MICROTEK says goodbye.\n");
4138 }
4139 
4140 
4141 
4142 /********************************************************************/
4143 /* sane_cancel                                                      */
4144 /********************************************************************/
4145 void
sane_cancel(SANE_Handle handle)4146 sane_cancel (SANE_Handle handle)
4147 {
4148   Microtek_Scanner *ms = handle;
4149   DBG(10, "sane_cancel...\n");
4150   ms->cancel = SANE_TRUE;
4151   if (!(ms->woe)) end_scan(ms, SANE_STATUS_CANCELLED);
4152 }
4153 
4154 
4155 
4156 /********************************************************************/
4157 /* sane_set_io_mode                                                 */
4158 /********************************************************************/
4159 SANE_Status
sane_set_io_mode(SANE_Handle handle,SANE_Bool non_blocking)4160 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
4161 {
4162   DBG(10, "sane_set_io_mode...\n");
4163   (void) handle;
4164   if (non_blocking)
4165     return SANE_STATUS_UNSUPPORTED;
4166   else
4167     return SANE_STATUS_GOOD;
4168 }
4169 
4170 
4171 
4172 /********************************************************************/
4173 /* sane_get_select_fd                                               */
4174 /********************************************************************/
4175 SANE_Status
sane_get_select_fd(SANE_Handle handle,SANE_Int * fd)4176 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
4177 {
4178   DBG(10, "sane_get_select_fd...\n");
4179   (void) handle, (void) fd;
4180   return SANE_STATUS_UNSUPPORTED;
4181 }
4182