1141cc406Sopenharmony_ci/* ========================================================================= */ 2141cc406Sopenharmony_ci/* 3141cc406Sopenharmony_ci SANE - Scanner Access Now Easy. 4141cc406Sopenharmony_ci coolscan2.c , version 0.1.8 5141cc406Sopenharmony_ci 6141cc406Sopenharmony_ci This file is part of the SANE package. 7141cc406Sopenharmony_ci 8141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 9141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 10141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 11141cc406Sopenharmony_ci License, or (at your option) any later version. 12141cc406Sopenharmony_ci 13141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 14141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 15141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16141cc406Sopenharmony_ci General Public License for more details. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 19141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 20141cc406Sopenharmony_ci 21141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 22141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 23141cc406Sopenharmony_ci 24141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 25141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 26141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 27141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 28141cc406Sopenharmony_ci account of linking the SANE library code into it. 29141cc406Sopenharmony_ci 30141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 31141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 32141cc406Sopenharmony_ci License. 33141cc406Sopenharmony_ci 34141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 35141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 36141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 37141cc406Sopenharmony_ci 38141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 39141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 40141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 41141cc406Sopenharmony_ci 42141cc406Sopenharmony_ci This file implements a SANE backend for Nikon Coolscan film scanners. 43141cc406Sopenharmony_ci 44141cc406Sopenharmony_ci Written by András Major (andras@users.sourceforge.net), 2001-2002. 45141cc406Sopenharmony_ci 46141cc406Sopenharmony_ci The developers wish to express their thanks to Nikon Corporation 47141cc406Sopenharmony_ci for providing technical information and thus making this backend 48141cc406Sopenharmony_ci possible. 49141cc406Sopenharmony_ci*/ 50141cc406Sopenharmony_ci/* ========================================================================= */ 51141cc406Sopenharmony_ci 52141cc406Sopenharmony_ci 53141cc406Sopenharmony_ci/* ========================================================================= */ 54141cc406Sopenharmony_ci/* 55141cc406Sopenharmony_ci Revision log: 56141cc406Sopenharmony_ci 57141cc406Sopenharmony_ci 0.1.9, 20/10/2005, ariel: added support for the LS-50/5000 58141cc406Sopenharmony_ci 0.1.8, 27/09/2002, andras: added subframe and load options 59141cc406Sopenharmony_ci 0.1.7, 22/08/2002, andras: added exposure correction option 60141cc406Sopenharmony_ci and hack for LS-40 IR readout 61141cc406Sopenharmony_ci 0.1.6, 14/06/2002, andras: types etc. fixed, fixes for LS-8000 62141cc406Sopenharmony_ci 0.1.5, 26/04/2002, andras: lots of minor fixes related to saned 63141cc406Sopenharmony_ci 0.1.4, 22/04/2002, andras: first version to be included in SANE CVS 64141cc406Sopenharmony_ci 65141cc406Sopenharmony_ci*/ 66141cc406Sopenharmony_ci/* ========================================================================= */ 67141cc406Sopenharmony_ci 68141cc406Sopenharmony_ci#ifdef _AIX 69141cc406Sopenharmony_ci# include "../include/lalloca.h" /* MUST come first for AIX! */ 70141cc406Sopenharmony_ci#endif 71141cc406Sopenharmony_ci#include "../include/sane/config.h" 72141cc406Sopenharmony_ci#include "../include/lalloca.h" 73141cc406Sopenharmony_ci 74141cc406Sopenharmony_ci#include <math.h> 75141cc406Sopenharmony_ci#include <stdio.h> 76141cc406Sopenharmony_ci#include <stdlib.h> 77141cc406Sopenharmony_ci#include <string.h> 78141cc406Sopenharmony_ci#include <ctype.h> 79141cc406Sopenharmony_ci#include <unistd.h> 80141cc406Sopenharmony_ci#include <time.h> 81141cc406Sopenharmony_ci/* 82141cc406Sopenharmony_ci#include <limits.h> 83141cc406Sopenharmony_ci#include <sys/types.h> 84141cc406Sopenharmony_ci*/ 85141cc406Sopenharmony_ci 86141cc406Sopenharmony_ci#include "../include/_stdint.h" 87141cc406Sopenharmony_ci 88141cc406Sopenharmony_ci#include "../include/sane/sane.h" 89141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 90141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 91141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h" 92141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h" 93141cc406Sopenharmony_ci#include "../include/sane/sanei_debug.h" 94141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 95141cc406Sopenharmony_ci#define BACKEND_NAME coolscan2 96141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" /* must be last */ 97141cc406Sopenharmony_ci 98141cc406Sopenharmony_ci#define CS2_VERSION_MAJOR 0 99141cc406Sopenharmony_ci#define CS2_VERSION_MINOR 1 100141cc406Sopenharmony_ci#define CS2_REVISION 8 101141cc406Sopenharmony_ci#define CS2_CONFIG_FILE "coolscan2.conf" 102141cc406Sopenharmony_ci 103141cc406Sopenharmony_ci#define WSIZE (sizeof (SANE_Word)) 104141cc406Sopenharmony_ci 105141cc406Sopenharmony_ci/* 106141cc406Sopenharmony_ci#define CS2_BLEEDING_EDGE 107141cc406Sopenharmony_ci*/ 108141cc406Sopenharmony_ci 109141cc406Sopenharmony_ci 110141cc406Sopenharmony_ci/* ========================================================================= */ 111141cc406Sopenharmony_ci/* typedefs */ 112141cc406Sopenharmony_ci 113141cc406Sopenharmony_citypedef enum 114141cc406Sopenharmony_ci{ 115141cc406Sopenharmony_ci CS2_TYPE_UNKOWN, 116141cc406Sopenharmony_ci CS2_TYPE_LS30, 117141cc406Sopenharmony_ci CS2_TYPE_LS40, 118141cc406Sopenharmony_ci CS2_TYPE_LS50, 119141cc406Sopenharmony_ci CS2_TYPE_LS2000, 120141cc406Sopenharmony_ci CS2_TYPE_LS4000, 121141cc406Sopenharmony_ci CS2_TYPE_LS5000, 122141cc406Sopenharmony_ci CS2_TYPE_LS8000 123141cc406Sopenharmony_ci} 124141cc406Sopenharmony_cics2_type_t; 125141cc406Sopenharmony_ci 126141cc406Sopenharmony_citypedef enum 127141cc406Sopenharmony_ci{ 128141cc406Sopenharmony_ci CS2_INTERFACE_UNKNOWN, 129141cc406Sopenharmony_ci CS2_INTERFACE_SCSI, /* includes IEEE1394 via SBP2 */ 130141cc406Sopenharmony_ci CS2_INTERFACE_USB 131141cc406Sopenharmony_ci} 132141cc406Sopenharmony_cics2_interface_t; 133141cc406Sopenharmony_ci 134141cc406Sopenharmony_citypedef enum 135141cc406Sopenharmony_ci{ 136141cc406Sopenharmony_ci CS2_PHASE_NONE = 0x00, 137141cc406Sopenharmony_ci CS2_PHASE_STATUS = 0x01, 138141cc406Sopenharmony_ci CS2_PHASE_OUT = 0x02, 139141cc406Sopenharmony_ci CS2_PHASE_IN = 0x03, 140141cc406Sopenharmony_ci CS2_PHASE_BUSY = 0x04 141141cc406Sopenharmony_ci} 142141cc406Sopenharmony_cics2_phase_t; 143141cc406Sopenharmony_ci 144141cc406Sopenharmony_citypedef enum 145141cc406Sopenharmony_ci{ 146141cc406Sopenharmony_ci CS2_SCAN_NORMAL, 147141cc406Sopenharmony_ci CS2_SCAN_AE, 148141cc406Sopenharmony_ci CS2_SCAN_AE_WB 149141cc406Sopenharmony_ci} 150141cc406Sopenharmony_cics2_scan_t; 151141cc406Sopenharmony_ci 152141cc406Sopenharmony_citypedef enum 153141cc406Sopenharmony_ci{ 154141cc406Sopenharmony_ci CS2_INFRARED_OFF, 155141cc406Sopenharmony_ci CS2_INFRARED_IN, 156141cc406Sopenharmony_ci CS2_INFRARED_OUT 157141cc406Sopenharmony_ci} 158141cc406Sopenharmony_cics2_infrared_t; 159141cc406Sopenharmony_ci 160141cc406Sopenharmony_citypedef enum 161141cc406Sopenharmony_ci{ 162141cc406Sopenharmony_ci CS2_STATUS_READY = 0, 163141cc406Sopenharmony_ci CS2_STATUS_BUSY = 1, 164141cc406Sopenharmony_ci CS2_STATUS_NO_DOCS = 2, 165141cc406Sopenharmony_ci CS2_STATUS_PROCESSING = 4, 166141cc406Sopenharmony_ci CS2_STATUS_ERROR = 8, 167141cc406Sopenharmony_ci CS2_STATUS_REISSUE = 16, 168141cc406Sopenharmony_ci CS2_STATUS_ALL = 31 /* sum of all others */ 169141cc406Sopenharmony_ci} 170141cc406Sopenharmony_cics2_status_t; 171141cc406Sopenharmony_ci 172141cc406Sopenharmony_citypedef enum 173141cc406Sopenharmony_ci{ 174141cc406Sopenharmony_ci CS2_OPTION_NUM = 0, 175141cc406Sopenharmony_ci 176141cc406Sopenharmony_ci CS2_OPTION_PREVIEW, 177141cc406Sopenharmony_ci 178141cc406Sopenharmony_ci CS2_OPTION_NEGATIVE, 179141cc406Sopenharmony_ci 180141cc406Sopenharmony_ci CS2_OPTION_INFRARED, 181141cc406Sopenharmony_ci 182141cc406Sopenharmony_ci CS2_OPTION_SAMPLES_PER_SCAN, 183141cc406Sopenharmony_ci 184141cc406Sopenharmony_ci CS2_OPTION_DEPTH, 185141cc406Sopenharmony_ci 186141cc406Sopenharmony_ci CS2_OPTION_EXPOSURE, 187141cc406Sopenharmony_ci CS2_OPTION_EXPOSURE_R, 188141cc406Sopenharmony_ci CS2_OPTION_EXPOSURE_G, 189141cc406Sopenharmony_ci CS2_OPTION_EXPOSURE_B, 190141cc406Sopenharmony_ci CS2_OPTION_SCAN_AE, 191141cc406Sopenharmony_ci CS2_OPTION_SCAN_AE_WB, 192141cc406Sopenharmony_ci 193141cc406Sopenharmony_ci CS2_OPTION_LUT_R, 194141cc406Sopenharmony_ci CS2_OPTION_LUT_G, 195141cc406Sopenharmony_ci CS2_OPTION_LUT_B, 196141cc406Sopenharmony_ci 197141cc406Sopenharmony_ci CS2_OPTION_RES, 198141cc406Sopenharmony_ci CS2_OPTION_RESX, 199141cc406Sopenharmony_ci CS2_OPTION_RESY, 200141cc406Sopenharmony_ci CS2_OPTION_RES_INDEPENDENT, 201141cc406Sopenharmony_ci 202141cc406Sopenharmony_ci CS2_OPTION_PREVIEW_RESOLUTION, 203141cc406Sopenharmony_ci 204141cc406Sopenharmony_ci CS2_OPTION_FRAME, 205141cc406Sopenharmony_ci CS2_OPTION_SUBFRAME, 206141cc406Sopenharmony_ci CS2_OPTION_XMIN, 207141cc406Sopenharmony_ci CS2_OPTION_XMAX, 208141cc406Sopenharmony_ci CS2_OPTION_YMIN, 209141cc406Sopenharmony_ci CS2_OPTION_YMAX, 210141cc406Sopenharmony_ci 211141cc406Sopenharmony_ci CS2_OPTION_LOAD, 212141cc406Sopenharmony_ci CS2_OPTION_EJECT, 213141cc406Sopenharmony_ci CS2_OPTION_RESET, 214141cc406Sopenharmony_ci 215141cc406Sopenharmony_ci CS2_OPTION_FOCUS_ON_CENTRE, 216141cc406Sopenharmony_ci CS2_OPTION_FOCUS, 217141cc406Sopenharmony_ci CS2_OPTION_AUTOFOCUS, 218141cc406Sopenharmony_ci CS2_OPTION_FOCUSX, 219141cc406Sopenharmony_ci CS2_OPTION_FOCUSY, 220141cc406Sopenharmony_ci 221141cc406Sopenharmony_ci CS2_N_OPTIONS /* must be last -- counts number of enum items */ 222141cc406Sopenharmony_ci} 223141cc406Sopenharmony_cics2_option_t; 224141cc406Sopenharmony_ci 225141cc406Sopenharmony_citypedef unsigned int cs2_pixel_t; 226141cc406Sopenharmony_ci 227141cc406Sopenharmony_citypedef struct 228141cc406Sopenharmony_ci{ 229141cc406Sopenharmony_ci /* interface */ 230141cc406Sopenharmony_ci cs2_interface_t interface; 231141cc406Sopenharmony_ci int fd; 232141cc406Sopenharmony_ci SANE_Byte *send_buf, *recv_buf; 233141cc406Sopenharmony_ci size_t send_buf_size, recv_buf_size; 234141cc406Sopenharmony_ci size_t n_cmd, n_send, n_recv; 235141cc406Sopenharmony_ci 236141cc406Sopenharmony_ci /* device characteristics */ 237141cc406Sopenharmony_ci char vendor_string[9], product_string[17], revision_string[5]; 238141cc406Sopenharmony_ci cs2_type_t type; 239141cc406Sopenharmony_ci int maxbits; 240141cc406Sopenharmony_ci unsigned int resx_optical, resx_min, resx_max, *resx_list, resx_n_list; 241141cc406Sopenharmony_ci unsigned int resy_optical, resy_min, resy_max, *resy_list, resy_n_list; 242141cc406Sopenharmony_ci unsigned long boundaryx, boundaryy; 243141cc406Sopenharmony_ci unsigned long frame_offset; 244141cc406Sopenharmony_ci unsigned int unit_dpi; 245141cc406Sopenharmony_ci double unit_mm; 246141cc406Sopenharmony_ci int n_frames; 247141cc406Sopenharmony_ci 248141cc406Sopenharmony_ci int focus_min, focus_max; 249141cc406Sopenharmony_ci 250141cc406Sopenharmony_ci /* settings */ 251141cc406Sopenharmony_ci SANE_Bool preview, negative, infrared; 252141cc406Sopenharmony_ci int samples_per_scan, depth, real_depth, bytes_per_pixel, shift_bits, 253141cc406Sopenharmony_ci n_colour_in, n_colour_out; 254141cc406Sopenharmony_ci cs2_pixel_t n_lut; 255141cc406Sopenharmony_ci cs2_pixel_t *lut_r, *lut_g, *lut_b, *lut_neutral; 256141cc406Sopenharmony_ci unsigned long resx, resy, res, res_independent, res_preview; 257141cc406Sopenharmony_ci unsigned long xmin, xmax, ymin, ymax; 258141cc406Sopenharmony_ci int i_frame; 259141cc406Sopenharmony_ci double subframe; 260141cc406Sopenharmony_ci 261141cc406Sopenharmony_ci unsigned int real_resx, real_resy, real_pitchx, real_pitchy; 262141cc406Sopenharmony_ci unsigned long real_xoffset, real_yoffset, real_width, real_height, 263141cc406Sopenharmony_ci logical_width, logical_height; 264141cc406Sopenharmony_ci int odd_padding; 265141cc406Sopenharmony_ci int block_padding; 266141cc406Sopenharmony_ci 267141cc406Sopenharmony_ci double exposure, exposure_r, exposure_g, exposure_b; 268141cc406Sopenharmony_ci unsigned long real_exposure[10]; 269141cc406Sopenharmony_ci 270141cc406Sopenharmony_ci SANE_Bool focus_on_centre; 271141cc406Sopenharmony_ci unsigned long focusx, focusy, real_focusx, real_focusy; 272141cc406Sopenharmony_ci int focus; 273141cc406Sopenharmony_ci 274141cc406Sopenharmony_ci /* status */ 275141cc406Sopenharmony_ci SANE_Bool scanning; 276141cc406Sopenharmony_ci cs2_infrared_t infrared_stage, infrared_next; 277141cc406Sopenharmony_ci SANE_Byte *infrared_buf; 278141cc406Sopenharmony_ci size_t n_infrared_buf, infrared_index; 279141cc406Sopenharmony_ci SANE_Byte *line_buf; 280141cc406Sopenharmony_ci ssize_t n_line_buf, i_line_buf; 281141cc406Sopenharmony_ci unsigned long sense_key, sense_asc, sense_ascq, sense_info; 282141cc406Sopenharmony_ci unsigned long sense_code; 283141cc406Sopenharmony_ci cs2_status_t status; 284141cc406Sopenharmony_ci size_t xfer_position, xfer_bytes_total; 285141cc406Sopenharmony_ci 286141cc406Sopenharmony_ci /* SANE stuff */ 287141cc406Sopenharmony_ci SANE_Option_Descriptor option_list[CS2_N_OPTIONS]; 288141cc406Sopenharmony_ci} 289141cc406Sopenharmony_cics2_t; 290141cc406Sopenharmony_ci 291141cc406Sopenharmony_ci 292141cc406Sopenharmony_ci/* ========================================================================= */ 293141cc406Sopenharmony_ci/* prototypes */ 294141cc406Sopenharmony_ci 295141cc406Sopenharmony_cistatic SANE_Status cs2_open (const char *device, cs2_interface_t interface, 296141cc406Sopenharmony_ci cs2_t ** sp); 297141cc406Sopenharmony_cistatic void cs2_close (cs2_t * s); 298141cc406Sopenharmony_cistatic SANE_Status cs2_attach (const char *dev); 299141cc406Sopenharmony_cistatic SANE_Status cs2_scsi_sense_handler (int fd, u_char * sense_buffer, 300141cc406Sopenharmony_ci void *arg); 301141cc406Sopenharmony_cistatic SANE_Status cs2_parse_sense_data (cs2_t * s); 302141cc406Sopenharmony_cistatic void cs2_init_buffer (cs2_t * s); 303141cc406Sopenharmony_cistatic SANE_Status cs2_pack_byte (cs2_t * s, SANE_Byte byte); 304141cc406Sopenharmony_cistatic SANE_Status cs2_parse_cmd (cs2_t * s, char *text); 305141cc406Sopenharmony_cistatic SANE_Status cs2_grow_send_buffer (cs2_t * s); 306141cc406Sopenharmony_cistatic SANE_Status cs2_issue_cmd (cs2_t * s); 307141cc406Sopenharmony_cistatic cs2_phase_t cs2_phase_check (cs2_t * s); 308141cc406Sopenharmony_cistatic SANE_Status cs2_set_boundary (cs2_t *s); 309141cc406Sopenharmony_cistatic SANE_Status cs2_scanner_ready (cs2_t * s, int flags); 310141cc406Sopenharmony_cistatic SANE_Status cs2_page_inquiry (cs2_t * s, int page); 311141cc406Sopenharmony_cistatic SANE_Status cs2_full_inquiry (cs2_t * s); 312141cc406Sopenharmony_cistatic SANE_Status cs2_execute (cs2_t * s); 313141cc406Sopenharmony_cistatic SANE_Status cs2_load (cs2_t * s); 314141cc406Sopenharmony_cistatic SANE_Status cs2_eject (cs2_t * s); 315141cc406Sopenharmony_cistatic SANE_Status cs2_reset (cs2_t * s); 316141cc406Sopenharmony_cistatic SANE_Status cs2_focus (cs2_t * s); 317141cc406Sopenharmony_cistatic SANE_Status cs2_autofocus (cs2_t * s); 318141cc406Sopenharmony_cistatic SANE_Status cs2_get_exposure (cs2_t * s); 319141cc406Sopenharmony_cistatic SANE_Status cs2_convert_options (cs2_t * s); 320141cc406Sopenharmony_cistatic SANE_Status cs2_scan (cs2_t * s, cs2_scan_t type); 321141cc406Sopenharmony_cistatic void *cs2_xmalloc (size_t size); 322141cc406Sopenharmony_cistatic void *cs2_xrealloc (void *p, size_t size); 323141cc406Sopenharmony_cistatic void cs2_xfree (const void *p); 324141cc406Sopenharmony_ci 325141cc406Sopenharmony_ci 326141cc406Sopenharmony_ci/* ========================================================================= */ 327141cc406Sopenharmony_ci/* global variables */ 328141cc406Sopenharmony_ci 329141cc406Sopenharmony_cistatic int cs2_colour_list[] = { 1, 2, 3, 9 }; 330141cc406Sopenharmony_ci 331141cc406Sopenharmony_cistatic SANE_Device **device_list = NULL; 332141cc406Sopenharmony_cistatic int n_device_list = 0; 333141cc406Sopenharmony_cistatic cs2_interface_t try_interface = CS2_INTERFACE_UNKNOWN; 334141cc406Sopenharmony_cistatic int open_devices = 0; 335141cc406Sopenharmony_ci 336141cc406Sopenharmony_ci 337141cc406Sopenharmony_ci/* ========================================================================= */ 338141cc406Sopenharmony_ci/* SANE entry points */ 339141cc406Sopenharmony_ci 340141cc406Sopenharmony_ciSANE_Status 341141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) 342141cc406Sopenharmony_ci{ 343141cc406Sopenharmony_ci DBG_INIT (); 344141cc406Sopenharmony_ci DBG (10, "sane_init() called.\n"); 345141cc406Sopenharmony_ci DBG (1, "coolscan2 backend, version %i.%i.%i initializing.\n", CS2_VERSION_MAJOR, CS2_VERSION_MINOR, CS2_REVISION); 346141cc406Sopenharmony_ci 347141cc406Sopenharmony_ci (void) authorize; /* to shut up compiler */ 348141cc406Sopenharmony_ci 349141cc406Sopenharmony_ci if (version_code) 350141cc406Sopenharmony_ci *version_code = 351141cc406Sopenharmony_ci SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0); 352141cc406Sopenharmony_ci 353141cc406Sopenharmony_ci sanei_usb_init (); 354141cc406Sopenharmony_ci 355141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 356141cc406Sopenharmony_ci} 357141cc406Sopenharmony_ci 358141cc406Sopenharmony_civoid 359141cc406Sopenharmony_cisane_exit (void) 360141cc406Sopenharmony_ci{ 361141cc406Sopenharmony_ci int i; 362141cc406Sopenharmony_ci 363141cc406Sopenharmony_ci DBG (10, "sane_exit() called.\n"); 364141cc406Sopenharmony_ci 365141cc406Sopenharmony_ci for (i = 0; i < n_device_list; i++) 366141cc406Sopenharmony_ci { 367141cc406Sopenharmony_ci cs2_xfree (device_list[i]->name); 368141cc406Sopenharmony_ci cs2_xfree (device_list[i]->vendor); 369141cc406Sopenharmony_ci cs2_xfree (device_list[i]->model); 370141cc406Sopenharmony_ci cs2_xfree (device_list[i]); 371141cc406Sopenharmony_ci } 372141cc406Sopenharmony_ci cs2_xfree (device_list); 373141cc406Sopenharmony_ci} 374141cc406Sopenharmony_ci 375141cc406Sopenharmony_ciSANE_Status 376141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** list, SANE_Bool local_only) 377141cc406Sopenharmony_ci{ 378141cc406Sopenharmony_ci char line[PATH_MAX], *p; 379141cc406Sopenharmony_ci FILE *config; 380141cc406Sopenharmony_ci 381141cc406Sopenharmony_ci (void) local_only; /* to shut up compiler */ 382141cc406Sopenharmony_ci 383141cc406Sopenharmony_ci DBG (10, "sane_get_devices() called.\n"); 384141cc406Sopenharmony_ci 385141cc406Sopenharmony_ci if (device_list) 386141cc406Sopenharmony_ci DBG (6, 387141cc406Sopenharmony_ci "sane_get_devices(): Device list already populated, not probing again.\n"); 388141cc406Sopenharmony_ci else 389141cc406Sopenharmony_ci { 390141cc406Sopenharmony_ci if (open_devices) 391141cc406Sopenharmony_ci { 392141cc406Sopenharmony_ci DBG (4, 393141cc406Sopenharmony_ci "sane_get_devices(): Devices open, not scanning for scanners.\n"); 394141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 395141cc406Sopenharmony_ci } 396141cc406Sopenharmony_ci 397141cc406Sopenharmony_ci config = sanei_config_open (CS2_CONFIG_FILE); 398141cc406Sopenharmony_ci if (config) 399141cc406Sopenharmony_ci { 400141cc406Sopenharmony_ci DBG (4, "sane_get_devices(): Reading config file.\n"); 401141cc406Sopenharmony_ci while (sanei_config_read (line, sizeof (line), config)) 402141cc406Sopenharmony_ci { 403141cc406Sopenharmony_ci p = line; 404141cc406Sopenharmony_ci p += strspn (line, " \t"); 405141cc406Sopenharmony_ci if (strlen (p) && (p[0] != '\n') && (p[0] != '#')) 406141cc406Sopenharmony_ci cs2_open (line, CS2_INTERFACE_UNKNOWN, NULL); 407141cc406Sopenharmony_ci } 408141cc406Sopenharmony_ci fclose (config); 409141cc406Sopenharmony_ci } 410141cc406Sopenharmony_ci else 411141cc406Sopenharmony_ci { 412141cc406Sopenharmony_ci DBG (4, "sane_get_devices(): No config file found.\n"); 413141cc406Sopenharmony_ci cs2_open ("auto", CS2_INTERFACE_UNKNOWN, NULL); 414141cc406Sopenharmony_ci } 415141cc406Sopenharmony_ci 416141cc406Sopenharmony_ci switch (n_device_list) 417141cc406Sopenharmony_ci { 418141cc406Sopenharmony_ci case 0: 419141cc406Sopenharmony_ci DBG (6, "sane_get_devices(): No devices detected.\n"); 420141cc406Sopenharmony_ci break; 421141cc406Sopenharmony_ci case 1: 422141cc406Sopenharmony_ci DBG (6, "sane_get_devices(): 1 device detected.\n"); 423141cc406Sopenharmony_ci break; 424141cc406Sopenharmony_ci default: 425141cc406Sopenharmony_ci DBG (6, "sane_get_devices(): %i devices detected.\n", 426141cc406Sopenharmony_ci n_device_list); 427141cc406Sopenharmony_ci break; 428141cc406Sopenharmony_ci } 429141cc406Sopenharmony_ci } 430141cc406Sopenharmony_ci 431141cc406Sopenharmony_ci *list = (const SANE_Device **) device_list; 432141cc406Sopenharmony_ci 433141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 434141cc406Sopenharmony_ci} 435141cc406Sopenharmony_ci 436141cc406Sopenharmony_ciSANE_Status 437141cc406Sopenharmony_cisane_open (SANE_String_Const name, SANE_Handle * h) 438141cc406Sopenharmony_ci{ 439141cc406Sopenharmony_ci SANE_Status status; 440141cc406Sopenharmony_ci cs2_t *s; 441141cc406Sopenharmony_ci int i_option; 442141cc406Sopenharmony_ci unsigned int i_list; 443141cc406Sopenharmony_ci SANE_Option_Descriptor o; 444141cc406Sopenharmony_ci SANE_Word *word_list; 445141cc406Sopenharmony_ci SANE_Range *range = NULL; 446141cc406Sopenharmony_ci int alloc_failed = 0; 447141cc406Sopenharmony_ci 448141cc406Sopenharmony_ci DBG (10, "sane_open() called.\n"); 449141cc406Sopenharmony_ci 450141cc406Sopenharmony_ci status = cs2_open (name, CS2_INTERFACE_UNKNOWN, &s); 451141cc406Sopenharmony_ci if (status) 452141cc406Sopenharmony_ci return status; 453141cc406Sopenharmony_ci 454141cc406Sopenharmony_ci *h = (SANE_Handle) s; 455141cc406Sopenharmony_ci 456141cc406Sopenharmony_ci /* get device properties */ 457141cc406Sopenharmony_ci 458141cc406Sopenharmony_ci s->lut_r = s->lut_g = s->lut_b = s->lut_neutral = NULL; 459141cc406Sopenharmony_ci s->resx_list = s->resy_list = NULL; 460141cc406Sopenharmony_ci s->resx_n_list = s->resy_n_list = 0; 461141cc406Sopenharmony_ci 462141cc406Sopenharmony_ci status = cs2_full_inquiry (s); 463141cc406Sopenharmony_ci if (status) 464141cc406Sopenharmony_ci return status; 465141cc406Sopenharmony_ci 466141cc406Sopenharmony_ci /* option descriptors */ 467141cc406Sopenharmony_ci 468141cc406Sopenharmony_ci for (i_option = 0; i_option < CS2_N_OPTIONS; i_option++) 469141cc406Sopenharmony_ci { 470141cc406Sopenharmony_ci o.name = o.title = o.desc = NULL; 471141cc406Sopenharmony_ci o.type = SANE_TYPE_BOOL; 472141cc406Sopenharmony_ci o.unit = SANE_UNIT_NONE; 473141cc406Sopenharmony_ci o.size = o.cap = 0; 474141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_NONE; 475141cc406Sopenharmony_ci o.constraint.range = NULL; /* only one union member needs to be NULLed */ 476141cc406Sopenharmony_ci switch (i_option) 477141cc406Sopenharmony_ci { 478141cc406Sopenharmony_ci case CS2_OPTION_NUM: 479141cc406Sopenharmony_ci o.name = ""; 480141cc406Sopenharmony_ci o.title = SANE_TITLE_NUM_OPTIONS; 481141cc406Sopenharmony_ci o.desc = SANE_DESC_NUM_OPTIONS; 482141cc406Sopenharmony_ci o.type = SANE_TYPE_INT; 483141cc406Sopenharmony_ci o.size = WSIZE; 484141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_DETECT; 485141cc406Sopenharmony_ci break; 486141cc406Sopenharmony_ci case CS2_OPTION_PREVIEW: 487141cc406Sopenharmony_ci o.name = "preview"; 488141cc406Sopenharmony_ci o.title = "Preview mode"; 489141cc406Sopenharmony_ci o.desc = "Preview mode"; 490141cc406Sopenharmony_ci o.type = SANE_TYPE_BOOL; 491141cc406Sopenharmony_ci o.size = WSIZE; 492141cc406Sopenharmony_ci o.cap = 493141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 494141cc406Sopenharmony_ci break; 495141cc406Sopenharmony_ci case CS2_OPTION_NEGATIVE: 496141cc406Sopenharmony_ci o.name = "negative"; 497141cc406Sopenharmony_ci o.title = "Negative"; 498141cc406Sopenharmony_ci o.desc = "Negative film: make scanner invert colours"; 499141cc406Sopenharmony_ci o.type = SANE_TYPE_BOOL; 500141cc406Sopenharmony_ci o.size = WSIZE; 501141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 502141cc406Sopenharmony_ci#ifndef CS2_BLEEDING_EDGE 503141cc406Sopenharmony_ci o.cap |= SANE_CAP_INACTIVE; 504141cc406Sopenharmony_ci#endif 505141cc406Sopenharmony_ci break; 506141cc406Sopenharmony_ci case CS2_OPTION_INFRARED: 507141cc406Sopenharmony_ci o.name = "infrared"; 508141cc406Sopenharmony_ci o.title = "Read infrared channel"; 509141cc406Sopenharmony_ci o.desc = "Read infrared channel in addition to scan colours"; 510141cc406Sopenharmony_ci o.type = SANE_TYPE_BOOL; 511141cc406Sopenharmony_ci o.size = WSIZE; 512141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 513141cc406Sopenharmony_ci break; 514141cc406Sopenharmony_ci case CS2_OPTION_SAMPLES_PER_SCAN: 515141cc406Sopenharmony_ci o.name = "samples-per-scan"; 516141cc406Sopenharmony_ci o.title = "Samples per Scan"; 517141cc406Sopenharmony_ci o.desc = "Number of samples per scan"; 518141cc406Sopenharmony_ci o.type = SANE_TYPE_INT; 519141cc406Sopenharmony_ci o.unit = SANE_UNIT_NONE; 520141cc406Sopenharmony_ci o.size = WSIZE; 521141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 522141cc406Sopenharmony_ci if (s->type != CS2_TYPE_LS2000 && s->type != CS2_TYPE_LS4000 523141cc406Sopenharmony_ci && s->type != CS2_TYPE_LS5000 && s->type != CS2_TYPE_LS8000) 524141cc406Sopenharmony_ci o.cap |= SANE_CAP_INACTIVE; 525141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_RANGE; 526141cc406Sopenharmony_ci range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); 527141cc406Sopenharmony_ci if (! range) 528141cc406Sopenharmony_ci alloc_failed = 1; 529141cc406Sopenharmony_ci else 530141cc406Sopenharmony_ci { 531141cc406Sopenharmony_ci range->min = 1; 532141cc406Sopenharmony_ci range->max = 16; 533141cc406Sopenharmony_ci range->quant = 1; 534141cc406Sopenharmony_ci o.constraint.range = range; 535141cc406Sopenharmony_ci } 536141cc406Sopenharmony_ci break; 537141cc406Sopenharmony_ci case CS2_OPTION_DEPTH: 538141cc406Sopenharmony_ci o.name = "depth"; 539141cc406Sopenharmony_ci o.title = "Bit depth per channel"; 540141cc406Sopenharmony_ci o.desc = "Number of bits output by scanner for each channel"; 541141cc406Sopenharmony_ci o.type = SANE_TYPE_INT; 542141cc406Sopenharmony_ci o.unit = SANE_UNIT_NONE; 543141cc406Sopenharmony_ci o.size = WSIZE; 544141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 545141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_WORD_LIST; 546141cc406Sopenharmony_ci word_list = (SANE_Word *) cs2_xmalloc (2 * sizeof (SANE_Word)); 547141cc406Sopenharmony_ci if (!word_list) 548141cc406Sopenharmony_ci alloc_failed = 1; 549141cc406Sopenharmony_ci else 550141cc406Sopenharmony_ci { 551141cc406Sopenharmony_ci word_list[1] = 8; 552141cc406Sopenharmony_ci word_list[2] = s->maxbits; 553141cc406Sopenharmony_ci word_list[0] = 2; 554141cc406Sopenharmony_ci o.constraint.word_list = word_list; 555141cc406Sopenharmony_ci } 556141cc406Sopenharmony_ci break; 557141cc406Sopenharmony_ci case CS2_OPTION_EXPOSURE: 558141cc406Sopenharmony_ci o.name = "exposure"; 559141cc406Sopenharmony_ci o.title = "Exposure multiplier"; 560141cc406Sopenharmony_ci o.desc = "Exposure multiplier for all channels"; 561141cc406Sopenharmony_ci o.type = SANE_TYPE_FIXED; 562141cc406Sopenharmony_ci o.unit = SANE_UNIT_NONE; 563141cc406Sopenharmony_ci o.size = WSIZE; 564141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 565141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_RANGE; 566141cc406Sopenharmony_ci range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); 567141cc406Sopenharmony_ci if (!range) 568141cc406Sopenharmony_ci alloc_failed = 1; 569141cc406Sopenharmony_ci else 570141cc406Sopenharmony_ci { 571141cc406Sopenharmony_ci range->min = SANE_FIX (0.); 572141cc406Sopenharmony_ci range->max = SANE_FIX (10.); 573141cc406Sopenharmony_ci range->quant = SANE_FIX (0.1); 574141cc406Sopenharmony_ci o.constraint.range = range; 575141cc406Sopenharmony_ci } 576141cc406Sopenharmony_ci break; 577141cc406Sopenharmony_ci case CS2_OPTION_EXPOSURE_R: 578141cc406Sopenharmony_ci o.name = "red-exposure"; 579141cc406Sopenharmony_ci o.title = "Red exposure time"; 580141cc406Sopenharmony_ci o.desc = "Exposure time for red channel"; 581141cc406Sopenharmony_ci o.type = SANE_TYPE_FIXED; 582141cc406Sopenharmony_ci o.unit = SANE_UNIT_MICROSECOND; 583141cc406Sopenharmony_ci o.size = WSIZE; 584141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 585141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_RANGE; 586141cc406Sopenharmony_ci range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); 587141cc406Sopenharmony_ci if (!range) 588141cc406Sopenharmony_ci alloc_failed = 1; 589141cc406Sopenharmony_ci else 590141cc406Sopenharmony_ci { 591141cc406Sopenharmony_ci range->min = SANE_FIX (50.); 592141cc406Sopenharmony_ci range->max = SANE_FIX (20000.); 593141cc406Sopenharmony_ci range->quant = SANE_FIX (10.); 594141cc406Sopenharmony_ci o.constraint.range = range; 595141cc406Sopenharmony_ci } 596141cc406Sopenharmony_ci break; 597141cc406Sopenharmony_ci case CS2_OPTION_EXPOSURE_G: 598141cc406Sopenharmony_ci o.name = "green-exposure"; 599141cc406Sopenharmony_ci o.title = "Green exposure time"; 600141cc406Sopenharmony_ci o.desc = "Exposure time for green channel"; 601141cc406Sopenharmony_ci o.type = SANE_TYPE_FIXED; 602141cc406Sopenharmony_ci o.unit = SANE_UNIT_MICROSECOND; 603141cc406Sopenharmony_ci o.size = WSIZE; 604141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 605141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_RANGE; 606141cc406Sopenharmony_ci range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); 607141cc406Sopenharmony_ci if (!range) 608141cc406Sopenharmony_ci alloc_failed = 1; 609141cc406Sopenharmony_ci else 610141cc406Sopenharmony_ci { 611141cc406Sopenharmony_ci range->min = SANE_FIX (50.); 612141cc406Sopenharmony_ci range->max = SANE_FIX (20000.); 613141cc406Sopenharmony_ci range->quant = SANE_FIX (10.); 614141cc406Sopenharmony_ci o.constraint.range = range; 615141cc406Sopenharmony_ci } 616141cc406Sopenharmony_ci break; 617141cc406Sopenharmony_ci case CS2_OPTION_EXPOSURE_B: 618141cc406Sopenharmony_ci o.name = "blue-exposure"; 619141cc406Sopenharmony_ci o.title = "Blue exposure time"; 620141cc406Sopenharmony_ci o.desc = "Exposure time for blue channel"; 621141cc406Sopenharmony_ci o.type = SANE_TYPE_FIXED; 622141cc406Sopenharmony_ci o.unit = SANE_UNIT_MICROSECOND; 623141cc406Sopenharmony_ci o.size = WSIZE; 624141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 625141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_RANGE; 626141cc406Sopenharmony_ci range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); 627141cc406Sopenharmony_ci if (!range) 628141cc406Sopenharmony_ci alloc_failed = 1; 629141cc406Sopenharmony_ci else 630141cc406Sopenharmony_ci { 631141cc406Sopenharmony_ci range->min = SANE_FIX (50.); 632141cc406Sopenharmony_ci range->max = SANE_FIX (20000.); 633141cc406Sopenharmony_ci range->quant = SANE_FIX (10.); 634141cc406Sopenharmony_ci o.constraint.range = range; 635141cc406Sopenharmony_ci } 636141cc406Sopenharmony_ci break; 637141cc406Sopenharmony_ci case CS2_OPTION_LUT_R: 638141cc406Sopenharmony_ci o.name = "red-gamma-table"; 639141cc406Sopenharmony_ci o.title = "LUT for red channel"; 640141cc406Sopenharmony_ci o.desc = "LUT for red channel"; 641141cc406Sopenharmony_ci o.type = SANE_TYPE_INT; 642141cc406Sopenharmony_ci o.size = s->n_lut * WSIZE; 643141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 644141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_RANGE; 645141cc406Sopenharmony_ci range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); 646141cc406Sopenharmony_ci if (!range) 647141cc406Sopenharmony_ci alloc_failed = 1; 648141cc406Sopenharmony_ci else 649141cc406Sopenharmony_ci { 650141cc406Sopenharmony_ci range->min = 0; 651141cc406Sopenharmony_ci range->max = s->n_lut - 1; 652141cc406Sopenharmony_ci range->quant = 1; 653141cc406Sopenharmony_ci o.constraint.range = range; 654141cc406Sopenharmony_ci } 655141cc406Sopenharmony_ci break; 656141cc406Sopenharmony_ci case CS2_OPTION_LUT_G: 657141cc406Sopenharmony_ci o.name = "green-gamma-table"; 658141cc406Sopenharmony_ci o.title = "LUT for green channel"; 659141cc406Sopenharmony_ci o.desc = "LUT for green channel"; 660141cc406Sopenharmony_ci o.type = SANE_TYPE_INT; 661141cc406Sopenharmony_ci o.size = s->n_lut * WSIZE; 662141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 663141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_RANGE; 664141cc406Sopenharmony_ci range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); 665141cc406Sopenharmony_ci if (!range) 666141cc406Sopenharmony_ci alloc_failed = 1; 667141cc406Sopenharmony_ci else 668141cc406Sopenharmony_ci { 669141cc406Sopenharmony_ci range->min = 0; 670141cc406Sopenharmony_ci range->max = s->n_lut - 1; 671141cc406Sopenharmony_ci range->quant = 1; 672141cc406Sopenharmony_ci o.constraint.range = range; 673141cc406Sopenharmony_ci } 674141cc406Sopenharmony_ci break; 675141cc406Sopenharmony_ci case CS2_OPTION_LUT_B: 676141cc406Sopenharmony_ci o.name = "blue-gamma-table"; 677141cc406Sopenharmony_ci o.title = "LUT for blue channel"; 678141cc406Sopenharmony_ci o.desc = "LUT for blue channel"; 679141cc406Sopenharmony_ci o.type = SANE_TYPE_INT; 680141cc406Sopenharmony_ci o.size = s->n_lut * WSIZE; 681141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 682141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_RANGE; 683141cc406Sopenharmony_ci range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); 684141cc406Sopenharmony_ci if (!range) 685141cc406Sopenharmony_ci alloc_failed = 1; 686141cc406Sopenharmony_ci else 687141cc406Sopenharmony_ci { 688141cc406Sopenharmony_ci range->min = 0; 689141cc406Sopenharmony_ci range->max = s->n_lut - 1; 690141cc406Sopenharmony_ci range->quant = 1; 691141cc406Sopenharmony_ci o.constraint.range = range; 692141cc406Sopenharmony_ci } 693141cc406Sopenharmony_ci break; 694141cc406Sopenharmony_ci case CS2_OPTION_LOAD: 695141cc406Sopenharmony_ci o.name = "load"; 696141cc406Sopenharmony_ci o.title = "Load"; 697141cc406Sopenharmony_ci o.desc = "Load next slide"; 698141cc406Sopenharmony_ci o.type = SANE_TYPE_BUTTON; 699141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 700141cc406Sopenharmony_ci break; 701141cc406Sopenharmony_ci case CS2_OPTION_EJECT: 702141cc406Sopenharmony_ci o.name = "eject"; 703141cc406Sopenharmony_ci o.title = "Eject"; 704141cc406Sopenharmony_ci o.desc = "Eject loaded medium"; 705141cc406Sopenharmony_ci o.type = SANE_TYPE_BUTTON; 706141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 707141cc406Sopenharmony_ci break; 708141cc406Sopenharmony_ci case CS2_OPTION_RESET: 709141cc406Sopenharmony_ci o.name = "reset"; 710141cc406Sopenharmony_ci o.title = "Reset scanner"; 711141cc406Sopenharmony_ci o.desc = "Initialize scanner"; 712141cc406Sopenharmony_ci o.type = SANE_TYPE_BUTTON; 713141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 714141cc406Sopenharmony_ci break; 715141cc406Sopenharmony_ci case CS2_OPTION_RESX: 716141cc406Sopenharmony_ci case CS2_OPTION_RES: 717141cc406Sopenharmony_ci case CS2_OPTION_PREVIEW_RESOLUTION: 718141cc406Sopenharmony_ci if (i_option == CS2_OPTION_PREVIEW_RESOLUTION) 719141cc406Sopenharmony_ci { 720141cc406Sopenharmony_ci o.name = "preview-resolution"; 721141cc406Sopenharmony_ci o.title = "Preview resolution"; 722141cc406Sopenharmony_ci o.desc = 723141cc406Sopenharmony_ci "Scanning resolution for preview mode in dpi, affecting both x and y directions"; 724141cc406Sopenharmony_ci } 725141cc406Sopenharmony_ci else if (i_option == CS2_OPTION_RES) 726141cc406Sopenharmony_ci { 727141cc406Sopenharmony_ci o.name = "resolution"; 728141cc406Sopenharmony_ci o.title = "Resolution"; 729141cc406Sopenharmony_ci o.desc = 730141cc406Sopenharmony_ci "Scanning resolution in dpi, affecting both x and y directions"; 731141cc406Sopenharmony_ci } 732141cc406Sopenharmony_ci else 733141cc406Sopenharmony_ci { 734141cc406Sopenharmony_ci o.name = "x-resolution"; 735141cc406Sopenharmony_ci o.title = "X resolution"; 736141cc406Sopenharmony_ci o.desc = 737141cc406Sopenharmony_ci "Scanning resolution in dpi, affecting x direction only"; 738141cc406Sopenharmony_ci } 739141cc406Sopenharmony_ci o.type = SANE_TYPE_INT; 740141cc406Sopenharmony_ci o.unit = SANE_UNIT_DPI; 741141cc406Sopenharmony_ci o.size = WSIZE; 742141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 743141cc406Sopenharmony_ci if (i_option == CS2_OPTION_RESX) 744141cc406Sopenharmony_ci o.cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; 745141cc406Sopenharmony_ci if (i_option == CS2_OPTION_PREVIEW_RESOLUTION) 746141cc406Sopenharmony_ci o.cap |= SANE_CAP_ADVANCED; 747141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_WORD_LIST; 748141cc406Sopenharmony_ci word_list = 749141cc406Sopenharmony_ci (SANE_Word *) cs2_xmalloc ((s->resx_n_list + 1) * 750141cc406Sopenharmony_ci sizeof (SANE_Word)); 751141cc406Sopenharmony_ci if (!word_list) 752141cc406Sopenharmony_ci alloc_failed = 1; 753141cc406Sopenharmony_ci else 754141cc406Sopenharmony_ci { 755141cc406Sopenharmony_ci for (i_list = 0; i_list < s->resx_n_list; i_list++) 756141cc406Sopenharmony_ci word_list[i_list + 1] = s->resx_list[i_list]; 757141cc406Sopenharmony_ci word_list[0] = s->resx_n_list; 758141cc406Sopenharmony_ci o.constraint.word_list = word_list; 759141cc406Sopenharmony_ci } 760141cc406Sopenharmony_ci break; 761141cc406Sopenharmony_ci case CS2_OPTION_RESY: 762141cc406Sopenharmony_ci o.name = "y-resolution"; 763141cc406Sopenharmony_ci o.title = "Y resolution"; 764141cc406Sopenharmony_ci o.desc = "Scanning resolution in dpi, affecting y direction only"; 765141cc406Sopenharmony_ci o.type = SANE_TYPE_INT; 766141cc406Sopenharmony_ci o.unit = SANE_UNIT_DPI; 767141cc406Sopenharmony_ci o.size = WSIZE; 768141cc406Sopenharmony_ci o.cap = 769141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE | 770141cc406Sopenharmony_ci SANE_CAP_ADVANCED; 771141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_WORD_LIST; 772141cc406Sopenharmony_ci word_list = 773141cc406Sopenharmony_ci (SANE_Word *) cs2_xmalloc ((s->resy_n_list + 1) * 774141cc406Sopenharmony_ci sizeof (SANE_Word)); 775141cc406Sopenharmony_ci if (!word_list) 776141cc406Sopenharmony_ci alloc_failed = 1; 777141cc406Sopenharmony_ci else 778141cc406Sopenharmony_ci { 779141cc406Sopenharmony_ci for (i_list = 0; i_list < s->resy_n_list; i_list++) 780141cc406Sopenharmony_ci word_list[i_list + 1] = s->resy_list[i_list]; 781141cc406Sopenharmony_ci word_list[0] = s->resy_n_list; 782141cc406Sopenharmony_ci o.constraint.word_list = word_list; 783141cc406Sopenharmony_ci } 784141cc406Sopenharmony_ci break; 785141cc406Sopenharmony_ci case CS2_OPTION_RES_INDEPENDENT: 786141cc406Sopenharmony_ci o.name = "independent-res"; 787141cc406Sopenharmony_ci o.title = "Independent x/y resolutions"; 788141cc406Sopenharmony_ci o.desc = 789141cc406Sopenharmony_ci "Enable independent controls for scanning resolution in x and y direction"; 790141cc406Sopenharmony_ci o.type = SANE_TYPE_BOOL; 791141cc406Sopenharmony_ci o.size = WSIZE; 792141cc406Sopenharmony_ci o.cap = 793141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE | 794141cc406Sopenharmony_ci SANE_CAP_ADVANCED; 795141cc406Sopenharmony_ci break; 796141cc406Sopenharmony_ci case CS2_OPTION_FRAME: 797141cc406Sopenharmony_ci o.name = "frame"; 798141cc406Sopenharmony_ci o.title = "Frame number"; 799141cc406Sopenharmony_ci o.desc = "Number of frame to be scanned, starting with 1"; 800141cc406Sopenharmony_ci o.type = SANE_TYPE_INT; 801141cc406Sopenharmony_ci o.unit = SANE_UNIT_NONE; 802141cc406Sopenharmony_ci o.size = WSIZE; 803141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 804141cc406Sopenharmony_ci if (s->n_frames <= 1) 805141cc406Sopenharmony_ci o.cap |= SANE_CAP_INACTIVE; 806141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_RANGE; 807141cc406Sopenharmony_ci range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); 808141cc406Sopenharmony_ci if (!range) 809141cc406Sopenharmony_ci alloc_failed = 1; 810141cc406Sopenharmony_ci else 811141cc406Sopenharmony_ci { 812141cc406Sopenharmony_ci range->min = 1; 813141cc406Sopenharmony_ci range->max = s->n_frames; 814141cc406Sopenharmony_ci range->quant = 1; 815141cc406Sopenharmony_ci o.constraint.range = range; 816141cc406Sopenharmony_ci } 817141cc406Sopenharmony_ci break; 818141cc406Sopenharmony_ci case CS2_OPTION_SUBFRAME: 819141cc406Sopenharmony_ci o.name = "subframe"; 820141cc406Sopenharmony_ci o.title = "Frame shift"; 821141cc406Sopenharmony_ci o.desc = "Fine position within the selected frame"; 822141cc406Sopenharmony_ci o.type = SANE_TYPE_FIXED; 823141cc406Sopenharmony_ci o.unit = SANE_UNIT_MM; 824141cc406Sopenharmony_ci o.size = WSIZE; 825141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 826141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_RANGE; 827141cc406Sopenharmony_ci range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); 828141cc406Sopenharmony_ci if (!range) 829141cc406Sopenharmony_ci alloc_failed = 1; 830141cc406Sopenharmony_ci else 831141cc406Sopenharmony_ci { 832141cc406Sopenharmony_ci range->min = SANE_FIX (0.); 833141cc406Sopenharmony_ci range->max = SANE_FIX ((s->boundaryy - 1) * s->unit_mm); 834141cc406Sopenharmony_ci range->quant = SANE_FIX (0.); 835141cc406Sopenharmony_ci o.constraint.range = range; 836141cc406Sopenharmony_ci } 837141cc406Sopenharmony_ci break; 838141cc406Sopenharmony_ci case CS2_OPTION_XMIN: 839141cc406Sopenharmony_ci o.name = "tl-x"; 840141cc406Sopenharmony_ci o.title = "Left x value of scan area"; 841141cc406Sopenharmony_ci o.desc = "Left x value of scan area"; 842141cc406Sopenharmony_ci o.type = SANE_TYPE_INT; 843141cc406Sopenharmony_ci o.unit = SANE_UNIT_PIXEL; 844141cc406Sopenharmony_ci o.size = WSIZE; 845141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 846141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_RANGE; 847141cc406Sopenharmony_ci if (!range) 848141cc406Sopenharmony_ci alloc_failed = 1; 849141cc406Sopenharmony_ci else 850141cc406Sopenharmony_ci { 851141cc406Sopenharmony_ci range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); 852141cc406Sopenharmony_ci range->min = 0; 853141cc406Sopenharmony_ci range->max = s->boundaryx - 1; 854141cc406Sopenharmony_ci range->quant = 1; 855141cc406Sopenharmony_ci o.constraint.range = range; 856141cc406Sopenharmony_ci } 857141cc406Sopenharmony_ci break; 858141cc406Sopenharmony_ci case CS2_OPTION_XMAX: 859141cc406Sopenharmony_ci o.name = "br-x"; 860141cc406Sopenharmony_ci o.title = "Right x value of scan area"; 861141cc406Sopenharmony_ci o.desc = "Right x value of scan area"; 862141cc406Sopenharmony_ci o.type = SANE_TYPE_INT; 863141cc406Sopenharmony_ci o.unit = SANE_UNIT_PIXEL; 864141cc406Sopenharmony_ci o.size = WSIZE; 865141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 866141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_RANGE; 867141cc406Sopenharmony_ci range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); 868141cc406Sopenharmony_ci if (!range) 869141cc406Sopenharmony_ci alloc_failed = 1; 870141cc406Sopenharmony_ci else 871141cc406Sopenharmony_ci { 872141cc406Sopenharmony_ci range->min = 0; 873141cc406Sopenharmony_ci range->max = s->boundaryx - 1; 874141cc406Sopenharmony_ci range->quant = 1; 875141cc406Sopenharmony_ci o.constraint.range = range; 876141cc406Sopenharmony_ci } 877141cc406Sopenharmony_ci break; 878141cc406Sopenharmony_ci case CS2_OPTION_YMIN: 879141cc406Sopenharmony_ci o.name = "tl-y"; 880141cc406Sopenharmony_ci o.title = "Top y value of scan area"; 881141cc406Sopenharmony_ci o.desc = "Top y value of scan area"; 882141cc406Sopenharmony_ci o.type = SANE_TYPE_INT; 883141cc406Sopenharmony_ci o.unit = SANE_UNIT_PIXEL; 884141cc406Sopenharmony_ci o.size = WSIZE; 885141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 886141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_RANGE; 887141cc406Sopenharmony_ci range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); 888141cc406Sopenharmony_ci if (!range) 889141cc406Sopenharmony_ci alloc_failed = 1; 890141cc406Sopenharmony_ci else 891141cc406Sopenharmony_ci { 892141cc406Sopenharmony_ci range->min = 0; 893141cc406Sopenharmony_ci range->max = s->boundaryy - 1; 894141cc406Sopenharmony_ci range->quant = 1; 895141cc406Sopenharmony_ci o.constraint.range = range; 896141cc406Sopenharmony_ci } 897141cc406Sopenharmony_ci break; 898141cc406Sopenharmony_ci case CS2_OPTION_YMAX: 899141cc406Sopenharmony_ci o.name = "br-y"; 900141cc406Sopenharmony_ci o.title = "Bottom y value of scan area"; 901141cc406Sopenharmony_ci o.desc = "Bottom y value of scan area"; 902141cc406Sopenharmony_ci o.type = SANE_TYPE_INT; 903141cc406Sopenharmony_ci o.unit = SANE_UNIT_PIXEL; 904141cc406Sopenharmony_ci o.size = WSIZE; 905141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 906141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_RANGE; 907141cc406Sopenharmony_ci range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); 908141cc406Sopenharmony_ci if (!range) 909141cc406Sopenharmony_ci alloc_failed = 1; 910141cc406Sopenharmony_ci else 911141cc406Sopenharmony_ci { 912141cc406Sopenharmony_ci range->min = 0; 913141cc406Sopenharmony_ci range->max = s->boundaryy - 1; 914141cc406Sopenharmony_ci range->quant = 1; 915141cc406Sopenharmony_ci o.constraint.range = range; 916141cc406Sopenharmony_ci } 917141cc406Sopenharmony_ci break; 918141cc406Sopenharmony_ci case CS2_OPTION_FOCUS_ON_CENTRE: 919141cc406Sopenharmony_ci o.name = "focus-on-centre"; 920141cc406Sopenharmony_ci o.title = "Use centre of scan area as AF point"; 921141cc406Sopenharmony_ci o.desc = 922141cc406Sopenharmony_ci "Use centre of scan area as AF point instead of manual AF point selection"; 923141cc406Sopenharmony_ci o.type = SANE_TYPE_BOOL; 924141cc406Sopenharmony_ci o.size = WSIZE; 925141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 926141cc406Sopenharmony_ci break; 927141cc406Sopenharmony_ci case CS2_OPTION_FOCUS: 928141cc406Sopenharmony_ci o.name = SANE_NAME_FOCUS; 929141cc406Sopenharmony_ci o.title = SANE_TITLE_FOCUS; 930141cc406Sopenharmony_ci o.desc = SANE_DESC_FOCUS; 931141cc406Sopenharmony_ci o.type = SANE_TYPE_INT; 932141cc406Sopenharmony_ci o.unit = SANE_UNIT_NONE; 933141cc406Sopenharmony_ci o.size = WSIZE; 934141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 935141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_RANGE; 936141cc406Sopenharmony_ci range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); 937141cc406Sopenharmony_ci if (!range) 938141cc406Sopenharmony_ci alloc_failed = 1; 939141cc406Sopenharmony_ci else 940141cc406Sopenharmony_ci { 941141cc406Sopenharmony_ci range->min = s->focus_min; 942141cc406Sopenharmony_ci range->max = s->focus_max; 943141cc406Sopenharmony_ci range->quant = 1; 944141cc406Sopenharmony_ci o.constraint.range = range; 945141cc406Sopenharmony_ci } 946141cc406Sopenharmony_ci break; 947141cc406Sopenharmony_ci case CS2_OPTION_AUTOFOCUS: 948141cc406Sopenharmony_ci o.name = SANE_NAME_AUTOFOCUS; 949141cc406Sopenharmony_ci o.title = SANE_TITLE_AUTOFOCUS; 950141cc406Sopenharmony_ci o.desc = SANE_DESC_AUTOFOCUS; 951141cc406Sopenharmony_ci o.type = SANE_TYPE_BUTTON; 952141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 953141cc406Sopenharmony_ci break; 954141cc406Sopenharmony_ci case CS2_OPTION_FOCUSX: 955141cc406Sopenharmony_ci o.name = "focusx"; 956141cc406Sopenharmony_ci o.title = "X coordinate of AF point"; 957141cc406Sopenharmony_ci o.desc = "X coordinate of AF point"; 958141cc406Sopenharmony_ci o.type = SANE_TYPE_INT; 959141cc406Sopenharmony_ci o.unit = SANE_UNIT_PIXEL; 960141cc406Sopenharmony_ci o.size = WSIZE; 961141cc406Sopenharmony_ci o.cap = 962141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; 963141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_RANGE; 964141cc406Sopenharmony_ci range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); 965141cc406Sopenharmony_ci if (!range) 966141cc406Sopenharmony_ci alloc_failed = 1; 967141cc406Sopenharmony_ci else 968141cc406Sopenharmony_ci { 969141cc406Sopenharmony_ci range->min = 0; 970141cc406Sopenharmony_ci range->max = s->boundaryx - 1; 971141cc406Sopenharmony_ci range->quant = 1; 972141cc406Sopenharmony_ci o.constraint.range = range; 973141cc406Sopenharmony_ci } 974141cc406Sopenharmony_ci break; 975141cc406Sopenharmony_ci case CS2_OPTION_FOCUSY: 976141cc406Sopenharmony_ci o.name = "focusy"; 977141cc406Sopenharmony_ci o.title = "Y coordinate of AF point"; 978141cc406Sopenharmony_ci o.desc = "Y coordinate of AF point"; 979141cc406Sopenharmony_ci o.type = SANE_TYPE_INT; 980141cc406Sopenharmony_ci o.unit = SANE_UNIT_PIXEL; 981141cc406Sopenharmony_ci o.size = WSIZE; 982141cc406Sopenharmony_ci o.cap = 983141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; 984141cc406Sopenharmony_ci o.constraint_type = SANE_CONSTRAINT_RANGE; 985141cc406Sopenharmony_ci range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); 986141cc406Sopenharmony_ci if (!range) 987141cc406Sopenharmony_ci alloc_failed = 1; 988141cc406Sopenharmony_ci else 989141cc406Sopenharmony_ci { 990141cc406Sopenharmony_ci range->min = 0; 991141cc406Sopenharmony_ci range->max = s->boundaryy - 1; 992141cc406Sopenharmony_ci range->quant = 1; 993141cc406Sopenharmony_ci o.constraint.range = range; 994141cc406Sopenharmony_ci } 995141cc406Sopenharmony_ci break; 996141cc406Sopenharmony_ci case CS2_OPTION_SCAN_AE: 997141cc406Sopenharmony_ci o.name = "ae"; 998141cc406Sopenharmony_ci o.title = "Auto-exposure scan now"; 999141cc406Sopenharmony_ci o.desc = "Perform auto-exposure scan"; 1000141cc406Sopenharmony_ci o.type = SANE_TYPE_BUTTON; 1001141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 1002141cc406Sopenharmony_ci break; 1003141cc406Sopenharmony_ci case CS2_OPTION_SCAN_AE_WB: 1004141cc406Sopenharmony_ci o.name = "ae-wb"; 1005141cc406Sopenharmony_ci o.title = "Auto-exposure scan with white balance now"; 1006141cc406Sopenharmony_ci o.desc = "Perform auto-exposure scan with white balance"; 1007141cc406Sopenharmony_ci o.type = SANE_TYPE_BUTTON; 1008141cc406Sopenharmony_ci o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 1009141cc406Sopenharmony_ci break; 1010141cc406Sopenharmony_ci default: 1011141cc406Sopenharmony_ci DBG (1, "BUG: sane_open(): Unknown option number.\n"); 1012141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1013141cc406Sopenharmony_ci break; 1014141cc406Sopenharmony_ci } 1015141cc406Sopenharmony_ci s->option_list[i_option] = o; 1016141cc406Sopenharmony_ci } 1017141cc406Sopenharmony_ci 1018141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 1019141cc406Sopenharmony_ci s->preview = SANE_FALSE; 1020141cc406Sopenharmony_ci s->negative = SANE_FALSE; 1021141cc406Sopenharmony_ci s->depth = 8; 1022141cc406Sopenharmony_ci s->infrared = 0; 1023141cc406Sopenharmony_ci s->samples_per_scan = 1; 1024141cc406Sopenharmony_ci s->i_frame = 1; 1025141cc406Sopenharmony_ci s->subframe = 0.; 1026141cc406Sopenharmony_ci s->res = s->resx = s->resx_max; 1027141cc406Sopenharmony_ci s->resy = s->resy_max; 1028141cc406Sopenharmony_ci s->res_independent = SANE_FALSE; 1029141cc406Sopenharmony_ci s->res_preview = s->resx_max / 10; 1030141cc406Sopenharmony_ci if (s->res_preview < s->resx_min) 1031141cc406Sopenharmony_ci s->res_preview = s->resx_min; 1032141cc406Sopenharmony_ci s->xmin = 0; 1033141cc406Sopenharmony_ci s->xmax = s->boundaryx - 1; 1034141cc406Sopenharmony_ci s->ymin = 0; 1035141cc406Sopenharmony_ci s->ymax = s->boundaryy - 1; 1036141cc406Sopenharmony_ci s->focus_on_centre = SANE_TRUE; 1037141cc406Sopenharmony_ci s->focus = 0; 1038141cc406Sopenharmony_ci s->focusx = 0; 1039141cc406Sopenharmony_ci s->focusy = 0; 1040141cc406Sopenharmony_ci s->exposure = 1.; 1041141cc406Sopenharmony_ci s->exposure_r = 1200.; 1042141cc406Sopenharmony_ci s->exposure_g = 1200.; 1043141cc406Sopenharmony_ci s->exposure_b = 1000.; 1044141cc406Sopenharmony_ci s->infrared_stage = CS2_INFRARED_OFF; 1045141cc406Sopenharmony_ci s->infrared_next = CS2_INFRARED_OFF; 1046141cc406Sopenharmony_ci s->infrared_buf = NULL; 1047141cc406Sopenharmony_ci s->n_infrared_buf = 0; 1048141cc406Sopenharmony_ci s->line_buf = NULL; 1049141cc406Sopenharmony_ci s->n_line_buf = 0; 1050141cc406Sopenharmony_ci 1051141cc406Sopenharmony_ci if (alloc_failed) 1052141cc406Sopenharmony_ci { 1053141cc406Sopenharmony_ci cs2_close (s); 1054141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1055141cc406Sopenharmony_ci } 1056141cc406Sopenharmony_ci 1057141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1058141cc406Sopenharmony_ci} 1059141cc406Sopenharmony_ci 1060141cc406Sopenharmony_civoid 1061141cc406Sopenharmony_cisane_close (SANE_Handle h) 1062141cc406Sopenharmony_ci{ 1063141cc406Sopenharmony_ci cs2_t *s = (cs2_t *) h; 1064141cc406Sopenharmony_ci 1065141cc406Sopenharmony_ci DBG (10, "sane_close() called.\n"); 1066141cc406Sopenharmony_ci 1067141cc406Sopenharmony_ci cs2_close (s); 1068141cc406Sopenharmony_ci} 1069141cc406Sopenharmony_ci 1070141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 1071141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle h, SANE_Int n) 1072141cc406Sopenharmony_ci{ 1073141cc406Sopenharmony_ci cs2_t *s = (cs2_t *) h; 1074141cc406Sopenharmony_ci 1075141cc406Sopenharmony_ci DBG (10, "sane_get_option_descriptor() called, option #%i.\n", n); 1076141cc406Sopenharmony_ci 1077141cc406Sopenharmony_ci if ((n >= 0) && (n < CS2_N_OPTIONS)) 1078141cc406Sopenharmony_ci return &s->option_list[n]; 1079141cc406Sopenharmony_ci else 1080141cc406Sopenharmony_ci return NULL; 1081141cc406Sopenharmony_ci} 1082141cc406Sopenharmony_ci 1083141cc406Sopenharmony_ciSANE_Status 1084141cc406Sopenharmony_cisane_control_option (SANE_Handle h, SANE_Int n, SANE_Action a, void *v, 1085141cc406Sopenharmony_ci SANE_Int * i) 1086141cc406Sopenharmony_ci{ 1087141cc406Sopenharmony_ci cs2_t *s = (cs2_t *) h; 1088141cc406Sopenharmony_ci SANE_Int flags = 0; 1089141cc406Sopenharmony_ci cs2_pixel_t pixel; 1090141cc406Sopenharmony_ci SANE_Status status; 1091141cc406Sopenharmony_ci SANE_Option_Descriptor o = s->option_list[n]; 1092141cc406Sopenharmony_ci 1093141cc406Sopenharmony_ci DBG (10, "sane_control_option() called, option #%i, action #%i.\n", n, a); 1094141cc406Sopenharmony_ci 1095141cc406Sopenharmony_ci switch (a) 1096141cc406Sopenharmony_ci { 1097141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 1098141cc406Sopenharmony_ci 1099141cc406Sopenharmony_ci switch (n) 1100141cc406Sopenharmony_ci { 1101141cc406Sopenharmony_ci case CS2_OPTION_NUM: 1102141cc406Sopenharmony_ci *(SANE_Word *) v = CS2_N_OPTIONS; 1103141cc406Sopenharmony_ci break; 1104141cc406Sopenharmony_ci case CS2_OPTION_NEGATIVE: 1105141cc406Sopenharmony_ci *(SANE_Word *) v = s->negative; 1106141cc406Sopenharmony_ci break; 1107141cc406Sopenharmony_ci case CS2_OPTION_INFRARED: 1108141cc406Sopenharmony_ci *(SANE_Word *) v = s->infrared; 1109141cc406Sopenharmony_ci break; 1110141cc406Sopenharmony_ci case CS2_OPTION_SAMPLES_PER_SCAN: 1111141cc406Sopenharmony_ci *(SANE_Word *) v = s->samples_per_scan; 1112141cc406Sopenharmony_ci break; 1113141cc406Sopenharmony_ci case CS2_OPTION_DEPTH: 1114141cc406Sopenharmony_ci *(SANE_Word *) v = s->depth; 1115141cc406Sopenharmony_ci break; 1116141cc406Sopenharmony_ci case CS2_OPTION_PREVIEW: 1117141cc406Sopenharmony_ci *(SANE_Word *) v = s->preview; 1118141cc406Sopenharmony_ci break; 1119141cc406Sopenharmony_ci case CS2_OPTION_EXPOSURE: 1120141cc406Sopenharmony_ci *(SANE_Word *) v = SANE_FIX (s->exposure); 1121141cc406Sopenharmony_ci break; 1122141cc406Sopenharmony_ci case CS2_OPTION_EXPOSURE_R: 1123141cc406Sopenharmony_ci *(SANE_Word *) v = SANE_FIX (s->exposure_r); 1124141cc406Sopenharmony_ci break; 1125141cc406Sopenharmony_ci case CS2_OPTION_EXPOSURE_G: 1126141cc406Sopenharmony_ci *(SANE_Word *) v = SANE_FIX (s->exposure_g); 1127141cc406Sopenharmony_ci break; 1128141cc406Sopenharmony_ci case CS2_OPTION_EXPOSURE_B: 1129141cc406Sopenharmony_ci *(SANE_Word *) v = SANE_FIX (s->exposure_b); 1130141cc406Sopenharmony_ci break; 1131141cc406Sopenharmony_ci case CS2_OPTION_LUT_R: 1132141cc406Sopenharmony_ci if (!(s->lut_r)) 1133141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1134141cc406Sopenharmony_ci for (pixel = 0; pixel < s->n_lut; pixel++) 1135141cc406Sopenharmony_ci ((SANE_Word *) v)[pixel] = s->lut_r[pixel]; 1136141cc406Sopenharmony_ci break; 1137141cc406Sopenharmony_ci case CS2_OPTION_LUT_G: 1138141cc406Sopenharmony_ci if (!(s->lut_g)) 1139141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1140141cc406Sopenharmony_ci for (pixel = 0; pixel < s->n_lut; pixel++) 1141141cc406Sopenharmony_ci ((SANE_Word *) v)[pixel] = s->lut_g[pixel]; 1142141cc406Sopenharmony_ci break; 1143141cc406Sopenharmony_ci case CS2_OPTION_LUT_B: 1144141cc406Sopenharmony_ci if (!(s->lut_b)) 1145141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1146141cc406Sopenharmony_ci for (pixel = 0; pixel < s->n_lut; pixel++) 1147141cc406Sopenharmony_ci ((SANE_Word *) v)[pixel] = s->lut_b[pixel]; 1148141cc406Sopenharmony_ci break; 1149141cc406Sopenharmony_ci case CS2_OPTION_EJECT: 1150141cc406Sopenharmony_ci break; 1151141cc406Sopenharmony_ci case CS2_OPTION_LOAD: 1152141cc406Sopenharmony_ci break; 1153141cc406Sopenharmony_ci case CS2_OPTION_RESET: 1154141cc406Sopenharmony_ci break; 1155141cc406Sopenharmony_ci case CS2_OPTION_FRAME: 1156141cc406Sopenharmony_ci *(SANE_Word *) v = s->i_frame; 1157141cc406Sopenharmony_ci break; 1158141cc406Sopenharmony_ci case CS2_OPTION_SUBFRAME: 1159141cc406Sopenharmony_ci *(SANE_Word *) v = SANE_FIX (s->subframe); 1160141cc406Sopenharmony_ci break; 1161141cc406Sopenharmony_ci case CS2_OPTION_RES: 1162141cc406Sopenharmony_ci *(SANE_Word *) v = s->res; 1163141cc406Sopenharmony_ci break; 1164141cc406Sopenharmony_ci case CS2_OPTION_RESX: 1165141cc406Sopenharmony_ci *(SANE_Word *) v = s->resx; 1166141cc406Sopenharmony_ci break; 1167141cc406Sopenharmony_ci case CS2_OPTION_RESY: 1168141cc406Sopenharmony_ci *(SANE_Word *) v = s->resy; 1169141cc406Sopenharmony_ci break; 1170141cc406Sopenharmony_ci case CS2_OPTION_RES_INDEPENDENT: 1171141cc406Sopenharmony_ci *(SANE_Word *) v = s->res_independent; 1172141cc406Sopenharmony_ci break; 1173141cc406Sopenharmony_ci case CS2_OPTION_PREVIEW_RESOLUTION: 1174141cc406Sopenharmony_ci *(SANE_Word *) v = s->res_preview; 1175141cc406Sopenharmony_ci break; 1176141cc406Sopenharmony_ci case CS2_OPTION_XMIN: 1177141cc406Sopenharmony_ci *(SANE_Word *) v = s->xmin; 1178141cc406Sopenharmony_ci break; 1179141cc406Sopenharmony_ci case CS2_OPTION_XMAX: 1180141cc406Sopenharmony_ci *(SANE_Word *) v = s->xmax; 1181141cc406Sopenharmony_ci break; 1182141cc406Sopenharmony_ci case CS2_OPTION_YMIN: 1183141cc406Sopenharmony_ci *(SANE_Word *) v = s->ymin; 1184141cc406Sopenharmony_ci break; 1185141cc406Sopenharmony_ci case CS2_OPTION_YMAX: 1186141cc406Sopenharmony_ci *(SANE_Word *) v = s->ymax; 1187141cc406Sopenharmony_ci break; 1188141cc406Sopenharmony_ci case CS2_OPTION_FOCUS_ON_CENTRE: 1189141cc406Sopenharmony_ci *(SANE_Word *) v = s->focus_on_centre; 1190141cc406Sopenharmony_ci break; 1191141cc406Sopenharmony_ci case CS2_OPTION_FOCUS: 1192141cc406Sopenharmony_ci *(SANE_Word *) v = s->focus; 1193141cc406Sopenharmony_ci break; 1194141cc406Sopenharmony_ci case CS2_OPTION_AUTOFOCUS: 1195141cc406Sopenharmony_ci break; 1196141cc406Sopenharmony_ci case CS2_OPTION_FOCUSX: 1197141cc406Sopenharmony_ci *(SANE_Word *) v = s->focusx; 1198141cc406Sopenharmony_ci break; 1199141cc406Sopenharmony_ci case CS2_OPTION_FOCUSY: 1200141cc406Sopenharmony_ci *(SANE_Word *) v = s->focusy; 1201141cc406Sopenharmony_ci break; 1202141cc406Sopenharmony_ci case CS2_OPTION_SCAN_AE: 1203141cc406Sopenharmony_ci break; 1204141cc406Sopenharmony_ci case CS2_OPTION_SCAN_AE_WB: 1205141cc406Sopenharmony_ci break; 1206141cc406Sopenharmony_ci default: 1207141cc406Sopenharmony_ci DBG (4, "Error: sane_control_option(): Unknown option (bug?).\n"); 1208141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1209141cc406Sopenharmony_ci } 1210141cc406Sopenharmony_ci break; 1211141cc406Sopenharmony_ci 1212141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 1213141cc406Sopenharmony_ci if (s->scanning) 1214141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1215141cc406Sopenharmony_ci/* XXXXXXXXXXXXXXXXX do this for all elements of arrays */ 1216141cc406Sopenharmony_ci switch (o.type) 1217141cc406Sopenharmony_ci { 1218141cc406Sopenharmony_ci case SANE_TYPE_BOOL: 1219141cc406Sopenharmony_ci if ((*(SANE_Word *) v != SANE_TRUE) 1220141cc406Sopenharmony_ci && (*(SANE_Word *) v != SANE_FALSE)) 1221141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1222141cc406Sopenharmony_ci break; 1223141cc406Sopenharmony_ci case SANE_TYPE_INT: 1224141cc406Sopenharmony_ci case SANE_TYPE_FIXED: 1225141cc406Sopenharmony_ci switch (o.constraint_type) 1226141cc406Sopenharmony_ci { 1227141cc406Sopenharmony_ci case SANE_CONSTRAINT_RANGE: 1228141cc406Sopenharmony_ci if (*(SANE_Word *) v < o.constraint.range->min) 1229141cc406Sopenharmony_ci { 1230141cc406Sopenharmony_ci *(SANE_Word *) v = o.constraint.range->min; 1231141cc406Sopenharmony_ci flags |= SANE_INFO_INEXACT; 1232141cc406Sopenharmony_ci } 1233141cc406Sopenharmony_ci else if (*(SANE_Word *) v > o.constraint.range->max) 1234141cc406Sopenharmony_ci { 1235141cc406Sopenharmony_ci *(SANE_Word *) v = o.constraint.range->max; 1236141cc406Sopenharmony_ci flags |= SANE_INFO_INEXACT; 1237141cc406Sopenharmony_ci } 1238141cc406Sopenharmony_ci break; 1239141cc406Sopenharmony_ci case SANE_CONSTRAINT_WORD_LIST: 1240141cc406Sopenharmony_ci break; 1241141cc406Sopenharmony_ci default: 1242141cc406Sopenharmony_ci break; 1243141cc406Sopenharmony_ci } 1244141cc406Sopenharmony_ci break; 1245141cc406Sopenharmony_ci case SANE_TYPE_STRING: 1246141cc406Sopenharmony_ci break; 1247141cc406Sopenharmony_ci case SANE_TYPE_BUTTON: 1248141cc406Sopenharmony_ci break; 1249141cc406Sopenharmony_ci case SANE_TYPE_GROUP: 1250141cc406Sopenharmony_ci break; 1251141cc406Sopenharmony_ci } 1252141cc406Sopenharmony_ci switch (n) 1253141cc406Sopenharmony_ci { 1254141cc406Sopenharmony_ci case CS2_OPTION_NUM: 1255141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1256141cc406Sopenharmony_ci break; 1257141cc406Sopenharmony_ci case CS2_OPTION_NEGATIVE: 1258141cc406Sopenharmony_ci s->negative = *(SANE_Word *) v; 1259141cc406Sopenharmony_ci break; 1260141cc406Sopenharmony_ci case CS2_OPTION_INFRARED: 1261141cc406Sopenharmony_ci s->infrared = *(SANE_Word *) v; 1262141cc406Sopenharmony_ci /* flags |= SANE_INFO_RELOAD_PARAMS; XXXXXXXXXXXXXXXXX */ 1263141cc406Sopenharmony_ci break; 1264141cc406Sopenharmony_ci case CS2_OPTION_SAMPLES_PER_SCAN: 1265141cc406Sopenharmony_ci s->samples_per_scan = *(SANE_Word *) v; 1266141cc406Sopenharmony_ci break; 1267141cc406Sopenharmony_ci case CS2_OPTION_DEPTH: 1268141cc406Sopenharmony_ci s->depth = *(SANE_Word *) v; 1269141cc406Sopenharmony_ci flags |= SANE_INFO_RELOAD_PARAMS; 1270141cc406Sopenharmony_ci break; 1271141cc406Sopenharmony_ci case CS2_OPTION_PREVIEW: 1272141cc406Sopenharmony_ci s->preview = *(SANE_Word *) v; 1273141cc406Sopenharmony_ci break; 1274141cc406Sopenharmony_ci case CS2_OPTION_EXPOSURE: 1275141cc406Sopenharmony_ci s->exposure = SANE_UNFIX (*(SANE_Word *) v); 1276141cc406Sopenharmony_ci break; 1277141cc406Sopenharmony_ci case CS2_OPTION_EXPOSURE_R: 1278141cc406Sopenharmony_ci s->exposure_r = SANE_UNFIX (*(SANE_Word *) v); 1279141cc406Sopenharmony_ci break; 1280141cc406Sopenharmony_ci case CS2_OPTION_EXPOSURE_G: 1281141cc406Sopenharmony_ci s->exposure_g = SANE_UNFIX (*(SANE_Word *) v); 1282141cc406Sopenharmony_ci break; 1283141cc406Sopenharmony_ci case CS2_OPTION_EXPOSURE_B: 1284141cc406Sopenharmony_ci s->exposure_b = SANE_UNFIX (*(SANE_Word *) v); 1285141cc406Sopenharmony_ci break; 1286141cc406Sopenharmony_ci case CS2_OPTION_LUT_R: 1287141cc406Sopenharmony_ci if (!(s->lut_r)) 1288141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1289141cc406Sopenharmony_ci for (pixel = 0; pixel < s->n_lut; pixel++) 1290141cc406Sopenharmony_ci s->lut_r[pixel] = ((SANE_Word *) v)[pixel]; 1291141cc406Sopenharmony_ci break; 1292141cc406Sopenharmony_ci case CS2_OPTION_LUT_G: 1293141cc406Sopenharmony_ci if (!(s->lut_g)) 1294141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1295141cc406Sopenharmony_ci for (pixel = 0; pixel < s->n_lut; pixel++) 1296141cc406Sopenharmony_ci s->lut_g[pixel] = ((SANE_Word *) v)[pixel]; 1297141cc406Sopenharmony_ci break; 1298141cc406Sopenharmony_ci case CS2_OPTION_LUT_B: 1299141cc406Sopenharmony_ci if (!(s->lut_b)) 1300141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1301141cc406Sopenharmony_ci for (pixel = 0; pixel < s->n_lut; pixel++) 1302141cc406Sopenharmony_ci s->lut_b[pixel] = ((SANE_Word *) v)[pixel]; 1303141cc406Sopenharmony_ci break; 1304141cc406Sopenharmony_ci case CS2_OPTION_LOAD: 1305141cc406Sopenharmony_ci cs2_load (s); 1306141cc406Sopenharmony_ci break; 1307141cc406Sopenharmony_ci case CS2_OPTION_EJECT: 1308141cc406Sopenharmony_ci cs2_eject (s); 1309141cc406Sopenharmony_ci break; 1310141cc406Sopenharmony_ci case CS2_OPTION_RESET: 1311141cc406Sopenharmony_ci cs2_reset (s); 1312141cc406Sopenharmony_ci break; 1313141cc406Sopenharmony_ci case CS2_OPTION_FRAME: 1314141cc406Sopenharmony_ci s->i_frame = *(SANE_Word *) v; 1315141cc406Sopenharmony_ci break; 1316141cc406Sopenharmony_ci case CS2_OPTION_SUBFRAME: 1317141cc406Sopenharmony_ci s->subframe = SANE_UNFIX (*(SANE_Word *) v); 1318141cc406Sopenharmony_ci break; 1319141cc406Sopenharmony_ci case CS2_OPTION_RES: 1320141cc406Sopenharmony_ci s->res = *(SANE_Word *) v; 1321141cc406Sopenharmony_ci flags |= SANE_INFO_RELOAD_PARAMS; 1322141cc406Sopenharmony_ci break; 1323141cc406Sopenharmony_ci case CS2_OPTION_RESX: 1324141cc406Sopenharmony_ci s->resx = *(SANE_Word *) v; 1325141cc406Sopenharmony_ci flags |= SANE_INFO_RELOAD_PARAMS; 1326141cc406Sopenharmony_ci break; 1327141cc406Sopenharmony_ci case CS2_OPTION_RESY: 1328141cc406Sopenharmony_ci s->resy = *(SANE_Word *) v; 1329141cc406Sopenharmony_ci flags |= SANE_INFO_RELOAD_PARAMS; 1330141cc406Sopenharmony_ci break; 1331141cc406Sopenharmony_ci case CS2_OPTION_RES_INDEPENDENT: 1332141cc406Sopenharmony_ci s->res_independent = *(SANE_Word *) v; 1333141cc406Sopenharmony_ci flags |= SANE_INFO_RELOAD_PARAMS; 1334141cc406Sopenharmony_ci break; 1335141cc406Sopenharmony_ci case CS2_OPTION_PREVIEW_RESOLUTION: 1336141cc406Sopenharmony_ci s->res_preview = *(SANE_Word *) v; 1337141cc406Sopenharmony_ci flags |= SANE_INFO_RELOAD_PARAMS; 1338141cc406Sopenharmony_ci break; 1339141cc406Sopenharmony_ci case CS2_OPTION_XMIN: 1340141cc406Sopenharmony_ci s->xmin = *(SANE_Word *) v; 1341141cc406Sopenharmony_ci flags |= SANE_INFO_RELOAD_PARAMS; 1342141cc406Sopenharmony_ci break; 1343141cc406Sopenharmony_ci case CS2_OPTION_XMAX: 1344141cc406Sopenharmony_ci s->xmax = *(SANE_Word *) v; 1345141cc406Sopenharmony_ci flags |= SANE_INFO_RELOAD_PARAMS; 1346141cc406Sopenharmony_ci break; 1347141cc406Sopenharmony_ci case CS2_OPTION_YMIN: 1348141cc406Sopenharmony_ci s->ymin = *(SANE_Word *) v; 1349141cc406Sopenharmony_ci flags |= SANE_INFO_RELOAD_PARAMS; 1350141cc406Sopenharmony_ci break; 1351141cc406Sopenharmony_ci case CS2_OPTION_YMAX: 1352141cc406Sopenharmony_ci s->ymax = *(SANE_Word *) v; 1353141cc406Sopenharmony_ci flags |= SANE_INFO_RELOAD_PARAMS; 1354141cc406Sopenharmony_ci break; 1355141cc406Sopenharmony_ci case CS2_OPTION_FOCUS_ON_CENTRE: 1356141cc406Sopenharmony_ci s->focus_on_centre = *(SANE_Word *) v; 1357141cc406Sopenharmony_ci if (s->focus_on_centre) 1358141cc406Sopenharmony_ci { 1359141cc406Sopenharmony_ci s->option_list[CS2_OPTION_FOCUSX].cap |= SANE_CAP_INACTIVE; 1360141cc406Sopenharmony_ci s->option_list[CS2_OPTION_FOCUSY].cap |= SANE_CAP_INACTIVE; 1361141cc406Sopenharmony_ci } 1362141cc406Sopenharmony_ci else 1363141cc406Sopenharmony_ci { 1364141cc406Sopenharmony_ci s->option_list[CS2_OPTION_FOCUSX].cap &= ~SANE_CAP_INACTIVE; 1365141cc406Sopenharmony_ci s->option_list[CS2_OPTION_FOCUSY].cap &= ~SANE_CAP_INACTIVE; 1366141cc406Sopenharmony_ci } 1367141cc406Sopenharmony_ci flags |= SANE_INFO_RELOAD_OPTIONS; 1368141cc406Sopenharmony_ci break; 1369141cc406Sopenharmony_ci case CS2_OPTION_FOCUS: 1370141cc406Sopenharmony_ci s->focus = *(SANE_Word *) v; 1371141cc406Sopenharmony_ci break; 1372141cc406Sopenharmony_ci case CS2_OPTION_AUTOFOCUS: 1373141cc406Sopenharmony_ci cs2_autofocus (s); 1374141cc406Sopenharmony_ci flags |= SANE_INFO_RELOAD_OPTIONS; 1375141cc406Sopenharmony_ci break; 1376141cc406Sopenharmony_ci case CS2_OPTION_FOCUSX: 1377141cc406Sopenharmony_ci s->focusx = *(SANE_Word *) v; 1378141cc406Sopenharmony_ci break; 1379141cc406Sopenharmony_ci case CS2_OPTION_FOCUSY: 1380141cc406Sopenharmony_ci s->focusy = *(SANE_Word *) v; 1381141cc406Sopenharmony_ci break; 1382141cc406Sopenharmony_ci case CS2_OPTION_SCAN_AE: 1383141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); 1384141cc406Sopenharmony_ci status = cs2_scan (s, CS2_SCAN_AE); 1385141cc406Sopenharmony_ci if (status) 1386141cc406Sopenharmony_ci return status; 1387141cc406Sopenharmony_ci status = cs2_get_exposure (s); 1388141cc406Sopenharmony_ci if (status) 1389141cc406Sopenharmony_ci return status; 1390141cc406Sopenharmony_ci s->exposure = 1.; 1391141cc406Sopenharmony_ci s->exposure_r = s->real_exposure[1] / 100.; 1392141cc406Sopenharmony_ci s->exposure_g = s->real_exposure[2] / 100.; 1393141cc406Sopenharmony_ci s->exposure_b = s->real_exposure[3] / 100.; 1394141cc406Sopenharmony_ci flags |= SANE_INFO_RELOAD_OPTIONS; 1395141cc406Sopenharmony_ci break; 1396141cc406Sopenharmony_ci case CS2_OPTION_SCAN_AE_WB: 1397141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); 1398141cc406Sopenharmony_ci status = cs2_scan (s, CS2_SCAN_AE_WB); 1399141cc406Sopenharmony_ci if (status) 1400141cc406Sopenharmony_ci return status; 1401141cc406Sopenharmony_ci status = cs2_get_exposure (s); 1402141cc406Sopenharmony_ci if (status) 1403141cc406Sopenharmony_ci return status; 1404141cc406Sopenharmony_ci s->exposure = 1.; 1405141cc406Sopenharmony_ci s->exposure_r = s->real_exposure[1] / 100.; 1406141cc406Sopenharmony_ci s->exposure_g = s->real_exposure[2] / 100.; 1407141cc406Sopenharmony_ci s->exposure_b = s->real_exposure[3] / 100.; 1408141cc406Sopenharmony_ci flags |= SANE_INFO_RELOAD_OPTIONS; 1409141cc406Sopenharmony_ci break; 1410141cc406Sopenharmony_ci default: 1411141cc406Sopenharmony_ci DBG (4, 1412141cc406Sopenharmony_ci "Error: sane_control_option(): Unknown option number (bug?).\n"); 1413141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1414141cc406Sopenharmony_ci break; 1415141cc406Sopenharmony_ci } 1416141cc406Sopenharmony_ci break; 1417141cc406Sopenharmony_ci 1418141cc406Sopenharmony_ci default: 1419141cc406Sopenharmony_ci DBG (1, "BUG: sane_control_option(): Unknown action number.\n"); 1420141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1421141cc406Sopenharmony_ci break; 1422141cc406Sopenharmony_ci } 1423141cc406Sopenharmony_ci 1424141cc406Sopenharmony_ci if (i) 1425141cc406Sopenharmony_ci *i = flags; 1426141cc406Sopenharmony_ci 1427141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1428141cc406Sopenharmony_ci} 1429141cc406Sopenharmony_ci 1430141cc406Sopenharmony_ciSANE_Status 1431141cc406Sopenharmony_cisane_get_parameters (SANE_Handle h, SANE_Parameters * p) 1432141cc406Sopenharmony_ci{ 1433141cc406Sopenharmony_ci cs2_t *s = (cs2_t *) h; 1434141cc406Sopenharmony_ci SANE_Status status; 1435141cc406Sopenharmony_ci 1436141cc406Sopenharmony_ci DBG (10, "sane_get_parameters() called.\n"); 1437141cc406Sopenharmony_ci 1438141cc406Sopenharmony_ci if (!s->scanning) /* only recalculate when not scanning */ 1439141cc406Sopenharmony_ci { 1440141cc406Sopenharmony_ci status = cs2_convert_options (s); 1441141cc406Sopenharmony_ci if (status) 1442141cc406Sopenharmony_ci return status; 1443141cc406Sopenharmony_ci } 1444141cc406Sopenharmony_ci 1445141cc406Sopenharmony_ci if (s->infrared_stage == CS2_INFRARED_OUT) 1446141cc406Sopenharmony_ci { 1447141cc406Sopenharmony_ci p->format = SANE_FRAME_GRAY; 1448141cc406Sopenharmony_ci p->bytes_per_line = s->logical_width * s->bytes_per_pixel; 1449141cc406Sopenharmony_ci } 1450141cc406Sopenharmony_ci else 1451141cc406Sopenharmony_ci { 1452141cc406Sopenharmony_ci p->format = SANE_FRAME_RGB; /* XXXXXXXX CCCCCCCCCC */ 1453141cc406Sopenharmony_ci p->bytes_per_line = 1454141cc406Sopenharmony_ci s->n_colour_out * s->logical_width * s->bytes_per_pixel; 1455141cc406Sopenharmony_ci } 1456141cc406Sopenharmony_ci p->last_frame = SANE_TRUE; 1457141cc406Sopenharmony_ci p->lines = s->logical_height; 1458141cc406Sopenharmony_ci p->depth = 8 * s->bytes_per_pixel; 1459141cc406Sopenharmony_ci p->pixels_per_line = s->logical_width; 1460141cc406Sopenharmony_ci 1461141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1462141cc406Sopenharmony_ci} 1463141cc406Sopenharmony_ci 1464141cc406Sopenharmony_ciSANE_Status 1465141cc406Sopenharmony_cisane_start (SANE_Handle h) 1466141cc406Sopenharmony_ci{ 1467141cc406Sopenharmony_ci cs2_t *s = (cs2_t *) h; 1468141cc406Sopenharmony_ci SANE_Status status; 1469141cc406Sopenharmony_ci 1470141cc406Sopenharmony_ci DBG (10, "sane_start() called.\n"); 1471141cc406Sopenharmony_ci 1472141cc406Sopenharmony_ci if (s->scanning) 1473141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1474141cc406Sopenharmony_ci 1475141cc406Sopenharmony_ci status = cs2_convert_options (s); 1476141cc406Sopenharmony_ci if (status) 1477141cc406Sopenharmony_ci return status; 1478141cc406Sopenharmony_ci 1479141cc406Sopenharmony_ci s->infrared_index = 0; 1480141cc406Sopenharmony_ci s->i_line_buf = 0; 1481141cc406Sopenharmony_ci s->xfer_position = 0; 1482141cc406Sopenharmony_ci 1483141cc406Sopenharmony_ci s->scanning = SANE_TRUE; 1484141cc406Sopenharmony_ci 1485141cc406Sopenharmony_ci if (s->infrared_stage == CS2_INFRARED_OUT) 1486141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1487141cc406Sopenharmony_ci else 1488141cc406Sopenharmony_ci return cs2_scan (s, CS2_SCAN_NORMAL); 1489141cc406Sopenharmony_ci} 1490141cc406Sopenharmony_ci 1491141cc406Sopenharmony_ciSANE_Status 1492141cc406Sopenharmony_cisane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len) 1493141cc406Sopenharmony_ci{ 1494141cc406Sopenharmony_ci cs2_t *s = (cs2_t *) h; 1495141cc406Sopenharmony_ci SANE_Status status; 1496141cc406Sopenharmony_ci ssize_t xfer_len_in, xfer_len_line, xfer_len_out; 1497141cc406Sopenharmony_ci unsigned long index; 1498141cc406Sopenharmony_ci int colour, n_colours, sample_pass; 1499141cc406Sopenharmony_ci uint8_t *s8 = NULL; 1500141cc406Sopenharmony_ci uint16_t *s16 = NULL; 1501141cc406Sopenharmony_ci double m_avg_sum; 1502141cc406Sopenharmony_ci SANE_Byte *line_buf_new; 1503141cc406Sopenharmony_ci 1504141cc406Sopenharmony_ci DBG (10, "sane_read() called, maxlen = %i.\n", maxlen); 1505141cc406Sopenharmony_ci 1506141cc406Sopenharmony_ci if (!s->scanning) { 1507141cc406Sopenharmony_ci *len = 0; 1508141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 1509141cc406Sopenharmony_ci } 1510141cc406Sopenharmony_ci 1511141cc406Sopenharmony_ci if (s->infrared_stage == CS2_INFRARED_OUT) 1512141cc406Sopenharmony_ci { 1513141cc406Sopenharmony_ci xfer_len_out = maxlen; 1514141cc406Sopenharmony_ci 1515141cc406Sopenharmony_ci if (s->xfer_position + xfer_len_out > s->n_infrared_buf) 1516141cc406Sopenharmony_ci xfer_len_out = s->n_infrared_buf - s->xfer_position; 1517141cc406Sopenharmony_ci 1518141cc406Sopenharmony_ci if (xfer_len_out == 0) /* no more data */ 1519141cc406Sopenharmony_ci { 1520141cc406Sopenharmony_ci *len = 0; 1521141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 1522141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1523141cc406Sopenharmony_ci } 1524141cc406Sopenharmony_ci 1525141cc406Sopenharmony_ci memcpy (buf, &(s->infrared_buf[s->xfer_position]), xfer_len_out); 1526141cc406Sopenharmony_ci 1527141cc406Sopenharmony_ci s->xfer_position += xfer_len_out; 1528141cc406Sopenharmony_ci 1529141cc406Sopenharmony_ci if (s->xfer_position >= s->n_infrared_buf) 1530141cc406Sopenharmony_ci s->infrared_next = CS2_INFRARED_OFF; 1531141cc406Sopenharmony_ci 1532141cc406Sopenharmony_ci *len = xfer_len_out; 1533141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1534141cc406Sopenharmony_ci } 1535141cc406Sopenharmony_ci 1536141cc406Sopenharmony_ci if (s->i_line_buf > 0) 1537141cc406Sopenharmony_ci { 1538141cc406Sopenharmony_ci xfer_len_out = s->n_line_buf - s->i_line_buf; 1539141cc406Sopenharmony_ci if (xfer_len_out > maxlen) 1540141cc406Sopenharmony_ci xfer_len_out = maxlen; 1541141cc406Sopenharmony_ci 1542141cc406Sopenharmony_ci memcpy (buf, &(s->line_buf[s->i_line_buf]), xfer_len_out); 1543141cc406Sopenharmony_ci 1544141cc406Sopenharmony_ci s->i_line_buf += xfer_len_out; 1545141cc406Sopenharmony_ci if (s->i_line_buf >= s->n_line_buf) 1546141cc406Sopenharmony_ci s->i_line_buf = 0; 1547141cc406Sopenharmony_ci 1548141cc406Sopenharmony_ci *len = xfer_len_out; 1549141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1550141cc406Sopenharmony_ci } 1551141cc406Sopenharmony_ci 1552141cc406Sopenharmony_ci xfer_len_line = s->n_colour_out * s->logical_width * s->bytes_per_pixel; 1553141cc406Sopenharmony_ci xfer_len_in = 1554141cc406Sopenharmony_ci s->n_colour_in * s->logical_width * s->bytes_per_pixel + 1555141cc406Sopenharmony_ci s->n_colour_in * s->odd_padding; 1556141cc406Sopenharmony_ci /* Do not change the behaviour of older models */ 1557141cc406Sopenharmony_ci if ((s->type == CS2_TYPE_LS50) || (s->type == CS2_TYPE_LS5000)) 1558141cc406Sopenharmony_ci { 1559141cc406Sopenharmony_ci /* Ariel - Check, win driver uses multiple of 64, docu seems to say 512? */ 1560141cc406Sopenharmony_ci ssize_t i; 1561141cc406Sopenharmony_ci xfer_len_in += s->block_padding; 1562141cc406Sopenharmony_ci i = (xfer_len_in & 0x3f); 1563141cc406Sopenharmony_ci if (i != 0) 1564141cc406Sopenharmony_ci DBG (1, "BUG: sane_read(): Read size is not a multiple of 64. (0x%06lx)\n", (long) i); 1565141cc406Sopenharmony_ci } 1566141cc406Sopenharmony_ci 1567141cc406Sopenharmony_ci if (s->xfer_position + xfer_len_line > s->xfer_bytes_total) 1568141cc406Sopenharmony_ci xfer_len_line = s->xfer_bytes_total - s->xfer_position; /* just in case */ 1569141cc406Sopenharmony_ci 1570141cc406Sopenharmony_ci if (xfer_len_line == 0) /* no more data */ 1571141cc406Sopenharmony_ci { 1572141cc406Sopenharmony_ci *len = 0; 1573141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 1574141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1575141cc406Sopenharmony_ci } 1576141cc406Sopenharmony_ci 1577141cc406Sopenharmony_ci if (xfer_len_line != s->n_line_buf) 1578141cc406Sopenharmony_ci { 1579141cc406Sopenharmony_ci line_buf_new = 1580141cc406Sopenharmony_ci (SANE_Byte *) cs2_xrealloc (s->line_buf, 1581141cc406Sopenharmony_ci xfer_len_line * sizeof (SANE_Byte)); 1582141cc406Sopenharmony_ci if (!line_buf_new) 1583141cc406Sopenharmony_ci { 1584141cc406Sopenharmony_ci *len = 0; 1585141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1586141cc406Sopenharmony_ci } 1587141cc406Sopenharmony_ci s->line_buf = line_buf_new; 1588141cc406Sopenharmony_ci s->n_line_buf = xfer_len_line; 1589141cc406Sopenharmony_ci } 1590141cc406Sopenharmony_ci 1591141cc406Sopenharmony_ci /* adapt for multi-sampling */ 1592141cc406Sopenharmony_ci xfer_len_in *= s->samples_per_scan; 1593141cc406Sopenharmony_ci 1594141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_READY); 1595141cc406Sopenharmony_ci cs2_init_buffer (s); 1596141cc406Sopenharmony_ci cs2_parse_cmd (s, "28 00 00 00 00 00"); 1597141cc406Sopenharmony_ci cs2_pack_byte (s, (xfer_len_in >> 16) & 0xff); 1598141cc406Sopenharmony_ci cs2_pack_byte (s, (xfer_len_in >> 8) & 0xff); 1599141cc406Sopenharmony_ci cs2_pack_byte (s, xfer_len_in & 0xff); 1600141cc406Sopenharmony_ci cs2_parse_cmd (s, "00"); 1601141cc406Sopenharmony_ci s->n_recv = xfer_len_in; 1602141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 1603141cc406Sopenharmony_ci 1604141cc406Sopenharmony_ci if (status) 1605141cc406Sopenharmony_ci { 1606141cc406Sopenharmony_ci *len = 0; 1607141cc406Sopenharmony_ci return status; 1608141cc406Sopenharmony_ci } 1609141cc406Sopenharmony_ci 1610141cc406Sopenharmony_ci n_colours = s->n_colour_out + 1611141cc406Sopenharmony_ci (s->infrared_stage == CS2_INFRARED_IN ? 1 : 0); 1612141cc406Sopenharmony_ci 1613141cc406Sopenharmony_ci for (index = 0; index < s->logical_width; index++) 1614141cc406Sopenharmony_ci for (colour = 0; colour < n_colours; colour++) { 1615141cc406Sopenharmony_ci m_avg_sum = 0.0; 1616141cc406Sopenharmony_ci switch (s->bytes_per_pixel) 1617141cc406Sopenharmony_ci { 1618141cc406Sopenharmony_ci case 1: 1619141cc406Sopenharmony_ci /* calculate target address */ 1620141cc406Sopenharmony_ci if ((s->infrared_stage == CS2_INFRARED_IN) 1621141cc406Sopenharmony_ci && (colour == s->n_colour_out)) 1622141cc406Sopenharmony_ci s8 = (uint8_t *) & (s->infrared_buf[s->infrared_index++]); 1623141cc406Sopenharmony_ci else 1624141cc406Sopenharmony_ci s8 = 1625141cc406Sopenharmony_ci (uint8_t *) & (s->line_buf[s->n_colour_out * index + colour]); 1626141cc406Sopenharmony_ci 1627141cc406Sopenharmony_ci if (s->samples_per_scan > 1) 1628141cc406Sopenharmony_ci { 1629141cc406Sopenharmony_ci /* calculate average of multi samples */ 1630141cc406Sopenharmony_ci for (sample_pass = 0; 1631141cc406Sopenharmony_ci sample_pass < s->samples_per_scan; 1632141cc406Sopenharmony_ci sample_pass++) 1633141cc406Sopenharmony_ci m_avg_sum += (double) 1634141cc406Sopenharmony_ci s->recv_buf[s->logical_width * 1635141cc406Sopenharmony_ci (sample_pass * n_colours + colour) + 1636141cc406Sopenharmony_ci (colour + 1) * s->odd_padding + index]; 1637141cc406Sopenharmony_ci 1638141cc406Sopenharmony_ci *s8 = (uint8_t) (m_avg_sum / s->samples_per_scan + 0.5); 1639141cc406Sopenharmony_ci } 1640141cc406Sopenharmony_ci else 1641141cc406Sopenharmony_ci /* shortcut for single sample */ 1642141cc406Sopenharmony_ci *s8 = 1643141cc406Sopenharmony_ci s->recv_buf[colour * s->logical_width + 1644141cc406Sopenharmony_ci (colour + 1) * s->odd_padding + index]; 1645141cc406Sopenharmony_ci break; 1646141cc406Sopenharmony_ci case 2: 1647141cc406Sopenharmony_ci /* calculate target address */ 1648141cc406Sopenharmony_ci if ((s->infrared_stage == CS2_INFRARED_IN) 1649141cc406Sopenharmony_ci && (colour == s->n_colour_out)) 1650141cc406Sopenharmony_ci s16 = 1651141cc406Sopenharmony_ci (uint16_t *) & (s->infrared_buf[2 * (s->infrared_index++)]); 1652141cc406Sopenharmony_ci else 1653141cc406Sopenharmony_ci s16 = 1654141cc406Sopenharmony_ci (uint16_t *) & (s-> 1655141cc406Sopenharmony_ci line_buf[2 * 1656141cc406Sopenharmony_ci (s->n_colour_out * index + colour)]); 1657141cc406Sopenharmony_ci 1658141cc406Sopenharmony_ci if (s->samples_per_scan > 1) 1659141cc406Sopenharmony_ci { 1660141cc406Sopenharmony_ci /* calculate average of multi samples */ 1661141cc406Sopenharmony_ci for (sample_pass = 0; 1662141cc406Sopenharmony_ci s->samples_per_scan > 1 && sample_pass < s->samples_per_scan; 1663141cc406Sopenharmony_ci sample_pass++) 1664141cc406Sopenharmony_ci m_avg_sum += (double) 1665141cc406Sopenharmony_ci (s->recv_buf[2 * (s->logical_width * (sample_pass * n_colours + colour) + index)] * 256 + 1666141cc406Sopenharmony_ci s->recv_buf[2 * (s->logical_width * (sample_pass * n_colours + colour) + index) + 1]); 1667141cc406Sopenharmony_ci 1668141cc406Sopenharmony_ci *s16 = (uint16_t) (m_avg_sum / s->samples_per_scan + 0.5); 1669141cc406Sopenharmony_ci } 1670141cc406Sopenharmony_ci else 1671141cc406Sopenharmony_ci /* shortcut for single sample */ 1672141cc406Sopenharmony_ci *s16 = 1673141cc406Sopenharmony_ci s->recv_buf[2 * (colour * s->logical_width + index)] * 256 + 1674141cc406Sopenharmony_ci s->recv_buf[2 * (colour * s->logical_width + index) + 1]; 1675141cc406Sopenharmony_ci *s16 <<= s->shift_bits; 1676141cc406Sopenharmony_ci break; 1677141cc406Sopenharmony_ci default: 1678141cc406Sopenharmony_ci DBG (1, "BUG: sane_read(): Unknown number of bytes per pixel.\n"); 1679141cc406Sopenharmony_ci *len = 0; 1680141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1681141cc406Sopenharmony_ci break; 1682141cc406Sopenharmony_ci } 1683141cc406Sopenharmony_ci } 1684141cc406Sopenharmony_ci s->xfer_position += xfer_len_line; 1685141cc406Sopenharmony_ci 1686141cc406Sopenharmony_ci xfer_len_out = xfer_len_line; 1687141cc406Sopenharmony_ci if (xfer_len_out > maxlen) 1688141cc406Sopenharmony_ci xfer_len_out = maxlen; 1689141cc406Sopenharmony_ci 1690141cc406Sopenharmony_ci memcpy (buf, s->line_buf, xfer_len_out); 1691141cc406Sopenharmony_ci if (xfer_len_out < xfer_len_line) 1692141cc406Sopenharmony_ci s->i_line_buf = xfer_len_out; /* data left in the line buffer, read out next time */ 1693141cc406Sopenharmony_ci 1694141cc406Sopenharmony_ci if ((s->infrared_stage == CS2_INFRARED_IN) 1695141cc406Sopenharmony_ci && (s->xfer_position >= s->n_infrared_buf)) 1696141cc406Sopenharmony_ci s->infrared_next = CS2_INFRARED_OUT; 1697141cc406Sopenharmony_ci 1698141cc406Sopenharmony_ci *len = xfer_len_out; 1699141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1700141cc406Sopenharmony_ci} 1701141cc406Sopenharmony_ci 1702141cc406Sopenharmony_civoid 1703141cc406Sopenharmony_cisane_cancel (SANE_Handle h) 1704141cc406Sopenharmony_ci{ 1705141cc406Sopenharmony_ci cs2_t *s = (cs2_t *) h; 1706141cc406Sopenharmony_ci 1707141cc406Sopenharmony_ci if (s->scanning) 1708141cc406Sopenharmony_ci DBG (10, "sane_cancel() called while scanning.\n"); 1709141cc406Sopenharmony_ci else 1710141cc406Sopenharmony_ci DBG (10, "sane_cancel() called while not scanning.\n"); 1711141cc406Sopenharmony_ci 1712141cc406Sopenharmony_ci if (s->scanning && (s->infrared_stage != CS2_INFRARED_OUT)) 1713141cc406Sopenharmony_ci { 1714141cc406Sopenharmony_ci cs2_init_buffer (s); 1715141cc406Sopenharmony_ci cs2_parse_cmd (s, "c0 00 00 00 00 00"); 1716141cc406Sopenharmony_ci cs2_issue_cmd (s); 1717141cc406Sopenharmony_ci } 1718141cc406Sopenharmony_ci 1719141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 1720141cc406Sopenharmony_ci} 1721141cc406Sopenharmony_ci 1722141cc406Sopenharmony_ciSANE_Status 1723141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle h, SANE_Bool m) 1724141cc406Sopenharmony_ci{ 1725141cc406Sopenharmony_ci cs2_t *s = (cs2_t *) h; 1726141cc406Sopenharmony_ci 1727141cc406Sopenharmony_ci DBG (10, "sane_set_io_mode() called.\n"); 1728141cc406Sopenharmony_ci 1729141cc406Sopenharmony_ci if (!s->scanning) 1730141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1731141cc406Sopenharmony_ci if (m == SANE_FALSE) 1732141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1733141cc406Sopenharmony_ci else 1734141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1735141cc406Sopenharmony_ci} 1736141cc406Sopenharmony_ci 1737141cc406Sopenharmony_ciSANE_Status 1738141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle h, SANE_Int * fd) 1739141cc406Sopenharmony_ci{ 1740141cc406Sopenharmony_ci cs2_t *s = (cs2_t *) h; 1741141cc406Sopenharmony_ci 1742141cc406Sopenharmony_ci DBG (10, "sane_get_select_fd() called.\n"); 1743141cc406Sopenharmony_ci 1744141cc406Sopenharmony_ci (void) fd; /* to shut up compiler */ 1745141cc406Sopenharmony_ci (void) s; /* to shut up compiler */ 1746141cc406Sopenharmony_ci 1747141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1748141cc406Sopenharmony_ci} 1749141cc406Sopenharmony_ci 1750141cc406Sopenharmony_ci 1751141cc406Sopenharmony_ci/* ========================================================================= */ 1752141cc406Sopenharmony_ci/* private functions */ 1753141cc406Sopenharmony_ci 1754141cc406Sopenharmony_cistatic SANE_Status 1755141cc406Sopenharmony_cics2_open (const char *device, cs2_interface_t interface, cs2_t ** sp) 1756141cc406Sopenharmony_ci{ 1757141cc406Sopenharmony_ci SANE_Status status; 1758141cc406Sopenharmony_ci cs2_t *s; 1759141cc406Sopenharmony_ci char *prefix = NULL, *line; 1760141cc406Sopenharmony_ci const char *device2; 1761141cc406Sopenharmony_ci int i; 1762141cc406Sopenharmony_ci int alloc_failed = 0; 1763141cc406Sopenharmony_ci SANE_Device **device_list_new; 1764141cc406Sopenharmony_ci 1765141cc406Sopenharmony_ci DBG (6, "cs2_open() called, with device = %s and interface = %i\n", device, 1766141cc406Sopenharmony_ci interface); 1767141cc406Sopenharmony_ci 1768141cc406Sopenharmony_ci if (!strncmp (device, "auto", 5)) 1769141cc406Sopenharmony_ci { 1770141cc406Sopenharmony_ci try_interface = CS2_INTERFACE_SCSI; 1771141cc406Sopenharmony_ci sanei_config_attach_matching_devices ("scsi Nikon *", cs2_attach); 1772141cc406Sopenharmony_ci try_interface = CS2_INTERFACE_USB; 1773141cc406Sopenharmony_ci sanei_usb_attach_matching_devices ("usb 0x04b0 0x4000", cs2_attach); 1774141cc406Sopenharmony_ci sanei_usb_attach_matching_devices ("usb 0x04b0 0x4001", cs2_attach); 1775141cc406Sopenharmony_ci sanei_usb_attach_matching_devices ("usb 0x04b0 0x4002", cs2_attach); 1776141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1777141cc406Sopenharmony_ci } 1778141cc406Sopenharmony_ci 1779141cc406Sopenharmony_ci if ((s = (cs2_t *) cs2_xmalloc (sizeof (cs2_t))) == NULL) 1780141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1781141cc406Sopenharmony_ci memset (s, 0, sizeof (cs2_t)); 1782141cc406Sopenharmony_ci s->send_buf = s->recv_buf = NULL; 1783141cc406Sopenharmony_ci s->send_buf_size = s->recv_buf_size = 0; 1784141cc406Sopenharmony_ci 1785141cc406Sopenharmony_ci switch (interface) 1786141cc406Sopenharmony_ci { 1787141cc406Sopenharmony_ci case CS2_INTERFACE_UNKNOWN: 1788141cc406Sopenharmony_ci for (i = 0; i < 2; i++) 1789141cc406Sopenharmony_ci { 1790141cc406Sopenharmony_ci switch (i) 1791141cc406Sopenharmony_ci { 1792141cc406Sopenharmony_ci case 1: 1793141cc406Sopenharmony_ci prefix = "usb:"; 1794141cc406Sopenharmony_ci try_interface = CS2_INTERFACE_USB; 1795141cc406Sopenharmony_ci break; 1796141cc406Sopenharmony_ci default: 1797141cc406Sopenharmony_ci prefix = "scsi:"; 1798141cc406Sopenharmony_ci try_interface = CS2_INTERFACE_SCSI; 1799141cc406Sopenharmony_ci break; 1800141cc406Sopenharmony_ci } 1801141cc406Sopenharmony_ci if (!strncmp (device, prefix, strlen (prefix))) 1802141cc406Sopenharmony_ci { 1803141cc406Sopenharmony_ci device2 = device + strlen (prefix); 1804141cc406Sopenharmony_ci cs2_xfree (s); 1805141cc406Sopenharmony_ci return cs2_open (device2, try_interface, sp); 1806141cc406Sopenharmony_ci } 1807141cc406Sopenharmony_ci } 1808141cc406Sopenharmony_ci cs2_xfree (s); 1809141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1810141cc406Sopenharmony_ci break; 1811141cc406Sopenharmony_ci case CS2_INTERFACE_SCSI: 1812141cc406Sopenharmony_ci s->interface = CS2_INTERFACE_SCSI; 1813141cc406Sopenharmony_ci DBG (6, 1814141cc406Sopenharmony_ci "cs2_open(): Trying to open %s, assuming SCSI or SBP2 interface ...\n", 1815141cc406Sopenharmony_ci device); 1816141cc406Sopenharmony_ci status = sanei_scsi_open (device, &s->fd, cs2_scsi_sense_handler, s); 1817141cc406Sopenharmony_ci if (status) 1818141cc406Sopenharmony_ci { 1819141cc406Sopenharmony_ci DBG (6, "cs2_open(): ... failed: %s.\n", sane_strstatus (status)); 1820141cc406Sopenharmony_ci cs2_xfree (s); 1821141cc406Sopenharmony_ci return status; 1822141cc406Sopenharmony_ci } 1823141cc406Sopenharmony_ci break; 1824141cc406Sopenharmony_ci case CS2_INTERFACE_USB: 1825141cc406Sopenharmony_ci s->interface = CS2_INTERFACE_USB; 1826141cc406Sopenharmony_ci DBG (6, "cs2_open(): Trying to open %s, assuming USB interface ...\n", 1827141cc406Sopenharmony_ci device); 1828141cc406Sopenharmony_ci status = sanei_usb_open (device, &s->fd); 1829141cc406Sopenharmony_ci if (status) 1830141cc406Sopenharmony_ci { 1831141cc406Sopenharmony_ci DBG (6, "cs2_open(): ... failed: %s.\n", sane_strstatus (status)); 1832141cc406Sopenharmony_ci cs2_xfree (s); 1833141cc406Sopenharmony_ci return status; 1834141cc406Sopenharmony_ci } 1835141cc406Sopenharmony_ci break; 1836141cc406Sopenharmony_ci } 1837141cc406Sopenharmony_ci 1838141cc406Sopenharmony_ci open_devices++; 1839141cc406Sopenharmony_ci DBG (6, "cs2_open(): ... looks OK, trying to identify device.\n"); 1840141cc406Sopenharmony_ci 1841141cc406Sopenharmony_ci /* identify scanner */ 1842141cc406Sopenharmony_ci status = cs2_page_inquiry (s, -1); 1843141cc406Sopenharmony_ci if (status) 1844141cc406Sopenharmony_ci { 1845141cc406Sopenharmony_ci DBG (4, "Error: cs2_open(): failed to get page: %s.\n", 1846141cc406Sopenharmony_ci sane_strstatus (status)); 1847141cc406Sopenharmony_ci cs2_close (s); 1848141cc406Sopenharmony_ci return status; 1849141cc406Sopenharmony_ci } 1850141cc406Sopenharmony_ci 1851141cc406Sopenharmony_ci strncpy (s->vendor_string, (char *)s->recv_buf + 8, 8); 1852141cc406Sopenharmony_ci s->vendor_string[8] = '\0'; 1853141cc406Sopenharmony_ci strncpy (s->product_string, (char *)s->recv_buf + 16, 16); 1854141cc406Sopenharmony_ci s->product_string[16] = '\0'; 1855141cc406Sopenharmony_ci strncpy (s->revision_string, (char *)s->recv_buf + 32, 4); 1856141cc406Sopenharmony_ci s->revision_string[4] = '\0'; 1857141cc406Sopenharmony_ci 1858141cc406Sopenharmony_ci DBG (10, 1859141cc406Sopenharmony_ci "cs2_open(): Inquiry reveals: vendor = '%s', product = '%s', revision = '%s'.\n", 1860141cc406Sopenharmony_ci s->vendor_string, s->product_string, s->revision_string); 1861141cc406Sopenharmony_ci 1862141cc406Sopenharmony_ci if (!strncmp (s->product_string, "COOLSCANIII ", 16)) 1863141cc406Sopenharmony_ci s->type = CS2_TYPE_LS30; 1864141cc406Sopenharmony_ci else if (!strncmp (s->product_string, "LS-40 ED ", 16)) 1865141cc406Sopenharmony_ci s->type = CS2_TYPE_LS40; 1866141cc406Sopenharmony_ci else if (!strncmp (s->product_string, "LS-50 ED ", 16)) 1867141cc406Sopenharmony_ci s->type = CS2_TYPE_LS50; 1868141cc406Sopenharmony_ci else if (!strncmp (s->product_string, "LS-2000 ", 16)) 1869141cc406Sopenharmony_ci s->type = CS2_TYPE_LS2000; 1870141cc406Sopenharmony_ci else if (!strncmp (s->product_string, "LS-4000 ED ", 16)) 1871141cc406Sopenharmony_ci s->type = CS2_TYPE_LS4000; 1872141cc406Sopenharmony_ci else if (!strncmp (s->product_string, "LS-5000 ED ", 16)) 1873141cc406Sopenharmony_ci s->type = CS2_TYPE_LS5000; 1874141cc406Sopenharmony_ci else if (!strncmp (s->product_string, "LS-8000 ED ", 16)) 1875141cc406Sopenharmony_ci s->type = CS2_TYPE_LS8000; 1876141cc406Sopenharmony_ci 1877141cc406Sopenharmony_ci if (s->type != CS2_TYPE_UNKOWN) 1878141cc406Sopenharmony_ci DBG (10, "cs2_open(): Device identified as coolscan2 type #%i.\n", 1879141cc406Sopenharmony_ci s->type); 1880141cc406Sopenharmony_ci else 1881141cc406Sopenharmony_ci { 1882141cc406Sopenharmony_ci DBG (10, "cs2_open(): Device not identified.\n"); 1883141cc406Sopenharmony_ci cs2_close (s); 1884141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1885141cc406Sopenharmony_ci } 1886141cc406Sopenharmony_ci 1887141cc406Sopenharmony_ci if (sp) 1888141cc406Sopenharmony_ci *sp = s; 1889141cc406Sopenharmony_ci else 1890141cc406Sopenharmony_ci { 1891141cc406Sopenharmony_ci device_list_new = 1892141cc406Sopenharmony_ci (SANE_Device **) cs2_xrealloc (device_list, 1893141cc406Sopenharmony_ci (n_device_list + 1894141cc406Sopenharmony_ci 2) * sizeof (SANE_Device *)); 1895141cc406Sopenharmony_ci if (!device_list_new) 1896141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1897141cc406Sopenharmony_ci device_list = device_list_new; 1898141cc406Sopenharmony_ci device_list[n_device_list] = 1899141cc406Sopenharmony_ci (SANE_Device *) cs2_xmalloc (sizeof (SANE_Device)); 1900141cc406Sopenharmony_ci if (!device_list[n_device_list]) 1901141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1902141cc406Sopenharmony_ci switch (interface) 1903141cc406Sopenharmony_ci { 1904141cc406Sopenharmony_ci case CS2_INTERFACE_UNKNOWN: 1905141cc406Sopenharmony_ci DBG (1, "BUG: cs2_open(): unknown interface.\n"); 1906141cc406Sopenharmony_ci cs2_close (s); 1907141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1908141cc406Sopenharmony_ci break; 1909141cc406Sopenharmony_ci case CS2_INTERFACE_SCSI: 1910141cc406Sopenharmony_ci prefix = "scsi:"; 1911141cc406Sopenharmony_ci break; 1912141cc406Sopenharmony_ci case CS2_INTERFACE_USB: 1913141cc406Sopenharmony_ci prefix = "usb:"; 1914141cc406Sopenharmony_ci break; 1915141cc406Sopenharmony_ci } 1916141cc406Sopenharmony_ci 1917141cc406Sopenharmony_ci line = (char *) cs2_xmalloc (strlen (device) + strlen (prefix) + 1); 1918141cc406Sopenharmony_ci if (!line) 1919141cc406Sopenharmony_ci alloc_failed = 1; 1920141cc406Sopenharmony_ci else 1921141cc406Sopenharmony_ci { 1922141cc406Sopenharmony_ci strcpy (line, prefix); 1923141cc406Sopenharmony_ci strcat (line, device); 1924141cc406Sopenharmony_ci device_list[n_device_list]->name = line; 1925141cc406Sopenharmony_ci } 1926141cc406Sopenharmony_ci 1927141cc406Sopenharmony_ci line = (char *) cs2_xmalloc (strlen (s->vendor_string) + 1); 1928141cc406Sopenharmony_ci if (!line) 1929141cc406Sopenharmony_ci alloc_failed = 1; 1930141cc406Sopenharmony_ci else 1931141cc406Sopenharmony_ci { 1932141cc406Sopenharmony_ci strcpy (line, s->vendor_string); 1933141cc406Sopenharmony_ci device_list[n_device_list]->vendor = line; 1934141cc406Sopenharmony_ci } 1935141cc406Sopenharmony_ci 1936141cc406Sopenharmony_ci line = (char *) cs2_xmalloc (strlen (s->product_string) + 1); 1937141cc406Sopenharmony_ci if (!line) 1938141cc406Sopenharmony_ci alloc_failed = 1; 1939141cc406Sopenharmony_ci else 1940141cc406Sopenharmony_ci { 1941141cc406Sopenharmony_ci strcpy (line, s->product_string); 1942141cc406Sopenharmony_ci device_list[n_device_list]->model = line; 1943141cc406Sopenharmony_ci } 1944141cc406Sopenharmony_ci 1945141cc406Sopenharmony_ci device_list[n_device_list]->type = "film scanner"; 1946141cc406Sopenharmony_ci 1947141cc406Sopenharmony_ci if (alloc_failed) 1948141cc406Sopenharmony_ci { 1949141cc406Sopenharmony_ci cs2_xfree (device_list[n_device_list]->name); 1950141cc406Sopenharmony_ci cs2_xfree (device_list[n_device_list]->vendor); 1951141cc406Sopenharmony_ci cs2_xfree (device_list[n_device_list]->model); 1952141cc406Sopenharmony_ci cs2_xfree (device_list[n_device_list]); 1953141cc406Sopenharmony_ci } 1954141cc406Sopenharmony_ci else 1955141cc406Sopenharmony_ci n_device_list++; 1956141cc406Sopenharmony_ci device_list[n_device_list] = NULL; 1957141cc406Sopenharmony_ci 1958141cc406Sopenharmony_ci cs2_close (s); 1959141cc406Sopenharmony_ci } 1960141cc406Sopenharmony_ci 1961141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1962141cc406Sopenharmony_ci} 1963141cc406Sopenharmony_ci 1964141cc406Sopenharmony_civoid 1965141cc406Sopenharmony_cics2_close (cs2_t * s) 1966141cc406Sopenharmony_ci{ 1967141cc406Sopenharmony_ci cs2_xfree (s->lut_r); 1968141cc406Sopenharmony_ci cs2_xfree (s->lut_g); 1969141cc406Sopenharmony_ci cs2_xfree (s->lut_b); 1970141cc406Sopenharmony_ci cs2_xfree (s->lut_neutral); 1971141cc406Sopenharmony_ci cs2_xfree (s->infrared_buf); 1972141cc406Sopenharmony_ci cs2_xfree (s->line_buf); 1973141cc406Sopenharmony_ci 1974141cc406Sopenharmony_ci switch (s->interface) 1975141cc406Sopenharmony_ci { 1976141cc406Sopenharmony_ci case CS2_INTERFACE_UNKNOWN: 1977141cc406Sopenharmony_ci DBG (1, "BUG: cs2_close(): Unknown interface number.\n"); 1978141cc406Sopenharmony_ci break; 1979141cc406Sopenharmony_ci case CS2_INTERFACE_SCSI: 1980141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 1981141cc406Sopenharmony_ci open_devices--; 1982141cc406Sopenharmony_ci break; 1983141cc406Sopenharmony_ci case CS2_INTERFACE_USB: 1984141cc406Sopenharmony_ci sanei_usb_close (s->fd); 1985141cc406Sopenharmony_ci open_devices--; 1986141cc406Sopenharmony_ci break; 1987141cc406Sopenharmony_ci } 1988141cc406Sopenharmony_ci 1989141cc406Sopenharmony_ci cs2_xfree (s); 1990141cc406Sopenharmony_ci} 1991141cc406Sopenharmony_ci 1992141cc406Sopenharmony_cistatic SANE_Status 1993141cc406Sopenharmony_cics2_attach (const char *dev) 1994141cc406Sopenharmony_ci{ 1995141cc406Sopenharmony_ci SANE_Status status; 1996141cc406Sopenharmony_ci 1997141cc406Sopenharmony_ci if (try_interface == CS2_INTERFACE_UNKNOWN) 1998141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1999141cc406Sopenharmony_ci 2000141cc406Sopenharmony_ci status = cs2_open (dev, try_interface, NULL); 2001141cc406Sopenharmony_ci return status; 2002141cc406Sopenharmony_ci} 2003141cc406Sopenharmony_ci 2004141cc406Sopenharmony_cistatic SANE_Status 2005141cc406Sopenharmony_cics2_scsi_sense_handler (int fd, u_char * sense_buffer, void *arg) 2006141cc406Sopenharmony_ci{ 2007141cc406Sopenharmony_ci cs2_t *s = (cs2_t *) arg; 2008141cc406Sopenharmony_ci 2009141cc406Sopenharmony_ci (void) fd; /* to shut up compiler */ 2010141cc406Sopenharmony_ci 2011141cc406Sopenharmony_ci /* sort this out ! XXXXXXXXX */ 2012141cc406Sopenharmony_ci 2013141cc406Sopenharmony_ci s->sense_key = sense_buffer[2] & 0x0f; 2014141cc406Sopenharmony_ci s->sense_asc = sense_buffer[12]; 2015141cc406Sopenharmony_ci s->sense_ascq = sense_buffer[13]; 2016141cc406Sopenharmony_ci s->sense_info = sense_buffer[3]; 2017141cc406Sopenharmony_ci 2018141cc406Sopenharmony_ci return cs2_parse_sense_data (s); 2019141cc406Sopenharmony_ci} 2020141cc406Sopenharmony_ci 2021141cc406Sopenharmony_cistatic SANE_Status 2022141cc406Sopenharmony_cics2_parse_sense_data (cs2_t * s) 2023141cc406Sopenharmony_ci{ 2024141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 2025141cc406Sopenharmony_ci 2026141cc406Sopenharmony_ci s->sense_code = 2027141cc406Sopenharmony_ci (s->sense_key << 24) + (s->sense_asc << 16) + (s->sense_ascq << 8) + 2028141cc406Sopenharmony_ci s->sense_info; 2029141cc406Sopenharmony_ci 2030141cc406Sopenharmony_ci if (s->sense_key) 2031141cc406Sopenharmony_ci DBG (10, "Sense code: %02lx-%02lx-%02lx-%02lx\n", s->sense_key, 2032141cc406Sopenharmony_ci s->sense_asc, s->sense_ascq, s->sense_info); 2033141cc406Sopenharmony_ci 2034141cc406Sopenharmony_ci switch (s->sense_key) 2035141cc406Sopenharmony_ci { 2036141cc406Sopenharmony_ci case 0x00: 2037141cc406Sopenharmony_ci s->status = CS2_STATUS_READY; 2038141cc406Sopenharmony_ci break; 2039141cc406Sopenharmony_ci case 0x02: 2040141cc406Sopenharmony_ci switch (s->sense_asc) 2041141cc406Sopenharmony_ci { 2042141cc406Sopenharmony_ci case 0x04: 2043141cc406Sopenharmony_ci s->status = CS2_STATUS_PROCESSING; 2044141cc406Sopenharmony_ci break; 2045141cc406Sopenharmony_ci case 0x3a: 2046141cc406Sopenharmony_ci s->status = CS2_STATUS_NO_DOCS; 2047141cc406Sopenharmony_ci break; 2048141cc406Sopenharmony_ci default: 2049141cc406Sopenharmony_ci s->status = CS2_STATUS_ERROR; 2050141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2051141cc406Sopenharmony_ci break; 2052141cc406Sopenharmony_ci } 2053141cc406Sopenharmony_ci break; 2054141cc406Sopenharmony_ci default: 2055141cc406Sopenharmony_ci s->status = CS2_STATUS_ERROR; 2056141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2057141cc406Sopenharmony_ci break; 2058141cc406Sopenharmony_ci } 2059141cc406Sopenharmony_ci 2060141cc406Sopenharmony_ci if ((s->sense_code == 0x09800600) || (s->sense_code == 0x09800601)) 2061141cc406Sopenharmony_ci s->status = CS2_STATUS_REISSUE; 2062141cc406Sopenharmony_ci 2063141cc406Sopenharmony_ci return status; 2064141cc406Sopenharmony_ci} 2065141cc406Sopenharmony_ci 2066141cc406Sopenharmony_cistatic void 2067141cc406Sopenharmony_cics2_init_buffer (cs2_t * s) 2068141cc406Sopenharmony_ci{ 2069141cc406Sopenharmony_ci s->n_cmd = 0; 2070141cc406Sopenharmony_ci s->n_send = 0; 2071141cc406Sopenharmony_ci s->n_recv = 0; 2072141cc406Sopenharmony_ci} 2073141cc406Sopenharmony_ci 2074141cc406Sopenharmony_cistatic SANE_Status 2075141cc406Sopenharmony_cics2_pack_byte (cs2_t * s, SANE_Byte byte) 2076141cc406Sopenharmony_ci{ 2077141cc406Sopenharmony_ci while (s->send_buf_size <= s->n_send) 2078141cc406Sopenharmony_ci { 2079141cc406Sopenharmony_ci s->send_buf_size += 16; 2080141cc406Sopenharmony_ci s->send_buf = 2081141cc406Sopenharmony_ci (SANE_Byte *) cs2_xrealloc (s->send_buf, s->send_buf_size); 2082141cc406Sopenharmony_ci if (!s->send_buf) 2083141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2084141cc406Sopenharmony_ci } 2085141cc406Sopenharmony_ci 2086141cc406Sopenharmony_ci s->send_buf[s->n_send++] = byte; 2087141cc406Sopenharmony_ci 2088141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2089141cc406Sopenharmony_ci} 2090141cc406Sopenharmony_ci 2091141cc406Sopenharmony_cistatic SANE_Status 2092141cc406Sopenharmony_cics2_parse_cmd (cs2_t * s, char *text) 2093141cc406Sopenharmony_ci{ 2094141cc406Sopenharmony_ci size_t i, j; 2095141cc406Sopenharmony_ci char c, h; 2096141cc406Sopenharmony_ci SANE_Status status; 2097141cc406Sopenharmony_ci 2098141cc406Sopenharmony_ci for (i = 0; i < strlen (text); i += 2) 2099141cc406Sopenharmony_ci if (text[i] == ' ') 2100141cc406Sopenharmony_ci i--; /* a bit dirty... advance by -1+2=1 */ 2101141cc406Sopenharmony_ci else 2102141cc406Sopenharmony_ci { 2103141cc406Sopenharmony_ci if ((!isxdigit (text[i])) || (!isxdigit (text[i + 1]))) 2104141cc406Sopenharmony_ci DBG (1, "BUG: cs2_parse_cmd(): Parser got invalid character.\n"); 2105141cc406Sopenharmony_ci c = 0; 2106141cc406Sopenharmony_ci for (j = 0; j < 2; j++) 2107141cc406Sopenharmony_ci { 2108141cc406Sopenharmony_ci h = tolower (text[i + j]); 2109141cc406Sopenharmony_ci if ((h >= 'a') && (h <= 'f')) 2110141cc406Sopenharmony_ci c += 10 + h - 'a'; 2111141cc406Sopenharmony_ci else 2112141cc406Sopenharmony_ci c += h - '0'; 2113141cc406Sopenharmony_ci if (j == 0) 2114141cc406Sopenharmony_ci c <<= 4; 2115141cc406Sopenharmony_ci } 2116141cc406Sopenharmony_ci status = cs2_pack_byte (s, c); 2117141cc406Sopenharmony_ci if (status) 2118141cc406Sopenharmony_ci return status; 2119141cc406Sopenharmony_ci } 2120141cc406Sopenharmony_ci 2121141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2122141cc406Sopenharmony_ci} 2123141cc406Sopenharmony_ci 2124141cc406Sopenharmony_cistatic SANE_Status 2125141cc406Sopenharmony_cics2_grow_send_buffer (cs2_t * s) 2126141cc406Sopenharmony_ci{ 2127141cc406Sopenharmony_ci if (s->n_send > s->send_buf_size) 2128141cc406Sopenharmony_ci { 2129141cc406Sopenharmony_ci s->send_buf_size = s->n_send; 2130141cc406Sopenharmony_ci s->send_buf = 2131141cc406Sopenharmony_ci (SANE_Byte *) cs2_xrealloc (s->send_buf, s->send_buf_size); 2132141cc406Sopenharmony_ci if (!s->send_buf) 2133141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2134141cc406Sopenharmony_ci } 2135141cc406Sopenharmony_ci 2136141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2137141cc406Sopenharmony_ci} 2138141cc406Sopenharmony_ci 2139141cc406Sopenharmony_cistatic SANE_Status 2140141cc406Sopenharmony_cics2_issue_cmd (cs2_t * s) 2141141cc406Sopenharmony_ci{ 2142141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_INVAL; 2143141cc406Sopenharmony_ci size_t n_data, n_status; 2144141cc406Sopenharmony_ci static SANE_Byte status_buf[8]; 2145141cc406Sopenharmony_ci int status_only = 0; 2146141cc406Sopenharmony_ci 2147141cc406Sopenharmony_ci DBG (20, "cs2_issue_cmd(): opcode = 0x%02x, n_send = %lu, n_recv = %lu.\n", 2148141cc406Sopenharmony_ci s->send_buf[0], (unsigned long) s->n_send, (unsigned long) s->n_recv); 2149141cc406Sopenharmony_ci 2150141cc406Sopenharmony_ci s->status = CS2_STATUS_READY; 2151141cc406Sopenharmony_ci 2152141cc406Sopenharmony_ci if (!s->n_cmd) 2153141cc406Sopenharmony_ci switch (s->send_buf[0]) 2154141cc406Sopenharmony_ci { 2155141cc406Sopenharmony_ci case 0x00: 2156141cc406Sopenharmony_ci case 0x12: 2157141cc406Sopenharmony_ci case 0x15: 2158141cc406Sopenharmony_ci case 0x16: 2159141cc406Sopenharmony_ci case 0x17: 2160141cc406Sopenharmony_ci case 0x1a: 2161141cc406Sopenharmony_ci case 0x1b: 2162141cc406Sopenharmony_ci case 0x1c: 2163141cc406Sopenharmony_ci case 0x1d: 2164141cc406Sopenharmony_ci case 0xc0: 2165141cc406Sopenharmony_ci case 0xc1: 2166141cc406Sopenharmony_ci s->n_cmd = 6; 2167141cc406Sopenharmony_ci break; 2168141cc406Sopenharmony_ci case 0x24: 2169141cc406Sopenharmony_ci case 0x25: 2170141cc406Sopenharmony_ci case 0x28: 2171141cc406Sopenharmony_ci case 0x2a: 2172141cc406Sopenharmony_ci case 0xe0: 2173141cc406Sopenharmony_ci case 0xe1: 2174141cc406Sopenharmony_ci s->n_cmd = 10; 2175141cc406Sopenharmony_ci break; 2176141cc406Sopenharmony_ci default: 2177141cc406Sopenharmony_ci DBG (1, "BUG: cs2_issue_cmd(): Unknown command opcode 0x%02x.\n", 2178141cc406Sopenharmony_ci s->send_buf[0]); 2179141cc406Sopenharmony_ci break; 2180141cc406Sopenharmony_ci } 2181141cc406Sopenharmony_ci 2182141cc406Sopenharmony_ci if (s->n_send < s->n_cmd) 2183141cc406Sopenharmony_ci { 2184141cc406Sopenharmony_ci DBG (1, 2185141cc406Sopenharmony_ci "BUG: cs2_issue_cmd(): Negative number of data out bytes requested.\n"); 2186141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2187141cc406Sopenharmony_ci } 2188141cc406Sopenharmony_ci 2189141cc406Sopenharmony_ci n_data = s->n_send - s->n_cmd; 2190141cc406Sopenharmony_ci if (s->n_recv > 0) 2191141cc406Sopenharmony_ci { 2192141cc406Sopenharmony_ci if (n_data > 0) 2193141cc406Sopenharmony_ci { 2194141cc406Sopenharmony_ci DBG (1, 2195141cc406Sopenharmony_ci "BUG: cs2_issue_cmd(): Both data in and data out requested.\n"); 2196141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2197141cc406Sopenharmony_ci } 2198141cc406Sopenharmony_ci else 2199141cc406Sopenharmony_ci { 2200141cc406Sopenharmony_ci n_data = s->n_recv; 2201141cc406Sopenharmony_ci } 2202141cc406Sopenharmony_ci } 2203141cc406Sopenharmony_ci 2204141cc406Sopenharmony_ci s->recv_buf = (SANE_Byte *) cs2_xrealloc (s->recv_buf, s->n_recv); 2205141cc406Sopenharmony_ci if (!s->recv_buf) 2206141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2207141cc406Sopenharmony_ci 2208141cc406Sopenharmony_ci switch (s->interface) 2209141cc406Sopenharmony_ci { 2210141cc406Sopenharmony_ci case CS2_INTERFACE_UNKNOWN: 2211141cc406Sopenharmony_ci DBG (1, 2212141cc406Sopenharmony_ci "BUG: cs2_issue_cmd(): Unknown or uninitialized interface number.\n"); 2213141cc406Sopenharmony_ci break; 2214141cc406Sopenharmony_ci case CS2_INTERFACE_SCSI: 2215141cc406Sopenharmony_ci sanei_scsi_cmd2 (s->fd, s->send_buf, s->n_cmd, s->send_buf + s->n_cmd, 2216141cc406Sopenharmony_ci s->n_send - s->n_cmd, s->recv_buf, &s->n_recv); 2217141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 2218141cc406Sopenharmony_ci break; 2219141cc406Sopenharmony_ci case CS2_INTERFACE_USB: 2220141cc406Sopenharmony_ci status = sanei_usb_write_bulk (s->fd, s->send_buf, &s->n_cmd); 2221141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2222141cc406Sopenharmony_ci { 2223141cc406Sopenharmony_ci DBG (1, "Error: cs2_issue_cmd(): Could not write command.\n"); 2224141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2225141cc406Sopenharmony_ci } 2226141cc406Sopenharmony_ci switch (cs2_phase_check (s)) 2227141cc406Sopenharmony_ci { 2228141cc406Sopenharmony_ci case CS2_PHASE_OUT: 2229141cc406Sopenharmony_ci if (s->n_send - s->n_cmd < n_data || !n_data) 2230141cc406Sopenharmony_ci { 2231141cc406Sopenharmony_ci DBG (4, "Error: cs2_issue_cmd(): Unexpected data out phase.\n"); 2232141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2233141cc406Sopenharmony_ci } 2234141cc406Sopenharmony_ci status = 2235141cc406Sopenharmony_ci sanei_usb_write_bulk (s->fd, s->send_buf + s->n_cmd, &n_data); 2236141cc406Sopenharmony_ci break; 2237141cc406Sopenharmony_ci case CS2_PHASE_IN: 2238141cc406Sopenharmony_ci if (s->n_recv < n_data || !n_data) 2239141cc406Sopenharmony_ci { 2240141cc406Sopenharmony_ci DBG (4, "Error: cs2_issue_cmd(): Unexpected data in phase.\n"); 2241141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2242141cc406Sopenharmony_ci } 2243141cc406Sopenharmony_ci status = sanei_usb_read_bulk (s->fd, s->recv_buf, &n_data); 2244141cc406Sopenharmony_ci s->n_recv = n_data; 2245141cc406Sopenharmony_ci break; 2246141cc406Sopenharmony_ci case CS2_PHASE_NONE: 2247141cc406Sopenharmony_ci DBG (4, "Error: cs2_issue_cmd(): No command received!\n"); 2248141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2249141cc406Sopenharmony_ci default: 2250141cc406Sopenharmony_ci if (n_data) 2251141cc406Sopenharmony_ci { 2252141cc406Sopenharmony_ci DBG (4, 2253141cc406Sopenharmony_ci "Error: cs2_issue_cmd(): Unexpected non-data phase, but n_data != 0.\n"); 2254141cc406Sopenharmony_ci status_only = 1; 2255141cc406Sopenharmony_ci } 2256141cc406Sopenharmony_ci break; 2257141cc406Sopenharmony_ci } 2258141cc406Sopenharmony_ci n_status = 8; 2259141cc406Sopenharmony_ci status = sanei_usb_read_bulk (s->fd, status_buf, &n_status); 2260141cc406Sopenharmony_ci if (n_status != 8) 2261141cc406Sopenharmony_ci { 2262141cc406Sopenharmony_ci DBG (4, 2263141cc406Sopenharmony_ci "Error: cs2_issue_cmd(): Failed to read 8 status bytes from USB.\n"); 2264141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2265141cc406Sopenharmony_ci } 2266141cc406Sopenharmony_ci s->sense_key = status_buf[1] & 0x0f; 2267141cc406Sopenharmony_ci s->sense_asc = status_buf[2] & 0xff; 2268141cc406Sopenharmony_ci s->sense_ascq = status_buf[3] & 0xff; 2269141cc406Sopenharmony_ci s->sense_info = status_buf[4] & 0xff; 2270141cc406Sopenharmony_ci cs2_parse_sense_data (s); 2271141cc406Sopenharmony_ci break; 2272141cc406Sopenharmony_ci } 2273141cc406Sopenharmony_ci 2274141cc406Sopenharmony_ci if (status_only) 2275141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2276141cc406Sopenharmony_ci else 2277141cc406Sopenharmony_ci return status; 2278141cc406Sopenharmony_ci} 2279141cc406Sopenharmony_ci 2280141cc406Sopenharmony_cistatic cs2_phase_t 2281141cc406Sopenharmony_cics2_phase_check (cs2_t * s) 2282141cc406Sopenharmony_ci{ 2283141cc406Sopenharmony_ci static SANE_Byte phase_send_buf[1] = { 0xd0 }, phase_recv_buf[1]; 2284141cc406Sopenharmony_ci SANE_Status status = 0; 2285141cc406Sopenharmony_ci size_t n = 1; 2286141cc406Sopenharmony_ci 2287141cc406Sopenharmony_ci status = sanei_usb_write_bulk (s->fd, phase_send_buf, &n); 2288141cc406Sopenharmony_ci status |= sanei_usb_read_bulk (s->fd, phase_recv_buf, &n); 2289141cc406Sopenharmony_ci 2290141cc406Sopenharmony_ci DBG (6, "cs2_phase_check(): Phase check returned phase = 0x%02x.\n", 2291141cc406Sopenharmony_ci phase_recv_buf[0]); 2292141cc406Sopenharmony_ci 2293141cc406Sopenharmony_ci if (status) 2294141cc406Sopenharmony_ci return -1; 2295141cc406Sopenharmony_ci else 2296141cc406Sopenharmony_ci return phase_recv_buf[0]; 2297141cc406Sopenharmony_ci} 2298141cc406Sopenharmony_ci 2299141cc406Sopenharmony_cistatic SANE_Status 2300141cc406Sopenharmony_cics2_scanner_ready (cs2_t * s, int flags) 2301141cc406Sopenharmony_ci{ 2302141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 2303141cc406Sopenharmony_ci int i = -1; 2304141cc406Sopenharmony_ci unsigned long count = 0; 2305141cc406Sopenharmony_ci int retry = 3; 2306141cc406Sopenharmony_ci 2307141cc406Sopenharmony_ci do 2308141cc406Sopenharmony_ci { 2309141cc406Sopenharmony_ci if (i >= 0) /* dirty !!! */ 2310141cc406Sopenharmony_ci usleep (500000); 2311141cc406Sopenharmony_ci cs2_init_buffer (s); 2312141cc406Sopenharmony_ci for (i = 0; i < 6; i++) 2313141cc406Sopenharmony_ci cs2_pack_byte (s, 0x00); 2314141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 2315141cc406Sopenharmony_ci if (status) 2316141cc406Sopenharmony_ci if (--retry < 0) 2317141cc406Sopenharmony_ci return status; 2318141cc406Sopenharmony_ci if (++count > 240) 2319141cc406Sopenharmony_ci { /* 120s timeout */ 2320141cc406Sopenharmony_ci DBG (4, "Error: cs2_scanner_ready(): Timeout expired.\n"); 2321141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2322141cc406Sopenharmony_ci break; 2323141cc406Sopenharmony_ci } 2324141cc406Sopenharmony_ci } 2325141cc406Sopenharmony_ci while (s->status & ~flags); /* until all relevant bits are 0 */ 2326141cc406Sopenharmony_ci 2327141cc406Sopenharmony_ci return status; 2328141cc406Sopenharmony_ci} 2329141cc406Sopenharmony_ci 2330141cc406Sopenharmony_cistatic SANE_Status 2331141cc406Sopenharmony_cics2_page_inquiry (cs2_t * s, int page) 2332141cc406Sopenharmony_ci{ 2333141cc406Sopenharmony_ci SANE_Status status; 2334141cc406Sopenharmony_ci 2335141cc406Sopenharmony_ci size_t n; 2336141cc406Sopenharmony_ci 2337141cc406Sopenharmony_ci if (page >= 0) 2338141cc406Sopenharmony_ci { 2339141cc406Sopenharmony_ci 2340141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); 2341141cc406Sopenharmony_ci cs2_init_buffer (s); 2342141cc406Sopenharmony_ci cs2_parse_cmd (s, "12 01"); 2343141cc406Sopenharmony_ci cs2_pack_byte (s, page); 2344141cc406Sopenharmony_ci cs2_parse_cmd (s, "00 04 00"); 2345141cc406Sopenharmony_ci s->n_recv = 4; 2346141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 2347141cc406Sopenharmony_ci if (status) 2348141cc406Sopenharmony_ci { 2349141cc406Sopenharmony_ci DBG (4, 2350141cc406Sopenharmony_ci "Error: cs2_page_inquiry(): Inquiry of page size failed: %s.\n", 2351141cc406Sopenharmony_ci sane_strstatus (status)); 2352141cc406Sopenharmony_ci return status; 2353141cc406Sopenharmony_ci } 2354141cc406Sopenharmony_ci 2355141cc406Sopenharmony_ci n = s->recv_buf[3] + 4; 2356141cc406Sopenharmony_ci 2357141cc406Sopenharmony_ci } 2358141cc406Sopenharmony_ci else 2359141cc406Sopenharmony_ci n = 36; 2360141cc406Sopenharmony_ci 2361141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); 2362141cc406Sopenharmony_ci cs2_init_buffer (s); 2363141cc406Sopenharmony_ci if (page >= 0) 2364141cc406Sopenharmony_ci { 2365141cc406Sopenharmony_ci cs2_parse_cmd (s, "12 01"); 2366141cc406Sopenharmony_ci cs2_pack_byte (s, page); 2367141cc406Sopenharmony_ci cs2_parse_cmd (s, "00"); 2368141cc406Sopenharmony_ci } 2369141cc406Sopenharmony_ci else 2370141cc406Sopenharmony_ci cs2_parse_cmd (s, "12 00 00 00"); 2371141cc406Sopenharmony_ci cs2_pack_byte (s, n); 2372141cc406Sopenharmony_ci cs2_parse_cmd (s, "00"); 2373141cc406Sopenharmony_ci s->n_recv = n; 2374141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 2375141cc406Sopenharmony_ci if (status) 2376141cc406Sopenharmony_ci { 2377141cc406Sopenharmony_ci DBG (4, "Error: cs2_page_inquiry(): Inquiry of page failed: %s.\n", 2378141cc406Sopenharmony_ci sane_strstatus (status)); 2379141cc406Sopenharmony_ci return status; 2380141cc406Sopenharmony_ci } 2381141cc406Sopenharmony_ci 2382141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2383141cc406Sopenharmony_ci} 2384141cc406Sopenharmony_ci 2385141cc406Sopenharmony_cistatic SANE_Status 2386141cc406Sopenharmony_cics2_full_inquiry (cs2_t * s) 2387141cc406Sopenharmony_ci{ 2388141cc406Sopenharmony_ci SANE_Status status; 2389141cc406Sopenharmony_ci int pitch, pitch_max; 2390141cc406Sopenharmony_ci cs2_pixel_t pixel; 2391141cc406Sopenharmony_ci 2392141cc406Sopenharmony_ci status = cs2_page_inquiry (s, 0xc1); 2393141cc406Sopenharmony_ci if (status) 2394141cc406Sopenharmony_ci { 2395141cc406Sopenharmony_ci DBG (4, "Error: cs2_full_inquiry(): Failed to get page: %s\n", 2396141cc406Sopenharmony_ci sane_strstatus (status)); 2397141cc406Sopenharmony_ci return status; 2398141cc406Sopenharmony_ci } 2399141cc406Sopenharmony_ci 2400141cc406Sopenharmony_ci s->maxbits = s->recv_buf[82]; 2401141cc406Sopenharmony_ci if (s->type == CS2_TYPE_LS30) /* must be overridden, LS-30 claims to have 12 bits */ 2402141cc406Sopenharmony_ci s->maxbits = 10; 2403141cc406Sopenharmony_ci 2404141cc406Sopenharmony_ci s->n_lut = 1; 2405141cc406Sopenharmony_ci s->n_lut <<= s->maxbits; 2406141cc406Sopenharmony_ci s->lut_r = 2407141cc406Sopenharmony_ci (cs2_pixel_t *) cs2_xrealloc (s->lut_r, s->n_lut * sizeof (cs2_pixel_t)); 2408141cc406Sopenharmony_ci s->lut_g = 2409141cc406Sopenharmony_ci (cs2_pixel_t *) cs2_xrealloc (s->lut_g, s->n_lut * sizeof (cs2_pixel_t)); 2410141cc406Sopenharmony_ci s->lut_b = 2411141cc406Sopenharmony_ci (cs2_pixel_t *) cs2_xrealloc (s->lut_b, s->n_lut * sizeof (cs2_pixel_t)); 2412141cc406Sopenharmony_ci s->lut_neutral = 2413141cc406Sopenharmony_ci (cs2_pixel_t *) cs2_xrealloc (s->lut_neutral, 2414141cc406Sopenharmony_ci s->n_lut * sizeof (cs2_pixel_t)); 2415141cc406Sopenharmony_ci 2416141cc406Sopenharmony_ci if (!s->lut_r || !s->lut_g || !s->lut_b || !s->lut_neutral) 2417141cc406Sopenharmony_ci { 2418141cc406Sopenharmony_ci cs2_xfree (s->lut_r); 2419141cc406Sopenharmony_ci cs2_xfree (s->lut_g); 2420141cc406Sopenharmony_ci cs2_xfree (s->lut_b); 2421141cc406Sopenharmony_ci cs2_xfree (s->lut_neutral); 2422141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2423141cc406Sopenharmony_ci } 2424141cc406Sopenharmony_ci 2425141cc406Sopenharmony_ci for (pixel = 0; pixel < s->n_lut; pixel++) 2426141cc406Sopenharmony_ci s->lut_r[pixel] = s->lut_g[pixel] = s->lut_b[pixel] = 2427141cc406Sopenharmony_ci s->lut_neutral[pixel] = pixel; 2428141cc406Sopenharmony_ci 2429141cc406Sopenharmony_ci s->resx_optical = 256 * s->recv_buf[18] + s->recv_buf[19]; 2430141cc406Sopenharmony_ci s->resx_max = 256 * s->recv_buf[20] + s->recv_buf[21]; 2431141cc406Sopenharmony_ci s->resx_min = 256 * s->recv_buf[22] + s->recv_buf[23]; 2432141cc406Sopenharmony_ci s->boundaryx = 2433141cc406Sopenharmony_ci 65536 * (256 * s->recv_buf[36] + s->recv_buf[37]) + 2434141cc406Sopenharmony_ci 256 * s->recv_buf[38] + s->recv_buf[39]; 2435141cc406Sopenharmony_ci 2436141cc406Sopenharmony_ci s->resy_optical = 256 * s->recv_buf[40] + s->recv_buf[41]; 2437141cc406Sopenharmony_ci s->resy_max = 256 * s->recv_buf[42] + s->recv_buf[43]; 2438141cc406Sopenharmony_ci s->resy_min = 256 * s->recv_buf[44] + s->recv_buf[45]; 2439141cc406Sopenharmony_ci s->boundaryy = 2440141cc406Sopenharmony_ci 65536 * (256 * s->recv_buf[58] + s->recv_buf[59]) + 2441141cc406Sopenharmony_ci 256 * s->recv_buf[60] + s->recv_buf[61]; 2442141cc406Sopenharmony_ci 2443141cc406Sopenharmony_ci s->focus_min = 256 * s->recv_buf[76] + s->recv_buf[77]; 2444141cc406Sopenharmony_ci s->focus_max = 256 * s->recv_buf[78] + s->recv_buf[79]; 2445141cc406Sopenharmony_ci 2446141cc406Sopenharmony_ci s->n_frames = s->recv_buf[75]; 2447141cc406Sopenharmony_ci 2448141cc406Sopenharmony_ci s->frame_offset = s->resy_max * 1.5 + 1; /* works for LS-30, maybe not for others */ 2449141cc406Sopenharmony_ci 2450141cc406Sopenharmony_ci /* generate resolution list for x */ 2451141cc406Sopenharmony_ci s->resx_n_list = pitch_max = floor (s->resx_max / (double) s->resx_min); 2452141cc406Sopenharmony_ci s->resx_list = 2453141cc406Sopenharmony_ci (unsigned int *) cs2_xrealloc (s->resx_list, 2454141cc406Sopenharmony_ci pitch_max * sizeof (unsigned int)); 2455141cc406Sopenharmony_ci for (pitch = 1; pitch <= pitch_max; pitch++) 2456141cc406Sopenharmony_ci s->resx_list[pitch - 1] = s->resx_max / pitch; 2457141cc406Sopenharmony_ci 2458141cc406Sopenharmony_ci /* generate resolution list for y */ 2459141cc406Sopenharmony_ci s->resy_n_list = pitch_max = floor (s->resy_max / (double) s->resy_min); 2460141cc406Sopenharmony_ci s->resy_list = 2461141cc406Sopenharmony_ci (unsigned int *) cs2_xrealloc (s->resy_list, 2462141cc406Sopenharmony_ci pitch_max * sizeof (unsigned int)); 2463141cc406Sopenharmony_ci for (pitch = 1; pitch <= pitch_max; pitch++) 2464141cc406Sopenharmony_ci s->resy_list[pitch - 1] = s->resy_max / pitch; 2465141cc406Sopenharmony_ci 2466141cc406Sopenharmony_ci s->unit_dpi = s->resx_max; 2467141cc406Sopenharmony_ci s->unit_mm = 25.4 / s->unit_dpi; 2468141cc406Sopenharmony_ci 2469141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2470141cc406Sopenharmony_ci} 2471141cc406Sopenharmony_ci 2472141cc406Sopenharmony_cistatic SANE_Status 2473141cc406Sopenharmony_cics2_execute (cs2_t * s) 2474141cc406Sopenharmony_ci{ 2475141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); 2476141cc406Sopenharmony_ci cs2_init_buffer (s); 2477141cc406Sopenharmony_ci cs2_parse_cmd (s, "c1 00 00 00 00 00"); 2478141cc406Sopenharmony_ci return cs2_issue_cmd (s); 2479141cc406Sopenharmony_ci} 2480141cc406Sopenharmony_ci 2481141cc406Sopenharmony_cistatic SANE_Status 2482141cc406Sopenharmony_cics2_load (cs2_t * s) 2483141cc406Sopenharmony_ci{ 2484141cc406Sopenharmony_ci SANE_Status status; 2485141cc406Sopenharmony_ci 2486141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); 2487141cc406Sopenharmony_ci cs2_init_buffer (s); 2488141cc406Sopenharmony_ci cs2_parse_cmd (s, "e0 00 d1 00 00 00 00 00 0d 00"); 2489141cc406Sopenharmony_ci s->n_send += 13; 2490141cc406Sopenharmony_ci status = cs2_grow_send_buffer (s); 2491141cc406Sopenharmony_ci if (status) 2492141cc406Sopenharmony_ci return status; 2493141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 2494141cc406Sopenharmony_ci if (status) 2495141cc406Sopenharmony_ci return status; 2496141cc406Sopenharmony_ci 2497141cc406Sopenharmony_ci return cs2_execute (s); 2498141cc406Sopenharmony_ci} 2499141cc406Sopenharmony_ci 2500141cc406Sopenharmony_cistatic SANE_Status 2501141cc406Sopenharmony_cics2_eject (cs2_t * s) 2502141cc406Sopenharmony_ci{ 2503141cc406Sopenharmony_ci SANE_Status status; 2504141cc406Sopenharmony_ci 2505141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); 2506141cc406Sopenharmony_ci cs2_init_buffer (s); 2507141cc406Sopenharmony_ci cs2_parse_cmd (s, "e0 00 d0 00 00 00 00 00 0d 00"); 2508141cc406Sopenharmony_ci s->n_send += 13; 2509141cc406Sopenharmony_ci status = cs2_grow_send_buffer (s); 2510141cc406Sopenharmony_ci if (status) 2511141cc406Sopenharmony_ci return status; 2512141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 2513141cc406Sopenharmony_ci if (status) 2514141cc406Sopenharmony_ci return status; 2515141cc406Sopenharmony_ci 2516141cc406Sopenharmony_ci return cs2_execute (s); 2517141cc406Sopenharmony_ci} 2518141cc406Sopenharmony_ci 2519141cc406Sopenharmony_cistatic SANE_Status 2520141cc406Sopenharmony_cics2_reset (cs2_t * s) 2521141cc406Sopenharmony_ci{ 2522141cc406Sopenharmony_ci SANE_Status status; 2523141cc406Sopenharmony_ci 2524141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); 2525141cc406Sopenharmony_ci cs2_init_buffer (s); 2526141cc406Sopenharmony_ci cs2_parse_cmd (s, "e0 00 80 00 00 00 00 00 0d 00"); 2527141cc406Sopenharmony_ci s->n_send += 13; 2528141cc406Sopenharmony_ci status = cs2_grow_send_buffer (s); 2529141cc406Sopenharmony_ci if (status) 2530141cc406Sopenharmony_ci return status; 2531141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 2532141cc406Sopenharmony_ci if (status) 2533141cc406Sopenharmony_ci return status; 2534141cc406Sopenharmony_ci 2535141cc406Sopenharmony_ci return cs2_execute (s); 2536141cc406Sopenharmony_ci} 2537141cc406Sopenharmony_ci 2538141cc406Sopenharmony_cistatic SANE_Status 2539141cc406Sopenharmony_cics2_focus (cs2_t * s) 2540141cc406Sopenharmony_ci{ 2541141cc406Sopenharmony_ci SANE_Status status; 2542141cc406Sopenharmony_ci 2543141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_READY); 2544141cc406Sopenharmony_ci cs2_init_buffer (s); 2545141cc406Sopenharmony_ci cs2_parse_cmd (s, "e0 00 c1 00 00 00 00 00 0d 00 00"); 2546141cc406Sopenharmony_ci cs2_pack_byte (s, (s->focus >> 24) & 0xff); 2547141cc406Sopenharmony_ci cs2_pack_byte (s, (s->focus >> 16) & 0xff); 2548141cc406Sopenharmony_ci cs2_pack_byte (s, (s->focus >> 8) & 0xff); 2549141cc406Sopenharmony_ci cs2_pack_byte (s, s->focus & 0xff); 2550141cc406Sopenharmony_ci cs2_parse_cmd (s, "00 00 00 00 00 00 00 00"); 2551141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 2552141cc406Sopenharmony_ci if (status) 2553141cc406Sopenharmony_ci return status; 2554141cc406Sopenharmony_ci 2555141cc406Sopenharmony_ci return cs2_execute (s); 2556141cc406Sopenharmony_ci} 2557141cc406Sopenharmony_ci 2558141cc406Sopenharmony_cistatic SANE_Status 2559141cc406Sopenharmony_cics2_autofocus (cs2_t * s) 2560141cc406Sopenharmony_ci{ 2561141cc406Sopenharmony_ci SANE_Status status; 2562141cc406Sopenharmony_ci 2563141cc406Sopenharmony_ci cs2_convert_options (s); 2564141cc406Sopenharmony_ci 2565141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_READY); 2566141cc406Sopenharmony_ci cs2_init_buffer (s); 2567141cc406Sopenharmony_ci cs2_parse_cmd (s, "e0 00 a0 00 00 00 00 00 0d 00 00"); 2568141cc406Sopenharmony_ci cs2_pack_byte (s, (s->real_focusx >> 24) & 0xff); 2569141cc406Sopenharmony_ci cs2_pack_byte (s, (s->real_focusx >> 16) & 0xff); 2570141cc406Sopenharmony_ci cs2_pack_byte (s, (s->real_focusx >> 8) & 0xff); 2571141cc406Sopenharmony_ci cs2_pack_byte (s, s->real_focusx & 0xff); 2572141cc406Sopenharmony_ci cs2_pack_byte (s, (s->real_focusy >> 24) & 0xff); 2573141cc406Sopenharmony_ci cs2_pack_byte (s, (s->real_focusy >> 16) & 0xff); 2574141cc406Sopenharmony_ci cs2_pack_byte (s, (s->real_focusy >> 8) & 0xff); 2575141cc406Sopenharmony_ci cs2_pack_byte (s, s->real_focusy & 0xff); 2576141cc406Sopenharmony_ci cs2_parse_cmd (s, "00 00 00 00"); 2577141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 2578141cc406Sopenharmony_ci if (status) 2579141cc406Sopenharmony_ci return status; 2580141cc406Sopenharmony_ci 2581141cc406Sopenharmony_ci status = cs2_execute (s); 2582141cc406Sopenharmony_ci if (status) 2583141cc406Sopenharmony_ci return status; 2584141cc406Sopenharmony_ci 2585141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_READY); 2586141cc406Sopenharmony_ci cs2_init_buffer (s); 2587141cc406Sopenharmony_ci cs2_parse_cmd (s, "e1 00 c1 00 00 00 00 00 0d 00"); 2588141cc406Sopenharmony_ci s->n_recv = 13; 2589141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 2590141cc406Sopenharmony_ci if (status) 2591141cc406Sopenharmony_ci return status; 2592141cc406Sopenharmony_ci 2593141cc406Sopenharmony_ci s->focus = 2594141cc406Sopenharmony_ci 65536 * (256 * s->recv_buf[1] + s->recv_buf[2]) + 256 * s->recv_buf[3] + 2595141cc406Sopenharmony_ci s->recv_buf[4]; 2596141cc406Sopenharmony_ci 2597141cc406Sopenharmony_ci return status; 2598141cc406Sopenharmony_ci} 2599141cc406Sopenharmony_ci 2600141cc406Sopenharmony_cistatic SANE_Status 2601141cc406Sopenharmony_cics2_get_exposure (cs2_t * s) 2602141cc406Sopenharmony_ci{ 2603141cc406Sopenharmony_ci SANE_Status status; 2604141cc406Sopenharmony_ci int i_colour; 2605141cc406Sopenharmony_ci 2606141cc406Sopenharmony_ci for (i_colour = 0; i_colour < 3; i_colour++) 2607141cc406Sopenharmony_ci { /* XXXXXXXXXXXXX CCCCCCCCCCCCC */ 2608141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); 2609141cc406Sopenharmony_ci 2610141cc406Sopenharmony_ci cs2_init_buffer (s); 2611141cc406Sopenharmony_ci cs2_parse_cmd (s, "25 01 00 00 00"); 2612141cc406Sopenharmony_ci cs2_pack_byte (s, cs2_colour_list[i_colour]); 2613141cc406Sopenharmony_ci cs2_parse_cmd (s, "00 00 3a 00"); 2614141cc406Sopenharmony_ci s->n_recv = 58; 2615141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 2616141cc406Sopenharmony_ci if (status) 2617141cc406Sopenharmony_ci return status; 2618141cc406Sopenharmony_ci 2619141cc406Sopenharmony_ci s->real_exposure[cs2_colour_list[i_colour]] = 2620141cc406Sopenharmony_ci 65536 * (256 * s->recv_buf[54] + s->recv_buf[55]) + 2621141cc406Sopenharmony_ci 256 * s->recv_buf[56] + s->recv_buf[57]; 2622141cc406Sopenharmony_ci 2623141cc406Sopenharmony_ci DBG (6, "cs2_get_exposure(): exposure for colour %i: %li * 10ns\n", cs2_colour_list[i_colour], s->real_exposure[cs2_colour_list[i_colour]]); 2624141cc406Sopenharmony_ci } 2625141cc406Sopenharmony_ci 2626141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2627141cc406Sopenharmony_ci} 2628141cc406Sopenharmony_ci 2629141cc406Sopenharmony_cistatic SANE_Status 2630141cc406Sopenharmony_cics2_convert_options (cs2_t * s) 2631141cc406Sopenharmony_ci{ 2632141cc406Sopenharmony_ci int i_colour; 2633141cc406Sopenharmony_ci unsigned long xmin, xmax, ymin, ymax; 2634141cc406Sopenharmony_ci SANE_Byte *infrared_buf_new; 2635141cc406Sopenharmony_ci 2636141cc406Sopenharmony_ci s->real_depth = (s->preview ? 8 : s->depth); 2637141cc406Sopenharmony_ci s->bytes_per_pixel = (s->real_depth > 8 ? 2 : 1); 2638141cc406Sopenharmony_ci s->shift_bits = 8 * s->bytes_per_pixel - s->real_depth; 2639141cc406Sopenharmony_ci 2640141cc406Sopenharmony_ci if (s->preview) 2641141cc406Sopenharmony_ci { 2642141cc406Sopenharmony_ci s->real_resx = s->res_preview; 2643141cc406Sopenharmony_ci s->real_resy = s->res_preview; 2644141cc406Sopenharmony_ci } 2645141cc406Sopenharmony_ci else if (s->res_independent) 2646141cc406Sopenharmony_ci { 2647141cc406Sopenharmony_ci s->real_resx = s->resx; 2648141cc406Sopenharmony_ci s->real_resy = s->resy; 2649141cc406Sopenharmony_ci } 2650141cc406Sopenharmony_ci else 2651141cc406Sopenharmony_ci { 2652141cc406Sopenharmony_ci s->real_resx = s->res; 2653141cc406Sopenharmony_ci s->real_resy = s->res; 2654141cc406Sopenharmony_ci } 2655141cc406Sopenharmony_ci s->real_pitchx = s->resx_max / s->real_resx; 2656141cc406Sopenharmony_ci s->real_pitchy = s->resy_max / s->real_resy; 2657141cc406Sopenharmony_ci 2658141cc406Sopenharmony_ci s->real_resx = s->resx_max / s->real_pitchx; 2659141cc406Sopenharmony_ci s->real_resy = s->resy_max / s->real_pitchy; 2660141cc406Sopenharmony_ci 2661141cc406Sopenharmony_ci /* The prefix "real_" refers to data in device units (1/maxdpi), "logical_" refers to resolution-dependent data. */ 2662141cc406Sopenharmony_ci 2663141cc406Sopenharmony_ci if (s->xmin < s->xmax) 2664141cc406Sopenharmony_ci { 2665141cc406Sopenharmony_ci xmin = s->xmin; 2666141cc406Sopenharmony_ci xmax = s->xmax; 2667141cc406Sopenharmony_ci } 2668141cc406Sopenharmony_ci else 2669141cc406Sopenharmony_ci { 2670141cc406Sopenharmony_ci xmin = s->xmax; 2671141cc406Sopenharmony_ci xmax = s->xmin; 2672141cc406Sopenharmony_ci } 2673141cc406Sopenharmony_ci 2674141cc406Sopenharmony_ci if (s->ymin < s->ymax) 2675141cc406Sopenharmony_ci { 2676141cc406Sopenharmony_ci ymin = s->ymin; 2677141cc406Sopenharmony_ci ymax = s->ymax; 2678141cc406Sopenharmony_ci } 2679141cc406Sopenharmony_ci else 2680141cc406Sopenharmony_ci { 2681141cc406Sopenharmony_ci ymin = s->ymax; 2682141cc406Sopenharmony_ci ymax = s->ymin; 2683141cc406Sopenharmony_ci } 2684141cc406Sopenharmony_ci 2685141cc406Sopenharmony_ci s->real_xoffset = xmin; 2686141cc406Sopenharmony_ci s->real_yoffset = 2687141cc406Sopenharmony_ci ymin + (s->i_frame - 1) * s->frame_offset + s->subframe / s->unit_mm; 2688141cc406Sopenharmony_ci s->logical_width = (xmax - xmin + 1) / s->real_pitchx; /* XXXXXXXXX use mm units */ 2689141cc406Sopenharmony_ci s->logical_height = (ymax - ymin + 1) / s->real_pitchy; 2690141cc406Sopenharmony_ci s->real_width = s->logical_width * s->real_pitchx; 2691141cc406Sopenharmony_ci s->real_height = s->logical_height * s->real_pitchy; 2692141cc406Sopenharmony_ci 2693141cc406Sopenharmony_ci s->odd_padding = 0; 2694141cc406Sopenharmony_ci if ((s->bytes_per_pixel == 1) && (s->logical_width & 0x01) 2695141cc406Sopenharmony_ci && (s->type != CS2_TYPE_LS30) && (s->type != CS2_TYPE_LS2000)) 2696141cc406Sopenharmony_ci s->odd_padding = 1; 2697141cc406Sopenharmony_ci 2698141cc406Sopenharmony_ci if (s->focus_on_centre) 2699141cc406Sopenharmony_ci { 2700141cc406Sopenharmony_ci s->real_focusx = s->real_xoffset + s->real_width / 2; 2701141cc406Sopenharmony_ci s->real_focusy = s->real_yoffset + s->real_height / 2; 2702141cc406Sopenharmony_ci } 2703141cc406Sopenharmony_ci else 2704141cc406Sopenharmony_ci { 2705141cc406Sopenharmony_ci s->real_focusx = s->focusx; 2706141cc406Sopenharmony_ci s->real_focusy = 2707141cc406Sopenharmony_ci s->focusy + (s->i_frame - 1) * s->frame_offset + 2708141cc406Sopenharmony_ci s->subframe / s->unit_mm; 2709141cc406Sopenharmony_ci } 2710141cc406Sopenharmony_ci 2711141cc406Sopenharmony_ci s->real_exposure[1] = s->exposure * s->exposure_r * 100.; 2712141cc406Sopenharmony_ci s->real_exposure[2] = s->exposure * s->exposure_g * 100.; 2713141cc406Sopenharmony_ci s->real_exposure[3] = s->exposure * s->exposure_b * 100.; 2714141cc406Sopenharmony_ci 2715141cc406Sopenharmony_ci for (i_colour = 0; i_colour < 3; i_colour++) 2716141cc406Sopenharmony_ci if (s->real_exposure[cs2_colour_list[i_colour]] < 1) 2717141cc406Sopenharmony_ci s->real_exposure[cs2_colour_list[i_colour]] = 1; 2718141cc406Sopenharmony_ci 2719141cc406Sopenharmony_ci s->n_colour_out = s->n_colour_in = 3; /* XXXXXXXXXXXXXX CCCCCCCCCCCCCC */ 2720141cc406Sopenharmony_ci 2721141cc406Sopenharmony_ci s->xfer_bytes_total = 2722141cc406Sopenharmony_ci s->bytes_per_pixel * s->n_colour_out * s->logical_width * 2723141cc406Sopenharmony_ci s->logical_height; 2724141cc406Sopenharmony_ci 2725141cc406Sopenharmony_ci if (s->preview) 2726141cc406Sopenharmony_ci s->infrared_stage = s->infrared_next = CS2_INFRARED_OFF; 2727141cc406Sopenharmony_ci else 2728141cc406Sopenharmony_ci { 2729141cc406Sopenharmony_ci if ((s->infrared) && (s->infrared_stage == CS2_INFRARED_OFF)) 2730141cc406Sopenharmony_ci s->infrared_next = CS2_INFRARED_IN; 2731141cc406Sopenharmony_ci 2732141cc406Sopenharmony_ci s->infrared_stage = s->infrared_next; 2733141cc406Sopenharmony_ci 2734141cc406Sopenharmony_ci if (s->infrared) 2735141cc406Sopenharmony_ci { 2736141cc406Sopenharmony_ci s->n_colour_in ++; 2737141cc406Sopenharmony_ci s->n_infrared_buf = 2738141cc406Sopenharmony_ci s->bytes_per_pixel * s->logical_width * s->logical_height; 2739141cc406Sopenharmony_ci infrared_buf_new = 2740141cc406Sopenharmony_ci (SANE_Byte *) cs2_xrealloc (s->infrared_buf, s->n_infrared_buf); 2741141cc406Sopenharmony_ci if (infrared_buf_new) 2742141cc406Sopenharmony_ci s->infrared_buf = infrared_buf_new; 2743141cc406Sopenharmony_ci else 2744141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2745141cc406Sopenharmony_ci } 2746141cc406Sopenharmony_ci } 2747141cc406Sopenharmony_ci 2748141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2749141cc406Sopenharmony_ci} 2750141cc406Sopenharmony_ci 2751141cc406Sopenharmony_cistatic SANE_Status 2752141cc406Sopenharmony_cics2_set_boundary (cs2_t *s) 2753141cc406Sopenharmony_ci{ 2754141cc406Sopenharmony_ci SANE_Status status; 2755141cc406Sopenharmony_ci int i_boundary; 2756141cc406Sopenharmony_ci unsigned long lvalue; 2757141cc406Sopenharmony_ci 2758141cc406Sopenharmony_ci/* Ariel - Check this function */ 2759141cc406Sopenharmony_ci 2760141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_READY); 2761141cc406Sopenharmony_ci cs2_init_buffer (s); 2762141cc406Sopenharmony_ci cs2_parse_cmd (s, "2a 00 88 00 00 03"); 2763141cc406Sopenharmony_ci cs2_pack_byte (s, ((4 + s->n_frames * 16) >> 16) & 0xff); 2764141cc406Sopenharmony_ci cs2_pack_byte (s, ((4 + s->n_frames * 16) >> 8) & 0xff); 2765141cc406Sopenharmony_ci cs2_pack_byte (s, (4 + s->n_frames * 16) & 0xff); 2766141cc406Sopenharmony_ci cs2_parse_cmd (s, "00"); 2767141cc406Sopenharmony_ci 2768141cc406Sopenharmony_ci cs2_pack_byte (s, ((4 + s->n_frames * 16) >> 8) & 0xff); 2769141cc406Sopenharmony_ci cs2_pack_byte (s, (4 + s->n_frames * 16) & 0xff); 2770141cc406Sopenharmony_ci cs2_pack_byte (s, s->n_frames); 2771141cc406Sopenharmony_ci cs2_pack_byte (s, s->n_frames); 2772141cc406Sopenharmony_ci for (i_boundary = 0; i_boundary < s->n_frames; i_boundary++) 2773141cc406Sopenharmony_ci { 2774141cc406Sopenharmony_ci lvalue = s->frame_offset * i_boundary + s->subframe / s->unit_mm; 2775141cc406Sopenharmony_ci cs2_pack_byte (s, (lvalue >> 24) & 0xff); 2776141cc406Sopenharmony_ci cs2_pack_byte (s, (lvalue >> 16) & 0xff); 2777141cc406Sopenharmony_ci cs2_pack_byte (s, (lvalue >> 8) & 0xff); 2778141cc406Sopenharmony_ci cs2_pack_byte (s, lvalue & 0xff); 2779141cc406Sopenharmony_ci 2780141cc406Sopenharmony_ci lvalue = 0; 2781141cc406Sopenharmony_ci cs2_pack_byte (s, (lvalue >> 24) & 0xff); 2782141cc406Sopenharmony_ci cs2_pack_byte (s, (lvalue >> 16) & 0xff); 2783141cc406Sopenharmony_ci cs2_pack_byte (s, (lvalue >> 8) & 0xff); 2784141cc406Sopenharmony_ci cs2_pack_byte (s, lvalue & 0xff); 2785141cc406Sopenharmony_ci 2786141cc406Sopenharmony_ci lvalue = s->frame_offset * i_boundary + s->subframe / s->unit_mm + s->frame_offset - 1; 2787141cc406Sopenharmony_ci cs2_pack_byte (s, (lvalue >> 24) & 0xff); 2788141cc406Sopenharmony_ci cs2_pack_byte (s, (lvalue >> 16) & 0xff); 2789141cc406Sopenharmony_ci cs2_pack_byte (s, (lvalue >> 8) & 0xff); 2790141cc406Sopenharmony_ci cs2_pack_byte (s, lvalue & 0xff); 2791141cc406Sopenharmony_ci 2792141cc406Sopenharmony_ci lvalue = s->boundaryx - 1; 2793141cc406Sopenharmony_ci cs2_pack_byte (s, (lvalue >> 24) & 0xff); 2794141cc406Sopenharmony_ci cs2_pack_byte (s, (lvalue >> 16) & 0xff); 2795141cc406Sopenharmony_ci cs2_pack_byte (s, (lvalue >> 8) & 0xff); 2796141cc406Sopenharmony_ci cs2_pack_byte (s, lvalue & 0xff); 2797141cc406Sopenharmony_ci } 2798141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 2799141cc406Sopenharmony_ci if (status) 2800141cc406Sopenharmony_ci return status; 2801141cc406Sopenharmony_ci 2802141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2803141cc406Sopenharmony_ci} 2804141cc406Sopenharmony_ci 2805141cc406Sopenharmony_cistatic SANE_Status 2806141cc406Sopenharmony_cics2_scan (cs2_t * s, cs2_scan_t type) 2807141cc406Sopenharmony_ci{ 2808141cc406Sopenharmony_ci SANE_Status status; 2809141cc406Sopenharmony_ci int i_colour; 2810141cc406Sopenharmony_ci cs2_pixel_t pixel; 2811141cc406Sopenharmony_ci cs2_pixel_t *lut; 2812141cc406Sopenharmony_ci 2813141cc406Sopenharmony_ci /* wait for device to be ready with document, and set device unit */ 2814141cc406Sopenharmony_ci 2815141cc406Sopenharmony_ci status = cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); 2816141cc406Sopenharmony_ci if (status) 2817141cc406Sopenharmony_ci return status; 2818141cc406Sopenharmony_ci if (s->status & CS2_STATUS_NO_DOCS) 2819141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 2820141cc406Sopenharmony_ci 2821141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_READY); 2822141cc406Sopenharmony_ci cs2_init_buffer (s); 2823141cc406Sopenharmony_ci /* Ariel - the '0b' byte in the 'else' part seems to be wrong, should be 0 */ 2824141cc406Sopenharmony_ci if ((s->type == CS2_TYPE_LS50) || (s->type == CS2_TYPE_LS5000)) 2825141cc406Sopenharmony_ci cs2_parse_cmd (s, "15 10 00 00 14 00 00 00 00 08 00 00 00 00 00 00 00 01 03 06 00 00"); 2826141cc406Sopenharmony_ci else 2827141cc406Sopenharmony_ci cs2_parse_cmd (s, "15 10 00 00 0c 00 0b 00 00 00 03 06 00 00"); 2828141cc406Sopenharmony_ci cs2_pack_byte (s, (s->unit_dpi >> 8) & 0xff); 2829141cc406Sopenharmony_ci cs2_pack_byte (s, s->unit_dpi & 0xff); 2830141cc406Sopenharmony_ci cs2_parse_cmd (s, "00 00"); 2831141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 2832141cc406Sopenharmony_ci if (status) 2833141cc406Sopenharmony_ci return status; 2834141cc406Sopenharmony_ci 2835141cc406Sopenharmony_ci status = cs2_convert_options (s); 2836141cc406Sopenharmony_ci if (status) 2837141cc406Sopenharmony_ci return status; 2838141cc406Sopenharmony_ci 2839141cc406Sopenharmony_ci /* Ariel - Is this the best place to initialize it? */ 2840141cc406Sopenharmony_ci s->block_padding = 0; 2841141cc406Sopenharmony_ci 2842141cc406Sopenharmony_ci status = cs2_set_boundary (s); 2843141cc406Sopenharmony_ci if (status) 2844141cc406Sopenharmony_ci return status; 2845141cc406Sopenharmony_ci 2846141cc406Sopenharmony_ci switch (type) 2847141cc406Sopenharmony_ci { 2848141cc406Sopenharmony_ci case CS2_SCAN_NORMAL: 2849141cc406Sopenharmony_ci 2850141cc406Sopenharmony_ci for (i_colour = 0; i_colour < s->n_colour_in; i_colour++) 2851141cc406Sopenharmony_ci { 2852141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_READY); 2853141cc406Sopenharmony_ci 2854141cc406Sopenharmony_ci switch (i_colour) 2855141cc406Sopenharmony_ci { 2856141cc406Sopenharmony_ci case 0: 2857141cc406Sopenharmony_ci lut = s->lut_r; 2858141cc406Sopenharmony_ci break; 2859141cc406Sopenharmony_ci case 1: 2860141cc406Sopenharmony_ci lut = s->lut_g; 2861141cc406Sopenharmony_ci break; 2862141cc406Sopenharmony_ci case 2: 2863141cc406Sopenharmony_ci lut = s->lut_b; 2864141cc406Sopenharmony_ci break; 2865141cc406Sopenharmony_ci case 3: 2866141cc406Sopenharmony_ci lut = s->lut_neutral; 2867141cc406Sopenharmony_ci break; 2868141cc406Sopenharmony_ci default: 2869141cc406Sopenharmony_ci DBG (1, 2870141cc406Sopenharmony_ci "BUG: cs2_scan(): Unknown colour number for LUT download.\n"); 2871141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2872141cc406Sopenharmony_ci break; 2873141cc406Sopenharmony_ci } 2874141cc406Sopenharmony_ci 2875141cc406Sopenharmony_ci cs2_init_buffer (s); 2876141cc406Sopenharmony_ci cs2_parse_cmd (s, "2a 00 03 00"); 2877141cc406Sopenharmony_ci cs2_pack_byte (s, cs2_colour_list[i_colour]); 2878141cc406Sopenharmony_ci cs2_pack_byte (s, 2 - 1); /* XXXXXXXXXX number of bytes per data point - 1 */ 2879141cc406Sopenharmony_ci cs2_pack_byte (s, ((2 * s->n_lut) >> 16) & 0xff); /* XXXXXXXXXX 2 bytes per point */ 2880141cc406Sopenharmony_ci cs2_pack_byte (s, ((2 * s->n_lut) >> 8) & 0xff); /* XXXXXXXXXX 2 bytes per point */ 2881141cc406Sopenharmony_ci cs2_pack_byte (s, (2 * s->n_lut) & 0xff); /* XXXXXXXXXX 2 bytes per point */ 2882141cc406Sopenharmony_ci cs2_pack_byte (s, 0x00); 2883141cc406Sopenharmony_ci 2884141cc406Sopenharmony_ci for (pixel = 0; pixel < s->n_lut; pixel++) 2885141cc406Sopenharmony_ci { /* XXXXXXXXXXXXXXX 2 bytes per point */ 2886141cc406Sopenharmony_ci cs2_pack_byte (s, (lut[pixel] >> 8) & 0xff); 2887141cc406Sopenharmony_ci cs2_pack_byte (s, lut[pixel] & 0xff); 2888141cc406Sopenharmony_ci } 2889141cc406Sopenharmony_ci 2890141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 2891141cc406Sopenharmony_ci if (status) 2892141cc406Sopenharmony_ci return status; 2893141cc406Sopenharmony_ci } 2894141cc406Sopenharmony_ci 2895141cc406Sopenharmony_ci break; 2896141cc406Sopenharmony_ci 2897141cc406Sopenharmony_ci default: 2898141cc406Sopenharmony_ci break; 2899141cc406Sopenharmony_ci } 2900141cc406Sopenharmony_ci 2901141cc406Sopenharmony_ci for (i_colour = 0; i_colour < s->n_colour_in; i_colour++) 2902141cc406Sopenharmony_ci { 2903141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_READY); 2904141cc406Sopenharmony_ci 2905141cc406Sopenharmony_ci cs2_init_buffer (s); 2906141cc406Sopenharmony_ci if ((s->type == CS2_TYPE_LS40) || (s->type == CS2_TYPE_LS4000)) 2907141cc406Sopenharmony_ci cs2_parse_cmd (s, "24 00 00 00 00 00 00 00 3a 80"); 2908141cc406Sopenharmony_ci else 2909141cc406Sopenharmony_ci cs2_parse_cmd (s, "24 00 00 00 00 00 00 00 3a 00"); 2910141cc406Sopenharmony_ci cs2_parse_cmd (s, "00 00 00 00 00 00 00 32"); 2911141cc406Sopenharmony_ci 2912141cc406Sopenharmony_ci cs2_pack_byte (s, cs2_colour_list[i_colour]); 2913141cc406Sopenharmony_ci 2914141cc406Sopenharmony_ci cs2_pack_byte (s, 0x00); 2915141cc406Sopenharmony_ci 2916141cc406Sopenharmony_ci cs2_pack_byte (s, s->real_resx >> 8); 2917141cc406Sopenharmony_ci cs2_pack_byte (s, s->real_resx & 0xff); 2918141cc406Sopenharmony_ci cs2_pack_byte (s, s->real_resy >> 8); 2919141cc406Sopenharmony_ci cs2_pack_byte (s, s->real_resy & 0xff); 2920141cc406Sopenharmony_ci 2921141cc406Sopenharmony_ci cs2_pack_byte (s, (s->real_xoffset >> 24) & 0xff); 2922141cc406Sopenharmony_ci cs2_pack_byte (s, (s->real_xoffset >> 16) & 0xff); 2923141cc406Sopenharmony_ci cs2_pack_byte (s, (s->real_xoffset >> 8) & 0xff); 2924141cc406Sopenharmony_ci cs2_pack_byte (s, s->real_xoffset & 0xff); 2925141cc406Sopenharmony_ci 2926141cc406Sopenharmony_ci cs2_pack_byte (s, (s->real_yoffset >> 24) & 0xff); 2927141cc406Sopenharmony_ci cs2_pack_byte (s, (s->real_yoffset >> 16) & 0xff); 2928141cc406Sopenharmony_ci cs2_pack_byte (s, (s->real_yoffset >> 8) & 0xff); 2929141cc406Sopenharmony_ci cs2_pack_byte (s, s->real_yoffset & 0xff); 2930141cc406Sopenharmony_ci 2931141cc406Sopenharmony_ci cs2_pack_byte (s, (s->real_width >> 24) & 0xff); 2932141cc406Sopenharmony_ci cs2_pack_byte (s, (s->real_width >> 16) & 0xff); 2933141cc406Sopenharmony_ci cs2_pack_byte (s, (s->real_width >> 8) & 0xff); 2934141cc406Sopenharmony_ci cs2_pack_byte (s, s->real_width & 0xff); 2935141cc406Sopenharmony_ci 2936141cc406Sopenharmony_ci cs2_pack_byte (s, (s->real_height >> 24) & 0xff); 2937141cc406Sopenharmony_ci cs2_pack_byte (s, (s->real_height >> 16) & 0xff); 2938141cc406Sopenharmony_ci cs2_pack_byte (s, (s->real_height >> 8) & 0xff); 2939141cc406Sopenharmony_ci cs2_pack_byte (s, s->real_height & 0xff); 2940141cc406Sopenharmony_ci 2941141cc406Sopenharmony_ci cs2_pack_byte (s, 0x00); /* brightness, etc. */ 2942141cc406Sopenharmony_ci cs2_pack_byte (s, 0x00); 2943141cc406Sopenharmony_ci cs2_pack_byte (s, 0x00); 2944141cc406Sopenharmony_ci cs2_pack_byte (s, 0x05); /* image composition CCCCCCC */ 2945141cc406Sopenharmony_ci cs2_pack_byte (s, s->real_depth); /* pixel composition */ 2946141cc406Sopenharmony_ci cs2_parse_cmd (s, "00 00 00 00 00 00 00 00 00 00 00 00 00"); 2947141cc406Sopenharmony_ci cs2_pack_byte (s, ((s->samples_per_scan - 1) << 4) + 0x00); /* multiread, ordering */ 2948141cc406Sopenharmony_ci /* No need to use an undocumented bit in LS50 */ 2949141cc406Sopenharmony_ci if ((s->type == CS2_TYPE_LS50) || (s->type == CS2_TYPE_LS5000)) 2950141cc406Sopenharmony_ci cs2_pack_byte (s, 0x00 + (s->negative ? 0 : 1)); /* averaging, pos/neg */ 2951141cc406Sopenharmony_ci else 2952141cc406Sopenharmony_ci cs2_pack_byte (s, 0x80 + (s->negative ? 0 : 1)); /* averaging, pos/neg */ 2953141cc406Sopenharmony_ci 2954141cc406Sopenharmony_ci switch (type) 2955141cc406Sopenharmony_ci { /* scanning kind */ 2956141cc406Sopenharmony_ci case CS2_SCAN_NORMAL: 2957141cc406Sopenharmony_ci cs2_pack_byte (s, 0x01); 2958141cc406Sopenharmony_ci break; 2959141cc406Sopenharmony_ci case CS2_SCAN_AE: 2960141cc406Sopenharmony_ci cs2_pack_byte (s, 0x20); 2961141cc406Sopenharmony_ci break; 2962141cc406Sopenharmony_ci case CS2_SCAN_AE_WB: 2963141cc406Sopenharmony_ci cs2_pack_byte (s, 0x40); 2964141cc406Sopenharmony_ci break; 2965141cc406Sopenharmony_ci default: 2966141cc406Sopenharmony_ci DBG (1, "BUG: cs2_scan(): Unknown scanning type.\n"); 2967141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2968141cc406Sopenharmony_ci } 2969141cc406Sopenharmony_ci if (s->samples_per_scan == 1) 2970141cc406Sopenharmony_ci cs2_pack_byte (s, 0x02); /* scanning mode single */ 2971141cc406Sopenharmony_ci else 2972141cc406Sopenharmony_ci cs2_pack_byte (s, 0x10); /* scanning mode multi */ 2973141cc406Sopenharmony_ci cs2_pack_byte (s, 0x02); /* colour interleaving */ 2974141cc406Sopenharmony_ci cs2_pack_byte (s, 0xff); /* (ae) */ 2975141cc406Sopenharmony_ci if (i_colour == 3) /* infrared */ 2976141cc406Sopenharmony_ci cs2_parse_cmd (s, "00 00 00 00"); /* automatic */ 2977141cc406Sopenharmony_ci else 2978141cc406Sopenharmony_ci { 2979141cc406Sopenharmony_ci cs2_pack_byte (s, 2980141cc406Sopenharmony_ci (s-> 2981141cc406Sopenharmony_ci real_exposure[cs2_colour_list[i_colour]] >> 24) & 2982141cc406Sopenharmony_ci 0xff); 2983141cc406Sopenharmony_ci cs2_pack_byte (s, 2984141cc406Sopenharmony_ci (s-> 2985141cc406Sopenharmony_ci real_exposure[cs2_colour_list[i_colour]] >> 16) & 2986141cc406Sopenharmony_ci 0xff); 2987141cc406Sopenharmony_ci cs2_pack_byte (s, 2988141cc406Sopenharmony_ci (s-> 2989141cc406Sopenharmony_ci real_exposure[cs2_colour_list[i_colour]] >> 8) & 2990141cc406Sopenharmony_ci 0xff); 2991141cc406Sopenharmony_ci cs2_pack_byte (s, 2992141cc406Sopenharmony_ci s->real_exposure[cs2_colour_list[i_colour]] & 0xff); 2993141cc406Sopenharmony_ci } 2994141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 2995141cc406Sopenharmony_ci if (status) 2996141cc406Sopenharmony_ci return status; 2997141cc406Sopenharmony_ci } 2998141cc406Sopenharmony_ci 2999141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_READY); 3000141cc406Sopenharmony_ci cs2_focus (s); 3001141cc406Sopenharmony_ci 3002141cc406Sopenharmony_ci cs2_scanner_ready (s, CS2_STATUS_READY); 3003141cc406Sopenharmony_ci cs2_init_buffer (s); 3004141cc406Sopenharmony_ci switch (s->n_colour_in) 3005141cc406Sopenharmony_ci { 3006141cc406Sopenharmony_ci case 3: 3007141cc406Sopenharmony_ci cs2_parse_cmd (s, "1b 00 00 00 03 00 01 02 03"); 3008141cc406Sopenharmony_ci break; 3009141cc406Sopenharmony_ci case 4: 3010141cc406Sopenharmony_ci cs2_parse_cmd (s, "1b 00 00 00 04 00 01 02 03 09"); 3011141cc406Sopenharmony_ci break; 3012141cc406Sopenharmony_ci default: 3013141cc406Sopenharmony_ci DBG (1, "BUG: cs2_scan(): Unknown number of input colours.\n"); 3014141cc406Sopenharmony_ci break; 3015141cc406Sopenharmony_ci } 3016141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 3017141cc406Sopenharmony_ci if (status) 3018141cc406Sopenharmony_ci return status; 3019141cc406Sopenharmony_ci if (s->status == CS2_STATUS_REISSUE) 3020141cc406Sopenharmony_ci { 3021141cc406Sopenharmony_ci /* Make sure we don't affect the behaviour for other scanners */ 3022141cc406Sopenharmony_ci if ((s->type == CS2_TYPE_LS50) || (s->type == CS2_TYPE_LS5000)) 3023141cc406Sopenharmony_ci { 3024141cc406Sopenharmony_ci cs2_init_buffer (s); 3025141cc406Sopenharmony_ci cs2_parse_cmd (s, "28 00 87 00 00 00 00 00 06 00"); 3026141cc406Sopenharmony_ci s->n_recv = 6; 3027141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 3028141cc406Sopenharmony_ci if (status) 3029141cc406Sopenharmony_ci return status; 3030141cc406Sopenharmony_ci cs2_init_buffer (s); 3031141cc406Sopenharmony_ci cs2_parse_cmd (s, "28 00 87 00 00 00 00 00"); 3032141cc406Sopenharmony_ci cs2_pack_byte (s, s->recv_buf[5] + 6); 3033141cc406Sopenharmony_ci cs2_parse_cmd (s, "00"); 3034141cc406Sopenharmony_ci s->n_recv = s->recv_buf[5] + 6; 3035141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 3036141cc406Sopenharmony_ci if (status) 3037141cc406Sopenharmony_ci return status; 3038141cc406Sopenharmony_ci if ((s->recv_buf[11] != 0x08) || (s->recv_buf[12] != 0x00)) 3039141cc406Sopenharmony_ci DBG (1, "BUG: cs2_scan(): Unexpected block_padding position.\n"); 3040141cc406Sopenharmony_ci s->block_padding = 256 * s->recv_buf[19] + s->recv_buf[20]; 3041141cc406Sopenharmony_ci cs2_init_buffer (s); 3042141cc406Sopenharmony_ci switch (s->n_colour_in) 3043141cc406Sopenharmony_ci { 3044141cc406Sopenharmony_ci case 3: 3045141cc406Sopenharmony_ci cs2_parse_cmd (s, "1b 00 00 00 03 00 01 02 03"); 3046141cc406Sopenharmony_ci break; 3047141cc406Sopenharmony_ci case 4: 3048141cc406Sopenharmony_ci cs2_parse_cmd (s, "1b 00 00 00 04 00 01 02 03 09"); 3049141cc406Sopenharmony_ci break; 3050141cc406Sopenharmony_ci } 3051141cc406Sopenharmony_ci } 3052141cc406Sopenharmony_ci status = cs2_issue_cmd (s); 3053141cc406Sopenharmony_ci if (status) 3054141cc406Sopenharmony_ci return status; 3055141cc406Sopenharmony_ci } 3056141cc406Sopenharmony_ci 3057141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3058141cc406Sopenharmony_ci} 3059141cc406Sopenharmony_ci 3060141cc406Sopenharmony_cistatic void * 3061141cc406Sopenharmony_cics2_xmalloc (size_t size) 3062141cc406Sopenharmony_ci{ 3063141cc406Sopenharmony_ci register void *value = malloc (size); 3064141cc406Sopenharmony_ci 3065141cc406Sopenharmony_ci if (!value) 3066141cc406Sopenharmony_ci DBG (0, "Error: cs2_xmalloc(): Failed to malloc() %lu bytes.\n", 3067141cc406Sopenharmony_ci (unsigned long) size); 3068141cc406Sopenharmony_ci 3069141cc406Sopenharmony_ci return value; 3070141cc406Sopenharmony_ci} 3071141cc406Sopenharmony_ci 3072141cc406Sopenharmony_cistatic void * 3073141cc406Sopenharmony_cics2_xrealloc (void *p, size_t size) 3074141cc406Sopenharmony_ci{ 3075141cc406Sopenharmony_ci register void *value; 3076141cc406Sopenharmony_ci 3077141cc406Sopenharmony_ci if (!size) 3078141cc406Sopenharmony_ci return p; 3079141cc406Sopenharmony_ci 3080141cc406Sopenharmony_ci value = realloc (p, size); 3081141cc406Sopenharmony_ci 3082141cc406Sopenharmony_ci if (!value) 3083141cc406Sopenharmony_ci DBG (0, "Error: cs2_xrealloc(): Failed to realloc() %lu bytes.\n", 3084141cc406Sopenharmony_ci (unsigned long) size); 3085141cc406Sopenharmony_ci 3086141cc406Sopenharmony_ci return value; 3087141cc406Sopenharmony_ci} 3088141cc406Sopenharmony_ci 3089141cc406Sopenharmony_cistatic void 3090141cc406Sopenharmony_cics2_xfree (const void *p) 3091141cc406Sopenharmony_ci{ 3092141cc406Sopenharmony_ci if (p) 3093141cc406Sopenharmony_ci free ((void *) p); 3094141cc406Sopenharmony_ci} 3095