1141cc406Sopenharmony_ci/* 2141cc406Sopenharmony_ci * epson2.c - SANE library for Epson scanners. 3141cc406Sopenharmony_ci * 4141cc406Sopenharmony_ci * Based on Kazuhiro Sasayama previous 5141cc406Sopenharmony_ci * Work on epson.[ch] file from the SANE package. 6141cc406Sopenharmony_ci * Please see those files for additional copyrights. 7141cc406Sopenharmony_ci * 8141cc406Sopenharmony_ci * Copyright (C) 2006-10 Tower Technologies 9141cc406Sopenharmony_ci * Author: Alessandro Zummo <a.zummo@towertech.it> 10141cc406Sopenharmony_ci * 11141cc406Sopenharmony_ci * This file is part of the SANE package. 12141cc406Sopenharmony_ci * 13141cc406Sopenharmony_ci * This program is free software; you can redistribute it and/or 14141cc406Sopenharmony_ci * modify it under the terms of the GNU General Public License as 15141cc406Sopenharmony_ci * published by the Free Software Foundation, version 2. 16141cc406Sopenharmony_ci */ 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci/* debugging levels: 19141cc406Sopenharmony_ci * 20141cc406Sopenharmony_ci * 127 e2_recv buffer 21141cc406Sopenharmony_ci * 125 e2_send buffer 22141cc406Sopenharmony_ci * 32 more network progression 23141cc406Sopenharmony_ci * 24 network header 24141cc406Sopenharmony_ci * 23 network info 25141cc406Sopenharmony_ci * 20 usb cmd counters 26141cc406Sopenharmony_ci * 18 sane_read 27141cc406Sopenharmony_ci * 17 setvalue, getvalue, control_option 28141cc406Sopenharmony_ci * 16 gamma table 29141cc406Sopenharmony_ci * 15 e2_send, e2_recv calls 30141cc406Sopenharmony_ci * 13 e2_cmd_info_block 31141cc406Sopenharmony_ci * 12 epson_cmd_simple 32141cc406Sopenharmony_ci * 11 even more 33141cc406Sopenharmony_ci * 10 more debug in ESC/I commands 34141cc406Sopenharmony_ci * 9 ESC x/FS x in e2_send 35141cc406Sopenharmony_ci * 8 ESC/I commands 36141cc406Sopenharmony_ci * 7 open/close/attach 37141cc406Sopenharmony_ci * 6 print_params 38141cc406Sopenharmony_ci * 5 basic functions 39141cc406Sopenharmony_ci * 3 status information 40141cc406Sopenharmony_ci * 1 scanner info and capabilities 41141cc406Sopenharmony_ci * warnings 42141cc406Sopenharmony_ci */ 43141cc406Sopenharmony_ci 44141cc406Sopenharmony_ci#include "sane/config.h" 45141cc406Sopenharmony_ci 46141cc406Sopenharmony_ci#include "epson2.h" 47141cc406Sopenharmony_ci 48141cc406Sopenharmony_ci#include <limits.h> 49141cc406Sopenharmony_ci#include <stdio.h> 50141cc406Sopenharmony_ci#include <string.h> 51141cc406Sopenharmony_ci#include <stdlib.h> 52141cc406Sopenharmony_ci#include <ctype.h> 53141cc406Sopenharmony_ci#include <fcntl.h> 54141cc406Sopenharmony_ci#include <unistd.h> 55141cc406Sopenharmony_ci#include <errno.h> 56141cc406Sopenharmony_ci#include <sys/time.h> 57141cc406Sopenharmony_ci#include <sys/types.h> 58141cc406Sopenharmony_ci#ifdef HAVE_SYS_SOCKET_H 59141cc406Sopenharmony_ci#include <sys/socket.h> 60141cc406Sopenharmony_ci#endif 61141cc406Sopenharmony_ci 62141cc406Sopenharmony_ci#include "sane/saneopts.h" 63141cc406Sopenharmony_ci#include "sane/sanei_scsi.h" 64141cc406Sopenharmony_ci#include "sane/sanei_usb.h" 65141cc406Sopenharmony_ci#include "sane/sanei_pio.h" 66141cc406Sopenharmony_ci#include "sane/sanei_tcp.h" 67141cc406Sopenharmony_ci#include "sane/sanei_udp.h" 68141cc406Sopenharmony_ci#include "sane/sanei_backend.h" 69141cc406Sopenharmony_ci#include "sane/sanei_config.h" 70141cc406Sopenharmony_ci 71141cc406Sopenharmony_ci#include "epson2-io.h" 72141cc406Sopenharmony_ci#include "epson2-commands.h" 73141cc406Sopenharmony_ci#include "epson2-ops.h" 74141cc406Sopenharmony_ci 75141cc406Sopenharmony_ci#include "epson2_scsi.h" 76141cc406Sopenharmony_ci#include "epson_usb.h" 77141cc406Sopenharmony_ci#include "epson2_net.h" 78141cc406Sopenharmony_ci 79141cc406Sopenharmony_ci/* 80141cc406Sopenharmony_ci * Definition of the mode_param struct, that is used to 81141cc406Sopenharmony_ci * specify the valid parameters for the different scan modes. 82141cc406Sopenharmony_ci * 83141cc406Sopenharmony_ci * The depth variable gets updated when the bit depth is modified. 84141cc406Sopenharmony_ci */ 85141cc406Sopenharmony_ci 86141cc406Sopenharmony_cistruct mode_param mode_params[] = { 87141cc406Sopenharmony_ci {0, 0x00, 0x30, 1}, 88141cc406Sopenharmony_ci {0, 0x00, 0x30, 8}, 89141cc406Sopenharmony_ci {1, 0x02, 0x00, 8}, 90141cc406Sopenharmony_ci {0, 0x00, 0x30, 1} 91141cc406Sopenharmony_ci}; 92141cc406Sopenharmony_ci 93141cc406Sopenharmony_cistatic SANE_String_Const mode_list[] = { 94141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_LINEART, 95141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_GRAY, 96141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_COLOR, 97141cc406Sopenharmony_ci#ifdef SANE_FRAME_IR 98141cc406Sopenharmony_ci SANE_I18N("Infrared"), 99141cc406Sopenharmony_ci#endif 100141cc406Sopenharmony_ci NULL 101141cc406Sopenharmony_ci}; 102141cc406Sopenharmony_ci 103141cc406Sopenharmony_cistatic const SANE_String_Const adf_mode_list[] = { 104141cc406Sopenharmony_ci SANE_I18N("Simplex"), 105141cc406Sopenharmony_ci SANE_I18N("Duplex"), 106141cc406Sopenharmony_ci NULL 107141cc406Sopenharmony_ci}; 108141cc406Sopenharmony_ci 109141cc406Sopenharmony_ci/* Define the different scan sources */ 110141cc406Sopenharmony_ci 111141cc406Sopenharmony_ci#define FBF_STR SANE_I18N("Flatbed") 112141cc406Sopenharmony_ci#define TPU_STR SANE_I18N("Transparency Unit") 113141cc406Sopenharmony_ci#define TPU_STR2 SANE_I18N("TPU8x10") 114141cc406Sopenharmony_ci#define ADF_STR SANE_I18N("Automatic Document Feeder") 115141cc406Sopenharmony_ci 116141cc406Sopenharmony_ci/* 117141cc406Sopenharmony_ci * source list need one dummy entry (save device settings is crashing). 118141cc406Sopenharmony_ci * NOTE: no const - this list gets created while exploring the capabilities 119141cc406Sopenharmony_ci * of the scanner. 120141cc406Sopenharmony_ci */ 121141cc406Sopenharmony_ci 122141cc406Sopenharmony_ciSANE_String_Const source_list[] = { 123141cc406Sopenharmony_ci FBF_STR, 124141cc406Sopenharmony_ci NULL, 125141cc406Sopenharmony_ci NULL, 126141cc406Sopenharmony_ci NULL 127141cc406Sopenharmony_ci}; 128141cc406Sopenharmony_ci 129141cc406Sopenharmony_cistatic const SANE_String_Const film_list[] = { 130141cc406Sopenharmony_ci SANE_I18N("Positive Film"), 131141cc406Sopenharmony_ci SANE_I18N("Negative Film"), 132141cc406Sopenharmony_ci SANE_I18N("Positive Slide"), 133141cc406Sopenharmony_ci SANE_I18N("Negative Slide"), 134141cc406Sopenharmony_ci NULL 135141cc406Sopenharmony_ci}; 136141cc406Sopenharmony_ci 137141cc406Sopenharmony_ci#define HALFTONE_NONE 0x01 138141cc406Sopenharmony_ci#define HALFTONE_TET 0x03 139141cc406Sopenharmony_ci 140141cc406Sopenharmony_ciconst int halftone_params[] = { 141141cc406Sopenharmony_ci HALFTONE_NONE, 142141cc406Sopenharmony_ci 0x00, 143141cc406Sopenharmony_ci 0x10, 144141cc406Sopenharmony_ci 0x20, 145141cc406Sopenharmony_ci 0x80, 146141cc406Sopenharmony_ci 0x90, 147141cc406Sopenharmony_ci 0xa0, 148141cc406Sopenharmony_ci 0xb0, 149141cc406Sopenharmony_ci HALFTONE_TET, 150141cc406Sopenharmony_ci 0xc0, 151141cc406Sopenharmony_ci 0xd0 152141cc406Sopenharmony_ci}; 153141cc406Sopenharmony_ci 154141cc406Sopenharmony_cistatic const SANE_String_Const halftone_list[] = { 155141cc406Sopenharmony_ci SANE_I18N("None"), 156141cc406Sopenharmony_ci SANE_I18N("Halftone A (Hard Tone)"), 157141cc406Sopenharmony_ci SANE_I18N("Halftone B (Soft Tone)"), 158141cc406Sopenharmony_ci SANE_I18N("Halftone C (Net Screen)"), 159141cc406Sopenharmony_ci NULL 160141cc406Sopenharmony_ci}; 161141cc406Sopenharmony_ci 162141cc406Sopenharmony_cistatic const SANE_String_Const halftone_list_4[] = { 163141cc406Sopenharmony_ci SANE_I18N("None"), 164141cc406Sopenharmony_ci SANE_I18N("Halftone A (Hard Tone)"), 165141cc406Sopenharmony_ci SANE_I18N("Halftone B (Soft Tone)"), 166141cc406Sopenharmony_ci SANE_I18N("Halftone C (Net Screen)"), 167141cc406Sopenharmony_ci SANE_I18N("Dither A (4x4 Bayer)"), 168141cc406Sopenharmony_ci SANE_I18N("Dither B (4x4 Spiral)"), 169141cc406Sopenharmony_ci SANE_I18N("Dither C (4x4 Net Screen)"), 170141cc406Sopenharmony_ci SANE_I18N("Dither D (8x4 Net Screen)"), 171141cc406Sopenharmony_ci NULL 172141cc406Sopenharmony_ci}; 173141cc406Sopenharmony_ci 174141cc406Sopenharmony_cistatic const SANE_String_Const halftone_list_7[] = { 175141cc406Sopenharmony_ci SANE_I18N("None"), 176141cc406Sopenharmony_ci SANE_I18N("Halftone A (Hard Tone)"), 177141cc406Sopenharmony_ci SANE_I18N("Halftone B (Soft Tone)"), 178141cc406Sopenharmony_ci SANE_I18N("Halftone C (Net Screen)"), 179141cc406Sopenharmony_ci SANE_I18N("Dither A (4x4 Bayer)"), 180141cc406Sopenharmony_ci SANE_I18N("Dither B (4x4 Spiral)"), 181141cc406Sopenharmony_ci SANE_I18N("Dither C (4x4 Net Screen)"), 182141cc406Sopenharmony_ci SANE_I18N("Dither D (8x4 Net Screen)"), 183141cc406Sopenharmony_ci SANE_I18N("Text Enhanced Technology"), 184141cc406Sopenharmony_ci SANE_I18N("Download pattern A"), 185141cc406Sopenharmony_ci SANE_I18N("Download pattern B"), 186141cc406Sopenharmony_ci NULL 187141cc406Sopenharmony_ci}; 188141cc406Sopenharmony_ci 189141cc406Sopenharmony_cistatic const SANE_String_Const dropout_list[] = { 190141cc406Sopenharmony_ci SANE_I18N("None"), 191141cc406Sopenharmony_ci SANE_I18N("Red"), 192141cc406Sopenharmony_ci SANE_I18N("Green"), 193141cc406Sopenharmony_ci SANE_I18N("Blue"), 194141cc406Sopenharmony_ci NULL 195141cc406Sopenharmony_ci}; 196141cc406Sopenharmony_ci 197141cc406Sopenharmony_cistatic const SANE_Bool correction_userdefined[] = { 198141cc406Sopenharmony_ci SANE_FALSE, 199141cc406Sopenharmony_ci SANE_TRUE, 200141cc406Sopenharmony_ci SANE_TRUE, 201141cc406Sopenharmony_ci}; 202141cc406Sopenharmony_ci 203141cc406Sopenharmony_cistatic const SANE_String_Const correction_list[] = { 204141cc406Sopenharmony_ci SANE_I18N("None"), 205141cc406Sopenharmony_ci SANE_I18N("Built in CCT profile"), 206141cc406Sopenharmony_ci SANE_I18N("User defined CCT profile"), 207141cc406Sopenharmony_ci NULL 208141cc406Sopenharmony_ci}; 209141cc406Sopenharmony_ci 210141cc406Sopenharmony_cienum { 211141cc406Sopenharmony_ci CORR_NONE, CORR_AUTO, CORR_USER 212141cc406Sopenharmony_ci}; 213141cc406Sopenharmony_ci 214141cc406Sopenharmony_cistatic const SANE_String_Const cct_mode_list[] = { 215141cc406Sopenharmony_ci "Automatic", 216141cc406Sopenharmony_ci "Reflective", 217141cc406Sopenharmony_ci "Colour negatives", 218141cc406Sopenharmony_ci "Monochrome negatives", 219141cc406Sopenharmony_ci "Colour positives", 220141cc406Sopenharmony_ci NULL 221141cc406Sopenharmony_ci}; 222141cc406Sopenharmony_ci 223141cc406Sopenharmony_cienum { 224141cc406Sopenharmony_ci CCT_AUTO, CCT_REFLECTIVE, CCT_COLORNEG, CCT_MONONEG, 225141cc406Sopenharmony_ci CCT_COLORPOS 226141cc406Sopenharmony_ci}; 227141cc406Sopenharmony_ci 228141cc406Sopenharmony_ci/* 229141cc406Sopenharmony_ci * Gamma correction: 230141cc406Sopenharmony_ci * The A and B level scanners work differently than the D level scanners, 231141cc406Sopenharmony_ci * therefore I define two different sets of arrays, plus one set of 232141cc406Sopenharmony_ci * variables that get set to the actually used params and list arrays at runtime. 233141cc406Sopenharmony_ci */ 234141cc406Sopenharmony_ci 235141cc406Sopenharmony_cistatic int gamma_params_ab[] = { 236141cc406Sopenharmony_ci 0x01, 237141cc406Sopenharmony_ci 0x03, 238141cc406Sopenharmony_ci 0x00, 239141cc406Sopenharmony_ci 0x10, 240141cc406Sopenharmony_ci 0x20 241141cc406Sopenharmony_ci}; 242141cc406Sopenharmony_ci 243141cc406Sopenharmony_cistatic const SANE_String_Const gamma_list_ab[] = { 244141cc406Sopenharmony_ci SANE_I18N("Default"), 245141cc406Sopenharmony_ci SANE_I18N("User defined"), 246141cc406Sopenharmony_ci SANE_I18N("High density printing"), 247141cc406Sopenharmony_ci SANE_I18N("Low density printing"), 248141cc406Sopenharmony_ci SANE_I18N("High contrast printing"), 249141cc406Sopenharmony_ci NULL 250141cc406Sopenharmony_ci}; 251141cc406Sopenharmony_ci 252141cc406Sopenharmony_cistatic SANE_Bool gamma_userdefined_ab[] = { 253141cc406Sopenharmony_ci SANE_FALSE, 254141cc406Sopenharmony_ci SANE_TRUE, 255141cc406Sopenharmony_ci SANE_FALSE, 256141cc406Sopenharmony_ci SANE_FALSE, 257141cc406Sopenharmony_ci SANE_FALSE, 258141cc406Sopenharmony_ci}; 259141cc406Sopenharmony_ci 260141cc406Sopenharmony_cistatic int gamma_params_d[] = { 261141cc406Sopenharmony_ci 0x03, 262141cc406Sopenharmony_ci 0x04 263141cc406Sopenharmony_ci}; 264141cc406Sopenharmony_ci 265141cc406Sopenharmony_cistatic const SANE_String_Const gamma_list_d[] = { 266141cc406Sopenharmony_ci SANE_I18N("User defined (Gamma=1.0)"), 267141cc406Sopenharmony_ci SANE_I18N("User defined (Gamma=1.8)"), 268141cc406Sopenharmony_ci NULL 269141cc406Sopenharmony_ci}; 270141cc406Sopenharmony_ci 271141cc406Sopenharmony_cistatic SANE_Bool gamma_userdefined_d[] = { 272141cc406Sopenharmony_ci SANE_TRUE, 273141cc406Sopenharmony_ci SANE_TRUE 274141cc406Sopenharmony_ci}; 275141cc406Sopenharmony_ci 276141cc406Sopenharmony_cistatic SANE_Bool *gamma_userdefined; 277141cc406Sopenharmony_ciint *gamma_params; 278141cc406Sopenharmony_ci 279141cc406Sopenharmony_ci/* Bay list: 280141cc406Sopenharmony_ci * this is used for the FilmScan 281141cc406Sopenharmony_ci * XXX Add APS loader support 282141cc406Sopenharmony_ci */ 283141cc406Sopenharmony_ci 284141cc406Sopenharmony_cistatic const SANE_String_Const bay_list[] = { 285141cc406Sopenharmony_ci "1", 286141cc406Sopenharmony_ci "2", 287141cc406Sopenharmony_ci "3", 288141cc406Sopenharmony_ci "4", 289141cc406Sopenharmony_ci "5", 290141cc406Sopenharmony_ci "6", 291141cc406Sopenharmony_ci NULL 292141cc406Sopenharmony_ci}; 293141cc406Sopenharmony_ci 294141cc406Sopenharmony_ci/* minimum, maximum, quantization */ 295141cc406Sopenharmony_cistatic const SANE_Range focus_range = { 0, 254, 0 }; 296141cc406Sopenharmony_cistatic const SANE_Range u8_range = { 0, 255, 0 }; 297141cc406Sopenharmony_cistatic const SANE_Range fx_range = { SANE_FIX(-2.0), SANE_FIX(2.0), 0 }; 298141cc406Sopenharmony_cistatic const SANE_Range outline_emphasis_range = { -2, 2, 0 }; 299141cc406Sopenharmony_ci 300141cc406Sopenharmony_ci/* 301141cc406Sopenharmony_ci * List of pointers to devices - will be dynamically allocated depending 302141cc406Sopenharmony_ci * on the number of devices found. 303141cc406Sopenharmony_ci */ 304141cc406Sopenharmony_cistatic const SANE_Device **devlist; 305141cc406Sopenharmony_ci 306141cc406Sopenharmony_ci 307141cc406Sopenharmony_ci/* Some utility functions */ 308141cc406Sopenharmony_ci 309141cc406Sopenharmony_cistatic size_t 310141cc406Sopenharmony_cimax_string_size(const SANE_String_Const strings[]) 311141cc406Sopenharmony_ci{ 312141cc406Sopenharmony_ci size_t size, max_size = 0; 313141cc406Sopenharmony_ci int i; 314141cc406Sopenharmony_ci 315141cc406Sopenharmony_ci for (i = 0; strings[i]; i++) { 316141cc406Sopenharmony_ci size = strlen(strings[i]) + 1; 317141cc406Sopenharmony_ci if (size > max_size) 318141cc406Sopenharmony_ci max_size = size; 319141cc406Sopenharmony_ci } 320141cc406Sopenharmony_ci return max_size; 321141cc406Sopenharmony_ci} 322141cc406Sopenharmony_ci 323141cc406Sopenharmony_cistatic SANE_Status attach_one_usb(SANE_String_Const devname); 324141cc406Sopenharmony_cistatic SANE_Status attach_one_net(SANE_String_Const devname); 325141cc406Sopenharmony_ci 326141cc406Sopenharmony_cistatic void 327141cc406Sopenharmony_ciprint_params(const SANE_Parameters params) 328141cc406Sopenharmony_ci{ 329141cc406Sopenharmony_ci DBG(6, "params.format = %d\n", params.format); 330141cc406Sopenharmony_ci DBG(6, "params.last_frame = %d\n", params.last_frame); 331141cc406Sopenharmony_ci DBG(6, "params.bytes_per_line = %d\n", params.bytes_per_line); 332141cc406Sopenharmony_ci DBG(6, "params.pixels_per_line = %d\n", params.pixels_per_line); 333141cc406Sopenharmony_ci DBG(6, "params.lines = %d\n", params.lines); 334141cc406Sopenharmony_ci DBG(6, "params.depth = %d\n", params.depth); 335141cc406Sopenharmony_ci} 336141cc406Sopenharmony_ci 337141cc406Sopenharmony_ci/* 338141cc406Sopenharmony_ci * close_scanner() 339141cc406Sopenharmony_ci * 340141cc406Sopenharmony_ci * Close the open scanner. Depending on the connection method, a different 341141cc406Sopenharmony_ci * close function is called. 342141cc406Sopenharmony_ci */ 343141cc406Sopenharmony_ci 344141cc406Sopenharmony_cistatic void 345141cc406Sopenharmony_ciclose_scanner(Epson_Scanner *s) 346141cc406Sopenharmony_ci{ 347141cc406Sopenharmony_ci int i; 348141cc406Sopenharmony_ci 349141cc406Sopenharmony_ci DBG(7, "%s: fd = %d\n", __func__, s->fd); 350141cc406Sopenharmony_ci 351141cc406Sopenharmony_ci if (s->fd == -1) 352141cc406Sopenharmony_ci goto free; 353141cc406Sopenharmony_ci 354141cc406Sopenharmony_ci /* send a request_status. This toggles w_cmd_count and r_cmd_count */ 355141cc406Sopenharmony_ci if (r_cmd_count % 2) 356141cc406Sopenharmony_ci esci_request_status(s, NULL); 357141cc406Sopenharmony_ci 358141cc406Sopenharmony_ci /* request extended status. This toggles w_cmd_count only */ 359141cc406Sopenharmony_ci if (w_cmd_count % 2) 360141cc406Sopenharmony_ci esci_request_extended_status(s, NULL, NULL); 361141cc406Sopenharmony_ci 362141cc406Sopenharmony_ci if (s->hw->connection == SANE_EPSON_NET) { 363141cc406Sopenharmony_ci sanei_epson_net_unlock(s); 364141cc406Sopenharmony_ci sanei_tcp_close(s->fd); 365141cc406Sopenharmony_ci } else if (s->hw->connection == SANE_EPSON_SCSI) { 366141cc406Sopenharmony_ci sanei_scsi_close(s->fd); 367141cc406Sopenharmony_ci } else if (s->hw->connection == SANE_EPSON_PIO) { 368141cc406Sopenharmony_ci sanei_pio_close(s->fd); 369141cc406Sopenharmony_ci } else if (s->hw->connection == SANE_EPSON_USB) { 370141cc406Sopenharmony_ci sanei_usb_close(s->fd); 371141cc406Sopenharmony_ci } 372141cc406Sopenharmony_ci 373141cc406Sopenharmony_ci s->fd = -1; 374141cc406Sopenharmony_ci 375141cc406Sopenharmony_cifree: 376141cc406Sopenharmony_ci for (i = 0; i < LINES_SHUFFLE_MAX; i++) { 377141cc406Sopenharmony_ci if (s->line_buffer[i] != NULL) 378141cc406Sopenharmony_ci free(s->line_buffer[i]); 379141cc406Sopenharmony_ci } 380141cc406Sopenharmony_ci 381141cc406Sopenharmony_ci free(s); 382141cc406Sopenharmony_ci} 383141cc406Sopenharmony_ci 384141cc406Sopenharmony_cistatic void 385141cc406Sopenharmony_cie2_network_discovery(void) 386141cc406Sopenharmony_ci{ 387141cc406Sopenharmony_ci fd_set rfds; 388141cc406Sopenharmony_ci int fd, len; 389141cc406Sopenharmony_ci SANE_Status status; 390141cc406Sopenharmony_ci 391141cc406Sopenharmony_ci char *ip, *query = "EPSONP\x00\xff\x00\x00\x00\x00\x00\x00\x00"; 392141cc406Sopenharmony_ci unsigned char buf[76]; 393141cc406Sopenharmony_ci 394141cc406Sopenharmony_ci struct timeval to; 395141cc406Sopenharmony_ci 396141cc406Sopenharmony_ci status = sanei_udp_open_broadcast(&fd); 397141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 398141cc406Sopenharmony_ci return; 399141cc406Sopenharmony_ci 400141cc406Sopenharmony_ci sanei_udp_write_broadcast(fd, 3289, (unsigned char *) query, 15); 401141cc406Sopenharmony_ci 402141cc406Sopenharmony_ci DBG(5, "%s, sent discovery packet\n", __func__); 403141cc406Sopenharmony_ci 404141cc406Sopenharmony_ci to.tv_sec = 1; 405141cc406Sopenharmony_ci to.tv_usec = 0; 406141cc406Sopenharmony_ci 407141cc406Sopenharmony_ci FD_ZERO(&rfds); 408141cc406Sopenharmony_ci FD_SET(fd, &rfds); 409141cc406Sopenharmony_ci 410141cc406Sopenharmony_ci sanei_udp_set_nonblock(fd, SANE_TRUE); 411141cc406Sopenharmony_ci while (select(fd + 1, &rfds, NULL, NULL, &to) > 0) { 412141cc406Sopenharmony_ci if ((len = sanei_udp_recvfrom(fd, buf, 76, &ip)) == 76) { 413141cc406Sopenharmony_ci DBG(5, " response from %s\n", ip); 414141cc406Sopenharmony_ci 415141cc406Sopenharmony_ci /* minimal check, protocol unknown */ 416141cc406Sopenharmony_ci if (strncmp((char *) buf, "EPSON", 5) == 0) 417141cc406Sopenharmony_ci attach_one_net(ip); 418141cc406Sopenharmony_ci } 419141cc406Sopenharmony_ci } 420141cc406Sopenharmony_ci 421141cc406Sopenharmony_ci DBG(5, "%s, end\n", __func__); 422141cc406Sopenharmony_ci 423141cc406Sopenharmony_ci sanei_udp_close(fd); 424141cc406Sopenharmony_ci} 425141cc406Sopenharmony_ci 426141cc406Sopenharmony_ci/* 427141cc406Sopenharmony_ci * open_scanner() 428141cc406Sopenharmony_ci * 429141cc406Sopenharmony_ci * Open the scanner device. Depending on the connection method, 430141cc406Sopenharmony_ci * different open functions are called. 431141cc406Sopenharmony_ci */ 432141cc406Sopenharmony_ci 433141cc406Sopenharmony_cistatic SANE_Status 434141cc406Sopenharmony_ciopen_scanner(Epson_Scanner *s) 435141cc406Sopenharmony_ci{ 436141cc406Sopenharmony_ci SANE_Status status = 0; 437141cc406Sopenharmony_ci 438141cc406Sopenharmony_ci DBG(7, "%s: %s\n", __func__, s->hw->sane.name); 439141cc406Sopenharmony_ci 440141cc406Sopenharmony_ci if (s->fd != -1) { 441141cc406Sopenharmony_ci DBG(5, "scanner is already open: fd = %d\n", s->fd); 442141cc406Sopenharmony_ci return SANE_STATUS_GOOD; /* no need to open the scanner */ 443141cc406Sopenharmony_ci } 444141cc406Sopenharmony_ci 445141cc406Sopenharmony_ci if (s->hw->connection == SANE_EPSON_NET) { 446141cc406Sopenharmony_ci unsigned char buf[5]; 447141cc406Sopenharmony_ci 448141cc406Sopenharmony_ci /* device name has the form net:ipaddr */ 449141cc406Sopenharmony_ci status = sanei_tcp_open(&s->hw->sane.name[4], 1865, &s->fd); 450141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) { 451141cc406Sopenharmony_ci 452141cc406Sopenharmony_ci ssize_t read; 453141cc406Sopenharmony_ci struct timeval tv; 454141cc406Sopenharmony_ci 455141cc406Sopenharmony_ci tv.tv_sec = 5; 456141cc406Sopenharmony_ci tv.tv_usec = 0; 457141cc406Sopenharmony_ci 458141cc406Sopenharmony_ci setsockopt(s->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); 459141cc406Sopenharmony_ci 460141cc406Sopenharmony_ci s->netlen = 0; 461141cc406Sopenharmony_ci 462141cc406Sopenharmony_ci DBG(32, "awaiting welcome message\n"); 463141cc406Sopenharmony_ci 464141cc406Sopenharmony_ci /* the scanner sends a kind of welcome msg */ 465141cc406Sopenharmony_ci read = e2_recv(s, buf, 5, &status); 466141cc406Sopenharmony_ci if (read != 5) { 467141cc406Sopenharmony_ci sanei_tcp_close(s->fd); 468141cc406Sopenharmony_ci s->fd = -1; 469141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 470141cc406Sopenharmony_ci } 471141cc406Sopenharmony_ci 472141cc406Sopenharmony_ci DBG(32, "welcome message received, locking the scanner...\n"); 473141cc406Sopenharmony_ci 474141cc406Sopenharmony_ci /* lock the scanner for use by sane */ 475141cc406Sopenharmony_ci status = sanei_epson_net_lock(s); 476141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 477141cc406Sopenharmony_ci DBG(1, "%s cannot lock scanner: %s\n", s->hw->sane.name, 478141cc406Sopenharmony_ci sane_strstatus(status)); 479141cc406Sopenharmony_ci 480141cc406Sopenharmony_ci sanei_tcp_close(s->fd); 481141cc406Sopenharmony_ci s->fd = -1; 482141cc406Sopenharmony_ci 483141cc406Sopenharmony_ci return status; 484141cc406Sopenharmony_ci } 485141cc406Sopenharmony_ci 486141cc406Sopenharmony_ci DBG(32, "scanner locked\n"); 487141cc406Sopenharmony_ci } 488141cc406Sopenharmony_ci 489141cc406Sopenharmony_ci } else if (s->hw->connection == SANE_EPSON_SCSI) 490141cc406Sopenharmony_ci status = sanei_scsi_open(s->hw->sane.name, &s->fd, 491141cc406Sopenharmony_ci sanei_epson2_scsi_sense_handler, 492141cc406Sopenharmony_ci NULL); 493141cc406Sopenharmony_ci else if (s->hw->connection == SANE_EPSON_PIO) 494141cc406Sopenharmony_ci /* device name has the form pio:0xnnn */ 495141cc406Sopenharmony_ci status = sanei_pio_open(&s->hw->sane.name[4], &s->fd); 496141cc406Sopenharmony_ci 497141cc406Sopenharmony_ci else if (s->hw->connection == SANE_EPSON_USB) 498141cc406Sopenharmony_ci status = sanei_usb_open(s->hw->sane.name, &s->fd); 499141cc406Sopenharmony_ci 500141cc406Sopenharmony_ci if (status == SANE_STATUS_ACCESS_DENIED) { 501141cc406Sopenharmony_ci DBG(1, "please check that you have permissions on the device.\n"); 502141cc406Sopenharmony_ci DBG(1, "if this is a multi-function device with a printer,\n"); 503141cc406Sopenharmony_ci DBG(1, "disable any conflicting driver (like usblp).\n"); 504141cc406Sopenharmony_ci } 505141cc406Sopenharmony_ci 506141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 507141cc406Sopenharmony_ci DBG(1, "%s open failed: %s\n", s->hw->sane.name, 508141cc406Sopenharmony_ci sane_strstatus(status)); 509141cc406Sopenharmony_ci else 510141cc406Sopenharmony_ci DBG(5, "scanner opened\n"); 511141cc406Sopenharmony_ci 512141cc406Sopenharmony_ci return status; 513141cc406Sopenharmony_ci} 514141cc406Sopenharmony_ci 515141cc406Sopenharmony_cistatic SANE_Status detect_scsi(struct Epson_Scanner *s) 516141cc406Sopenharmony_ci{ 517141cc406Sopenharmony_ci SANE_Status status; 518141cc406Sopenharmony_ci struct Epson_Device *dev = s->hw; 519141cc406Sopenharmony_ci 520141cc406Sopenharmony_ci char buf[INQUIRY_BUF_SIZE + 1]; 521141cc406Sopenharmony_ci size_t buf_size = INQUIRY_BUF_SIZE; 522141cc406Sopenharmony_ci 523141cc406Sopenharmony_ci char *vendor = buf + 8; 524141cc406Sopenharmony_ci char *model = buf + 16; 525141cc406Sopenharmony_ci char *rev = buf + 32; 526141cc406Sopenharmony_ci 527141cc406Sopenharmony_ci status = sanei_epson2_scsi_inquiry(s->fd, buf, &buf_size); 528141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 529141cc406Sopenharmony_ci DBG(1, "%s: inquiry failed: %s\n", __func__, 530141cc406Sopenharmony_ci sane_strstatus(status)); 531141cc406Sopenharmony_ci return status; 532141cc406Sopenharmony_ci } 533141cc406Sopenharmony_ci 534141cc406Sopenharmony_ci buf[INQUIRY_BUF_SIZE] = 0; 535141cc406Sopenharmony_ci DBG(1, "inquiry data:\n"); 536141cc406Sopenharmony_ci DBG(1, " vendor : %.8s\n", vendor); 537141cc406Sopenharmony_ci DBG(1, " model : %.16s\n", model); 538141cc406Sopenharmony_ci DBG(1, " revision: %.4s\n", rev); 539141cc406Sopenharmony_ci 540141cc406Sopenharmony_ci if (buf[0] != TYPE_PROCESSOR) { 541141cc406Sopenharmony_ci DBG(1, "%s: device is not of processor type (%d)\n", 542141cc406Sopenharmony_ci __func__, buf[0]); 543141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 544141cc406Sopenharmony_ci } 545141cc406Sopenharmony_ci 546141cc406Sopenharmony_ci if (strncmp(vendor, "EPSON", 5) != 0) { 547141cc406Sopenharmony_ci DBG(1, 548141cc406Sopenharmony_ci "%s: device doesn't look like an EPSON scanner\n", 549141cc406Sopenharmony_ci __func__); 550141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 551141cc406Sopenharmony_ci } 552141cc406Sopenharmony_ci 553141cc406Sopenharmony_ci if (strncmp(model, "SCANNER ", 8) != 0 554141cc406Sopenharmony_ci && strncmp(model, "FilmScan 200", 12) != 0 555141cc406Sopenharmony_ci && strncmp(model, "Perfection", 10) != 0 556141cc406Sopenharmony_ci && strncmp(model, "Expression", 10) != 0 557141cc406Sopenharmony_ci && strncmp(model, "GT", 2) != 0) { 558141cc406Sopenharmony_ci DBG(1, "%s: this EPSON scanner is not supported\n", 559141cc406Sopenharmony_ci __func__); 560141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 561141cc406Sopenharmony_ci } 562141cc406Sopenharmony_ci 563141cc406Sopenharmony_ci if (strncmp(model, "FilmScan 200", 12) == 0) { 564141cc406Sopenharmony_ci dev->sane.type = "film scanner"; 565141cc406Sopenharmony_ci e2_set_model(s, (unsigned char *) model, 12); 566141cc406Sopenharmony_ci } 567141cc406Sopenharmony_ci 568141cc406Sopenharmony_ci /* Issue a test unit ready SCSI command. The FilmScan 200 569141cc406Sopenharmony_ci * requires it for a sort of "wake up". We might eventually 570141cc406Sopenharmony_ci * get the return code and reissue it in case of failure. 571141cc406Sopenharmony_ci */ 572141cc406Sopenharmony_ci sanei_epson2_scsi_test_unit_ready(s->fd); 573141cc406Sopenharmony_ci 574141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 575141cc406Sopenharmony_ci} 576141cc406Sopenharmony_ci 577141cc406Sopenharmony_cistatic SANE_Status 578141cc406Sopenharmony_cidetect_usb(struct Epson_Scanner *s, SANE_Bool assume_valid) 579141cc406Sopenharmony_ci{ 580141cc406Sopenharmony_ci SANE_Status status; 581141cc406Sopenharmony_ci int vendor, product; 582141cc406Sopenharmony_ci int i, numIds; 583141cc406Sopenharmony_ci SANE_Bool is_valid = assume_valid; 584141cc406Sopenharmony_ci 585141cc406Sopenharmony_ci /* if the sanei_usb_get_vendor_product call is not supported, 586141cc406Sopenharmony_ci * then we just ignore this and rely on the user to config 587141cc406Sopenharmony_ci * the correct device. 588141cc406Sopenharmony_ci */ 589141cc406Sopenharmony_ci 590141cc406Sopenharmony_ci status = sanei_usb_get_vendor_product(s->fd, &vendor, &product); 591141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 592141cc406Sopenharmony_ci DBG(1, "the device cannot be verified - will continue\n"); 593141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 594141cc406Sopenharmony_ci } 595141cc406Sopenharmony_ci 596141cc406Sopenharmony_ci /* check the vendor ID to see if we are dealing with an EPSON device */ 597141cc406Sopenharmony_ci if (vendor != SANE_EPSON_VENDOR_ID) { 598141cc406Sopenharmony_ci /* this is not a supported vendor ID */ 599141cc406Sopenharmony_ci DBG(1, "not an Epson device at %s (vendor id=0x%x)\n", 600141cc406Sopenharmony_ci s->hw->sane.name, vendor); 601141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 602141cc406Sopenharmony_ci } 603141cc406Sopenharmony_ci 604141cc406Sopenharmony_ci numIds = sanei_epson_getNumberOfUSBProductIds(); 605141cc406Sopenharmony_ci i = 0; 606141cc406Sopenharmony_ci 607141cc406Sopenharmony_ci /* check all known product IDs to verify that we know 608141cc406Sopenharmony_ci about the device */ 609141cc406Sopenharmony_ci while (i != numIds) { 610141cc406Sopenharmony_ci if (product == sanei_epson_usb_product_ids[i]) { 611141cc406Sopenharmony_ci is_valid = SANE_TRUE; 612141cc406Sopenharmony_ci break; 613141cc406Sopenharmony_ci } 614141cc406Sopenharmony_ci i++; 615141cc406Sopenharmony_ci } 616141cc406Sopenharmony_ci 617141cc406Sopenharmony_ci if (is_valid == SANE_FALSE) { 618141cc406Sopenharmony_ci DBG(1, "the device at %s is not supported (product id=0x%x)\n", 619141cc406Sopenharmony_ci s->hw->sane.name, product); 620141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 621141cc406Sopenharmony_ci } 622141cc406Sopenharmony_ci 623141cc406Sopenharmony_ci DBG(1, "found valid Epson scanner: 0x%x/0x%x (vendorID/productID)\n", 624141cc406Sopenharmony_ci vendor, product); 625141cc406Sopenharmony_ci 626141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 627141cc406Sopenharmony_ci} 628141cc406Sopenharmony_ci 629141cc406Sopenharmony_cistatic int num_devices; /* number of scanners attached to backend */ 630141cc406Sopenharmony_cistatic Epson_Device *first_dev; /* first EPSON scanner in list */ 631141cc406Sopenharmony_ci 632141cc406Sopenharmony_cistatic struct Epson_Scanner * 633141cc406Sopenharmony_ciscanner_create(struct Epson_Device *dev, SANE_Status *status) 634141cc406Sopenharmony_ci{ 635141cc406Sopenharmony_ci struct Epson_Scanner *s; 636141cc406Sopenharmony_ci 637141cc406Sopenharmony_ci s = malloc(sizeof(struct Epson_Scanner)); 638141cc406Sopenharmony_ci if (s == NULL) { 639141cc406Sopenharmony_ci *status = SANE_STATUS_NO_MEM; 640141cc406Sopenharmony_ci return NULL; 641141cc406Sopenharmony_ci } 642141cc406Sopenharmony_ci 643141cc406Sopenharmony_ci memset(s, 0x00, sizeof(struct Epson_Scanner)); 644141cc406Sopenharmony_ci 645141cc406Sopenharmony_ci s->fd = -1; 646141cc406Sopenharmony_ci s->hw = dev; 647141cc406Sopenharmony_ci 648141cc406Sopenharmony_ci return s; 649141cc406Sopenharmony_ci} 650141cc406Sopenharmony_ci 651141cc406Sopenharmony_cistatic struct Epson_Scanner * 652141cc406Sopenharmony_cidevice_detect(const char *name, int type, SANE_Bool assume_valid, SANE_Status *status) 653141cc406Sopenharmony_ci{ 654141cc406Sopenharmony_ci struct Epson_Scanner *s; 655141cc406Sopenharmony_ci struct Epson_Device *dev; 656141cc406Sopenharmony_ci 657141cc406Sopenharmony_ci /* try to find the device in our list */ 658141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) { 659141cc406Sopenharmony_ci if (strcmp(dev->sane.name, name) == 0) { 660141cc406Sopenharmony_ci 661141cc406Sopenharmony_ci /* the device might have been just probed, 662141cc406Sopenharmony_ci * sleep a bit. 663141cc406Sopenharmony_ci */ 664141cc406Sopenharmony_ci if (dev->connection == SANE_EPSON_NET) 665141cc406Sopenharmony_ci sleep(1); 666141cc406Sopenharmony_ci 667141cc406Sopenharmony_ci return scanner_create(dev, status); 668141cc406Sopenharmony_ci } 669141cc406Sopenharmony_ci } 670141cc406Sopenharmony_ci 671141cc406Sopenharmony_ci if (type == SANE_EPSON_NODEV) { 672141cc406Sopenharmony_ci *status = SANE_STATUS_INVAL; 673141cc406Sopenharmony_ci return NULL; 674141cc406Sopenharmony_ci } 675141cc406Sopenharmony_ci 676141cc406Sopenharmony_ci /* alloc and clear our device structure */ 677141cc406Sopenharmony_ci dev = malloc(sizeof(*dev)); 678141cc406Sopenharmony_ci if (!dev) { 679141cc406Sopenharmony_ci *status = SANE_STATUS_NO_MEM; 680141cc406Sopenharmony_ci return NULL; 681141cc406Sopenharmony_ci } 682141cc406Sopenharmony_ci memset(dev, 0x00, sizeof(struct Epson_Device)); 683141cc406Sopenharmony_ci 684141cc406Sopenharmony_ci s = scanner_create(dev, status); 685141cc406Sopenharmony_ci if (s == NULL) 686141cc406Sopenharmony_ci return NULL; 687141cc406Sopenharmony_ci 688141cc406Sopenharmony_ci e2_dev_init(dev, name, type); 689141cc406Sopenharmony_ci 690141cc406Sopenharmony_ci *status = open_scanner(s); 691141cc406Sopenharmony_ci if (*status != SANE_STATUS_GOOD) { 692141cc406Sopenharmony_ci free(s); 693141cc406Sopenharmony_ci return NULL; 694141cc406Sopenharmony_ci } 695141cc406Sopenharmony_ci 696141cc406Sopenharmony_ci /* from now on, close_scanner() must be called */ 697141cc406Sopenharmony_ci 698141cc406Sopenharmony_ci /* SCSI and USB requires special care */ 699141cc406Sopenharmony_ci if (dev->connection == SANE_EPSON_SCSI) { 700141cc406Sopenharmony_ci 701141cc406Sopenharmony_ci *status = detect_scsi(s); 702141cc406Sopenharmony_ci 703141cc406Sopenharmony_ci } else if (dev->connection == SANE_EPSON_USB) { 704141cc406Sopenharmony_ci 705141cc406Sopenharmony_ci *status = detect_usb(s, assume_valid); 706141cc406Sopenharmony_ci } 707141cc406Sopenharmony_ci 708141cc406Sopenharmony_ci if (*status != SANE_STATUS_GOOD) 709141cc406Sopenharmony_ci goto close; 710141cc406Sopenharmony_ci 711141cc406Sopenharmony_ci /* set name and model (if not already set) */ 712141cc406Sopenharmony_ci if (dev->model == NULL) 713141cc406Sopenharmony_ci e2_set_model(s, (unsigned char *) "generic", 7); 714141cc406Sopenharmony_ci 715141cc406Sopenharmony_ci dev->name = strdup(name); 716141cc406Sopenharmony_ci dev->sane.name = dev->name; 717141cc406Sopenharmony_ci 718141cc406Sopenharmony_ci /* ESC @, reset */ 719141cc406Sopenharmony_ci *status = esci_reset(s); 720141cc406Sopenharmony_ci if (*status != SANE_STATUS_GOOD) 721141cc406Sopenharmony_ci goto close; 722141cc406Sopenharmony_ci 723141cc406Sopenharmony_ci *status = e2_discover_capabilities(s); 724141cc406Sopenharmony_ci if (*status != SANE_STATUS_GOOD) 725141cc406Sopenharmony_ci goto close; 726141cc406Sopenharmony_ci 727141cc406Sopenharmony_ci if (source_list[0] == NULL || dev->dpi_range.min == 0) { 728141cc406Sopenharmony_ci DBG(1, "something is wrong in the discovery process, aborting.\n"); 729141cc406Sopenharmony_ci *status = SANE_STATUS_IO_ERROR; 730141cc406Sopenharmony_ci goto close; 731141cc406Sopenharmony_ci } 732141cc406Sopenharmony_ci 733141cc406Sopenharmony_ci e2_dev_post_init(dev); 734141cc406Sopenharmony_ci 735141cc406Sopenharmony_ci *status = esci_reset(s); 736141cc406Sopenharmony_ci if (*status != SANE_STATUS_GOOD) 737141cc406Sopenharmony_ci goto close; 738141cc406Sopenharmony_ci 739141cc406Sopenharmony_ci DBG(1, "scanner model: %s\n", dev->model); 740141cc406Sopenharmony_ci 741141cc406Sopenharmony_ci /* add this scanner to the device list */ 742141cc406Sopenharmony_ci 743141cc406Sopenharmony_ci num_devices++; 744141cc406Sopenharmony_ci dev->next = first_dev; 745141cc406Sopenharmony_ci first_dev = dev; 746141cc406Sopenharmony_ci 747141cc406Sopenharmony_ci return s; 748141cc406Sopenharmony_ci 749141cc406Sopenharmony_ciclose: 750141cc406Sopenharmony_ci close_scanner(s); 751141cc406Sopenharmony_ci return NULL; 752141cc406Sopenharmony_ci} 753141cc406Sopenharmony_ci 754141cc406Sopenharmony_ci 755141cc406Sopenharmony_cistatic SANE_Status 756141cc406Sopenharmony_ciattach(const char *name, int type) 757141cc406Sopenharmony_ci{ 758141cc406Sopenharmony_ci SANE_Status status; 759141cc406Sopenharmony_ci Epson_Scanner *s; 760141cc406Sopenharmony_ci 761141cc406Sopenharmony_ci DBG(7, "%s: devname = %s, type = %d\n", __func__, name, type); 762141cc406Sopenharmony_ci 763141cc406Sopenharmony_ci s = device_detect(name, type, 0, &status); 764141cc406Sopenharmony_ci if(s == NULL) 765141cc406Sopenharmony_ci return status; 766141cc406Sopenharmony_ci 767141cc406Sopenharmony_ci close_scanner(s); 768141cc406Sopenharmony_ci return status; 769141cc406Sopenharmony_ci} 770141cc406Sopenharmony_ci 771141cc406Sopenharmony_cistatic SANE_Status 772141cc406Sopenharmony_ciattach_one_scsi(const char *dev) 773141cc406Sopenharmony_ci{ 774141cc406Sopenharmony_ci DBG(7, "%s: dev = %s\n", __func__, dev); 775141cc406Sopenharmony_ci return attach(dev, SANE_EPSON_SCSI); 776141cc406Sopenharmony_ci} 777141cc406Sopenharmony_ci 778141cc406Sopenharmony_ciSANE_Status 779141cc406Sopenharmony_ciattach_one_usb(const char *dev) 780141cc406Sopenharmony_ci{ 781141cc406Sopenharmony_ci DBG(7, "%s: dev = %s\n", __func__, dev); 782141cc406Sopenharmony_ci return attach(dev, SANE_EPSON_USB); 783141cc406Sopenharmony_ci} 784141cc406Sopenharmony_ci 785141cc406Sopenharmony_cistatic SANE_Status 786141cc406Sopenharmony_ciattach_one_net(const char *dev) 787141cc406Sopenharmony_ci{ 788141cc406Sopenharmony_ci char name[39+4]; 789141cc406Sopenharmony_ci 790141cc406Sopenharmony_ci DBG(7, "%s: dev = %s\n", __func__, dev); 791141cc406Sopenharmony_ci 792141cc406Sopenharmony_ci strcpy(name, "net:"); 793141cc406Sopenharmony_ci strcat(name, dev); 794141cc406Sopenharmony_ci return attach(name, SANE_EPSON_NET); 795141cc406Sopenharmony_ci} 796141cc406Sopenharmony_ci 797141cc406Sopenharmony_cistatic SANE_Status 798141cc406Sopenharmony_ciattach_one_pio(const char *dev) 799141cc406Sopenharmony_ci{ 800141cc406Sopenharmony_ci DBG(7, "%s: dev = %s\n", __func__, dev); 801141cc406Sopenharmony_ci return attach(dev, SANE_EPSON_PIO); 802141cc406Sopenharmony_ci} 803141cc406Sopenharmony_ci 804141cc406Sopenharmony_cistatic SANE_Status 805141cc406Sopenharmony_ciattach_one_config(SANEI_Config __sane_unused__ *config, const char *line, 806141cc406Sopenharmony_ci void *data) 807141cc406Sopenharmony_ci{ 808141cc406Sopenharmony_ci int vendor, product; 809141cc406Sopenharmony_ci SANE_Bool local_only = *(SANE_Bool*) data; 810141cc406Sopenharmony_ci int len = strlen(line); 811141cc406Sopenharmony_ci 812141cc406Sopenharmony_ci DBG(7, "%s: len = %d, line = %s\n", __func__, len, line); 813141cc406Sopenharmony_ci 814141cc406Sopenharmony_ci if (sscanf(line, "usb %i %i", &vendor, &product) == 2) { 815141cc406Sopenharmony_ci 816141cc406Sopenharmony_ci /* add the vendor and product IDs to the list of 817141cc406Sopenharmony_ci known devices before we call the attach function */ 818141cc406Sopenharmony_ci 819141cc406Sopenharmony_ci int numIds = sanei_epson_getNumberOfUSBProductIds(); 820141cc406Sopenharmony_ci 821141cc406Sopenharmony_ci if (vendor != 0x4b8) 822141cc406Sopenharmony_ci return SANE_STATUS_INVAL; /* this is not an EPSON device */ 823141cc406Sopenharmony_ci 824141cc406Sopenharmony_ci sanei_epson_usb_product_ids[numIds - 1] = product; 825141cc406Sopenharmony_ci sanei_usb_attach_matching_devices(line, attach_one_usb); 826141cc406Sopenharmony_ci 827141cc406Sopenharmony_ci } else if (strncmp(line, "usb", 3) == 0 && len == 3) { 828141cc406Sopenharmony_ci 829141cc406Sopenharmony_ci int i, numIds; 830141cc406Sopenharmony_ci 831141cc406Sopenharmony_ci numIds = sanei_epson_getNumberOfUSBProductIds(); 832141cc406Sopenharmony_ci 833141cc406Sopenharmony_ci for (i = 0; i < numIds; i++) { 834141cc406Sopenharmony_ci sanei_usb_find_devices(0x4b8, 835141cc406Sopenharmony_ci sanei_epson_usb_product_ids[i], attach_one_usb); 836141cc406Sopenharmony_ci } 837141cc406Sopenharmony_ci 838141cc406Sopenharmony_ci } else if (strncmp(line, "net", 3) == 0) { 839141cc406Sopenharmony_ci 840141cc406Sopenharmony_ci if (!local_only) { 841141cc406Sopenharmony_ci /* remove the "net" sub string */ 842141cc406Sopenharmony_ci const char *name = 843141cc406Sopenharmony_ci sanei_config_skip_whitespace(line + 3); 844141cc406Sopenharmony_ci 845141cc406Sopenharmony_ci if (strncmp(name, "autodiscovery", 13) == 0) 846141cc406Sopenharmony_ci e2_network_discovery(); 847141cc406Sopenharmony_ci else 848141cc406Sopenharmony_ci attach_one_net(name); 849141cc406Sopenharmony_ci } 850141cc406Sopenharmony_ci 851141cc406Sopenharmony_ci } else if (strncmp(line, "pio", 3) == 0) { 852141cc406Sopenharmony_ci 853141cc406Sopenharmony_ci /* remove the "pio" sub string */ 854141cc406Sopenharmony_ci const char *name = sanei_config_skip_whitespace(line + 3); 855141cc406Sopenharmony_ci 856141cc406Sopenharmony_ci attach_one_pio(name); 857141cc406Sopenharmony_ci 858141cc406Sopenharmony_ci } else { 859141cc406Sopenharmony_ci sanei_config_attach_matching_devices(line, attach_one_scsi); 860141cc406Sopenharmony_ci } 861141cc406Sopenharmony_ci 862141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 863141cc406Sopenharmony_ci} 864141cc406Sopenharmony_ci 865141cc406Sopenharmony_cistatic void 866141cc406Sopenharmony_cifree_devices(void) 867141cc406Sopenharmony_ci{ 868141cc406Sopenharmony_ci Epson_Device *dev, *next; 869141cc406Sopenharmony_ci 870141cc406Sopenharmony_ci DBG(5, "%s\n", __func__); 871141cc406Sopenharmony_ci 872141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = next) { 873141cc406Sopenharmony_ci next = dev->next; 874141cc406Sopenharmony_ci free(dev->name); 875141cc406Sopenharmony_ci free(dev->model); 876141cc406Sopenharmony_ci free(dev); 877141cc406Sopenharmony_ci } 878141cc406Sopenharmony_ci 879141cc406Sopenharmony_ci free(devlist); 880141cc406Sopenharmony_ci 881141cc406Sopenharmony_ci first_dev = NULL; 882141cc406Sopenharmony_ci} 883141cc406Sopenharmony_ci 884141cc406Sopenharmony_cistatic void 885141cc406Sopenharmony_ciprobe_devices(SANE_Bool local_only) 886141cc406Sopenharmony_ci{ 887141cc406Sopenharmony_ci DBG(5, "%s\n", __func__); 888141cc406Sopenharmony_ci 889141cc406Sopenharmony_ci free_devices(); 890141cc406Sopenharmony_ci 891141cc406Sopenharmony_ci sanei_configure_attach(EPSON2_CONFIG_FILE, NULL, 892141cc406Sopenharmony_ci attach_one_config, &local_only); 893141cc406Sopenharmony_ci} 894141cc406Sopenharmony_ci 895141cc406Sopenharmony_ciSANE_Status 896141cc406Sopenharmony_cisane_init(SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize) 897141cc406Sopenharmony_ci{ 898141cc406Sopenharmony_ci DBG_INIT(); 899141cc406Sopenharmony_ci DBG(1, "%s: version " VERSION "\n", __func__); 900141cc406Sopenharmony_ci 901141cc406Sopenharmony_ci /* Keep '124' as our build version. The arg is obsolete by now */ 902141cc406Sopenharmony_ci if (version_code) 903141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 124); 904141cc406Sopenharmony_ci 905141cc406Sopenharmony_ci sanei_usb_init(); 906141cc406Sopenharmony_ci sanei_usb_set_timeout(60 * 1000); 907141cc406Sopenharmony_ci 908141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 909141cc406Sopenharmony_ci} 910141cc406Sopenharmony_ci 911141cc406Sopenharmony_ci/* Clean up the list of attached scanners. */ 912141cc406Sopenharmony_civoid 913141cc406Sopenharmony_cisane_exit(void) 914141cc406Sopenharmony_ci{ 915141cc406Sopenharmony_ci DBG(5, "%s\n", __func__); 916141cc406Sopenharmony_ci free_devices(); 917141cc406Sopenharmony_ci} 918141cc406Sopenharmony_ci 919141cc406Sopenharmony_ciSANE_Status 920141cc406Sopenharmony_cisane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only) 921141cc406Sopenharmony_ci{ 922141cc406Sopenharmony_ci Epson_Device *dev; 923141cc406Sopenharmony_ci int i; 924141cc406Sopenharmony_ci 925141cc406Sopenharmony_ci DBG(5, "%s\n", __func__); 926141cc406Sopenharmony_ci 927141cc406Sopenharmony_ci probe_devices(local_only); 928141cc406Sopenharmony_ci 929141cc406Sopenharmony_ci devlist = malloc((num_devices + 1) * sizeof(devlist[0])); 930141cc406Sopenharmony_ci if (!devlist) { 931141cc406Sopenharmony_ci DBG(1, "out of memory (line %d)\n", __LINE__); 932141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 933141cc406Sopenharmony_ci } 934141cc406Sopenharmony_ci 935141cc406Sopenharmony_ci DBG(5, "%s - results:\n", __func__); 936141cc406Sopenharmony_ci 937141cc406Sopenharmony_ci for (i = 0, dev = first_dev; i < num_devices && dev; dev = dev->next, i++) { 938141cc406Sopenharmony_ci DBG(1, " %d (%d): %s\n", i, dev->connection, dev->model); 939141cc406Sopenharmony_ci devlist[i] = &dev->sane; 940141cc406Sopenharmony_ci } 941141cc406Sopenharmony_ci 942141cc406Sopenharmony_ci devlist[i] = NULL; 943141cc406Sopenharmony_ci 944141cc406Sopenharmony_ci *device_list = devlist; 945141cc406Sopenharmony_ci 946141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 947141cc406Sopenharmony_ci} 948141cc406Sopenharmony_ci 949141cc406Sopenharmony_cistatic SANE_Status 950141cc406Sopenharmony_ciinit_options(Epson_Scanner *s) 951141cc406Sopenharmony_ci{ 952141cc406Sopenharmony_ci int i; 953141cc406Sopenharmony_ci 954141cc406Sopenharmony_ci for (i = 0; i < NUM_OPTIONS; i++) { 955141cc406Sopenharmony_ci s->opt[i].size = sizeof(SANE_Word); 956141cc406Sopenharmony_ci s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 957141cc406Sopenharmony_ci } 958141cc406Sopenharmony_ci 959141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 960141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 961141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 962141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 963141cc406Sopenharmony_ci s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; 964141cc406Sopenharmony_ci 965141cc406Sopenharmony_ci /* "Scan Mode" group: */ 966141cc406Sopenharmony_ci 967141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].title = SANE_I18N("Scan Mode"); 968141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].desc = ""; 969141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 970141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].cap = 0; 971141cc406Sopenharmony_ci 972141cc406Sopenharmony_ci /* scan mode */ 973141cc406Sopenharmony_ci s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; 974141cc406Sopenharmony_ci s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 975141cc406Sopenharmony_ci s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 976141cc406Sopenharmony_ci s->opt[OPT_MODE].type = SANE_TYPE_STRING; 977141cc406Sopenharmony_ci s->opt[OPT_MODE].size = max_string_size(mode_list); 978141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 979141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint.string_list = mode_list; 980141cc406Sopenharmony_ci s->val[OPT_MODE].w = 0; /* Lineart */ 981141cc406Sopenharmony_ci 982141cc406Sopenharmony_ci /* disable infrared on unsupported scanners */ 983141cc406Sopenharmony_ci if (!e2_model(s, "GT-X800") && !e2_model(s, "GT-X700") && !e2_model(s, "GT-X900") && !e2_model(s, "GT-X980")) 984141cc406Sopenharmony_ci mode_list[MODE_INFRARED] = NULL; 985141cc406Sopenharmony_ci 986141cc406Sopenharmony_ci /* bit depth */ 987141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; 988141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; 989141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; 990141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT; 991141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].unit = SANE_UNIT_BIT; 992141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; 993141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].constraint.word_list = s->hw->depth_list; 994141cc406Sopenharmony_ci s->val[OPT_BIT_DEPTH].w = 8; /* default to 8 bit */ 995141cc406Sopenharmony_ci 996141cc406Sopenharmony_ci /* default is Lineart, disable depth selection */ 997141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; 998141cc406Sopenharmony_ci 999141cc406Sopenharmony_ci /* halftone */ 1000141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].name = SANE_NAME_HALFTONE; 1001141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].title = SANE_TITLE_HALFTONE; 1002141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].desc = SANE_I18N("Selects the halftone."); 1003141cc406Sopenharmony_ci 1004141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].type = SANE_TYPE_STRING; 1005141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].size = max_string_size(halftone_list_7); 1006141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1007141cc406Sopenharmony_ci 1008141cc406Sopenharmony_ci /* XXX use defines */ 1009141cc406Sopenharmony_ci if (s->hw->level >= 7) 1010141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].constraint.string_list = halftone_list_7; 1011141cc406Sopenharmony_ci else if (s->hw->level >= 4) 1012141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].constraint.string_list = halftone_list_4; 1013141cc406Sopenharmony_ci else 1014141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].constraint.string_list = halftone_list; 1015141cc406Sopenharmony_ci 1016141cc406Sopenharmony_ci s->val[OPT_HALFTONE].w = 1; /* Halftone A */ 1017141cc406Sopenharmony_ci 1018141cc406Sopenharmony_ci if (!s->hw->cmd->set_halftoning) 1019141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; 1020141cc406Sopenharmony_ci 1021141cc406Sopenharmony_ci /* dropout */ 1022141cc406Sopenharmony_ci s->opt[OPT_DROPOUT].name = "dropout"; 1023141cc406Sopenharmony_ci s->opt[OPT_DROPOUT].title = SANE_I18N("Dropout"); 1024141cc406Sopenharmony_ci s->opt[OPT_DROPOUT].desc = SANE_I18N("Selects the dropout."); 1025141cc406Sopenharmony_ci 1026141cc406Sopenharmony_ci s->opt[OPT_DROPOUT].type = SANE_TYPE_STRING; 1027141cc406Sopenharmony_ci s->opt[OPT_DROPOUT].size = max_string_size(dropout_list); 1028141cc406Sopenharmony_ci s->opt[OPT_DROPOUT].cap |= SANE_CAP_ADVANCED; 1029141cc406Sopenharmony_ci s->opt[OPT_DROPOUT].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1030141cc406Sopenharmony_ci s->opt[OPT_DROPOUT].constraint.string_list = dropout_list; 1031141cc406Sopenharmony_ci s->val[OPT_DROPOUT].w = 0; /* None */ 1032141cc406Sopenharmony_ci 1033141cc406Sopenharmony_ci /* brightness */ 1034141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; 1035141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; 1036141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].desc = SANE_I18N("Selects the brightness."); 1037141cc406Sopenharmony_ci 1038141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; 1039141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; 1040141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; 1041141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].constraint.range = &s->hw->cmd->bright_range; 1042141cc406Sopenharmony_ci s->val[OPT_BRIGHTNESS].w = 0; /* Normal */ 1043141cc406Sopenharmony_ci 1044141cc406Sopenharmony_ci if (!s->hw->cmd->set_bright) 1045141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 1046141cc406Sopenharmony_ci 1047141cc406Sopenharmony_ci /* sharpness */ 1048141cc406Sopenharmony_ci s->opt[OPT_SHARPNESS].name = "sharpness"; 1049141cc406Sopenharmony_ci s->opt[OPT_SHARPNESS].title = SANE_I18N("Sharpness"); 1050141cc406Sopenharmony_ci s->opt[OPT_SHARPNESS].desc = ""; 1051141cc406Sopenharmony_ci 1052141cc406Sopenharmony_ci s->opt[OPT_SHARPNESS].type = SANE_TYPE_INT; 1053141cc406Sopenharmony_ci s->opt[OPT_SHARPNESS].unit = SANE_UNIT_NONE; 1054141cc406Sopenharmony_ci s->opt[OPT_SHARPNESS].constraint_type = SANE_CONSTRAINT_RANGE; 1055141cc406Sopenharmony_ci s->opt[OPT_SHARPNESS].constraint.range = &outline_emphasis_range; 1056141cc406Sopenharmony_ci s->val[OPT_SHARPNESS].w = 0; /* Normal */ 1057141cc406Sopenharmony_ci 1058141cc406Sopenharmony_ci if (!s->hw->cmd->set_outline_emphasis) 1059141cc406Sopenharmony_ci s->opt[OPT_SHARPNESS].cap |= SANE_CAP_INACTIVE; 1060141cc406Sopenharmony_ci 1061141cc406Sopenharmony_ci /* gamma */ 1062141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].name = SANE_NAME_GAMMA_CORRECTION; 1063141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].title = SANE_TITLE_GAMMA_CORRECTION; 1064141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].desc = SANE_DESC_GAMMA_CORRECTION; 1065141cc406Sopenharmony_ci 1066141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].type = SANE_TYPE_STRING; 1067141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].constraint_type = 1068141cc406Sopenharmony_ci SANE_CONSTRAINT_STRING_LIST; 1069141cc406Sopenharmony_ci 1070141cc406Sopenharmony_ci /* 1071141cc406Sopenharmony_ci * special handling for D1 function level - at this time I'm not 1072141cc406Sopenharmony_ci * testing for D1, I'm just assuming that all D level scanners will 1073141cc406Sopenharmony_ci * behave the same way. This has to be confirmed with the next D-level 1074141cc406Sopenharmony_ci * scanner 1075141cc406Sopenharmony_ci */ 1076141cc406Sopenharmony_ci if (s->hw->cmd->level[0] == 'D') { 1077141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].size = 1078141cc406Sopenharmony_ci max_string_size(gamma_list_d); 1079141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].constraint.string_list = 1080141cc406Sopenharmony_ci gamma_list_d; 1081141cc406Sopenharmony_ci s->val[OPT_GAMMA_CORRECTION].w = 1; /* Default */ 1082141cc406Sopenharmony_ci gamma_userdefined = gamma_userdefined_d; 1083141cc406Sopenharmony_ci gamma_params = gamma_params_d; 1084141cc406Sopenharmony_ci } else { 1085141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].size = 1086141cc406Sopenharmony_ci max_string_size(gamma_list_ab); 1087141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].constraint.string_list = 1088141cc406Sopenharmony_ci gamma_list_ab; 1089141cc406Sopenharmony_ci s->val[OPT_GAMMA_CORRECTION].w = 0; /* Default */ 1090141cc406Sopenharmony_ci gamma_userdefined = gamma_userdefined_ab; 1091141cc406Sopenharmony_ci gamma_params = gamma_params_ab; 1092141cc406Sopenharmony_ci } 1093141cc406Sopenharmony_ci 1094141cc406Sopenharmony_ci if (!s->hw->cmd->set_gamma) 1095141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].cap |= SANE_CAP_INACTIVE; 1096141cc406Sopenharmony_ci 1097141cc406Sopenharmony_ci /* red gamma vector */ 1098141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; 1099141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; 1100141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; 1101141cc406Sopenharmony_ci 1102141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; 1103141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; 1104141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof(SANE_Word); 1105141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; 1106141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; 1107141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR_R].wa = &s->gamma_table[0][0]; 1108141cc406Sopenharmony_ci 1109141cc406Sopenharmony_ci /* green gamma vector */ 1110141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; 1111141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; 1112141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; 1113141cc406Sopenharmony_ci 1114141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; 1115141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; 1116141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof(SANE_Word); 1117141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; 1118141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; 1119141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR_G].wa = &s->gamma_table[1][0]; 1120141cc406Sopenharmony_ci 1121141cc406Sopenharmony_ci 1122141cc406Sopenharmony_ci /* red gamma vector */ 1123141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; 1124141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; 1125141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; 1126141cc406Sopenharmony_ci 1127141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; 1128141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; 1129141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof(SANE_Word); 1130141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; 1131141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; 1132141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR_B].wa = &s->gamma_table[2][0]; 1133141cc406Sopenharmony_ci 1134141cc406Sopenharmony_ci if (s->hw->cmd->set_gamma_table 1135141cc406Sopenharmony_ci && gamma_userdefined[s->val[OPT_GAMMA_CORRECTION].w] == 1136141cc406Sopenharmony_ci SANE_TRUE) { 1137141cc406Sopenharmony_ci 1138141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; 1139141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; 1140141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; 1141141cc406Sopenharmony_ci } else { 1142141cc406Sopenharmony_ci 1143141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1144141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1145141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1146141cc406Sopenharmony_ci } 1147141cc406Sopenharmony_ci 1148141cc406Sopenharmony_ci /* initialize the Gamma tables */ 1149141cc406Sopenharmony_ci memset(&s->gamma_table[0], 0, 256 * sizeof(SANE_Word)); 1150141cc406Sopenharmony_ci memset(&s->gamma_table[1], 0, 256 * sizeof(SANE_Word)); 1151141cc406Sopenharmony_ci memset(&s->gamma_table[2], 0, 256 * sizeof(SANE_Word)); 1152141cc406Sopenharmony_ci 1153141cc406Sopenharmony_ci/* memset(&s->gamma_table[3], 0, 256 * sizeof(SANE_Word)); */ 1154141cc406Sopenharmony_ci for (i = 0; i < 256; i++) { 1155141cc406Sopenharmony_ci s->gamma_table[0][i] = i; 1156141cc406Sopenharmony_ci s->gamma_table[1][i] = i; 1157141cc406Sopenharmony_ci s->gamma_table[2][i] = i; 1158141cc406Sopenharmony_ci 1159141cc406Sopenharmony_ci/* s->gamma_table[3][i] = i; */ 1160141cc406Sopenharmony_ci } 1161141cc406Sopenharmony_ci 1162141cc406Sopenharmony_ci 1163141cc406Sopenharmony_ci /* color correction */ 1164141cc406Sopenharmony_ci s->opt[OPT_COLOR_CORRECTION].name = "color-correction"; 1165141cc406Sopenharmony_ci s->opt[OPT_COLOR_CORRECTION].title = SANE_I18N("Color correction"); 1166141cc406Sopenharmony_ci s->opt[OPT_COLOR_CORRECTION].desc = 1167141cc406Sopenharmony_ci SANE_I18N("Sets the color correction table for the selected output device."); 1168141cc406Sopenharmony_ci 1169141cc406Sopenharmony_ci s->opt[OPT_COLOR_CORRECTION].type = SANE_TYPE_STRING; 1170141cc406Sopenharmony_ci s->opt[OPT_COLOR_CORRECTION].size = max_string_size(correction_list); 1171141cc406Sopenharmony_ci s->opt[OPT_COLOR_CORRECTION].cap |= SANE_CAP_ADVANCED; 1172141cc406Sopenharmony_ci s->opt[OPT_COLOR_CORRECTION].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1173141cc406Sopenharmony_ci s->opt[OPT_COLOR_CORRECTION].constraint.string_list = correction_list; 1174141cc406Sopenharmony_ci s->val[OPT_COLOR_CORRECTION].w = CORR_AUTO; 1175141cc406Sopenharmony_ci 1176141cc406Sopenharmony_ci if (!s->hw->cmd->set_color_correction) 1177141cc406Sopenharmony_ci s->opt[OPT_COLOR_CORRECTION].cap |= SANE_CAP_INACTIVE; 1178141cc406Sopenharmony_ci 1179141cc406Sopenharmony_ci /* resolution */ 1180141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 1181141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 1182141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 1183141cc406Sopenharmony_ci 1184141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; 1185141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 1186141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; 1187141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].constraint.word_list = s->hw->resolution_list; 1188141cc406Sopenharmony_ci s->val[OPT_RESOLUTION].w = s->hw->dpi_range.min; 1189141cc406Sopenharmony_ci 1190141cc406Sopenharmony_ci /* threshold */ 1191141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; 1192141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; 1193141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; 1194141cc406Sopenharmony_ci 1195141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; 1196141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; 1197141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; 1198141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].constraint.range = &u8_range; 1199141cc406Sopenharmony_ci s->val[OPT_THRESHOLD].w = 0x80; 1200141cc406Sopenharmony_ci 1201141cc406Sopenharmony_ci if (!s->hw->cmd->set_threshold) 1202141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 1203141cc406Sopenharmony_ci 1204141cc406Sopenharmony_ci 1205141cc406Sopenharmony_ci /* "Advanced" group: */ 1206141cc406Sopenharmony_ci s->opt[OPT_ADVANCED_GROUP].title = SANE_I18N("Advanced"); 1207141cc406Sopenharmony_ci s->opt[OPT_ADVANCED_GROUP].desc = ""; 1208141cc406Sopenharmony_ci s->opt[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP; 1209141cc406Sopenharmony_ci s->opt[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED; 1210141cc406Sopenharmony_ci 1211141cc406Sopenharmony_ci /* "Color correction" group: */ 1212141cc406Sopenharmony_ci s->opt[OPT_CCT_GROUP].title = SANE_I18N("Color correction"); 1213141cc406Sopenharmony_ci s->opt[OPT_CCT_GROUP].desc = ""; 1214141cc406Sopenharmony_ci s->opt[OPT_CCT_GROUP].type = SANE_TYPE_GROUP; 1215141cc406Sopenharmony_ci s->opt[OPT_CCT_GROUP].cap = SANE_CAP_ADVANCED; 1216141cc406Sopenharmony_ci 1217141cc406Sopenharmony_ci /* XXX disabled for now */ 1218141cc406Sopenharmony_ci s->opt[OPT_CCT_MODE].name = "cct-type"; 1219141cc406Sopenharmony_ci s->opt[OPT_CCT_MODE].title = "CCT Profile Type"; 1220141cc406Sopenharmony_ci s->opt[OPT_CCT_MODE].desc = "Color correction profile type"; 1221141cc406Sopenharmony_ci s->opt[OPT_CCT_MODE].type = SANE_TYPE_STRING; 1222141cc406Sopenharmony_ci s->opt[OPT_CCT_MODE].cap |= SANE_CAP_ADVANCED | SANE_CAP_INACTIVE; 1223141cc406Sopenharmony_ci s->opt[OPT_CCT_MODE].size = max_string_size(cct_mode_list); 1224141cc406Sopenharmony_ci s->opt[OPT_CCT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1225141cc406Sopenharmony_ci s->opt[OPT_CCT_MODE].constraint.string_list = cct_mode_list; 1226141cc406Sopenharmony_ci s->val[OPT_CCT_MODE].w = CCT_AUTO; 1227141cc406Sopenharmony_ci 1228141cc406Sopenharmony_ci s->opt[OPT_CCT_PROFILE].name = "cct-profile"; 1229141cc406Sopenharmony_ci s->opt[OPT_CCT_PROFILE].title = "CCT Profile"; 1230141cc406Sopenharmony_ci s->opt[OPT_CCT_PROFILE].desc = "Color correction profile data"; 1231141cc406Sopenharmony_ci s->opt[OPT_CCT_PROFILE].type = SANE_TYPE_FIXED; 1232141cc406Sopenharmony_ci s->opt[OPT_CCT_PROFILE].cap |= SANE_CAP_ADVANCED; 1233141cc406Sopenharmony_ci s->opt[OPT_CCT_PROFILE].unit = SANE_UNIT_NONE; 1234141cc406Sopenharmony_ci s->opt[OPT_CCT_PROFILE].constraint_type = SANE_CONSTRAINT_RANGE; 1235141cc406Sopenharmony_ci s->opt[OPT_CCT_PROFILE].constraint.range = &fx_range; 1236141cc406Sopenharmony_ci s->opt[OPT_CCT_PROFILE].size = 9 * sizeof(SANE_Word); 1237141cc406Sopenharmony_ci s->val[OPT_CCT_PROFILE].wa = s->cct_table; 1238141cc406Sopenharmony_ci 1239141cc406Sopenharmony_ci/* if (!s->hw->cmd->set_color_correction) 1240141cc406Sopenharmony_ci s->opt[OPT_FILM_TYPE].cap |= SANE_CAP_INACTIVE; 1241141cc406Sopenharmony_ci*/ 1242141cc406Sopenharmony_ci 1243141cc406Sopenharmony_ci /* mirror */ 1244141cc406Sopenharmony_ci s->opt[OPT_MIRROR].name = "mirror"; 1245141cc406Sopenharmony_ci s->opt[OPT_MIRROR].title = SANE_I18N("Mirror image"); 1246141cc406Sopenharmony_ci s->opt[OPT_MIRROR].desc = SANE_I18N("Mirror the image."); 1247141cc406Sopenharmony_ci 1248141cc406Sopenharmony_ci s->opt[OPT_MIRROR].type = SANE_TYPE_BOOL; 1249141cc406Sopenharmony_ci s->val[OPT_MIRROR].w = SANE_FALSE; 1250141cc406Sopenharmony_ci 1251141cc406Sopenharmony_ci if (!s->hw->cmd->mirror_image) 1252141cc406Sopenharmony_ci s->opt[OPT_MIRROR].cap |= SANE_CAP_INACTIVE; 1253141cc406Sopenharmony_ci 1254141cc406Sopenharmony_ci /* auto area segmentation */ 1255141cc406Sopenharmony_ci s->opt[OPT_AAS].name = "auto-area-segmentation"; 1256141cc406Sopenharmony_ci s->opt[OPT_AAS].title = SANE_I18N("Auto area segmentation"); 1257141cc406Sopenharmony_ci s->opt[OPT_AAS].desc = 1258141cc406Sopenharmony_ci "Enables different dithering modes in image and text areas"; 1259141cc406Sopenharmony_ci 1260141cc406Sopenharmony_ci s->opt[OPT_AAS].type = SANE_TYPE_BOOL; 1261141cc406Sopenharmony_ci s->val[OPT_AAS].w = SANE_TRUE; 1262141cc406Sopenharmony_ci 1263141cc406Sopenharmony_ci if (!s->hw->cmd->control_auto_area_segmentation) 1264141cc406Sopenharmony_ci s->opt[OPT_AAS].cap |= SANE_CAP_INACTIVE; 1265141cc406Sopenharmony_ci 1266141cc406Sopenharmony_ci /* "Preview settings" group: */ 1267141cc406Sopenharmony_ci s->opt[OPT_PREVIEW_GROUP].title = SANE_TITLE_PREVIEW; 1268141cc406Sopenharmony_ci s->opt[OPT_PREVIEW_GROUP].desc = ""; 1269141cc406Sopenharmony_ci s->opt[OPT_PREVIEW_GROUP].type = SANE_TYPE_GROUP; 1270141cc406Sopenharmony_ci s->opt[OPT_PREVIEW_GROUP].cap = SANE_CAP_ADVANCED; 1271141cc406Sopenharmony_ci 1272141cc406Sopenharmony_ci /* preview */ 1273141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; 1274141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; 1275141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; 1276141cc406Sopenharmony_ci 1277141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; 1278141cc406Sopenharmony_ci s->val[OPT_PREVIEW].w = SANE_FALSE; 1279141cc406Sopenharmony_ci 1280141cc406Sopenharmony_ci /* "Geometry" group: */ 1281141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N("Geometry"); 1282141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].desc = ""; 1283141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 1284141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; 1285141cc406Sopenharmony_ci 1286141cc406Sopenharmony_ci /* top-left x */ 1287141cc406Sopenharmony_ci s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 1288141cc406Sopenharmony_ci s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 1289141cc406Sopenharmony_ci s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 1290141cc406Sopenharmony_ci 1291141cc406Sopenharmony_ci s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; 1292141cc406Sopenharmony_ci s->opt[OPT_TL_X].unit = SANE_UNIT_MM; 1293141cc406Sopenharmony_ci s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 1294141cc406Sopenharmony_ci s->opt[OPT_TL_X].constraint.range = s->hw->x_range; 1295141cc406Sopenharmony_ci s->val[OPT_TL_X].w = 0; 1296141cc406Sopenharmony_ci 1297141cc406Sopenharmony_ci /* top-left y */ 1298141cc406Sopenharmony_ci s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 1299141cc406Sopenharmony_ci s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 1300141cc406Sopenharmony_ci s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 1301141cc406Sopenharmony_ci 1302141cc406Sopenharmony_ci s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; 1303141cc406Sopenharmony_ci s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; 1304141cc406Sopenharmony_ci s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 1305141cc406Sopenharmony_ci s->opt[OPT_TL_Y].constraint.range = s->hw->y_range; 1306141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = 0; 1307141cc406Sopenharmony_ci 1308141cc406Sopenharmony_ci /* bottom-right x */ 1309141cc406Sopenharmony_ci s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 1310141cc406Sopenharmony_ci s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 1311141cc406Sopenharmony_ci s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 1312141cc406Sopenharmony_ci 1313141cc406Sopenharmony_ci s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; 1314141cc406Sopenharmony_ci s->opt[OPT_BR_X].unit = SANE_UNIT_MM; 1315141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 1316141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint.range = s->hw->x_range; 1317141cc406Sopenharmony_ci s->val[OPT_BR_X].w = s->hw->x_range->max; 1318141cc406Sopenharmony_ci 1319141cc406Sopenharmony_ci /* bottom-right y */ 1320141cc406Sopenharmony_ci s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 1321141cc406Sopenharmony_ci s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 1322141cc406Sopenharmony_ci s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 1323141cc406Sopenharmony_ci 1324141cc406Sopenharmony_ci s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; 1325141cc406Sopenharmony_ci s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; 1326141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 1327141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint.range = s->hw->y_range; 1328141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = s->hw->y_range->max; 1329141cc406Sopenharmony_ci 1330141cc406Sopenharmony_ci /* "Focus" group: */ 1331141cc406Sopenharmony_ci s->opt[OPT_FOCUS_GROUP].title = SANE_I18N("Focus"); 1332141cc406Sopenharmony_ci s->opt[OPT_FOCUS_GROUP].desc = ""; 1333141cc406Sopenharmony_ci s->opt[OPT_FOCUS_GROUP].type = SANE_TYPE_GROUP; 1334141cc406Sopenharmony_ci s->opt[OPT_FOCUS_GROUP].cap = SANE_CAP_ADVANCED; 1335141cc406Sopenharmony_ci 1336141cc406Sopenharmony_ci /* autofocus */ 1337141cc406Sopenharmony_ci s->opt[OPT_AUTOFOCUS].name = SANE_NAME_AUTOFOCUS; 1338141cc406Sopenharmony_ci s->opt[OPT_AUTOFOCUS].title = SANE_TITLE_AUTOFOCUS; 1339141cc406Sopenharmony_ci s->opt[OPT_AUTOFOCUS].desc = SANE_DESC_AUTOFOCUS; 1340141cc406Sopenharmony_ci s->opt[OPT_AUTOFOCUS].type = SANE_TYPE_BOOL; 1341141cc406Sopenharmony_ci s->val[OPT_AUTOFOCUS].w = SANE_FALSE; 1342141cc406Sopenharmony_ci s->opt[OPT_AUTOFOCUS].cap |= SANE_CAP_ADVANCED; 1343141cc406Sopenharmony_ci 1344141cc406Sopenharmony_ci /* focus position */ 1345141cc406Sopenharmony_ci s->opt[OPT_FOCUS_POS].name = SANE_NAME_FOCUS; 1346141cc406Sopenharmony_ci s->opt[OPT_FOCUS_POS].title = SANE_TITLE_FOCUS; 1347141cc406Sopenharmony_ci s->opt[OPT_FOCUS_POS].desc = SANE_DESC_FOCUS; 1348141cc406Sopenharmony_ci s->opt[OPT_FOCUS_POS].type = SANE_TYPE_INT; 1349141cc406Sopenharmony_ci s->opt[OPT_FOCUS_POS].unit = SANE_UNIT_NONE; 1350141cc406Sopenharmony_ci s->opt[OPT_FOCUS_POS].constraint_type = SANE_CONSTRAINT_RANGE; 1351141cc406Sopenharmony_ci s->opt[OPT_FOCUS_POS].constraint.range = &focus_range; 1352141cc406Sopenharmony_ci s->val[OPT_FOCUS_POS].w = FOCUS_ON_GLASS; 1353141cc406Sopenharmony_ci s->opt[OPT_FOCUS_POS].cap |= SANE_CAP_ADVANCED; 1354141cc406Sopenharmony_ci 1355141cc406Sopenharmony_ci if (s->hw->focusSupport == SANE_TRUE) { 1356141cc406Sopenharmony_ci s->opt[OPT_FOCUS_POS].cap &= ~SANE_CAP_INACTIVE; 1357141cc406Sopenharmony_ci s->opt[OPT_AUTOFOCUS].cap &= ~SANE_CAP_INACTIVE; 1358141cc406Sopenharmony_ci } else { 1359141cc406Sopenharmony_ci s->opt[OPT_FOCUS_POS].cap |= SANE_CAP_INACTIVE; 1360141cc406Sopenharmony_ci s->opt[OPT_AUTOFOCUS].cap |= SANE_CAP_INACTIVE; 1361141cc406Sopenharmony_ci } 1362141cc406Sopenharmony_ci 1363141cc406Sopenharmony_ci /* "Optional equipment" group: */ 1364141cc406Sopenharmony_ci s->opt[OPT_EQU_GROUP].title = SANE_I18N("Optional equipment"); 1365141cc406Sopenharmony_ci s->opt[OPT_EQU_GROUP].desc = ""; 1366141cc406Sopenharmony_ci s->opt[OPT_EQU_GROUP].type = SANE_TYPE_GROUP; 1367141cc406Sopenharmony_ci s->opt[OPT_EQU_GROUP].cap = SANE_CAP_ADVANCED; 1368141cc406Sopenharmony_ci 1369141cc406Sopenharmony_ci /* source */ 1370141cc406Sopenharmony_ci s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; 1371141cc406Sopenharmony_ci s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; 1372141cc406Sopenharmony_ci s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; 1373141cc406Sopenharmony_ci 1374141cc406Sopenharmony_ci s->opt[OPT_SOURCE].type = SANE_TYPE_STRING; 1375141cc406Sopenharmony_ci s->opt[OPT_SOURCE].size = max_string_size(source_list); 1376141cc406Sopenharmony_ci 1377141cc406Sopenharmony_ci s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1378141cc406Sopenharmony_ci s->opt[OPT_SOURCE].constraint.string_list = source_list; 1379141cc406Sopenharmony_ci 1380141cc406Sopenharmony_ci if (!s->hw->extension) 1381141cc406Sopenharmony_ci s->opt[OPT_SOURCE].cap |= SANE_CAP_INACTIVE; 1382141cc406Sopenharmony_ci 1383141cc406Sopenharmony_ci s->val[OPT_SOURCE].w = 0; /* always use Flatbed as default */ 1384141cc406Sopenharmony_ci 1385141cc406Sopenharmony_ci 1386141cc406Sopenharmony_ci /* film type */ 1387141cc406Sopenharmony_ci s->opt[OPT_FILM_TYPE].name = "film-type"; 1388141cc406Sopenharmony_ci s->opt[OPT_FILM_TYPE].title = SANE_I18N("Film type"); 1389141cc406Sopenharmony_ci s->opt[OPT_FILM_TYPE].desc = ""; 1390141cc406Sopenharmony_ci s->opt[OPT_FILM_TYPE].type = SANE_TYPE_STRING; 1391141cc406Sopenharmony_ci s->opt[OPT_FILM_TYPE].size = max_string_size(film_list); 1392141cc406Sopenharmony_ci s->opt[OPT_FILM_TYPE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1393141cc406Sopenharmony_ci s->opt[OPT_FILM_TYPE].constraint.string_list = film_list; 1394141cc406Sopenharmony_ci s->val[OPT_FILM_TYPE].w = 0; 1395141cc406Sopenharmony_ci 1396141cc406Sopenharmony_ci if (!s->hw->cmd->set_bay) 1397141cc406Sopenharmony_ci s->opt[OPT_FILM_TYPE].cap |= SANE_CAP_INACTIVE; 1398141cc406Sopenharmony_ci 1399141cc406Sopenharmony_ci /* forward feed / eject */ 1400141cc406Sopenharmony_ci s->opt[OPT_EJECT].name = "eject"; 1401141cc406Sopenharmony_ci s->opt[OPT_EJECT].title = SANE_I18N("Eject"); 1402141cc406Sopenharmony_ci s->opt[OPT_EJECT].desc = SANE_I18N("Eject the sheet in the ADF"); 1403141cc406Sopenharmony_ci s->opt[OPT_EJECT].type = SANE_TYPE_BUTTON; 1404141cc406Sopenharmony_ci 1405141cc406Sopenharmony_ci if ((!s->hw->ADF) && (!s->hw->cmd->set_bay)) { /* Hack: Using set_bay to indicate. */ 1406141cc406Sopenharmony_ci s->opt[OPT_EJECT].cap |= SANE_CAP_INACTIVE; 1407141cc406Sopenharmony_ci } 1408141cc406Sopenharmony_ci 1409141cc406Sopenharmony_ci 1410141cc406Sopenharmony_ci /* auto forward feed / eject */ 1411141cc406Sopenharmony_ci s->opt[OPT_AUTO_EJECT].name = "auto-eject"; 1412141cc406Sopenharmony_ci s->opt[OPT_AUTO_EJECT].title = SANE_I18N("Auto eject"); 1413141cc406Sopenharmony_ci s->opt[OPT_AUTO_EJECT].desc = 1414141cc406Sopenharmony_ci SANE_I18N("Eject document after scanning"); 1415141cc406Sopenharmony_ci 1416141cc406Sopenharmony_ci s->opt[OPT_AUTO_EJECT].type = SANE_TYPE_BOOL; 1417141cc406Sopenharmony_ci s->val[OPT_AUTO_EJECT].w = SANE_FALSE; 1418141cc406Sopenharmony_ci 1419141cc406Sopenharmony_ci if (!s->hw->ADF) 1420141cc406Sopenharmony_ci s->opt[OPT_AUTO_EJECT].cap |= SANE_CAP_INACTIVE; 1421141cc406Sopenharmony_ci 1422141cc406Sopenharmony_ci 1423141cc406Sopenharmony_ci s->opt[OPT_ADF_MODE].name = "adf-mode"; 1424141cc406Sopenharmony_ci s->opt[OPT_ADF_MODE].title = SANE_I18N("ADF Mode"); 1425141cc406Sopenharmony_ci s->opt[OPT_ADF_MODE].desc = 1426141cc406Sopenharmony_ci SANE_I18N("Selects the ADF mode (simplex/duplex)"); 1427141cc406Sopenharmony_ci s->opt[OPT_ADF_MODE].type = SANE_TYPE_STRING; 1428141cc406Sopenharmony_ci s->opt[OPT_ADF_MODE].size = max_string_size(adf_mode_list); 1429141cc406Sopenharmony_ci s->opt[OPT_ADF_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1430141cc406Sopenharmony_ci s->opt[OPT_ADF_MODE].constraint.string_list = adf_mode_list; 1431141cc406Sopenharmony_ci s->val[OPT_ADF_MODE].w = 0; /* simplex */ 1432141cc406Sopenharmony_ci 1433141cc406Sopenharmony_ci if ((!s->hw->ADF) || (s->hw->duplex == SANE_FALSE)) 1434141cc406Sopenharmony_ci s->opt[OPT_ADF_MODE].cap |= SANE_CAP_INACTIVE; 1435141cc406Sopenharmony_ci 1436141cc406Sopenharmony_ci /* select bay */ 1437141cc406Sopenharmony_ci s->opt[OPT_BAY].name = "bay"; 1438141cc406Sopenharmony_ci s->opt[OPT_BAY].title = SANE_I18N("Bay"); 1439141cc406Sopenharmony_ci s->opt[OPT_BAY].desc = SANE_I18N("Select bay to scan"); 1440141cc406Sopenharmony_ci s->opt[OPT_BAY].type = SANE_TYPE_STRING; 1441141cc406Sopenharmony_ci s->opt[OPT_BAY].size = max_string_size(bay_list); 1442141cc406Sopenharmony_ci s->opt[OPT_BAY].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1443141cc406Sopenharmony_ci s->opt[OPT_BAY].constraint.string_list = bay_list; 1444141cc406Sopenharmony_ci s->val[OPT_BAY].w = 0; /* Bay 1 */ 1445141cc406Sopenharmony_ci 1446141cc406Sopenharmony_ci if (!s->hw->cmd->set_bay) 1447141cc406Sopenharmony_ci s->opt[OPT_BAY].cap |= SANE_CAP_INACTIVE; 1448141cc406Sopenharmony_ci 1449141cc406Sopenharmony_ci 1450141cc406Sopenharmony_ci s->opt[OPT_WAIT_FOR_BUTTON].name = SANE_EPSON_WAIT_FOR_BUTTON_NAME; 1451141cc406Sopenharmony_ci s->opt[OPT_WAIT_FOR_BUTTON].title = SANE_EPSON_WAIT_FOR_BUTTON_TITLE; 1452141cc406Sopenharmony_ci s->opt[OPT_WAIT_FOR_BUTTON].desc = SANE_EPSON_WAIT_FOR_BUTTON_DESC; 1453141cc406Sopenharmony_ci 1454141cc406Sopenharmony_ci s->opt[OPT_WAIT_FOR_BUTTON].type = SANE_TYPE_BOOL; 1455141cc406Sopenharmony_ci s->opt[OPT_WAIT_FOR_BUTTON].unit = SANE_UNIT_NONE; 1456141cc406Sopenharmony_ci s->opt[OPT_WAIT_FOR_BUTTON].constraint_type = SANE_CONSTRAINT_NONE; 1457141cc406Sopenharmony_ci s->opt[OPT_WAIT_FOR_BUTTON].constraint.range = NULL; 1458141cc406Sopenharmony_ci s->opt[OPT_WAIT_FOR_BUTTON].cap |= SANE_CAP_ADVANCED; 1459141cc406Sopenharmony_ci 1460141cc406Sopenharmony_ci if (!s->hw->cmd->request_push_button_status) 1461141cc406Sopenharmony_ci s->opt[OPT_WAIT_FOR_BUTTON].cap |= SANE_CAP_INACTIVE; 1462141cc406Sopenharmony_ci 1463141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1464141cc406Sopenharmony_ci} 1465141cc406Sopenharmony_ci 1466141cc406Sopenharmony_ciSANE_Status 1467141cc406Sopenharmony_cisane_open(SANE_String_Const name, SANE_Handle *handle) 1468141cc406Sopenharmony_ci{ 1469141cc406Sopenharmony_ci SANE_Status status; 1470141cc406Sopenharmony_ci Epson_Scanner *s = NULL; 1471141cc406Sopenharmony_ci 1472141cc406Sopenharmony_ci int l = strlen(name); 1473141cc406Sopenharmony_ci 1474141cc406Sopenharmony_ci DBG(7, "%s: name = %s\n", __func__, name); 1475141cc406Sopenharmony_ci 1476141cc406Sopenharmony_ci *handle = NULL; 1477141cc406Sopenharmony_ci 1478141cc406Sopenharmony_ci /* probe if empty device name provided */ 1479141cc406Sopenharmony_ci if (l == 0) { 1480141cc406Sopenharmony_ci 1481141cc406Sopenharmony_ci probe_devices(SANE_FALSE); 1482141cc406Sopenharmony_ci 1483141cc406Sopenharmony_ci if (first_dev == NULL) { 1484141cc406Sopenharmony_ci DBG(1, "no device detected\n"); 1485141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1486141cc406Sopenharmony_ci } 1487141cc406Sopenharmony_ci 1488141cc406Sopenharmony_ci s = device_detect(first_dev->sane.name, first_dev->connection, 1489141cc406Sopenharmony_ci 0, &status); 1490141cc406Sopenharmony_ci if (s == NULL) { 1491141cc406Sopenharmony_ci DBG(1, "cannot open a perfectly valid device (%s)," 1492141cc406Sopenharmony_ci " please report to the authors\n", name); 1493141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1494141cc406Sopenharmony_ci } 1495141cc406Sopenharmony_ci 1496141cc406Sopenharmony_ci } else { 1497141cc406Sopenharmony_ci 1498141cc406Sopenharmony_ci if (strncmp(name, "net:", 4) == 0) { 1499141cc406Sopenharmony_ci s = device_detect(name, SANE_EPSON_NET, 0, &status); 1500141cc406Sopenharmony_ci if (s == NULL) 1501141cc406Sopenharmony_ci return status; 1502141cc406Sopenharmony_ci } else if (strncmp(name, "libusb:", 7) == 0) { 1503141cc406Sopenharmony_ci s = device_detect(name, SANE_EPSON_USB, 1, &status); 1504141cc406Sopenharmony_ci if (s == NULL) 1505141cc406Sopenharmony_ci return status; 1506141cc406Sopenharmony_ci } else if (strncmp(name, "pio:", 4) == 0) { 1507141cc406Sopenharmony_ci s = device_detect(name, SANE_EPSON_PIO, 0, &status); 1508141cc406Sopenharmony_ci if (s == NULL) 1509141cc406Sopenharmony_ci return status; 1510141cc406Sopenharmony_ci } else { 1511141cc406Sopenharmony_ci 1512141cc406Sopenharmony_ci /* as a last resort, check for a match 1513141cc406Sopenharmony_ci * in the device list. This should handle SCSI 1514141cc406Sopenharmony_ci * devices and platforms without libusb. 1515141cc406Sopenharmony_ci */ 1516141cc406Sopenharmony_ci 1517141cc406Sopenharmony_ci if (first_dev == NULL) 1518141cc406Sopenharmony_ci probe_devices(SANE_FALSE); 1519141cc406Sopenharmony_ci 1520141cc406Sopenharmony_ci s = device_detect(name, SANE_EPSON_NODEV, 0, &status); 1521141cc406Sopenharmony_ci if (s == NULL) { 1522141cc406Sopenharmony_ci DBG(1, "invalid device name: %s\n", name); 1523141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1524141cc406Sopenharmony_ci } 1525141cc406Sopenharmony_ci } 1526141cc406Sopenharmony_ci } 1527141cc406Sopenharmony_ci 1528141cc406Sopenharmony_ci 1529141cc406Sopenharmony_ci /* s is always valid here */ 1530141cc406Sopenharmony_ci 1531141cc406Sopenharmony_ci DBG(1, "handle obtained\n"); 1532141cc406Sopenharmony_ci 1533141cc406Sopenharmony_ci init_options(s); 1534141cc406Sopenharmony_ci 1535141cc406Sopenharmony_ci status = open_scanner(s); 1536141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 1537141cc406Sopenharmony_ci free(s); 1538141cc406Sopenharmony_ci return status; 1539141cc406Sopenharmony_ci } 1540141cc406Sopenharmony_ci 1541141cc406Sopenharmony_ci status = esci_reset(s); 1542141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 1543141cc406Sopenharmony_ci close_scanner(s); 1544141cc406Sopenharmony_ci return status; 1545141cc406Sopenharmony_ci } 1546141cc406Sopenharmony_ci 1547141cc406Sopenharmony_ci *handle = (SANE_Handle)s; 1548141cc406Sopenharmony_ci 1549141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1550141cc406Sopenharmony_ci} 1551141cc406Sopenharmony_ci 1552141cc406Sopenharmony_civoid 1553141cc406Sopenharmony_cisane_close(SANE_Handle handle) 1554141cc406Sopenharmony_ci{ 1555141cc406Sopenharmony_ci Epson_Scanner *s; 1556141cc406Sopenharmony_ci 1557141cc406Sopenharmony_ci DBG(1, "* %s\n", __func__); 1558141cc406Sopenharmony_ci 1559141cc406Sopenharmony_ci /* 1560141cc406Sopenharmony_ci * XXX Test if there is still data pending from 1561141cc406Sopenharmony_ci * the scanner. If so, then do a cancel 1562141cc406Sopenharmony_ci */ 1563141cc406Sopenharmony_ci 1564141cc406Sopenharmony_ci s = (Epson_Scanner *) handle; 1565141cc406Sopenharmony_ci 1566141cc406Sopenharmony_ci close_scanner(s); 1567141cc406Sopenharmony_ci} 1568141cc406Sopenharmony_ci 1569141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 1570141cc406Sopenharmony_cisane_get_option_descriptor(SANE_Handle handle, SANE_Int option) 1571141cc406Sopenharmony_ci{ 1572141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 1573141cc406Sopenharmony_ci 1574141cc406Sopenharmony_ci if (option < 0 || option >= NUM_OPTIONS) 1575141cc406Sopenharmony_ci return NULL; 1576141cc406Sopenharmony_ci 1577141cc406Sopenharmony_ci return s->opt + option; 1578141cc406Sopenharmony_ci} 1579141cc406Sopenharmony_ci 1580141cc406Sopenharmony_cistatic const SANE_String_Const * 1581141cc406Sopenharmony_cisearch_string_list(const SANE_String_Const *list, SANE_String value) 1582141cc406Sopenharmony_ci{ 1583141cc406Sopenharmony_ci while (*list != NULL && strcmp(value, *list) != 0) 1584141cc406Sopenharmony_ci list++; 1585141cc406Sopenharmony_ci 1586141cc406Sopenharmony_ci return ((*list == NULL) ? NULL : list); 1587141cc406Sopenharmony_ci} 1588141cc406Sopenharmony_ci 1589141cc406Sopenharmony_ci/* 1590141cc406Sopenharmony_ci Activate, deactivate an option. Subroutines so we can add 1591141cc406Sopenharmony_ci debugging info if we want. The change flag is set to TRUE 1592141cc406Sopenharmony_ci if we changed an option. If we did not change an option, 1593141cc406Sopenharmony_ci then the value of the changed flag is not modified. 1594141cc406Sopenharmony_ci*/ 1595141cc406Sopenharmony_ci 1596141cc406Sopenharmony_cistatic void 1597141cc406Sopenharmony_ciactivateOption(Epson_Scanner *s, SANE_Int option, SANE_Bool *change) 1598141cc406Sopenharmony_ci{ 1599141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) { 1600141cc406Sopenharmony_ci s->opt[option].cap &= ~SANE_CAP_INACTIVE; 1601141cc406Sopenharmony_ci *change = SANE_TRUE; 1602141cc406Sopenharmony_ci } 1603141cc406Sopenharmony_ci} 1604141cc406Sopenharmony_ci 1605141cc406Sopenharmony_cistatic void 1606141cc406Sopenharmony_cideactivateOption(Epson_Scanner *s, SANE_Int option, SANE_Bool *change) 1607141cc406Sopenharmony_ci{ 1608141cc406Sopenharmony_ci if (SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) { 1609141cc406Sopenharmony_ci s->opt[option].cap |= SANE_CAP_INACTIVE; 1610141cc406Sopenharmony_ci *change = SANE_TRUE; 1611141cc406Sopenharmony_ci } 1612141cc406Sopenharmony_ci} 1613141cc406Sopenharmony_ci 1614141cc406Sopenharmony_cistatic void 1615141cc406Sopenharmony_cisetOptionState(Epson_Scanner *s, SANE_Bool state, SANE_Int option, 1616141cc406Sopenharmony_ci SANE_Bool *change) 1617141cc406Sopenharmony_ci{ 1618141cc406Sopenharmony_ci if (state) 1619141cc406Sopenharmony_ci activateOption(s, option, change); 1620141cc406Sopenharmony_ci else 1621141cc406Sopenharmony_ci deactivateOption(s, option, change); 1622141cc406Sopenharmony_ci} 1623141cc406Sopenharmony_ci 1624141cc406Sopenharmony_cistatic SANE_Status 1625141cc406Sopenharmony_cigetvalue(SANE_Handle handle, SANE_Int option, void *value) 1626141cc406Sopenharmony_ci{ 1627141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 1628141cc406Sopenharmony_ci SANE_Option_Descriptor *sopt = &(s->opt[option]); 1629141cc406Sopenharmony_ci Option_Value *sval = &(s->val[option]); 1630141cc406Sopenharmony_ci 1631141cc406Sopenharmony_ci DBG(17, "%s: option = %d\n", __func__, option); 1632141cc406Sopenharmony_ci 1633141cc406Sopenharmony_ci switch (option) { 1634141cc406Sopenharmony_ci 1635141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 1636141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 1637141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 1638141cc406Sopenharmony_ci case OPT_CCT_PROFILE: 1639141cc406Sopenharmony_ci memcpy(value, sval->wa, sopt->size); 1640141cc406Sopenharmony_ci break; 1641141cc406Sopenharmony_ci 1642141cc406Sopenharmony_ci case OPT_NUM_OPTS: 1643141cc406Sopenharmony_ci case OPT_RESOLUTION: 1644141cc406Sopenharmony_ci case OPT_TL_X: 1645141cc406Sopenharmony_ci case OPT_TL_Y: 1646141cc406Sopenharmony_ci case OPT_BR_X: 1647141cc406Sopenharmony_ci case OPT_BR_Y: 1648141cc406Sopenharmony_ci case OPT_MIRROR: 1649141cc406Sopenharmony_ci case OPT_AAS: 1650141cc406Sopenharmony_ci case OPT_PREVIEW: 1651141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 1652141cc406Sopenharmony_ci case OPT_SHARPNESS: 1653141cc406Sopenharmony_ci case OPT_AUTO_EJECT: 1654141cc406Sopenharmony_ci case OPT_THRESHOLD: 1655141cc406Sopenharmony_ci case OPT_BIT_DEPTH: 1656141cc406Sopenharmony_ci case OPT_WAIT_FOR_BUTTON: 1657141cc406Sopenharmony_ci case OPT_AUTOFOCUS: 1658141cc406Sopenharmony_ci case OPT_FOCUS_POS: 1659141cc406Sopenharmony_ci *((SANE_Word *) value) = sval->w; 1660141cc406Sopenharmony_ci break; 1661141cc406Sopenharmony_ci 1662141cc406Sopenharmony_ci case OPT_MODE: 1663141cc406Sopenharmony_ci case OPT_CCT_MODE: 1664141cc406Sopenharmony_ci case OPT_ADF_MODE: 1665141cc406Sopenharmony_ci case OPT_HALFTONE: 1666141cc406Sopenharmony_ci case OPT_DROPOUT: 1667141cc406Sopenharmony_ci case OPT_SOURCE: 1668141cc406Sopenharmony_ci case OPT_FILM_TYPE: 1669141cc406Sopenharmony_ci case OPT_GAMMA_CORRECTION: 1670141cc406Sopenharmony_ci case OPT_COLOR_CORRECTION: 1671141cc406Sopenharmony_ci case OPT_BAY: 1672141cc406Sopenharmony_ci strcpy((char *) value, sopt->constraint.string_list[sval->w]); 1673141cc406Sopenharmony_ci break; 1674141cc406Sopenharmony_ci 1675141cc406Sopenharmony_ci default: 1676141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1677141cc406Sopenharmony_ci } 1678141cc406Sopenharmony_ci 1679141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1680141cc406Sopenharmony_ci} 1681141cc406Sopenharmony_ci 1682141cc406Sopenharmony_ci/* 1683141cc406Sopenharmony_ci * This routine handles common options between OPT_MODE and 1684141cc406Sopenharmony_ci * OPT_HALFTONE. These options are TET (a HALFTONE mode), AAS 1685141cc406Sopenharmony_ci * - auto area segmentation, and threshold. Apparently AAS 1686141cc406Sopenharmony_ci * is some method to differentiate between text and photos. 1687141cc406Sopenharmony_ci * Or something like that. 1688141cc406Sopenharmony_ci * 1689141cc406Sopenharmony_ci * AAS is available when the scan color depth is 1 and the 1690141cc406Sopenharmony_ci * halftone method is not TET. 1691141cc406Sopenharmony_ci * 1692141cc406Sopenharmony_ci * Threshold is available when halftone is NONE, and depth is 1. 1693141cc406Sopenharmony_ci */ 1694141cc406Sopenharmony_cistatic void 1695141cc406Sopenharmony_cihandle_depth_halftone(Epson_Scanner *s, SANE_Bool *reload) 1696141cc406Sopenharmony_ci{ 1697141cc406Sopenharmony_ci int hti = s->val[OPT_HALFTONE].w; 1698141cc406Sopenharmony_ci int mdi = s->val[OPT_MODE].w; 1699141cc406Sopenharmony_ci SANE_Bool aas = SANE_FALSE; 1700141cc406Sopenharmony_ci SANE_Bool thresh = SANE_FALSE; 1701141cc406Sopenharmony_ci 1702141cc406Sopenharmony_ci /* this defaults to false */ 1703141cc406Sopenharmony_ci setOptionState(s, thresh, OPT_THRESHOLD, reload); 1704141cc406Sopenharmony_ci 1705141cc406Sopenharmony_ci if (!s->hw->cmd->control_auto_area_segmentation) 1706141cc406Sopenharmony_ci return; 1707141cc406Sopenharmony_ci 1708141cc406Sopenharmony_ci if (mode_params[mdi].depth == 1) { 1709141cc406Sopenharmony_ci 1710141cc406Sopenharmony_ci if (halftone_params[hti] != HALFTONE_TET) 1711141cc406Sopenharmony_ci aas = SANE_TRUE; 1712141cc406Sopenharmony_ci 1713141cc406Sopenharmony_ci if (halftone_params[hti] == HALFTONE_NONE) 1714141cc406Sopenharmony_ci thresh = SANE_TRUE; 1715141cc406Sopenharmony_ci } 1716141cc406Sopenharmony_ci setOptionState(s, aas, OPT_AAS, reload); 1717141cc406Sopenharmony_ci setOptionState(s, thresh, OPT_THRESHOLD, reload); 1718141cc406Sopenharmony_ci} 1719141cc406Sopenharmony_ci 1720141cc406Sopenharmony_ci/* 1721141cc406Sopenharmony_ci * Handles setting the source (flatbed, transparency adapter (TPU), 1722141cc406Sopenharmony_ci * or auto document feeder (ADF)). 1723141cc406Sopenharmony_ci * 1724141cc406Sopenharmony_ci * For newer scanners it also sets the focus according to the 1725141cc406Sopenharmony_ci * glass / TPU settings. 1726141cc406Sopenharmony_ci */ 1727141cc406Sopenharmony_ci 1728141cc406Sopenharmony_cistatic void 1729141cc406Sopenharmony_cichange_source(Epson_Scanner *s, SANE_Int optindex, char *value) 1730141cc406Sopenharmony_ci{ 1731141cc406Sopenharmony_ci int force_max = SANE_FALSE; 1732141cc406Sopenharmony_ci SANE_Bool dummy; 1733141cc406Sopenharmony_ci 1734141cc406Sopenharmony_ci DBG(1, "%s: optindex = %d, source = '%s'\n", __func__, optindex, 1735141cc406Sopenharmony_ci value); 1736141cc406Sopenharmony_ci 1737141cc406Sopenharmony_ci /* reset the scanner when we are changing the source setting - 1738141cc406Sopenharmony_ci this is necessary for the Perfection 1650 */ 1739141cc406Sopenharmony_ci if (s->hw->need_reset_on_source_change) 1740141cc406Sopenharmony_ci esci_reset(s); 1741141cc406Sopenharmony_ci 1742141cc406Sopenharmony_ci if (s->val[OPT_SOURCE].w == optindex) 1743141cc406Sopenharmony_ci return; 1744141cc406Sopenharmony_ci 1745141cc406Sopenharmony_ci s->val[OPT_SOURCE].w = optindex; 1746141cc406Sopenharmony_ci 1747141cc406Sopenharmony_ci if (s->val[OPT_TL_X].w == s->hw->x_range->min 1748141cc406Sopenharmony_ci && s->val[OPT_TL_Y].w == s->hw->y_range->min 1749141cc406Sopenharmony_ci && s->val[OPT_BR_X].w == s->hw->x_range->max 1750141cc406Sopenharmony_ci && s->val[OPT_BR_Y].w == s->hw->y_range->max) { 1751141cc406Sopenharmony_ci force_max = SANE_TRUE; 1752141cc406Sopenharmony_ci } 1753141cc406Sopenharmony_ci 1754141cc406Sopenharmony_ci if (strcmp(ADF_STR, value) == 0) { 1755141cc406Sopenharmony_ci s->hw->x_range = &s->hw->adf_x_range; 1756141cc406Sopenharmony_ci s->hw->y_range = &s->hw->adf_y_range; 1757141cc406Sopenharmony_ci s->hw->use_extension = SANE_TRUE; 1758141cc406Sopenharmony_ci /* disable film type option */ 1759141cc406Sopenharmony_ci deactivateOption(s, OPT_FILM_TYPE, &dummy); 1760141cc406Sopenharmony_ci s->val[OPT_FOCUS_POS].w = FOCUS_ON_GLASS; 1761141cc406Sopenharmony_ci if (s->hw->duplex) { 1762141cc406Sopenharmony_ci activateOption(s, OPT_ADF_MODE, &dummy); 1763141cc406Sopenharmony_ci } else { 1764141cc406Sopenharmony_ci deactivateOption(s, OPT_ADF_MODE, &dummy); 1765141cc406Sopenharmony_ci s->val[OPT_ADF_MODE].w = 0; 1766141cc406Sopenharmony_ci } 1767141cc406Sopenharmony_ci 1768141cc406Sopenharmony_ci DBG(1, "adf activated (ext: %d, duplex: %d)\n", 1769141cc406Sopenharmony_ci s->hw->use_extension, 1770141cc406Sopenharmony_ci s->hw->duplex); 1771141cc406Sopenharmony_ci 1772141cc406Sopenharmony_ci } else if (strcmp(TPU_STR, value) == 0 || strcmp(TPU_STR2, value) == 0) { 1773141cc406Sopenharmony_ci if (strcmp(TPU_STR, value) == 0) { 1774141cc406Sopenharmony_ci s->hw->x_range = &s->hw->tpu_x_range; 1775141cc406Sopenharmony_ci s->hw->y_range = &s->hw->tpu_y_range; 1776141cc406Sopenharmony_ci s->hw->TPU2 = SANE_FALSE; 1777141cc406Sopenharmony_ci } 1778141cc406Sopenharmony_ci if (strcmp(TPU_STR2, value) == 0) { 1779141cc406Sopenharmony_ci s->hw->x_range = &s->hw->tpu2_x_range; 1780141cc406Sopenharmony_ci s->hw->y_range = &s->hw->tpu2_y_range; 1781141cc406Sopenharmony_ci s->hw->TPU2 = SANE_TRUE; 1782141cc406Sopenharmony_ci } 1783141cc406Sopenharmony_ci s->hw->use_extension = SANE_TRUE; 1784141cc406Sopenharmony_ci 1785141cc406Sopenharmony_ci /* enable film type option only if the scanner supports it */ 1786141cc406Sopenharmony_ci if (s->hw->cmd->set_film_type != 0) 1787141cc406Sopenharmony_ci activateOption(s, OPT_FILM_TYPE, &dummy); 1788141cc406Sopenharmony_ci else 1789141cc406Sopenharmony_ci deactivateOption(s, OPT_FILM_TYPE, &dummy); 1790141cc406Sopenharmony_ci 1791141cc406Sopenharmony_ci /* enable focus position if the scanner supports it */ 1792141cc406Sopenharmony_ci if (s->hw->focusSupport) 1793141cc406Sopenharmony_ci s->val[OPT_FOCUS_POS].w = FOCUS_ABOVE_25MM; 1794141cc406Sopenharmony_ci 1795141cc406Sopenharmony_ci deactivateOption(s, OPT_ADF_MODE, &dummy); 1796141cc406Sopenharmony_ci deactivateOption(s, OPT_EJECT, &dummy); 1797141cc406Sopenharmony_ci deactivateOption(s, OPT_AUTO_EJECT, &dummy); 1798141cc406Sopenharmony_ci } else { 1799141cc406Sopenharmony_ci /* neither ADF nor TPU active */ 1800141cc406Sopenharmony_ci s->hw->x_range = &s->hw->fbf_x_range; 1801141cc406Sopenharmony_ci s->hw->y_range = &s->hw->fbf_y_range; 1802141cc406Sopenharmony_ci s->hw->use_extension = SANE_FALSE; 1803141cc406Sopenharmony_ci 1804141cc406Sopenharmony_ci /* disable film type option */ 1805141cc406Sopenharmony_ci deactivateOption(s, OPT_FILM_TYPE, &dummy); 1806141cc406Sopenharmony_ci s->val[OPT_FOCUS_POS].w = FOCUS_ON_GLASS; 1807141cc406Sopenharmony_ci deactivateOption(s, OPT_ADF_MODE, &dummy); 1808141cc406Sopenharmony_ci } 1809141cc406Sopenharmony_ci 1810141cc406Sopenharmony_ci /* special handling for FilmScan 200 */ 1811141cc406Sopenharmony_ci if (s->hw->cmd->level[0] == 'F') 1812141cc406Sopenharmony_ci activateOption(s, OPT_FILM_TYPE, &dummy); 1813141cc406Sopenharmony_ci 1814141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint.range = s->hw->x_range; 1815141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint.range = s->hw->y_range; 1816141cc406Sopenharmony_ci 1817141cc406Sopenharmony_ci if (s->val[OPT_TL_X].w < s->hw->x_range->min || force_max) 1818141cc406Sopenharmony_ci s->val[OPT_TL_X].w = s->hw->x_range->min; 1819141cc406Sopenharmony_ci 1820141cc406Sopenharmony_ci if (s->val[OPT_TL_Y].w < s->hw->y_range->min || force_max) 1821141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = s->hw->y_range->min; 1822141cc406Sopenharmony_ci 1823141cc406Sopenharmony_ci if (s->val[OPT_BR_X].w > s->hw->x_range->max || force_max) 1824141cc406Sopenharmony_ci s->val[OPT_BR_X].w = s->hw->x_range->max; 1825141cc406Sopenharmony_ci 1826141cc406Sopenharmony_ci if (s->val[OPT_BR_Y].w > s->hw->y_range->max || force_max) 1827141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = s->hw->y_range->max; 1828141cc406Sopenharmony_ci 1829141cc406Sopenharmony_ci setOptionState(s, s->hw->ADF 1830141cc406Sopenharmony_ci && s->hw->use_extension, OPT_AUTO_EJECT, &dummy); 1831141cc406Sopenharmony_ci setOptionState(s, s->hw->ADF 1832141cc406Sopenharmony_ci && s->hw->use_extension, OPT_EJECT, &dummy); 1833141cc406Sopenharmony_ci} 1834141cc406Sopenharmony_ci 1835141cc406Sopenharmony_cistatic SANE_Status 1836141cc406Sopenharmony_cisetvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info) 1837141cc406Sopenharmony_ci{ 1838141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 1839141cc406Sopenharmony_ci SANE_Option_Descriptor *sopt = &(s->opt[option]); 1840141cc406Sopenharmony_ci Option_Value *sval = &(s->val[option]); 1841141cc406Sopenharmony_ci 1842141cc406Sopenharmony_ci SANE_Status status; 1843141cc406Sopenharmony_ci const SANE_String_Const *optval = NULL; 1844141cc406Sopenharmony_ci int optindex = 0; 1845141cc406Sopenharmony_ci SANE_Bool reload = SANE_FALSE; 1846141cc406Sopenharmony_ci 1847141cc406Sopenharmony_ci DBG(17, "%s: option = %d, value = %p\n", __func__, option, value); 1848141cc406Sopenharmony_ci 1849141cc406Sopenharmony_ci status = sanei_constrain_value(sopt, value, info); 1850141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1851141cc406Sopenharmony_ci return status; 1852141cc406Sopenharmony_ci 1853141cc406Sopenharmony_ci if (info && value && (*info & SANE_INFO_INEXACT) 1854141cc406Sopenharmony_ci && sopt->type == SANE_TYPE_INT) 1855141cc406Sopenharmony_ci DBG(17, "%s: constrained val = %d\n", __func__, 1856141cc406Sopenharmony_ci *(SANE_Word *) value); 1857141cc406Sopenharmony_ci 1858141cc406Sopenharmony_ci if (sopt->constraint_type == SANE_CONSTRAINT_STRING_LIST) { 1859141cc406Sopenharmony_ci optval = search_string_list(sopt->constraint.string_list, 1860141cc406Sopenharmony_ci (char *) value); 1861141cc406Sopenharmony_ci if (optval == NULL) 1862141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1863141cc406Sopenharmony_ci optindex = optval - sopt->constraint.string_list; 1864141cc406Sopenharmony_ci } 1865141cc406Sopenharmony_ci 1866141cc406Sopenharmony_ci switch (option) { 1867141cc406Sopenharmony_ci 1868141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 1869141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 1870141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 1871141cc406Sopenharmony_ci case OPT_CCT_PROFILE: 1872141cc406Sopenharmony_ci memcpy(sval->wa, value, sopt->size); /* Word arrays */ 1873141cc406Sopenharmony_ci break; 1874141cc406Sopenharmony_ci 1875141cc406Sopenharmony_ci case OPT_CCT_MODE: 1876141cc406Sopenharmony_ci case OPT_ADF_MODE: 1877141cc406Sopenharmony_ci case OPT_DROPOUT: 1878141cc406Sopenharmony_ci case OPT_FILM_TYPE: 1879141cc406Sopenharmony_ci case OPT_BAY: 1880141cc406Sopenharmony_ci sval->w = optindex; /* Simple lists */ 1881141cc406Sopenharmony_ci break; 1882141cc406Sopenharmony_ci 1883141cc406Sopenharmony_ci case OPT_EJECT: 1884141cc406Sopenharmony_ci /* XXX required? control_extension(s, 1); */ 1885141cc406Sopenharmony_ci esci_eject(s); 1886141cc406Sopenharmony_ci break; 1887141cc406Sopenharmony_ci 1888141cc406Sopenharmony_ci case OPT_RESOLUTION: 1889141cc406Sopenharmony_ci sval->w = *((SANE_Word *) value); 1890141cc406Sopenharmony_ci DBG(17, "setting resolution to %d\n", sval->w); 1891141cc406Sopenharmony_ci reload = SANE_TRUE; 1892141cc406Sopenharmony_ci break; 1893141cc406Sopenharmony_ci 1894141cc406Sopenharmony_ci case OPT_BR_X: 1895141cc406Sopenharmony_ci case OPT_BR_Y: 1896141cc406Sopenharmony_ci if (SANE_UNFIX(*((SANE_Word *) value)) == 0) { 1897141cc406Sopenharmony_ci DBG(17, "invalid br-x or br-y\n"); 1898141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1899141cc406Sopenharmony_ci } 1900141cc406Sopenharmony_ci // fall through 1901141cc406Sopenharmony_ci case OPT_TL_X: 1902141cc406Sopenharmony_ci case OPT_TL_Y: 1903141cc406Sopenharmony_ci sval->w = *((SANE_Word *) value); 1904141cc406Sopenharmony_ci DBG(17, "setting size to %f\n", SANE_UNFIX(sval->w)); 1905141cc406Sopenharmony_ci if (NULL != info) 1906141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 1907141cc406Sopenharmony_ci break; 1908141cc406Sopenharmony_ci 1909141cc406Sopenharmony_ci case OPT_SOURCE: 1910141cc406Sopenharmony_ci change_source(s, optindex, (char *) value); 1911141cc406Sopenharmony_ci reload = SANE_TRUE; 1912141cc406Sopenharmony_ci break; 1913141cc406Sopenharmony_ci 1914141cc406Sopenharmony_ci case OPT_MODE: 1915141cc406Sopenharmony_ci { 1916141cc406Sopenharmony_ci SANE_Bool isColor = mode_params[optindex].color; 1917141cc406Sopenharmony_ci 1918141cc406Sopenharmony_ci sval->w = optindex; 1919141cc406Sopenharmony_ci 1920141cc406Sopenharmony_ci DBG(17, "%s: setting mode to %d\n", __func__, optindex); 1921141cc406Sopenharmony_ci 1922141cc406Sopenharmony_ci /* halftoning available only on bw scans */ 1923141cc406Sopenharmony_ci if (s->hw->cmd->set_halftoning != 0) 1924141cc406Sopenharmony_ci setOptionState(s, mode_params[optindex].depth == 1, 1925141cc406Sopenharmony_ci OPT_HALFTONE, &reload); 1926141cc406Sopenharmony_ci 1927141cc406Sopenharmony_ci /* disable dropout on non-color scans */ 1928141cc406Sopenharmony_ci setOptionState(s, !isColor, OPT_DROPOUT, &reload); 1929141cc406Sopenharmony_ci 1930141cc406Sopenharmony_ci if (s->hw->cmd->set_color_correction) 1931141cc406Sopenharmony_ci setOptionState(s, isColor, 1932141cc406Sopenharmony_ci OPT_COLOR_CORRECTION, &reload); 1933141cc406Sopenharmony_ci 1934141cc406Sopenharmony_ci /* if binary, then disable the bit depth selection */ 1935141cc406Sopenharmony_ci if (optindex == 0) { 1936141cc406Sopenharmony_ci DBG(17, "%s: disabling bit depth selection\n", __func__); 1937141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; 1938141cc406Sopenharmony_ci } else { 1939141cc406Sopenharmony_ci if (s->hw->depth_list[0] == 1) { 1940141cc406Sopenharmony_ci DBG(17, "%s: only one depth is available\n", __func__); 1941141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; 1942141cc406Sopenharmony_ci } else { 1943141cc406Sopenharmony_ci 1944141cc406Sopenharmony_ci DBG(17, "%s: enabling bit depth selection\n", __func__); 1945141cc406Sopenharmony_ci 1946141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].cap &= ~SANE_CAP_INACTIVE; 1947141cc406Sopenharmony_ci s->val[OPT_BIT_DEPTH].w = mode_params[optindex].depth; 1948141cc406Sopenharmony_ci } 1949141cc406Sopenharmony_ci } 1950141cc406Sopenharmony_ci 1951141cc406Sopenharmony_ci handle_depth_halftone(s, &reload); 1952141cc406Sopenharmony_ci reload = SANE_TRUE; 1953141cc406Sopenharmony_ci 1954141cc406Sopenharmony_ci break; 1955141cc406Sopenharmony_ci } 1956141cc406Sopenharmony_ci 1957141cc406Sopenharmony_ci case OPT_BIT_DEPTH: 1958141cc406Sopenharmony_ci sval->w = *((SANE_Word *) value); 1959141cc406Sopenharmony_ci mode_params[s->val[OPT_MODE].w].depth = sval->w; 1960141cc406Sopenharmony_ci reload = SANE_TRUE; 1961141cc406Sopenharmony_ci break; 1962141cc406Sopenharmony_ci 1963141cc406Sopenharmony_ci case OPT_HALFTONE: 1964141cc406Sopenharmony_ci sval->w = optindex; 1965141cc406Sopenharmony_ci handle_depth_halftone(s, &reload); 1966141cc406Sopenharmony_ci break; 1967141cc406Sopenharmony_ci 1968141cc406Sopenharmony_ci case OPT_COLOR_CORRECTION: 1969141cc406Sopenharmony_ci { 1970141cc406Sopenharmony_ci sval->w = optindex; 1971141cc406Sopenharmony_ci break; 1972141cc406Sopenharmony_ci } 1973141cc406Sopenharmony_ci 1974141cc406Sopenharmony_ci case OPT_GAMMA_CORRECTION: 1975141cc406Sopenharmony_ci { 1976141cc406Sopenharmony_ci SANE_Bool f = gamma_userdefined[optindex]; 1977141cc406Sopenharmony_ci 1978141cc406Sopenharmony_ci sval->w = optindex; 1979141cc406Sopenharmony_ci 1980141cc406Sopenharmony_ci setOptionState(s, f, OPT_GAMMA_VECTOR_R, &reload); 1981141cc406Sopenharmony_ci setOptionState(s, f, OPT_GAMMA_VECTOR_G, &reload); 1982141cc406Sopenharmony_ci setOptionState(s, f, OPT_GAMMA_VECTOR_B, &reload); 1983141cc406Sopenharmony_ci setOptionState(s, !f, OPT_BRIGHTNESS, &reload); /* Note... */ 1984141cc406Sopenharmony_ci 1985141cc406Sopenharmony_ci break; 1986141cc406Sopenharmony_ci } 1987141cc406Sopenharmony_ci 1988141cc406Sopenharmony_ci case OPT_AUTOFOCUS: 1989141cc406Sopenharmony_ci sval->w = *((SANE_Word *) value); 1990141cc406Sopenharmony_ci setOptionState(s, !sval->w, OPT_FOCUS_POS, &reload); 1991141cc406Sopenharmony_ci break; 1992141cc406Sopenharmony_ci 1993141cc406Sopenharmony_ci case OPT_MIRROR: 1994141cc406Sopenharmony_ci case OPT_AAS: 1995141cc406Sopenharmony_ci case OPT_PREVIEW: /* needed? */ 1996141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 1997141cc406Sopenharmony_ci case OPT_SHARPNESS: 1998141cc406Sopenharmony_ci case OPT_AUTO_EJECT: 1999141cc406Sopenharmony_ci case OPT_THRESHOLD: 2000141cc406Sopenharmony_ci case OPT_WAIT_FOR_BUTTON: 2001141cc406Sopenharmony_ci case OPT_FOCUS_POS: 2002141cc406Sopenharmony_ci sval->w = *((SANE_Word *) value); 2003141cc406Sopenharmony_ci break; 2004141cc406Sopenharmony_ci 2005141cc406Sopenharmony_ci default: 2006141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2007141cc406Sopenharmony_ci } 2008141cc406Sopenharmony_ci 2009141cc406Sopenharmony_ci if (reload && info != NULL) 2010141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 2011141cc406Sopenharmony_ci 2012141cc406Sopenharmony_ci DBG(17, "%s: end\n", __func__); 2013141cc406Sopenharmony_ci 2014141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2015141cc406Sopenharmony_ci} 2016141cc406Sopenharmony_ci 2017141cc406Sopenharmony_ciSANE_Status 2018141cc406Sopenharmony_cisane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, 2019141cc406Sopenharmony_ci void *value, SANE_Int *info) 2020141cc406Sopenharmony_ci{ 2021141cc406Sopenharmony_ci DBG(17, "%s: action = %x, option = %d\n", __func__, action, option); 2022141cc406Sopenharmony_ci 2023141cc406Sopenharmony_ci if (option < 0 || option >= NUM_OPTIONS) 2024141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2025141cc406Sopenharmony_ci 2026141cc406Sopenharmony_ci if (info != NULL) 2027141cc406Sopenharmony_ci *info = 0; 2028141cc406Sopenharmony_ci 2029141cc406Sopenharmony_ci switch (action) { 2030141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 2031141cc406Sopenharmony_ci return getvalue(handle, option, value); 2032141cc406Sopenharmony_ci 2033141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 2034141cc406Sopenharmony_ci return setvalue(handle, option, value, info); 2035141cc406Sopenharmony_ci 2036141cc406Sopenharmony_ci default: 2037141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2038141cc406Sopenharmony_ci } 2039141cc406Sopenharmony_ci 2040141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2041141cc406Sopenharmony_ci} 2042141cc406Sopenharmony_ci 2043141cc406Sopenharmony_ciSANE_Status 2044141cc406Sopenharmony_cisane_get_parameters(SANE_Handle handle, SANE_Parameters *params) 2045141cc406Sopenharmony_ci{ 2046141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 2047141cc406Sopenharmony_ci 2048141cc406Sopenharmony_ci DBG(5, "%s\n", __func__); 2049141cc406Sopenharmony_ci 2050141cc406Sopenharmony_ci if (params == NULL) 2051141cc406Sopenharmony_ci DBG(1, "%s: params is NULL\n", __func__); 2052141cc406Sopenharmony_ci 2053141cc406Sopenharmony_ci /* 2054141cc406Sopenharmony_ci * If sane_start was already called, then just retrieve the parameters 2055141cc406Sopenharmony_ci * from the scanner data structure 2056141cc406Sopenharmony_ci */ 2057141cc406Sopenharmony_ci 2058141cc406Sopenharmony_ci if (!s->eof && s->ptr != NULL) { 2059141cc406Sopenharmony_ci DBG(5, "scan in progress, returning saved params structure\n"); 2060141cc406Sopenharmony_ci } else { 2061141cc406Sopenharmony_ci /* otherwise initialize the params structure and gather the data */ 2062141cc406Sopenharmony_ci e2_init_parameters(s); 2063141cc406Sopenharmony_ci } 2064141cc406Sopenharmony_ci 2065141cc406Sopenharmony_ci if (params != NULL) 2066141cc406Sopenharmony_ci *params = s->params; 2067141cc406Sopenharmony_ci 2068141cc406Sopenharmony_ci print_params(s->params); 2069141cc406Sopenharmony_ci 2070141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2071141cc406Sopenharmony_ci} 2072141cc406Sopenharmony_ci 2073141cc406Sopenharmony_cistatic void e2_load_cct_profile(struct Epson_Scanner *s, unsigned int index) 2074141cc406Sopenharmony_ci{ 2075141cc406Sopenharmony_ci s->cct_table[0] = SANE_FIX(s->hw->cct_profile->cct[index][0]); 2076141cc406Sopenharmony_ci s->cct_table[1] = SANE_FIX(s->hw->cct_profile->cct[index][1]); 2077141cc406Sopenharmony_ci s->cct_table[2] = SANE_FIX(s->hw->cct_profile->cct[index][2]); 2078141cc406Sopenharmony_ci s->cct_table[3] = SANE_FIX(s->hw->cct_profile->cct[index][3]); 2079141cc406Sopenharmony_ci s->cct_table[4] = SANE_FIX(s->hw->cct_profile->cct[index][4]); 2080141cc406Sopenharmony_ci s->cct_table[5] = SANE_FIX(s->hw->cct_profile->cct[index][5]); 2081141cc406Sopenharmony_ci s->cct_table[6] = SANE_FIX(s->hw->cct_profile->cct[index][6]); 2082141cc406Sopenharmony_ci s->cct_table[7] = SANE_FIX(s->hw->cct_profile->cct[index][7]); 2083141cc406Sopenharmony_ci s->cct_table[8] = SANE_FIX(s->hw->cct_profile->cct[index][8]); 2084141cc406Sopenharmony_ci} 2085141cc406Sopenharmony_ci 2086141cc406Sopenharmony_ci/* 2087141cc406Sopenharmony_ci * This function is part of the SANE API and gets called from the front end to 2088141cc406Sopenharmony_ci * start the scan process. 2089141cc406Sopenharmony_ci */ 2090141cc406Sopenharmony_ci 2091141cc406Sopenharmony_ciSANE_Status 2092141cc406Sopenharmony_cisane_start(SANE_Handle handle) 2093141cc406Sopenharmony_ci{ 2094141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 2095141cc406Sopenharmony_ci Epson_Device *dev = s->hw; 2096141cc406Sopenharmony_ci SANE_Status status; 2097141cc406Sopenharmony_ci 2098141cc406Sopenharmony_ci DBG(5, "* %s\n", __func__); 2099141cc406Sopenharmony_ci 2100141cc406Sopenharmony_ci s->eof = SANE_FALSE; 2101141cc406Sopenharmony_ci s->canceling = SANE_FALSE; 2102141cc406Sopenharmony_ci 2103141cc406Sopenharmony_ci /* check if we just have finished working with the ADF */ 2104141cc406Sopenharmony_ci status = e2_check_adf(s); 2105141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2106141cc406Sopenharmony_ci return status; 2107141cc406Sopenharmony_ci 2108141cc406Sopenharmony_ci /* calc scanning parameters */ 2109141cc406Sopenharmony_ci status = e2_init_parameters(s); 2110141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2111141cc406Sopenharmony_ci return status; 2112141cc406Sopenharmony_ci 2113141cc406Sopenharmony_ci print_params(s->params); 2114141cc406Sopenharmony_ci 2115141cc406Sopenharmony_ci /* enable infrared */ 2116141cc406Sopenharmony_ci if (s->val[OPT_MODE].w == MODE_INFRARED) 2117141cc406Sopenharmony_ci esci_enable_infrared(handle); 2118141cc406Sopenharmony_ci 2119141cc406Sopenharmony_ci /* ESC , bay */ 2120141cc406Sopenharmony_ci if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_BAY].cap)) { 2121141cc406Sopenharmony_ci status = esci_set_bay(s, s->val[OPT_BAY].w); 2122141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2123141cc406Sopenharmony_ci return status; 2124141cc406Sopenharmony_ci } 2125141cc406Sopenharmony_ci 2126141cc406Sopenharmony_ci /* set scanning parameters */ 2127141cc406Sopenharmony_ci if (dev->extended_commands) 2128141cc406Sopenharmony_ci status = e2_set_extended_scanning_parameters(s); 2129141cc406Sopenharmony_ci else 2130141cc406Sopenharmony_ci status = e2_set_scanning_parameters(s); 2131141cc406Sopenharmony_ci 2132141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2133141cc406Sopenharmony_ci return status; 2134141cc406Sopenharmony_ci 2135141cc406Sopenharmony_ci /* 2136141cc406Sopenharmony_ci * set focus after we set scanning parameters because the scanner will 2137141cc406Sopenharmony_ci * use the middle of the scanning area for autofocus. If we want to 2138141cc406Sopenharmony_ci * support a defined x,y position for autofocus, we'd need to send 2139141cc406Sopenharmony_ci * specific scanning paramters just for autofocus. 2140141cc406Sopenharmony_ci */ 2141141cc406Sopenharmony_ci if (s->hw->focusSupport == SANE_TRUE) { 2142141cc406Sopenharmony_ci if (s->val[OPT_AUTOFOCUS].w) { 2143141cc406Sopenharmony_ci DBG(1, "setting autofocus\n"); 2144141cc406Sopenharmony_ci status = esci_set_focus_position(s, 0xff); 2145141cc406Sopenharmony_ci } else { 2146141cc406Sopenharmony_ci DBG(1, "setting focus to %u\n", s->val[OPT_FOCUS_POS].w); 2147141cc406Sopenharmony_ci status = esci_set_focus_position(s, s->val[OPT_FOCUS_POS].w); 2148141cc406Sopenharmony_ci } 2149141cc406Sopenharmony_ci 2150141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 2151141cc406Sopenharmony_ci DBG(1, "setting focus failed\n"); 2152141cc406Sopenharmony_ci return status; 2153141cc406Sopenharmony_ci } 2154141cc406Sopenharmony_ci } 2155141cc406Sopenharmony_ci 2156141cc406Sopenharmony_ci /* ESC z, user defined gamma table */ 2157141cc406Sopenharmony_ci if (dev->cmd->set_gamma_table 2158141cc406Sopenharmony_ci && gamma_userdefined[s->val[OPT_GAMMA_CORRECTION].w]) { 2159141cc406Sopenharmony_ci status = esci_set_gamma_table(s); 2160141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2161141cc406Sopenharmony_ci return status; 2162141cc406Sopenharmony_ci } 2163141cc406Sopenharmony_ci 2164141cc406Sopenharmony_ci 2165141cc406Sopenharmony_ci if (s->val[OPT_COLOR_CORRECTION].w == CORR_AUTO) { /* Automatic */ 2166141cc406Sopenharmony_ci 2167141cc406Sopenharmony_ci DBG(1, "using built in CCT profile\n"); 2168141cc406Sopenharmony_ci 2169141cc406Sopenharmony_ci if (dev->model_id == 0) 2170141cc406Sopenharmony_ci DBG(1, " specific profile not available, using default\n"); 2171141cc406Sopenharmony_ci 2172141cc406Sopenharmony_ci 2173141cc406Sopenharmony_ci if (0) { /* XXX TPU */ 2174141cc406Sopenharmony_ci 2175141cc406Sopenharmony_ci /* XXX check this */ 2176141cc406Sopenharmony_ci if (s->val[OPT_FILM_TYPE].w == 0) 2177141cc406Sopenharmony_ci e2_load_cct_profile(s, CCTP_COLORPOS); 2178141cc406Sopenharmony_ci else 2179141cc406Sopenharmony_ci e2_load_cct_profile(s, CCTP_COLORNEG); 2180141cc406Sopenharmony_ci 2181141cc406Sopenharmony_ci } else { 2182141cc406Sopenharmony_ci e2_load_cct_profile(s, CCTP_REFLECTIVE); 2183141cc406Sopenharmony_ci } 2184141cc406Sopenharmony_ci } 2185141cc406Sopenharmony_ci 2186141cc406Sopenharmony_ci /* ESC m, user defined color correction */ 2187141cc406Sopenharmony_ci if (s->hw->cmd->set_color_correction_coefficients 2188141cc406Sopenharmony_ci && correction_userdefined[s->val[OPT_COLOR_CORRECTION].w]) { 2189141cc406Sopenharmony_ci 2190141cc406Sopenharmony_ci status = esci_set_color_correction_coefficients(s, 2191141cc406Sopenharmony_ci s->cct_table); 2192141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2193141cc406Sopenharmony_ci return status; 2194141cc406Sopenharmony_ci } 2195141cc406Sopenharmony_ci 2196141cc406Sopenharmony_ci /* check if we just have finished working with the ADF. 2197141cc406Sopenharmony_ci * this seems to work only after the scanner has been 2198141cc406Sopenharmony_ci * set up with scanning parameters 2199141cc406Sopenharmony_ci */ 2200141cc406Sopenharmony_ci status = e2_check_adf(s); 2201141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2202141cc406Sopenharmony_ci return status; 2203141cc406Sopenharmony_ci 2204141cc406Sopenharmony_ci /* 2205141cc406Sopenharmony_ci * If WAIT_FOR_BUTTON is active, then do just that: 2206141cc406Sopenharmony_ci * Wait until the button is pressed. If the button was already 2207141cc406Sopenharmony_ci * pressed, then we will get the button pressed event right away. 2208141cc406Sopenharmony_ci */ 2209141cc406Sopenharmony_ci if (s->val[OPT_WAIT_FOR_BUTTON].w == SANE_TRUE) 2210141cc406Sopenharmony_ci e2_wait_button(s); 2211141cc406Sopenharmony_ci 2212141cc406Sopenharmony_ci /* for debug, request command parameter */ 2213141cc406Sopenharmony_ci/* if (DBG_LEVEL) { 2214141cc406Sopenharmony_ci unsigned char buf[45]; 2215141cc406Sopenharmony_ci request_command_parameter(s, buf); 2216141cc406Sopenharmony_ci } 2217141cc406Sopenharmony_ci*/ 2218141cc406Sopenharmony_ci /* set the retry count to 0 */ 2219141cc406Sopenharmony_ci s->retry_count = 0; 2220141cc406Sopenharmony_ci 2221141cc406Sopenharmony_ci /* allocate buffers for color shuffling */ 2222141cc406Sopenharmony_ci if (dev->color_shuffle == SANE_TRUE) { 2223141cc406Sopenharmony_ci int i; 2224141cc406Sopenharmony_ci /* initialize the line buffers */ 2225141cc406Sopenharmony_ci for (i = 0; i < s->line_distance * 2 + 1; i++) { 2226141cc406Sopenharmony_ci 2227141cc406Sopenharmony_ci if (s->line_buffer[i] != NULL) 2228141cc406Sopenharmony_ci free(s->line_buffer[i]); 2229141cc406Sopenharmony_ci 2230141cc406Sopenharmony_ci s->line_buffer[i] = malloc(s->params.bytes_per_line); 2231141cc406Sopenharmony_ci if (s->line_buffer[i] == NULL) { 2232141cc406Sopenharmony_ci DBG(1, "out of memory (line %d)\n", __LINE__); 2233141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2234141cc406Sopenharmony_ci } 2235141cc406Sopenharmony_ci } 2236141cc406Sopenharmony_ci } 2237141cc406Sopenharmony_ci 2238141cc406Sopenharmony_ci /* prepare buffer here so that a memory allocation failure 2239141cc406Sopenharmony_ci * will leave the scanner in a sane state. 2240141cc406Sopenharmony_ci * the buffer will have to hold the image data plus 2241141cc406Sopenharmony_ci * an error code in the extended handshaking mode. 2242141cc406Sopenharmony_ci */ 2243141cc406Sopenharmony_ci s->buf = realloc(s->buf, (s->lcount * s->params.bytes_per_line) + 1); 2244141cc406Sopenharmony_ci if (s->buf == NULL) 2245141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2246141cc406Sopenharmony_ci 2247141cc406Sopenharmony_ci s->ptr = s->end = s->buf; 2248141cc406Sopenharmony_ci 2249141cc406Sopenharmony_ci /* feed the first sheet in the ADF */ 2250141cc406Sopenharmony_ci if (dev->ADF && dev->use_extension && dev->cmd->feed) { 2251141cc406Sopenharmony_ci status = esci_feed(s); 2252141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2253141cc406Sopenharmony_ci return status; 2254141cc406Sopenharmony_ci } 2255141cc406Sopenharmony_ci 2256141cc406Sopenharmony_ci /* this seems to work only for some devices */ 2257141cc406Sopenharmony_ci status = e2_wait_warm_up(s); 2258141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2259141cc406Sopenharmony_ci return status; 2260141cc406Sopenharmony_ci 2261141cc406Sopenharmony_ci if (s->hw->focusSupport == SANE_TRUE && s->val[OPT_AUTOFOCUS].w) { 2262141cc406Sopenharmony_ci status = esci_request_focus_position(s, &s->currentFocusPosition); 2263141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) 2264141cc406Sopenharmony_ci s->val[OPT_FOCUS_POS].w = s->currentFocusPosition; 2265141cc406Sopenharmony_ci } 2266141cc406Sopenharmony_ci 2267141cc406Sopenharmony_ci /* start scanning */ 2268141cc406Sopenharmony_ci DBG(1, "%s: scanning...\n", __func__); 2269141cc406Sopenharmony_ci 2270141cc406Sopenharmony_ci if (dev->extended_commands) { 2271141cc406Sopenharmony_ci status = e2_start_ext_scan(s); 2272141cc406Sopenharmony_ci 2273141cc406Sopenharmony_ci /* sometimes the scanner gives an io error when 2274141cc406Sopenharmony_ci * it's warming up. 2275141cc406Sopenharmony_ci */ 2276141cc406Sopenharmony_ci if (status == SANE_STATUS_IO_ERROR) { 2277141cc406Sopenharmony_ci status = e2_wait_warm_up(s); 2278141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) 2279141cc406Sopenharmony_ci status = e2_start_ext_scan(s); 2280141cc406Sopenharmony_ci } 2281141cc406Sopenharmony_ci } else 2282141cc406Sopenharmony_ci status = e2_start_std_scan(s); 2283141cc406Sopenharmony_ci 2284141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 2285141cc406Sopenharmony_ci DBG(1, "%s: start failed: %s\n", __func__, 2286141cc406Sopenharmony_ci sane_strstatus(status)); 2287141cc406Sopenharmony_ci 2288141cc406Sopenharmony_ci return status; 2289141cc406Sopenharmony_ci } 2290141cc406Sopenharmony_ci 2291141cc406Sopenharmony_ci /* this is a kind of read request */ 2292141cc406Sopenharmony_ci if (dev->connection == SANE_EPSON_NET) { 2293141cc406Sopenharmony_ci sanei_epson_net_write(s, 0x2000, NULL, 0, 2294141cc406Sopenharmony_ci s->ext_block_len + 1, &status); 2295141cc406Sopenharmony_ci } 2296141cc406Sopenharmony_ci 2297141cc406Sopenharmony_ci return status; 2298141cc406Sopenharmony_ci} 2299141cc406Sopenharmony_ci 2300141cc406Sopenharmony_ci/* this moves data from our buffers to SANE */ 2301141cc406Sopenharmony_ci 2302141cc406Sopenharmony_ciSANE_Status 2303141cc406Sopenharmony_cisane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length, 2304141cc406Sopenharmony_ci SANE_Int *length) 2305141cc406Sopenharmony_ci{ 2306141cc406Sopenharmony_ci SANE_Status status; 2307141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 2308141cc406Sopenharmony_ci 2309141cc406Sopenharmony_ci DBG(18, "* %s: eof: %d, canceling: %d\n", 2310141cc406Sopenharmony_ci __func__, s->eof, s->canceling); 2311141cc406Sopenharmony_ci 2312141cc406Sopenharmony_ci /* sane_read called before sane_start? */ 2313141cc406Sopenharmony_ci if (s->buf == NULL) { 2314141cc406Sopenharmony_ci DBG(1, "%s: buffer is NULL", __func__); 2315141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2316141cc406Sopenharmony_ci } 2317141cc406Sopenharmony_ci 2318141cc406Sopenharmony_ci *length = 0; 2319141cc406Sopenharmony_ci 2320141cc406Sopenharmony_ci if (s->hw->extended_commands) 2321141cc406Sopenharmony_ci status = e2_ext_read(s); 2322141cc406Sopenharmony_ci else 2323141cc406Sopenharmony_ci status = e2_block_read(s); 2324141cc406Sopenharmony_ci 2325141cc406Sopenharmony_ci /* The scanning operation might be canceled by the scanner itself 2326141cc406Sopenharmony_ci * or the fronted program 2327141cc406Sopenharmony_ci */ 2328141cc406Sopenharmony_ci if (status == SANE_STATUS_CANCELLED || s->canceling) { 2329141cc406Sopenharmony_ci e2_scan_finish(s); 2330141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 2331141cc406Sopenharmony_ci } 2332141cc406Sopenharmony_ci 2333141cc406Sopenharmony_ci /* XXX if FS G and STATUS_IOERR, use e2_check_extended_status */ 2334141cc406Sopenharmony_ci 2335141cc406Sopenharmony_ci DBG(18, "moving data %p %p, %d (%d lines)\n", 2336141cc406Sopenharmony_ci (void *) s->ptr, (void *) s->end, 2337141cc406Sopenharmony_ci max_length, max_length / s->params.bytes_per_line); 2338141cc406Sopenharmony_ci 2339141cc406Sopenharmony_ci e2_copy_image_data(s, data, max_length, length); 2340141cc406Sopenharmony_ci 2341141cc406Sopenharmony_ci DBG(18, "%d lines read, eof: %d, canceling: %d, status: %d\n", 2342141cc406Sopenharmony_ci *length / s->params.bytes_per_line, 2343141cc406Sopenharmony_ci s->canceling, s->eof, status); 2344141cc406Sopenharmony_ci 2345141cc406Sopenharmony_ci /* continue reading if appropriate */ 2346141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) 2347141cc406Sopenharmony_ci return status; 2348141cc406Sopenharmony_ci 2349141cc406Sopenharmony_ci e2_scan_finish(s); 2350141cc406Sopenharmony_ci 2351141cc406Sopenharmony_ci return status; 2352141cc406Sopenharmony_ci} 2353141cc406Sopenharmony_ci 2354141cc406Sopenharmony_ci/* 2355141cc406Sopenharmony_ci * void sane_cancel(SANE_Handle handle) 2356141cc406Sopenharmony_ci * 2357141cc406Sopenharmony_ci * Set the cancel flag to true. The next time the backend requests data 2358141cc406Sopenharmony_ci * from the scanner the CAN message will be sent. 2359141cc406Sopenharmony_ci */ 2360141cc406Sopenharmony_ci 2361141cc406Sopenharmony_civoid 2362141cc406Sopenharmony_cisane_cancel(SANE_Handle handle) 2363141cc406Sopenharmony_ci{ 2364141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 2365141cc406Sopenharmony_ci 2366141cc406Sopenharmony_ci DBG(1, "* %s\n", __func__); 2367141cc406Sopenharmony_ci 2368141cc406Sopenharmony_ci s->canceling = SANE_TRUE; 2369141cc406Sopenharmony_ci} 2370141cc406Sopenharmony_ci 2371141cc406Sopenharmony_ci/* 2372141cc406Sopenharmony_ci * SANE_Status sane_set_io_mode() 2373141cc406Sopenharmony_ci * 2374141cc406Sopenharmony_ci * not supported - for asynchronous I/O 2375141cc406Sopenharmony_ci */ 2376141cc406Sopenharmony_ci 2377141cc406Sopenharmony_ciSANE_Status 2378141cc406Sopenharmony_cisane_set_io_mode(SANE_Handle __sane_unused__ handle, 2379141cc406Sopenharmony_ci SANE_Bool __sane_unused__ non_blocking) 2380141cc406Sopenharmony_ci{ 2381141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 2382141cc406Sopenharmony_ci} 2383141cc406Sopenharmony_ci 2384141cc406Sopenharmony_ci/* 2385141cc406Sopenharmony_ci * SANE_Status sane_get_select_fd() 2386141cc406Sopenharmony_ci * 2387141cc406Sopenharmony_ci * not supported - for asynchronous I/O 2388141cc406Sopenharmony_ci */ 2389141cc406Sopenharmony_ci 2390141cc406Sopenharmony_ciSANE_Status 2391141cc406Sopenharmony_cisane_get_select_fd(SANE_Handle __sane_unused__ handle, 2392141cc406Sopenharmony_ci SANE_Int __sane_unused__ *fd) 2393141cc406Sopenharmony_ci{ 2394141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 2395141cc406Sopenharmony_ci} 2396