1 /* sane - Scanner Access Now Easy.
2
3 Copyright (C) 1998 David Huggins-Daines, heavily based on the Apple
4 scanner driver (since Abaton scanners are very similar to old Apple
5 scanners), which is (C) 1998 Milon Firikis, which is, in turn, based
6 on the Mustek driver, (C) 1996-7 David Mosberger-Tang.
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 This file implements a SANE backend for Abaton flatbed scanners. */
45
46 #include "../include/sane/config.h"
47
48 #include <ctype.h>
49 #include <errno.h>
50 #include <fcntl.h>
51 #include <limits.h>
52 #include <signal.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <unistd.h>
57
58 #include <sys/time.h>
59 #include <sys/types.h>
60 #include <sys/wait.h>
61
62 #include "../include/_stdint.h"
63
64 #include "../include/sane/sane.h"
65 #include "../include/sane/sanei.h"
66 #include "../include/sane/saneopts.h"
67 #include "../include/sane/sanei_scsi.h"
68
69 #define BACKEND_NAME abaton
70 #include "../include/sane/sanei_backend.h"
71
72 #ifndef PATH_MAX
73 # define PATH_MAX 1024
74 #endif
75
76 #include "../include/sane/sanei_config.h"
77 #define ABATON_CONFIG_FILE "abaton.conf"
78
79 #include "abaton.h"
80
81
82
83 static const SANE_Device **devlist = 0;
84 static int num_devices;
85 static Abaton_Device *first_dev;
86 static Abaton_Scanner *first_handle;
87
88 static SANE_String_Const mode_list[5];
89
90 static const SANE_String_Const halftone_pattern_list[] =
91 {
92 "spiral", "bayer",
93 0
94 };
95
96 static const SANE_Range dpi_range =
97 {
98 /* min, max, quant */
99 72,
100 300,
101 1
102 };
103
104 static const SANE_Range enhance_range =
105 {
106 1,
107 255,
108 1
109 };
110
111 static const SANE_Range x_range =
112 {
113 0,
114 8.5 * MM_PER_INCH,
115 1
116 };
117
118 static const SANE_Range y_range =
119 {
120 0,
121 14.0 * MM_PER_INCH,
122 1
123 };
124
125 #define ERROR_MESSAGE 1
126 #define USER_MESSAGE 5
127 #define FLOW_CONTROL 50
128 #define VARIABLE_CONTROL 70
129 #define DEBUG_SPECIAL 100
130 #define IO_MESSAGE 110
131 #define INNER_LOOP 120
132
133
134 /* SCSI commands that the Abaton scanners understand: */
135 #define TEST_UNIT_READY 0x00
136 #define REQUEST_SENSE 0x03
137 #define INQUIRY 0x12
138 #define START_STOP 0x1b
139 #define SET_WINDOW 0x24
140 #define READ_10 0x28
141 #define WRITE_10 0x2b /* not used, AFAIK */
142 #define GET_DATA_STATUS 0x34
143
144
145 #define INQ_LEN 0x60
146 static const uint8_t inquiry[] =
147 {
148 INQUIRY, 0x00, 0x00, 0x00, INQ_LEN, 0x00
149 };
150
151 static const uint8_t test_unit_ready[] =
152 {
153 TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00
154 };
155
156 /* convenience macros */
157 #define ENABLE(OPTION) s->opt[OPTION].cap &= ~SANE_CAP_INACTIVE
158 #define DISABLE(OPTION) s->opt[OPTION].cap |= SANE_CAP_INACTIVE
159 #define IS_ACTIVE(OPTION) (((s->opt[OPTION].cap) & SANE_CAP_INACTIVE) == 0)
160
161 /* store an 8-bit-wide value at the location specified by ptr */
162 #define STORE8(ptr, val) (*((uint8_t *) ptr) = val)
163
164 /* store a 16-bit-wide value in network (big-endian) byte order */
165 #define STORE16(ptr, val) \
166 { \
167 *((uint8_t *) ptr) = (val >> 8) & 0xff; \
168 *((uint8_t *) ptr+1) = val & 0xff; \
169 }
170
171 /* store a 24-bit-wide value in network (big-endian) byte order */
172 #define STORE24(ptr, val) \
173 { \
174 *((uint8_t *) ptr) = (val >> 16) & 0xff; \
175 *((uint8_t *) ptr+1) = (val >> 8) & 0xff; \
176 *((uint8_t *) ptr+2) = val & 0xff; \
177 }
178
179 /* store a 32-bit-wide value in network (big-endian) byte order */
180 #define STORE32(ptr, val) \
181 { \
182 *((uint8_t *) ptr) = (val >> 24) & 0xff; \
183 *((uint8_t *) ptr+1) = (val >> 16) & 0xff; \
184 *((uint8_t *) ptr+2) = (val >> 8) & 0xff; \
185 *((uint8_t *) ptr+3) = val & 0xff; \
186 }
187
188 /* retrieve a 24-bit-wide big-endian value at ptr */
189 #define GET24(ptr) \
190 (*((uint8_t *) ptr) << 16) + \
191 (*((uint8_t *) ptr+1) << 8) + \
192 (*((uint8_t *) ptr+2))
193
194 static SANE_Status
wait_ready(int fd)195 wait_ready (int fd)
196 {
197 #define MAX_WAITING_TIME 60 /* one minute, at most */
198 struct timeval now, start;
199 SANE_Status status;
200
201 gettimeofday (&start, 0);
202
203 while (1)
204 {
205 DBG (USER_MESSAGE, "wait_ready: sending TEST_UNIT_READY\n");
206
207 status = sanei_scsi_cmd (fd, test_unit_ready, sizeof (test_unit_ready),
208 0, 0);
209 switch (status)
210 {
211 default:
212 /* Ignore errors while waiting for scanner to become ready.
213 Some SCSI drivers return EIO while the scanner is
214 returning to the home position. */
215 DBG (ERROR_MESSAGE, "wait_ready: test unit ready failed (%s)\n",
216 sane_strstatus (status));
217 /* fall through */
218 case SANE_STATUS_DEVICE_BUSY:
219 gettimeofday (&now, 0);
220 if (now.tv_sec - start.tv_sec >= MAX_WAITING_TIME)
221 {
222 DBG (ERROR_MESSAGE, "wait_ready: timed out after %ld seconds\n",
223 (long) (now.tv_sec - start.tv_sec));
224 return SANE_STATUS_INVAL;
225 }
226 usleep (100000); /* retry after 100ms */
227 break;
228
229 case SANE_STATUS_GOOD:
230 return status;
231 }
232 }
233 return SANE_STATUS_INVAL;
234 }
235
236 static SANE_Status
sense_handler(int scsi_fd,u_char * result,void * arg)237 sense_handler (int scsi_fd, u_char * result, void *arg)
238 {
239 scsi_fd = scsi_fd; /* silence gcc */
240 arg = arg; /* silence gcc */
241
242 switch (result[2] & 0x0F)
243 {
244 case 0:
245 DBG (USER_MESSAGE, "Sense: No sense Error\n");
246 return SANE_STATUS_GOOD;
247 case 2:
248 DBG (ERROR_MESSAGE, "Sense: Scanner not ready\n");
249 return SANE_STATUS_DEVICE_BUSY;
250 case 4:
251 DBG (ERROR_MESSAGE, "Sense: Hardware Error. Read more...\n");
252 return SANE_STATUS_IO_ERROR;
253 case 5:
254 DBG (ERROR_MESSAGE, "Sense: Illegal request\n");
255 return SANE_STATUS_UNSUPPORTED;
256 case 6:
257 DBG (ERROR_MESSAGE, "Sense: Unit Attention (Wait until scanner "
258 "boots)\n");
259 return SANE_STATUS_DEVICE_BUSY;
260 case 9:
261 DBG (ERROR_MESSAGE, "Sense: Vendor Unique. Read more...\n");
262 return SANE_STATUS_IO_ERROR;
263 default:
264 DBG (ERROR_MESSAGE, "Sense: Unknown Sense Key. Read more...\n");
265 return SANE_STATUS_IO_ERROR;
266 }
267
268 return SANE_STATUS_GOOD;
269 }
270
271 static SANE_Status
request_sense(Abaton_Scanner * s)272 request_sense (Abaton_Scanner * s)
273 {
274 uint8_t cmd[6];
275 uint8_t result[22];
276 size_t size = sizeof (result);
277 SANE_Status status;
278
279 memset (cmd, 0, sizeof (cmd));
280 memset (result, 0, sizeof (result));
281
282 cmd[0] = REQUEST_SENSE;
283 STORE8 (cmd + 4, sizeof (result));
284 sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), result, &size);
285
286 if (result[7] != 14)
287 {
288 DBG (ERROR_MESSAGE, "Additional Length %u\n", (unsigned int) result[7]);
289 status = SANE_STATUS_IO_ERROR;
290 }
291
292
293 status = sense_handler (s->fd, result, NULL);
294 if (status == SANE_STATUS_IO_ERROR)
295 {
296
297 /* Since I haven't figured out the vendor unique error codes on
298 this thing, I'll just handle the normal ones for now */
299
300 if (result[18] & 0x80)
301 DBG (ERROR_MESSAGE, "Sense: Dim Light (output of lamp below 70%%).\n");
302
303 if (result[18] & 0x40)
304 DBG (ERROR_MESSAGE, "Sense: No Light at all.\n");
305
306 if (result[18] & 0x20)
307 DBG (ERROR_MESSAGE, "Sense: No Home.\n");
308
309 if (result[18] & 0x10)
310 DBG (ERROR_MESSAGE, "Sense: No Limit. Tried to scan out of range.\n");
311 }
312
313 DBG (USER_MESSAGE, "Sense: Optical gain %u.\n", (unsigned int) result[20]);
314 return status;
315 }
316
317 static SANE_Status
set_window(Abaton_Scanner * s)318 set_window (Abaton_Scanner * s)
319 {
320 uint8_t cmd[10 + 40];
321 uint8_t *window = cmd + 10 + 8;
322 int invert;
323
324 memset (cmd, 0, sizeof (cmd));
325 cmd[0] = SET_WINDOW;
326 cmd[8] = 40;
327
328 /* Just like the Apple scanners, we put the resolution here */
329 STORE16 (window + 2, s->val[OPT_X_RESOLUTION].w);
330 STORE16 (window + 4, s->val[OPT_Y_RESOLUTION].w);
331
332 /* Unlike Apple scanners, these are pixel values */
333 STORE16 (window + 6, s->ULx);
334 STORE16 (window + 8, s->ULy);
335 STORE16 (window + 10, s->Width);
336 STORE16 (window + 12, s->Height);
337
338 STORE8 (window + 14, s->val[OPT_BRIGHTNESS].w);
339 STORE8 (window + 15, s->val[OPT_THRESHOLD].w);
340 STORE8 (window + 16, s->val[OPT_CONTRAST].w);
341
342 invert = s->val[OPT_NEGATIVE].w;
343
344 if (!strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART))
345 {
346 STORE8 (window + 17, 0);
347 }
348 else if (!strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_HALFTONE))
349 {
350 STORE8 (window + 17, 1);
351 }
352 else if (!strcmp (s->val[OPT_MODE].s, "Gray256")
353 || !strcmp (s->val[OPT_MODE].s, "Gray16"))
354 {
355 STORE8 (window + 17, 2);
356 invert = !s->val[OPT_NEGATIVE].w;
357 }
358 else
359 {
360 DBG (ERROR_MESSAGE, "Can't match mode %s\n", s->val[OPT_MODE].s);
361 return SANE_STATUS_INVAL;
362 }
363
364 STORE8 (window + 18, s->bpp);
365
366 if (!strcmp (s->val[OPT_HALFTONE_PATTERN].s, "spiral"))
367 {
368 STORE8 (window + 20, 0);
369 }
370 else if (!strcmp (s->val[OPT_HALFTONE_PATTERN].s, "bayer"))
371 {
372 STORE8 (window + 20, 1);
373 }
374 else
375 {
376 DBG (ERROR_MESSAGE, "Can't match haftone pattern %s\n",
377 s->val[OPT_HALFTONE_PATTERN].s);
378 return SANE_STATUS_INVAL;
379 }
380
381 /* We have to invert these ones for some reason, so why not
382 let the scanner do it for us... */
383 STORE8 (window + 21, invert ? 0x80 : 0);
384
385 STORE16 (window + 22, (s->val[OPT_MIRROR].w != 0));
386
387 return sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), 0, 0);
388 }
389
390 static SANE_Status
start_scan(Abaton_Scanner * s)391 start_scan (Abaton_Scanner * s)
392 {
393 SANE_Status status;
394 uint8_t start[7];
395
396
397 memset (start, 0, sizeof (start));
398 start[0] = START_STOP;
399 start[4] = 1;
400
401 status = sanei_scsi_cmd (s->fd, start, sizeof (start), 0, 0);
402 return status;
403 }
404
405 static SANE_Status
attach(const char * devname,Abaton_Device ** devp,int may_wait)406 attach (const char *devname, Abaton_Device ** devp, int may_wait)
407 {
408 char result[INQ_LEN];
409 const char *model_name = result + 44;
410 int fd, abaton_scanner;
411 Abaton_Device *dev;
412 SANE_Status status;
413 size_t size;
414
415 for (dev = first_dev; dev; dev = dev->next)
416 if (strcmp (dev->sane.name, devname) == 0)
417 {
418 if (devp)
419 *devp = dev;
420 return SANE_STATUS_GOOD;
421 }
422
423 DBG (USER_MESSAGE, "attach: opening %s\n", devname);
424 status = sanei_scsi_open (devname, &fd, sense_handler, 0);
425 if (status != SANE_STATUS_GOOD)
426 {
427 DBG (ERROR_MESSAGE, "attach: open failed (%s)\n",
428 sane_strstatus (status));
429 return SANE_STATUS_INVAL;
430 }
431
432 if (may_wait)
433 wait_ready (fd);
434
435 DBG (USER_MESSAGE, "attach: sending INQUIRY\n");
436 size = sizeof (result);
437 status = sanei_scsi_cmd (fd, inquiry, sizeof (inquiry), result, &size);
438 if (status != SANE_STATUS_GOOD)
439 {
440 DBG (ERROR_MESSAGE, "attach: inquiry failed (%s)\n",
441 sane_strstatus (status));
442 sanei_scsi_close (fd);
443 return status;
444 }
445
446 status = wait_ready (fd);
447 sanei_scsi_close (fd);
448 if (status != SANE_STATUS_GOOD)
449 return status;
450
451 /* check that we've got an Abaton */
452 abaton_scanner = (strncmp (result + 8, "ABATON ", 8) == 0);
453 model_name = result + 16;
454
455 /* make sure it's a scanner ;-) */
456 abaton_scanner = abaton_scanner && (result[0] == 0x06);
457
458 if (!abaton_scanner)
459 {
460 DBG (ERROR_MESSAGE, "attach: device doesn't look like an Abaton scanner "
461 "(result[0]=%#02x)\n", result[0]);
462 return SANE_STATUS_INVAL;
463 }
464
465 dev = malloc (sizeof (*dev));
466 if (!dev)
467 return SANE_STATUS_NO_MEM;
468
469 memset (dev, 0, sizeof (*dev));
470
471 dev->sane.name = strdup (devname);
472 dev->sane.vendor = "Abaton";
473 dev->sane.model = strndup (model_name, 16);
474 dev->sane.type = "flatbed scanner";
475
476 if (!strncmp (model_name, "SCAN 300/GS", 11))
477 {
478 dev->ScannerModel = ABATON_300GS;
479 }
480 else if (!strncmp (model_name, "SCAN 300/S", 10))
481 {
482 dev->ScannerModel = ABATON_300S;
483 }
484
485 DBG (USER_MESSAGE, "attach: found Abaton scanner model %s (%s)\n",
486 dev->sane.model, dev->sane.type);
487
488 ++num_devices;
489 dev->next = first_dev;
490 first_dev = dev;
491
492 if (devp)
493 *devp = dev;
494
495 return SANE_STATUS_GOOD;
496 }
497
498 static SANE_Status
attach_one(const char * devname)499 attach_one (const char *devname)
500 {
501 return attach (devname, 0, SANE_FALSE);
502 }
503
504 static SANE_Status
calc_parameters(Abaton_Scanner * s)505 calc_parameters (Abaton_Scanner * s)
506 {
507 SANE_String val = s->val[OPT_MODE].s;
508 SANE_Status status = SANE_STATUS_GOOD;
509 SANE_Int dpix = s->val[OPT_X_RESOLUTION].w;
510 SANE_Int dpiy = s->val[OPT_Y_RESOLUTION].w;
511 double ulx, uly, width, height;
512
513 DBG (FLOW_CONTROL, "Entering calc_parameters\n");
514
515 if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) || !strcmp (val, SANE_VALUE_SCAN_MODE_HALFTONE))
516 {
517 s->params.depth = 1;
518 s->bpp = 1;
519 }
520 else if (!strcmp (val, "Gray16"))
521 {
522 s->params.depth = 8;
523 s->bpp = 4;
524 }
525 else if (!strcmp (val, "Gray256"))
526 {
527 s->params.depth = 8;
528 s->bpp = 8;
529 }
530 else
531 {
532 DBG (ERROR_MESSAGE, "calc_parameters: Invalid mode %s\n", (char *) val);
533 status = SANE_STATUS_INVAL;
534 }
535
536 /* in inches */
537 ulx = (double) s->val[OPT_TL_X].w / MM_PER_INCH;
538 uly = (double) s->val[OPT_TL_Y].w / MM_PER_INCH;
539 width = (double) s->val[OPT_BR_X].w / MM_PER_INCH - ulx;
540 height = (double) s->val[OPT_BR_Y].w / MM_PER_INCH - uly;
541
542 DBG (VARIABLE_CONTROL, "(inches) ulx: %f, uly: %f, width: %f, height: %f\n",
543 ulx, uly, width, height);
544
545 /* turn 'em into pixel quantities */
546 s->ULx = ulx * dpix;
547 s->ULy = uly * dpiy;
548 s->Width = width * dpix;
549 s->Height = height * dpiy;
550
551 DBG (VARIABLE_CONTROL, "(pixels) ulx: %d, uly: %d, width: %d, height: %d\n",
552 s->ULx, s->ULy, s->Width, s->Height);
553
554 /* floor width to a byte multiple */
555 if ((s->Width * s->bpp) % 8)
556 {
557 s->Width /= 8;
558 s->Width *= 8;
559 DBG (VARIABLE_CONTROL, "Adapting to width %d\n", s->Width);
560 }
561
562 s->params.pixels_per_line = s->Width;
563 s->params.lines = s->Height;
564 s->params.bytes_per_line = s->params.pixels_per_line * s->params.depth / 8;
565
566
567 DBG (VARIABLE_CONTROL, "format=%d\n", s->params.format);
568 DBG (VARIABLE_CONTROL, "last_frame=%d\n", s->params.last_frame);
569 DBG (VARIABLE_CONTROL, "lines=%d\n", s->params.lines);
570 DBG (VARIABLE_CONTROL, "depth=%d (%d)\n", s->params.depth, s->bpp);
571 DBG (VARIABLE_CONTROL, "pixels_per_line=%d\n", s->params.pixels_per_line);
572 DBG (VARIABLE_CONTROL, "bytes_per_line=%d\n", s->params.bytes_per_line);
573 DBG (VARIABLE_CONTROL, "Pixels %dx%dx%d\n",
574 s->params.pixels_per_line, s->params.lines, 1 << s->params.depth);
575
576 DBG (FLOW_CONTROL, "Leaving calc_parameters\n");
577 return status;
578 }
579
580 static SANE_Status
mode_update(SANE_Handle handle,char * val)581 mode_update (SANE_Handle handle, char *val)
582 {
583 Abaton_Scanner *s = handle;
584
585 if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART))
586 {
587 DISABLE (OPT_BRIGHTNESS);
588 DISABLE (OPT_CONTRAST);
589 ENABLE (OPT_THRESHOLD);
590 DISABLE (OPT_HALFTONE_PATTERN);
591 }
592 else if (!strcmp (val, SANE_VALUE_SCAN_MODE_HALFTONE))
593 {
594 ENABLE (OPT_BRIGHTNESS);
595 ENABLE (OPT_CONTRAST);
596 DISABLE (OPT_THRESHOLD);
597 ENABLE (OPT_HALFTONE_PATTERN);
598 }
599 else if (!strcmp (val, "Gray16") || !strcmp (val, "Gray256"))
600 {
601 ENABLE (OPT_BRIGHTNESS);
602 ENABLE (OPT_CONTRAST);
603 DISABLE (OPT_THRESHOLD);
604 DISABLE (OPT_HALFTONE_PATTERN);
605 } /* End of Gray */
606 else
607 {
608 DBG (ERROR_MESSAGE, "Invalid mode %s\n", (char *) val);
609 return SANE_STATUS_INVAL;
610 }
611
612 calc_parameters (s);
613
614 return SANE_STATUS_GOOD;
615 }
616
617 /* find the longest of a list of strings */
618 static size_t
max_string_size(const SANE_String_Const strings[])619 max_string_size (const SANE_String_Const strings[])
620 {
621 size_t size, max_size = 0;
622 int i;
623
624 for (i = 0; strings[i]; ++i)
625 {
626 size = strlen (strings[i]) + 1;
627 if (size > max_size)
628 max_size = size;
629 }
630
631 return max_size;
632 }
633
634 static SANE_Status
init_options(Abaton_Scanner * s)635 init_options (Abaton_Scanner * s)
636 {
637 int i;
638
639 memset (s->opt, 0, sizeof (s->opt));
640 memset (s->val, 0, sizeof (s->val));
641
642 for (i = 0; i < NUM_OPTIONS; ++i)
643 {
644 s->opt[i].size = sizeof (SANE_Word);
645 s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
646 }
647
648 s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
649 s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
650 s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
651 s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
652 s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
653
654
655 /* "Mode" group: */
656 s->opt[OPT_MODE_GROUP].title = "Scan Mode";
657 s->opt[OPT_MODE_GROUP].desc = "";
658 s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
659 s->opt[OPT_MODE_GROUP].cap = 0;
660 s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
661
662 mode_list[0]=SANE_VALUE_SCAN_MODE_LINEART;
663
664 switch (s->hw->ScannerModel)
665 {
666 case ABATON_300GS:
667 mode_list[1]=SANE_VALUE_SCAN_MODE_HALFTONE;
668 mode_list[2]="Gray16";
669 mode_list[3]="Gray256";
670 mode_list[4]=NULL;
671 break;
672 case ABATON_300S:
673 default:
674 mode_list[1]=NULL;
675 break;
676 }
677
678 /* scan mode */
679 s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
680 s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
681 s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
682 s->opt[OPT_MODE].type = SANE_TYPE_STRING;
683 s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
684 s->opt[OPT_MODE].size = max_string_size (mode_list);
685 s->opt[OPT_MODE].constraint.string_list = mode_list;
686 s->val[OPT_MODE].s = strdup (mode_list[0]);
687
688 /* resolution - horizontal */
689 s->opt[OPT_X_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
690 s->opt[OPT_X_RESOLUTION].title = SANE_TITLE_SCAN_X_RESOLUTION;
691 s->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_X_RESOLUTION;
692 s->opt[OPT_X_RESOLUTION].type = SANE_TYPE_INT;
693 s->opt[OPT_X_RESOLUTION].unit = SANE_UNIT_DPI;
694 s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
695 s->opt[OPT_X_RESOLUTION].constraint.range = &dpi_range;
696 s->val[OPT_X_RESOLUTION].w = 150;
697
698 /* resolution - vertical */
699 s->opt[OPT_Y_RESOLUTION].name = SANE_NAME_SCAN_Y_RESOLUTION;
700 s->opt[OPT_Y_RESOLUTION].title = SANE_TITLE_SCAN_Y_RESOLUTION;
701 s->opt[OPT_Y_RESOLUTION].desc = SANE_DESC_SCAN_Y_RESOLUTION;
702 s->opt[OPT_Y_RESOLUTION].type = SANE_TYPE_INT;
703 s->opt[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI;
704 s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
705 s->opt[OPT_Y_RESOLUTION].constraint.range = &dpi_range;
706 s->val[OPT_Y_RESOLUTION].w = 150;
707
708 /* constrain resolutions */
709 s->opt[OPT_RESOLUTION_BIND].name = SANE_NAME_RESOLUTION_BIND;
710 s->opt[OPT_RESOLUTION_BIND].title = SANE_TITLE_RESOLUTION_BIND;
711 s->opt[OPT_RESOLUTION_BIND].desc = SANE_DESC_RESOLUTION_BIND;
712 s->opt[OPT_RESOLUTION_BIND].type = SANE_TYPE_BOOL;
713 s->opt[OPT_RESOLUTION_BIND].unit = SANE_UNIT_NONE;
714 s->opt[OPT_RESOLUTION_BIND].constraint_type = SANE_CONSTRAINT_NONE;
715 /* until I fix it */
716 s->val[OPT_RESOLUTION_BIND].w = SANE_FALSE;
717
718 /* preview mode */
719 s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
720 s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
721 s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
722 s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
723 s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL;
724 s->val[OPT_PREVIEW].w = SANE_FALSE;
725
726 /* halftone pattern */
727 s->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN;
728 s->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN;
729 s->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN;
730 s->opt[OPT_HALFTONE_PATTERN].size = max_string_size (halftone_pattern_list);
731 s->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING;
732 s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
733 s->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST;
734 s->opt[OPT_HALFTONE_PATTERN].constraint.string_list = halftone_pattern_list;
735 s->val[OPT_HALFTONE_PATTERN].s = strdup (halftone_pattern_list[0]);
736
737
738 /* "Geometry" group: */
739 s->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
740 s->opt[OPT_GEOMETRY_GROUP].desc = "";
741 s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
742 s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
743 s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
744
745 /* top-left x */
746 s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
747 s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
748 s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
749 s->opt[OPT_TL_X].type = SANE_TYPE_INT;
750 s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
751 s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
752 s->opt[OPT_TL_X].constraint.range = &x_range;
753 s->val[OPT_TL_X].w = 0;
754
755 /* top-left y */
756 s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
757 s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
758 s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
759 s->opt[OPT_TL_Y].type = SANE_TYPE_INT;
760 s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
761 s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
762 s->opt[OPT_TL_Y].constraint.range = &y_range;
763 s->val[OPT_TL_Y].w = 0;
764
765 /* bottom-right x */
766 s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
767 s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
768 s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
769 s->opt[OPT_BR_X].type = SANE_TYPE_INT;
770 s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
771 s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
772 s->opt[OPT_BR_X].constraint.range = &x_range;
773 s->val[OPT_BR_X].w = x_range.max;
774
775 /* bottom-right y */
776 s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
777 s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
778 s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
779 s->opt[OPT_BR_Y].type = SANE_TYPE_INT;
780 s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
781 s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
782 s->opt[OPT_BR_Y].constraint.range = &y_range;
783 s->val[OPT_BR_Y].w = y_range.max;
784
785
786 /* "Enhancement" group: */
787 s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement";
788 s->opt[OPT_ENHANCEMENT_GROUP].desc = "";
789 s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
790 s->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
791 s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
792
793 /* brightness */
794 s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
795 s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
796 s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
797 s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
798 s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE;
799 s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
800 s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
801 s->opt[OPT_BRIGHTNESS].constraint.range = &enhance_range;
802 s->val[OPT_BRIGHTNESS].w = 150;
803
804 /* contrast */
805 s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
806 s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
807 s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
808 s->opt[OPT_CONTRAST].type = SANE_TYPE_INT;
809 s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE;
810 s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE;
811 s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
812 s->opt[OPT_CONTRAST].constraint.range = &enhance_range;
813 s->val[OPT_CONTRAST].w = 150;
814
815 /* threshold */
816 s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
817 s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
818 s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
819 s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT;
820 s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE;
821 s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
822 s->opt[OPT_THRESHOLD].constraint.range = &enhance_range;
823 s->val[OPT_THRESHOLD].w = 150;
824
825 /* negative */
826 s->opt[OPT_NEGATIVE].name = SANE_NAME_NEGATIVE;
827 s->opt[OPT_NEGATIVE].title = SANE_TITLE_NEGATIVE;
828 s->opt[OPT_NEGATIVE].desc = SANE_DESC_NEGATIVE;
829 s->opt[OPT_NEGATIVE].type = SANE_TYPE_BOOL;
830 s->opt[OPT_NEGATIVE].unit = SANE_UNIT_NONE;
831 s->opt[OPT_NEGATIVE].constraint_type = SANE_CONSTRAINT_NONE;
832 s->val[OPT_NEGATIVE].w = SANE_FALSE;
833
834 /* mirror-image */
835 s->opt[OPT_MIRROR].name = "mirror";
836 s->opt[OPT_MIRROR].title = "Mirror Image";
837 s->opt[OPT_MIRROR].desc = "Scan in mirror-image";
838 s->opt[OPT_MIRROR].type = SANE_TYPE_BOOL;
839 s->opt[OPT_MIRROR].unit = SANE_UNIT_NONE;
840 s->opt[OPT_MIRROR].constraint_type = SANE_CONSTRAINT_NONE;
841 s->val[OPT_MIRROR].w = SANE_FALSE;
842
843 return SANE_STATUS_GOOD;
844 }
845
846 SANE_Status
sane_init(SANE_Int * version_code,SANE_Auth_Callback authorize)847 sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
848 {
849 char dev_name[PATH_MAX];
850 size_t len;
851 FILE *fp;
852
853 authorize = authorize; /* silence gcc */
854
855 DBG_INIT ();
856
857 if (version_code)
858 *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0);
859
860 fp = sanei_config_open (ABATON_CONFIG_FILE);
861 if (!fp)
862 {
863 /* default to /dev/scanner instead of insisting on config file */
864 attach ("/dev/scanner", 0, SANE_FALSE);
865 return SANE_STATUS_GOOD;
866 }
867
868 while (sanei_config_read (dev_name, sizeof (dev_name), fp))
869 {
870 if (dev_name[0] == '#') /* ignore line comments */
871 continue;
872
873 len = strlen (dev_name);
874
875 if (!len)
876 continue; /* ignore empty lines */
877
878 if (strncmp (dev_name, "option", 6) == 0
879 && isspace (dev_name[6]))
880 {
881 const char *str = dev_name + 7;
882
883 while (isspace (*str))
884 ++str;
885
886 continue;
887 }
888
889 sanei_config_attach_matching_devices (dev_name, attach_one);
890 }
891 fclose (fp);
892 return SANE_STATUS_GOOD;
893 }
894
895 void
sane_exit(void)896 sane_exit (void)
897 {
898 Abaton_Device *dev, *next;
899
900 for (dev = first_dev; dev; dev = next)
901 {
902 next = dev->next;
903 free ((void *) dev->sane.name);
904 free ((void *) dev->sane.model);
905 free (dev);
906 }
907
908 if (devlist)
909 free (devlist);
910 }
911
912 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)913 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
914 {
915 Abaton_Device *dev;
916 int i;
917
918 local_only = local_only; /* silence gcc */
919
920 if (devlist)
921 free (devlist);
922
923 devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
924 if (!devlist)
925 return SANE_STATUS_NO_MEM;
926
927 i = 0;
928 for (dev = first_dev; i < num_devices; dev = dev->next)
929 devlist[i++] = &dev->sane;
930 devlist[i++] = 0;
931
932 *device_list = devlist;
933 return SANE_STATUS_GOOD;
934 }
935
936 SANE_Status
sane_open(SANE_String_Const devicename,SANE_Handle * handle)937 sane_open (SANE_String_Const devicename, SANE_Handle * handle)
938 {
939 Abaton_Device *dev;
940 SANE_Status status;
941 Abaton_Scanner *s;
942
943 if (devicename[0])
944 {
945 for (dev = first_dev; dev; dev = dev->next)
946 if (strcmp (dev->sane.name, devicename) == 0)
947 break;
948
949 if (!dev)
950 {
951 status = attach (devicename, &dev, SANE_TRUE);
952 if (status != SANE_STATUS_GOOD)
953 return status;
954 }
955 }
956 else
957 /* empty devicname -> use first device */
958 dev = first_dev;
959
960 if (!dev)
961 return SANE_STATUS_INVAL;
962
963 s = malloc (sizeof (*s));
964 if (!s)
965 return SANE_STATUS_NO_MEM;
966 memset (s, 0, sizeof (*s));
967 s->fd = -1;
968 s->hw = dev;
969
970 init_options (s);
971
972 /* set up some universal parameters */
973 s->params.last_frame = SANE_TRUE;
974 s->params.format = SANE_FRAME_GRAY;
975
976 /* insert newly opened handle into list of open handles: */
977 s->next = first_handle;
978 first_handle = s;
979
980 *handle = s;
981 return SANE_STATUS_GOOD;
982 }
983
984 void
sane_close(SANE_Handle handle)985 sane_close (SANE_Handle handle)
986 {
987 Abaton_Scanner *prev, *s;
988
989 /* remove handle from list of open handles: */
990 prev = 0;
991 for (s = first_handle; s; s = s->next)
992 {
993 if (s == (Abaton_Scanner *) handle)
994 break;
995 prev = s;
996 }
997 if (!s)
998 {
999 DBG (ERROR_MESSAGE, "close: invalid handle %p\n", handle);
1000 return; /* oops, not a handle we know about */
1001 }
1002
1003 if (prev)
1004 prev->next = s->next;
1005 else
1006 first_handle = s->next;
1007
1008 free (handle);
1009 }
1010
1011 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle,SANE_Int option)1012 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
1013 {
1014 Abaton_Scanner *s = handle;
1015
1016 if ((unsigned) option >= NUM_OPTIONS)
1017 return NULL;
1018
1019 return s->opt + option;
1020 }
1021
1022 SANE_Status
sane_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * val,SANE_Int * info)1023 sane_control_option (SANE_Handle handle, SANE_Int option,
1024 SANE_Action action, void *val, SANE_Int * info)
1025 {
1026 Abaton_Scanner *s = handle;
1027 SANE_Status status;
1028 SANE_Word cap;
1029
1030
1031 if (option < 0 || option >= NUM_OPTIONS)
1032 return SANE_STATUS_INVAL;
1033
1034 if (info != NULL)
1035 *info = 0;
1036
1037 if (s->scanning)
1038 return SANE_STATUS_DEVICE_BUSY;
1039
1040 cap = s->opt[option].cap;
1041
1042 if (!SANE_OPTION_IS_ACTIVE (cap))
1043 return SANE_STATUS_INVAL;
1044
1045 if (action == SANE_ACTION_GET_VALUE)
1046 {
1047 switch (option)
1048 {
1049 /* word options: */
1050 case OPT_NUM_OPTS:
1051 case OPT_X_RESOLUTION:
1052 case OPT_Y_RESOLUTION:
1053 case OPT_RESOLUTION_BIND:
1054 case OPT_PREVIEW:
1055 case OPT_TL_X:
1056 case OPT_TL_Y:
1057 case OPT_BR_X:
1058 case OPT_BR_Y:
1059 case OPT_BRIGHTNESS:
1060 case OPT_CONTRAST:
1061 case OPT_THRESHOLD:
1062 case OPT_NEGATIVE:
1063 case OPT_MIRROR:
1064 *(SANE_Word *) val = s->val[option].w;
1065 return SANE_STATUS_GOOD;
1066
1067 /* string options */
1068
1069 case OPT_MODE:
1070 case OPT_HALFTONE_PATTERN:
1071 status = sanei_constrain_value (s->opt + option, s->val[option].s,
1072 info);
1073 strcpy (val, s->val[option].s);
1074 return SANE_STATUS_GOOD;
1075 }
1076 }
1077 else if (action == SANE_ACTION_SET_VALUE)
1078 {
1079 if (!SANE_OPTION_IS_SETTABLE (cap))
1080 return SANE_STATUS_INVAL;
1081
1082 status = sanei_constrain_value (s->opt + option, val, info);
1083
1084 if (status != SANE_STATUS_GOOD)
1085 return status;
1086
1087
1088 switch (option)
1089 {
1090 /* resolution should be uniform for previews, or when the
1091 user says so. */
1092 case OPT_PREVIEW:
1093 s->val[option].w = *(SANE_Word *) val;
1094 if (*(SANE_Word *) val) {
1095 s->val[OPT_Y_RESOLUTION].w = s->val[OPT_X_RESOLUTION].w;
1096 if (info)
1097 *info |= SANE_INFO_RELOAD_OPTIONS;
1098 }
1099 /* always recalculate! */
1100 calc_parameters (s);
1101 if (info)
1102 *info |= SANE_INFO_RELOAD_PARAMS;
1103 return SANE_STATUS_GOOD;
1104
1105 case OPT_RESOLUTION_BIND:
1106 s->val[option].w = *(SANE_Word *) val;
1107 if (*(SANE_Word *) val) {
1108 s->val[OPT_Y_RESOLUTION].w = s->val[OPT_X_RESOLUTION].w;
1109 calc_parameters (s);
1110 if (info)
1111 *info |= SANE_INFO_RELOAD_PARAMS |
1112 SANE_INFO_RELOAD_OPTIONS;
1113 }
1114 return SANE_STATUS_GOOD;
1115
1116 case OPT_X_RESOLUTION:
1117 if (s->val[OPT_PREVIEW].w || s->val[OPT_RESOLUTION_BIND].w) {
1118 s->val[OPT_Y_RESOLUTION].w = *(SANE_Word *)val;
1119 if (info)
1120 *info |= SANE_INFO_RELOAD_OPTIONS;
1121 }
1122 s->val[option].w = *(SANE_Word *) val;
1123 calc_parameters (s);
1124 if (info)
1125 *info |= SANE_INFO_RELOAD_PARAMS;
1126 return SANE_STATUS_GOOD;
1127
1128 case OPT_Y_RESOLUTION:
1129 if (s->val[OPT_PREVIEW].w || s->val[OPT_RESOLUTION_BIND].w) {
1130 s->val[OPT_X_RESOLUTION].w = *(SANE_Word *)val;
1131 if (info)
1132 *info |= SANE_INFO_RELOAD_OPTIONS;
1133 }
1134 s->val[option].w = *(SANE_Word *) val;
1135 calc_parameters (s);
1136 if (info)
1137 *info |= SANE_INFO_RELOAD_PARAMS;
1138 return SANE_STATUS_GOOD;
1139
1140 /* these ones don't have crazy side effects */
1141 case OPT_TL_X:
1142 case OPT_TL_Y:
1143 case OPT_BR_Y:
1144 s->val[option].w = *(SANE_Word *) val;
1145 calc_parameters (s);
1146 if (info)
1147 *info |= SANE_INFO_RELOAD_PARAMS;
1148 return SANE_STATUS_GOOD;
1149
1150 /* this one is somewhat imprecise */
1151 case OPT_BR_X:
1152 s->val[option].w = *(SANE_Word *) val;
1153 calc_parameters (s);
1154 if (info)
1155 *info |= SANE_INFO_RELOAD_PARAMS
1156 | SANE_INFO_INEXACT;
1157 return SANE_STATUS_GOOD;
1158
1159 /* no side-effects whatsoever */
1160 case OPT_BRIGHTNESS:
1161 case OPT_CONTRAST:
1162 case OPT_THRESHOLD:
1163 case OPT_NEGATIVE:
1164 case OPT_MIRROR:
1165
1166 s->val[option].w = *(SANE_Word *) val;
1167 return SANE_STATUS_GOOD;
1168
1169 /* string options */
1170 case OPT_HALFTONE_PATTERN:
1171 if (info)
1172 *info |= SANE_INFO_RELOAD_OPTIONS;
1173 if (s->val[option].s)
1174 free (s->val[option].s);
1175 s->val[option].s = strdup (val);
1176 return SANE_STATUS_GOOD;
1177
1178 case OPT_MODE:
1179 status = mode_update (s, val);
1180 if (status != SANE_STATUS_GOOD)
1181 return status;
1182 if (s->val[option].s)
1183 free (s->val[option].s);
1184 s->val[option].s = strdup (val);
1185
1186 if (info)
1187 *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
1188 return SANE_STATUS_GOOD;
1189 } /* End of switch */
1190 } /* End of SET_VALUE */
1191 return SANE_STATUS_INVAL;
1192 }
1193
1194 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)1195 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
1196 {
1197 Abaton_Scanner *s = handle;
1198
1199 DBG (FLOW_CONTROL, "Entering sane_get_parameters\n");
1200 calc_parameters (s);
1201
1202
1203 if (params)
1204 *params = s->params;
1205 return SANE_STATUS_GOOD;
1206 }
1207
1208 SANE_Status
sane_start(SANE_Handle handle)1209 sane_start (SANE_Handle handle)
1210 {
1211 Abaton_Scanner *s = handle;
1212 SANE_Status status;
1213
1214 /* First make sure we have a current parameter set. Some of the
1215 parameters will be overwritten below, but that's OK. */
1216
1217 calc_parameters (s);
1218
1219 if (s->fd < 0)
1220 {
1221 /* this is the first (and maybe only) pass... */
1222
1223 status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, 0);
1224 if (status != SANE_STATUS_GOOD)
1225 {
1226 DBG (ERROR_MESSAGE, "open: open of %s failed: %s\n",
1227 s->hw->sane.name, sane_strstatus (status));
1228 return status;
1229 }
1230 }
1231
1232 status = wait_ready (s->fd);
1233 if (status != SANE_STATUS_GOOD)
1234 {
1235 DBG (ERROR_MESSAGE, "open: wait_ready() failed: %s\n",
1236 sane_strstatus (status));
1237 goto stop_scanner_and_return;
1238 }
1239
1240 status = request_sense (s);
1241 if (status != SANE_STATUS_GOOD)
1242 {
1243 DBG (ERROR_MESSAGE, "sane_start: request_sense revealed error: %s\n",
1244 sane_strstatus (status));
1245 goto stop_scanner_and_return;
1246 }
1247
1248 status = set_window (s);
1249 if (status != SANE_STATUS_GOOD)
1250 {
1251 DBG (ERROR_MESSAGE, "open: set scan area command failed: %s\n",
1252 sane_strstatus (status));
1253 goto stop_scanner_and_return;
1254 }
1255
1256 s->scanning = SANE_TRUE;
1257 s->AbortedByUser = SANE_FALSE;
1258
1259 status = start_scan (s);
1260 if (status != SANE_STATUS_GOOD)
1261 goto stop_scanner_and_return;
1262
1263 return SANE_STATUS_GOOD;
1264
1265 stop_scanner_and_return:
1266 s->scanning = SANE_FALSE;
1267 s->AbortedByUser = SANE_FALSE;
1268 return status;
1269 }
1270
1271 SANE_Status
sane_read(SANE_Handle handle,SANE_Byte * buf,SANE_Int max_len,SANE_Int * len)1272 sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
1273 SANE_Int * len)
1274 {
1275 Abaton_Scanner *s = handle;
1276 SANE_Status status;
1277
1278 uint8_t get_data_status[10];
1279 uint8_t read[10];
1280
1281 uint8_t result[12];
1282 size_t size;
1283 SANE_Int data_av = 0;
1284 SANE_Int data_length = 0;
1285 SANE_Int offset = 0;
1286 SANE_Int rread = 0;
1287 SANE_Bool Pseudo8bit = SANE_FALSE;
1288
1289
1290 *len = 0;
1291
1292 /* don't let bogus read requests reach the scanner */
1293 /* this is a sub-optimal way of doing this, I'm sure */
1294 if (!s->scanning)
1295 return SANE_STATUS_EOF;
1296
1297 if (!strcmp (s->val[OPT_MODE].s, "Gray16"))
1298 Pseudo8bit = SANE_TRUE;
1299
1300 memset (get_data_status, 0, sizeof (get_data_status));
1301 get_data_status[0] = GET_DATA_STATUS;
1302 /* This means "block" for Apple scanners, it seems to be the same
1303 for Abaton. The scanner will do non-blocking I/O, but I don't
1304 want to go there right now. */
1305 get_data_status[1] = 1;
1306 STORE8 (get_data_status + 8, sizeof (result));
1307
1308 memset (read, 0, sizeof (read));
1309 read[0] = READ_10;
1310
1311 do
1312 {
1313 size = sizeof (result);
1314 /* this isn't necessary */
1315 /* memset (result, 0, size); */
1316 status = sanei_scsi_cmd (s->fd, get_data_status,
1317 sizeof (get_data_status), result, &size);
1318
1319 if (status != SANE_STATUS_GOOD)
1320 return status;
1321 if (!size)
1322 {
1323 DBG (ERROR_MESSAGE, "sane_read: cannot get_data_status.\n");
1324 return SANE_STATUS_IO_ERROR;
1325 }
1326
1327 /* this is not an accurate name, but oh well... */
1328 data_length = GET24 (result);
1329 data_av = GET24 (result + 9);
1330
1331 /* don't check result[3] here, because that screws things up
1332 somewhat */
1333 if (data_length) {
1334 DBG (IO_MESSAGE,
1335 "sane_read: (status) Available in scanner buffer %u.\n",
1336 data_av);
1337
1338 if (Pseudo8bit)
1339 {
1340 if ((data_av * 2) + offset > max_len)
1341 rread = (max_len - offset) / 2;
1342 else
1343 rread = data_av;
1344 }
1345 else if (data_av + offset > max_len)
1346 {
1347 rread = max_len - offset;
1348 }
1349 else
1350 {
1351 rread = data_av;
1352 }
1353
1354 DBG (IO_MESSAGE,
1355 "sane_read: (action) Actual read request for %u bytes.\n",
1356 rread);
1357
1358 size = rread;
1359
1360 STORE24 (read + 6, rread);
1361
1362 status = sanei_scsi_cmd (s->fd, read, sizeof (read),
1363 buf + offset, &size);
1364
1365 if (Pseudo8bit)
1366 {
1367 SANE_Int byte;
1368 SANE_Int pos = offset + (rread << 1) - 1;
1369 SANE_Byte B;
1370 for (byte = offset + rread - 1; byte >= offset; byte--)
1371 {
1372 B = buf[byte];
1373 /* don't invert these! */
1374 buf[pos--] = B << 4; /* low (right) nibble */
1375 buf[pos--] = B & 0xF0; /* high (left) nibble */
1376 }
1377 /* putting an end to bitop abuse here */
1378 offset += size * 2;
1379 }
1380 else
1381 offset += size;
1382
1383 DBG (IO_MESSAGE, "sane_read: Buffer %u of %u full %g%%\n",
1384 offset, max_len, (double) (offset * 100. / max_len));
1385 }
1386 }
1387 while (offset < max_len && data_length != 0 && !s->AbortedByUser);
1388
1389 if (s->AbortedByUser)
1390 {
1391 s->scanning = SANE_FALSE;
1392
1393 if (status != SANE_STATUS_GOOD)
1394 {
1395 DBG (ERROR_MESSAGE, "sane_read: request_sense revealed error: %s\n",
1396 sane_strstatus (status));
1397 return status;
1398 }
1399
1400 status = sanei_scsi_cmd (s->fd, test_unit_ready,
1401 sizeof (test_unit_ready), 0, 0);
1402 if (status != SANE_STATUS_GOOD || status != SANE_STATUS_INVAL)
1403 return status;
1404 return SANE_STATUS_CANCELLED;
1405 }
1406
1407 if (!data_length)
1408 {
1409 s->scanning = SANE_FALSE;
1410 DBG (IO_MESSAGE, "sane_read: (status) No more data...");
1411 if (!offset)
1412 {
1413 /* this shouldn't happen */
1414 *len = 0;
1415 DBG (IO_MESSAGE, "EOF\n");
1416 return SANE_STATUS_EOF;
1417 }
1418 else
1419 {
1420 *len = offset;
1421 DBG (IO_MESSAGE, "GOOD\n");
1422 return SANE_STATUS_GOOD;
1423 }
1424 }
1425
1426
1427 DBG (FLOW_CONTROL,
1428 "sane_read: Normal Exiting, Aborted=%u, data_length=%u\n",
1429 s->AbortedByUser, data_av);
1430 *len = offset;
1431
1432 return SANE_STATUS_GOOD;
1433 }
1434
1435 void
sane_cancel(SANE_Handle handle)1436 sane_cancel (SANE_Handle handle)
1437 {
1438 Abaton_Scanner *s = handle;
1439
1440 if (s->scanning)
1441 {
1442 if (s->AbortedByUser)
1443 {
1444 DBG (FLOW_CONTROL,
1445 "sane_cancel: Already Aborted. Please Wait...\n");
1446 }
1447 else
1448 {
1449 s->scanning = SANE_FALSE;
1450 s->AbortedByUser = SANE_TRUE;
1451 DBG (FLOW_CONTROL, "sane_cancel: Signal Caught! Aborting...\n");
1452 }
1453 }
1454 else
1455 {
1456 if (s->AbortedByUser)
1457 {
1458 DBG (FLOW_CONTROL, "sane_cancel: Scan has not been initiated yet."
1459 "we probably received a signal while writing data.\n");
1460 s->AbortedByUser = SANE_FALSE;
1461 }
1462 else
1463 {
1464 DBG (FLOW_CONTROL, "sane_cancel: Scan has not been initiated "
1465 "yet (or it's over).\n");
1466 }
1467 }
1468
1469 return;
1470 }
1471
1472 SANE_Status
sane_set_io_mode(SANE_Handle handle,SANE_Bool non_blocking)1473 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
1474 {
1475 handle = handle; /* silence gcc */
1476 non_blocking = non_blocking; /* silence gcc */
1477
1478 DBG (FLOW_CONTROL, "sane_set_io_mode: Don't call me please. "
1479 "Unimplemented function\n");
1480 return SANE_STATUS_UNSUPPORTED;
1481 }
1482
1483 SANE_Status
sane_get_select_fd(SANE_Handle handle,SANE_Int * fd)1484 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
1485 {
1486 handle = handle; /* silence gcc */
1487 fd = fd; /* silence gcc */
1488
1489 DBG (FLOW_CONTROL, "sane_get_select_fd: Don't call me please. "
1490 "Unimplemented function\n");
1491 return SANE_STATUS_UNSUPPORTED;
1492 }
1493