1 /* sane - Scanner Access Now Easy.
2
3 BACKEND canon_lide70
4
5 Copyright (C) 2019 Juergen Ernst and pimvantend.
6
7 This file is part of the SANE package.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <https://www.gnu.org/licenses/>.
21
22 This file implements a SANE backend for the Canon CanoScan LiDE 70 and 600 */
23
24 #define BUILD 0
25 #define MM_IN_INCH 25.4
26
27 #include "../include/sane/config.h"
28
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <sys/ioctl.h>
35
36 #include "../include/sane/sane.h"
37 #include "../include/sane/sanei.h"
38 #include "../include/sane/saneopts.h"
39 #include "../include/sane/sanei_config.h"
40 #include "../include/sane/sanei_usb.h"
41 #define BACKEND_NAME canon_lide70
42 #define CANONUSB_CONFIG_FILE "canon_lide70.conf"
43 #include "../include/sane/sanei_backend.h"
44
45 typedef enum
46 {
47 opt_num_opts = 0,
48 opt_mode_group,
49 opt_threshold,
50 opt_mode,
51 opt_resolution,
52 opt_non_blocking,
53 opt_geometry_group,
54 opt_tl_x,
55 opt_tl_y,
56 opt_br_x,
57 opt_br_y,
58 /* must come last: */
59 num_options
60 }
61 canon_opts;
62
63 #include "canon_lide70-common.c"
64
65 static size_t
max_string_size(const SANE_String_Const strings[])66 max_string_size (const SANE_String_Const strings[])
67 {
68 size_t size, max_size = 0;
69 SANE_Int i;
70
71 for (i = 0; strings[i]; ++i)
72 {
73 size = strlen (strings[i]) + 1;
74 if (size > max_size)
75 max_size = size;
76 }
77 return max_size;
78 }
79
80 static SANE_String_Const mode_list[] = {
81 SANE_VALUE_SCAN_MODE_COLOR,
82 SANE_VALUE_SCAN_MODE_GRAY,
83 SANE_VALUE_SCAN_MODE_LINEART,
84 0
85 };
86
87 static SANE_Fixed init_tl_x = SANE_FIX (0.0);
88 static SANE_Fixed init_tl_y = SANE_FIX (0.0);
89 static SANE_Fixed init_br_x = SANE_FIX (80.0);
90 static SANE_Fixed init_br_y = SANE_FIX (100.0);
91 static SANE_Int init_threshold = 75;
92 static SANE_Int init_resolution = 600;
93 static SANE_String init_mode = SANE_VALUE_SCAN_MODE_COLOR;
94 static SANE_Int init_graymode = 0;
95 static SANE_Bool init_non_blocking = SANE_FALSE;
96
97 /*-----------------------------------------------------------------*/
98 /*
99 Scan range
100 */
101
102 static const SANE_Range widthRange = {
103 0, /* minimum */
104 SANE_FIX (CANON_MAX_WIDTH * MM_IN_INCH / 600), /* maximum */
105 0 /* quantization */
106 };
107
108 static const SANE_Range heightRange = {
109 0, /* minimum */
110 /* SANE_FIX (CANON_MAX_HEIGHT * MM_IN_INCH / 600 - TOP_EDGE ), maximum */
111 SANE_FIX (297.0),
112 0 /* quantization */
113 };
114
115 static const SANE_Range threshold_range = {
116 0,
117 100,
118 1
119 };
120
121 static SANE_Int resolution_list[] = { 5,
122 75,
123 150,
124 300,
125 600,
126 1200
127 };
128
129 typedef struct Canon_Device
130 {
131 struct Canon_Device *next;
132 SANE_String name;
133 SANE_Device sane;
134 }
135 Canon_Device;
136
137 /* Canon_Scanner is the type used for the sane handle */
138 typedef struct Canon_Scanner
139 {
140 struct Canon_Scanner *next;
141 Canon_Device *device;
142 CANON_Handle scan;
143 }
144 Canon_Scanner;
145
146 static int num_devices = 0;
147 static const SANE_Device **devlist = NULL;
148 static Canon_Device *first_dev = NULL;
149 static Canon_Scanner *first_handle = NULL;
150
151 /*-----------------------------------------------------------------*/
152 static SANE_Status
attach_scanner(const char * devicename,Canon_Device ** devp)153 attach_scanner (const char *devicename, Canon_Device ** devp)
154 {
155 CANON_Handle scan;
156 Canon_Device *dev;
157 SANE_Status status;
158
159 DBG (3, "attach_scanner: %s\n", devicename);
160
161 for (dev = first_dev; dev; dev = dev->next)
162 {
163 if (strcmp (dev->sane.name, devicename) == 0)
164 {
165 if (devp)
166 *devp = dev;
167 return SANE_STATUS_GOOD;
168 }
169 }
170
171 dev = malloc (sizeof (*dev));
172 if (!dev)
173 return SANE_STATUS_NO_MEM;
174 memset (dev, '\0', sizeof (Canon_Device)); /* clear structure */
175
176 DBG (4, "attach_scanner: opening %s\n", devicename);
177
178 status = CANON_open_device (&scan, devicename);
179 if (status != SANE_STATUS_GOOD)
180 {
181 DBG (1, "ERROR: attach_scanner: opening %s failed\n", devicename);
182 free (dev);
183 return status;
184 }
185 dev->name = strdup (devicename);
186 dev->sane.name = dev->name;
187 dev->sane.vendor = "CANON";
188 dev->sane.model = CANON_get_device_name (&scan);
189 dev->sane.type = "flatbed scanner";
190 CANON_close_device (&scan);
191
192 ++num_devices;
193 dev->next = first_dev;
194 first_dev = dev;
195
196 if (devp)
197 *devp = dev;
198 return SANE_STATUS_GOOD;
199 }
200
201
202 /* callback function for sanei_usb_attach_matching_devices */
203 static SANE_Status
attach_one(const char * name)204 attach_one (const char *name)
205 {
206 attach_scanner (name, 0);
207 return SANE_STATUS_GOOD;
208 }
209
210
211 /* Find our devices */
212 SANE_Status
sane_init(SANE_Int * version_code,SANE_Auth_Callback authorize)213 sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
214 {
215 char config_line[PATH_MAX];
216 size_t len;
217 FILE *fp;
218
219 DBG_INIT ();
220
221 #if 0
222 DBG_LEVEL = 10;
223 #endif
224
225 DBG (2, "sane_init: version_code %s 0, authorize %s 0\n",
226 version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!=");
227 DBG (1, "sane_init: SANE Canon LiDE70 backend version %d.%d.%d from %s\n",
228 V_MAJOR, V_MINOR, BUILD, PACKAGE_STRING);
229
230 if (version_code)
231 *version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, BUILD);
232
233 sanei_usb_init ();
234
235 fp = sanei_config_open (CANONUSB_CONFIG_FILE);
236
237 if (!fp)
238 {
239 /* no config-file: try these */
240 attach_scanner ("/dev/scanner", 0);
241 attach_scanner ("/dev/usbscanner", 0);
242 attach_scanner ("/dev/usb/scanner", 0);
243 return SANE_STATUS_GOOD;
244 }
245
246 DBG (3, "reading configure file %s\n", CANONUSB_CONFIG_FILE);
247
248 while (sanei_config_read (config_line, sizeof (config_line), fp))
249 {
250 if (config_line[0] == '#')
251 continue; /* ignore line comments */
252
253 len = strlen (config_line);
254
255 if (!len)
256 continue; /* ignore empty lines */
257
258 DBG (4, "attach_matching_devices(%s)\n", config_line);
259 sanei_usb_attach_matching_devices (config_line, attach_one);
260 }
261
262 DBG (4, "finished reading configure file\n");
263
264 fclose (fp);
265
266 return SANE_STATUS_GOOD;
267 }
268
269
270 void
sane_exit(void)271 sane_exit (void)
272 {
273 Canon_Device *dev, *next;
274
275 DBG (3, "sane_exit\n");
276
277 for (dev = first_dev; dev; dev = next)
278 {
279 next = dev->next;
280 free (dev->name);
281 free (dev);
282 }
283
284 if (devlist)
285 free (devlist);
286 return;
287 }
288
289
290 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)291 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
292 {
293 Canon_Device *dev;
294 int i;
295
296 DBG (3, "sane_get_devices(local_only = %d)\n", local_only);
297
298 if (devlist)
299 free (devlist);
300
301 devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
302 if (!devlist)
303 return SANE_STATUS_NO_MEM;
304
305 i = 0;
306
307 for (dev = first_dev; i < num_devices; dev = dev->next)
308 devlist[i++] = &dev->sane;
309
310 devlist[i++] = 0;
311
312 *device_list = devlist;
313
314 return SANE_STATUS_GOOD;
315 }
316
317 static SANE_Status
init_options(CANON_Handle * chndl)318 init_options (CANON_Handle * chndl)
319 {
320 SANE_Option_Descriptor *od;
321
322 DBG (2, "begin init_options: chndl=%p\n", (void *) chndl);
323
324 /* opt_num_opts */
325 od = &chndl->opt[opt_num_opts];
326 od->name = "";
327 od->title = SANE_TITLE_NUM_OPTIONS;
328 od->desc = SANE_DESC_NUM_OPTIONS;
329 od->type = SANE_TYPE_INT;
330 od->unit = SANE_UNIT_NONE;
331 od->size = sizeof (SANE_Word);
332 od->cap = SANE_CAP_SOFT_DETECT;
333 od->constraint_type = SANE_CONSTRAINT_NONE;
334 od->constraint.range = 0;
335 chndl->val[opt_num_opts].w = num_options;
336
337 DBG (2, "val[opt_num_opts]: %d\n", chndl->val[opt_num_opts].w);
338
339 /* opt_mode_group */
340 od = &chndl->opt[opt_mode_group];
341 od->name = "";
342 od->title = SANE_I18N ("Scan Mode");
343 od->desc = "";
344 od->type = SANE_TYPE_GROUP;
345 od->unit = SANE_UNIT_NONE;
346 od->size = 0;
347 od->cap = 0;
348 od->constraint_type = SANE_CONSTRAINT_NONE;
349 od->constraint.range = 0;
350 chndl->val[opt_mode_group].w = 0;
351
352 /* opt_mode */
353 od = &chndl->opt[opt_mode];
354 od->name = SANE_NAME_SCAN_MODE;
355 od->title = SANE_TITLE_SCAN_MODE;
356 od->desc = SANE_DESC_SCAN_MODE;
357 od->type = SANE_TYPE_STRING;
358 od->unit = SANE_UNIT_NONE;
359 od->size = max_string_size (mode_list);
360 od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
361 od->constraint_type = SANE_CONSTRAINT_STRING_LIST;
362 od->constraint.string_list = mode_list;
363 chndl->val[opt_mode].s = malloc (od->size);
364 if (!chndl->val[opt_mode].s)
365 return SANE_STATUS_NO_MEM;
366 strcpy (chndl->val[opt_mode].s, init_mode);
367 chndl->graymode = init_graymode;
368
369 /* opt_threshold */
370 od = &chndl->opt[opt_threshold];
371 od->name = SANE_NAME_THRESHOLD;
372 od->title = SANE_TITLE_THRESHOLD;
373 od->desc = SANE_DESC_THRESHOLD;
374 od->type = SANE_TYPE_INT;
375 od->unit = SANE_UNIT_PERCENT;
376 od->size = sizeof (SANE_Word);
377 od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE;
378 od->constraint_type = SANE_CONSTRAINT_RANGE;
379 od->constraint.range = &threshold_range;
380 chndl->val[opt_threshold].w = init_threshold;
381
382 /* opt_resolution */
383 od = &chndl->opt[opt_resolution];
384 od->name = SANE_NAME_SCAN_RESOLUTION;
385 od->title = SANE_TITLE_SCAN_RESOLUTION;
386 od->desc = SANE_DESC_SCAN_RESOLUTION;
387 od->type = SANE_TYPE_INT;
388 od->unit = SANE_UNIT_DPI;
389 od->size = sizeof (SANE_Word);
390 od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
391 od->constraint_type = SANE_CONSTRAINT_WORD_LIST;
392 if (chndl->productcode == 0x2224)
393 {
394 resolution_list[0] = 4;
395 }
396 od->constraint.word_list = resolution_list;
397 chndl->val[opt_resolution].w = init_resolution;
398
399 /* opt_non_blocking */
400 od = &chndl->opt[opt_non_blocking];
401 od->name = "non-blocking";
402 od->title = SANE_I18N ("Use non-blocking IO");
403 od->desc = SANE_I18N ("Use non-blocking IO for sane_read() if supported "
404 "by the frontend.");
405 od->type = SANE_TYPE_BOOL;
406 od->unit = SANE_UNIT_NONE;
407 od->size = sizeof (SANE_Word);
408 od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE;
409 od->constraint_type = SANE_CONSTRAINT_NONE;
410 od->constraint.range = 0;
411 chndl->val[opt_non_blocking].w = init_non_blocking;
412
413 /* opt_geometry_group */
414 od = &chndl->opt[opt_geometry_group];
415 od->name = "";
416 od->title = SANE_I18N ("Geometry");
417 od->desc = "";
418 od->type = SANE_TYPE_GROUP;
419 od->unit = SANE_UNIT_NONE;
420 od->size = 0;
421 od->cap = 0;
422 od->constraint_type = SANE_CONSTRAINT_NONE;
423 od->constraint.range = 0;
424 chndl->val[opt_geometry_group].w = 0;
425
426 /* opt_tl_x */
427 od = &chndl->opt[opt_tl_x];
428 od->name = SANE_NAME_SCAN_TL_X;
429 od->title = SANE_TITLE_SCAN_TL_X;
430 od->desc = SANE_DESC_SCAN_TL_X;
431 od->type = SANE_TYPE_FIXED;
432 od->unit = SANE_UNIT_MM;
433 od->size = sizeof (SANE_Word);
434 od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
435 od->constraint_type = SANE_CONSTRAINT_RANGE;
436 od->constraint.range = &widthRange;
437 chndl->val[opt_tl_x].w = init_tl_x;
438
439 /* opt_tl_y */
440 od = &chndl->opt[opt_tl_y];
441 od->name = SANE_NAME_SCAN_TL_Y;
442 od->title = SANE_TITLE_SCAN_TL_Y;
443 od->desc = SANE_DESC_SCAN_TL_Y;
444 od->type = SANE_TYPE_FIXED;
445 od->unit = SANE_UNIT_MM;
446 od->size = sizeof (SANE_Word);
447 od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
448 od->constraint_type = SANE_CONSTRAINT_RANGE;
449 od->constraint.range = &heightRange;
450 chndl->val[opt_tl_y].w = init_tl_y;
451
452 /* opt_br_x */
453 od = &chndl->opt[opt_br_x];
454 od->name = SANE_NAME_SCAN_BR_X;
455 od->title = SANE_TITLE_SCAN_BR_X;
456 od->desc = SANE_DESC_SCAN_BR_X;
457 od->type = SANE_TYPE_FIXED;
458 od->unit = SANE_UNIT_MM;
459 od->size = sizeof (SANE_Word);
460 od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
461 od->constraint_type = SANE_CONSTRAINT_RANGE;
462 od->constraint.range = &widthRange;
463 chndl->val[opt_br_x].w = init_br_x;
464
465 /* opt_br_y */
466 od = &chndl->opt[opt_br_y];
467 od->name = SANE_NAME_SCAN_BR_Y;
468 od->title = SANE_TITLE_SCAN_BR_Y;
469 od->desc = SANE_DESC_SCAN_BR_Y;
470 od->type = SANE_TYPE_FIXED;
471 od->unit = SANE_UNIT_MM;
472 od->size = sizeof (SANE_Word);
473 od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
474 od->constraint_type = SANE_CONSTRAINT_RANGE;
475 od->constraint.range = &heightRange;
476 chndl->val[opt_br_y].w = init_br_y;
477
478 DBG (2, "end init_options: chndl=%p\n", (void *) chndl);
479
480 return SANE_STATUS_GOOD;
481 }
482
483 SANE_Status
sane_open(SANE_String_Const devicename,SANE_Handle * handle)484 sane_open (SANE_String_Const devicename, SANE_Handle * handle)
485 {
486 Canon_Device *dev;
487 SANE_Status status;
488 Canon_Scanner *scanner;
489
490 DBG (3, "sane_open\n");
491
492 if (devicename[0]) /* search for devicename */
493 {
494 DBG (4, "sane_open: devicename=%s\n", devicename);
495
496 for (dev = first_dev; dev; dev = dev->next)
497 if (strcmp (dev->sane.name, devicename) == 0)
498 break;
499
500 if (!dev)
501 {
502 status = attach_scanner (devicename, &dev);
503
504 if (status != SANE_STATUS_GOOD)
505 return status;
506 }
507 }
508 else
509 {
510 DBG (2, "sane_open: no devicename, opening first device\n");
511 dev = first_dev;
512 }
513
514 if (!dev)
515 return SANE_STATUS_INVAL;
516
517 scanner = malloc (sizeof (*scanner));
518
519 if (!scanner)
520 return SANE_STATUS_NO_MEM;
521
522 memset (scanner, 0, sizeof (*scanner));
523 scanner->device = dev;
524
525 status = CANON_open_device (&scanner->scan, dev->sane.name);
526
527 if (status != SANE_STATUS_GOOD)
528 {
529 free (scanner);
530 return status;
531 }
532
533 status = init_options (&scanner->scan);
534
535 *handle = scanner;
536
537 /* insert newly opened handle into list of open handles: */
538 scanner->next = first_handle;
539
540 first_handle = scanner;
541
542 return status;
543 }
544
545 static void
print_options(CANON_Handle * chndl)546 print_options (CANON_Handle * chndl)
547 {
548 SANE_Option_Descriptor *od;
549 SANE_Word option_number;
550 SANE_Char caps[1024];
551
552 for (option_number = 0; option_number < num_options; option_number++)
553 {
554 od = &chndl->opt[option_number];
555 DBG (50, "-----> number: %d\n", option_number);
556 DBG (50, " name: `%s'\n", od->name);
557 DBG (50, " title: `%s'\n", od->title);
558 DBG (50, " description: `%s'\n", od->desc);
559 DBG (50, " type: %s\n",
560 od->type == SANE_TYPE_BOOL ? "SANE_TYPE_BOOL" :
561 od->type == SANE_TYPE_INT ? "SANE_TYPE_INT" :
562 od->type == SANE_TYPE_FIXED ? "SANE_TYPE_FIXED" :
563 od->type == SANE_TYPE_STRING ? "SANE_TYPE_STRING" :
564 od->type == SANE_TYPE_BUTTON ? "SANE_TYPE_BUTTON" :
565 od->type == SANE_TYPE_GROUP ? "SANE_TYPE_GROUP" : "unknown");
566 DBG (50, " unit: %s\n",
567 od->unit == SANE_UNIT_NONE ? "SANE_UNIT_NONE" :
568 od->unit == SANE_UNIT_PIXEL ? "SANE_UNIT_PIXEL" :
569 od->unit == SANE_UNIT_BIT ? "SANE_UNIT_BIT" :
570 od->unit == SANE_UNIT_MM ? "SANE_UNIT_MM" :
571 od->unit == SANE_UNIT_DPI ? "SANE_UNIT_DPI" :
572 od->unit == SANE_UNIT_PERCENT ? "SANE_UNIT_PERCENT" :
573 od->unit == SANE_UNIT_MICROSECOND ? "SANE_UNIT_MICROSECOND" :
574 "unknown");
575 DBG (50, " size: %d\n", od->size);
576 caps[0] = '\0';
577 if (od->cap & SANE_CAP_SOFT_SELECT)
578 strcat (caps, "SANE_CAP_SOFT_SELECT ");
579 if (od->cap & SANE_CAP_HARD_SELECT)
580 strcat (caps, "SANE_CAP_HARD_SELECT ");
581 if (od->cap & SANE_CAP_SOFT_DETECT)
582 strcat (caps, "SANE_CAP_SOFT_DETECT ");
583 if (od->cap & SANE_CAP_EMULATED)
584 strcat (caps, "SANE_CAP_EMULATED ");
585 if (od->cap & SANE_CAP_AUTOMATIC)
586 strcat (caps, "SANE_CAP_AUTOMATIC ");
587 if (od->cap & SANE_CAP_INACTIVE)
588 strcat (caps, "SANE_CAP_INACTIVE ");
589 if (od->cap & SANE_CAP_ADVANCED)
590 strcat (caps, "SANE_CAP_ADVANCED ");
591 DBG (50, " capabilities: %s\n", caps);
592 DBG (50, "constraint type: %s\n",
593 od->constraint_type == SANE_CONSTRAINT_NONE ?
594 "SANE_CONSTRAINT_NONE" :
595 od->constraint_type == SANE_CONSTRAINT_RANGE ?
596 "SANE_CONSTRAINT_RANGE" :
597 od->constraint_type == SANE_CONSTRAINT_WORD_LIST ?
598 "SANE_CONSTRAINT_WORD_LIST" :
599 od->constraint_type == SANE_CONSTRAINT_STRING_LIST ?
600 "SANE_CONSTRAINT_STRING_LIST" : "unknown");
601 if (od->type == SANE_TYPE_INT)
602 DBG (50, " value: %d\n", chndl->val[option_number].w);
603 else if (od->type == SANE_TYPE_FIXED)
604 DBG (50, " value: %f\n",
605 SANE_UNFIX (chndl->val[option_number].w));
606 else if (od->type == SANE_TYPE_STRING)
607 DBG (50, " value: %s\n", chndl->val[option_number].s);
608 }
609 }
610
611 void
sane_close(SANE_Handle handle)612 sane_close (SANE_Handle handle)
613 {
614 Canon_Scanner *prev, *scanner;
615 SANE_Status res;
616
617 DBG (3, "sane_close\n");
618
619 scanner = handle;
620 print_options (&scanner->scan);
621
622 if (!first_handle)
623 {
624 DBG (1, "ERROR: sane_close: no handles opened\n");
625 return;
626 }
627
628 /* remove handle from list of open handles: */
629
630 prev = NULL;
631
632 for (scanner = first_handle; scanner; scanner = scanner->next)
633 {
634 if (scanner == handle)
635 break;
636
637 prev = scanner;
638 }
639
640 if (!scanner)
641 {
642 DBG (1, "ERROR: sane_close: invalid handle %p\n", handle);
643 return; /* oops, not a handle we know about */
644 }
645
646 if (prev)
647 prev->next = scanner->next;
648 else
649 first_handle = scanner->next;
650
651 res = CANON_close_device (&scanner->scan);
652 DBG (3, "CANON_close_device returned: %d\n", res);
653 free (scanner);
654 }
655
656 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle,SANE_Int option)657 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
658 {
659 Canon_Scanner *scanner = handle;
660 CANON_Handle *chndl = &scanner->scan;
661
662
663 DBG (4, "sane_get_option_descriptor: handle=%p, option = %d\n",
664 (void *) handle, option);
665 if (option < 0 || option >= num_options)
666 {
667 DBG (3, "sane_get_option_descriptor: option < 0 || "
668 "option > num_options\n");
669 return 0;
670 }
671
672 return &chndl->opt[option];
673 }
674
675 SANE_Status
sane_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * value,SANE_Int * info)676 sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action,
677 void *value, SANE_Int * info)
678 {
679 Canon_Scanner *scanner = handle;
680 CANON_Handle *chndl = &scanner->scan;
681
682 SANE_Int myinfo = 0;
683 SANE_Status status;
684
685 DBG (4, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n",
686 (void *) handle, option, action, (void *) value, (void *) info);
687
688 if (option < 0 || option >= num_options)
689 {
690 DBG (1, "sane_control_option: option < 0 || option > num_options\n");
691 return SANE_STATUS_INVAL;
692 }
693
694 if (!SANE_OPTION_IS_ACTIVE (chndl->opt[option].cap))
695 {
696 DBG (1, "sane_control_option: option is inactive\n");
697 return SANE_STATUS_INVAL;
698 }
699
700 if (chndl->opt[option].type == SANE_TYPE_GROUP)
701 {
702 DBG (1, "sane_control_option: option is a group\n");
703 return SANE_STATUS_INVAL;
704 }
705
706 switch (action)
707 {
708 case SANE_ACTION_SET_VALUE:
709 if (!SANE_OPTION_IS_SETTABLE (chndl->opt[option].cap))
710 {
711 DBG (1, "sane_control_option: option is not setable\n");
712 return SANE_STATUS_INVAL;
713 }
714 status = sanei_constrain_value (&chndl->opt[option], value, &myinfo);
715 if (status != SANE_STATUS_GOOD)
716 {
717 DBG (3, "sane_control_option: sanei_constrain_value returned %s\n",
718 sane_strstatus (status));
719 return status;
720 }
721 switch (option)
722 {
723 case opt_tl_x: /* Fixed with parameter reloading */
724 case opt_tl_y:
725 case opt_br_x:
726 case opt_br_y:
727 if (chndl->val[option].w == *(SANE_Fixed *) value)
728 {
729 DBG (4, "sane_control_option: option %d (%s) not changed\n",
730 option, chndl->opt[option].name);
731 break;
732 }
733 chndl->val[option].w = *(SANE_Fixed *) value;
734 myinfo |= SANE_INFO_RELOAD_PARAMS;
735 DBG (4, "sane_control_option: set option %d (%s) to %.0f %s\n",
736 option, chndl->opt[option].name,
737 SANE_UNFIX (*(SANE_Fixed *) value),
738 chndl->opt[option].unit == SANE_UNIT_MM ? "mm" : "dpi");
739 break;
740 case opt_non_blocking:
741 if (chndl->val[option].w == *(SANE_Bool *) value)
742 {
743 DBG (4, "sane_control_option: option %d (%s) not changed\n",
744 option, chndl->opt[option].name);
745 break;
746 }
747 chndl->val[option].w = *(SANE_Bool *) value;
748 DBG (4, "sane_control_option: set option %d (%s) to %s\n",
749 option, chndl->opt[option].name,
750 *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
751 break;
752 case opt_resolution:
753 case opt_threshold:
754 if (chndl->val[option].w == *(SANE_Int *) value)
755 {
756 DBG (4, "sane_control_option: option %d (%s) not changed\n",
757 option, chndl->opt[option].name);
758 break;
759 }
760 chndl->val[option].w = *(SANE_Int *) value;
761 myinfo |= SANE_INFO_RELOAD_PARAMS;
762 myinfo |= SANE_INFO_RELOAD_OPTIONS;
763 DBG (4, "sane_control_option: set option %d (%s) to %d\n",
764 option, chndl->opt[option].name, *(SANE_Int *) value);
765 break;
766 case opt_mode:
767 if (strcmp (chndl->val[option].s, value) == 0)
768 {
769 DBG (4, "sane_control_option: option %d (%s) not changed\n",
770 option, chndl->opt[option].name);
771 break;
772 }
773 strcpy (chndl->val[option].s, (SANE_String) value);
774
775 if (strcmp (chndl->val[option].s, SANE_VALUE_SCAN_MODE_LINEART) ==
776 0)
777 {
778 chndl->opt[opt_threshold].cap &= ~SANE_CAP_INACTIVE;
779 chndl->graymode = 2;
780 }
781 if (strcmp (chndl->val[option].s, SANE_VALUE_SCAN_MODE_COLOR) == 0)
782 {
783 chndl->opt[opt_threshold].cap |= SANE_CAP_INACTIVE;
784 chndl->graymode = 0;
785 }
786 if (strcmp (chndl->val[option].s, SANE_VALUE_SCAN_MODE_GRAY) == 0)
787 {
788 chndl->opt[opt_threshold].cap |= SANE_CAP_INACTIVE;
789 chndl->graymode = 1;
790 }
791
792
793 myinfo |= SANE_INFO_RELOAD_PARAMS;
794 myinfo |= SANE_INFO_RELOAD_OPTIONS;
795 DBG (4, "sane_control_option: set option %d (%s) to %s\n",
796 option, chndl->opt[option].name, (SANE_String) value);
797 break;
798 default:
799 DBG (1, "sane_control_option: trying to set unexpected option\n");
800 return SANE_STATUS_INVAL;
801 }
802 break;
803
804 case SANE_ACTION_GET_VALUE:
805 switch (option)
806 {
807 case opt_num_opts:
808 *(SANE_Word *) value = num_options;
809 DBG (4, "sane_control_option: get option 0, value = %d\n",
810 num_options);
811 break;
812 case opt_tl_x: /* Fixed options */
813 case opt_tl_y:
814 case opt_br_x:
815 case opt_br_y:
816 {
817 *(SANE_Fixed *) value = chndl->val[option].w;
818 DBG (4,
819 "sane_control_option: get option %d (%s), value=%.1f %s\n",
820 option, chndl->opt[option].name,
821 SANE_UNFIX (*(SANE_Fixed *) value),
822 chndl->opt[option].unit ==
823 SANE_UNIT_MM ? "mm" : SANE_UNIT_DPI ? "dpi" : "");
824 break;
825 }
826 case opt_non_blocking:
827 *(SANE_Bool *) value = chndl->val[option].w;
828 DBG (4,
829 "sane_control_option: get option %d (%s), value=%s\n",
830 option, chndl->opt[option].name,
831 *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
832 break;
833 case opt_mode: /* String (list) options */
834 strcpy (value, chndl->val[option].s);
835 DBG (4, "sane_control_option: get option %d (%s), value=`%s'\n",
836 option, chndl->opt[option].name, (SANE_String) value);
837 break;
838 case opt_resolution:
839 case opt_threshold:
840 *(SANE_Int *) value = chndl->val[option].w;
841 DBG (4, "sane_control_option: get option %d (%s), value=%d\n",
842 option, chndl->opt[option].name, *(SANE_Int *) value);
843 break;
844 default:
845 DBG (1, "sane_control_option: trying to get unexpected option\n");
846 return SANE_STATUS_INVAL;
847 }
848 break;
849 default:
850 DBG (1, "sane_control_option: trying unexpected action %d\n", action);
851 return SANE_STATUS_INVAL;
852 }
853
854 if (info)
855 *info = myinfo;
856 return SANE_STATUS_GOOD;
857 }
858
859
860 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)861 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
862 {
863 Canon_Scanner *hndl = handle; /* Eliminate compiler warning */
864 CANON_Handle *chndl = &hndl->scan;
865
866 int rc = SANE_STATUS_GOOD;
867 int w = SANE_UNFIX (chndl->val[opt_br_x].w -
868 chndl->val[opt_tl_x].w) / MM_IN_INCH *
869 chndl->val[opt_resolution].w;
870 int h =
871 SANE_UNFIX (chndl->val[opt_br_y].w -
872 chndl->val[opt_tl_y].w) / MM_IN_INCH *
873 chndl->val[opt_resolution].w;
874
875 DBG (3, "sane_get_parameters\n");
876 chndl->params.depth = 8;
877 chndl->params.last_frame = SANE_TRUE;
878 chndl->params.pixels_per_line = w;
879 chndl->params.lines = h;
880
881 if (chndl->graymode == 1)
882 {
883 chndl->params.format = SANE_FRAME_GRAY;
884 chndl->params.bytes_per_line = w;
885 }
886 else if (chndl->graymode == 2)
887 {
888 chndl->params.format = SANE_FRAME_GRAY;
889 w /= 8;
890
891 if ((chndl->params.pixels_per_line % 8) != 0)
892 w++;
893
894 chndl->params.bytes_per_line = w;
895 chndl->params.depth = 1;
896 }
897 else
898 {
899 chndl->params.format = SANE_FRAME_RGB;
900 chndl->params.bytes_per_line = w * 3;
901 }
902
903 *params = chndl->params;
904 DBG (1, "%d\n", chndl->params.format);
905 return rc;
906 }
907
908
909 SANE_Status
sane_start(SANE_Handle handle)910 sane_start (SANE_Handle handle)
911 {
912 Canon_Scanner *scanner = handle;
913 CANON_Handle *chndl = &scanner->scan;
914 SANE_Status res;
915
916 DBG (3, "sane_start\n");
917
918 res = sane_get_parameters (handle, &chndl->params);
919 res = CANON_set_scan_parameters (&scanner->scan);
920
921 if (res != SANE_STATUS_GOOD)
922 return res;
923
924 return CANON_start_scan (&scanner->scan);
925 }
926
927
928 SANE_Status
sane_read(SANE_Handle handle,SANE_Byte * data,SANE_Int max_length,SANE_Int * length)929 sane_read (SANE_Handle handle, SANE_Byte * data,
930 SANE_Int max_length, SANE_Int * length)
931 {
932 Canon_Scanner *scanner = handle;
933 return CANON_read (&scanner->scan, data, max_length, length);
934 }
935
936
937 void
sane_cancel(SANE_Handle handle)938 sane_cancel (SANE_Handle handle)
939 {
940 DBG (3, "sane_cancel: handle = %p\n", handle);
941 DBG (3, "sane_cancel: cancelling is unsupported in this backend\n");
942 }
943
944
945 SANE_Status
sane_set_io_mode(SANE_Handle handle,SANE_Bool non_blocking)946 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
947 {
948 DBG (3, "sane_set_io_mode: handle = %p, non_blocking = %d\n", handle,
949 non_blocking);
950 if (non_blocking != SANE_FALSE)
951 return SANE_STATUS_UNSUPPORTED;
952 return SANE_STATUS_GOOD;
953 }
954
955
956 SANE_Status
sane_get_select_fd(SANE_Handle handle,SANE_Int * fd)957 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
958 {
959 handle = handle; /* silence gcc */
960 fd = fd; /* silence gcc */
961 return SANE_STATUS_UNSUPPORTED;
962 }
963