1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci BACKEND canon_lide70 4141cc406Sopenharmony_ci 5141cc406Sopenharmony_ci Copyright (C) 2019 Juergen Ernst and pimvantend. 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 This file implements a SANE backend for the Canon CanoScan LiDE 70 and 600 */ 23141cc406Sopenharmony_ci 24141cc406Sopenharmony_ci#define BUILD 0 25141cc406Sopenharmony_ci#define MM_IN_INCH 25.4 26141cc406Sopenharmony_ci 27141cc406Sopenharmony_ci#include "../include/sane/config.h" 28141cc406Sopenharmony_ci 29141cc406Sopenharmony_ci#include <stdlib.h> 30141cc406Sopenharmony_ci#include <string.h> 31141cc406Sopenharmony_ci#include <stdio.h> 32141cc406Sopenharmony_ci#include <unistd.h> 33141cc406Sopenharmony_ci#include <fcntl.h> 34141cc406Sopenharmony_ci#include <sys/ioctl.h> 35141cc406Sopenharmony_ci 36141cc406Sopenharmony_ci#include "../include/sane/sane.h" 37141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 38141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 39141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 40141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h" 41141cc406Sopenharmony_ci#define BACKEND_NAME canon_lide70 42141cc406Sopenharmony_ci#define CANONUSB_CONFIG_FILE "canon_lide70.conf" 43141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 44141cc406Sopenharmony_ci 45141cc406Sopenharmony_citypedef enum 46141cc406Sopenharmony_ci{ 47141cc406Sopenharmony_ci opt_num_opts = 0, 48141cc406Sopenharmony_ci opt_mode_group, 49141cc406Sopenharmony_ci opt_threshold, 50141cc406Sopenharmony_ci opt_mode, 51141cc406Sopenharmony_ci opt_resolution, 52141cc406Sopenharmony_ci opt_non_blocking, 53141cc406Sopenharmony_ci opt_geometry_group, 54141cc406Sopenharmony_ci opt_tl_x, 55141cc406Sopenharmony_ci opt_tl_y, 56141cc406Sopenharmony_ci opt_br_x, 57141cc406Sopenharmony_ci opt_br_y, 58141cc406Sopenharmony_ci /* must come last: */ 59141cc406Sopenharmony_ci num_options 60141cc406Sopenharmony_ci} 61141cc406Sopenharmony_cicanon_opts; 62141cc406Sopenharmony_ci 63141cc406Sopenharmony_ci#include "canon_lide70-common.c" 64141cc406Sopenharmony_ci 65141cc406Sopenharmony_cistatic size_t 66141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[]) 67141cc406Sopenharmony_ci{ 68141cc406Sopenharmony_ci size_t size, max_size = 0; 69141cc406Sopenharmony_ci SANE_Int i; 70141cc406Sopenharmony_ci 71141cc406Sopenharmony_ci for (i = 0; strings[i]; ++i) 72141cc406Sopenharmony_ci { 73141cc406Sopenharmony_ci size = strlen (strings[i]) + 1; 74141cc406Sopenharmony_ci if (size > max_size) 75141cc406Sopenharmony_ci max_size = size; 76141cc406Sopenharmony_ci } 77141cc406Sopenharmony_ci return max_size; 78141cc406Sopenharmony_ci} 79141cc406Sopenharmony_ci 80141cc406Sopenharmony_cistatic SANE_String_Const mode_list[] = { 81141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_COLOR, 82141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_GRAY, 83141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_LINEART, 84141cc406Sopenharmony_ci 0 85141cc406Sopenharmony_ci}; 86141cc406Sopenharmony_ci 87141cc406Sopenharmony_cistatic SANE_Fixed init_tl_x = SANE_FIX (0.0); 88141cc406Sopenharmony_cistatic SANE_Fixed init_tl_y = SANE_FIX (0.0); 89141cc406Sopenharmony_cistatic SANE_Fixed init_br_x = SANE_FIX (80.0); 90141cc406Sopenharmony_cistatic SANE_Fixed init_br_y = SANE_FIX (100.0); 91141cc406Sopenharmony_cistatic SANE_Int init_threshold = 75; 92141cc406Sopenharmony_cistatic SANE_Int init_resolution = 600; 93141cc406Sopenharmony_cistatic SANE_String init_mode = SANE_VALUE_SCAN_MODE_COLOR; 94141cc406Sopenharmony_cistatic SANE_Int init_graymode = 0; 95141cc406Sopenharmony_cistatic SANE_Bool init_non_blocking = SANE_FALSE; 96141cc406Sopenharmony_ci 97141cc406Sopenharmony_ci/*-----------------------------------------------------------------*/ 98141cc406Sopenharmony_ci/* 99141cc406Sopenharmony_ciScan range 100141cc406Sopenharmony_ci*/ 101141cc406Sopenharmony_ci 102141cc406Sopenharmony_cistatic const SANE_Range widthRange = { 103141cc406Sopenharmony_ci 0, /* minimum */ 104141cc406Sopenharmony_ci SANE_FIX (CANON_MAX_WIDTH * MM_IN_INCH / 600), /* maximum */ 105141cc406Sopenharmony_ci 0 /* quantization */ 106141cc406Sopenharmony_ci}; 107141cc406Sopenharmony_ci 108141cc406Sopenharmony_cistatic const SANE_Range heightRange = { 109141cc406Sopenharmony_ci 0, /* minimum */ 110141cc406Sopenharmony_ci/* SANE_FIX (CANON_MAX_HEIGHT * MM_IN_INCH / 600 - TOP_EDGE ), maximum */ 111141cc406Sopenharmony_ci SANE_FIX (297.0), 112141cc406Sopenharmony_ci 0 /* quantization */ 113141cc406Sopenharmony_ci}; 114141cc406Sopenharmony_ci 115141cc406Sopenharmony_cistatic const SANE_Range threshold_range = { 116141cc406Sopenharmony_ci 0, 117141cc406Sopenharmony_ci 100, 118141cc406Sopenharmony_ci 1 119141cc406Sopenharmony_ci}; 120141cc406Sopenharmony_ci 121141cc406Sopenharmony_cistatic SANE_Int resolution_list[] = { 5, 122141cc406Sopenharmony_ci 75, 123141cc406Sopenharmony_ci 150, 124141cc406Sopenharmony_ci 300, 125141cc406Sopenharmony_ci 600, 126141cc406Sopenharmony_ci 1200 127141cc406Sopenharmony_ci}; 128141cc406Sopenharmony_ci 129141cc406Sopenharmony_citypedef struct Canon_Device 130141cc406Sopenharmony_ci{ 131141cc406Sopenharmony_ci struct Canon_Device *next; 132141cc406Sopenharmony_ci SANE_String name; 133141cc406Sopenharmony_ci SANE_Device sane; 134141cc406Sopenharmony_ci} 135141cc406Sopenharmony_ciCanon_Device; 136141cc406Sopenharmony_ci 137141cc406Sopenharmony_ci/* Canon_Scanner is the type used for the sane handle */ 138141cc406Sopenharmony_citypedef struct Canon_Scanner 139141cc406Sopenharmony_ci{ 140141cc406Sopenharmony_ci struct Canon_Scanner *next; 141141cc406Sopenharmony_ci Canon_Device *device; 142141cc406Sopenharmony_ci CANON_Handle scan; 143141cc406Sopenharmony_ci} 144141cc406Sopenharmony_ciCanon_Scanner; 145141cc406Sopenharmony_ci 146141cc406Sopenharmony_cistatic int num_devices = 0; 147141cc406Sopenharmony_cistatic const SANE_Device **devlist = NULL; 148141cc406Sopenharmony_cistatic Canon_Device *first_dev = NULL; 149141cc406Sopenharmony_cistatic Canon_Scanner *first_handle = NULL; 150141cc406Sopenharmony_ci 151141cc406Sopenharmony_ci/*-----------------------------------------------------------------*/ 152141cc406Sopenharmony_cistatic SANE_Status 153141cc406Sopenharmony_ciattach_scanner (const char *devicename, Canon_Device ** devp) 154141cc406Sopenharmony_ci{ 155141cc406Sopenharmony_ci CANON_Handle scan; 156141cc406Sopenharmony_ci Canon_Device *dev; 157141cc406Sopenharmony_ci SANE_Status status; 158141cc406Sopenharmony_ci 159141cc406Sopenharmony_ci DBG (3, "attach_scanner: %s\n", devicename); 160141cc406Sopenharmony_ci 161141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 162141cc406Sopenharmony_ci { 163141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) 164141cc406Sopenharmony_ci { 165141cc406Sopenharmony_ci if (devp) 166141cc406Sopenharmony_ci *devp = dev; 167141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 168141cc406Sopenharmony_ci } 169141cc406Sopenharmony_ci } 170141cc406Sopenharmony_ci 171141cc406Sopenharmony_ci dev = malloc (sizeof (*dev)); 172141cc406Sopenharmony_ci if (!dev) 173141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 174141cc406Sopenharmony_ci memset (dev, '\0', sizeof (Canon_Device)); /* clear structure */ 175141cc406Sopenharmony_ci 176141cc406Sopenharmony_ci DBG (4, "attach_scanner: opening %s\n", devicename); 177141cc406Sopenharmony_ci 178141cc406Sopenharmony_ci status = CANON_open_device (&scan, devicename); 179141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 180141cc406Sopenharmony_ci { 181141cc406Sopenharmony_ci DBG (1, "ERROR: attach_scanner: opening %s failed\n", devicename); 182141cc406Sopenharmony_ci free (dev); 183141cc406Sopenharmony_ci return status; 184141cc406Sopenharmony_ci } 185141cc406Sopenharmony_ci dev->name = strdup (devicename); 186141cc406Sopenharmony_ci dev->sane.name = dev->name; 187141cc406Sopenharmony_ci dev->sane.vendor = "CANON"; 188141cc406Sopenharmony_ci dev->sane.model = CANON_get_device_name (&scan); 189141cc406Sopenharmony_ci dev->sane.type = "flatbed scanner"; 190141cc406Sopenharmony_ci CANON_close_device (&scan); 191141cc406Sopenharmony_ci 192141cc406Sopenharmony_ci ++num_devices; 193141cc406Sopenharmony_ci dev->next = first_dev; 194141cc406Sopenharmony_ci first_dev = dev; 195141cc406Sopenharmony_ci 196141cc406Sopenharmony_ci if (devp) 197141cc406Sopenharmony_ci *devp = dev; 198141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 199141cc406Sopenharmony_ci} 200141cc406Sopenharmony_ci 201141cc406Sopenharmony_ci 202141cc406Sopenharmony_ci/* callback function for sanei_usb_attach_matching_devices */ 203141cc406Sopenharmony_cistatic SANE_Status 204141cc406Sopenharmony_ciattach_one (const char *name) 205141cc406Sopenharmony_ci{ 206141cc406Sopenharmony_ci attach_scanner (name, 0); 207141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 208141cc406Sopenharmony_ci} 209141cc406Sopenharmony_ci 210141cc406Sopenharmony_ci 211141cc406Sopenharmony_ci/* Find our devices */ 212141cc406Sopenharmony_ciSANE_Status 213141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) 214141cc406Sopenharmony_ci{ 215141cc406Sopenharmony_ci char config_line[PATH_MAX]; 216141cc406Sopenharmony_ci size_t len; 217141cc406Sopenharmony_ci FILE *fp; 218141cc406Sopenharmony_ci 219141cc406Sopenharmony_ci DBG_INIT (); 220141cc406Sopenharmony_ci 221141cc406Sopenharmony_ci#if 0 222141cc406Sopenharmony_ci DBG_LEVEL = 10; 223141cc406Sopenharmony_ci#endif 224141cc406Sopenharmony_ci 225141cc406Sopenharmony_ci DBG (2, "sane_init: version_code %s 0, authorize %s 0\n", 226141cc406Sopenharmony_ci version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!="); 227141cc406Sopenharmony_ci DBG (1, "sane_init: SANE Canon LiDE70 backend version %d.%d.%d from %s\n", 228141cc406Sopenharmony_ci SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD, PACKAGE_STRING); 229141cc406Sopenharmony_ci 230141cc406Sopenharmony_ci if (version_code) 231141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 232141cc406Sopenharmony_ci 233141cc406Sopenharmony_ci sanei_usb_init (); 234141cc406Sopenharmony_ci 235141cc406Sopenharmony_ci fp = sanei_config_open (CANONUSB_CONFIG_FILE); 236141cc406Sopenharmony_ci 237141cc406Sopenharmony_ci if (!fp) 238141cc406Sopenharmony_ci { 239141cc406Sopenharmony_ci /* no config-file: try these */ 240141cc406Sopenharmony_ci attach_scanner ("/dev/scanner", 0); 241141cc406Sopenharmony_ci attach_scanner ("/dev/usbscanner", 0); 242141cc406Sopenharmony_ci attach_scanner ("/dev/usb/scanner", 0); 243141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 244141cc406Sopenharmony_ci } 245141cc406Sopenharmony_ci 246141cc406Sopenharmony_ci DBG (3, "reading configure file %s\n", CANONUSB_CONFIG_FILE); 247141cc406Sopenharmony_ci 248141cc406Sopenharmony_ci while (sanei_config_read (config_line, sizeof (config_line), fp)) 249141cc406Sopenharmony_ci { 250141cc406Sopenharmony_ci if (config_line[0] == '#') 251141cc406Sopenharmony_ci continue; /* ignore line comments */ 252141cc406Sopenharmony_ci 253141cc406Sopenharmony_ci len = strlen (config_line); 254141cc406Sopenharmony_ci 255141cc406Sopenharmony_ci if (!len) 256141cc406Sopenharmony_ci continue; /* ignore empty lines */ 257141cc406Sopenharmony_ci 258141cc406Sopenharmony_ci DBG (4, "attach_matching_devices(%s)\n", config_line); 259141cc406Sopenharmony_ci sanei_usb_attach_matching_devices (config_line, attach_one); 260141cc406Sopenharmony_ci } 261141cc406Sopenharmony_ci 262141cc406Sopenharmony_ci DBG (4, "finished reading configure file\n"); 263141cc406Sopenharmony_ci 264141cc406Sopenharmony_ci fclose (fp); 265141cc406Sopenharmony_ci 266141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 267141cc406Sopenharmony_ci} 268141cc406Sopenharmony_ci 269141cc406Sopenharmony_ci 270141cc406Sopenharmony_civoid 271141cc406Sopenharmony_cisane_exit (void) 272141cc406Sopenharmony_ci{ 273141cc406Sopenharmony_ci Canon_Device *dev, *next; 274141cc406Sopenharmony_ci 275141cc406Sopenharmony_ci DBG (3, "sane_exit\n"); 276141cc406Sopenharmony_ci 277141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = next) 278141cc406Sopenharmony_ci { 279141cc406Sopenharmony_ci next = dev->next; 280141cc406Sopenharmony_ci free (dev->name); 281141cc406Sopenharmony_ci free (dev); 282141cc406Sopenharmony_ci } 283141cc406Sopenharmony_ci 284141cc406Sopenharmony_ci if (devlist) 285141cc406Sopenharmony_ci free (devlist); 286141cc406Sopenharmony_ci return; 287141cc406Sopenharmony_ci} 288141cc406Sopenharmony_ci 289141cc406Sopenharmony_ci 290141cc406Sopenharmony_ciSANE_Status 291141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) 292141cc406Sopenharmony_ci{ 293141cc406Sopenharmony_ci Canon_Device *dev; 294141cc406Sopenharmony_ci int i; 295141cc406Sopenharmony_ci 296141cc406Sopenharmony_ci DBG (3, "sane_get_devices(local_only = %d)\n", local_only); 297141cc406Sopenharmony_ci 298141cc406Sopenharmony_ci if (devlist) 299141cc406Sopenharmony_ci free (devlist); 300141cc406Sopenharmony_ci 301141cc406Sopenharmony_ci devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); 302141cc406Sopenharmony_ci if (!devlist) 303141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 304141cc406Sopenharmony_ci 305141cc406Sopenharmony_ci i = 0; 306141cc406Sopenharmony_ci 307141cc406Sopenharmony_ci for (dev = first_dev; i < num_devices; dev = dev->next) 308141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 309141cc406Sopenharmony_ci 310141cc406Sopenharmony_ci devlist[i++] = 0; 311141cc406Sopenharmony_ci 312141cc406Sopenharmony_ci *device_list = devlist; 313141cc406Sopenharmony_ci 314141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 315141cc406Sopenharmony_ci} 316141cc406Sopenharmony_ci 317141cc406Sopenharmony_cistatic SANE_Status 318141cc406Sopenharmony_ciinit_options (CANON_Handle * chndl) 319141cc406Sopenharmony_ci{ 320141cc406Sopenharmony_ci SANE_Option_Descriptor *od; 321141cc406Sopenharmony_ci 322141cc406Sopenharmony_ci DBG (2, "begin init_options: chndl=%p\n", (void *) chndl); 323141cc406Sopenharmony_ci 324141cc406Sopenharmony_ci /* opt_num_opts */ 325141cc406Sopenharmony_ci od = &chndl->opt[opt_num_opts]; 326141cc406Sopenharmony_ci od->name = ""; 327141cc406Sopenharmony_ci od->title = SANE_TITLE_NUM_OPTIONS; 328141cc406Sopenharmony_ci od->desc = SANE_DESC_NUM_OPTIONS; 329141cc406Sopenharmony_ci od->type = SANE_TYPE_INT; 330141cc406Sopenharmony_ci od->unit = SANE_UNIT_NONE; 331141cc406Sopenharmony_ci od->size = sizeof (SANE_Word); 332141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_DETECT; 333141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_NONE; 334141cc406Sopenharmony_ci od->constraint.range = 0; 335141cc406Sopenharmony_ci chndl->val[opt_num_opts].w = num_options; 336141cc406Sopenharmony_ci 337141cc406Sopenharmony_ci DBG (2, "val[opt_num_opts]: %d\n", chndl->val[opt_num_opts].w); 338141cc406Sopenharmony_ci 339141cc406Sopenharmony_ci /* opt_mode_group */ 340141cc406Sopenharmony_ci od = &chndl->opt[opt_mode_group]; 341141cc406Sopenharmony_ci od->name = ""; 342141cc406Sopenharmony_ci od->title = SANE_I18N ("Scan Mode"); 343141cc406Sopenharmony_ci od->desc = ""; 344141cc406Sopenharmony_ci od->type = SANE_TYPE_GROUP; 345141cc406Sopenharmony_ci od->unit = SANE_UNIT_NONE; 346141cc406Sopenharmony_ci od->size = 0; 347141cc406Sopenharmony_ci od->cap = 0; 348141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_NONE; 349141cc406Sopenharmony_ci od->constraint.range = 0; 350141cc406Sopenharmony_ci chndl->val[opt_mode_group].w = 0; 351141cc406Sopenharmony_ci 352141cc406Sopenharmony_ci /* opt_mode */ 353141cc406Sopenharmony_ci od = &chndl->opt[opt_mode]; 354141cc406Sopenharmony_ci od->name = SANE_NAME_SCAN_MODE; 355141cc406Sopenharmony_ci od->title = SANE_TITLE_SCAN_MODE; 356141cc406Sopenharmony_ci od->desc = SANE_DESC_SCAN_MODE; 357141cc406Sopenharmony_ci od->type = SANE_TYPE_STRING; 358141cc406Sopenharmony_ci od->unit = SANE_UNIT_NONE; 359141cc406Sopenharmony_ci od->size = max_string_size (mode_list); 360141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 361141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_STRING_LIST; 362141cc406Sopenharmony_ci od->constraint.string_list = mode_list; 363141cc406Sopenharmony_ci chndl->val[opt_mode].s = malloc (od->size); 364141cc406Sopenharmony_ci if (!chndl->val[opt_mode].s) 365141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 366141cc406Sopenharmony_ci strcpy (chndl->val[opt_mode].s, init_mode); 367141cc406Sopenharmony_ci chndl->graymode = init_graymode; 368141cc406Sopenharmony_ci 369141cc406Sopenharmony_ci /* opt_threshold */ 370141cc406Sopenharmony_ci od = &chndl->opt[opt_threshold]; 371141cc406Sopenharmony_ci od->name = SANE_NAME_THRESHOLD; 372141cc406Sopenharmony_ci od->title = SANE_TITLE_THRESHOLD; 373141cc406Sopenharmony_ci od->desc = SANE_DESC_THRESHOLD; 374141cc406Sopenharmony_ci od->type = SANE_TYPE_INT; 375141cc406Sopenharmony_ci od->unit = SANE_UNIT_PERCENT; 376141cc406Sopenharmony_ci od->size = sizeof (SANE_Word); 377141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE; 378141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_RANGE; 379141cc406Sopenharmony_ci od->constraint.range = &threshold_range; 380141cc406Sopenharmony_ci chndl->val[opt_threshold].w = init_threshold; 381141cc406Sopenharmony_ci 382141cc406Sopenharmony_ci /* opt_resolution */ 383141cc406Sopenharmony_ci od = &chndl->opt[opt_resolution]; 384141cc406Sopenharmony_ci od->name = SANE_NAME_SCAN_RESOLUTION; 385141cc406Sopenharmony_ci od->title = SANE_TITLE_SCAN_RESOLUTION; 386141cc406Sopenharmony_ci od->desc = SANE_DESC_SCAN_RESOLUTION; 387141cc406Sopenharmony_ci od->type = SANE_TYPE_INT; 388141cc406Sopenharmony_ci od->unit = SANE_UNIT_DPI; 389141cc406Sopenharmony_ci od->size = sizeof (SANE_Word); 390141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 391141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_WORD_LIST; 392141cc406Sopenharmony_ci if (chndl->productcode == 0x2224) 393141cc406Sopenharmony_ci { 394141cc406Sopenharmony_ci resolution_list[0] = 4; 395141cc406Sopenharmony_ci } 396141cc406Sopenharmony_ci od->constraint.word_list = resolution_list; 397141cc406Sopenharmony_ci chndl->val[opt_resolution].w = init_resolution; 398141cc406Sopenharmony_ci 399141cc406Sopenharmony_ci /* opt_non_blocking */ 400141cc406Sopenharmony_ci od = &chndl->opt[opt_non_blocking]; 401141cc406Sopenharmony_ci od->name = "non-blocking"; 402141cc406Sopenharmony_ci od->title = SANE_I18N ("Use non-blocking IO"); 403141cc406Sopenharmony_ci od->desc = SANE_I18N ("Use non-blocking IO for sane_read() if supported " 404141cc406Sopenharmony_ci "by the frontend."); 405141cc406Sopenharmony_ci od->type = SANE_TYPE_BOOL; 406141cc406Sopenharmony_ci od->unit = SANE_UNIT_NONE; 407141cc406Sopenharmony_ci od->size = sizeof (SANE_Word); 408141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE; 409141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_NONE; 410141cc406Sopenharmony_ci od->constraint.range = 0; 411141cc406Sopenharmony_ci chndl->val[opt_non_blocking].w = init_non_blocking; 412141cc406Sopenharmony_ci 413141cc406Sopenharmony_ci /* opt_geometry_group */ 414141cc406Sopenharmony_ci od = &chndl->opt[opt_geometry_group]; 415141cc406Sopenharmony_ci od->name = ""; 416141cc406Sopenharmony_ci od->title = SANE_I18N ("Geometry"); 417141cc406Sopenharmony_ci od->desc = ""; 418141cc406Sopenharmony_ci od->type = SANE_TYPE_GROUP; 419141cc406Sopenharmony_ci od->unit = SANE_UNIT_NONE; 420141cc406Sopenharmony_ci od->size = 0; 421141cc406Sopenharmony_ci od->cap = 0; 422141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_NONE; 423141cc406Sopenharmony_ci od->constraint.range = 0; 424141cc406Sopenharmony_ci chndl->val[opt_geometry_group].w = 0; 425141cc406Sopenharmony_ci 426141cc406Sopenharmony_ci /* opt_tl_x */ 427141cc406Sopenharmony_ci od = &chndl->opt[opt_tl_x]; 428141cc406Sopenharmony_ci od->name = SANE_NAME_SCAN_TL_X; 429141cc406Sopenharmony_ci od->title = SANE_TITLE_SCAN_TL_X; 430141cc406Sopenharmony_ci od->desc = SANE_DESC_SCAN_TL_X; 431141cc406Sopenharmony_ci od->type = SANE_TYPE_FIXED; 432141cc406Sopenharmony_ci od->unit = SANE_UNIT_MM; 433141cc406Sopenharmony_ci od->size = sizeof (SANE_Word); 434141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 435141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_RANGE; 436141cc406Sopenharmony_ci od->constraint.range = &widthRange; 437141cc406Sopenharmony_ci chndl->val[opt_tl_x].w = init_tl_x; 438141cc406Sopenharmony_ci 439141cc406Sopenharmony_ci /* opt_tl_y */ 440141cc406Sopenharmony_ci od = &chndl->opt[opt_tl_y]; 441141cc406Sopenharmony_ci od->name = SANE_NAME_SCAN_TL_Y; 442141cc406Sopenharmony_ci od->title = SANE_TITLE_SCAN_TL_Y; 443141cc406Sopenharmony_ci od->desc = SANE_DESC_SCAN_TL_Y; 444141cc406Sopenharmony_ci od->type = SANE_TYPE_FIXED; 445141cc406Sopenharmony_ci od->unit = SANE_UNIT_MM; 446141cc406Sopenharmony_ci od->size = sizeof (SANE_Word); 447141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 448141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_RANGE; 449141cc406Sopenharmony_ci od->constraint.range = &heightRange; 450141cc406Sopenharmony_ci chndl->val[opt_tl_y].w = init_tl_y; 451141cc406Sopenharmony_ci 452141cc406Sopenharmony_ci /* opt_br_x */ 453141cc406Sopenharmony_ci od = &chndl->opt[opt_br_x]; 454141cc406Sopenharmony_ci od->name = SANE_NAME_SCAN_BR_X; 455141cc406Sopenharmony_ci od->title = SANE_TITLE_SCAN_BR_X; 456141cc406Sopenharmony_ci od->desc = SANE_DESC_SCAN_BR_X; 457141cc406Sopenharmony_ci od->type = SANE_TYPE_FIXED; 458141cc406Sopenharmony_ci od->unit = SANE_UNIT_MM; 459141cc406Sopenharmony_ci od->size = sizeof (SANE_Word); 460141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 461141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_RANGE; 462141cc406Sopenharmony_ci od->constraint.range = &widthRange; 463141cc406Sopenharmony_ci chndl->val[opt_br_x].w = init_br_x; 464141cc406Sopenharmony_ci 465141cc406Sopenharmony_ci /* opt_br_y */ 466141cc406Sopenharmony_ci od = &chndl->opt[opt_br_y]; 467141cc406Sopenharmony_ci od->name = SANE_NAME_SCAN_BR_Y; 468141cc406Sopenharmony_ci od->title = SANE_TITLE_SCAN_BR_Y; 469141cc406Sopenharmony_ci od->desc = SANE_DESC_SCAN_BR_Y; 470141cc406Sopenharmony_ci od->type = SANE_TYPE_FIXED; 471141cc406Sopenharmony_ci od->unit = SANE_UNIT_MM; 472141cc406Sopenharmony_ci od->size = sizeof (SANE_Word); 473141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 474141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_RANGE; 475141cc406Sopenharmony_ci od->constraint.range = &heightRange; 476141cc406Sopenharmony_ci chndl->val[opt_br_y].w = init_br_y; 477141cc406Sopenharmony_ci 478141cc406Sopenharmony_ci DBG (2, "end init_options: chndl=%p\n", (void *) chndl); 479141cc406Sopenharmony_ci 480141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 481141cc406Sopenharmony_ci} 482141cc406Sopenharmony_ci 483141cc406Sopenharmony_ciSANE_Status 484141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 485141cc406Sopenharmony_ci{ 486141cc406Sopenharmony_ci Canon_Device *dev; 487141cc406Sopenharmony_ci SANE_Status status; 488141cc406Sopenharmony_ci Canon_Scanner *scanner; 489141cc406Sopenharmony_ci 490141cc406Sopenharmony_ci DBG (3, "sane_open\n"); 491141cc406Sopenharmony_ci 492141cc406Sopenharmony_ci if (devicename[0]) /* search for devicename */ 493141cc406Sopenharmony_ci { 494141cc406Sopenharmony_ci DBG (4, "sane_open: devicename=%s\n", devicename); 495141cc406Sopenharmony_ci 496141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 497141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) 498141cc406Sopenharmony_ci break; 499141cc406Sopenharmony_ci 500141cc406Sopenharmony_ci if (!dev) 501141cc406Sopenharmony_ci { 502141cc406Sopenharmony_ci status = attach_scanner (devicename, &dev); 503141cc406Sopenharmony_ci 504141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 505141cc406Sopenharmony_ci return status; 506141cc406Sopenharmony_ci } 507141cc406Sopenharmony_ci } 508141cc406Sopenharmony_ci else 509141cc406Sopenharmony_ci { 510141cc406Sopenharmony_ci DBG (2, "sane_open: no devicename, opening first device\n"); 511141cc406Sopenharmony_ci dev = first_dev; 512141cc406Sopenharmony_ci } 513141cc406Sopenharmony_ci 514141cc406Sopenharmony_ci if (!dev) 515141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 516141cc406Sopenharmony_ci 517141cc406Sopenharmony_ci scanner = malloc (sizeof (*scanner)); 518141cc406Sopenharmony_ci 519141cc406Sopenharmony_ci if (!scanner) 520141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 521141cc406Sopenharmony_ci 522141cc406Sopenharmony_ci memset (scanner, 0, sizeof (*scanner)); 523141cc406Sopenharmony_ci scanner->device = dev; 524141cc406Sopenharmony_ci 525141cc406Sopenharmony_ci status = CANON_open_device (&scanner->scan, dev->sane.name); 526141cc406Sopenharmony_ci 527141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 528141cc406Sopenharmony_ci { 529141cc406Sopenharmony_ci free (scanner); 530141cc406Sopenharmony_ci return status; 531141cc406Sopenharmony_ci } 532141cc406Sopenharmony_ci 533141cc406Sopenharmony_ci status = init_options (&scanner->scan); 534141cc406Sopenharmony_ci 535141cc406Sopenharmony_ci *handle = scanner; 536141cc406Sopenharmony_ci 537141cc406Sopenharmony_ci /* insert newly opened handle into list of open handles: */ 538141cc406Sopenharmony_ci scanner->next = first_handle; 539141cc406Sopenharmony_ci 540141cc406Sopenharmony_ci first_handle = scanner; 541141cc406Sopenharmony_ci 542141cc406Sopenharmony_ci return status; 543141cc406Sopenharmony_ci} 544141cc406Sopenharmony_ci 545141cc406Sopenharmony_cistatic void 546141cc406Sopenharmony_ciprint_options (CANON_Handle * chndl) 547141cc406Sopenharmony_ci{ 548141cc406Sopenharmony_ci SANE_Option_Descriptor *od; 549141cc406Sopenharmony_ci SANE_Word option_number; 550141cc406Sopenharmony_ci SANE_Char caps[1024]; 551141cc406Sopenharmony_ci 552141cc406Sopenharmony_ci for (option_number = 0; option_number < num_options; option_number++) 553141cc406Sopenharmony_ci { 554141cc406Sopenharmony_ci od = &chndl->opt[option_number]; 555141cc406Sopenharmony_ci DBG (50, "-----> number: %d\n", option_number); 556141cc406Sopenharmony_ci DBG (50, " name: `%s'\n", od->name); 557141cc406Sopenharmony_ci DBG (50, " title: `%s'\n", od->title); 558141cc406Sopenharmony_ci DBG (50, " description: `%s'\n", od->desc); 559141cc406Sopenharmony_ci DBG (50, " type: %s\n", 560141cc406Sopenharmony_ci od->type == SANE_TYPE_BOOL ? "SANE_TYPE_BOOL" : 561141cc406Sopenharmony_ci od->type == SANE_TYPE_INT ? "SANE_TYPE_INT" : 562141cc406Sopenharmony_ci od->type == SANE_TYPE_FIXED ? "SANE_TYPE_FIXED" : 563141cc406Sopenharmony_ci od->type == SANE_TYPE_STRING ? "SANE_TYPE_STRING" : 564141cc406Sopenharmony_ci od->type == SANE_TYPE_BUTTON ? "SANE_TYPE_BUTTON" : 565141cc406Sopenharmony_ci od->type == SANE_TYPE_GROUP ? "SANE_TYPE_GROUP" : "unknown"); 566141cc406Sopenharmony_ci DBG (50, " unit: %s\n", 567141cc406Sopenharmony_ci od->unit == SANE_UNIT_NONE ? "SANE_UNIT_NONE" : 568141cc406Sopenharmony_ci od->unit == SANE_UNIT_PIXEL ? "SANE_UNIT_PIXEL" : 569141cc406Sopenharmony_ci od->unit == SANE_UNIT_BIT ? "SANE_UNIT_BIT" : 570141cc406Sopenharmony_ci od->unit == SANE_UNIT_MM ? "SANE_UNIT_MM" : 571141cc406Sopenharmony_ci od->unit == SANE_UNIT_DPI ? "SANE_UNIT_DPI" : 572141cc406Sopenharmony_ci od->unit == SANE_UNIT_PERCENT ? "SANE_UNIT_PERCENT" : 573141cc406Sopenharmony_ci od->unit == SANE_UNIT_MICROSECOND ? "SANE_UNIT_MICROSECOND" : 574141cc406Sopenharmony_ci "unknown"); 575141cc406Sopenharmony_ci DBG (50, " size: %d\n", od->size); 576141cc406Sopenharmony_ci caps[0] = '\0'; 577141cc406Sopenharmony_ci if (od->cap & SANE_CAP_SOFT_SELECT) 578141cc406Sopenharmony_ci strcat (caps, "SANE_CAP_SOFT_SELECT "); 579141cc406Sopenharmony_ci if (od->cap & SANE_CAP_HARD_SELECT) 580141cc406Sopenharmony_ci strcat (caps, "SANE_CAP_HARD_SELECT "); 581141cc406Sopenharmony_ci if (od->cap & SANE_CAP_SOFT_DETECT) 582141cc406Sopenharmony_ci strcat (caps, "SANE_CAP_SOFT_DETECT "); 583141cc406Sopenharmony_ci if (od->cap & SANE_CAP_EMULATED) 584141cc406Sopenharmony_ci strcat (caps, "SANE_CAP_EMULATED "); 585141cc406Sopenharmony_ci if (od->cap & SANE_CAP_AUTOMATIC) 586141cc406Sopenharmony_ci strcat (caps, "SANE_CAP_AUTOMATIC "); 587141cc406Sopenharmony_ci if (od->cap & SANE_CAP_INACTIVE) 588141cc406Sopenharmony_ci strcat (caps, "SANE_CAP_INACTIVE "); 589141cc406Sopenharmony_ci if (od->cap & SANE_CAP_ADVANCED) 590141cc406Sopenharmony_ci strcat (caps, "SANE_CAP_ADVANCED "); 591141cc406Sopenharmony_ci DBG (50, " capabilities: %s\n", caps); 592141cc406Sopenharmony_ci DBG (50, "constraint type: %s\n", 593141cc406Sopenharmony_ci od->constraint_type == SANE_CONSTRAINT_NONE ? 594141cc406Sopenharmony_ci "SANE_CONSTRAINT_NONE" : 595141cc406Sopenharmony_ci od->constraint_type == SANE_CONSTRAINT_RANGE ? 596141cc406Sopenharmony_ci "SANE_CONSTRAINT_RANGE" : 597141cc406Sopenharmony_ci od->constraint_type == SANE_CONSTRAINT_WORD_LIST ? 598141cc406Sopenharmony_ci "SANE_CONSTRAINT_WORD_LIST" : 599141cc406Sopenharmony_ci od->constraint_type == SANE_CONSTRAINT_STRING_LIST ? 600141cc406Sopenharmony_ci "SANE_CONSTRAINT_STRING_LIST" : "unknown"); 601141cc406Sopenharmony_ci if (od->type == SANE_TYPE_INT) 602141cc406Sopenharmony_ci DBG (50, " value: %d\n", chndl->val[option_number].w); 603141cc406Sopenharmony_ci else if (od->type == SANE_TYPE_FIXED) 604141cc406Sopenharmony_ci DBG (50, " value: %f\n", 605141cc406Sopenharmony_ci SANE_UNFIX (chndl->val[option_number].w)); 606141cc406Sopenharmony_ci else if (od->type == SANE_TYPE_STRING) 607141cc406Sopenharmony_ci DBG (50, " value: %s\n", chndl->val[option_number].s); 608141cc406Sopenharmony_ci } 609141cc406Sopenharmony_ci} 610141cc406Sopenharmony_ci 611141cc406Sopenharmony_civoid 612141cc406Sopenharmony_cisane_close (SANE_Handle handle) 613141cc406Sopenharmony_ci{ 614141cc406Sopenharmony_ci Canon_Scanner *prev, *scanner; 615141cc406Sopenharmony_ci SANE_Status res; 616141cc406Sopenharmony_ci 617141cc406Sopenharmony_ci DBG (3, "sane_close\n"); 618141cc406Sopenharmony_ci 619141cc406Sopenharmony_ci scanner = handle; 620141cc406Sopenharmony_ci print_options (&scanner->scan); 621141cc406Sopenharmony_ci 622141cc406Sopenharmony_ci if (!first_handle) 623141cc406Sopenharmony_ci { 624141cc406Sopenharmony_ci DBG (1, "ERROR: sane_close: no handles opened\n"); 625141cc406Sopenharmony_ci return; 626141cc406Sopenharmony_ci } 627141cc406Sopenharmony_ci 628141cc406Sopenharmony_ci /* remove handle from list of open handles: */ 629141cc406Sopenharmony_ci 630141cc406Sopenharmony_ci prev = NULL; 631141cc406Sopenharmony_ci 632141cc406Sopenharmony_ci for (scanner = first_handle; scanner; scanner = scanner->next) 633141cc406Sopenharmony_ci { 634141cc406Sopenharmony_ci if (scanner == handle) 635141cc406Sopenharmony_ci break; 636141cc406Sopenharmony_ci 637141cc406Sopenharmony_ci prev = scanner; 638141cc406Sopenharmony_ci } 639141cc406Sopenharmony_ci 640141cc406Sopenharmony_ci if (!scanner) 641141cc406Sopenharmony_ci { 642141cc406Sopenharmony_ci DBG (1, "ERROR: sane_close: invalid handle %p\n", handle); 643141cc406Sopenharmony_ci return; /* oops, not a handle we know about */ 644141cc406Sopenharmony_ci } 645141cc406Sopenharmony_ci 646141cc406Sopenharmony_ci if (prev) 647141cc406Sopenharmony_ci prev->next = scanner->next; 648141cc406Sopenharmony_ci else 649141cc406Sopenharmony_ci first_handle = scanner->next; 650141cc406Sopenharmony_ci 651141cc406Sopenharmony_ci res = CANON_close_device (&scanner->scan); 652141cc406Sopenharmony_ci DBG (3, "CANON_close_device returned: %d\n", res); 653141cc406Sopenharmony_ci free (scanner); 654141cc406Sopenharmony_ci} 655141cc406Sopenharmony_ci 656141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 657141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 658141cc406Sopenharmony_ci{ 659141cc406Sopenharmony_ci Canon_Scanner *scanner = handle; 660141cc406Sopenharmony_ci CANON_Handle *chndl = &scanner->scan; 661141cc406Sopenharmony_ci 662141cc406Sopenharmony_ci 663141cc406Sopenharmony_ci DBG (4, "sane_get_option_descriptor: handle=%p, option = %d\n", 664141cc406Sopenharmony_ci (void *) handle, option); 665141cc406Sopenharmony_ci if (option < 0 || option >= num_options) 666141cc406Sopenharmony_ci { 667141cc406Sopenharmony_ci DBG (3, "sane_get_option_descriptor: option < 0 || " 668141cc406Sopenharmony_ci "option > num_options\n"); 669141cc406Sopenharmony_ci return 0; 670141cc406Sopenharmony_ci } 671141cc406Sopenharmony_ci 672141cc406Sopenharmony_ci return &chndl->opt[option]; 673141cc406Sopenharmony_ci} 674141cc406Sopenharmony_ci 675141cc406Sopenharmony_ciSANE_Status 676141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, 677141cc406Sopenharmony_ci void *value, SANE_Int * info) 678141cc406Sopenharmony_ci{ 679141cc406Sopenharmony_ci Canon_Scanner *scanner = handle; 680141cc406Sopenharmony_ci CANON_Handle *chndl = &scanner->scan; 681141cc406Sopenharmony_ci 682141cc406Sopenharmony_ci SANE_Int myinfo = 0; 683141cc406Sopenharmony_ci SANE_Status status; 684141cc406Sopenharmony_ci 685141cc406Sopenharmony_ci DBG (4, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n", 686141cc406Sopenharmony_ci (void *) handle, option, action, (void *) value, (void *) info); 687141cc406Sopenharmony_ci 688141cc406Sopenharmony_ci if (option < 0 || option >= num_options) 689141cc406Sopenharmony_ci { 690141cc406Sopenharmony_ci DBG (1, "sane_control_option: option < 0 || option > num_options\n"); 691141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 692141cc406Sopenharmony_ci } 693141cc406Sopenharmony_ci 694141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (chndl->opt[option].cap)) 695141cc406Sopenharmony_ci { 696141cc406Sopenharmony_ci DBG (1, "sane_control_option: option is inactive\n"); 697141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 698141cc406Sopenharmony_ci } 699141cc406Sopenharmony_ci 700141cc406Sopenharmony_ci if (chndl->opt[option].type == SANE_TYPE_GROUP) 701141cc406Sopenharmony_ci { 702141cc406Sopenharmony_ci DBG (1, "sane_control_option: option is a group\n"); 703141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 704141cc406Sopenharmony_ci } 705141cc406Sopenharmony_ci 706141cc406Sopenharmony_ci switch (action) 707141cc406Sopenharmony_ci { 708141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 709141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (chndl->opt[option].cap)) 710141cc406Sopenharmony_ci { 711141cc406Sopenharmony_ci DBG (1, "sane_control_option: option is not setable\n"); 712141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 713141cc406Sopenharmony_ci } 714141cc406Sopenharmony_ci status = sanei_constrain_value (&chndl->opt[option], value, &myinfo); 715141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 716141cc406Sopenharmony_ci { 717141cc406Sopenharmony_ci DBG (3, "sane_control_option: sanei_constrain_value returned %s\n", 718141cc406Sopenharmony_ci sane_strstatus (status)); 719141cc406Sopenharmony_ci return status; 720141cc406Sopenharmony_ci } 721141cc406Sopenharmony_ci switch (option) 722141cc406Sopenharmony_ci { 723141cc406Sopenharmony_ci case opt_tl_x: /* Fixed with parameter reloading */ 724141cc406Sopenharmony_ci case opt_tl_y: 725141cc406Sopenharmony_ci case opt_br_x: 726141cc406Sopenharmony_ci case opt_br_y: 727141cc406Sopenharmony_ci if (chndl->val[option].w == *(SANE_Fixed *) value) 728141cc406Sopenharmony_ci { 729141cc406Sopenharmony_ci DBG (4, "sane_control_option: option %d (%s) not changed\n", 730141cc406Sopenharmony_ci option, chndl->opt[option].name); 731141cc406Sopenharmony_ci break; 732141cc406Sopenharmony_ci } 733141cc406Sopenharmony_ci chndl->val[option].w = *(SANE_Fixed *) value; 734141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_PARAMS; 735141cc406Sopenharmony_ci DBG (4, "sane_control_option: set option %d (%s) to %.0f %s\n", 736141cc406Sopenharmony_ci option, chndl->opt[option].name, 737141cc406Sopenharmony_ci SANE_UNFIX (*(SANE_Fixed *) value), 738141cc406Sopenharmony_ci chndl->opt[option].unit == SANE_UNIT_MM ? "mm" : "dpi"); 739141cc406Sopenharmony_ci break; 740141cc406Sopenharmony_ci case opt_non_blocking: 741141cc406Sopenharmony_ci if (chndl->val[option].w == *(SANE_Bool *) value) 742141cc406Sopenharmony_ci { 743141cc406Sopenharmony_ci DBG (4, "sane_control_option: option %d (%s) not changed\n", 744141cc406Sopenharmony_ci option, chndl->opt[option].name); 745141cc406Sopenharmony_ci break; 746141cc406Sopenharmony_ci } 747141cc406Sopenharmony_ci chndl->val[option].w = *(SANE_Bool *) value; 748141cc406Sopenharmony_ci DBG (4, "sane_control_option: set option %d (%s) to %s\n", 749141cc406Sopenharmony_ci option, chndl->opt[option].name, 750141cc406Sopenharmony_ci *(SANE_Bool *) value == SANE_TRUE ? "true" : "false"); 751141cc406Sopenharmony_ci break; 752141cc406Sopenharmony_ci case opt_resolution: 753141cc406Sopenharmony_ci case opt_threshold: 754141cc406Sopenharmony_ci if (chndl->val[option].w == *(SANE_Int *) value) 755141cc406Sopenharmony_ci { 756141cc406Sopenharmony_ci DBG (4, "sane_control_option: option %d (%s) not changed\n", 757141cc406Sopenharmony_ci option, chndl->opt[option].name); 758141cc406Sopenharmony_ci break; 759141cc406Sopenharmony_ci } 760141cc406Sopenharmony_ci chndl->val[option].w = *(SANE_Int *) value; 761141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_PARAMS; 762141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_OPTIONS; 763141cc406Sopenharmony_ci DBG (4, "sane_control_option: set option %d (%s) to %d\n", 764141cc406Sopenharmony_ci option, chndl->opt[option].name, *(SANE_Int *) value); 765141cc406Sopenharmony_ci break; 766141cc406Sopenharmony_ci case opt_mode: 767141cc406Sopenharmony_ci if (strcmp (chndl->val[option].s, value) == 0) 768141cc406Sopenharmony_ci { 769141cc406Sopenharmony_ci DBG (4, "sane_control_option: option %d (%s) not changed\n", 770141cc406Sopenharmony_ci option, chndl->opt[option].name); 771141cc406Sopenharmony_ci break; 772141cc406Sopenharmony_ci } 773141cc406Sopenharmony_ci strcpy (chndl->val[option].s, (SANE_String) value); 774141cc406Sopenharmony_ci 775141cc406Sopenharmony_ci if (strcmp (chndl->val[option].s, SANE_VALUE_SCAN_MODE_LINEART) == 776141cc406Sopenharmony_ci 0) 777141cc406Sopenharmony_ci { 778141cc406Sopenharmony_ci chndl->opt[opt_threshold].cap &= ~SANE_CAP_INACTIVE; 779141cc406Sopenharmony_ci chndl->graymode = 2; 780141cc406Sopenharmony_ci } 781141cc406Sopenharmony_ci if (strcmp (chndl->val[option].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) 782141cc406Sopenharmony_ci { 783141cc406Sopenharmony_ci chndl->opt[opt_threshold].cap |= SANE_CAP_INACTIVE; 784141cc406Sopenharmony_ci chndl->graymode = 0; 785141cc406Sopenharmony_ci } 786141cc406Sopenharmony_ci if (strcmp (chndl->val[option].s, SANE_VALUE_SCAN_MODE_GRAY) == 0) 787141cc406Sopenharmony_ci { 788141cc406Sopenharmony_ci chndl->opt[opt_threshold].cap |= SANE_CAP_INACTIVE; 789141cc406Sopenharmony_ci chndl->graymode = 1; 790141cc406Sopenharmony_ci } 791141cc406Sopenharmony_ci 792141cc406Sopenharmony_ci 793141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_PARAMS; 794141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_OPTIONS; 795141cc406Sopenharmony_ci DBG (4, "sane_control_option: set option %d (%s) to %s\n", 796141cc406Sopenharmony_ci option, chndl->opt[option].name, (SANE_String) value); 797141cc406Sopenharmony_ci break; 798141cc406Sopenharmony_ci default: 799141cc406Sopenharmony_ci DBG (1, "sane_control_option: trying to set unexpected option\n"); 800141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 801141cc406Sopenharmony_ci } 802141cc406Sopenharmony_ci break; 803141cc406Sopenharmony_ci 804141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 805141cc406Sopenharmony_ci switch (option) 806141cc406Sopenharmony_ci { 807141cc406Sopenharmony_ci case opt_num_opts: 808141cc406Sopenharmony_ci *(SANE_Word *) value = num_options; 809141cc406Sopenharmony_ci DBG (4, "sane_control_option: get option 0, value = %d\n", 810141cc406Sopenharmony_ci num_options); 811141cc406Sopenharmony_ci break; 812141cc406Sopenharmony_ci case opt_tl_x: /* Fixed options */ 813141cc406Sopenharmony_ci case opt_tl_y: 814141cc406Sopenharmony_ci case opt_br_x: 815141cc406Sopenharmony_ci case opt_br_y: 816141cc406Sopenharmony_ci { 817141cc406Sopenharmony_ci *(SANE_Fixed *) value = chndl->val[option].w; 818141cc406Sopenharmony_ci DBG (4, 819141cc406Sopenharmony_ci "sane_control_option: get option %d (%s), value=%.1f %s\n", 820141cc406Sopenharmony_ci option, chndl->opt[option].name, 821141cc406Sopenharmony_ci SANE_UNFIX (*(SANE_Fixed *) value), 822141cc406Sopenharmony_ci chndl->opt[option].unit == SANE_UNIT_MM ? "mm" : 823141cc406Sopenharmony_ci (chndl->opt[option].unit == SANE_UNIT_DPI ? "dpi" : "")); 824141cc406Sopenharmony_ci break; 825141cc406Sopenharmony_ci } 826141cc406Sopenharmony_ci case opt_non_blocking: 827141cc406Sopenharmony_ci *(SANE_Bool *) value = chndl->val[option].w; 828141cc406Sopenharmony_ci DBG (4, 829141cc406Sopenharmony_ci "sane_control_option: get option %d (%s), value=%s\n", 830141cc406Sopenharmony_ci option, chndl->opt[option].name, 831141cc406Sopenharmony_ci *(SANE_Bool *) value == SANE_TRUE ? "true" : "false"); 832141cc406Sopenharmony_ci break; 833141cc406Sopenharmony_ci case opt_mode: /* String (list) options */ 834141cc406Sopenharmony_ci strcpy (value, chndl->val[option].s); 835141cc406Sopenharmony_ci DBG (4, "sane_control_option: get option %d (%s), value=`%s'\n", 836141cc406Sopenharmony_ci option, chndl->opt[option].name, (SANE_String) value); 837141cc406Sopenharmony_ci break; 838141cc406Sopenharmony_ci case opt_resolution: 839141cc406Sopenharmony_ci case opt_threshold: 840141cc406Sopenharmony_ci *(SANE_Int *) value = chndl->val[option].w; 841141cc406Sopenharmony_ci DBG (4, "sane_control_option: get option %d (%s), value=%d\n", 842141cc406Sopenharmony_ci option, chndl->opt[option].name, *(SANE_Int *) value); 843141cc406Sopenharmony_ci break; 844141cc406Sopenharmony_ci default: 845141cc406Sopenharmony_ci DBG (1, "sane_control_option: trying to get unexpected option\n"); 846141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 847141cc406Sopenharmony_ci } 848141cc406Sopenharmony_ci break; 849141cc406Sopenharmony_ci default: 850141cc406Sopenharmony_ci DBG (1, "sane_control_option: trying unexpected action %d\n", action); 851141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 852141cc406Sopenharmony_ci } 853141cc406Sopenharmony_ci 854141cc406Sopenharmony_ci if (info) 855141cc406Sopenharmony_ci *info = myinfo; 856141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 857141cc406Sopenharmony_ci} 858141cc406Sopenharmony_ci 859141cc406Sopenharmony_ci 860141cc406Sopenharmony_ciSANE_Status 861141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 862141cc406Sopenharmony_ci{ 863141cc406Sopenharmony_ci Canon_Scanner *hndl = handle; /* Eliminate compiler warning */ 864141cc406Sopenharmony_ci CANON_Handle *chndl = &hndl->scan; 865141cc406Sopenharmony_ci 866141cc406Sopenharmony_ci SANE_Status rc = SANE_STATUS_GOOD; 867141cc406Sopenharmony_ci int w = SANE_UNFIX (chndl->val[opt_br_x].w - 868141cc406Sopenharmony_ci chndl->val[opt_tl_x].w) / MM_IN_INCH * 869141cc406Sopenharmony_ci chndl->val[opt_resolution].w; 870141cc406Sopenharmony_ci int h = 871141cc406Sopenharmony_ci SANE_UNFIX (chndl->val[opt_br_y].w - 872141cc406Sopenharmony_ci chndl->val[opt_tl_y].w) / MM_IN_INCH * 873141cc406Sopenharmony_ci chndl->val[opt_resolution].w; 874141cc406Sopenharmony_ci 875141cc406Sopenharmony_ci DBG (3, "sane_get_parameters\n"); 876141cc406Sopenharmony_ci chndl->params.depth = 8; 877141cc406Sopenharmony_ci chndl->params.last_frame = SANE_TRUE; 878141cc406Sopenharmony_ci chndl->params.pixels_per_line = w; 879141cc406Sopenharmony_ci chndl->params.lines = h; 880141cc406Sopenharmony_ci 881141cc406Sopenharmony_ci if (chndl->graymode == 1) 882141cc406Sopenharmony_ci { 883141cc406Sopenharmony_ci chndl->params.format = SANE_FRAME_GRAY; 884141cc406Sopenharmony_ci chndl->params.bytes_per_line = w; 885141cc406Sopenharmony_ci } 886141cc406Sopenharmony_ci else if (chndl->graymode == 2) 887141cc406Sopenharmony_ci { 888141cc406Sopenharmony_ci chndl->params.format = SANE_FRAME_GRAY; 889141cc406Sopenharmony_ci w /= 8; 890141cc406Sopenharmony_ci 891141cc406Sopenharmony_ci if ((chndl->params.pixels_per_line % 8) != 0) 892141cc406Sopenharmony_ci w++; 893141cc406Sopenharmony_ci 894141cc406Sopenharmony_ci chndl->params.bytes_per_line = w; 895141cc406Sopenharmony_ci chndl->params.depth = 1; 896141cc406Sopenharmony_ci } 897141cc406Sopenharmony_ci else 898141cc406Sopenharmony_ci { 899141cc406Sopenharmony_ci chndl->params.format = SANE_FRAME_RGB; 900141cc406Sopenharmony_ci chndl->params.bytes_per_line = w * 3; 901141cc406Sopenharmony_ci } 902141cc406Sopenharmony_ci 903141cc406Sopenharmony_ci *params = chndl->params; 904141cc406Sopenharmony_ci DBG (1, "%d\n", chndl->params.format); 905141cc406Sopenharmony_ci return rc; 906141cc406Sopenharmony_ci} 907141cc406Sopenharmony_ci 908141cc406Sopenharmony_ci 909141cc406Sopenharmony_ciSANE_Status 910141cc406Sopenharmony_cisane_start (SANE_Handle handle) 911141cc406Sopenharmony_ci{ 912141cc406Sopenharmony_ci Canon_Scanner *scanner = handle; 913141cc406Sopenharmony_ci CANON_Handle *chndl = &scanner->scan; 914141cc406Sopenharmony_ci SANE_Status res; 915141cc406Sopenharmony_ci 916141cc406Sopenharmony_ci DBG (3, "sane_start\n"); 917141cc406Sopenharmony_ci 918141cc406Sopenharmony_ci res = sane_get_parameters (handle, &chndl->params); 919141cc406Sopenharmony_ci res = CANON_set_scan_parameters (&scanner->scan); 920141cc406Sopenharmony_ci 921141cc406Sopenharmony_ci if (res != SANE_STATUS_GOOD) 922141cc406Sopenharmony_ci return res; 923141cc406Sopenharmony_ci 924141cc406Sopenharmony_ci return CANON_start_scan (&scanner->scan); 925141cc406Sopenharmony_ci} 926141cc406Sopenharmony_ci 927141cc406Sopenharmony_ci 928141cc406Sopenharmony_ciSANE_Status 929141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * data, 930141cc406Sopenharmony_ci SANE_Int max_length, SANE_Int * length) 931141cc406Sopenharmony_ci{ 932141cc406Sopenharmony_ci Canon_Scanner *scanner = handle; 933141cc406Sopenharmony_ci return CANON_read (&scanner->scan, data, max_length, length); 934141cc406Sopenharmony_ci} 935141cc406Sopenharmony_ci 936141cc406Sopenharmony_ci 937141cc406Sopenharmony_civoid 938141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 939141cc406Sopenharmony_ci{ 940141cc406Sopenharmony_ci DBG (3, "sane_cancel: handle = %p\n", handle); 941141cc406Sopenharmony_ci DBG (3, "sane_cancel: cancelling is unsupported in this backend\n"); 942141cc406Sopenharmony_ci} 943141cc406Sopenharmony_ci 944141cc406Sopenharmony_ci 945141cc406Sopenharmony_ciSANE_Status 946141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 947141cc406Sopenharmony_ci{ 948141cc406Sopenharmony_ci DBG (3, "sane_set_io_mode: handle = %p, non_blocking = %d\n", handle, 949141cc406Sopenharmony_ci non_blocking); 950141cc406Sopenharmony_ci if (non_blocking != SANE_FALSE) 951141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 952141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 953141cc406Sopenharmony_ci} 954141cc406Sopenharmony_ci 955141cc406Sopenharmony_ci 956141cc406Sopenharmony_ciSANE_Status 957141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd) 958141cc406Sopenharmony_ci{ 959141cc406Sopenharmony_ci (void) handle; /* silence gcc */ 960141cc406Sopenharmony_ci (void) fd; /* silence gcc */ 961141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 962141cc406Sopenharmony_ci} 963