1 /* sane - Scanner Access Now Easy.
2
3 Copyright (C) 2001, Marcio Luis Teixeira
4
5 Parts copyright (C) 1996, 1997 Andreas Beck
6 Parts copyright (C) 2000, 2001 Michael Herder <crapsite@gmx.net>
7 Parts copyright (C) 2001 Henning Meier-Geinitz <henning@meier-geinitz.de>
8 Parts copyright (C) 2006 Patrick Lessard
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 #define BUILD 2
45 #define MM_IN_INCH 25.4
46
47 #include "../include/sane/config.h"
48
49 #include <stdlib.h>
50 #include <string.h>
51 #include <stdio.h>
52 #include <unistd.h>
53 #include <fcntl.h>
54 #include <sys/ioctl.h>
55
56 #include "../include/sane/sane.h"
57 #include "../include/sane/sanei.h"
58 #include "../include/sane/saneopts.h"
59 #include "../include/sane/sanei_config.h"
60 #include "../include/sane/sanei_usb.h"
61 #include "../include/sane/sanei_pv8630.h"
62
63 #define BACKEND_NAME umax1220u
64 #define UMAX_CONFIG_FILE "umax1220u.conf"
65
66 #include "../include/sane/sanei_backend.h"
67
68 #include "umax1220u-common.c"
69
70 typedef struct Umax_Device
71 {
72 struct Umax_Device *next;
73 SANE_String name;
74 SANE_Device sane;
75 }
76 Umax_Device;
77
78 typedef struct Umax_Scanner
79 {
80 struct Umax_Scanner *next;
81 Umax_Device *device;
82 UMAX_Handle scan;
83 }
84 Umax_Scanner;
85
86 static int num_devices = 0;
87 static const SANE_Device **devlist = NULL;
88 static Umax_Device *first_dev = NULL;
89 static Umax_Scanner *first_handle = NULL;
90
91 static SANE_Parameters parms = {
92 SANE_FRAME_RGB,
93 0,
94 0, /* Number of bytes returned per scan line: */
95 0, /* Number of pixels per scan line. */
96 0, /* Number of lines for the current scan. */
97 8 /* Number of bits per sample. */
98 };
99
100 struct _SANE_Option
101 {
102 SANE_Option_Descriptor *descriptor;
103 SANE_Status (*callback) (struct _SANE_Option * option, SANE_Handle handle,
104 SANE_Action action, void *value,
105 SANE_Int * info);
106 };
107
108 typedef struct _SANE_Option SANE_Option;
109
110 static SANE_Word getNumberOfOptions (void); /* Forward declaration */
111
112 /*
113 This read-only option returns the number of options available for
114 the device. It should be the first option in the options array
115 declared below.
116 */
117
118 static SANE_Option_Descriptor optionNumOptionsDescriptor = {
119 SANE_NAME_NUM_OPTIONS,
120 SANE_TITLE_NUM_OPTIONS,
121 SANE_DESC_NUM_OPTIONS,
122 SANE_TYPE_INT,
123 SANE_UNIT_NONE,
124 sizeof (SANE_Word),
125 SANE_CAP_SOFT_DETECT,
126 SANE_CONSTRAINT_NONE,
127 {NULL}
128 };
129
130 static SANE_Status
optionNumOptionsCallback(SANE_Option * option,SANE_Handle handle,SANE_Action action,void * value,SANE_Int * info)131 optionNumOptionsCallback (SANE_Option * option, SANE_Handle handle,
132 SANE_Action action, void *value, SANE_Int * info)
133 {
134 option = option;
135 handle = handle;
136 info = info; /* Eliminate warning about unused parameters */
137
138 if (action != SANE_ACTION_GET_VALUE)
139 return SANE_STATUS_INVAL;
140 *(SANE_Word *) value = getNumberOfOptions ();
141 return SANE_STATUS_GOOD;
142 }
143
144 /*
145 This option lets the user select the scan resolution. The UMAX
146 scanner only supports the following resolutions: 75, 150, 300 and
147 600
148 */
149
150 static const SANE_Word optionResolutionList[] = {
151 4, /* Number of elements */
152 75, 150, 300, 600 /* Resolution list */
153 };
154
155 static SANE_Option_Descriptor optionResolutionDescriptor = {
156 SANE_NAME_SCAN_RESOLUTION,
157 SANE_TITLE_SCAN_RESOLUTION,
158 SANE_DESC_SCAN_RESOLUTION,
159 SANE_TYPE_INT,
160 SANE_UNIT_DPI,
161 sizeof (SANE_Word),
162 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC,
163 SANE_CONSTRAINT_WORD_LIST,
164 {(const SANE_String_Const *) optionResolutionList}
165 };
166
167 static SANE_Word optionResolutionValue = 75;
168
169 static SANE_Status
optionResolutionCallback(SANE_Option * option,SANE_Handle handle,SANE_Action action,void * value,SANE_Int * info)170 optionResolutionCallback (SANE_Option * option, SANE_Handle handle,
171 SANE_Action action, void *value, SANE_Int * info)
172 {
173 SANE_Status status;
174 SANE_Word autoValue = 75;
175
176 handle = handle; /* Eliminate warning about unused parameters */
177
178 switch (action)
179 {
180 case SANE_ACTION_SET_AUTO:
181 status =
182 sanei_constrain_value (option->descriptor, (void *) &autoValue, info);
183 if (status != SANE_STATUS_GOOD)
184 return status;
185 optionResolutionValue = autoValue;
186 *info |= SANE_INFO_RELOAD_PARAMS;
187 break;
188 case SANE_ACTION_SET_VALUE:
189 *info |= SANE_INFO_RELOAD_PARAMS;
190 optionResolutionValue = *(SANE_Word *) value;
191 break;
192 case SANE_ACTION_GET_VALUE:
193 *(SANE_Word *) value = optionResolutionValue;
194 break;
195 }
196 return SANE_STATUS_GOOD;
197 }
198
199 /*
200 This option lets the user select a gray scale scan
201 */
202 static SANE_Word optionGrayscaleValue = SANE_FALSE;
203
204 static SANE_Option_Descriptor optionGrayscaleDescriptor = {
205 "gray",
206 SANE_I18N ("Grayscale scan"),
207 SANE_I18N ("Do a grayscale rather than color scan"),
208 SANE_TYPE_BOOL,
209 SANE_UNIT_NONE,
210 sizeof (SANE_Word),
211 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
212 SANE_CONSTRAINT_NONE,
213 {NULL}
214 };
215
216 static SANE_Status
optionGrayscaleCallback(SANE_Option * option,SANE_Handle handle,SANE_Action action,void * value,SANE_Int * info)217 optionGrayscaleCallback (SANE_Option * option, SANE_Handle handle,
218 SANE_Action action, void *value, SANE_Int * info)
219 {
220 handle = handle;
221 option = option; /* Eliminate warning about unused parameters */
222
223 switch (action)
224 {
225 case SANE_ACTION_SET_AUTO:
226 return SANE_STATUS_INVAL;
227 break;
228 case SANE_ACTION_SET_VALUE:
229 *info |= SANE_INFO_RELOAD_PARAMS;
230 optionGrayscaleValue = *(SANE_Bool *) value;
231 break;
232 case SANE_ACTION_GET_VALUE:
233 *(SANE_Word *) value = optionGrayscaleValue;
234 break;
235 }
236 return SANE_STATUS_GOOD;
237 }
238
239 /*
240 This option is a button that allows the user to turn off the
241 lamp in the UMAX scanner
242 */
243
244 static SANE_Option_Descriptor optionLampOffDescriptor = {
245 "lamp-off",
246 SANE_I18N ("Lamp off"),
247 SANE_I18N ("Turn off scanner lamp"),
248 SANE_TYPE_BUTTON,
249 SANE_UNIT_NONE,
250 0,
251 SANE_CAP_SOFT_SELECT,
252 SANE_CONSTRAINT_NONE,
253 {NULL}
254 };
255
256 static SANE_Status
optionLampOffCallback(SANE_Option * option,SANE_Handle handle,SANE_Action action,void * value,SANE_Int * info)257 optionLampOffCallback (SANE_Option * option, SANE_Handle handle,
258 SANE_Action action, void *value, SANE_Int * info)
259 {
260 Umax_Scanner *scanner = handle;
261 SANE_Status res = SANE_STATUS_GOOD;
262
263 /* Eliminate warnings about unused parameters */
264 option = option;
265 handle = handle;
266 info = info;
267 value = value;
268
269 if (action != SANE_ACTION_SET_VALUE)
270 return SANE_STATUS_INVAL;
271
272 res = UMAX_set_lamp_state (&scanner->scan, UMAX_LAMP_OFF);
273
274 return res;
275 }
276
277 static const SANE_Range widthRange = {
278 0, /* minimum */
279 SANE_FIX (UMAX_MAX_WIDTH * MM_IN_INCH / 600), /* maximum */
280 0 /* quantization */
281 };
282
283 static const SANE_Range heightRange = {
284 0, /* minimum */
285 SANE_FIX (UMAX_MAX_HEIGHT * MM_IN_INCH / 600), /* maximum */
286 0 /* quantization */
287 };
288
289 /*
290 This option controls the top-left-x corner of the scan
291 */
292
293 static SANE_Fixed optionTopLeftXValue = 0;
294
295 static SANE_Option_Descriptor optionTopLeftXDescriptor = {
296 SANE_NAME_SCAN_TL_X,
297 SANE_TITLE_SCAN_TL_X,
298 SANE_DESC_SCAN_TL_X,
299 SANE_TYPE_FIXED,
300 SANE_UNIT_MM,
301 sizeof (SANE_Fixed),
302 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
303 SANE_CONSTRAINT_RANGE,
304 {(const SANE_String_Const *) & widthRange}
305 };
306
307 static SANE_Status
optionTopLeftXCallback(SANE_Option * option,SANE_Handle handle,SANE_Action action,void * value,SANE_Int * info)308 optionTopLeftXCallback (SANE_Option * option, SANE_Handle handle,
309 SANE_Action action, void *value, SANE_Int * info)
310 {
311 option = option;
312 handle = handle;
313 value = value; /* Eliminate warning about unused parameters */
314
315 switch (action)
316 {
317 case SANE_ACTION_SET_AUTO:
318 return SANE_STATUS_INVAL;
319 break;
320 case SANE_ACTION_SET_VALUE:
321 optionTopLeftXValue = *(SANE_Fixed *) value;
322 *info |= SANE_INFO_RELOAD_PARAMS;
323 break;
324 case SANE_ACTION_GET_VALUE:
325 *(SANE_Fixed *) value = optionTopLeftXValue;
326 break;
327 }
328 return SANE_STATUS_GOOD;
329 }
330
331 /*
332 This option controls the top-left-y corner of the scan
333 */
334
335 static SANE_Fixed optionTopLeftYValue = 0;
336
337 static SANE_Option_Descriptor optionTopLeftYDescriptor = {
338 SANE_NAME_SCAN_TL_Y,
339 SANE_TITLE_SCAN_TL_Y,
340 SANE_DESC_SCAN_TL_Y,
341 SANE_TYPE_FIXED,
342 SANE_UNIT_MM,
343 sizeof (SANE_Fixed),
344 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
345 SANE_CONSTRAINT_RANGE,
346 {(const SANE_String_Const *) & heightRange}
347 };
348
349 static SANE_Status
optionTopLeftYCallback(SANE_Option * option,SANE_Handle handle,SANE_Action action,void * value,SANE_Int * info)350 optionTopLeftYCallback (SANE_Option * option, SANE_Handle handle,
351 SANE_Action action, void *value, SANE_Int * info)
352 {
353 /* Eliminate warnings about unused parameters */
354 option = option;
355 handle = handle;
356
357 switch (action)
358 {
359 case SANE_ACTION_SET_AUTO:
360 return SANE_STATUS_INVAL;
361 break;
362 case SANE_ACTION_SET_VALUE:
363 optionTopLeftYValue = *(SANE_Fixed *) value;
364 *info |= SANE_INFO_RELOAD_PARAMS;
365 break;
366 case SANE_ACTION_GET_VALUE:
367 *(SANE_Fixed *) value = optionTopLeftYValue;
368 break;
369 }
370 return SANE_STATUS_GOOD;
371 }
372
373 /*
374 This option controls the bot-right-x corner of the scan
375 */
376
377 static SANE_Fixed optionBotRightXValue
378 = SANE_FIX (UMAX_MAX_WIDTH * MM_IN_INCH / 600);
379
380 static SANE_Option_Descriptor optionBotRightXDescriptor = {
381 SANE_NAME_SCAN_BR_X,
382 SANE_TITLE_SCAN_BR_X,
383 SANE_DESC_SCAN_BR_X,
384 SANE_TYPE_FIXED,
385 SANE_UNIT_MM,
386 sizeof (SANE_Fixed),
387 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
388 SANE_CONSTRAINT_RANGE,
389 {(const SANE_String_Const *) & widthRange}
390 };
391
392 static SANE_Status
optionBotRightXCallback(SANE_Option * option,SANE_Handle handle,SANE_Action action,void * value,SANE_Int * info)393 optionBotRightXCallback (SANE_Option * option, SANE_Handle handle,
394 SANE_Action action, void *value, SANE_Int * info)
395 {
396 /* Eliminate warnings about unused parameters */
397 option = option;
398 handle = handle;
399
400 switch (action)
401 {
402 case SANE_ACTION_SET_AUTO:
403 return SANE_STATUS_INVAL;
404 break;
405 case SANE_ACTION_SET_VALUE:
406 optionBotRightXValue = *(SANE_Fixed *) value;
407 *info |= SANE_INFO_RELOAD_PARAMS;
408 break;
409 case SANE_ACTION_GET_VALUE:
410 *(SANE_Fixed *) value = optionBotRightXValue;
411 break;
412 }
413 return SANE_STATUS_GOOD;
414 }
415
416 /*
417 This option controls the bot-right-y corner of the scan
418 */
419
420 static SANE_Fixed optionBotRightYValue
421 = SANE_FIX (UMAX_MAX_HEIGHT * MM_IN_INCH / 600);
422
423 static SANE_Option_Descriptor optionBotRightYDescriptor = {
424 SANE_NAME_SCAN_BR_Y,
425 SANE_TITLE_SCAN_BR_Y,
426 SANE_DESC_SCAN_BR_Y,
427 SANE_TYPE_FIXED,
428 SANE_UNIT_MM,
429 sizeof (SANE_Fixed),
430 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
431 SANE_CONSTRAINT_RANGE,
432 {(const SANE_String_Const *) & heightRange}
433 };
434
435 static SANE_Status
optionBotRightYCallback(SANE_Option * option,SANE_Handle handle,SANE_Action action,void * value,SANE_Int * info)436 optionBotRightYCallback (SANE_Option * option, SANE_Handle handle,
437 SANE_Action action, void *value, SANE_Int * info)
438 {
439 /* Eliminate warnings about unused parameters */
440 option = option;
441 handle = handle;
442
443 switch (action)
444 {
445 case SANE_ACTION_SET_AUTO:
446 return SANE_STATUS_INVAL;
447 break;
448 case SANE_ACTION_SET_VALUE:
449 optionBotRightYValue = *(SANE_Fixed *) value;
450 *info |= SANE_INFO_RELOAD_PARAMS;
451 break;
452 case SANE_ACTION_GET_VALUE:
453 *(SANE_Fixed *) value = optionBotRightYValue;
454 break;
455 }
456 return SANE_STATUS_GOOD;
457 }
458
459 /*
460 The following array binds the option descriptors to
461 their respective callback routines
462 */
463
464 static SANE_Option so[] = {
465 {&optionNumOptionsDescriptor, optionNumOptionsCallback},
466 {&optionResolutionDescriptor, optionResolutionCallback},
467 {&optionGrayscaleDescriptor, optionGrayscaleCallback},
468 {&optionTopLeftXDescriptor, optionTopLeftXCallback},
469 {&optionTopLeftYDescriptor, optionTopLeftYCallback},
470 {&optionBotRightXDescriptor, optionBotRightXCallback},
471 {&optionBotRightYDescriptor, optionBotRightYCallback},
472 {&optionLampOffDescriptor, optionLampOffCallback}
473 };
474
475 static SANE_Word
getNumberOfOptions(void)476 getNumberOfOptions (void)
477 {
478 return NELEMS (so);
479 }
480
481 /*
482 This routine dispatches the control message to the appropriate
483 callback routine, it outght to be called by sane_control_option
484 after any driver specific validation.
485 */
486 static SANE_Status
dispatch_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * value,SANE_Int * info)487 dispatch_control_option (SANE_Handle handle, SANE_Int option,
488 SANE_Action action, void *value, SANE_Int * info)
489 {
490 SANE_Option *op = so + option;
491 SANE_Int myinfo = 0;
492 SANE_Status status = SANE_STATUS_GOOD;
493
494 if (option < 0 || option >= NELEMS (so))
495 return SANE_STATUS_INVAL; /* Unknown option ... */
496
497 if ((action == SANE_ACTION_SET_VALUE) &&
498 ((op->descriptor->cap & SANE_CAP_SOFT_SELECT) == 0))
499 return SANE_STATUS_INVAL;
500
501 if ((action == SANE_ACTION_GET_VALUE) &&
502 ((op->descriptor->cap & SANE_CAP_SOFT_DETECT) == 0))
503 return SANE_STATUS_INVAL;
504
505 if ((action == SANE_ACTION_SET_AUTO) &&
506 ((op->descriptor->cap & SANE_CAP_AUTOMATIC) == 0))
507 return SANE_STATUS_INVAL;
508
509 if (action == SANE_ACTION_SET_VALUE)
510 {
511 status = sanei_constrain_value (op->descriptor, value, &myinfo);
512 if (status != SANE_STATUS_GOOD)
513 return status;
514 }
515
516 status = (op->callback) (op, handle, action, value, &myinfo);
517
518 if (info)
519 *info = myinfo;
520
521 return status;
522 }
523
524 static SANE_Status
attach_scanner(const char * devicename,Umax_Device ** devp)525 attach_scanner (const char *devicename, Umax_Device ** devp)
526 {
527 UMAX_Handle scan;
528 Umax_Device *dev;
529 SANE_Status status;
530
531 DBG (3, "attach_scanner: %s\n", devicename);
532
533 for (dev = first_dev; dev; dev = dev->next)
534 {
535 if (strcmp (dev->sane.name, devicename) == 0)
536 {
537 if (devp)
538 *devp = dev;
539 return SANE_STATUS_GOOD;
540 }
541 }
542
543 dev = malloc (sizeof (*dev));
544 if (!dev)
545 return SANE_STATUS_NO_MEM;
546 memset (dev, '\0', sizeof (Umax_Device)); /* clear structure */
547
548 DBG (4, "attach_scanner: opening %s\n", devicename);
549
550 status = UMAX_open_device (&scan, devicename);
551 if (status != SANE_STATUS_GOOD)
552 {
553 DBG (1, "ERROR: attach_scanner: opening %s failed\n", devicename);
554 free (dev);
555 return status;
556 }
557 dev->name = strdup (devicename);
558 dev->sane.name = dev->name;
559 dev->sane.vendor = "UMAX";
560 dev->sane.model = UMAX_get_device_name (&scan);
561 dev->sane.type = "flatbed scanner";
562 UMAX_close_device (&scan);
563
564 ++num_devices;
565 dev->next = first_dev;
566 first_dev = dev;
567
568 if (devp)
569 *devp = dev;
570 return SANE_STATUS_GOOD;
571 }
572
573 /* callback function for sanei_usb_attach_matching_devices
574 */
575 static SANE_Status
attach_one(const char * name)576 attach_one (const char *name)
577 {
578 attach_scanner (name, 0);
579 return SANE_STATUS_GOOD;
580 }
581
582 /* This file implements a SANE backend for the UMAX Astra 1220U scanner.
583 */
584 SANE_Status
sane_init(SANE_Int * version_code,SANE_Auth_Callback authorize)585 sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
586 {
587 char config_line[PATH_MAX];
588 size_t len;
589 FILE *fp;
590
591 DBG_INIT ();
592
593 DBG (2, "sane_init: version_code %s 0, authorize %s 0\n",
594 version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!=");
595 DBG (1, "sane_init: SANE umax1220u backend version %d.%d.%d from %s\n",
596 SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING);
597
598 if (version_code)
599 *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD);
600
601 sanei_usb_init ();
602 sanei_pv8630_init ();
603
604 fp = sanei_config_open (UMAX_CONFIG_FILE);
605 if (!fp)
606 {
607 /* no config-file: try /dev/scanner and /dev/usbscanner. */
608 attach_scanner ("/dev/scanner", 0);
609 attach_scanner ("/dev/usbscanner", 0);
610 return SANE_STATUS_GOOD;
611 }
612
613 DBG (3, "reading configure file %s\n", UMAX_CONFIG_FILE);
614
615 while (sanei_config_read (config_line, sizeof (config_line), fp))
616 {
617 if (config_line[0] == '#')
618 continue; /* ignore line comments */
619
620 len = strlen (config_line);
621
622 if (!len)
623 continue; /* ignore empty lines */
624
625 DBG (4, "attach_matching_devices(%s)\n", config_line);
626 sanei_usb_attach_matching_devices (config_line, attach_one);
627 }
628
629 DBG (4, "finished reading configure file\n");
630
631 fclose (fp);
632
633 return SANE_STATUS_GOOD;
634 }
635
636 void
sane_exit(void)637 sane_exit (void)
638 {
639 Umax_Device *dev, *next;
640
641 DBG (3, "sane_exit\n");
642
643 for (dev = first_dev; dev; dev = next)
644 {
645 next = dev->next;
646 free (dev->name);
647 free (dev);
648 }
649
650 if (devlist)
651 free (devlist);
652 return;
653 }
654
655 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)656 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
657 {
658 Umax_Device *dev;
659 int i;
660
661 DBG (3, "sane_get_devices(local_only = %d)\n", local_only);
662
663 if (devlist)
664 free (devlist);
665
666 devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
667 if (!devlist)
668 return SANE_STATUS_NO_MEM;
669
670 i = 0;
671
672 for (dev = first_dev; i < num_devices; dev = dev->next)
673 devlist[i++] = &dev->sane;
674
675 devlist[i++] = 0;
676
677 *device_list = devlist;
678
679 return SANE_STATUS_GOOD;
680 }
681
682 SANE_Status
sane_open(SANE_String_Const devicename,SANE_Handle * handle)683 sane_open (SANE_String_Const devicename, SANE_Handle * handle)
684 {
685 Umax_Device *dev;
686 SANE_Status status;
687 Umax_Scanner *scanner;
688
689 DBG (3, "sane_open\n");
690
691 if (devicename[0]) /* search for devicename */
692 {
693 DBG (4, "sane_open: devicename=%s\n", devicename);
694
695 for (dev = first_dev; dev; dev = dev->next)
696 if (strcmp (dev->sane.name, devicename) == 0)
697 break;
698
699 if (!dev)
700 {
701 status = attach_scanner (devicename, &dev);
702 if (status != SANE_STATUS_GOOD)
703 return status;
704 }
705 }
706 else
707 {
708 DBG (2, "sane_open: no devicename, opening first device\n");
709 dev = first_dev;
710 }
711
712 if (!dev)
713 return SANE_STATUS_INVAL;
714
715 scanner = malloc (sizeof (*scanner));
716 if (!scanner)
717 return SANE_STATUS_NO_MEM;
718
719 memset (scanner, 0, sizeof (*scanner));
720 scanner->device = dev;
721
722 status = UMAX_open_device (&scanner->scan, dev->sane.name);
723 if (status != SANE_STATUS_GOOD)
724 {
725 free (scanner);
726 return status;
727 }
728
729 *handle = scanner;
730
731 /* insert newly opened handle into list of open handles: */
732 scanner->next = first_handle;
733
734 first_handle = scanner;
735
736 return SANE_STATUS_GOOD;
737 }
738
739 void
sane_close(SANE_Handle handle)740 sane_close (SANE_Handle handle)
741 {
742 Umax_Scanner *prev, *scanner;
743
744 DBG (3, "sane_close\n");
745
746 if (!first_handle)
747 {
748 DBG (1, "ERROR: sane_close: no handles opened\n");
749 return;
750 }
751
752 /* remove handle from list of open handles: */
753
754 prev = NULL;
755
756 for (scanner = first_handle; scanner; scanner = scanner->next)
757 {
758 if (scanner == handle)
759 break;
760
761 prev = scanner;
762 }
763
764 if (!scanner)
765 {
766 DBG (1, "ERROR: sane_close: invalid handle %p\n", handle);
767 return; /* oops, not a handle we know about */
768 }
769
770 if (prev)
771 prev->next = scanner->next;
772 else
773 first_handle = scanner->next;
774
775 UMAX_close_device (&scanner->scan);
776
777 free (scanner);
778 }
779
780 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle,SANE_Int option)781 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
782 {
783 handle = handle; /* Eliminate compiler warning */
784
785 DBG (3, "sane_get_option_descriptor: option = %d\n", option);
786 if (option < 0 || option >= NELEMS (so))
787 return NULL;
788 return so[option].descriptor;
789 }
790
791 SANE_Status
sane_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * value,SANE_Int * info)792 sane_control_option (SANE_Handle handle, SANE_Int option,
793 SANE_Action action, void *value, SANE_Int * info)
794 {
795 handle = handle; /* Eliminate compiler warning */
796
797 DBG (3,
798 "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n",
799 handle, option, action, value, (void*) info);
800
801 return dispatch_control_option (handle, option, action, value, info);
802 }
803
804 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)805 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
806 {
807 int rc = SANE_STATUS_GOOD;
808 int w =
809 SANE_UNFIX (optionBotRightXValue -
810 optionTopLeftXValue) / MM_IN_INCH * optionResolutionValue;
811 int h =
812 SANE_UNFIX (optionBotRightYValue -
813 optionTopLeftYValue) / MM_IN_INCH * optionResolutionValue;
814
815 handle = handle; /* Eliminate compiler warning */
816
817 DBG (3, "sane_get_parameters\n");
818 parms.depth = 8;
819 parms.last_frame = SANE_TRUE;
820 parms.pixels_per_line = w;
821 parms.lines = h;
822
823 if (optionGrayscaleValue == SANE_TRUE)
824 {
825 parms.format = SANE_FRAME_GRAY;
826 parms.bytes_per_line = w;
827 }
828 else
829 {
830 parms.format = SANE_FRAME_RGB;
831 parms.bytes_per_line = w * 3;
832 }
833 *params = parms;
834 return rc;
835 }
836
837 SANE_Status
sane_start(SANE_Handle handle)838 sane_start (SANE_Handle handle)
839 {
840 Umax_Scanner *scanner = handle;
841 SANE_Status res;
842
843 DBG (3, "sane_start\n");
844
845 res = UMAX_set_scan_parameters (&scanner->scan,
846 optionGrayscaleValue == SANE_FALSE,
847 SANE_UNFIX (optionTopLeftXValue) /
848 MM_IN_INCH * 600,
849 SANE_UNFIX (optionTopLeftYValue) /
850 MM_IN_INCH * 600,
851 SANE_UNFIX (optionBotRightXValue -
852 optionTopLeftXValue) /
853 MM_IN_INCH * optionResolutionValue,
854 SANE_UNFIX (optionBotRightYValue -
855 optionTopLeftYValue) /
856 MM_IN_INCH * optionResolutionValue,
857 optionResolutionValue,
858 optionResolutionValue);
859
860 if (res != SANE_STATUS_GOOD)
861 return res;
862
863 if (scanner->scan.model == ASTRA_1220U)
864 return UMAX_start_scan (&scanner->scan);
865 else
866 return UMAX_start_scan_2100U (&scanner->scan);
867 }
868
869 SANE_Status
sane_read(SANE_Handle handle,SANE_Byte * data,SANE_Int max_length,SANE_Int * length)870 sane_read (SANE_Handle handle, SANE_Byte * data,
871 SANE_Int max_length, SANE_Int * length)
872 {
873 Umax_Scanner *scanner = handle;
874 SANE_Status res;
875 int len;
876 unsigned char rgb[3];
877
878 len = *length = 0;
879
880 if (!data || !length)
881 return SANE_STATUS_INVAL;
882
883 if (scanner->scan.done)
884 {
885 res = UMAX_finish_scan (&scanner->scan);
886
887 if (scanner->scan.model == ASTRA_1220U)
888 res = UMAX_park_head (&scanner->scan);
889 else
890 res = UMAX_park_head_2100U (&scanner->scan);
891
892 return SANE_STATUS_EOF;
893 }
894
895 DBG (3, "sane_read: max_length = %d\n", max_length);
896
897 if (optionGrayscaleValue == SANE_FALSE)
898 {
899 while (!scanner->scan.done && (max_length >= 3))
900 {
901 res = UMAX_get_rgb (&scanner->scan, rgb);
902 if (res != SANE_STATUS_GOOD)
903 {
904 *length = 0;
905 return res;
906 }
907 *data++ = rgb[0];
908 *data++ = rgb[1];
909 *data++ = rgb[2];
910 max_length -= 3;
911 len += 3;
912 }
913 }
914 else
915 {
916 while (!scanner->scan.done && max_length)
917 {
918 res = UMAX_get_rgb (&scanner->scan, rgb);
919 if (res != SANE_STATUS_GOOD)
920 {
921 *length = 0;
922 return res;
923 }
924 *data++ = rgb[0];
925 max_length--;
926 len++;
927 }
928 }
929
930 *length = len;
931 return SANE_STATUS_GOOD;
932 }
933
934 void
sane_cancel(SANE_Handle handle)935 sane_cancel (SANE_Handle handle)
936 {
937 DBG (3, "sane_cancel: handle = %p\n", handle);
938 DBG (3, "sane_cancel: canceling is unsupported in this backend\n");
939 }
940
941 SANE_Status
sane_set_io_mode(SANE_Handle handle,SANE_Bool non_blocking)942 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
943 {
944 DBG (3, "sane_set_io_mode: handle = %p, non_blocking = %d\n", handle,
945 non_blocking);
946 if (non_blocking != SANE_FALSE)
947 return SANE_STATUS_UNSUPPORTED;
948 return SANE_STATUS_GOOD;
949 }
950
951 SANE_Status
sane_get_select_fd(SANE_Handle handle,SANE_Int * fd)952 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
953 {
954 DBG (3, "sane_get_select_fd: handle = %p, fd %s 0\n", handle,
955 fd ? "!=" : "=");
956 return SANE_STATUS_UNSUPPORTED;
957 }
958