| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | /* sane - Scanner Access Now Easy.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    BACKEND canon_lide70 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |    Copyright (C) 2019 Juergen Ernst and pimvantend. | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    This file is part of the SANE package. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |    modify it under the terms of the GNU General Public License as | 
					
						
							|  |  |  |    published by the Free Software Foundation; either version 2 of the | 
					
						
							|  |  |  |    License, or (at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This program is distributed in the hope that it will be useful, but | 
					
						
							|  |  |  |    WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |    General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |    along with this program; if not, write to the Free Software | 
					
						
							|  |  |  |    Foundation, Inc., 59 Temple Place - Suite 330, Boston, | 
					
						
							|  |  |  |    MA 02111-1307, USA. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |    This file implements a SANE backend for the Canon CanoScan LiDE 70 */ | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | #define BUILD 0
 | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | #define MM_IN_INCH 25.4
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "../include/sane/config.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | #include <fcntl.h>
 | 
					
						
							|  |  |  | #include <sys/ioctl.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "../include/sane/sane.h"
 | 
					
						
							|  |  |  | #include "../include/sane/sanei.h"
 | 
					
						
							|  |  |  | #include "../include/sane/saneopts.h"
 | 
					
						
							|  |  |  | #include "../include/sane/sanei_config.h"
 | 
					
						
							|  |  |  | #include "../include/sane/sanei_usb.h"
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | #define BACKEND_NAME        canon_lide70
 | 
					
						
							|  |  |  | #define CANONUSB_CONFIG_FILE "canon_lide70.conf"
 | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | #include "../include/sane/sanei_backend.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | typedef enum | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   opt_num_opts = 0, | 
					
						
							|  |  |  |   opt_mode_group, | 
					
						
							|  |  |  |   opt_threshold, | 
					
						
							|  |  |  |   opt_mode, | 
					
						
							|  |  |  |   opt_resolution, | 
					
						
							|  |  |  |   opt_non_blocking, | 
					
						
							|  |  |  |   opt_geometry_group, | 
					
						
							|  |  |  |   opt_tl_x, | 
					
						
							|  |  |  |   opt_tl_y, | 
					
						
							|  |  |  |   opt_br_x, | 
					
						
							|  |  |  |   opt_br_y, | 
					
						
							|  |  |  |   /* must come last: */ | 
					
						
							|  |  |  |   num_options | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | canon_opts; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | #include "canon_lide70-common.c"
 | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | static size_t | 
					
						
							|  |  |  | max_string_size (const SANE_String_Const strings[]) | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   size_t size, max_size = 0; | 
					
						
							|  |  |  |   SANE_Int i; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   for (i = 0; strings[i]; ++i) | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |       size = strlen (strings[i]) + 1; | 
					
						
							|  |  |  |       if (size > max_size) | 
					
						
							|  |  |  | 	max_size = size; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   return max_size; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | static SANE_String_Const mode_list[] = { | 
					
						
							|  |  |  |   SANE_VALUE_SCAN_MODE_COLOR, | 
					
						
							|  |  |  |   SANE_VALUE_SCAN_MODE_GRAY, | 
					
						
							|  |  |  |   SANE_VALUE_SCAN_MODE_LINEART, | 
					
						
							|  |  |  |   0 | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | static SANE_Fixed init_tl_x = SANE_FIX (0.0); | 
					
						
							|  |  |  | static SANE_Fixed init_tl_y = SANE_FIX (0.0); | 
					
						
							|  |  |  | static SANE_Fixed init_br_x = SANE_FIX (80.0); | 
					
						
							|  |  |  | static SANE_Fixed init_br_y = SANE_FIX (100.0); | 
					
						
							|  |  |  | static SANE_Int init_threshold = 75; | 
					
						
							|  |  |  | static SANE_Int init_resolution = 600; | 
					
						
							|  |  |  | static SANE_String init_mode = SANE_VALUE_SCAN_MODE_COLOR; | 
					
						
							|  |  |  | static SANE_Int init_graymode = 0; | 
					
						
							|  |  |  | static SANE_Bool init_non_blocking = SANE_FALSE; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*-----------------------------------------------------------------*/ | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | Scan range | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const SANE_Range widthRange = { | 
					
						
							|  |  |  |   0,				/* minimum */ | 
					
						
							|  |  |  |   SANE_FIX (CANON_MAX_WIDTH * MM_IN_INCH / 600),	/* maximum */ | 
					
						
							|  |  |  |   0				/* quantization */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const SANE_Range heightRange = { | 
					
						
							|  |  |  |   0,				/* minimum */ | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | /*  SANE_FIX (CANON_MAX_HEIGHT * MM_IN_INCH / 600 - TOP_EDGE ),	 maximum */ | 
					
						
							|  |  |  |   SANE_FIX (297.0), | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  |   0				/* quantization */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | static const SANE_Range threshold_range = { | 
					
						
							|  |  |  |   0, | 
					
						
							|  |  |  |   100, | 
					
						
							|  |  |  |   1 | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | static SANE_Int resolution_list[] = { 5, | 
					
						
							|  |  |  |   75, | 
					
						
							|  |  |  |   150, | 
					
						
							|  |  |  |   300, | 
					
						
							|  |  |  |   600, | 
					
						
							|  |  |  |   1200 | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | typedef struct Canon_Device | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   struct Canon_Device *next; | 
					
						
							|  |  |  |   SANE_String name; | 
					
						
							|  |  |  |   SANE_Device sane; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | Canon_Device; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | /* Canon_Scanner is the type used for the sane handle */ | 
					
						
							|  |  |  | typedef struct Canon_Scanner | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   struct Canon_Scanner *next; | 
					
						
							|  |  |  |   Canon_Device *device; | 
					
						
							|  |  |  |   CANON_Handle scan; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | Canon_Scanner; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | static int num_devices = 0; | 
					
						
							|  |  |  | static const SANE_Device **devlist = NULL; | 
					
						
							|  |  |  | static Canon_Device *first_dev = NULL; | 
					
						
							|  |  |  | static Canon_Scanner *first_handle = NULL; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*-----------------------------------------------------------------*/ | 
					
						
							|  |  |  | static SANE_Status | 
					
						
							|  |  |  | attach_scanner (const char *devicename, Canon_Device ** devp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   CANON_Handle scan; | 
					
						
							|  |  |  |   Canon_Device *dev; | 
					
						
							|  |  |  |   SANE_Status status; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DBG (3, "attach_scanner: %s\n", devicename); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (dev = first_dev; dev; dev = dev->next) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (strcmp (dev->sane.name, devicename) == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  if (devp) | 
					
						
							|  |  |  | 	    *devp = dev; | 
					
						
							|  |  |  | 	  return SANE_STATUS_GOOD; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   dev = malloc (sizeof (*dev)); | 
					
						
							|  |  |  |   if (!dev) | 
					
						
							|  |  |  |     return SANE_STATUS_NO_MEM; | 
					
						
							|  |  |  |   memset (dev, '\0', sizeof (Canon_Device));	/* clear structure */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DBG (4, "attach_scanner: opening %s\n", devicename); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   status = CANON_open_device (&scan, devicename); | 
					
						
							|  |  |  |   if (status != SANE_STATUS_GOOD) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       DBG (1, "ERROR: attach_scanner: opening %s failed\n", devicename); | 
					
						
							|  |  |  |       free (dev); | 
					
						
							|  |  |  |       return status; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   dev->name = strdup (devicename); | 
					
						
							|  |  |  |   dev->sane.name = dev->name; | 
					
						
							|  |  |  |   dev->sane.vendor = "CANON"; | 
					
						
							|  |  |  |   dev->sane.model = CANON_get_device_name (&scan); | 
					
						
							|  |  |  |   dev->sane.type = "flatbed scanner"; | 
					
						
							|  |  |  |   CANON_close_device (&scan); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ++num_devices; | 
					
						
							|  |  |  |   dev->next = first_dev; | 
					
						
							|  |  |  |   first_dev = dev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (devp) | 
					
						
							|  |  |  |     *devp = dev; | 
					
						
							|  |  |  |   return SANE_STATUS_GOOD; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* callback function for sanei_usb_attach_matching_devices */ | 
					
						
							|  |  |  | static SANE_Status | 
					
						
							|  |  |  | attach_one (const char *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   attach_scanner (name, 0); | 
					
						
							|  |  |  |   return SANE_STATUS_GOOD; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Find our devices */ | 
					
						
							|  |  |  | SANE_Status | 
					
						
							|  |  |  | sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char config_line[PATH_MAX]; | 
					
						
							|  |  |  |   size_t len; | 
					
						
							|  |  |  |   FILE *fp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DBG_INIT (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  |   DBG_LEVEL = 10; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DBG (2, "sane_init: version_code %s 0, authorize %s 0\n", | 
					
						
							|  |  |  |        version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!="); | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   DBG (1, "sane_init: SANE Canon LiDE70 backend version %d.%d.%d from %s\n", | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  |        V_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (version_code) | 
					
						
							|  |  |  |     *version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, BUILD); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   sanei_usb_init (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   fp = sanei_config_open (CANONUSB_CONFIG_FILE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!fp) | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       /* no config-file: try these */ | 
					
						
							|  |  |  |       attach_scanner ("/dev/scanner", 0); | 
					
						
							|  |  |  |       attach_scanner ("/dev/usbscanner", 0); | 
					
						
							|  |  |  |       attach_scanner ("/dev/usb/scanner", 0); | 
					
						
							|  |  |  |       return SANE_STATUS_GOOD; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   DBG (3, "reading configure file %s\n", CANONUSB_CONFIG_FILE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (sanei_config_read (config_line, sizeof (config_line), fp)) | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       if (config_line[0] == '#') | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 	continue;		/* ignore line comments */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |       len = strlen (config_line); | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |       if (!len) | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 	continue;		/* ignore empty lines */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |       DBG (4, "attach_matching_devices(%s)\n", config_line); | 
					
						
							|  |  |  |       sanei_usb_attach_matching_devices (config_line, attach_one); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   DBG (4, "finished reading configure file\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   fclose (fp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return SANE_STATUS_GOOD; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sane_exit (void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Canon_Device *dev, *next; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DBG (3, "sane_exit\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (dev = first_dev; dev; dev = next) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       next = dev->next; | 
					
						
							|  |  |  |       free (dev->name); | 
					
						
							|  |  |  |       free (dev); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (devlist) | 
					
						
							|  |  |  |     free (devlist); | 
					
						
							|  |  |  |   return; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SANE_Status | 
					
						
							|  |  |  | sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Canon_Device *dev; | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DBG (3, "sane_get_devices(local_only = %d)\n", local_only); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (devlist) | 
					
						
							|  |  |  |     free (devlist); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); | 
					
						
							|  |  |  |   if (!devlist) | 
					
						
							|  |  |  |     return SANE_STATUS_NO_MEM; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   i = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (dev = first_dev; i < num_devices; dev = dev->next) | 
					
						
							|  |  |  |     devlist[i++] = &dev->sane; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   devlist[i++] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   *device_list = devlist; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return SANE_STATUS_GOOD; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | static SANE_Status | 
					
						
							|  |  |  | init_options (CANON_Handle * chndl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SANE_Option_Descriptor *od; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DBG (2, "begin init_options: chndl=%p\n", (void *) chndl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* opt_num_opts */ | 
					
						
							|  |  |  |   od = &chndl->opt[opt_num_opts]; | 
					
						
							|  |  |  |   od->name = ""; | 
					
						
							|  |  |  |   od->title = SANE_TITLE_NUM_OPTIONS; | 
					
						
							|  |  |  |   od->desc = SANE_DESC_NUM_OPTIONS; | 
					
						
							|  |  |  |   od->type = SANE_TYPE_INT; | 
					
						
							|  |  |  |   od->unit = SANE_UNIT_NONE; | 
					
						
							|  |  |  |   od->size = sizeof (SANE_Word); | 
					
						
							|  |  |  |   od->cap = SANE_CAP_SOFT_DETECT; | 
					
						
							|  |  |  |   od->constraint_type = SANE_CONSTRAINT_NONE; | 
					
						
							|  |  |  |   od->constraint.range = 0; | 
					
						
							|  |  |  |   chndl->val[opt_num_opts].w = num_options; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DBG (2, "val[opt_num_opts]: %d\n", chndl->val[opt_num_opts].w); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* opt_mode_group */ | 
					
						
							|  |  |  |   od = &chndl->opt[opt_mode_group]; | 
					
						
							|  |  |  |   od->name = ""; | 
					
						
							|  |  |  |   od->title = SANE_I18N ("Scan Mode"); | 
					
						
							|  |  |  |   od->desc = ""; | 
					
						
							|  |  |  |   od->type = SANE_TYPE_GROUP; | 
					
						
							|  |  |  |   od->unit = SANE_UNIT_NONE; | 
					
						
							|  |  |  |   od->size = 0; | 
					
						
							|  |  |  |   od->cap = 0; | 
					
						
							|  |  |  |   od->constraint_type = SANE_CONSTRAINT_NONE; | 
					
						
							|  |  |  |   od->constraint.range = 0; | 
					
						
							|  |  |  |   chndl->val[opt_mode_group].w = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* opt_mode */ | 
					
						
							|  |  |  |   od = &chndl->opt[opt_mode]; | 
					
						
							|  |  |  |   od->name = SANE_NAME_SCAN_MODE; | 
					
						
							|  |  |  |   od->title = SANE_TITLE_SCAN_MODE; | 
					
						
							|  |  |  |   od->desc = SANE_DESC_SCAN_MODE; | 
					
						
							|  |  |  |   od->type = SANE_TYPE_STRING; | 
					
						
							|  |  |  |   od->unit = SANE_UNIT_NONE; | 
					
						
							|  |  |  |   od->size = max_string_size (mode_list); | 
					
						
							|  |  |  |   od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; | 
					
						
							|  |  |  |   od->constraint_type = SANE_CONSTRAINT_STRING_LIST; | 
					
						
							|  |  |  |   od->constraint.string_list = mode_list; | 
					
						
							|  |  |  |   chndl->val[opt_mode].s = malloc (od->size); | 
					
						
							|  |  |  |   if (!chndl->val[opt_mode].s) | 
					
						
							|  |  |  |     return SANE_STATUS_NO_MEM; | 
					
						
							|  |  |  |   strcpy (chndl->val[opt_mode].s, init_mode); | 
					
						
							|  |  |  |   chndl->graymode = init_graymode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* opt_threshold */ | 
					
						
							|  |  |  |   od = &chndl->opt[opt_threshold]; | 
					
						
							|  |  |  |   od->name = SANE_NAME_THRESHOLD; | 
					
						
							|  |  |  |   od->title = SANE_TITLE_THRESHOLD; | 
					
						
							|  |  |  |   od->desc = SANE_DESC_THRESHOLD; | 
					
						
							|  |  |  |   od->type = SANE_TYPE_INT; | 
					
						
							|  |  |  |   od->unit = SANE_UNIT_PERCENT; | 
					
						
							|  |  |  |   od->size = sizeof (SANE_Word); | 
					
						
							|  |  |  |   od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE; | 
					
						
							|  |  |  |   od->constraint_type = SANE_CONSTRAINT_RANGE; | 
					
						
							|  |  |  |   od->constraint.range = &threshold_range; | 
					
						
							|  |  |  |   chndl->val[opt_threshold].w = init_threshold; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* opt_resolution */ | 
					
						
							|  |  |  |   od = &chndl->opt[opt_resolution]; | 
					
						
							|  |  |  |   od->name = SANE_NAME_SCAN_RESOLUTION; | 
					
						
							|  |  |  |   od->title = SANE_TITLE_SCAN_RESOLUTION; | 
					
						
							|  |  |  |   od->desc = SANE_DESC_SCAN_RESOLUTION; | 
					
						
							|  |  |  |   od->type = SANE_TYPE_INT; | 
					
						
							|  |  |  |   od->unit = SANE_UNIT_DPI; | 
					
						
							|  |  |  |   od->size = sizeof (SANE_Word); | 
					
						
							|  |  |  |   od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; | 
					
						
							|  |  |  |   od->constraint_type = SANE_CONSTRAINT_WORD_LIST; | 
					
						
							|  |  |  |   od->constraint.word_list = resolution_list; | 
					
						
							|  |  |  |   chndl->val[opt_resolution].w = init_resolution; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* opt_non_blocking */ | 
					
						
							|  |  |  |   od = &chndl->opt[opt_non_blocking]; | 
					
						
							|  |  |  |   od->name = "non-blocking"; | 
					
						
							|  |  |  |   od->title = SANE_I18N ("Use non-blocking IO"); | 
					
						
							|  |  |  |   od->desc = SANE_I18N ("Use non-blocking IO for sane_read() if supported " | 
					
						
							|  |  |  | 			"by the frontend."); | 
					
						
							|  |  |  |   od->type = SANE_TYPE_BOOL; | 
					
						
							|  |  |  |   od->unit = SANE_UNIT_NONE; | 
					
						
							|  |  |  |   od->size = sizeof (SANE_Word); | 
					
						
							|  |  |  |   od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE; | 
					
						
							|  |  |  |   od->constraint_type = SANE_CONSTRAINT_NONE; | 
					
						
							|  |  |  |   od->constraint.range = 0; | 
					
						
							|  |  |  |   chndl->val[opt_non_blocking].w = init_non_blocking; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* opt_geometry_group */ | 
					
						
							|  |  |  |   od = &chndl->opt[opt_geometry_group]; | 
					
						
							|  |  |  |   od->name = ""; | 
					
						
							|  |  |  |   od->title = SANE_I18N ("Geometry"); | 
					
						
							|  |  |  |   od->desc = ""; | 
					
						
							|  |  |  |   od->type = SANE_TYPE_GROUP; | 
					
						
							|  |  |  |   od->unit = SANE_UNIT_NONE; | 
					
						
							|  |  |  |   od->size = 0; | 
					
						
							|  |  |  |   od->cap = 0; | 
					
						
							|  |  |  |   od->constraint_type = SANE_CONSTRAINT_NONE; | 
					
						
							|  |  |  |   od->constraint.range = 0; | 
					
						
							|  |  |  |   chndl->val[opt_geometry_group].w = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* opt_tl_x */ | 
					
						
							|  |  |  |   od = &chndl->opt[opt_tl_x]; | 
					
						
							|  |  |  |   od->name = SANE_NAME_SCAN_TL_X; | 
					
						
							|  |  |  |   od->title = SANE_TITLE_SCAN_TL_X; | 
					
						
							|  |  |  |   od->desc = SANE_DESC_SCAN_TL_X; | 
					
						
							|  |  |  |   od->type = SANE_TYPE_FIXED; | 
					
						
							|  |  |  |   od->unit = SANE_UNIT_MM; | 
					
						
							|  |  |  |   od->size = sizeof (SANE_Word); | 
					
						
							|  |  |  |   od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; | 
					
						
							|  |  |  |   od->constraint_type = SANE_CONSTRAINT_RANGE; | 
					
						
							|  |  |  |   od->constraint.range = &widthRange; | 
					
						
							|  |  |  |   chndl->val[opt_tl_x].w = init_tl_x; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* opt_tl_y */ | 
					
						
							|  |  |  |   od = &chndl->opt[opt_tl_y]; | 
					
						
							|  |  |  |   od->name = SANE_NAME_SCAN_TL_Y; | 
					
						
							|  |  |  |   od->title = SANE_TITLE_SCAN_TL_Y; | 
					
						
							|  |  |  |   od->desc = SANE_DESC_SCAN_TL_Y; | 
					
						
							|  |  |  |   od->type = SANE_TYPE_FIXED; | 
					
						
							|  |  |  |   od->unit = SANE_UNIT_MM; | 
					
						
							|  |  |  |   od->size = sizeof (SANE_Word); | 
					
						
							|  |  |  |   od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; | 
					
						
							|  |  |  |   od->constraint_type = SANE_CONSTRAINT_RANGE; | 
					
						
							|  |  |  |   od->constraint.range = &heightRange; | 
					
						
							|  |  |  |   chndl->val[opt_tl_y].w = init_tl_y; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* opt_br_x */ | 
					
						
							|  |  |  |   od = &chndl->opt[opt_br_x]; | 
					
						
							|  |  |  |   od->name = SANE_NAME_SCAN_BR_X; | 
					
						
							|  |  |  |   od->title = SANE_TITLE_SCAN_BR_X; | 
					
						
							|  |  |  |   od->desc = SANE_DESC_SCAN_BR_X; | 
					
						
							|  |  |  |   od->type = SANE_TYPE_FIXED; | 
					
						
							|  |  |  |   od->unit = SANE_UNIT_MM; | 
					
						
							|  |  |  |   od->size = sizeof (SANE_Word); | 
					
						
							|  |  |  |   od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; | 
					
						
							|  |  |  |   od->constraint_type = SANE_CONSTRAINT_RANGE; | 
					
						
							|  |  |  |   od->constraint.range = &widthRange; | 
					
						
							|  |  |  |   chndl->val[opt_br_x].w = init_br_x; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* opt_br_y */ | 
					
						
							|  |  |  |   od = &chndl->opt[opt_br_y]; | 
					
						
							|  |  |  |   od->name = SANE_NAME_SCAN_BR_Y; | 
					
						
							|  |  |  |   od->title = SANE_TITLE_SCAN_BR_Y; | 
					
						
							|  |  |  |   od->desc = SANE_DESC_SCAN_BR_Y; | 
					
						
							|  |  |  |   od->type = SANE_TYPE_FIXED; | 
					
						
							|  |  |  |   od->unit = SANE_UNIT_MM; | 
					
						
							|  |  |  |   od->size = sizeof (SANE_Word); | 
					
						
							|  |  |  |   od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; | 
					
						
							|  |  |  |   od->constraint_type = SANE_CONSTRAINT_RANGE; | 
					
						
							|  |  |  |   od->constraint.range = &heightRange; | 
					
						
							|  |  |  |   chndl->val[opt_br_y].w = init_br_y; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DBG (2, "end init_options: chndl=%p\n", (void *) chndl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return SANE_STATUS_GOOD; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | SANE_Status | 
					
						
							|  |  |  | sane_open (SANE_String_Const devicename, SANE_Handle * handle) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Canon_Device *dev; | 
					
						
							|  |  |  |   SANE_Status status; | 
					
						
							|  |  |  |   Canon_Scanner *scanner; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DBG (3, "sane_open\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (devicename[0])		/* search for devicename */ | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       DBG (4, "sane_open: devicename=%s\n", devicename); | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |       for (dev = first_dev; dev; dev = dev->next) | 
					
						
							|  |  |  | 	if (strcmp (dev->sane.name, devicename) == 0) | 
					
						
							|  |  |  | 	  break; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |       if (!dev) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  status = attach_scanner (devicename, &dev); | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | 	  if (status != SANE_STATUS_GOOD) | 
					
						
							|  |  |  | 	    return status; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       DBG (2, "sane_open: no devicename, opening first device\n"); | 
					
						
							|  |  |  |       dev = first_dev; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (!dev) | 
					
						
							|  |  |  |     return SANE_STATUS_INVAL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   scanner = malloc (sizeof (*scanner)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!scanner) | 
					
						
							|  |  |  |     return SANE_STATUS_NO_MEM; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   memset (scanner, 0, sizeof (*scanner)); | 
					
						
							|  |  |  |   scanner->device = dev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   status = CANON_open_device (&scanner->scan, dev->sane.name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (status != SANE_STATUS_GOOD) | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       free (scanner); | 
					
						
							|  |  |  |       return status; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   status = init_options (&scanner->scan); | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   *handle = scanner; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* insert newly opened handle into list of open handles: */ | 
					
						
							|  |  |  |   scanner->next = first_handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   first_handle = scanner; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   return status; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | print_options (CANON_Handle * chndl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SANE_Option_Descriptor *od; | 
					
						
							|  |  |  |   SANE_Word option_number; | 
					
						
							|  |  |  |   SANE_Char caps[1024]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (option_number = 0; option_number < num_options; option_number++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       od = &chndl->opt[option_number]; | 
					
						
							|  |  |  |       DBG (50, "-----> number: %d\n", option_number); | 
					
						
							|  |  |  |       DBG (50, "         name: `%s'\n", od->name); | 
					
						
							|  |  |  |       DBG (50, "        title: `%s'\n", od->title); | 
					
						
							|  |  |  |       DBG (50, "  description: `%s'\n", od->desc); | 
					
						
							|  |  |  |       DBG (50, "         type: %s\n", | 
					
						
							|  |  |  | 	   od->type == SANE_TYPE_BOOL ? "SANE_TYPE_BOOL" : | 
					
						
							|  |  |  | 	   od->type == SANE_TYPE_INT ? "SANE_TYPE_INT" : | 
					
						
							|  |  |  | 	   od->type == SANE_TYPE_FIXED ? "SANE_TYPE_FIXED" : | 
					
						
							|  |  |  | 	   od->type == SANE_TYPE_STRING ? "SANE_TYPE_STRING" : | 
					
						
							|  |  |  | 	   od->type == SANE_TYPE_BUTTON ? "SANE_TYPE_BUTTON" : | 
					
						
							|  |  |  | 	   od->type == SANE_TYPE_GROUP ? "SANE_TYPE_GROUP" : "unknown"); | 
					
						
							|  |  |  |       DBG (50, "         unit: %s\n", | 
					
						
							|  |  |  | 	   od->unit == SANE_UNIT_NONE ? "SANE_UNIT_NONE" : | 
					
						
							|  |  |  | 	   od->unit == SANE_UNIT_PIXEL ? "SANE_UNIT_PIXEL" : | 
					
						
							|  |  |  | 	   od->unit == SANE_UNIT_BIT ? "SANE_UNIT_BIT" : | 
					
						
							|  |  |  | 	   od->unit == SANE_UNIT_MM ? "SANE_UNIT_MM" : | 
					
						
							|  |  |  | 	   od->unit == SANE_UNIT_DPI ? "SANE_UNIT_DPI" : | 
					
						
							|  |  |  | 	   od->unit == SANE_UNIT_PERCENT ? "SANE_UNIT_PERCENT" : | 
					
						
							|  |  |  | 	   od->unit == SANE_UNIT_MICROSECOND ? "SANE_UNIT_MICROSECOND" : | 
					
						
							|  |  |  | 	   "unknown"); | 
					
						
							|  |  |  |       DBG (50, "         size: %d\n", od->size); | 
					
						
							|  |  |  |       caps[0] = '\0'; | 
					
						
							|  |  |  |       if (od->cap & SANE_CAP_SOFT_SELECT) | 
					
						
							|  |  |  | 	strcat (caps, "SANE_CAP_SOFT_SELECT "); | 
					
						
							|  |  |  |       if (od->cap & SANE_CAP_HARD_SELECT) | 
					
						
							|  |  |  | 	strcat (caps, "SANE_CAP_HARD_SELECT "); | 
					
						
							|  |  |  |       if (od->cap & SANE_CAP_SOFT_DETECT) | 
					
						
							|  |  |  | 	strcat (caps, "SANE_CAP_SOFT_DETECT "); | 
					
						
							|  |  |  |       if (od->cap & SANE_CAP_EMULATED) | 
					
						
							|  |  |  | 	strcat (caps, "SANE_CAP_EMULATED "); | 
					
						
							|  |  |  |       if (od->cap & SANE_CAP_AUTOMATIC) | 
					
						
							|  |  |  | 	strcat (caps, "SANE_CAP_AUTOMATIC "); | 
					
						
							|  |  |  |       if (od->cap & SANE_CAP_INACTIVE) | 
					
						
							|  |  |  | 	strcat (caps, "SANE_CAP_INACTIVE "); | 
					
						
							|  |  |  |       if (od->cap & SANE_CAP_ADVANCED) | 
					
						
							|  |  |  | 	strcat (caps, "SANE_CAP_ADVANCED "); | 
					
						
							|  |  |  |       DBG (50, " capabilities: %s\n", caps); | 
					
						
							|  |  |  |       DBG (50, "constraint type: %s\n", | 
					
						
							|  |  |  | 	   od->constraint_type == SANE_CONSTRAINT_NONE ? | 
					
						
							|  |  |  | 	   "SANE_CONSTRAINT_NONE" : | 
					
						
							|  |  |  | 	   od->constraint_type == SANE_CONSTRAINT_RANGE ? | 
					
						
							|  |  |  | 	   "SANE_CONSTRAINT_RANGE" : | 
					
						
							|  |  |  | 	   od->constraint_type == SANE_CONSTRAINT_WORD_LIST ? | 
					
						
							|  |  |  | 	   "SANE_CONSTRAINT_WORD_LIST" : | 
					
						
							|  |  |  | 	   od->constraint_type == SANE_CONSTRAINT_STRING_LIST ? | 
					
						
							|  |  |  | 	   "SANE_CONSTRAINT_STRING_LIST" : "unknown"); | 
					
						
							|  |  |  |       if (od->type == SANE_TYPE_INT) | 
					
						
							|  |  |  | 	DBG (50, "        value: %d\n", chndl->val[option_number].w); | 
					
						
							|  |  |  |       else if (od->type == SANE_TYPE_FIXED) | 
					
						
							|  |  |  | 	DBG (50, "        value: %f\n", | 
					
						
							|  |  |  | 	     SANE_UNFIX (chndl->val[option_number].w)); | 
					
						
							|  |  |  |       else if (od->type == SANE_TYPE_STRING) | 
					
						
							|  |  |  | 	DBG (50, "        value: %s\n", chndl->val[option_number].s); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sane_close (SANE_Handle handle) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Canon_Scanner *prev, *scanner; | 
					
						
							|  |  |  |   SANE_Status res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DBG (3, "sane_close\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   scanner = handle; | 
					
						
							|  |  |  |   print_options (&scanner->scan); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  |   if (!first_handle) | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       DBG (1, "ERROR: sane_close: no handles opened\n"); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* remove handle from list of open handles: */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   prev = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (scanner = first_handle; scanner; scanner = scanner->next) | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       if (scanner == handle) | 
					
						
							|  |  |  | 	break; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |       prev = scanner; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (!scanner) | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       DBG (1, "ERROR: sane_close: invalid handle %p\n", handle); | 
					
						
							|  |  |  |       return;			/* oops, not a handle we know about */ | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (prev) | 
					
						
							|  |  |  |     prev->next = scanner->next; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     first_handle = scanner->next; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   res = CANON_close_device (&scanner->scan); | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   DBG (3, "CANON_close_device returned: %d\n", res); | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  |   free (scanner); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const SANE_Option_Descriptor * | 
					
						
							|  |  |  | sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   Canon_Scanner *scanner = handle; | 
					
						
							|  |  |  |   CANON_Handle *chndl = &scanner->scan; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   DBG (4, "sane_get_option_descriptor: handle=%p, option = %d\n", | 
					
						
							|  |  |  |        (void *) handle, option); | 
					
						
							|  |  |  |   if (option < 0 || option >= num_options) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       DBG (3, "sane_get_option_descriptor: option < 0 || " | 
					
						
							|  |  |  | 	   "option > num_options\n"); | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   return &chndl->opt[option]; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SANE_Status | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  | sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, | 
					
						
							|  |  |  | 		     void *value, SANE_Int * info) | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   Canon_Scanner *scanner = handle; | 
					
						
							|  |  |  |   CANON_Handle *chndl = &scanner->scan; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   SANE_Int myinfo = 0; | 
					
						
							|  |  |  |   SANE_Status status; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DBG (4, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n", | 
					
						
							|  |  |  |        (void *) handle, option, action, (void *) value, (void *) info); | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   if (option < 0 || option >= num_options) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       DBG (1, "sane_control_option: option < 0 || option > num_options\n"); | 
					
						
							|  |  |  |       return SANE_STATUS_INVAL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!SANE_OPTION_IS_ACTIVE (chndl->opt[option].cap)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       DBG (1, "sane_control_option: option is inactive\n"); | 
					
						
							|  |  |  |       return SANE_STATUS_INVAL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (chndl->opt[option].type == SANE_TYPE_GROUP) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       DBG (1, "sane_control_option: option is a group\n"); | 
					
						
							|  |  |  |       return SANE_STATUS_INVAL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch (action) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case SANE_ACTION_SET_VALUE: | 
					
						
							|  |  |  |       if (!SANE_OPTION_IS_SETTABLE (chndl->opt[option].cap)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  DBG (1, "sane_control_option: option is not setable\n"); | 
					
						
							|  |  |  | 	  return SANE_STATUS_INVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       status = sanei_constrain_value (&chndl->opt[option], value, &myinfo); | 
					
						
							|  |  |  |       if (status != SANE_STATUS_GOOD) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  DBG (3, "sane_control_option: sanei_constrain_value returned %s\n", | 
					
						
							|  |  |  | 	       sane_strstatus (status)); | 
					
						
							|  |  |  | 	  return status; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       switch (option) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	case opt_tl_x:		/* Fixed with parameter reloading */ | 
					
						
							|  |  |  | 	case opt_tl_y: | 
					
						
							|  |  |  | 	case opt_br_x: | 
					
						
							|  |  |  | 	case opt_br_y: | 
					
						
							|  |  |  | 	  if (chndl->val[option].w == *(SANE_Fixed *) value) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      DBG (4, "sane_control_option: option %d (%s) not changed\n", | 
					
						
							|  |  |  | 		   option, chndl->opt[option].name); | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  chndl->val[option].w = *(SANE_Fixed *) value; | 
					
						
							|  |  |  | 	  myinfo |= SANE_INFO_RELOAD_PARAMS; | 
					
						
							|  |  |  | 	  DBG (4, "sane_control_option: set option %d (%s) to %.0f %s\n", | 
					
						
							|  |  |  | 	       option, chndl->opt[option].name, | 
					
						
							|  |  |  | 	       SANE_UNFIX (*(SANE_Fixed *) value), | 
					
						
							|  |  |  | 	       chndl->opt[option].unit == SANE_UNIT_MM ? "mm" : "dpi"); | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	case opt_non_blocking: | 
					
						
							|  |  |  | 	  if (chndl->val[option].w == *(SANE_Bool *) value) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      DBG (4, "sane_control_option: option %d (%s) not changed\n", | 
					
						
							|  |  |  | 		   option, chndl->opt[option].name); | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  chndl->val[option].w = *(SANE_Bool *) value; | 
					
						
							|  |  |  | 	  DBG (4, "sane_control_option: set option %d (%s) to %s\n", | 
					
						
							|  |  |  | 	       option, chndl->opt[option].name, | 
					
						
							|  |  |  | 	       *(SANE_Bool *) value == SANE_TRUE ? "true" : "false"); | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	case opt_resolution: | 
					
						
							|  |  |  | 	case opt_threshold: | 
					
						
							|  |  |  | 	  if (chndl->val[option].w == *(SANE_Int *) value) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      DBG (4, "sane_control_option: option %d (%s) not changed\n", | 
					
						
							|  |  |  | 		   option, chndl->opt[option].name); | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  chndl->val[option].w = *(SANE_Int *) value; | 
					
						
							|  |  |  | 	  myinfo |= SANE_INFO_RELOAD_PARAMS; | 
					
						
							|  |  |  | 	  myinfo |= SANE_INFO_RELOAD_OPTIONS; | 
					
						
							|  |  |  | 	  DBG (4, "sane_control_option: set option %d (%s) to %d\n", | 
					
						
							|  |  |  | 	       option, chndl->opt[option].name, *(SANE_Int *) value); | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	case opt_mode: | 
					
						
							|  |  |  | 	  if (strcmp (chndl->val[option].s, value) == 0) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      DBG (4, "sane_control_option: option %d (%s) not changed\n", | 
					
						
							|  |  |  | 		   option, chndl->opt[option].name); | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  strcpy (chndl->val[option].s, (SANE_String) value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  if (strcmp (chndl->val[option].s, SANE_VALUE_SCAN_MODE_LINEART) == | 
					
						
							|  |  |  | 	      0) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      chndl->opt[opt_threshold].cap &= ~SANE_CAP_INACTIVE; | 
					
						
							|  |  |  | 	      chndl->graymode = 2; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  if (strcmp (chndl->val[option].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      chndl->opt[opt_threshold].cap |= SANE_CAP_INACTIVE; | 
					
						
							|  |  |  | 	      chndl->graymode = 0; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  if (strcmp (chndl->val[option].s, SANE_VALUE_SCAN_MODE_GRAY) == 0) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      chndl->opt[opt_threshold].cap |= SANE_CAP_INACTIVE; | 
					
						
							|  |  |  | 	      chndl->graymode = 1; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  myinfo |= SANE_INFO_RELOAD_PARAMS; | 
					
						
							|  |  |  | 	  myinfo |= SANE_INFO_RELOAD_OPTIONS; | 
					
						
							|  |  |  | 	  DBG (4, "sane_control_option: set option %d (%s) to %s\n", | 
					
						
							|  |  |  | 	       option, chndl->opt[option].name, (SANE_String) value); | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 	  DBG (1, "sane_control_option: trying to set unexpected option\n"); | 
					
						
							|  |  |  | 	  return SANE_STATUS_INVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case SANE_ACTION_GET_VALUE: | 
					
						
							|  |  |  |       switch (option) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	case opt_num_opts: | 
					
						
							|  |  |  | 	  *(SANE_Word *) value = num_options; | 
					
						
							|  |  |  | 	  DBG (4, "sane_control_option: get option 0, value = %d\n", | 
					
						
							|  |  |  | 	       num_options); | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	case opt_tl_x:		/* Fixed options */ | 
					
						
							|  |  |  | 	case opt_tl_y: | 
					
						
							|  |  |  | 	case opt_br_x: | 
					
						
							|  |  |  | 	case opt_br_y: | 
					
						
							|  |  |  | 	  { | 
					
						
							|  |  |  | 	    *(SANE_Fixed *) value = chndl->val[option].w; | 
					
						
							|  |  |  | 	    DBG (4, | 
					
						
							|  |  |  | 		 "sane_control_option: get option %d (%s), value=%.1f %s\n", | 
					
						
							|  |  |  | 		 option, chndl->opt[option].name, | 
					
						
							|  |  |  | 		 SANE_UNFIX (*(SANE_Fixed *) value), | 
					
						
							|  |  |  | 		 chndl->opt[option].unit == | 
					
						
							|  |  |  | 		 SANE_UNIT_MM ? "mm" : SANE_UNIT_DPI ? "dpi" : ""); | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	case opt_non_blocking: | 
					
						
							|  |  |  | 	  *(SANE_Bool *) value = chndl->val[option].w; | 
					
						
							|  |  |  | 	  DBG (4, | 
					
						
							|  |  |  | 	       "sane_control_option: get option %d (%s), value=%s\n", | 
					
						
							|  |  |  | 	       option, chndl->opt[option].name, | 
					
						
							|  |  |  | 	       *(SANE_Bool *) value == SANE_TRUE ? "true" : "false"); | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	case opt_mode:		/* String (list) options */ | 
					
						
							|  |  |  | 	  strcpy (value, chndl->val[option].s); | 
					
						
							|  |  |  | 	  DBG (4, "sane_control_option: get option %d (%s), value=`%s'\n", | 
					
						
							|  |  |  | 	       option, chndl->opt[option].name, (SANE_String) value); | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	case opt_resolution: | 
					
						
							|  |  |  | 	case opt_threshold: | 
					
						
							|  |  |  | 	  *(SANE_Int *) value = chndl->val[option].w; | 
					
						
							|  |  |  | 	  DBG (4, "sane_control_option: get option %d (%s), value=%d\n", | 
					
						
							|  |  |  | 	       option, chndl->opt[option].name, *(SANE_Int *) value); | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 	  DBG (1, "sane_control_option: trying to get unexpected option\n"); | 
					
						
							|  |  |  | 	  return SANE_STATUS_INVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       DBG (1, "sane_control_option: trying unexpected action %d\n", action); | 
					
						
							|  |  |  |       return SANE_STATUS_INVAL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (info) | 
					
						
							|  |  |  |     *info = myinfo; | 
					
						
							|  |  |  |   return SANE_STATUS_GOOD; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SANE_Status | 
					
						
							|  |  |  | sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   Canon_Scanner *hndl = handle;	/* Eliminate compiler warning */ | 
					
						
							|  |  |  |   CANON_Handle *chndl = &hndl->scan; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   int rc = SANE_STATUS_GOOD; | 
					
						
							|  |  |  |   int w = SANE_UNFIX (chndl->val[opt_br_x].w - | 
					
						
							|  |  |  | 		      chndl->val[opt_tl_x].w) / MM_IN_INCH * | 
					
						
							|  |  |  |     chndl->val[opt_resolution].w; | 
					
						
							|  |  |  |   int h = | 
					
						
							|  |  |  |     SANE_UNFIX (chndl->val[opt_br_y].w - | 
					
						
							|  |  |  | 		chndl->val[opt_tl_y].w) / MM_IN_INCH * | 
					
						
							|  |  |  |     chndl->val[opt_resolution].w; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   DBG (3, "sane_get_parameters\n"); | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   chndl->params.depth = 8; | 
					
						
							|  |  |  |   chndl->params.last_frame = SANE_TRUE; | 
					
						
							|  |  |  |   chndl->params.pixels_per_line = w; | 
					
						
							|  |  |  |   chndl->params.lines = h; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (chndl->graymode == 1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       chndl->params.format = SANE_FRAME_GRAY; | 
					
						
							|  |  |  |       chndl->params.bytes_per_line = w; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else if (chndl->graymode == 2) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       chndl->params.format = SANE_FRAME_GRAY; | 
					
						
							|  |  |  |       w /= 8; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ((chndl->params.pixels_per_line % 8) != 0) | 
					
						
							|  |  |  | 	w++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       chndl->params.bytes_per_line = w; | 
					
						
							|  |  |  |       chndl->params.depth = 1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  |   else | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       chndl->params.format = SANE_FRAME_RGB; | 
					
						
							|  |  |  |       chndl->params.bytes_per_line = w * 3; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   *params = chndl->params; | 
					
						
							|  |  |  |   DBG (1, "%d\n", chndl->params.format); | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  |   return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SANE_Status | 
					
						
							|  |  |  | sane_start (SANE_Handle handle) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Canon_Scanner *scanner = handle; | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   CANON_Handle *chndl = &scanner->scan; | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  |   SANE_Status res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DBG (3, "sane_start\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   res = sane_get_parameters (handle, &chndl->params); | 
					
						
							|  |  |  |   res = CANON_set_scan_parameters (&scanner->scan); | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (res != SANE_STATUS_GOOD) | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return CANON_start_scan (&scanner->scan); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SANE_Status | 
					
						
							|  |  |  | sane_read (SANE_Handle handle, SANE_Byte * data, | 
					
						
							|  |  |  | 	   SANE_Int max_length, SANE_Int * length) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Canon_Scanner *scanner = handle; | 
					
						
							|  |  |  |   return CANON_read (&scanner->scan, data, max_length, length); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sane_cancel (SANE_Handle handle) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   DBG (3, "sane_cancel: handle = %p\n", handle); | 
					
						
							|  |  |  |   DBG (3, "sane_cancel: cancelling is unsupported in this backend\n"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SANE_Status | 
					
						
							|  |  |  | sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   DBG (3, "sane_set_io_mode: handle = %p, non_blocking = %d\n", handle, | 
					
						
							|  |  |  |        non_blocking); | 
					
						
							|  |  |  |   if (non_blocking != SANE_FALSE) | 
					
						
							|  |  |  |     return SANE_STATUS_UNSUPPORTED; | 
					
						
							|  |  |  |   return SANE_STATUS_GOOD; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SANE_Status | 
					
						
							|  |  |  | sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-01-04 15:18:57 +00:00
										 |  |  |   handle = handle;		/* silence gcc */ | 
					
						
							|  |  |  |   fd = fd;			/* silence gcc */ | 
					
						
							| 
									
										
										
										
											2020-01-01 12:00:21 +00:00
										 |  |  |   return SANE_STATUS_UNSUPPORTED; | 
					
						
							|  |  |  | } |