1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci pieusb.c 4141cc406Sopenharmony_ci 5141cc406Sopenharmony_ci Copyright (C) 2012-2015 Jan Vleeshouwers, Michael Rickmann, Klaus Kaempf 6141cc406Sopenharmony_ci 7141cc406Sopenharmony_ci This file is part of the SANE package. 8141cc406Sopenharmony_ci 9141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 10141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 11141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 12141cc406Sopenharmony_ci License, or (at your option) any later version. 13141cc406Sopenharmony_ci 14141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 15141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 16141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17141cc406Sopenharmony_ci General Public License for more details. 18141cc406Sopenharmony_ci 19141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 20141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 21141cc406Sopenharmony_ci 22141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 23141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 24141cc406Sopenharmony_ci 25141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 26141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 27141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 28141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 29141cc406Sopenharmony_ci account of linking the SANE library code into it. 30141cc406Sopenharmony_ci 31141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 32141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 33141cc406Sopenharmony_ci License. 34141cc406Sopenharmony_ci 35141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 36141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 37141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 38141cc406Sopenharmony_ci 39141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 40141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 41141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. */ 42141cc406Sopenharmony_ci 43141cc406Sopenharmony_ci/* ========================================================================= 44141cc406Sopenharmony_ci * 45141cc406Sopenharmony_ci * SANE interface to three Reflecta USB scanners with USB-id 0x05e3/0x0145: 46141cc406Sopenharmony_ci * - Reflecta CrystalScan 7200 (model id 0x30) 47141cc406Sopenharmony_ci * - Reflecta ProScan 7200 (model id 0x36) 48141cc406Sopenharmony_ci * - Reflecta 6000 Multiple Slide Scanner (model id 0x3A) 49141cc406Sopenharmony_ci * 50141cc406Sopenharmony_ci * ========================================================================= */ 51141cc406Sopenharmony_ci 52141cc406Sopenharmony_ci#define DEBUG_NOT_STATIC 53141cc406Sopenharmony_ci/* -------------------------------------------------------------------------- 54141cc406Sopenharmony_ci * 55141cc406Sopenharmony_ci * INCLUDES 56141cc406Sopenharmony_ci * 57141cc406Sopenharmony_ci * --------------------------------------------------------------------------*/ 58141cc406Sopenharmony_ci 59141cc406Sopenharmony_ci#include "../include/sane/config.h" 60141cc406Sopenharmony_ci/* Standard includes for various utiliy functions */ 61141cc406Sopenharmony_ci#include <stdio.h> /* for FILE */ 62141cc406Sopenharmony_ci#include <string.h> /* for strlen */ 63141cc406Sopenharmony_ci#include <stdlib.h> /* for NULL */ 64141cc406Sopenharmony_ci#include <stdint.h> 65141cc406Sopenharmony_ci#include <math.h> 66141cc406Sopenharmony_ci 67141cc406Sopenharmony_ci/* Configuration defines */ 68141cc406Sopenharmony_ci#include "../include/sane/config.h" 69141cc406Sopenharmony_ci 70141cc406Sopenharmony_ci/* SANE includes */ 71141cc406Sopenharmony_ci#include "../include/sane/sane.h" 72141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 73141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h" 74141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 75141cc406Sopenharmony_ci 76141cc406Sopenharmony_ci/* Backend includes */ 77141cc406Sopenharmony_ci#define BACKEND_NAME pieusb 78141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 79141cc406Sopenharmony_ci#include "pieusb.h" 80141cc406Sopenharmony_ci#include "pieusb_specific.h" 81141cc406Sopenharmony_ci 82141cc406Sopenharmony_ci#define CAN_DO_4_CHANNEL_TIFF 83141cc406Sopenharmony_ci 84141cc406Sopenharmony_ci#ifdef CAN_DO_4_CHANNEL_TIFF 85141cc406Sopenharmony_ciextern void write_tiff_rgbi_header (FILE *fptr, int width, int height, int depth, int resolution, const char *icc_profile); 86141cc406Sopenharmony_ci#endif 87141cc406Sopenharmony_ci 88141cc406Sopenharmony_ci/* -------------------------------------------------------------------------- 89141cc406Sopenharmony_ci * 90141cc406Sopenharmony_ci * DEFINES 91141cc406Sopenharmony_ci * 92141cc406Sopenharmony_ci * --------------------------------------------------------------------------*/ 93141cc406Sopenharmony_ci 94141cc406Sopenharmony_ci/* Build number of this backend */ 95141cc406Sopenharmony_ci#define BUILD 1 96141cc406Sopenharmony_ci 97141cc406Sopenharmony_ci/* Configuration filename */ 98141cc406Sopenharmony_ci#define PIEUSB_CONFIG_FILE "pieusb.conf" 99141cc406Sopenharmony_ci 100141cc406Sopenharmony_ci/* Debug error levels */ 101141cc406Sopenharmony_ci#define DBG_error 1 /* errors */ 102141cc406Sopenharmony_ci#define DBG_warning 3 /* warnings */ 103141cc406Sopenharmony_ci#define DBG_info 5 /* information */ 104141cc406Sopenharmony_ci#define DBG_info_sane 7 /* information sane interface level */ 105141cc406Sopenharmony_ci#define DBG_inquiry 8 /* inquiry data */ 106141cc406Sopenharmony_ci#define DBG_info_proc 9 /* information pieusb backend functions */ 107141cc406Sopenharmony_ci#define DBG_info_scan 11 /* information scanner commands */ 108141cc406Sopenharmony_ci#define DBG_info_usb 13 /* information usb level functions */ 109141cc406Sopenharmony_ci 110141cc406Sopenharmony_ci/* device flags */ 111141cc406Sopenharmony_ci 112141cc406Sopenharmony_ci#define FLAG_SLIDE_TRANSPORT 0x01 113141cc406Sopenharmony_ci/* Some scanners do understand SLIDE_TRANSPORT but not CMD_17 - introducing a new flag */ 114141cc406Sopenharmony_ci#define FLAG_CMD_17_NOSUPPORT 0x02 115141cc406Sopenharmony_ci 116141cc406Sopenharmony_ci/* -------------------------------------------------------------------------- 117141cc406Sopenharmony_ci * 118141cc406Sopenharmony_ci * SUPPORTED DEVICES SPECIFICS 119141cc406Sopenharmony_ci * 120141cc406Sopenharmony_ci * --------------------------------------------------------------------------*/ 121141cc406Sopenharmony_ci 122141cc406Sopenharmony_cistruct Pieusb_USB_Device_Entry* pieusb_supported_usb_device_list = NULL; 123141cc406Sopenharmony_cistruct Pieusb_USB_Device_Entry pieusb_supported_usb_device; /* for searching */ 124141cc406Sopenharmony_ci 125141cc406Sopenharmony_ci/* -------------------------------------------------------------------------- 126141cc406Sopenharmony_ci * 127141cc406Sopenharmony_ci * LISTS OF ACTIVE DEVICE DEFINITIONS AND SCANNERS 128141cc406Sopenharmony_ci * 129141cc406Sopenharmony_ci * --------------------------------------------------------------------------*/ 130141cc406Sopenharmony_ci 131141cc406Sopenharmony_ciPieusb_Device_Definition *pieusb_definition_list_head = NULL; 132141cc406Sopenharmony_cistatic Pieusb_Scanner *first_handle = NULL; 133141cc406Sopenharmony_cistatic const SANE_Device **devlist = NULL; 134141cc406Sopenharmony_ci 135141cc406Sopenharmony_ci/* -------------------------------------------------------------------------- 136141cc406Sopenharmony_ci * 137141cc406Sopenharmony_ci * SANE INTERFACE 138141cc406Sopenharmony_ci * 139141cc406Sopenharmony_ci * --------------------------------------------------------------------------*/ 140141cc406Sopenharmony_ci 141141cc406Sopenharmony_ci/** 142141cc406Sopenharmony_ci * Initializes the debugging system, the USB system, the version code and 143141cc406Sopenharmony_ci * 'attaches' available scanners, i.e. creates device definitions for all 144141cc406Sopenharmony_ci * scanner devices found. 145141cc406Sopenharmony_ci * 146141cc406Sopenharmony_ci * @param version_code 147141cc406Sopenharmony_ci * @param authorize 148141cc406Sopenharmony_ci * @return SANE_STATUS_GOOD 149141cc406Sopenharmony_ci */ 150141cc406Sopenharmony_ciSANE_Status 151141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) 152141cc406Sopenharmony_ci{ 153141cc406Sopenharmony_ci FILE *fp; 154141cc406Sopenharmony_ci char config_line[PATH_MAX]; 155141cc406Sopenharmony_ci SANE_Word vendor_id; 156141cc406Sopenharmony_ci SANE_Word product_id; 157141cc406Sopenharmony_ci SANE_Int model_number; 158141cc406Sopenharmony_ci SANE_Int flags; 159141cc406Sopenharmony_ci SANE_Status status; 160141cc406Sopenharmony_ci int i; 161141cc406Sopenharmony_ci 162141cc406Sopenharmony_ci /* Initialize debug logging */ 163141cc406Sopenharmony_ci DBG_INIT (); 164141cc406Sopenharmony_ci 165141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_init() build %d\n", BUILD); 166141cc406Sopenharmony_ci 167141cc406Sopenharmony_ci /* Set version code to current major, minor and build number */ 168141cc406Sopenharmony_ci if (version_code) 169141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 170141cc406Sopenharmony_ci 171141cc406Sopenharmony_ci /* Initialize usb */ 172141cc406Sopenharmony_ci sanei_usb_init (); 173141cc406Sopenharmony_ci sanei_usb_set_timeout (30 * 1000); /* 30 sec timeout */ 174141cc406Sopenharmony_ci 175141cc406Sopenharmony_ci /* There are currently 3 scanners hardcoded into this backend, see below. 176141cc406Sopenharmony_ci * The config file may add other scanners using a line like 177141cc406Sopenharmony_ci * usb 0x1234 0x5678 0x9A 178141cc406Sopenharmony_ci * where the first two hex numbers are vendor and product id, and the last 179141cc406Sopenharmony_ci * number is the model number. Unfortunately, this is not according to the 180141cc406Sopenharmony_ci * config file standard. Anyone any suggestions? */ 181141cc406Sopenharmony_ci 182141cc406Sopenharmony_ci /* Create default list */ 183141cc406Sopenharmony_ci pieusb_supported_usb_device_list = calloc (4, sizeof(struct Pieusb_USB_Device_Entry)); 184141cc406Sopenharmony_ci if (pieusb_supported_usb_device_list == NULL) 185141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 186141cc406Sopenharmony_ci /* Reflecta CrystalScan 7200, model number 0x30 */ 187141cc406Sopenharmony_ci pieusb_supported_usb_device_list[0].vendor = 0x05e3; 188141cc406Sopenharmony_ci pieusb_supported_usb_device_list[0].product = 0x0145; 189141cc406Sopenharmony_ci pieusb_supported_usb_device_list[0].model = 0x30; 190141cc406Sopenharmony_ci pieusb_supported_usb_device_list[0].flags = 0; 191141cc406Sopenharmony_ci /* Reflecta ProScan 7200, model number 0x36 */ 192141cc406Sopenharmony_ci pieusb_supported_usb_device_list[1].vendor = 0x05e3; 193141cc406Sopenharmony_ci pieusb_supported_usb_device_list[1].product = 0x0145; 194141cc406Sopenharmony_ci pieusb_supported_usb_device_list[1].model = 0x36; 195141cc406Sopenharmony_ci pieusb_supported_usb_device_list[1].flags = 0; 196141cc406Sopenharmony_ci /* Reflecta 6000 Multiple Slide Scanner, model number 0x3a */ 197141cc406Sopenharmony_ci pieusb_supported_usb_device_list[2].vendor = 0x05e3; 198141cc406Sopenharmony_ci pieusb_supported_usb_device_list[2].product = 0x0142; 199141cc406Sopenharmony_ci pieusb_supported_usb_device_list[2].model = 0x3a; 200141cc406Sopenharmony_ci pieusb_supported_usb_device_list[2].flags = FLAG_SLIDE_TRANSPORT; 201141cc406Sopenharmony_ci /* end of list */ 202141cc406Sopenharmony_ci pieusb_supported_usb_device_list[3].vendor = 0; 203141cc406Sopenharmony_ci pieusb_supported_usb_device_list[3].product = 0; 204141cc406Sopenharmony_ci pieusb_supported_usb_device_list[3].model = 0; 205141cc406Sopenharmony_ci pieusb_supported_usb_device_list[3].flags = 0; 206141cc406Sopenharmony_ci 207141cc406Sopenharmony_ci /* Add entries from config file */ 208141cc406Sopenharmony_ci fp = sanei_config_open (PIEUSB_CONFIG_FILE); 209141cc406Sopenharmony_ci if (!fp) { 210141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_init() did not find a config file, using default list of supported devices\n"); 211141cc406Sopenharmony_ci } else { 212141cc406Sopenharmony_ci while (sanei_config_read (config_line, sizeof (config_line), fp)) { 213141cc406Sopenharmony_ci /* Ignore line comments and empty lines */ 214141cc406Sopenharmony_ci if (config_line[0] == '#') continue; 215141cc406Sopenharmony_ci if (strlen (config_line) == 0) continue; 216141cc406Sopenharmony_ci /* Ignore lines which do not begin with 'usb ' */ 217141cc406Sopenharmony_ci if (strncmp (config_line, "usb ", 4) != 0) continue; 218141cc406Sopenharmony_ci /* Parse vendor-id, product-id and model number and add to list */ 219141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_init() config file parsing %s\n", config_line); 220141cc406Sopenharmony_ci status = sanei_pieusb_parse_config_line(config_line, &vendor_id, &product_id, &model_number, &flags); 221141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) { 222141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_init() config file lists device %04x %04x %02x %02x\n",vendor_id, product_id, model_number, flags); 223141cc406Sopenharmony_ci if (!sanei_pieusb_supported_device_list_contains(vendor_id, product_id, model_number, flags)) { 224141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_init() adding device %04x %04x %02x %02x\n",vendor_id, product_id, model_number, flags); 225141cc406Sopenharmony_ci sanei_pieusb_supported_device_list_add(vendor_id, product_id, model_number, flags); 226141cc406Sopenharmony_ci } else { 227141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_init() list already contains %04x %04x %02x %02x\n", vendor_id, product_id, model_number, flags); 228141cc406Sopenharmony_ci } 229141cc406Sopenharmony_ci } else { 230141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_init() config file parsing %s: error\n", config_line); 231141cc406Sopenharmony_ci } 232141cc406Sopenharmony_ci } 233141cc406Sopenharmony_ci fclose (fp); 234141cc406Sopenharmony_ci } 235141cc406Sopenharmony_ci 236141cc406Sopenharmony_ci /* Loop through supported device list */ 237141cc406Sopenharmony_ci i = 0; 238141cc406Sopenharmony_ci while (pieusb_supported_usb_device_list[i].vendor != 0) { 239141cc406Sopenharmony_ci /* Check if the supported device is present. If so, create a device 240141cc406Sopenharmony_ci * definition structure for it. 241141cc406Sopenharmony_ci * The variable pieusb_supported_usb_device is set to current values, 242141cc406Sopenharmony_ci * which are used in the callback. */ 243141cc406Sopenharmony_ci pieusb_supported_usb_device.vendor = pieusb_supported_usb_device_list[i].vendor; 244141cc406Sopenharmony_ci pieusb_supported_usb_device.product = pieusb_supported_usb_device_list[i].product; 245141cc406Sopenharmony_ci pieusb_supported_usb_device.model = pieusb_supported_usb_device_list[i].model; 246141cc406Sopenharmony_ci pieusb_supported_usb_device.flags = pieusb_supported_usb_device_list[i].flags; 247141cc406Sopenharmony_ci pieusb_supported_usb_device.device_number = -1; /* No device number (yet) */ 248141cc406Sopenharmony_ci DBG( DBG_info_sane, "sane_init() looking for scanner %04x %04x model %02x, flags %02x\n", 249141cc406Sopenharmony_ci pieusb_supported_usb_device.vendor, 250141cc406Sopenharmony_ci pieusb_supported_usb_device.product, 251141cc406Sopenharmony_ci pieusb_supported_usb_device.model, 252141cc406Sopenharmony_ci pieusb_supported_usb_device.flags); 253141cc406Sopenharmony_ci sanei_usb_find_devices (pieusb_supported_usb_device.vendor, pieusb_supported_usb_device.product, sanei_pieusb_find_device_callback); 254141cc406Sopenharmony_ci i++; 255141cc406Sopenharmony_ci } 256141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 257141cc406Sopenharmony_ci} 258141cc406Sopenharmony_ci 259141cc406Sopenharmony_ci/** 260141cc406Sopenharmony_ci * Backend exit. 261141cc406Sopenharmony_ci * Clean up allocated memory. 262141cc406Sopenharmony_ci */ 263141cc406Sopenharmony_civoid 264141cc406Sopenharmony_cisane_exit (void) 265141cc406Sopenharmony_ci{ 266141cc406Sopenharmony_ci Pieusb_Device_Definition *dev, *next; 267141cc406Sopenharmony_ci 268141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_exit()\n"); 269141cc406Sopenharmony_ci 270141cc406Sopenharmony_ci for (dev = pieusb_definition_list_head; dev; dev = next) { 271141cc406Sopenharmony_ci next = dev->next; 272141cc406Sopenharmony_ci free((void *)dev->sane.name); 273141cc406Sopenharmony_ci free((void *)dev->sane.vendor); 274141cc406Sopenharmony_ci free((void *)dev->sane.model); 275141cc406Sopenharmony_ci free (dev->version); 276141cc406Sopenharmony_ci free (dev); 277141cc406Sopenharmony_ci } 278141cc406Sopenharmony_ci pieusb_definition_list_head = NULL; 279141cc406Sopenharmony_ci 280141cc406Sopenharmony_ci if (devlist) { 281141cc406Sopenharmony_ci free (devlist); 282141cc406Sopenharmony_ci devlist = NULL; 283141cc406Sopenharmony_ci } 284141cc406Sopenharmony_ci} 285141cc406Sopenharmony_ci 286141cc406Sopenharmony_ci/** 287141cc406Sopenharmony_ci * Create a SANE device list from the device list generated by sane_init(). 288141cc406Sopenharmony_ci * 289141cc406Sopenharmony_ci * @param device_list List of SANE_Device elements 290141cc406Sopenharmony_ci * @param local_only If true, disregard network scanners. Not applicable for USB scanners. 291141cc406Sopenharmony_ci * @return SANE_STATUS_GOOD, or SANE_STATUS_NO_MEM if the list cannot be allocated 292141cc406Sopenharmony_ci */ 293141cc406Sopenharmony_ciSANE_Status 294141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) 295141cc406Sopenharmony_ci{ 296141cc406Sopenharmony_ci Pieusb_Device_Definition *dev; 297141cc406Sopenharmony_ci int i; 298141cc406Sopenharmony_ci 299141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_get_devices\n"); 300141cc406Sopenharmony_ci 301141cc406Sopenharmony_ci /* Create SANE_DEVICE list from device list created in sane_init() */ 302141cc406Sopenharmony_ci i = 0; 303141cc406Sopenharmony_ci for (dev = pieusb_definition_list_head; dev; dev = dev->next) { 304141cc406Sopenharmony_ci i++; 305141cc406Sopenharmony_ci } 306141cc406Sopenharmony_ci if (devlist) { 307141cc406Sopenharmony_ci free (devlist); 308141cc406Sopenharmony_ci } 309141cc406Sopenharmony_ci devlist = malloc ((i + 1) * sizeof (devlist[0])); 310141cc406Sopenharmony_ci if (!devlist) { 311141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 312141cc406Sopenharmony_ci } 313141cc406Sopenharmony_ci i = 0; 314141cc406Sopenharmony_ci for (dev = pieusb_definition_list_head; dev; dev = dev->next) { 315141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 316141cc406Sopenharmony_ci } 317141cc406Sopenharmony_ci devlist[i] = NULL; 318141cc406Sopenharmony_ci *device_list = devlist; 319141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 320141cc406Sopenharmony_ci} 321141cc406Sopenharmony_ci 322141cc406Sopenharmony_ci/** 323141cc406Sopenharmony_ci * Open the scanner with the given devicename and return a handle to it, which 324141cc406Sopenharmony_ci * is a pointer to a Pieusb_Scanner struct. The handle will be an input to 325141cc406Sopenharmony_ci * a couple of other functions of the SANE interface. 326141cc406Sopenharmony_ci * 327141cc406Sopenharmony_ci * @param devicename Name of the device, corresponds to SANE_Device.name 328141cc406Sopenharmony_ci * @param handle handle to scanner (pointer to a Pieusb_Scanner struct) 329141cc406Sopenharmony_ci * @return SANE_STATUS_GOOD if the device has been opened 330141cc406Sopenharmony_ci */ 331141cc406Sopenharmony_ciSANE_Status 332141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 333141cc406Sopenharmony_ci{ 334141cc406Sopenharmony_ci Pieusb_Device_Definition *dev; 335141cc406Sopenharmony_ci SANE_Status status; 336141cc406Sopenharmony_ci Pieusb_Scanner *scanner, *s; 337141cc406Sopenharmony_ci 338141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_open(%s)\n", devicename); 339141cc406Sopenharmony_ci 340141cc406Sopenharmony_ci /* Search for devicename */ 341141cc406Sopenharmony_ci if (devicename[0]) { 342141cc406Sopenharmony_ci for (dev = pieusb_definition_list_head; dev; dev = dev->next) { 343141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) { 344141cc406Sopenharmony_ci break; 345141cc406Sopenharmony_ci } 346141cc406Sopenharmony_ci } 347141cc406Sopenharmony_ci if (!dev) { 348141cc406Sopenharmony_ci /* Is it a valid USB device? */ 349141cc406Sopenharmony_ci SANE_Word vendor; 350141cc406Sopenharmony_ci SANE_Word product; 351141cc406Sopenharmony_ci int i = 0; 352141cc406Sopenharmony_ci 353141cc406Sopenharmony_ci status = sanei_usb_get_vendor_product_byname (devicename, &vendor, &product); 354141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 355141cc406Sopenharmony_ci DBG (DBG_error, "sane_open: sanei_usb_get_vendor_product_byname failed %s\n", devicename); 356141cc406Sopenharmony_ci return status; 357141cc406Sopenharmony_ci } 358141cc406Sopenharmony_ci /* Get vendor-product-model & verify that is is supported */ 359141cc406Sopenharmony_ci /* Loop through supported device list */ 360141cc406Sopenharmony_ci while (pieusb_supported_usb_device_list[i].vendor != 0) { 361141cc406Sopenharmony_ci /* Check if vendor and product match */ 362141cc406Sopenharmony_ci if (pieusb_supported_usb_device_list[i].vendor == vendor 363141cc406Sopenharmony_ci && pieusb_supported_usb_device_list[i].product == product) { 364141cc406Sopenharmony_ci /* Check if a supported device is present 365141cc406Sopenharmony_ci * If so, create a device definition structure for it. */ 366141cc406Sopenharmony_ci /* Set pieusb_supported_usb_device to current values: these are used in callback */ 367141cc406Sopenharmony_ci pieusb_supported_usb_device.vendor = vendor; 368141cc406Sopenharmony_ci pieusb_supported_usb_device.product = product; 369141cc406Sopenharmony_ci pieusb_supported_usb_device.model = pieusb_supported_usb_device_list[i].model; 370141cc406Sopenharmony_ci pieusb_supported_usb_device.flags = pieusb_supported_usb_device_list[i].flags; 371141cc406Sopenharmony_ci pieusb_supported_usb_device.device_number = -1; 372141cc406Sopenharmony_ci sanei_usb_find_devices (vendor, product, sanei_pieusb_find_device_callback); 373141cc406Sopenharmony_ci if (pieusb_supported_usb_device.device_number == -1) { 374141cc406Sopenharmony_ci /* Did not succeed in opening the USB device, which is an error. 375141cc406Sopenharmony_ci * This error is not caught by sanei_usb_find_devices(), so handle 376141cc406Sopenharmony_ci * it here. */ 377141cc406Sopenharmony_ci DBG (DBG_error, "sane_open: sanei_usb_find_devices did not open device %s\n", devicename); 378141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 379141cc406Sopenharmony_ci } 380141cc406Sopenharmony_ci } 381141cc406Sopenharmony_ci i++; 382141cc406Sopenharmony_ci } 383141cc406Sopenharmony_ci /* Now rescan the device list to see if it is present */ 384141cc406Sopenharmony_ci for (dev = pieusb_definition_list_head; dev; dev = dev->next) { 385141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) { 386141cc406Sopenharmony_ci break; 387141cc406Sopenharmony_ci } 388141cc406Sopenharmony_ci } 389141cc406Sopenharmony_ci } 390141cc406Sopenharmony_ci } else { 391141cc406Sopenharmony_ci /* empty devicename -> use first device */ 392141cc406Sopenharmony_ci dev = pieusb_definition_list_head; 393141cc406Sopenharmony_ci } 394141cc406Sopenharmony_ci /* If no device found, return error */ 395141cc406Sopenharmony_ci if (!dev) { 396141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 397141cc406Sopenharmony_ci } 398141cc406Sopenharmony_ci 399141cc406Sopenharmony_ci /* Now create a scanner structure to return */ 400141cc406Sopenharmony_ci 401141cc406Sopenharmony_ci /* Check if we are not opening the same scanner again. */ 402141cc406Sopenharmony_ci for (s = first_handle; s; s = s->next) { 403141cc406Sopenharmony_ci if (s->device->sane.name == devicename) { 404141cc406Sopenharmony_ci *handle = s; 405141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 406141cc406Sopenharmony_ci } 407141cc406Sopenharmony_ci } 408141cc406Sopenharmony_ci 409141cc406Sopenharmony_ci /* Create a new scanner instance */ 410141cc406Sopenharmony_ci scanner = malloc (sizeof (*scanner)); 411141cc406Sopenharmony_ci if (!scanner) { 412141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 413141cc406Sopenharmony_ci } 414141cc406Sopenharmony_ci memset (scanner, 0, sizeof (*scanner)); 415141cc406Sopenharmony_ci scanner->device = dev; 416141cc406Sopenharmony_ci sanei_usb_open (dev->sane.name, &scanner->device_number); 417141cc406Sopenharmony_ci scanner->cancel_request = 0; 418141cc406Sopenharmony_ci scanner->shading_data_present = SANE_FALSE; 419141cc406Sopenharmony_ci /* Options and buffers */ 420141cc406Sopenharmony_ci (void)sanei_pieusb_init_options (scanner); 421141cc406Sopenharmony_ci 422141cc406Sopenharmony_ci /* wait for warmup */ 423141cc406Sopenharmony_ci status = sanei_pieusb_wait_ready (scanner, 0); 424141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 425141cc406Sopenharmony_ci sanei_usb_close(scanner->device_number); 426141cc406Sopenharmony_ci free (scanner); 427141cc406Sopenharmony_ci DBG (DBG_error, "sane_open: scanner not ready\n"); 428141cc406Sopenharmony_ci return status; 429141cc406Sopenharmony_ci } 430141cc406Sopenharmony_ci 431141cc406Sopenharmony_ci /* First time settings */ 432141cc406Sopenharmony_ci /* ? */ 433141cc406Sopenharmony_ci /* Insert newly opened handle into list of open handles: */ 434141cc406Sopenharmony_ci scanner->next = first_handle; 435141cc406Sopenharmony_ci first_handle = scanner; 436141cc406Sopenharmony_ci 437141cc406Sopenharmony_ci *handle = scanner; 438141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 439141cc406Sopenharmony_ci} 440141cc406Sopenharmony_ci 441141cc406Sopenharmony_ci/** 442141cc406Sopenharmony_ci * Close the scanner and remove the scanner from the list of active scanners. 443141cc406Sopenharmony_ci * 444141cc406Sopenharmony_ci * @param handle Scanner handle 445141cc406Sopenharmony_ci */ 446141cc406Sopenharmony_civoid 447141cc406Sopenharmony_cisane_close (SANE_Handle handle) 448141cc406Sopenharmony_ci{ 449141cc406Sopenharmony_ci Pieusb_Scanner *prev, *scanner; 450141cc406Sopenharmony_ci SANE_Int k; 451141cc406Sopenharmony_ci 452141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_close()\n"); 453141cc406Sopenharmony_ci 454141cc406Sopenharmony_ci /* Find handle in list of open handles: */ 455141cc406Sopenharmony_ci prev = 0; 456141cc406Sopenharmony_ci for (scanner = first_handle; scanner; scanner = scanner->next) { 457141cc406Sopenharmony_ci if (scanner == handle) { 458141cc406Sopenharmony_ci break; 459141cc406Sopenharmony_ci } 460141cc406Sopenharmony_ci prev = scanner; 461141cc406Sopenharmony_ci } 462141cc406Sopenharmony_ci /* Not a handle we know about. This may happen since all different backend 463141cc406Sopenharmony_ci * scanner instances are all cast to SANE_Handle (a void pointer) */ 464141cc406Sopenharmony_ci if (!scanner) { 465141cc406Sopenharmony_ci DBG (DBG_error, "sane_close(): invalid handle %p\n", handle); 466141cc406Sopenharmony_ci return; 467141cc406Sopenharmony_ci } 468141cc406Sopenharmony_ci 469141cc406Sopenharmony_ci /* Stop scan if still scanning */ 470141cc406Sopenharmony_ci if (scanner->scanning) { 471141cc406Sopenharmony_ci sanei_pieusb_on_cancel(scanner); 472141cc406Sopenharmony_ci } 473141cc406Sopenharmony_ci 474141cc406Sopenharmony_ci /* USB scanners may be still open here */ 475141cc406Sopenharmony_ci if (scanner->device_number >= 0) { 476141cc406Sopenharmony_ci sanei_usb_reset (scanner->device_number); 477141cc406Sopenharmony_ci sanei_usb_close (scanner->device_number); 478141cc406Sopenharmony_ci } 479141cc406Sopenharmony_ci /* Remove handle from list */ 480141cc406Sopenharmony_ci if (prev) { 481141cc406Sopenharmony_ci prev->next = scanner->next; 482141cc406Sopenharmony_ci } else { 483141cc406Sopenharmony_ci first_handle = scanner->next; 484141cc406Sopenharmony_ci } 485141cc406Sopenharmony_ci 486141cc406Sopenharmony_ci /* Free scanner related allocated memory and the scanner itself */ 487141cc406Sopenharmony_ci /*TODO: check if complete */ 488141cc406Sopenharmony_ci if (scanner->buffer.data) sanei_pieusb_buffer_delete(&scanner->buffer); 489141cc406Sopenharmony_ci free (scanner->ccd_mask); 490141cc406Sopenharmony_ci for (k=0; k<4; k++) free (scanner->shading_ref[k]); 491141cc406Sopenharmony_ci free (scanner->val[OPT_MODE].s); 492141cc406Sopenharmony_ci free (scanner->val[OPT_HALFTONE_PATTERN].s); 493141cc406Sopenharmony_ci free (scanner); 494141cc406Sopenharmony_ci} 495141cc406Sopenharmony_ci 496141cc406Sopenharmony_ci/** 497141cc406Sopenharmony_ci * Get option descriptor. Return the option descriptor with the given index 498141cc406Sopenharmony_ci * 499141cc406Sopenharmony_ci * @param handle Scanner handle 500141cc406Sopenharmony_ci * @param option Index of option descriptor to return 501141cc406Sopenharmony_ci * @return The option descriptor 502141cc406Sopenharmony_ci */ 503141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 504141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 505141cc406Sopenharmony_ci{ 506141cc406Sopenharmony_ci Pieusb_Scanner *scanner = handle; 507141cc406Sopenharmony_ci 508141cc406Sopenharmony_ci DBG (DBG_info_proc, "sane_get_option_descriptor() option=%d\n", option); 509141cc406Sopenharmony_ci 510141cc406Sopenharmony_ci if ((unsigned) option >= NUM_OPTIONS) 511141cc406Sopenharmony_ci { 512141cc406Sopenharmony_ci return 0; 513141cc406Sopenharmony_ci } 514141cc406Sopenharmony_ci 515141cc406Sopenharmony_ci return scanner->opt + option; 516141cc406Sopenharmony_ci} 517141cc406Sopenharmony_ci 518141cc406Sopenharmony_ci/** 519141cc406Sopenharmony_ci * Set or inquire the current value of option number 'option' of the device 520141cc406Sopenharmony_ci * represented by the given handle. 521141cc406Sopenharmony_ci * 522141cc406Sopenharmony_ci * @param handle Scanner handle 523141cc406Sopenharmony_ci * @param option Index of option to set or get 524141cc406Sopenharmony_ci * @param action Determines if the option value is read or set 525141cc406Sopenharmony_ci * @param val Pointer to value to set or get 526141cc406Sopenharmony_ci * @param info About set result. May be NULL. 527141cc406Sopenharmony_ci * @return SANE_STATUS_GOOD, or SANE_STATUS_INVAL if a parameter cannot be set 528141cc406Sopenharmony_ci */ 529141cc406Sopenharmony_ciSANE_Status 530141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, 531141cc406Sopenharmony_ci void *val, SANE_Int * info) 532141cc406Sopenharmony_ci{ 533141cc406Sopenharmony_ci Pieusb_Scanner *scanner = handle; 534141cc406Sopenharmony_ci SANE_Status status; 535141cc406Sopenharmony_ci SANE_Word cap; 536141cc406Sopenharmony_ci SANE_String_Const name; 537141cc406Sopenharmony_ci 538141cc406Sopenharmony_ci DBG(DBG_info_sane,"sane_control_option()\n"); 539141cc406Sopenharmony_ci if (info) { 540141cc406Sopenharmony_ci *info = 0; 541141cc406Sopenharmony_ci } 542141cc406Sopenharmony_ci 543141cc406Sopenharmony_ci /* Don't set or get options while the scanner is busy */ 544141cc406Sopenharmony_ci if (scanner->scanning) { 545141cc406Sopenharmony_ci DBG(DBG_error,"Device busy scanning, no option returned\n"); 546141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 547141cc406Sopenharmony_ci } 548141cc406Sopenharmony_ci 549141cc406Sopenharmony_ci /* Check if option index is between bounds */ 550141cc406Sopenharmony_ci if ((unsigned) option >= NUM_OPTIONS) { 551141cc406Sopenharmony_ci DBG(DBG_error,"Index too large, no option returned\n"); 552141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 553141cc406Sopenharmony_ci } 554141cc406Sopenharmony_ci 555141cc406Sopenharmony_ci /* Check if option is switched on */ 556141cc406Sopenharmony_ci cap = scanner->opt[option].cap; 557141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (cap)) 558141cc406Sopenharmony_ci { 559141cc406Sopenharmony_ci DBG(DBG_error,"Option inactive (%s)\n", scanner->opt[option].name); 560141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 561141cc406Sopenharmony_ci } 562141cc406Sopenharmony_ci 563141cc406Sopenharmony_ci /* Get name of option */ 564141cc406Sopenharmony_ci name = scanner->opt[option].name; 565141cc406Sopenharmony_ci if (!name) 566141cc406Sopenharmony_ci { 567141cc406Sopenharmony_ci name = "(no name)"; 568141cc406Sopenharmony_ci } 569141cc406Sopenharmony_ci 570141cc406Sopenharmony_ci /* */ 571141cc406Sopenharmony_ci switch (action) { 572141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 573141cc406Sopenharmony_ci 574141cc406Sopenharmony_ci DBG (DBG_info_sane, "get %s [#%d]\n", name, option); 575141cc406Sopenharmony_ci 576141cc406Sopenharmony_ci switch (option) { 577141cc406Sopenharmony_ci 578141cc406Sopenharmony_ci /* word options: */ 579141cc406Sopenharmony_ci case OPT_NUM_OPTS: 580141cc406Sopenharmony_ci case OPT_BIT_DEPTH: 581141cc406Sopenharmony_ci case OPT_RESOLUTION: 582141cc406Sopenharmony_ci case OPT_TL_X: 583141cc406Sopenharmony_ci case OPT_TL_Y: 584141cc406Sopenharmony_ci case OPT_BR_X: 585141cc406Sopenharmony_ci case OPT_BR_Y: 586141cc406Sopenharmony_ci case OPT_THRESHOLD: 587141cc406Sopenharmony_ci case OPT_SHARPEN: 588141cc406Sopenharmony_ci case OPT_SHADING_ANALYSIS: 589141cc406Sopenharmony_ci case OPT_FAST_INFRARED: 590141cc406Sopenharmony_ci case OPT_ADVANCE_SLIDE: 591141cc406Sopenharmony_ci case OPT_CORRECT_SHADING: 592141cc406Sopenharmony_ci case OPT_CORRECT_INFRARED: 593141cc406Sopenharmony_ci case OPT_CLEAN_IMAGE: 594141cc406Sopenharmony_ci case OPT_SMOOTH_IMAGE: 595141cc406Sopenharmony_ci case OPT_TRANSFORM_TO_SRGB: 596141cc406Sopenharmony_ci case OPT_INVERT_IMAGE: 597141cc406Sopenharmony_ci case OPT_PREVIEW: 598141cc406Sopenharmony_ci case OPT_SAVE_SHADINGDATA: 599141cc406Sopenharmony_ci case OPT_SAVE_CCDMASK: 600141cc406Sopenharmony_ci case OPT_LIGHT: 601141cc406Sopenharmony_ci case OPT_DOUBLE_TIMES: 602141cc406Sopenharmony_ci case OPT_SET_EXPOSURE_R: 603141cc406Sopenharmony_ci case OPT_SET_EXPOSURE_G: 604141cc406Sopenharmony_ci case OPT_SET_EXPOSURE_B: 605141cc406Sopenharmony_ci case OPT_SET_EXPOSURE_I: 606141cc406Sopenharmony_ci case OPT_SET_GAIN_R: 607141cc406Sopenharmony_ci case OPT_SET_GAIN_G: 608141cc406Sopenharmony_ci case OPT_SET_GAIN_B: 609141cc406Sopenharmony_ci case OPT_SET_GAIN_I: 610141cc406Sopenharmony_ci case OPT_SET_OFFSET_R: 611141cc406Sopenharmony_ci case OPT_SET_OFFSET_G: 612141cc406Sopenharmony_ci case OPT_SET_OFFSET_B: 613141cc406Sopenharmony_ci case OPT_SET_OFFSET_I: 614141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->val[option].w; 615141cc406Sopenharmony_ci DBG (DBG_info_sane, "get %s [#%d] val=%d\n", name, option,scanner->val[option].w); 616141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 617141cc406Sopenharmony_ci 618141cc406Sopenharmony_ci /* word-array options: => for exposure gain offset? */ 619141cc406Sopenharmony_ci case OPT_CROP_IMAGE: 620141cc406Sopenharmony_ci memcpy (val, scanner->val[option].wa, scanner->opt[option].size); 621141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 622141cc406Sopenharmony_ci 623141cc406Sopenharmony_ci /* string options */ 624141cc406Sopenharmony_ci case OPT_MODE: 625141cc406Sopenharmony_ci case OPT_CALIBRATION_MODE: 626141cc406Sopenharmony_ci case OPT_GAIN_ADJUST: 627141cc406Sopenharmony_ci case OPT_HALFTONE_PATTERN: 628141cc406Sopenharmony_ci strcpy (val, scanner->val[option].s); 629141cc406Sopenharmony_ci DBG (DBG_info_sane, "get %s [#%d] val=%s\n", name, option,scanner->val[option].s); 630141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 631141cc406Sopenharmony_ci } 632141cc406Sopenharmony_ci break; 633141cc406Sopenharmony_ci 634141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 635141cc406Sopenharmony_ci 636141cc406Sopenharmony_ci switch (scanner->opt[option].type) { 637141cc406Sopenharmony_ci case SANE_TYPE_INT: 638141cc406Sopenharmony_ci DBG (DBG_info_sane, "set %s [#%d] to %d, size=%d\n", name, option, *(SANE_Word *) val, scanner->opt[option].size); 639141cc406Sopenharmony_ci break; 640141cc406Sopenharmony_ci case SANE_TYPE_FIXED: 641141cc406Sopenharmony_ci DBG (DBG_info_sane, "set %s [#%d] to %f\n", name, option, SANE_UNFIX (*(SANE_Word *) val)); 642141cc406Sopenharmony_ci break; 643141cc406Sopenharmony_ci case SANE_TYPE_STRING: 644141cc406Sopenharmony_ci DBG (DBG_info_sane, "set %s [#%d] to %s\n", name, option, (char *) val); 645141cc406Sopenharmony_ci break; 646141cc406Sopenharmony_ci case SANE_TYPE_BOOL: 647141cc406Sopenharmony_ci DBG (DBG_info_sane, "set %s [#%d] to %d\n", name, option, *(SANE_Word *) val); 648141cc406Sopenharmony_ci break; 649141cc406Sopenharmony_ci default: 650141cc406Sopenharmony_ci DBG (DBG_info_sane, "set %s [#%d]\n", name, option); 651141cc406Sopenharmony_ci } 652141cc406Sopenharmony_ci /* Check if option can be set */ 653141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (cap)) { 654141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 655141cc406Sopenharmony_ci } 656141cc406Sopenharmony_ci /* Check if new value within bounds */ 657141cc406Sopenharmony_ci status = sanei_constrain_value (scanner->opt + option, val, info); 658141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 659141cc406Sopenharmony_ci return status; 660141cc406Sopenharmony_ci } 661141cc406Sopenharmony_ci /* Set option and handle info return */ 662141cc406Sopenharmony_ci switch (option) 663141cc406Sopenharmony_ci { 664141cc406Sopenharmony_ci /* (mostly) side-effect-free word options: */ 665141cc406Sopenharmony_ci case OPT_BIT_DEPTH: 666141cc406Sopenharmony_ci case OPT_RESOLUTION: 667141cc406Sopenharmony_ci case OPT_TL_X: 668141cc406Sopenharmony_ci case OPT_TL_Y: 669141cc406Sopenharmony_ci case OPT_BR_X: 670141cc406Sopenharmony_ci case OPT_BR_Y: 671141cc406Sopenharmony_ci case OPT_SHARPEN: 672141cc406Sopenharmony_ci case OPT_SHADING_ANALYSIS: 673141cc406Sopenharmony_ci case OPT_FAST_INFRARED: 674141cc406Sopenharmony_ci if (info) { 675141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 676141cc406Sopenharmony_ci } 677141cc406Sopenharmony_ci /* fall through */ 678141cc406Sopenharmony_ci case OPT_NUM_OPTS: 679141cc406Sopenharmony_ci case OPT_PREVIEW: 680141cc406Sopenharmony_ci case OPT_ADVANCE_SLIDE: 681141cc406Sopenharmony_ci case OPT_CORRECT_SHADING: 682141cc406Sopenharmony_ci case OPT_CORRECT_INFRARED: 683141cc406Sopenharmony_ci case OPT_CLEAN_IMAGE: 684141cc406Sopenharmony_ci case OPT_SMOOTH_IMAGE: 685141cc406Sopenharmony_ci case OPT_TRANSFORM_TO_SRGB: 686141cc406Sopenharmony_ci case OPT_INVERT_IMAGE: 687141cc406Sopenharmony_ci case OPT_SAVE_SHADINGDATA: 688141cc406Sopenharmony_ci case OPT_SAVE_CCDMASK: 689141cc406Sopenharmony_ci case OPT_THRESHOLD: 690141cc406Sopenharmony_ci case OPT_LIGHT: 691141cc406Sopenharmony_ci case OPT_DOUBLE_TIMES: 692141cc406Sopenharmony_ci case OPT_SET_GAIN_R: 693141cc406Sopenharmony_ci case OPT_SET_GAIN_G: 694141cc406Sopenharmony_ci case OPT_SET_GAIN_B: 695141cc406Sopenharmony_ci case OPT_SET_GAIN_I: 696141cc406Sopenharmony_ci case OPT_SET_OFFSET_R: 697141cc406Sopenharmony_ci case OPT_SET_OFFSET_G: 698141cc406Sopenharmony_ci case OPT_SET_OFFSET_B: 699141cc406Sopenharmony_ci case OPT_SET_OFFSET_I: 700141cc406Sopenharmony_ci case OPT_SET_EXPOSURE_R: 701141cc406Sopenharmony_ci case OPT_SET_EXPOSURE_G: 702141cc406Sopenharmony_ci case OPT_SET_EXPOSURE_B: 703141cc406Sopenharmony_ci case OPT_SET_EXPOSURE_I: 704141cc406Sopenharmony_ci scanner->val[option].w = *(SANE_Word *) val; 705141cc406Sopenharmony_ci break; 706141cc406Sopenharmony_ci 707141cc406Sopenharmony_ci /* side-effect-free word-array options: */ 708141cc406Sopenharmony_ci case OPT_CROP_IMAGE: 709141cc406Sopenharmony_ci memcpy (scanner->val[option].wa, val, scanner->opt[option].size); 710141cc406Sopenharmony_ci break; 711141cc406Sopenharmony_ci 712141cc406Sopenharmony_ci /* options with side-effects: */ 713141cc406Sopenharmony_ci case OPT_MODE: 714141cc406Sopenharmony_ci { 715141cc406Sopenharmony_ci /* Free current setting */ 716141cc406Sopenharmony_ci if (scanner->val[option].s) { 717141cc406Sopenharmony_ci free (scanner->val[option].s); 718141cc406Sopenharmony_ci } 719141cc406Sopenharmony_ci /* New setting */ 720141cc406Sopenharmony_ci scanner->val[option].s = (SANE_Char *) strdup (val); 721141cc406Sopenharmony_ci /* Info */ 722141cc406Sopenharmony_ci if (info) { 723141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 724141cc406Sopenharmony_ci } 725141cc406Sopenharmony_ci break; 726141cc406Sopenharmony_ci } 727141cc406Sopenharmony_ci 728141cc406Sopenharmony_ci case OPT_CALIBRATION_MODE: 729141cc406Sopenharmony_ci case OPT_GAIN_ADJUST: 730141cc406Sopenharmony_ci case OPT_HALFTONE_PATTERN: 731141cc406Sopenharmony_ci { 732141cc406Sopenharmony_ci /* Free current setting */ 733141cc406Sopenharmony_ci if (scanner->val[option].s) { 734141cc406Sopenharmony_ci free (scanner->val[option].s); 735141cc406Sopenharmony_ci } 736141cc406Sopenharmony_ci /* New setting */ 737141cc406Sopenharmony_ci scanner->val[option].s = (SANE_Char *) strdup (val); 738141cc406Sopenharmony_ci break; 739141cc406Sopenharmony_ci } 740141cc406Sopenharmony_ci 741141cc406Sopenharmony_ci } 742141cc406Sopenharmony_ci 743141cc406Sopenharmony_ci /* Check the whole set */ 744141cc406Sopenharmony_ci if (sanei_pieusb_analyse_options(scanner)) { 745141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 746141cc406Sopenharmony_ci } else { 747141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 748141cc406Sopenharmony_ci } 749141cc406Sopenharmony_ci 750141cc406Sopenharmony_ci break; 751141cc406Sopenharmony_ci default: 752141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 753141cc406Sopenharmony_ci break; 754141cc406Sopenharmony_ci } 755141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 756141cc406Sopenharmony_ci} 757141cc406Sopenharmony_ci 758141cc406Sopenharmony_ci/** 759141cc406Sopenharmony_ci * Obtain the current scan parameters. The returned parameters are guaranteed 760141cc406Sopenharmony_ci * to be accurate between the time a scan has been started (sane start() has 761141cc406Sopenharmony_ci * been called) and the completion of that request. Outside of that window, the 762141cc406Sopenharmony_ci * returned values are best-effort estimates of what the parameters will be when 763141cc406Sopenharmony_ci * sane start() gets invoked. - says the SANE standard. 764141cc406Sopenharmony_ci * 765141cc406Sopenharmony_ci * @param handle Scanner handle 766141cc406Sopenharmony_ci * @param params Scan parameters 767141cc406Sopenharmony_ci * @return SANE_STATUS_GOOD 768141cc406Sopenharmony_ci */ 769141cc406Sopenharmony_ciSANE_Status 770141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 771141cc406Sopenharmony_ci{ 772141cc406Sopenharmony_ci Pieusb_Scanner *scanner = handle; 773141cc406Sopenharmony_ci const char *mode; 774141cc406Sopenharmony_ci double resolution, width, height; 775141cc406Sopenharmony_ci SANE_Int colors; 776141cc406Sopenharmony_ci 777141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_get_parameters\n"); 778141cc406Sopenharmony_ci 779141cc406Sopenharmony_ci if (params) { 780141cc406Sopenharmony_ci 781141cc406Sopenharmony_ci if (scanner->scanning) { 782141cc406Sopenharmony_ci /* sane_start() initialized a SANE_Parameters struct in the scanner */ 783141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_get_parameters from scanner values\n"); 784141cc406Sopenharmony_ci params->bytes_per_line = scanner->scan_parameters.bytes_per_line; 785141cc406Sopenharmony_ci params->depth = scanner->scan_parameters.depth; 786141cc406Sopenharmony_ci params->format = scanner->scan_parameters.format; 787141cc406Sopenharmony_ci params->last_frame = scanner->scan_parameters.last_frame; 788141cc406Sopenharmony_ci params->lines = scanner->scan_parameters.lines; 789141cc406Sopenharmony_ci params->pixels_per_line = scanner->scan_parameters.pixels_per_line; 790141cc406Sopenharmony_ci } else { 791141cc406Sopenharmony_ci /* Calculate appropriate values from option settings */ 792141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_get_parameters from option values\n"); 793141cc406Sopenharmony_ci if (scanner->val[OPT_PREVIEW].b) { 794141cc406Sopenharmony_ci resolution = scanner->device->fast_preview_resolution; 795141cc406Sopenharmony_ci } else { 796141cc406Sopenharmony_ci resolution = SANE_UNFIX(scanner->val[OPT_RESOLUTION].w); 797141cc406Sopenharmony_ci } 798141cc406Sopenharmony_ci DBG (DBG_info_sane, " resolution %f\n", resolution); 799141cc406Sopenharmony_ci width = SANE_UNFIX(scanner->val[OPT_BR_X].w)-SANE_UNFIX(scanner->val[OPT_TL_X].w); 800141cc406Sopenharmony_ci height = SANE_UNFIX(scanner->val[OPT_BR_Y].w)-SANE_UNFIX(scanner->val[OPT_TL_Y].w); 801141cc406Sopenharmony_ci DBG (DBG_info_sane, " width x height: %f x %f\n", width, height); 802141cc406Sopenharmony_ci params->lines = height / MM_PER_INCH * resolution; 803141cc406Sopenharmony_ci params->pixels_per_line = width / MM_PER_INCH * resolution; 804141cc406Sopenharmony_ci mode = scanner->val[OPT_MODE].s; 805141cc406Sopenharmony_ci if (strcmp(mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) { 806141cc406Sopenharmony_ci params->format = SANE_FRAME_GRAY; 807141cc406Sopenharmony_ci params->depth = 1; 808141cc406Sopenharmony_ci colors = 1; 809141cc406Sopenharmony_ci } else if(strcmp(mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) { 810141cc406Sopenharmony_ci params->format = SANE_FRAME_GRAY; 811141cc406Sopenharmony_ci params->depth = 1; 812141cc406Sopenharmony_ci colors = 1; 813141cc406Sopenharmony_ci } else if(strcmp(mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) { 814141cc406Sopenharmony_ci params->format = SANE_FRAME_GRAY; 815141cc406Sopenharmony_ci params->depth = scanner->val[OPT_BIT_DEPTH].w; 816141cc406Sopenharmony_ci colors = 1; 817141cc406Sopenharmony_ci } else if(strcmp(mode, SANE_VALUE_SCAN_MODE_RGBI) == 0) { 818141cc406Sopenharmony_ci params->format = SANE_FRAME_RGB; /* was: SANE_FRAME_RGBI */ 819141cc406Sopenharmony_ci params->depth = scanner->val[OPT_BIT_DEPTH].w; 820141cc406Sopenharmony_ci colors = 4; 821141cc406Sopenharmony_ci } else { /* SANE_VALUE_SCAN_MODE_COLOR */ 822141cc406Sopenharmony_ci params->format = SANE_FRAME_RGB; 823141cc406Sopenharmony_ci params->depth = scanner->val[OPT_BIT_DEPTH].w; 824141cc406Sopenharmony_ci colors = 3; 825141cc406Sopenharmony_ci } 826141cc406Sopenharmony_ci DBG (DBG_info_sane, " colors: %d\n", colors); 827141cc406Sopenharmony_ci if (params->depth == 1) { 828141cc406Sopenharmony_ci params->bytes_per_line = colors * (params->pixels_per_line + 7)/8; 829141cc406Sopenharmony_ci } else if (params->depth <= 8) { 830141cc406Sopenharmony_ci params->bytes_per_line = colors * params->pixels_per_line; 831141cc406Sopenharmony_ci } else if (params->depth <= 16) { 832141cc406Sopenharmony_ci params->bytes_per_line = 2 * colors * params->pixels_per_line; 833141cc406Sopenharmony_ci } 834141cc406Sopenharmony_ci params->last_frame = SANE_TRUE; 835141cc406Sopenharmony_ci } 836141cc406Sopenharmony_ci 837141cc406Sopenharmony_ci DBG(DBG_info_sane,"sane_get_parameters(): SANE parameters\n"); 838141cc406Sopenharmony_ci DBG(DBG_info_sane," format = %d\n",params->format); 839141cc406Sopenharmony_ci DBG(DBG_info_sane," last_frame = %d\n",params->last_frame); 840141cc406Sopenharmony_ci DBG(DBG_info_sane," bytes_per_line = %d\n",params->bytes_per_line); 841141cc406Sopenharmony_ci DBG(DBG_info_sane," pixels_per_line = %d\n",params->pixels_per_line); 842141cc406Sopenharmony_ci DBG(DBG_info_sane," lines = %d\n",params->lines); 843141cc406Sopenharmony_ci DBG(DBG_info_sane," depth = %d\n",params->depth); 844141cc406Sopenharmony_ci 845141cc406Sopenharmony_ci } else { 846141cc406Sopenharmony_ci 847141cc406Sopenharmony_ci DBG(DBG_info_sane," no params argument, no values returned\n"); 848141cc406Sopenharmony_ci 849141cc406Sopenharmony_ci } 850141cc406Sopenharmony_ci 851141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 852141cc406Sopenharmony_ci} 853141cc406Sopenharmony_ci 854141cc406Sopenharmony_ci/** 855141cc406Sopenharmony_ci * Initiates acquisition of an image from the scanner. 856141cc406Sopenharmony_ci * SCAN Phase 1: initialization and calibration 857141cc406Sopenharmony_ci * (SCAN Phase 2: line-by-line scan & read is not implemented) 858141cc406Sopenharmony_ci * SCAN Phase 3: get CCD-mask 859141cc406Sopenharmony_ci * SCAN phase 4: scan slide and save data in scanner buffer 860141cc406Sopenharmony_ci 861141cc406Sopenharmony_ci * @param handle Scanner handle 862141cc406Sopenharmony_ci * @return 863141cc406Sopenharmony_ci */ 864141cc406Sopenharmony_ciSANE_Status 865141cc406Sopenharmony_cisane_start (SANE_Handle handle) 866141cc406Sopenharmony_ci{ 867141cc406Sopenharmony_ci struct Pieusb_Scanner *scanner = handle; 868141cc406Sopenharmony_ci struct Pieusb_Command_Status status; 869141cc406Sopenharmony_ci SANE_Byte colors; 870141cc406Sopenharmony_ci const char *mode; 871141cc406Sopenharmony_ci SANE_Bool shading_correction_relevant; 872141cc406Sopenharmony_ci SANE_Bool infrared_post_processing_relevant; 873141cc406Sopenharmony_ci SANE_Status st; 874141cc406Sopenharmony_ci SANE_Int bytes_per_line; 875141cc406Sopenharmony_ci 876141cc406Sopenharmony_ci SANE_Int shading_width; 877141cc406Sopenharmony_ci SANE_Int shading_idx; 878141cc406Sopenharmony_ci 879141cc406Sopenharmony_ci struct Pieusb_Exposure_Time exptime = { 880141cc406Sopenharmony_ci 0x93, /* code 0x93 */ 881141cc406Sopenharmony_ci 3 * 2 * sizeof(SANE_Int), /* number of bytes in rest of structure */ 882141cc406Sopenharmony_ci { { 0x02, 100 }, { 0x04, 100 }, { 0x08, 100 } } 883141cc406Sopenharmony_ci }; 884141cc406Sopenharmony_ci 885141cc406Sopenharmony_ci struct Pieusb_Highlight_Shadow shadow = { 886141cc406Sopenharmony_ci 0x94, /* code 0x94 */ 887141cc406Sopenharmony_ci 3 * 2 * sizeof(SANE_Int), /* number of bytes in rest of structure */ 888141cc406Sopenharmony_ci { { 0x02, 100 }, { 0x04, 100 }, { 0x08, 100 } } 889141cc406Sopenharmony_ci }; 890141cc406Sopenharmony_ci 891141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_start()\n"); 892141cc406Sopenharmony_ci 893141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 894141cc406Sopenharmony_ci * 895141cc406Sopenharmony_ci * Exit if currently scanning 896141cc406Sopenharmony_ci * 897141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 898141cc406Sopenharmony_ci if (scanner->scanning) { 899141cc406Sopenharmony_ci DBG (DBG_error, "sane_start(): scanner is already scanning, exiting\n"); 900141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 901141cc406Sopenharmony_ci } 902141cc406Sopenharmony_ci 903141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 904141cc406Sopenharmony_ci * 905141cc406Sopenharmony_ci * Exit with pause if not warmed up 906141cc406Sopenharmony_ci * 907141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 908141cc406Sopenharmony_ci 909141cc406Sopenharmony_ci sanei_pieusb_cmd_read_state (scanner->device_number, &(scanner->state), &status); 910141cc406Sopenharmony_ci if (status.pieusb_status != PIEUSB_STATUS_GOOD) { 911141cc406Sopenharmony_ci if (status.pieusb_status == PIEUSB_STATUS_DEVICE_BUSY) 912141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; /* was: SANE_STATUS_WARMING_UP */ 913141cc406Sopenharmony_ci DBG (DBG_error, "sane_start(): warmed up check returns status: %s\n", sane_strstatus (sanei_pieusb_convert_status(status.pieusb_status))); 914141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 915141cc406Sopenharmony_ci } 916141cc406Sopenharmony_ci if (scanner->state.warmingUp) { 917141cc406Sopenharmony_ci DBG (DBG_error, "sane_start(): warming up, exiting\n"); 918141cc406Sopenharmony_ci /* Seen SANE_STATUS_WARMING_UP in scanimage => enabled */ 919141cc406Sopenharmony_ci sleep (10); /* scanimage does not pause, so do it here */ 920141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; /* was: SANE_STATUS_WARMING_UP */ 921141cc406Sopenharmony_ci } 922141cc406Sopenharmony_ci 923141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 924141cc406Sopenharmony_ci * set exposure time 925141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 926141cc406Sopenharmony_ci 927141cc406Sopenharmony_ci sanei_pieusb_cmd_set_exposure_time (scanner->device_number, &exptime, &status); 928141cc406Sopenharmony_ci if (status.pieusb_status != PIEUSB_STATUS_GOOD) { 929141cc406Sopenharmony_ci DBG (DBG_error, "sane_start(): sanei_pieusb_cmd_set_exposure_time failed: %d\n", status.pieusb_status); 930141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 931141cc406Sopenharmony_ci } 932141cc406Sopenharmony_ci 933141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 934141cc406Sopenharmony_ci * set highlight shadow 935141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 936141cc406Sopenharmony_ci 937141cc406Sopenharmony_ci sanei_pieusb_cmd_set_highlight_shadow (scanner->device_number, &shadow, &status); 938141cc406Sopenharmony_ci if (status.pieusb_status != PIEUSB_STATUS_GOOD) { 939141cc406Sopenharmony_ci DBG (DBG_error, "sane_start(): sanei_pieusb_cmd_set_highlight_shadow failed: %d\n", status.pieusb_status); 940141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 941141cc406Sopenharmony_ci } 942141cc406Sopenharmony_ci 943141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 944141cc406Sopenharmony_ci * get calibration info 945141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 946141cc406Sopenharmony_ci 947141cc406Sopenharmony_ci sanei_pieusb_cmd_get_shading_parms (scanner->device_number, scanner->device->shading_parameters, &status); 948141cc406Sopenharmony_ci if (status.pieusb_status != PIEUSB_STATUS_GOOD) { 949141cc406Sopenharmony_ci DBG (DBG_error, "sane_scan: sanei_pieusb_cmd_get_shading_parms failed: %d\n", status.pieusb_status); 950141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 951141cc406Sopenharmony_ci } 952141cc406Sopenharmony_ci shading_width = scanner->device->shading_parameters[0].pixelsPerLine; 953141cc406Sopenharmony_ci DBG (DBG_info, "shading_width %d\n", shading_width); 954141cc406Sopenharmony_ci for (shading_idx = 0; shading_idx < SHADING_PARAMETERS_INFO_COUNT; shading_idx++) { 955141cc406Sopenharmony_ci scanner->shading_ref[shading_idx] = 956141cc406Sopenharmony_ci realloc(scanner->shading_ref[shading_idx], 2 * shading_width * sizeof(SANE_Int)); 957141cc406Sopenharmony_ci if (scanner->shading_ref[shading_idx] == NULL) { 958141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 959141cc406Sopenharmony_ci } 960141cc406Sopenharmony_ci } 961141cc406Sopenharmony_ci scanner->ccd_mask = realloc (scanner->ccd_mask, shading_width); 962141cc406Sopenharmony_ci scanner->ccd_mask_size = shading_width; 963141cc406Sopenharmony_ci if (scanner->ccd_mask == NULL) { 964141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 965141cc406Sopenharmony_ci } 966141cc406Sopenharmony_ci 967141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 968141cc406Sopenharmony_ci * 969141cc406Sopenharmony_ci * Standard run does; 970141cc406Sopenharmony_ci * - set exposure time 0x0A/0x13 971141cc406Sopenharmony_ci * - set highlight shadow 0x0A/0x14 972141cc406Sopenharmony_ci * - read shading parameters 0x0A/0x95/0x08 973141cc406Sopenharmony_ci * - set scan frame 0x0A/0x12 974141cc406Sopenharmony_ci * "12 00 0a00 80 00 0300 0000 b829 e31a" 975141cc406Sopenharmony_ci * => 0:12 1:0 2:10 4:80 5:0 6:3 8:0 10:10680 12:6883 976141cc406Sopenharmony_ci * - read gain offset 0xD7 977141cc406Sopenharmony_ci * - set gain offset 0xDC 978141cc406Sopenharmony_ci * - set mode 0x15 979141cc406Sopenharmony_ci * "00 0f 2c01 80 04 04 00 01 0a 00 00 00 80 10 00" 980141cc406Sopenharmony_ci * size res pass dpt frm ord bitmap ptn thr 981141cc406Sopenharmony_ci * 15 300 RGB 8 inx intel 1=sharpen 0 128 982141cc406Sopenharmony_ci * 3=skipshad 983141cc406Sopenharmony_ci * 984141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 985141cc406Sopenharmony_ci 986141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 987141cc406Sopenharmony_ci * 988141cc406Sopenharmony_ci * Show and check options 989141cc406Sopenharmony_ci * 990141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 991141cc406Sopenharmony_ci sanei_pieusb_print_options (scanner); 992141cc406Sopenharmony_ci if (!sanei_pieusb_analyse_options (scanner)) { 993141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 994141cc406Sopenharmony_ci } 995141cc406Sopenharmony_ci 996141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 997141cc406Sopenharmony_ci * 998141cc406Sopenharmony_ci * Set scan frame 999141cc406Sopenharmony_ci * 1000141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 1001141cc406Sopenharmony_ci if (sanei_pieusb_set_frame_from_options (scanner) != SANE_STATUS_GOOD) { 1002141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1003141cc406Sopenharmony_ci } 1004141cc406Sopenharmony_ci 1005141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 1006141cc406Sopenharmony_ci * 1007141cc406Sopenharmony_ci * Function 17 1008141cc406Sopenharmony_ci * This function is not supported by all scanners which are capable of 1009141cc406Sopenharmony_ci * slide transport, therefore FLAG_CMD_17_NOSUPPORT was introduced. 1010141cc406Sopenharmony_ci * 1011141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 1012141cc406Sopenharmony_ci 1013141cc406Sopenharmony_ci if ( (scanner->device->flags & FLAG_SLIDE_TRANSPORT) & !(scanner->device->flags & FLAG_CMD_17_NOSUPPORT) ) { 1014141cc406Sopenharmony_ci sanei_pieusb_cmd_17 (scanner->device_number, 1, &status); 1015141cc406Sopenharmony_ci if (status.pieusb_status != PIEUSB_STATUS_GOOD) { 1016141cc406Sopenharmony_ci DBG (DBG_error, "sane_start(): sanei_pieusb_cmd_17 failed: %d\n", status.pieusb_status); 1017141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1018141cc406Sopenharmony_ci } 1019141cc406Sopenharmony_ci st = sanei_pieusb_wait_ready (scanner, 0); 1020141cc406Sopenharmony_ci if (st != SANE_STATUS_GOOD) { 1021141cc406Sopenharmony_ci DBG (DBG_error, "sane_start(): scanner not ready after sanei_pieusb_cmd_17: %d\n", st); 1022141cc406Sopenharmony_ci return st; 1023141cc406Sopenharmony_ci } 1024141cc406Sopenharmony_ci } 1025141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 1026141cc406Sopenharmony_ci * 1027141cc406Sopenharmony_ci * Get & set initial gains and offsets 1028141cc406Sopenharmony_ci * 1029141cc406Sopenharmony_ci * There does not seem to be much reason to set exposure/gain/offset 1030141cc406Sopenharmony_ci * now, but it does make a large difference in speed, because it 1031141cc406Sopenharmony_ci * creates a small BADF-table. This is probably because without SET GAIN 1032141cc406Sopenharmony_ci * OFFSET, extraEntries has a random value (it is not initialised). 1033141cc406Sopenharmony_ci * 1034141cc406Sopenharmony_ci * TODO: test if this may be done just once, in sane_open(). 1035141cc406Sopenharmony_ci * 1036141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 1037141cc406Sopenharmony_ci 1038141cc406Sopenharmony_ci if (sanei_pieusb_set_gain_offset (scanner, scanner->val[OPT_CALIBRATION_MODE].s) != SANE_STATUS_GOOD) { 1039141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1040141cc406Sopenharmony_ci } 1041141cc406Sopenharmony_ci 1042141cc406Sopenharmony_ci st = sanei_pieusb_wait_ready (scanner, 0); 1043141cc406Sopenharmony_ci if (st != SANE_STATUS_GOOD) { 1044141cc406Sopenharmony_ci DBG (DBG_error, "sane_start: scanner not ready %d\n", st); 1045141cc406Sopenharmony_ci return st; 1046141cc406Sopenharmony_ci } 1047141cc406Sopenharmony_ci 1048141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 1049141cc406Sopenharmony_ci * 1050141cc406Sopenharmony_ci * Set mode 1051141cc406Sopenharmony_ci * 1052141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 1053141cc406Sopenharmony_ci if (sanei_pieusb_set_mode_from_options (scanner) != SANE_STATUS_GOOD) { 1054141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1055141cc406Sopenharmony_ci } 1056141cc406Sopenharmony_ci 1057141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 1058141cc406Sopenharmony_ci * 1059141cc406Sopenharmony_ci * Init slide transport 1060141cc406Sopenharmony_ci * 1061141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 1062141cc406Sopenharmony_ci if (scanner->device->flags & FLAG_SLIDE_TRANSPORT) { 1063141cc406Sopenharmony_ci sanei_pieusb_cmd_slide (scanner->device_number, SLIDE_INIT, &status); 1064141cc406Sopenharmony_ci if (status.pieusb_status != PIEUSB_STATUS_GOOD) { 1065141cc406Sopenharmony_ci DBG (DBG_error, "sane_start(): sanei_pieusb_cmd_slide failed: %d\n", status.pieusb_status); 1066141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1067141cc406Sopenharmony_ci } 1068141cc406Sopenharmony_ci st = sanei_pieusb_wait_ready (scanner, 0); 1069141cc406Sopenharmony_ci if (st != SANE_STATUS_GOOD) { 1070141cc406Sopenharmony_ci DBG (DBG_error, "sane_start: scanner not ready %d\n", st); 1071141cc406Sopenharmony_ci return st; 1072141cc406Sopenharmony_ci } 1073141cc406Sopenharmony_ci } 1074141cc406Sopenharmony_ci /* Enter SCAN phase 1 */ 1075141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_start(): scan phase 1\n"); 1076141cc406Sopenharmony_ci 1077141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 1078141cc406Sopenharmony_ci * 1079141cc406Sopenharmony_ci * Start scan & wait until device ready 1080141cc406Sopenharmony_ci * 1081141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 1082141cc406Sopenharmony_ci scanner->scanning = SANE_TRUE; 1083141cc406Sopenharmony_ci scanner->cancel_request = SANE_FALSE; 1084141cc406Sopenharmony_ci for (;;) { 1085141cc406Sopenharmony_ci sanei_pieusb_cmd_start_scan (scanner->device_number, &status); 1086141cc406Sopenharmony_ci if (status.pieusb_status != PIEUSB_STATUS_WARMING_UP) 1087141cc406Sopenharmony_ci break; 1088141cc406Sopenharmony_ci sleep(5); 1089141cc406Sopenharmony_ci } 1090141cc406Sopenharmony_ci sanei_pieusb_wait_ready (scanner, 0); 1091141cc406Sopenharmony_ci if ((status.pieusb_status == PIEUSB_STATUS_MUST_CALIBRATE) 1092141cc406Sopenharmony_ci || (scanner->val[OPT_SHADING_ANALYSIS].b != 0)) { 1093141cc406Sopenharmony_ci 1094141cc406Sopenharmony_ci /* Overriding skip calibration */ 1095141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_start(): process shading data\n"); 1096141cc406Sopenharmony_ci 1097141cc406Sopenharmony_ci /* ------------------------------------------------------------------ 1098141cc406Sopenharmony_ci * 1099141cc406Sopenharmony_ci * Get and set gain and offset 1100141cc406Sopenharmony_ci * Get settings from scanner, from preview data, from options, 1101141cc406Sopenharmony_ci * or use defaults. 1102141cc406Sopenharmony_ci * 1103141cc406Sopenharmony_ci * ------------------------------------------------------------------ */ 1104141cc406Sopenharmony_ci if (sanei_pieusb_set_gain_offset (scanner, scanner->val[OPT_CALIBRATION_MODE].s) != SANE_STATUS_GOOD) { 1105141cc406Sopenharmony_ci sanei_pieusb_cmd_stop_scan (scanner->device_number, &status); 1106141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 1107141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1108141cc406Sopenharmony_ci } 1109141cc406Sopenharmony_ci /* ------------------------------------------------------------------ 1110141cc406Sopenharmony_ci * 1111141cc406Sopenharmony_ci * Obtain shading data 1112141cc406Sopenharmony_ci * Get parameters from scanner->device->shading_parameters[0] although 1113141cc406Sopenharmony_ci * it's 45 lines, scanner->ccd_mask_size pixels, 16 bit depth in all cases. 1114141cc406Sopenharmony_ci * 1115141cc406Sopenharmony_ci * ------------------------------------------------------------------ */ 1116141cc406Sopenharmony_ci if (sanei_pieusb_get_shading_data (scanner) != SANE_STATUS_GOOD) { 1117141cc406Sopenharmony_ci sanei_pieusb_cmd_stop_scan (scanner->device_number, &status); 1118141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 1119141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1120141cc406Sopenharmony_ci } 1121141cc406Sopenharmony_ci } 1122141cc406Sopenharmony_ci 1123141cc406Sopenharmony_ci /* Enter SCAN phase 2 */ 1124141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_start(): scan phase 2\n"); 1125141cc406Sopenharmony_ci 1126141cc406Sopenharmony_ci /* SCAN phase 2 (line-by-line scan) not implemented */ 1127141cc406Sopenharmony_ci 1128141cc406Sopenharmony_ci st = sanei_pieusb_wait_ready (scanner, 0); 1129141cc406Sopenharmony_ci if (st != SANE_STATUS_GOOD) { 1130141cc406Sopenharmony_ci DBG (DBG_error, "sane_start: scanner not ready %d\n", st); 1131141cc406Sopenharmony_ci return st; 1132141cc406Sopenharmony_ci } 1133141cc406Sopenharmony_ci 1134141cc406Sopenharmony_ci /* Enter SCAN phase 3 */ 1135141cc406Sopenharmony_ci 1136141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_start(): scan phase 3\n"); 1137141cc406Sopenharmony_ci 1138141cc406Sopenharmony_ci /* Handle cancel request */ 1139141cc406Sopenharmony_ci if (scanner->cancel_request) { 1140141cc406Sopenharmony_ci return sanei_pieusb_on_cancel (scanner); 1141141cc406Sopenharmony_ci } 1142141cc406Sopenharmony_ci 1143141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 1144141cc406Sopenharmony_ci * 1145141cc406Sopenharmony_ci * Get CCD mask 1146141cc406Sopenharmony_ci * 1147141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 1148141cc406Sopenharmony_ci 1149141cc406Sopenharmony_ci if (sanei_pieusb_get_ccd_mask (scanner) != SANE_STATUS_GOOD) { 1150141cc406Sopenharmony_ci sanei_pieusb_cmd_stop_scan (scanner->device_number, &status); 1151141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 1152141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1153141cc406Sopenharmony_ci } 1154141cc406Sopenharmony_ci 1155141cc406Sopenharmony_ci /* Enter SCAN phase 4 */ 1156141cc406Sopenharmony_ci 1157141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 1158141cc406Sopenharmony_ci * 1159141cc406Sopenharmony_ci * Read scan parameters & wait until ready for reading 1160141cc406Sopenharmony_ci * 1161141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 1162141cc406Sopenharmony_ci if (sanei_pieusb_get_parameters (scanner, &bytes_per_line) != SANE_STATUS_GOOD) { 1163141cc406Sopenharmony_ci sanei_pieusb_cmd_stop_scan (scanner->device_number, &status); 1164141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 1165141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1166141cc406Sopenharmony_ci } 1167141cc406Sopenharmony_ci 1168141cc406Sopenharmony_ci st = sanei_pieusb_wait_ready (scanner, 0); 1169141cc406Sopenharmony_ci if (st != SANE_STATUS_GOOD) { 1170141cc406Sopenharmony_ci DBG (DBG_error, "sane_start: scanner not ready %d\n", st); 1171141cc406Sopenharmony_ci return st; 1172141cc406Sopenharmony_ci } 1173141cc406Sopenharmony_ci 1174141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 1175141cc406Sopenharmony_ci * 1176141cc406Sopenharmony_ci * Prepare read buffer 1177141cc406Sopenharmony_ci * Currently this buffer is always a memory mapped buffer 1178141cc406Sopenharmony_ci * Might be faster to use RAM buffers for small images (such as preview) 1179141cc406Sopenharmony_ci * 1180141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 1181141cc406Sopenharmony_ci colors = 0x00; 1182141cc406Sopenharmony_ci switch (scanner->mode.passes) { 1183141cc406Sopenharmony_ci case SCAN_FILTER_RED: colors = 0x01; break; 1184141cc406Sopenharmony_ci case SCAN_FILTER_GREEN: colors = 0x02; break; 1185141cc406Sopenharmony_ci case SCAN_FILTER_BLUE: colors = 0x04; break; 1186141cc406Sopenharmony_ci case SCAN_FILTER_INFRARED: colors = 0x08; break; 1187141cc406Sopenharmony_ci case SCAN_ONE_PASS_COLOR: colors = 0x07; break; 1188141cc406Sopenharmony_ci case SCAN_ONE_PASS_RGBI: colors = 0x0F; break; 1189141cc406Sopenharmony_ci } 1190141cc406Sopenharmony_ci if (scanner->buffer.data) sanei_pieusb_buffer_delete(&scanner->buffer); /* free resources from previous invocation */ 1191141cc406Sopenharmony_ci st = sanei_pieusb_buffer_create (&(scanner->buffer), scanner->scan_parameters.pixels_per_line, 1192141cc406Sopenharmony_ci scanner->scan_parameters.lines, colors, 1193141cc406Sopenharmony_ci scanner->scan_parameters.depth); 1194141cc406Sopenharmony_ci if (st != SANE_STATUS_GOOD) { 1195141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 1196141cc406Sopenharmony_ci return st; 1197141cc406Sopenharmony_ci } 1198141cc406Sopenharmony_ci 1199141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 1200141cc406Sopenharmony_ci * 1201141cc406Sopenharmony_ci * Read all image data into the buffer 1202141cc406Sopenharmony_ci * 1203141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 1204141cc406Sopenharmony_ci if (sanei_pieusb_get_scan_data (scanner, bytes_per_line) != SANE_STATUS_GOOD) { 1205141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 1206141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1207141cc406Sopenharmony_ci } 1208141cc406Sopenharmony_ci sleep(2); 1209141cc406Sopenharmony_ci st = sanei_pieusb_wait_ready (scanner, 0); 1210141cc406Sopenharmony_ci if (st != SANE_STATUS_GOOD) { 1211141cc406Sopenharmony_ci DBG (DBG_error, "sane_start(): scanner not ready after sanei_pieusb_get_scan_data: %d\n", st); 1212141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 1213141cc406Sopenharmony_ci return st; 1214141cc406Sopenharmony_ci } 1215141cc406Sopenharmony_ci 1216141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 1217141cc406Sopenharmony_ci * 1218141cc406Sopenharmony_ci * Advance to next slide (except for preview) 1219141cc406Sopenharmony_ci * 1220141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 1221141cc406Sopenharmony_ci 1222141cc406Sopenharmony_ci if (scanner->device->flags & FLAG_SLIDE_TRANSPORT) { 1223141cc406Sopenharmony_ci if (scanner->val[OPT_ADVANCE_SLIDE].b && !scanner->val[OPT_PREVIEW].b) { 1224141cc406Sopenharmony_ci sanei_pieusb_cmd_slide (scanner->device_number, SLIDE_NEXT, &status); 1225141cc406Sopenharmony_ci if (status.pieusb_status != PIEUSB_STATUS_GOOD) { 1226141cc406Sopenharmony_ci DBG (DBG_error, "sane_start(): sanei_pieusb_cmd_slide failed: %d\n", status.pieusb_status); 1227141cc406Sopenharmony_ci } 1228141cc406Sopenharmony_ci } 1229141cc406Sopenharmony_ci } 1230141cc406Sopenharmony_ci 1231141cc406Sopenharmony_ci /* ---------------------------------------------------------------------- 1232141cc406Sopenharmony_ci * 1233141cc406Sopenharmony_ci * Post processing: 1234141cc406Sopenharmony_ci * 1. Correct for shading 1235141cc406Sopenharmony_ci * 2. Remove R-component from IR data 1236141cc406Sopenharmony_ci * 3. Remove dust 1237141cc406Sopenharmony_ci * 1238141cc406Sopenharmony_ci * ---------------------------------------------------------------------- */ 1239141cc406Sopenharmony_ci 1240141cc406Sopenharmony_ci mode = scanner->val[OPT_MODE].s; 1241141cc406Sopenharmony_ci if (strcmp(mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) { 1242141cc406Sopenharmony_ci shading_correction_relevant = SANE_FALSE; /* Shading correction irrelavant at bit depth 1 */ 1243141cc406Sopenharmony_ci infrared_post_processing_relevant = SANE_FALSE; /* No infrared, no postprocessing */ 1244141cc406Sopenharmony_ci } else if (strcmp(mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) { 1245141cc406Sopenharmony_ci shading_correction_relevant = SANE_FALSE; /* Shading correction irrelavant at bit depth 1 */ 1246141cc406Sopenharmony_ci infrared_post_processing_relevant = SANE_FALSE; /* No infrared, no postprocessing */ 1247141cc406Sopenharmony_ci } else if (strcmp(mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) { 1248141cc406Sopenharmony_ci shading_correction_relevant = SANE_TRUE; 1249141cc406Sopenharmony_ci infrared_post_processing_relevant = SANE_FALSE; /* No infrared, no postprocessing */ 1250141cc406Sopenharmony_ci } else if (scanner->val[OPT_PREVIEW].b) { 1251141cc406Sopenharmony_ci /* Catch preview here, otherwise next ifs get complicated */ 1252141cc406Sopenharmony_ci shading_correction_relevant = SANE_TRUE; 1253141cc406Sopenharmony_ci infrared_post_processing_relevant = SANE_FALSE; 1254141cc406Sopenharmony_ci } else if (strcmp(mode, SANE_VALUE_SCAN_MODE_RGBI) == 0) { 1255141cc406Sopenharmony_ci shading_correction_relevant = SANE_TRUE; 1256141cc406Sopenharmony_ci infrared_post_processing_relevant = SANE_TRUE; 1257141cc406Sopenharmony_ci } else if (strcmp(mode, SANE_VALUE_SCAN_MODE_COLOR) == 0 && scanner->val[OPT_CLEAN_IMAGE].b) { 1258141cc406Sopenharmony_ci shading_correction_relevant = SANE_TRUE; 1259141cc406Sopenharmony_ci infrared_post_processing_relevant = SANE_TRUE; 1260141cc406Sopenharmony_ci } else { /* SANE_VALUE_SCAN_MODE_COLOR */ 1261141cc406Sopenharmony_ci shading_correction_relevant = SANE_TRUE; 1262141cc406Sopenharmony_ci infrared_post_processing_relevant = SANE_TRUE; 1263141cc406Sopenharmony_ci } 1264141cc406Sopenharmony_ci if (scanner->val[OPT_CORRECT_SHADING].b && shading_correction_relevant) { 1265141cc406Sopenharmony_ci if (scanner->shading_data_present) { 1266141cc406Sopenharmony_ci sanei_pieusb_correct_shading (scanner, &scanner->buffer); 1267141cc406Sopenharmony_ci } else { 1268141cc406Sopenharmony_ci DBG(DBG_warning, "sane_start(): unable to correct for shading, no shading data available\n"); 1269141cc406Sopenharmony_ci } 1270141cc406Sopenharmony_ci } 1271141cc406Sopenharmony_ci if ((scanner->val[OPT_CORRECT_INFRARED].b || scanner->val[OPT_CLEAN_IMAGE].b) && !scanner->val[OPT_PREVIEW].b && infrared_post_processing_relevant) { 1272141cc406Sopenharmony_ci /* Create array of pointers to color planes R, G, B, I */ 1273141cc406Sopenharmony_ci SANE_Uint *planes[PLANES]; 1274141cc406Sopenharmony_ci SANE_Int N; 1275141cc406Sopenharmony_ci N = scanner->buffer.width * scanner->buffer.height; 1276141cc406Sopenharmony_ci planes[0] = scanner->buffer.data; 1277141cc406Sopenharmony_ci planes[1] = scanner->buffer.data + N; 1278141cc406Sopenharmony_ci planes[2] = scanner->buffer.data + 2 * N; 1279141cc406Sopenharmony_ci planes[3] = scanner->buffer.data + 3 * N; 1280141cc406Sopenharmony_ci sanei_ir_init (); 1281141cc406Sopenharmony_ci sanei_pieusb_post (scanner, planes, scanner->buffer.colors); 1282141cc406Sopenharmony_ci } 1283141cc406Sopenharmony_ci 1284141cc406Sopenharmony_ci /* Save preview data. Preview data only used once to set gain and offset. */ 1285141cc406Sopenharmony_ci if (scanner->val[OPT_PREVIEW].b) { 1286141cc406Sopenharmony_ci sanei_pieusb_analyze_preview(scanner); 1287141cc406Sopenharmony_ci } else { 1288141cc406Sopenharmony_ci scanner->preview_done = SANE_FALSE; 1289141cc406Sopenharmony_ci } 1290141cc406Sopenharmony_ci 1291141cc406Sopenharmony_ci /* Modify buffer in case the buffer has infrared, but no infrared should be returned */ 1292141cc406Sopenharmony_ci if (scanner->buffer.colors == PLANES && (strcmp(mode,SANE_VALUE_SCAN_MODE_COLOR) == 0 && scanner->val[OPT_CLEAN_IMAGE].b)) { 1293141cc406Sopenharmony_ci DBG(DBG_info_sane, "sane_start(): modifying buffer to ignore I\n"); 1294141cc406Sopenharmony_ci /* Base buffer parameters */ 1295141cc406Sopenharmony_ci scanner->buffer.colors = 3; 1296141cc406Sopenharmony_ci /* Derived quantities */ 1297141cc406Sopenharmony_ci scanner->buffer.image_size_bytes = scanner->buffer.colors * scanner->buffer.height * scanner->buffer.line_size_bytes; 1298141cc406Sopenharmony_ci scanner->buffer.color_index_infrared = -1; 1299141cc406Sopenharmony_ci scanner->buffer.bytes_unread = scanner->buffer.bytes_unread * 3 / 4; 1300141cc406Sopenharmony_ci scanner->buffer.bytes_written = scanner->buffer.bytes_written * 3 / 4; 1301141cc406Sopenharmony_ci } 1302141cc406Sopenharmony_ci 1303141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1304141cc406Sopenharmony_ci 1305141cc406Sopenharmony_ci} 1306141cc406Sopenharmony_ci 1307141cc406Sopenharmony_ci/** 1308141cc406Sopenharmony_ci * Read image data from the scanner buffer. 1309141cc406Sopenharmony_ci * 1310141cc406Sopenharmony_ci * @param handle 1311141cc406Sopenharmony_ci * @param buf 1312141cc406Sopenharmony_ci * @param max_len 1313141cc406Sopenharmony_ci * @param len 1314141cc406Sopenharmony_ci * @return 1315141cc406Sopenharmony_ci */ 1316141cc406Sopenharmony_ciSANE_Status 1317141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) 1318141cc406Sopenharmony_ci{ 1319141cc406Sopenharmony_ci 1320141cc406Sopenharmony_ci struct Pieusb_Scanner *scanner = handle; 1321141cc406Sopenharmony_ci SANE_Int return_size; 1322141cc406Sopenharmony_ci 1323141cc406Sopenharmony_ci DBG(DBG_info_sane, "sane_read(): requested %d bytes\n", max_len); 1324141cc406Sopenharmony_ci 1325141cc406Sopenharmony_ci /* No reading if not scanning */ 1326141cc406Sopenharmony_ci if (!scanner->scanning) { 1327141cc406Sopenharmony_ci *len = 0; 1328141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; /* SANE standard does not allow a SANE_STATUS_INVAL return */ 1329141cc406Sopenharmony_ci } 1330141cc406Sopenharmony_ci 1331141cc406Sopenharmony_ci /* Handle cancel request */ 1332141cc406Sopenharmony_ci if (scanner->cancel_request) { 1333141cc406Sopenharmony_ci return sanei_pieusb_on_cancel(scanner); 1334141cc406Sopenharmony_ci } 1335141cc406Sopenharmony_ci#if 0 1336141cc406Sopenharmony_ci /* Return image data, just read from scanner buffer */ 1337141cc406Sopenharmony_ci DBG(DBG_info_sane, "sane_read():\n"); 1338141cc406Sopenharmony_ci DBG(DBG_info_sane, " image size %d\n", scanner->buffer.image_size_bytes); 1339141cc406Sopenharmony_ci DBG(DBG_info_sane, " unread %d\n", scanner->buffer.bytes_unread); 1340141cc406Sopenharmony_ci DBG(DBG_info_sane, " read %d\n", scanner->buffer.bytes_read); 1341141cc406Sopenharmony_ci DBG(DBG_info_sane, " max_len %d\n", max_len); 1342141cc406Sopenharmony_ci#endif 1343141cc406Sopenharmony_ci if (scanner->buffer.bytes_read > scanner->buffer.image_size_bytes) { 1344141cc406Sopenharmony_ci /* Test if not reading past buffer boundaries */ 1345141cc406Sopenharmony_ci DBG(DBG_error, "sane_read(): reading past buffer boundaries (contains %d, read %d)\n", scanner->buffer.image_size_bytes, scanner->buffer.bytes_read); 1346141cc406Sopenharmony_ci *len = 0; 1347141cc406Sopenharmony_ci sanei_pieusb_on_cancel(scanner); 1348141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1349141cc406Sopenharmony_ci } else if (scanner->buffer.bytes_read == scanner->buffer.image_size_bytes) { 1350141cc406Sopenharmony_ci /* Return EOF since all data of this frame has already been read. */ 1351141cc406Sopenharmony_ci *len = 0; 1352141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 1353141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1354141cc406Sopenharmony_ci } else if (scanner->buffer.bytes_unread >= max_len) { 1355141cc406Sopenharmony_ci /* Already enough data to return, do not read */ 1356141cc406Sopenharmony_ci DBG(DBG_info_sane, "sane_read(): buffer suffices (contains %d, requested %d)\n", scanner->buffer.bytes_unread, max_len); 1357141cc406Sopenharmony_ci return_size = max_len; 1358141cc406Sopenharmony_ci } else if (scanner->buffer.bytes_read + scanner->buffer.bytes_unread == scanner->buffer.image_size_bytes) { 1359141cc406Sopenharmony_ci /* All the remaining data is in the buffer, do not read */ 1360141cc406Sopenharmony_ci DBG(DBG_info_sane, "sane_read(): buffer suffices (contains %d, requested %d, last batch though)\n", scanner->buffer.bytes_unread, max_len); 1361141cc406Sopenharmony_ci return_size = scanner->buffer.bytes_unread; 1362141cc406Sopenharmony_ci } else { 1363141cc406Sopenharmony_ci /* Should not happen in this implementation - all data read by sane_start() */ 1364141cc406Sopenharmony_ci DBG(DBG_error, "sane_read(): shouldn't be here...\n"); 1365141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1366141cc406Sopenharmony_ci } 1367141cc406Sopenharmony_ci 1368141cc406Sopenharmony_ci /* Check */ 1369141cc406Sopenharmony_ci if (return_size == 0 && scanner->buffer.bytes_read < scanner->buffer.image_size_bytes) { 1370141cc406Sopenharmony_ci DBG(DBG_error, "sane_read(): unable to service read request, %d bytes in frame, %d read\n", scanner->buffer.image_size_bytes, scanner->buffer.bytes_read); 1371141cc406Sopenharmony_ci } 1372141cc406Sopenharmony_ci 1373141cc406Sopenharmony_ci /* Return the available data: Output return_size bytes from buffer */ 1374141cc406Sopenharmony_ci sanei_pieusb_buffer_get(&scanner->buffer, buf, max_len, len); 1375141cc406Sopenharmony_ci#if 0 1376141cc406Sopenharmony_ci DBG(DBG_info_sane, "sane_read(): currently read %.2f lines of %d\n", 1377141cc406Sopenharmony_ci (double)scanner->buffer.bytes_written/(scanner->buffer.line_size_bytes*scanner->buffer.colors), 1378141cc406Sopenharmony_ci scanner->buffer.height); 1379141cc406Sopenharmony_ci DBG(DBG_info_sane, "sane_read(): returning %d bytes (requested %d), returned %d of %d \n", 1380141cc406Sopenharmony_ci *len, max_len,scanner->buffer.bytes_read, scanner->buffer.image_size_bytes); 1381141cc406Sopenharmony_ci#endif 1382141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1383141cc406Sopenharmony_ci 1384141cc406Sopenharmony_ci} 1385141cc406Sopenharmony_ci 1386141cc406Sopenharmony_ci/** 1387141cc406Sopenharmony_ci * Request cancellation of current scanning process. 1388141cc406Sopenharmony_ci * 1389141cc406Sopenharmony_ci * @param handle Scanner handle 1390141cc406Sopenharmony_ci */ 1391141cc406Sopenharmony_civoid 1392141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 1393141cc406Sopenharmony_ci{ 1394141cc406Sopenharmony_ci struct Pieusb_Scanner *scanner = handle; 1395141cc406Sopenharmony_ci 1396141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_cancel\n"); 1397141cc406Sopenharmony_ci 1398141cc406Sopenharmony_ci if (scanner->scanning) { 1399141cc406Sopenharmony_ci scanner->cancel_request = 1; 1400141cc406Sopenharmony_ci } 1401141cc406Sopenharmony_ci} 1402141cc406Sopenharmony_ci 1403141cc406Sopenharmony_ci/** 1404141cc406Sopenharmony_ci * Set the I/O mode of handle h. The I/O mode can be either blocking or 1405141cc406Sopenharmony_ci * non-blocking, but for USB devices, only blocking mode is supported. 1406141cc406Sopenharmony_ci * 1407141cc406Sopenharmony_ci * @param handle Scanner handle 1408141cc406Sopenharmony_ci * @param non_blocking 1409141cc406Sopenharmony_ci * @return SANE_STATUS_UNSUPPORTED; 1410141cc406Sopenharmony_ci */ 1411141cc406Sopenharmony_ciSANE_Status 1412141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 1413141cc406Sopenharmony_ci{ 1414141cc406Sopenharmony_ci /* Pieusb_Scanner *scanner = handle; */ 1415141cc406Sopenharmony_ci 1416141cc406Sopenharmony_ci DBG (DBG_info_sane, "sane_set_io_mode: handle = %p, non_blocking = %s\n", handle, non_blocking == SANE_TRUE ? "true" : "false"); 1417141cc406Sopenharmony_ci 1418141cc406Sopenharmony_ci if (non_blocking) { 1419141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1420141cc406Sopenharmony_ci } 1421141cc406Sopenharmony_ci 1422141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1423141cc406Sopenharmony_ci} 1424141cc406Sopenharmony_ci 1425141cc406Sopenharmony_ci/** 1426141cc406Sopenharmony_ci * Obtain a file-descriptor for the scanner that is readable if image data is 1427141cc406Sopenharmony_ci * available. The select file-descriptor is returned in *fd. 1428141cc406Sopenharmony_ci * The function has not been implemented since USB-device only operate in 1429141cc406Sopenharmony_ci * blocking mode. 1430141cc406Sopenharmony_ci * 1431141cc406Sopenharmony_ci * @param handle Scanner handle 1432141cc406Sopenharmony_ci * @param fd File descriptor with imae data 1433141cc406Sopenharmony_ci * @return SANE_STATUS_INVAL 1434141cc406Sopenharmony_ci */ 1435141cc406Sopenharmony_ciSANE_Status 1436141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd) 1437141cc406Sopenharmony_ci{ 1438141cc406Sopenharmony_ci DBG(DBG_info_sane,"sane_get_select_fd(): not supported (only for non-blocking IO)\n"); 1439141cc406Sopenharmony_ci (void) handle; 1440141cc406Sopenharmony_ci (void) fd; 1441141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1442141cc406Sopenharmony_ci} 1443