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