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