1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci Copyright (C) 1997 David Mosberger-Tang 3141cc406Sopenharmony_ci This file is part of the SANE package. 4141cc406Sopenharmony_ci 5141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 6141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 7141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 8141cc406Sopenharmony_ci License, or (at your option) any later version. 9141cc406Sopenharmony_ci 10141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 11141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 12141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13141cc406Sopenharmony_ci General Public License for more details. 14141cc406Sopenharmony_ci 15141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 16141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 19141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 20141cc406Sopenharmony_ci 21141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 22141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 23141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 24141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 25141cc406Sopenharmony_ci account of linking the SANE library code into it. 26141cc406Sopenharmony_ci 27141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 28141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 29141cc406Sopenharmony_ci License. 30141cc406Sopenharmony_ci 31141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 32141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 33141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 34141cc406Sopenharmony_ci 35141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 36141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 37141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 38141cc406Sopenharmony_ci 39141cc406Sopenharmony_ci This file implements a SANE backend for the Artec/Ultima scanners. 40141cc406Sopenharmony_ci 41141cc406Sopenharmony_ci Copyright (C) 1998-2000 Chris Pinkham 42141cc406Sopenharmony_ci Released under the terms of the GPL. 43141cc406Sopenharmony_ci *NO WARRANTY* 44141cc406Sopenharmony_ci 45141cc406Sopenharmony_ci Portions contributed by: 46141cc406Sopenharmony_ci David Leadbetter - A6000C (3-pass) 47141cc406Sopenharmony_ci Dick Bruijn - AT12 48141cc406Sopenharmony_ci 49141cc406Sopenharmony_ci ********************************************************************* 50141cc406Sopenharmony_ci For feedback/information: 51141cc406Sopenharmony_ci 52141cc406Sopenharmony_ci cpinkham@corp.infi.net 53141cc406Sopenharmony_ci http://www4.infi.net/~cpinkham/sane/sane-artec-doc.html 54141cc406Sopenharmony_ci ********************************************************************* 55141cc406Sopenharmony_ci */ 56141cc406Sopenharmony_ci 57141cc406Sopenharmony_ci#include "../include/sane/config.h" 58141cc406Sopenharmony_ci 59141cc406Sopenharmony_ci#include <ctype.h> 60141cc406Sopenharmony_ci#include <limits.h> 61141cc406Sopenharmony_ci#include <stdlib.h> 62141cc406Sopenharmony_ci#include <stdarg.h> 63141cc406Sopenharmony_ci#include <string.h> 64141cc406Sopenharmony_ci#include <unistd.h> 65141cc406Sopenharmony_ci#include <sys/types.h> 66141cc406Sopenharmony_ci#include <sys/stat.h> 67141cc406Sopenharmony_ci#include <fcntl.h> 68141cc406Sopenharmony_ci 69141cc406Sopenharmony_ci#include "../include/_stdint.h" 70141cc406Sopenharmony_ci 71141cc406Sopenharmony_ci#include "../include/sane/sane.h" 72141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 73141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h" 74141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 75141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 76141cc406Sopenharmony_ci 77141cc406Sopenharmony_ci#include <artec.h> 78141cc406Sopenharmony_ci 79141cc406Sopenharmony_ci#define BACKEND_NAME artec 80141cc406Sopenharmony_ci 81141cc406Sopenharmony_ci#define ARTEC_MAJOR 0 82141cc406Sopenharmony_ci#define ARTEC_MINOR 5 83141cc406Sopenharmony_ci#define ARTEC_SUB 16 84141cc406Sopenharmony_ci#define ARTEC_LAST_MOD "05/26/2001 17:28 EST" 85141cc406Sopenharmony_ci 86141cc406Sopenharmony_ci 87141cc406Sopenharmony_ci#ifndef PATH_MAX 88141cc406Sopenharmony_ci#define PATH_MAX 1024 89141cc406Sopenharmony_ci#endif 90141cc406Sopenharmony_ci 91141cc406Sopenharmony_ci#define ARTEC_CONFIG_FILE "artec.conf" 92141cc406Sopenharmony_ci#define ARTEC_MAX_READ_SIZE 32768 93141cc406Sopenharmony_ci 94141cc406Sopenharmony_cistatic int num_devices; 95141cc406Sopenharmony_cistatic const SANE_Device **devlist = 0; 96141cc406Sopenharmony_cistatic ARTEC_Device *first_dev; 97141cc406Sopenharmony_cistatic ARTEC_Scanner *first_handle; 98141cc406Sopenharmony_ci 99141cc406Sopenharmony_cistatic const SANE_String_Const mode_list[] = 100141cc406Sopenharmony_ci{ 101141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_LINEART, 102141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_HALFTONE, 103141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_GRAY, 104141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_COLOR, 105141cc406Sopenharmony_ci 0 106141cc406Sopenharmony_ci}; 107141cc406Sopenharmony_ci 108141cc406Sopenharmony_cistatic const SANE_String_Const filter_type_list[] = 109141cc406Sopenharmony_ci{ 110141cc406Sopenharmony_ci "Mono", "Red", "Green", "Blue", 111141cc406Sopenharmony_ci 0 112141cc406Sopenharmony_ci}; 113141cc406Sopenharmony_ci 114141cc406Sopenharmony_cistatic const SANE_String_Const halftone_pattern_list[] = 115141cc406Sopenharmony_ci{ 116141cc406Sopenharmony_ci "User defined (unsupported)", "4x4 Spiral", "4x4 Bayer", "8x8 Spiral", 117141cc406Sopenharmony_ci "8x8 Bayer", 118141cc406Sopenharmony_ci 0 119141cc406Sopenharmony_ci}; 120141cc406Sopenharmony_ci 121141cc406Sopenharmony_cistatic const SANE_Range u8_range = 122141cc406Sopenharmony_ci{ 123141cc406Sopenharmony_ci 0, /* minimum */ 124141cc406Sopenharmony_ci 255, /* maximum */ 125141cc406Sopenharmony_ci 0 /* quantization */ 126141cc406Sopenharmony_ci}; 127141cc406Sopenharmony_ci 128141cc406Sopenharmony_ci#define INQ_LEN 0x60 129141cc406Sopenharmony_cistatic const uint8_t inquiry[] = 130141cc406Sopenharmony_ci{ 131141cc406Sopenharmony_ci 0x12, 0x00, 0x00, 0x00, INQ_LEN, 0x00 132141cc406Sopenharmony_ci}; 133141cc406Sopenharmony_ci 134141cc406Sopenharmony_cistatic const uint8_t test_unit_ready[] = 135141cc406Sopenharmony_ci{ 136141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 137141cc406Sopenharmony_ci}; 138141cc406Sopenharmony_ci 139141cc406Sopenharmony_cistatic struct 140141cc406Sopenharmony_ci { 141141cc406Sopenharmony_ci SANE_String model; /* product model */ 142141cc406Sopenharmony_ci SANE_String type; /* type of scanner */ 143141cc406Sopenharmony_ci double width; /* width in inches */ 144141cc406Sopenharmony_ci double height; /* height in inches */ 145141cc406Sopenharmony_ci SANE_Word adc_bits; /* Analog-to-Digital Converter Bits */ 146141cc406Sopenharmony_ci SANE_Word setwindow_cmd_size; /* Set-Window command size */ 147141cc406Sopenharmony_ci SANE_Word max_read_size; /* Max Read size in bytes */ 148141cc406Sopenharmony_ci long flags; /* flags */ 149141cc406Sopenharmony_ci SANE_String horz_resolution_str; /* Horizontal resolution list */ 150141cc406Sopenharmony_ci SANE_String vert_resolution_str; /* Vertical resolution list */ 151141cc406Sopenharmony_ci } 152141cc406Sopenharmony_cicap_data[] = 153141cc406Sopenharmony_ci{ 154141cc406Sopenharmony_ci { 155141cc406Sopenharmony_ci "AT3", "flatbed", 156141cc406Sopenharmony_ci 8.3, 11, 8, 55, 32768, 157141cc406Sopenharmony_ci ARTEC_FLAG_CALIBRATE_RGB | 158141cc406Sopenharmony_ci ARTEC_FLAG_RGB_LINE_OFFSET | 159141cc406Sopenharmony_ci ARTEC_FLAG_RGB_CHAR_SHIFT | 160141cc406Sopenharmony_ci ARTEC_FLAG_OPT_CONTRAST | 161141cc406Sopenharmony_ci ARTEC_FLAG_GAMMA_SINGLE | 162141cc406Sopenharmony_ci ARTEC_FLAG_SEPARATE_RES | 163141cc406Sopenharmony_ci ARTEC_FLAG_SENSE_HANDLER | 164141cc406Sopenharmony_ci ARTEC_FLAG_SENSE_BYTE_19 | 165141cc406Sopenharmony_ci ARTEC_FLAG_ADF | 166141cc406Sopenharmony_ci ARTEC_FLAG_HALFTONE_PATTERN | 167141cc406Sopenharmony_ci ARTEC_FLAG_MBPP_NEGATIVE | 168141cc406Sopenharmony_ci ARTEC_FLAG_ONE_PASS_SCANNER, 169141cc406Sopenharmony_ci "50,100,200,300", "50,100,200,300,600" 170141cc406Sopenharmony_ci } 171141cc406Sopenharmony_ci , 172141cc406Sopenharmony_ci { 173141cc406Sopenharmony_ci "A6000C", "flatbed", 174141cc406Sopenharmony_ci 8.3, 14, 8, 55, 8192, 175141cc406Sopenharmony_ci/* some have reported that Calibration does not work the same as AT3 & A6000C+ 176141cc406Sopenharmony_ci ARTEC_FLAG_CALIBRATE_RGB | 177141cc406Sopenharmony_ci */ 178141cc406Sopenharmony_ci ARTEC_FLAG_OPT_CONTRAST | 179141cc406Sopenharmony_ci ARTEC_FLAG_OPT_BRIGHTNESS | 180141cc406Sopenharmony_ci ARTEC_FLAG_SEPARATE_RES | 181141cc406Sopenharmony_ci ARTEC_FLAG_SENSE_HANDLER | 182141cc406Sopenharmony_ci ARTEC_FLAG_ADF | 183141cc406Sopenharmony_ci ARTEC_FLAG_HALFTONE_PATTERN, 184141cc406Sopenharmony_ci "50,100,200,300", "50,100,200,300,600" 185141cc406Sopenharmony_ci } 186141cc406Sopenharmony_ci , 187141cc406Sopenharmony_ci { 188141cc406Sopenharmony_ci "A6000C PLUS", "flatbed", 189141cc406Sopenharmony_ci 8.3, 14, 8, 55, 8192, 190141cc406Sopenharmony_ci ARTEC_FLAG_CALIBRATE_RGB | 191141cc406Sopenharmony_ci ARTEC_FLAG_RGB_LINE_OFFSET | 192141cc406Sopenharmony_ci ARTEC_FLAG_RGB_CHAR_SHIFT | 193141cc406Sopenharmony_ci ARTEC_FLAG_OPT_CONTRAST | 194141cc406Sopenharmony_ci ARTEC_FLAG_GAMMA_SINGLE | 195141cc406Sopenharmony_ci ARTEC_FLAG_SEPARATE_RES | 196141cc406Sopenharmony_ci ARTEC_FLAG_SENSE_HANDLER | 197141cc406Sopenharmony_ci ARTEC_FLAG_SENSE_BYTE_19 | 198141cc406Sopenharmony_ci ARTEC_FLAG_ADF | 199141cc406Sopenharmony_ci ARTEC_FLAG_HALFTONE_PATTERN | 200141cc406Sopenharmony_ci ARTEC_FLAG_MBPP_NEGATIVE | 201141cc406Sopenharmony_ci ARTEC_FLAG_ONE_PASS_SCANNER, 202141cc406Sopenharmony_ci "50,100,200,300", "50,100,200,300,600" 203141cc406Sopenharmony_ci } 204141cc406Sopenharmony_ci , 205141cc406Sopenharmony_ci { 206141cc406Sopenharmony_ci "AT6", "flatbed", 207141cc406Sopenharmony_ci 8.3, 11, 10, 55, 32768, 208141cc406Sopenharmony_ci ARTEC_FLAG_CALIBRATE_RGB | 209141cc406Sopenharmony_ci ARTEC_FLAG_RGB_LINE_OFFSET | 210141cc406Sopenharmony_ci ARTEC_FLAG_RGB_CHAR_SHIFT | 211141cc406Sopenharmony_ci ARTEC_FLAG_OPT_CONTRAST | 212141cc406Sopenharmony_ci/* gamma not working totally correct yet. 213141cc406Sopenharmony_ci ARTEC_FLAG_GAMMA_SINGLE | 214141cc406Sopenharmony_ci */ 215141cc406Sopenharmony_ci ARTEC_FLAG_SEPARATE_RES | 216141cc406Sopenharmony_ci ARTEC_FLAG_SENSE_HANDLER | 217141cc406Sopenharmony_ci ARTEC_FLAG_ADF | 218141cc406Sopenharmony_ci ARTEC_FLAG_HALFTONE_PATTERN | 219141cc406Sopenharmony_ci ARTEC_FLAG_MBPP_NEGATIVE | 220141cc406Sopenharmony_ci ARTEC_FLAG_ONE_PASS_SCANNER, 221141cc406Sopenharmony_ci "50,100,200,300", "50,100,200,300,600" 222141cc406Sopenharmony_ci } 223141cc406Sopenharmony_ci , 224141cc406Sopenharmony_ci { 225141cc406Sopenharmony_ci "AT12", "flatbed", 226141cc406Sopenharmony_ci 8.5, 11, 12, 67, 32768, 227141cc406Sopenharmony_ci/* calibration works slower so disabled 228141cc406Sopenharmony_ci ARTEC_CALIBRATE_DARK_WHITE | 229141cc406Sopenharmony_ci */ 230141cc406Sopenharmony_ci/* gamma not working totally correct yet. 231141cc406Sopenharmony_ci ARTEC_FLAG_GAMMA | 232141cc406Sopenharmony_ci */ 233141cc406Sopenharmony_ci ARTEC_FLAG_OPT_CONTRAST | 234141cc406Sopenharmony_ci ARTEC_FLAG_SEPARATE_RES | 235141cc406Sopenharmony_ci ARTEC_FLAG_SENSE_HANDLER | 236141cc406Sopenharmony_ci ARTEC_FLAG_SENSE_ENH_18 | 237141cc406Sopenharmony_ci ARTEC_FLAG_SENSE_BYTE_22 | 238141cc406Sopenharmony_ci ARTEC_FLAG_SC_BUFFERS_LINES | 239141cc406Sopenharmony_ci ARTEC_FLAG_SC_HANDLES_OFFSET | 240141cc406Sopenharmony_ci ARTEC_FLAG_PIXEL_AVERAGING | 241141cc406Sopenharmony_ci ARTEC_FLAG_ENHANCE_LINE_EDGE | 242141cc406Sopenharmony_ci ARTEC_FLAG_ADF | 243141cc406Sopenharmony_ci ARTEC_FLAG_HALFTONE_PATTERN | 244141cc406Sopenharmony_ci ARTEC_FLAG_MBPP_NEGATIVE | 245141cc406Sopenharmony_ci ARTEC_FLAG_ONE_PASS_SCANNER, 246141cc406Sopenharmony_ci "25,50,100,200,300,400,500,600", 247141cc406Sopenharmony_ci "25,50,100,200,300,400,500,600,700,800,900,1000,1100,1200" 248141cc406Sopenharmony_ci } 249141cc406Sopenharmony_ci , 250141cc406Sopenharmony_ci { 251141cc406Sopenharmony_ci "AM12S", "flatbed", 252141cc406Sopenharmony_ci 8.26, 11.7, 12, 67, ARTEC_MAX_READ_SIZE, 253141cc406Sopenharmony_ci/* calibration works slower so disabled 254141cc406Sopenharmony_ci ARTEC_CALIBRATE_DARK_WHITE | 255141cc406Sopenharmony_ci */ 256141cc406Sopenharmony_ci/* gamma not working totally correct yet. 257141cc406Sopenharmony_ci ARTEC_FLAG_GAMMA | 258141cc406Sopenharmony_ci */ 259141cc406Sopenharmony_ci ARTEC_FLAG_RGB_LINE_OFFSET | 260141cc406Sopenharmony_ci ARTEC_FLAG_SEPARATE_RES | 261141cc406Sopenharmony_ci ARTEC_FLAG_IMAGE_REV_LR | 262141cc406Sopenharmony_ci ARTEC_FLAG_REVERSE_WINDOW | 263141cc406Sopenharmony_ci ARTEC_FLAG_SENSE_HANDLER | 264141cc406Sopenharmony_ci ARTEC_FLAG_SENSE_ENH_18 | 265141cc406Sopenharmony_ci ARTEC_FLAG_MBPP_NEGATIVE | 266141cc406Sopenharmony_ci ARTEC_FLAG_ONE_PASS_SCANNER, 267141cc406Sopenharmony_ci "50,100,300,600", 268141cc406Sopenharmony_ci "50,100,300,600,1200" 269141cc406Sopenharmony_ci } 270141cc406Sopenharmony_ci , 271141cc406Sopenharmony_ci}; 272141cc406Sopenharmony_ci 273141cc406Sopenharmony_ci/* store vendor and model if hardcoded in artec.conf */ 274141cc406Sopenharmony_cistatic char artec_vendor[9] = ""; 275141cc406Sopenharmony_cistatic char artec_model[17] = ""; 276141cc406Sopenharmony_ci 277141cc406Sopenharmony_ci/* file descriptor for debug data output */ 278141cc406Sopenharmony_cistatic int debug_fd = -1; 279141cc406Sopenharmony_ci 280141cc406Sopenharmony_cistatic char *artec_skip_whitespace (char *str) 281141cc406Sopenharmony_ci{ 282141cc406Sopenharmony_ci while (isspace (*str)) 283141cc406Sopenharmony_ci ++str; 284141cc406Sopenharmony_ci return str; 285141cc406Sopenharmony_ci} 286141cc406Sopenharmony_ci 287141cc406Sopenharmony_cistatic SANE_Status 288141cc406Sopenharmony_ciartec_str_list_to_word_list (SANE_Word ** word_list_ptr, SANE_String str) 289141cc406Sopenharmony_ci{ 290141cc406Sopenharmony_ci SANE_Word *word_list; 291141cc406Sopenharmony_ci char *start; 292141cc406Sopenharmony_ci char *end; 293141cc406Sopenharmony_ci char temp_str[1024]; 294141cc406Sopenharmony_ci int comma_count = 1; 295141cc406Sopenharmony_ci 296141cc406Sopenharmony_ci if ((str == NULL) || 297141cc406Sopenharmony_ci (strlen (str) == 0)) 298141cc406Sopenharmony_ci { 299141cc406Sopenharmony_ci /* alloc space for word which stores length (0 in this case) */ 300141cc406Sopenharmony_ci word_list = (SANE_Word *) malloc (sizeof (SANE_Word)); 301141cc406Sopenharmony_ci if (word_list == NULL) 302141cc406Sopenharmony_ci return (SANE_STATUS_NO_MEM); 303141cc406Sopenharmony_ci 304141cc406Sopenharmony_ci word_list[0] = 0; 305141cc406Sopenharmony_ci *word_list_ptr = word_list; 306141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 307141cc406Sopenharmony_ci } 308141cc406Sopenharmony_ci 309141cc406Sopenharmony_ci /* make temp copy of input string (only hold 1024 for now) */ 310141cc406Sopenharmony_ci strncpy (temp_str, str, 1023); 311141cc406Sopenharmony_ci temp_str[1023] = '\0'; 312141cc406Sopenharmony_ci 313141cc406Sopenharmony_ci end = strchr (temp_str, ','); 314141cc406Sopenharmony_ci while (end != NULL) 315141cc406Sopenharmony_ci { 316141cc406Sopenharmony_ci comma_count++; 317141cc406Sopenharmony_ci start = end + 1; 318141cc406Sopenharmony_ci end = strchr (start, ','); 319141cc406Sopenharmony_ci } 320141cc406Sopenharmony_ci 321141cc406Sopenharmony_ci word_list = (SANE_Word *) calloc (comma_count + 1, 322141cc406Sopenharmony_ci sizeof (SANE_Word)); 323141cc406Sopenharmony_ci 324141cc406Sopenharmony_ci if (word_list == NULL) 325141cc406Sopenharmony_ci return (SANE_STATUS_NO_MEM); 326141cc406Sopenharmony_ci 327141cc406Sopenharmony_ci word_list[0] = comma_count; 328141cc406Sopenharmony_ci 329141cc406Sopenharmony_ci comma_count = 1; 330141cc406Sopenharmony_ci start = temp_str; 331141cc406Sopenharmony_ci end = strchr (temp_str, ','); 332141cc406Sopenharmony_ci while (end != NULL) 333141cc406Sopenharmony_ci { 334141cc406Sopenharmony_ci *end = '\0'; 335141cc406Sopenharmony_ci word_list[comma_count] = atol (start); 336141cc406Sopenharmony_ci 337141cc406Sopenharmony_ci start = end + 1; 338141cc406Sopenharmony_ci comma_count++; 339141cc406Sopenharmony_ci end = strchr (start, ','); 340141cc406Sopenharmony_ci } 341141cc406Sopenharmony_ci 342141cc406Sopenharmony_ci word_list[comma_count] = atol (start); 343141cc406Sopenharmony_ci 344141cc406Sopenharmony_ci *word_list_ptr = word_list; 345141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 346141cc406Sopenharmony_ci} 347141cc406Sopenharmony_ci 348141cc406Sopenharmony_cistatic size_t 349141cc406Sopenharmony_ciartec_get_str_index (const SANE_String_Const strings[], char *str) 350141cc406Sopenharmony_ci{ 351141cc406Sopenharmony_ci size_t index; 352141cc406Sopenharmony_ci 353141cc406Sopenharmony_ci index = 0; 354141cc406Sopenharmony_ci while ((strings[index]) && strcmp (strings[index], str)) 355141cc406Sopenharmony_ci { 356141cc406Sopenharmony_ci index++; 357141cc406Sopenharmony_ci } 358141cc406Sopenharmony_ci 359141cc406Sopenharmony_ci if (!strings[index]) 360141cc406Sopenharmony_ci { 361141cc406Sopenharmony_ci index = 0; 362141cc406Sopenharmony_ci } 363141cc406Sopenharmony_ci 364141cc406Sopenharmony_ci return (index); 365141cc406Sopenharmony_ci} 366141cc406Sopenharmony_ci 367141cc406Sopenharmony_cistatic size_t 368141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[]) 369141cc406Sopenharmony_ci{ 370141cc406Sopenharmony_ci size_t size, max_size = 0; 371141cc406Sopenharmony_ci int i; 372141cc406Sopenharmony_ci 373141cc406Sopenharmony_ci for (i = 0; strings[i]; ++i) 374141cc406Sopenharmony_ci { 375141cc406Sopenharmony_ci size = strlen (strings[i]) + 1; 376141cc406Sopenharmony_ci if (size > max_size) 377141cc406Sopenharmony_ci max_size = size; 378141cc406Sopenharmony_ci } 379141cc406Sopenharmony_ci 380141cc406Sopenharmony_ci return (max_size); 381141cc406Sopenharmony_ci} 382141cc406Sopenharmony_ci 383141cc406Sopenharmony_ci/* DB added a sense handler */ 384141cc406Sopenharmony_ci/* last argument is expected to be a pointer to a Artec_Scanner structure */ 385141cc406Sopenharmony_cistatic SANE_Status 386141cc406Sopenharmony_cisense_handler (int fd, u_char * sense, void *arg) 387141cc406Sopenharmony_ci{ 388141cc406Sopenharmony_ci ARTEC_Scanner *s = (ARTEC_Scanner *)arg; 389141cc406Sopenharmony_ci int err; 390141cc406Sopenharmony_ci 391141cc406Sopenharmony_ci err = 0; 392141cc406Sopenharmony_ci 393141cc406Sopenharmony_ci DBG(2, "sense fd: %d, data: %02x %02x %02x %02x %02x %02x %02x %02x " 394141cc406Sopenharmony_ci "%02x %02x %02x %02x %02x %02x %02x %02x\n", fd, 395141cc406Sopenharmony_ci sense[0], sense[1], sense[2], sense[3], 396141cc406Sopenharmony_ci sense[4], sense[5], sense[6], sense[7], 397141cc406Sopenharmony_ci sense[8], sense[9], sense[10], sense[11], 398141cc406Sopenharmony_ci sense[12], sense[13], sense[14], sense[15]); 399141cc406Sopenharmony_ci 400141cc406Sopenharmony_ci /* byte 18 info pertaining to ADF */ 401141cc406Sopenharmony_ci if ((s) && (s->hw->flags & ARTEC_FLAG_ADF)) 402141cc406Sopenharmony_ci { 403141cc406Sopenharmony_ci if (sense[18] & 0x01) 404141cc406Sopenharmony_ci { 405141cc406Sopenharmony_ci DBG (2, "sense: ADF PAPER JAM\n"); 406141cc406Sopenharmony_ci err++; 407141cc406Sopenharmony_ci } 408141cc406Sopenharmony_ci if (sense[18] & 0x02) 409141cc406Sopenharmony_ci { 410141cc406Sopenharmony_ci DBG (2, "sense: ADF NO DOCUMENT IN BIN\n"); 411141cc406Sopenharmony_ci err++; 412141cc406Sopenharmony_ci } 413141cc406Sopenharmony_ci if (sense[18] & 0x04) 414141cc406Sopenharmony_ci { 415141cc406Sopenharmony_ci DBG (2, "sense: ADF SWITCH COVER OPEN\n"); 416141cc406Sopenharmony_ci err++; 417141cc406Sopenharmony_ci } 418141cc406Sopenharmony_ci /* DB : next is, i think no failure, so no incrementing s */ 419141cc406Sopenharmony_ci if (sense[18] & 0x08) 420141cc406Sopenharmony_ci { 421141cc406Sopenharmony_ci DBG (2, "sense: ADF SET CORRECTLY ON TARGET\n"); 422141cc406Sopenharmony_ci } 423141cc406Sopenharmony_ci /* The following only for AT12, its reserved (zero?) on other models, */ 424141cc406Sopenharmony_ci if (sense[18] & 0x10) 425141cc406Sopenharmony_ci { 426141cc406Sopenharmony_ci DBG (2, "sense: ADF LENGTH TOO SHORT\n"); 427141cc406Sopenharmony_ci err++; 428141cc406Sopenharmony_ci } 429141cc406Sopenharmony_ci } 430141cc406Sopenharmony_ci 431141cc406Sopenharmony_ci /* enhanced byte 18 sense data */ 432141cc406Sopenharmony_ci if ((s) && (s->hw->flags & ARTEC_FLAG_SENSE_ENH_18)) 433141cc406Sopenharmony_ci { 434141cc406Sopenharmony_ci if (sense[18] & 0x20) 435141cc406Sopenharmony_ci { 436141cc406Sopenharmony_ci DBG (2, "sense: LAMP FAIL : NOT WARM \n"); 437141cc406Sopenharmony_ci err++; 438141cc406Sopenharmony_ci } 439141cc406Sopenharmony_ci if (sense[18] & 0x40) 440141cc406Sopenharmony_ci { 441141cc406Sopenharmony_ci DBG (2, "sense: NOT READY STATE\n"); 442141cc406Sopenharmony_ci err++; 443141cc406Sopenharmony_ci } 444141cc406Sopenharmony_ci } 445141cc406Sopenharmony_ci 446141cc406Sopenharmony_ci if ((s) && (s->hw->flags & ARTEC_FLAG_SENSE_BYTE_19)) 447141cc406Sopenharmony_ci { 448141cc406Sopenharmony_ci if (sense[19] & 0x01) 449141cc406Sopenharmony_ci { 450141cc406Sopenharmony_ci DBG (2, "sense: 8031 program ROM checksum Error\n"); 451141cc406Sopenharmony_ci err++; 452141cc406Sopenharmony_ci } 453141cc406Sopenharmony_ci if (sense[19] & 0x02) 454141cc406Sopenharmony_ci { 455141cc406Sopenharmony_ci DBG (2, "sense: 8031 data RAM R/W Error\n"); 456141cc406Sopenharmony_ci err++; 457141cc406Sopenharmony_ci } 458141cc406Sopenharmony_ci if (sense[19] & 0x04) 459141cc406Sopenharmony_ci { 460141cc406Sopenharmony_ci DBG (2, "sense: Shadow Correction RAM R/W Error\n"); 461141cc406Sopenharmony_ci err++; 462141cc406Sopenharmony_ci } 463141cc406Sopenharmony_ci if (sense[19] & 0x08) 464141cc406Sopenharmony_ci { 465141cc406Sopenharmony_ci DBG (2, "sense: Line RAM R/W Error\n"); 466141cc406Sopenharmony_ci err++; 467141cc406Sopenharmony_ci } 468141cc406Sopenharmony_ci if (sense[19] & 0x10) 469141cc406Sopenharmony_ci { 470141cc406Sopenharmony_ci /* docs say "reserved to '0'" */ 471141cc406Sopenharmony_ci DBG (2, "sense: CCD control circuit Error\n"); 472141cc406Sopenharmony_ci err++; 473141cc406Sopenharmony_ci } 474141cc406Sopenharmony_ci if (sense[19] & 0x20) 475141cc406Sopenharmony_ci { 476141cc406Sopenharmony_ci DBG (2, "sense: Motor End Switch Error\n"); 477141cc406Sopenharmony_ci err++; 478141cc406Sopenharmony_ci } 479141cc406Sopenharmony_ci if (sense[19] & 0x40) 480141cc406Sopenharmony_ci { 481141cc406Sopenharmony_ci /* docs say "reserved to '0'" */ 482141cc406Sopenharmony_ci DBG (2, "sense: Lamp Error\n"); 483141cc406Sopenharmony_ci err++; 484141cc406Sopenharmony_ci } 485141cc406Sopenharmony_ci if (sense[19] & 0x80) 486141cc406Sopenharmony_ci { 487141cc406Sopenharmony_ci DBG (2, "sense: Optical Calibration/Shading Error\n"); 488141cc406Sopenharmony_ci err++; 489141cc406Sopenharmony_ci } 490141cc406Sopenharmony_ci } 491141cc406Sopenharmony_ci 492141cc406Sopenharmony_ci /* These are the self test results for tests 0-15 */ 493141cc406Sopenharmony_ci if ((s) && (s->hw->flags & ARTEC_FLAG_SENSE_BYTE_22)) 494141cc406Sopenharmony_ci { 495141cc406Sopenharmony_ci if (sense[22] & 0x01) 496141cc406Sopenharmony_ci { 497141cc406Sopenharmony_ci DBG (2, "sense: 8031 Internal Memory R/W Error\n"); 498141cc406Sopenharmony_ci err++; 499141cc406Sopenharmony_ci } 500141cc406Sopenharmony_ci if (sense[22] & 0x02) 501141cc406Sopenharmony_ci { 502141cc406Sopenharmony_ci DBG (2, "sense: EEPROM test pattern R/W Error\n"); 503141cc406Sopenharmony_ci err++; 504141cc406Sopenharmony_ci } 505141cc406Sopenharmony_ci if (sense[22] & 0x04) 506141cc406Sopenharmony_ci { 507141cc406Sopenharmony_ci DBG (2, "sense: ASIC Test Error\n"); 508141cc406Sopenharmony_ci err++; 509141cc406Sopenharmony_ci } 510141cc406Sopenharmony_ci if (sense[22] & 0x08) 511141cc406Sopenharmony_ci { 512141cc406Sopenharmony_ci DBG (2, "sense: Line RAM R/W Error\n"); 513141cc406Sopenharmony_ci err++; 514141cc406Sopenharmony_ci } 515141cc406Sopenharmony_ci if (sense[22] & 0x10) 516141cc406Sopenharmony_ci { 517141cc406Sopenharmony_ci DBG (2, "sense: PSRAM R/W Test Error\n"); 518141cc406Sopenharmony_ci err++; 519141cc406Sopenharmony_ci } 520141cc406Sopenharmony_ci if (sense[22] & 0x20) 521141cc406Sopenharmony_ci { 522141cc406Sopenharmony_ci DBG (2, "sense: Positioning Error\n"); 523141cc406Sopenharmony_ci err++; 524141cc406Sopenharmony_ci } 525141cc406Sopenharmony_ci if (sense[22] & 0x40) 526141cc406Sopenharmony_ci { 527141cc406Sopenharmony_ci DBG (2, "sense: Test 6 Error\n"); 528141cc406Sopenharmony_ci err++; 529141cc406Sopenharmony_ci } 530141cc406Sopenharmony_ci if (sense[22] & 0x80) 531141cc406Sopenharmony_ci { 532141cc406Sopenharmony_ci DBG (2, "sense: Test 7 Error\n"); 533141cc406Sopenharmony_ci err++; 534141cc406Sopenharmony_ci } 535141cc406Sopenharmony_ci if (sense[23] & 0x01) 536141cc406Sopenharmony_ci { 537141cc406Sopenharmony_ci DBG (2, "sense: Test 8 Error\n"); 538141cc406Sopenharmony_ci err++; 539141cc406Sopenharmony_ci } 540141cc406Sopenharmony_ci if (sense[23] & 0x02) 541141cc406Sopenharmony_ci { 542141cc406Sopenharmony_ci DBG (2, "sense: Test 9 Error\n"); 543141cc406Sopenharmony_ci err++; 544141cc406Sopenharmony_ci } 545141cc406Sopenharmony_ci if (sense[23] & 0x04) 546141cc406Sopenharmony_ci { 547141cc406Sopenharmony_ci DBG (2, "sense: Test 10 Error\n"); 548141cc406Sopenharmony_ci err++; 549141cc406Sopenharmony_ci } 550141cc406Sopenharmony_ci if (sense[23] & 0x08) 551141cc406Sopenharmony_ci { 552141cc406Sopenharmony_ci DBG (2, "sense: Test 11 Error\n"); 553141cc406Sopenharmony_ci err++; 554141cc406Sopenharmony_ci } 555141cc406Sopenharmony_ci if (sense[23] & 0x10) 556141cc406Sopenharmony_ci { 557141cc406Sopenharmony_ci DBG (2, "sense: Test 12 Error\n"); 558141cc406Sopenharmony_ci err++; 559141cc406Sopenharmony_ci } 560141cc406Sopenharmony_ci if (sense[23] & 0x20) 561141cc406Sopenharmony_ci { 562141cc406Sopenharmony_ci DBG (2, "sense: Test 13 Error\n"); 563141cc406Sopenharmony_ci err++; 564141cc406Sopenharmony_ci } 565141cc406Sopenharmony_ci if (sense[23] & 0x40) 566141cc406Sopenharmony_ci { 567141cc406Sopenharmony_ci DBG (2, "sense: Test 14 Error\n"); 568141cc406Sopenharmony_ci err++; 569141cc406Sopenharmony_ci } 570141cc406Sopenharmony_ci if (sense[23] & 0x80) 571141cc406Sopenharmony_ci { 572141cc406Sopenharmony_ci DBG (2, "sense: Test 15 Error\n"); 573141cc406Sopenharmony_ci err++; 574141cc406Sopenharmony_ci } 575141cc406Sopenharmony_ci } 576141cc406Sopenharmony_ci 577141cc406Sopenharmony_ci if (err) 578141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 579141cc406Sopenharmony_ci 580141cc406Sopenharmony_ci switch (sense[0]) 581141cc406Sopenharmony_ci { 582141cc406Sopenharmony_ci case 0x70: /* ALWAYS */ 583141cc406Sopenharmony_ci switch (sense[2]) 584141cc406Sopenharmony_ci { 585141cc406Sopenharmony_ci case 0x00: 586141cc406Sopenharmony_ci DBG (2, "sense: Successful command\n"); 587141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 588141cc406Sopenharmony_ci case 0x02: 589141cc406Sopenharmony_ci DBG (2, "sense: Not Ready, target can not be accessed\n"); 590141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 591141cc406Sopenharmony_ci case 0x03: 592141cc406Sopenharmony_ci DBG (2, "sense: Medium Error, paper jam or misfeed during ADF\n"); 593141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 594141cc406Sopenharmony_ci case 0x04: 595141cc406Sopenharmony_ci DBG (2, "sense: Hardware Error, non-recoverable\n"); 596141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 597141cc406Sopenharmony_ci case 0x05: 598141cc406Sopenharmony_ci DBG (2, "sense: Illegal Request, bad parameter in command block\n"); 599141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 600141cc406Sopenharmony_ci case 0x06: 601141cc406Sopenharmony_ci DBG (2, "sense: Unit Attention\n"); 602141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 603141cc406Sopenharmony_ci default: 604141cc406Sopenharmony_ci DBG (2, "sense: SENSE KEY UNKNOWN (%02x)\n", sense[2]); 605141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 606141cc406Sopenharmony_ci } 607141cc406Sopenharmony_ci default: 608141cc406Sopenharmony_ci DBG (2, "sense: Unknown Error Code Qualifier (%02x)\n", sense[0]); 609141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 610141cc406Sopenharmony_ci } 611141cc406Sopenharmony_ci 612141cc406Sopenharmony_ci DBG (2, "sense: Should not come here!\n"); 613141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 614141cc406Sopenharmony_ci} 615141cc406Sopenharmony_ci 616141cc406Sopenharmony_ci 617141cc406Sopenharmony_ci/* DB added a wait routine for the scanner to come ready */ 618141cc406Sopenharmony_cistatic SANE_Status 619141cc406Sopenharmony_ciwait_ready (int fd) 620141cc406Sopenharmony_ci{ 621141cc406Sopenharmony_ci SANE_Status status; 622141cc406Sopenharmony_ci int retry = 30; /* make this tuneable? */ 623141cc406Sopenharmony_ci 624141cc406Sopenharmony_ci DBG (7, "wait_ready()\n"); 625141cc406Sopenharmony_ci while (retry-- > 0) 626141cc406Sopenharmony_ci { 627141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, test_unit_ready, 628141cc406Sopenharmony_ci sizeof (test_unit_ready), 0, 0); 629141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) 630141cc406Sopenharmony_ci return status; 631141cc406Sopenharmony_ci 632141cc406Sopenharmony_ci if (status == SANE_STATUS_DEVICE_BUSY) 633141cc406Sopenharmony_ci { 634141cc406Sopenharmony_ci sleep (1); 635141cc406Sopenharmony_ci continue; 636141cc406Sopenharmony_ci } 637141cc406Sopenharmony_ci 638141cc406Sopenharmony_ci /* status != GOOD && != BUSY */ 639141cc406Sopenharmony_ci DBG (9, "wait_ready: '%s'\n", sane_strstatus (status)); 640141cc406Sopenharmony_ci return status; 641141cc406Sopenharmony_ci } 642141cc406Sopenharmony_ci 643141cc406Sopenharmony_ci /* BUSY after n retries */ 644141cc406Sopenharmony_ci DBG (9, "wait_ready: '%s'\n", sane_strstatus (status)); 645141cc406Sopenharmony_ci return status; 646141cc406Sopenharmony_ci} 647141cc406Sopenharmony_ci 648141cc406Sopenharmony_ci/* DB added a abort routine, executed via mode select */ 649141cc406Sopenharmony_cistatic SANE_Status 650141cc406Sopenharmony_ciabort_scan (SANE_Handle handle) 651141cc406Sopenharmony_ci{ 652141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 653141cc406Sopenharmony_ci uint8_t *data, comm[22]; 654141cc406Sopenharmony_ci 655141cc406Sopenharmony_ci DBG (7, "abort_scan()\n"); 656141cc406Sopenharmony_ci memset (comm, 0, sizeof (comm)); 657141cc406Sopenharmony_ci 658141cc406Sopenharmony_ci comm[0] = 0x15; 659141cc406Sopenharmony_ci comm[1] = 0x10; 660141cc406Sopenharmony_ci comm[2] = 0x00; 661141cc406Sopenharmony_ci comm[3] = 0x00; 662141cc406Sopenharmony_ci comm[4] = 0x10; 663141cc406Sopenharmony_ci comm[5] = 0x00; 664141cc406Sopenharmony_ci 665141cc406Sopenharmony_ci data = comm + 6; 666141cc406Sopenharmony_ci data[0] = 0x00; /* mode data length */ 667141cc406Sopenharmony_ci data[1] = 0x00; /* medium type */ 668141cc406Sopenharmony_ci data[2] = 0x00; /* device specific parameter */ 669141cc406Sopenharmony_ci data[3] = 0x00; /* block descriptor length */ 670141cc406Sopenharmony_ci 671141cc406Sopenharmony_ci data = comm + 10; 672141cc406Sopenharmony_ci data[0] = 0x00; /* control page parameters */ 673141cc406Sopenharmony_ci data[1] = 0x0a; /* parameter length */ 674141cc406Sopenharmony_ci data[2] = 0x02 | ((s->val[OPT_TRANSPARENCY].w == SANE_TRUE) ? 0x04 : 0x00) | 675141cc406Sopenharmony_ci ((s->val[OPT_ADF].w == SANE_TRUE) ? 0x00 : 0x01); 676141cc406Sopenharmony_ci data[3] = 0x00; /* reserved */ 677141cc406Sopenharmony_ci data[4] = 0x00; /* reserved */ 678141cc406Sopenharmony_ci 679141cc406Sopenharmony_ci DBG (9, "abort: sending abort command\n"); 680141cc406Sopenharmony_ci sanei_scsi_cmd (s->fd, comm, 6 + comm[4], 0, 0); 681141cc406Sopenharmony_ci 682141cc406Sopenharmony_ci DBG (9, "abort: wait for scanner to come ready...\n"); 683141cc406Sopenharmony_ci wait_ready (s->fd); 684141cc406Sopenharmony_ci 685141cc406Sopenharmony_ci DBG (9, "abort: resetting abort status\n"); 686141cc406Sopenharmony_ci data[2] = ((s->val[OPT_TRANSPARENCY].w == SANE_TRUE) ? 0x04 : 0x00) | 687141cc406Sopenharmony_ci ((s->val[OPT_ADF].w == SANE_TRUE) ? 0x00 : 0x01); 688141cc406Sopenharmony_ci sanei_scsi_cmd (s->fd, comm, 6 + comm[4], 0, 0); 689141cc406Sopenharmony_ci 690141cc406Sopenharmony_ci DBG (9, "abort: wait for scanner to come ready...\n"); 691141cc406Sopenharmony_ci return wait_ready (s->fd); 692141cc406Sopenharmony_ci} 693141cc406Sopenharmony_ci 694141cc406Sopenharmony_ci/* DAL - mode_select: used for transparency and ADF scanning */ 695141cc406Sopenharmony_ci/* Based on abort_scan */ 696141cc406Sopenharmony_cistatic SANE_Status 697141cc406Sopenharmony_ciartec_mode_select (SANE_Handle handle) 698141cc406Sopenharmony_ci{ 699141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 700141cc406Sopenharmony_ci uint8_t *data, comm[22]; 701141cc406Sopenharmony_ci 702141cc406Sopenharmony_ci DBG (7, "artec_mode_select()\n"); 703141cc406Sopenharmony_ci memset (comm, 0, sizeof (comm)); 704141cc406Sopenharmony_ci 705141cc406Sopenharmony_ci comm[0] = 0x15; 706141cc406Sopenharmony_ci comm[1] = 0x10; 707141cc406Sopenharmony_ci comm[2] = 0x00; 708141cc406Sopenharmony_ci comm[3] = 0x00; 709141cc406Sopenharmony_ci comm[4] = 0x10; 710141cc406Sopenharmony_ci comm[5] = 0x00; 711141cc406Sopenharmony_ci 712141cc406Sopenharmony_ci data = comm + 6; 713141cc406Sopenharmony_ci data[0] = 0x00; /* mode data length */ 714141cc406Sopenharmony_ci data[1] = 0x00; /* medium type */ 715141cc406Sopenharmony_ci data[2] = 0x00; /* device specific parameter */ 716141cc406Sopenharmony_ci data[3] = 0x00; /* block descriptor length */ 717141cc406Sopenharmony_ci 718141cc406Sopenharmony_ci data = comm + 10; 719141cc406Sopenharmony_ci data[0] = 0x00; /* control page parameters */ 720141cc406Sopenharmony_ci data[1] = 0x0a; /* parameter length */ 721141cc406Sopenharmony_ci data[2] = ((s->val[OPT_TRANSPARENCY].w == SANE_TRUE) ? 0x04 : 0x00) | 722141cc406Sopenharmony_ci ((s->val[OPT_ADF].w == SANE_TRUE) ? 0x00 : 0x01); 723141cc406Sopenharmony_ci data[3] = 0x00; /* reserved */ 724141cc406Sopenharmony_ci data[4] = 0x00; /* reserved */ 725141cc406Sopenharmony_ci 726141cc406Sopenharmony_ci DBG (9, "artec_mode_select: mode %d\n", data[2]); 727141cc406Sopenharmony_ci DBG (9, "artec_mode_select: sending mode command\n"); 728141cc406Sopenharmony_ci sanei_scsi_cmd (s->fd, comm, 6 + comm[4], 0, 0); 729141cc406Sopenharmony_ci 730141cc406Sopenharmony_ci DBG (9, "artec_mode_select: wait for scanner to come ready...\n"); 731141cc406Sopenharmony_ci return wait_ready (s->fd); 732141cc406Sopenharmony_ci} 733141cc406Sopenharmony_ci 734141cc406Sopenharmony_ci 735141cc406Sopenharmony_cistatic SANE_Status 736141cc406Sopenharmony_ciread_data (int fd, int data_type_code, u_char * dest, size_t * len) 737141cc406Sopenharmony_ci{ 738141cc406Sopenharmony_ci static u_char read_6[10]; 739141cc406Sopenharmony_ci 740141cc406Sopenharmony_ci DBG (7, "read_data()\n"); 741141cc406Sopenharmony_ci 742141cc406Sopenharmony_ci memset (read_6, 0, sizeof (read_6)); 743141cc406Sopenharmony_ci read_6[0] = 0x28; 744141cc406Sopenharmony_ci read_6[2] = data_type_code; 745141cc406Sopenharmony_ci read_6[6] = *len >> 16; 746141cc406Sopenharmony_ci read_6[7] = *len >> 8; 747141cc406Sopenharmony_ci read_6[8] = *len; 748141cc406Sopenharmony_ci 749141cc406Sopenharmony_ci return (sanei_scsi_cmd (fd, read_6, sizeof (read_6), dest, len)); 750141cc406Sopenharmony_ci} 751141cc406Sopenharmony_ci 752141cc406Sopenharmony_cistatic int 753141cc406Sopenharmony_ciartec_get_status (int fd) 754141cc406Sopenharmony_ci{ 755141cc406Sopenharmony_ci u_char write_10[10]; 756141cc406Sopenharmony_ci u_char read_12[12]; 757141cc406Sopenharmony_ci size_t nread; 758141cc406Sopenharmony_ci 759141cc406Sopenharmony_ci DBG (7, "artec_get_status()\n"); 760141cc406Sopenharmony_ci 761141cc406Sopenharmony_ci nread = 12; 762141cc406Sopenharmony_ci 763141cc406Sopenharmony_ci memset (write_10, 0, 10); 764141cc406Sopenharmony_ci write_10[0] = 0x34; 765141cc406Sopenharmony_ci write_10[8] = 0x0c; 766141cc406Sopenharmony_ci 767141cc406Sopenharmony_ci sanei_scsi_cmd (fd, write_10, 10, read_12, &nread); 768141cc406Sopenharmony_ci 769141cc406Sopenharmony_ci nread = (read_12[9] << 16) + (read_12[10] << 8) + read_12[11]; 770141cc406Sopenharmony_ci DBG (9, "artec_status: %lu\n", (u_long) nread); 771141cc406Sopenharmony_ci 772141cc406Sopenharmony_ci return (nread); 773141cc406Sopenharmony_ci} 774141cc406Sopenharmony_ci 775141cc406Sopenharmony_cistatic SANE_Status 776141cc406Sopenharmony_ciartec_reverse_line (SANE_Handle handle, SANE_Byte * data) 777141cc406Sopenharmony_ci{ 778141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 779141cc406Sopenharmony_ci SANE_Byte tmp_buf[32768]; /* max dpi 1200 * 8.5 inches * 3 = 30600 */ 780141cc406Sopenharmony_ci SANE_Byte *to, *from; 781141cc406Sopenharmony_ci int len; 782141cc406Sopenharmony_ci 783141cc406Sopenharmony_ci DBG (8, "artec_reverse_line()\n"); 784141cc406Sopenharmony_ci 785141cc406Sopenharmony_ci len = s->params.bytes_per_line; 786141cc406Sopenharmony_ci memcpy (tmp_buf, data, len); 787141cc406Sopenharmony_ci 788141cc406Sopenharmony_ci if (s->params.format == SANE_FRAME_RGB) /* RGB format */ 789141cc406Sopenharmony_ci { 790141cc406Sopenharmony_ci for (from = tmp_buf, to = data + len - 3; 791141cc406Sopenharmony_ci to >= data; 792141cc406Sopenharmony_ci to -= 3, from += 3) 793141cc406Sopenharmony_ci { 794141cc406Sopenharmony_ci *(to + 0) = *(from + 0); /* copy the R byte */ 795141cc406Sopenharmony_ci *(to + 1) = *(from + 1); /* copy the G byte */ 796141cc406Sopenharmony_ci *(to + 2) = *(from + 2); /* copy the B byte */ 797141cc406Sopenharmony_ci } 798141cc406Sopenharmony_ci } 799141cc406Sopenharmony_ci else if (s->params.format == SANE_FRAME_GRAY) 800141cc406Sopenharmony_ci { 801141cc406Sopenharmony_ci if (s->params.depth == 8) /* 256 color gray-scale */ 802141cc406Sopenharmony_ci { 803141cc406Sopenharmony_ci for (from = tmp_buf, to = data + len; to >= data; to--, from++) 804141cc406Sopenharmony_ci { 805141cc406Sopenharmony_ci *to = *from; 806141cc406Sopenharmony_ci } 807141cc406Sopenharmony_ci } 808141cc406Sopenharmony_ci else if (s->params.depth == 1) /* line art or halftone */ 809141cc406Sopenharmony_ci { 810141cc406Sopenharmony_ci for (from = tmp_buf, to = data + len; to >= data; to--, from++) 811141cc406Sopenharmony_ci { 812141cc406Sopenharmony_ci *to = (((*from & 0x01) << 7) | 813141cc406Sopenharmony_ci ((*from & 0x02) << 5) | 814141cc406Sopenharmony_ci ((*from & 0x04) << 3) | 815141cc406Sopenharmony_ci ((*from & 0x08) << 1) | 816141cc406Sopenharmony_ci ((*from & 0x10) >> 1) | 817141cc406Sopenharmony_ci ((*from & 0x20) >> 3) | 818141cc406Sopenharmony_ci ((*from & 0x40) >> 5) | 819141cc406Sopenharmony_ci ((*from & 0x80) >> 7)); 820141cc406Sopenharmony_ci } 821141cc406Sopenharmony_ci } 822141cc406Sopenharmony_ci } 823141cc406Sopenharmony_ci 824141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 825141cc406Sopenharmony_ci} 826141cc406Sopenharmony_ci 827141cc406Sopenharmony_ci 828141cc406Sopenharmony_ci#if 0 829141cc406Sopenharmony_cistatic SANE_Status 830141cc406Sopenharmony_ciartec_byte_rgb_to_line_rgb (SANE_Byte * data, SANE_Int len) 831141cc406Sopenharmony_ci{ 832141cc406Sopenharmony_ci SANE_Byte tmp_buf[32768]; /* max dpi 1200 * 8.5 inches * 3 = 30600 */ 833141cc406Sopenharmony_ci int count, from; 834141cc406Sopenharmony_ci 835141cc406Sopenharmony_ci DBG (8, "artec_byte_rgb_to_line_rgb()\n"); 836141cc406Sopenharmony_ci 837141cc406Sopenharmony_ci /* copy the RGBRGBRGBRGBRGB... formatted data to our temp buffer */ 838141cc406Sopenharmony_ci memcpy (tmp_buf, data, len * 3); 839141cc406Sopenharmony_ci 840141cc406Sopenharmony_ci /* now copy back to *data in RRRRRRRGGGGGGGBBBBBBB format */ 841141cc406Sopenharmony_ci for (count = 0, from = 0; count < len; count++, from += 3) 842141cc406Sopenharmony_ci { 843141cc406Sopenharmony_ci data[count] = tmp_buf[from]; /* R byte */ 844141cc406Sopenharmony_ci data[count + len] = tmp_buf[from + 1]; /* G byte */ 845141cc406Sopenharmony_ci data[count + (len * 2)] = tmp_buf[from + 2]; /* B byte */ 846141cc406Sopenharmony_ci } 847141cc406Sopenharmony_ci 848141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 849141cc406Sopenharmony_ci} 850141cc406Sopenharmony_ci#endif 851141cc406Sopenharmony_ci 852141cc406Sopenharmony_cistatic SANE_Status 853141cc406Sopenharmony_ciartec_line_rgb_to_byte_rgb (SANE_Byte * data, SANE_Int len) 854141cc406Sopenharmony_ci{ 855141cc406Sopenharmony_ci SANE_Byte tmp_buf[32768]; /* max dpi 1200 * 8.5 inches * 3 = 30600 */ 856141cc406Sopenharmony_ci int count, to; 857141cc406Sopenharmony_ci 858141cc406Sopenharmony_ci DBG (8, "artec_line_rgb_to_byte_rgb()\n"); 859141cc406Sopenharmony_ci 860141cc406Sopenharmony_ci /* copy the rgb data to our temp buffer */ 861141cc406Sopenharmony_ci memcpy (tmp_buf, data, len * 3); 862141cc406Sopenharmony_ci 863141cc406Sopenharmony_ci /* now copy back to *data in RGB format */ 864141cc406Sopenharmony_ci for (count = 0, to = 0; count < len; count++, to += 3) 865141cc406Sopenharmony_ci { 866141cc406Sopenharmony_ci data[to] = tmp_buf[count]; /* R byte */ 867141cc406Sopenharmony_ci data[to + 1] = tmp_buf[count + len]; /* G byte */ 868141cc406Sopenharmony_ci data[to + 2] = tmp_buf[count + (len * 2)]; /* B byte */ 869141cc406Sopenharmony_ci } 870141cc406Sopenharmony_ci 871141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 872141cc406Sopenharmony_ci} 873141cc406Sopenharmony_ci 874141cc406Sopenharmony_cistatic SANE_Byte **line_buffer = NULL; 875141cc406Sopenharmony_cistatic SANE_Byte *tmp_line_buf = NULL; 876141cc406Sopenharmony_cistatic SANE_Int r_buf_lines; 877141cc406Sopenharmony_cistatic SANE_Int g_buf_lines; 878141cc406Sopenharmony_ci 879141cc406Sopenharmony_cistatic SANE_Status 880141cc406Sopenharmony_ciartec_buffer_line_offset (SANE_Handle handle, SANE_Int line_offset, 881141cc406Sopenharmony_ci SANE_Byte * data, size_t * len) 882141cc406Sopenharmony_ci{ 883141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 884141cc406Sopenharmony_ci static SANE_Int width; 885141cc406Sopenharmony_ci static SANE_Int cur_line; 886141cc406Sopenharmony_ci SANE_Byte *tmp_buf_ptr; 887141cc406Sopenharmony_ci SANE_Byte *grn_ptr; 888141cc406Sopenharmony_ci SANE_Byte *blu_ptr; 889141cc406Sopenharmony_ci SANE_Byte *out_ptr; 890141cc406Sopenharmony_ci int count; 891141cc406Sopenharmony_ci 892141cc406Sopenharmony_ci DBG (8, "artec_buffer_line_offset()\n"); 893141cc406Sopenharmony_ci 894141cc406Sopenharmony_ci if (*len == 0) 895141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 896141cc406Sopenharmony_ci 897141cc406Sopenharmony_ci if (tmp_line_buf == NULL) 898141cc406Sopenharmony_ci { 899141cc406Sopenharmony_ci width = *len / 3; 900141cc406Sopenharmony_ci cur_line = 0; 901141cc406Sopenharmony_ci 902141cc406Sopenharmony_ci DBG (9, "buffer_line_offset: offset = %d, len = %lu\n", 903141cc406Sopenharmony_ci line_offset, (u_long) * len); 904141cc406Sopenharmony_ci 905141cc406Sopenharmony_ci tmp_line_buf = malloc (*len); 906141cc406Sopenharmony_ci if (tmp_line_buf == NULL) 907141cc406Sopenharmony_ci { 908141cc406Sopenharmony_ci DBG (1, "couldn't allocate memory for temp line buffer\n"); 909141cc406Sopenharmony_ci return (SANE_STATUS_NO_MEM); 910141cc406Sopenharmony_ci } 911141cc406Sopenharmony_ci 912141cc406Sopenharmony_ci r_buf_lines = line_offset * 2; 913141cc406Sopenharmony_ci g_buf_lines = line_offset; 914141cc406Sopenharmony_ci 915141cc406Sopenharmony_ci line_buffer = malloc (r_buf_lines * sizeof (SANE_Byte *)); 916141cc406Sopenharmony_ci if (line_buffer == NULL) 917141cc406Sopenharmony_ci { 918141cc406Sopenharmony_ci DBG (1, "couldn't allocate memory for line buffer pointers\n"); 919141cc406Sopenharmony_ci return (SANE_STATUS_NO_MEM); 920141cc406Sopenharmony_ci } 921141cc406Sopenharmony_ci 922141cc406Sopenharmony_ci for (count = 0; count < r_buf_lines; count++) 923141cc406Sopenharmony_ci { 924141cc406Sopenharmony_ci line_buffer[count] = malloc ((*len) * sizeof (SANE_Byte)); 925141cc406Sopenharmony_ci if (line_buffer[count] == NULL) 926141cc406Sopenharmony_ci { 927141cc406Sopenharmony_ci DBG (1, "couldn't allocate memory for line buffer %d\n", 928141cc406Sopenharmony_ci count); 929141cc406Sopenharmony_ci return (SANE_STATUS_NO_MEM); 930141cc406Sopenharmony_ci } 931141cc406Sopenharmony_ci } 932141cc406Sopenharmony_ci 933141cc406Sopenharmony_ci DBG (9, "buffer_line_offset: r lines = %d, g lines = %d\n", 934141cc406Sopenharmony_ci r_buf_lines, g_buf_lines); 935141cc406Sopenharmony_ci } 936141cc406Sopenharmony_ci 937141cc406Sopenharmony_ci cur_line++; 938141cc406Sopenharmony_ci 939141cc406Sopenharmony_ci if (r_buf_lines > 0) 940141cc406Sopenharmony_ci { 941141cc406Sopenharmony_ci if (cur_line > r_buf_lines) 942141cc406Sopenharmony_ci { 943141cc406Sopenharmony_ci /* copy the Red and Green portions out of the buffer */ 944141cc406Sopenharmony_ci /* if scanner returns RRRRRRRRGGGGGGGGGBBBBBBBB format it's easier */ 945141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_RGB_CHAR_SHIFT) 946141cc406Sopenharmony_ci { 947141cc406Sopenharmony_ci /* get the red line info from r_buf_lines ago */ 948141cc406Sopenharmony_ci memcpy (tmp_line_buf, line_buffer[0], width); 949141cc406Sopenharmony_ci 950141cc406Sopenharmony_ci /* get the green line info from g_buf_lines ago */ 951141cc406Sopenharmony_ci memcpy (tmp_line_buf + width, &line_buffer[line_offset][width], 952141cc406Sopenharmony_ci width); 953141cc406Sopenharmony_ci } 954141cc406Sopenharmony_ci else 955141cc406Sopenharmony_ci { 956141cc406Sopenharmony_ci /* get the red line info from r_buf_lines ago as a whole line */ 957141cc406Sopenharmony_ci memcpy (tmp_line_buf, line_buffer[0], *len); 958141cc406Sopenharmony_ci 959141cc406Sopenharmony_ci /* scanner returns RGBRGBRGB format so we do a loop for green */ 960141cc406Sopenharmony_ci grn_ptr = &line_buffer[line_offset][1]; 961141cc406Sopenharmony_ci out_ptr = tmp_line_buf + 1; 962141cc406Sopenharmony_ci for (count = 0; count < width; count++) 963141cc406Sopenharmony_ci { 964141cc406Sopenharmony_ci *out_ptr = *grn_ptr; /* copy green pixel */ 965141cc406Sopenharmony_ci 966141cc406Sopenharmony_ci grn_ptr += 3; 967141cc406Sopenharmony_ci out_ptr += 3; 968141cc406Sopenharmony_ci } 969141cc406Sopenharmony_ci } 970141cc406Sopenharmony_ci } 971141cc406Sopenharmony_ci 972141cc406Sopenharmony_ci /* move all the buffered lines down (just move the ptrs for speed) */ 973141cc406Sopenharmony_ci tmp_buf_ptr = line_buffer[0]; 974141cc406Sopenharmony_ci for (count = 0; count < (r_buf_lines - 1); count++) 975141cc406Sopenharmony_ci { 976141cc406Sopenharmony_ci line_buffer[count] = line_buffer[count + 1]; 977141cc406Sopenharmony_ci } 978141cc406Sopenharmony_ci line_buffer[r_buf_lines - 1] = tmp_buf_ptr; 979141cc406Sopenharmony_ci 980141cc406Sopenharmony_ci /* insert the new line data at the end of our FIFO */ 981141cc406Sopenharmony_ci memcpy (line_buffer[r_buf_lines - 1], data, *len); 982141cc406Sopenharmony_ci 983141cc406Sopenharmony_ci if (cur_line > r_buf_lines) 984141cc406Sopenharmony_ci { 985141cc406Sopenharmony_ci /* copy the Red and Green portions out of the buffer */ 986141cc406Sopenharmony_ci /* if scanner returns RRRRRRRRGGGGGGGGGBBBBBBBB format it's easier */ 987141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_RGB_CHAR_SHIFT) 988141cc406Sopenharmony_ci { 989141cc406Sopenharmony_ci /* copy the red and green data in with the original blue */ 990141cc406Sopenharmony_ci memcpy (data, tmp_line_buf, width * 2); 991141cc406Sopenharmony_ci } 992141cc406Sopenharmony_ci else 993141cc406Sopenharmony_ci { 994141cc406Sopenharmony_ci /* scanner returns RGBRGBRGB format so we have to do a loop */ 995141cc406Sopenharmony_ci /* copy the blue data into our temp buffer then copy full */ 996141cc406Sopenharmony_ci /* temp buffer overtop of input data */ 997141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_IMAGE_REV_LR) 998141cc406Sopenharmony_ci { 999141cc406Sopenharmony_ci blu_ptr = data; 1000141cc406Sopenharmony_ci out_ptr = tmp_line_buf; 1001141cc406Sopenharmony_ci } 1002141cc406Sopenharmony_ci else 1003141cc406Sopenharmony_ci { 1004141cc406Sopenharmony_ci blu_ptr = data + 2; 1005141cc406Sopenharmony_ci out_ptr = tmp_line_buf + 2; 1006141cc406Sopenharmony_ci } 1007141cc406Sopenharmony_ci 1008141cc406Sopenharmony_ci for (count = 0; count < width; count++) 1009141cc406Sopenharmony_ci { 1010141cc406Sopenharmony_ci *out_ptr = *blu_ptr; /* copy blue pixel */ 1011141cc406Sopenharmony_ci 1012141cc406Sopenharmony_ci blu_ptr += 3; 1013141cc406Sopenharmony_ci out_ptr += 3; 1014141cc406Sopenharmony_ci } 1015141cc406Sopenharmony_ci 1016141cc406Sopenharmony_ci /* now just copy tmp_line_buf back over original data */ 1017141cc406Sopenharmony_ci memcpy (data, tmp_line_buf, *len); 1018141cc406Sopenharmony_ci } 1019141cc406Sopenharmony_ci } 1020141cc406Sopenharmony_ci else 1021141cc406Sopenharmony_ci { 1022141cc406Sopenharmony_ci /* if in the first r_buf_lines, then don't return anything */ 1023141cc406Sopenharmony_ci *len = 0; 1024141cc406Sopenharmony_ci } 1025141cc406Sopenharmony_ci } 1026141cc406Sopenharmony_ci 1027141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 1028141cc406Sopenharmony_ci} 1029141cc406Sopenharmony_ci 1030141cc406Sopenharmony_cistatic SANE_Status 1031141cc406Sopenharmony_ciartec_buffer_line_offset_free (void) 1032141cc406Sopenharmony_ci{ 1033141cc406Sopenharmony_ci int count; 1034141cc406Sopenharmony_ci 1035141cc406Sopenharmony_ci DBG (7, "artec_buffer_line_offset_free()\n"); 1036141cc406Sopenharmony_ci 1037141cc406Sopenharmony_ci free (tmp_line_buf); 1038141cc406Sopenharmony_ci tmp_line_buf = NULL; 1039141cc406Sopenharmony_ci 1040141cc406Sopenharmony_ci for (count = 0; count < r_buf_lines; count++) 1041141cc406Sopenharmony_ci { 1042141cc406Sopenharmony_ci free (line_buffer[count]); 1043141cc406Sopenharmony_ci } 1044141cc406Sopenharmony_ci free (line_buffer); 1045141cc406Sopenharmony_ci line_buffer = NULL; 1046141cc406Sopenharmony_ci 1047141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 1048141cc406Sopenharmony_ci} 1049141cc406Sopenharmony_ci 1050141cc406Sopenharmony_ci 1051141cc406Sopenharmony_ci#if 0 1052141cc406Sopenharmony_cistatic SANE_Status 1053141cc406Sopenharmony_ciartec_read_gamma_table (SANE_Handle handle) 1054141cc406Sopenharmony_ci{ 1055141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 1056141cc406Sopenharmony_ci char write_6[4096 + 20]; /* max gamma table is 4096 + 20 for command data */ 1057141cc406Sopenharmony_ci char *data; 1058141cc406Sopenharmony_ci char prt_buf[128]; 1059141cc406Sopenharmony_ci char tmp_buf[128]; 1060141cc406Sopenharmony_ci int i; 1061141cc406Sopenharmony_ci 1062141cc406Sopenharmony_ci DBG (7, "artec_read_gamma_table()\n"); 1063141cc406Sopenharmony_ci 1064141cc406Sopenharmony_ci memset (write_6, 0, sizeof (*write_6)); 1065141cc406Sopenharmony_ci 1066141cc406Sopenharmony_ci write_6[0] = 0x28; /* read data code */ 1067141cc406Sopenharmony_ci 1068141cc406Sopenharmony_ci /* FIXME: AT12 and AM12S use 0x0E for reading all channels of data */ 1069141cc406Sopenharmony_ci write_6[2] = 0x03; /* data type code "gamma data" */ 1070141cc406Sopenharmony_ci 1071141cc406Sopenharmony_ci write_6[6] = (s->gamma_length + 9) >> 16; 1072141cc406Sopenharmony_ci write_6[7] = (s->gamma_length + 9) >> 8; 1073141cc406Sopenharmony_ci write_6[8] = (s->gamma_length + 9); 1074141cc406Sopenharmony_ci 1075141cc406Sopenharmony_ci /* FIXME: AT12 and AM12S have one less byte so use 18 */ 1076141cc406Sopenharmony_ci if ((!strcmp (s->hw->sane.model, "AT12")) || 1077141cc406Sopenharmony_ci (!strcmp (s->hw->sane.model, "AM12S"))) 1078141cc406Sopenharmony_ci { 1079141cc406Sopenharmony_ci data = write_6 + 18; 1080141cc406Sopenharmony_ci } 1081141cc406Sopenharmony_ci else 1082141cc406Sopenharmony_ci { 1083141cc406Sopenharmony_ci data = write_6 + 19; 1084141cc406Sopenharmony_ci } 1085141cc406Sopenharmony_ci 1086141cc406Sopenharmony_ci /* FIXME: AT12 & AM12S ignore this, it's a reserved field */ 1087141cc406Sopenharmony_ci write_6[10] = 0x08; /* bitmask, bit 3 means mono type */ 1088141cc406Sopenharmony_ci 1089141cc406Sopenharmony_ci if (!s->val[OPT_CUSTOM_GAMMA].w) 1090141cc406Sopenharmony_ci { 1091141cc406Sopenharmony_ci write_6[11] = 1; /* internal gamma table #1 (hope this is default) */ 1092141cc406Sopenharmony_ci } 1093141cc406Sopenharmony_ci 1094141cc406Sopenharmony_ci DBG( 9, "Gamma Table\n" ); 1095141cc406Sopenharmony_ci DBG( 9, "==================================\n" ); 1096141cc406Sopenharmony_ci 1097141cc406Sopenharmony_ci prt_buf[0] = '\0'; 1098141cc406Sopenharmony_ci for (i = 0; i < s->gamma_length; i++) 1099141cc406Sopenharmony_ci { 1100141cc406Sopenharmony_ci if (DBG_LEVEL >= 9) 1101141cc406Sopenharmony_ci { 1102141cc406Sopenharmony_ci if (!(i % 16)) 1103141cc406Sopenharmony_ci { 1104141cc406Sopenharmony_ci if ( prt_buf[0] ) 1105141cc406Sopenharmony_ci { 1106141cc406Sopenharmony_ci strcat( prt_buf, "\n" ); 1107141cc406Sopenharmony_ci DBG( 9, "%s", prt_buf ); 1108141cc406Sopenharmony_ci } 1109141cc406Sopenharmony_ci sprintf (prt_buf, "%02x: ", i); 1110141cc406Sopenharmony_ci } 1111141cc406Sopenharmony_ci sprintf (tmp_buf, "%02x ", (int) s->gamma_table[0][i]); 1112141cc406Sopenharmony_ci strcat (prt_buf, tmp_buf ); 1113141cc406Sopenharmony_ci } 1114141cc406Sopenharmony_ci 1115141cc406Sopenharmony_ci data[i] = s->gamma_table[0][i]; 1116141cc406Sopenharmony_ci } 1117141cc406Sopenharmony_ci 1118141cc406Sopenharmony_ci if ( prt_buf[0] ) 1119141cc406Sopenharmony_ci { 1120141cc406Sopenharmony_ci strcat( prt_buf, "\n" ); 1121141cc406Sopenharmony_ci DBG( 9, "%s", prt_buf ); 1122141cc406Sopenharmony_ci } 1123141cc406Sopenharmony_ci 1124141cc406Sopenharmony_ci if ((!strcmp (s->hw->sane.model, "AT12")) || 1125141cc406Sopenharmony_ci (!strcmp (s->hw->sane.model, "AM12S"))) 1126141cc406Sopenharmony_ci { 1127141cc406Sopenharmony_ci return (sanei_scsi_cmd (s->fd, write_6, 10 + 8 + s->gamma_length, 0, 0)); 1128141cc406Sopenharmony_ci } 1129141cc406Sopenharmony_ci else 1130141cc406Sopenharmony_ci { 1131141cc406Sopenharmony_ci return (sanei_scsi_cmd (s->fd, write_6, 10 + 9 + s->gamma_length, 0, 0)); 1132141cc406Sopenharmony_ci } 1133141cc406Sopenharmony_ci} 1134141cc406Sopenharmony_ci#endif 1135141cc406Sopenharmony_ci 1136141cc406Sopenharmony_cistatic SANE_Status 1137141cc406Sopenharmony_ciartec_send_gamma_table (SANE_Handle handle) 1138141cc406Sopenharmony_ci{ 1139141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 1140141cc406Sopenharmony_ci char write_6[4096 + 20]; /* max gamma table is 4096 + 20 for command data */ 1141141cc406Sopenharmony_ci char *data; 1142141cc406Sopenharmony_ci char prt_buf[128]; 1143141cc406Sopenharmony_ci char tmp_buf[128]; 1144141cc406Sopenharmony_ci int i; 1145141cc406Sopenharmony_ci 1146141cc406Sopenharmony_ci DBG (7, "artec_send_gamma_table()\n"); 1147141cc406Sopenharmony_ci 1148141cc406Sopenharmony_ci memset (write_6, 0, sizeof (*write_6)); 1149141cc406Sopenharmony_ci 1150141cc406Sopenharmony_ci write_6[0] = 0x2a; /* send data code */ 1151141cc406Sopenharmony_ci 1152141cc406Sopenharmony_ci if (s->hw->setwindow_cmd_size > 55) 1153141cc406Sopenharmony_ci { 1154141cc406Sopenharmony_ci /* newer scanners support sending 3 channels of gamma, or populating all */ 1155141cc406Sopenharmony_ci /* 3 channels with same data by using code 0x0e */ 1156141cc406Sopenharmony_ci write_6[2] = 0x0e; 1157141cc406Sopenharmony_ci } 1158141cc406Sopenharmony_ci else 1159141cc406Sopenharmony_ci { 1160141cc406Sopenharmony_ci /* older scanners only support 1 channel of gamma data using code 0x3 */ 1161141cc406Sopenharmony_ci write_6[2] = 0x03; 1162141cc406Sopenharmony_ci } 1163141cc406Sopenharmony_ci 1164141cc406Sopenharmony_ci /* FIXME: AT12 & AM!2S ignore this, it's a reserved field */ 1165141cc406Sopenharmony_ci write_6[10] = 0x08; /* bitmask, bit 3 means mono type */ 1166141cc406Sopenharmony_ci 1167141cc406Sopenharmony_ci if (!s->val[OPT_CUSTOM_GAMMA].w) 1168141cc406Sopenharmony_ci { 1169141cc406Sopenharmony_ci write_6[6] = 9 >> 16; 1170141cc406Sopenharmony_ci write_6[7] = 9 >> 8; 1171141cc406Sopenharmony_ci write_6[8] = 9; 1172141cc406Sopenharmony_ci write_6[11] = 1; /* internal gamma table #1 (hope this is default) */ 1173141cc406Sopenharmony_ci 1174141cc406Sopenharmony_ci return (sanei_scsi_cmd (s->fd, write_6, 10 + 9, 0, 0)); 1175141cc406Sopenharmony_ci } 1176141cc406Sopenharmony_ci else 1177141cc406Sopenharmony_ci { 1178141cc406Sopenharmony_ci write_6[6] = (s->gamma_length + 9) >> 16; 1179141cc406Sopenharmony_ci write_6[7] = (s->gamma_length + 9) >> 8; 1180141cc406Sopenharmony_ci write_6[8] = (s->gamma_length + 9); 1181141cc406Sopenharmony_ci 1182141cc406Sopenharmony_ci DBG( 9, "Gamma Table\n" ); 1183141cc406Sopenharmony_ci DBG( 9, "==================================\n" ); 1184141cc406Sopenharmony_ci 1185141cc406Sopenharmony_ci /* FIXME: AT12 and AM12S have one less byte so use 18 */ 1186141cc406Sopenharmony_ci if ((!strcmp (s->hw->sane.model, "AT12")) || 1187141cc406Sopenharmony_ci (!strcmp (s->hw->sane.model, "AM12S"))) 1188141cc406Sopenharmony_ci { 1189141cc406Sopenharmony_ci data = write_6 + 18; 1190141cc406Sopenharmony_ci } 1191141cc406Sopenharmony_ci else 1192141cc406Sopenharmony_ci { 1193141cc406Sopenharmony_ci data = write_6 + 19; 1194141cc406Sopenharmony_ci } 1195141cc406Sopenharmony_ci 1196141cc406Sopenharmony_ci prt_buf[0] = '\0'; 1197141cc406Sopenharmony_ci for (i = 0; i < s->gamma_length; i++) 1198141cc406Sopenharmony_ci { 1199141cc406Sopenharmony_ci if (DBG_LEVEL >= 9) 1200141cc406Sopenharmony_ci { 1201141cc406Sopenharmony_ci if (!(i % 16)) 1202141cc406Sopenharmony_ci { 1203141cc406Sopenharmony_ci if ( prt_buf[0] ) 1204141cc406Sopenharmony_ci { 1205141cc406Sopenharmony_ci strcat( prt_buf, "\n" ); 1206141cc406Sopenharmony_ci DBG( 9, "%s", prt_buf ); 1207141cc406Sopenharmony_ci } 1208141cc406Sopenharmony_ci sprintf (prt_buf, "%02x: ", i); 1209141cc406Sopenharmony_ci } 1210141cc406Sopenharmony_ci sprintf (tmp_buf, "%02x ", (int) s->gamma_table[0][i]); 1211141cc406Sopenharmony_ci strcat (prt_buf, tmp_buf ); 1212141cc406Sopenharmony_ci } 1213141cc406Sopenharmony_ci 1214141cc406Sopenharmony_ci data[i] = s->gamma_table[0][i]; 1215141cc406Sopenharmony_ci } 1216141cc406Sopenharmony_ci 1217141cc406Sopenharmony_ci data[s->gamma_length - 1] = 0; 1218141cc406Sopenharmony_ci 1219141cc406Sopenharmony_ci if ( prt_buf[0] ) 1220141cc406Sopenharmony_ci { 1221141cc406Sopenharmony_ci strcat( prt_buf, "\n" ); 1222141cc406Sopenharmony_ci DBG( 9, "%s", prt_buf ); 1223141cc406Sopenharmony_ci } 1224141cc406Sopenharmony_ci 1225141cc406Sopenharmony_ci /* FIXME: AT12 and AM12S have one less byte so use 18 */ 1226141cc406Sopenharmony_ci if ((!strcmp (s->hw->sane.model, "AT12")) || 1227141cc406Sopenharmony_ci (!strcmp (s->hw->sane.model, "AM12S"))) 1228141cc406Sopenharmony_ci { 1229141cc406Sopenharmony_ci return (sanei_scsi_cmd (s->fd, write_6, 10 + 8 + s->gamma_length, 0, 0)); 1230141cc406Sopenharmony_ci } 1231141cc406Sopenharmony_ci else 1232141cc406Sopenharmony_ci { 1233141cc406Sopenharmony_ci return (sanei_scsi_cmd (s->fd, write_6, 10 + 9 + s->gamma_length, 0, 0)); 1234141cc406Sopenharmony_ci } 1235141cc406Sopenharmony_ci } 1236141cc406Sopenharmony_ci} 1237141cc406Sopenharmony_ci 1238141cc406Sopenharmony_cistatic SANE_Status 1239141cc406Sopenharmony_ciartec_set_scan_window (SANE_Handle handle) 1240141cc406Sopenharmony_ci{ 1241141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 1242141cc406Sopenharmony_ci char write_6[4096]; 1243141cc406Sopenharmony_ci unsigned char *data; 1244141cc406Sopenharmony_ci int counter; 1245141cc406Sopenharmony_ci int reversed_x; 1246141cc406Sopenharmony_ci int max_x; 1247141cc406Sopenharmony_ci 1248141cc406Sopenharmony_ci DBG (7, "artec_set_scan_window()\n"); 1249141cc406Sopenharmony_ci 1250141cc406Sopenharmony_ci /* 1251141cc406Sopenharmony_ci * if we can, start before the desired window since we have to throw away 1252141cc406Sopenharmony_ci * s->line_offset number of rows because of the RGB fixup. 1253141cc406Sopenharmony_ci */ 1254141cc406Sopenharmony_ci if ((s->line_offset) && 1255141cc406Sopenharmony_ci (s->tl_y) && 1256141cc406Sopenharmony_ci (s->tl_y >= (s->line_offset * 2))) 1257141cc406Sopenharmony_ci { 1258141cc406Sopenharmony_ci s->tl_y -= (s->line_offset * 2); 1259141cc406Sopenharmony_ci } 1260141cc406Sopenharmony_ci 1261141cc406Sopenharmony_ci data = (unsigned char *)write_6 + 10; 1262141cc406Sopenharmony_ci 1263141cc406Sopenharmony_ci DBG (5, "Scan window info:\n"); 1264141cc406Sopenharmony_ci DBG (5, " X resolution: %5d (%d-%d)\n", 1265141cc406Sopenharmony_ci s->x_resolution, ARTEC_MIN_X (s->hw), ARTEC_MAX_X (s->hw)); 1266141cc406Sopenharmony_ci DBG (5, " Y resolution: %5d (%d-%d)\n", 1267141cc406Sopenharmony_ci s->y_resolution, ARTEC_MIN_Y (s->hw), ARTEC_MAX_Y (s->hw)); 1268141cc406Sopenharmony_ci DBG (5, " TL_X (pixel): %5d\n", 1269141cc406Sopenharmony_ci s->tl_x); 1270141cc406Sopenharmony_ci DBG (5, " TL_Y (pixel): %5d\n", 1271141cc406Sopenharmony_ci s->tl_y); 1272141cc406Sopenharmony_ci DBG (5, " Width : %5d (%d-%d)\n", 1273141cc406Sopenharmony_ci s->params.pixels_per_line, 1274141cc406Sopenharmony_ci s->hw->x_range.min, 1275141cc406Sopenharmony_ci (int) ((SANE_UNFIX (s->hw->x_range.max) / MM_PER_INCH) * 1276141cc406Sopenharmony_ci s->x_resolution)); 1277141cc406Sopenharmony_ci DBG (5, " Height : %5d (%d-%d)\n", 1278141cc406Sopenharmony_ci s->params.lines, 1279141cc406Sopenharmony_ci s->hw->y_range.min, 1280141cc406Sopenharmony_ci (int) ((SANE_UNFIX (s->hw->y_range.max) / MM_PER_INCH) * 1281141cc406Sopenharmony_ci s->y_resolution)); 1282141cc406Sopenharmony_ci 1283141cc406Sopenharmony_ci DBG (5, " Image Comp. : %s\n", s->mode); 1284141cc406Sopenharmony_ci DBG (5, " Line Offset : %lu\n", (u_long) s->line_offset); 1285141cc406Sopenharmony_ci 1286141cc406Sopenharmony_ci memset (write_6, 0, 4096); 1287141cc406Sopenharmony_ci write_6[0] = 0x24; 1288141cc406Sopenharmony_ci write_6[8] = s->hw->setwindow_cmd_size; /* total size of command */ 1289141cc406Sopenharmony_ci 1290141cc406Sopenharmony_ci /* beginning of set window data header */ 1291141cc406Sopenharmony_ci /* actual SCSI command data byte count */ 1292141cc406Sopenharmony_ci data[7] = s->hw->setwindow_cmd_size - 8; 1293141cc406Sopenharmony_ci 1294141cc406Sopenharmony_ci /* x resolution */ 1295141cc406Sopenharmony_ci data[10] = s->x_resolution >> 8; 1296141cc406Sopenharmony_ci data[11] = s->x_resolution; 1297141cc406Sopenharmony_ci 1298141cc406Sopenharmony_ci /* y resolution */ 1299141cc406Sopenharmony_ci data[12] = s->y_resolution >> 8; 1300141cc406Sopenharmony_ci data[13] = s->y_resolution; 1301141cc406Sopenharmony_ci 1302141cc406Sopenharmony_ci if ( s->hw->flags & ARTEC_FLAG_REVERSE_WINDOW ) 1303141cc406Sopenharmony_ci { 1304141cc406Sopenharmony_ci /* top left X value */ 1305141cc406Sopenharmony_ci /* the select area is flipped across the page, so we have to do some */ 1306141cc406Sopenharmony_ci /* calculation here to get the real starting X value */ 1307141cc406Sopenharmony_ci max_x = (int) ((SANE_UNFIX (s->hw->x_range.max) / MM_PER_INCH) * 1308141cc406Sopenharmony_ci s->x_resolution); 1309141cc406Sopenharmony_ci reversed_x = max_x - s->tl_x - s->params.pixels_per_line; 1310141cc406Sopenharmony_ci 1311141cc406Sopenharmony_ci data[14] = reversed_x >> 24; 1312141cc406Sopenharmony_ci data[15] = reversed_x >> 16; 1313141cc406Sopenharmony_ci data[16] = reversed_x >> 8; 1314141cc406Sopenharmony_ci data[17] = reversed_x; 1315141cc406Sopenharmony_ci } 1316141cc406Sopenharmony_ci else 1317141cc406Sopenharmony_ci { 1318141cc406Sopenharmony_ci /* top left X value */ 1319141cc406Sopenharmony_ci data[14] = s->tl_x >> 24; 1320141cc406Sopenharmony_ci data[15] = s->tl_x >> 16; 1321141cc406Sopenharmony_ci data[16] = s->tl_x >> 8; 1322141cc406Sopenharmony_ci data[17] = s->tl_x; 1323141cc406Sopenharmony_ci } 1324141cc406Sopenharmony_ci 1325141cc406Sopenharmony_ci /* top left Y value */ 1326141cc406Sopenharmony_ci data[18] = s->tl_y >> 24; 1327141cc406Sopenharmony_ci data[19] = s->tl_y >> 16; 1328141cc406Sopenharmony_ci data[20] = s->tl_y >> 8; 1329141cc406Sopenharmony_ci data[21] = s->tl_y; 1330141cc406Sopenharmony_ci 1331141cc406Sopenharmony_ci 1332141cc406Sopenharmony_ci /* width */ 1333141cc406Sopenharmony_ci data[22] = s->params.pixels_per_line >> 24; 1334141cc406Sopenharmony_ci data[23] = s->params.pixels_per_line >> 16; 1335141cc406Sopenharmony_ci data[24] = s->params.pixels_per_line >> 8; 1336141cc406Sopenharmony_ci data[25] = s->params.pixels_per_line; 1337141cc406Sopenharmony_ci 1338141cc406Sopenharmony_ci /* height */ 1339141cc406Sopenharmony_ci data[26] = (s->params.lines + (s->line_offset * 2)) >> 24; 1340141cc406Sopenharmony_ci data[27] = (s->params.lines + (s->line_offset * 2)) >> 16; 1341141cc406Sopenharmony_ci data[28] = (s->params.lines + (s->line_offset * 2)) >> 8; 1342141cc406Sopenharmony_ci data[29] = (s->params.lines + (s->line_offset * 2)); 1343141cc406Sopenharmony_ci 1344141cc406Sopenharmony_ci /* misc. single-byte settings */ 1345141cc406Sopenharmony_ci /* brightness */ 1346141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_OPT_BRIGHTNESS) 1347141cc406Sopenharmony_ci data[30] = s->val[OPT_BRIGHTNESS].w; 1348141cc406Sopenharmony_ci 1349141cc406Sopenharmony_ci data[31] = s->val[OPT_THRESHOLD].w; /* threshold */ 1350141cc406Sopenharmony_ci 1351141cc406Sopenharmony_ci /* contrast */ 1352141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_OPT_CONTRAST) 1353141cc406Sopenharmony_ci data[32] = s->val[OPT_CONTRAST].w; 1354141cc406Sopenharmony_ci 1355141cc406Sopenharmony_ci /* 1356141cc406Sopenharmony_ci * byte 33 is mode 1357141cc406Sopenharmony_ci * byte 37 bit 7 is "negative" setting 1358141cc406Sopenharmony_ci */ 1359141cc406Sopenharmony_ci if (strcmp (s->mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) 1360141cc406Sopenharmony_ci { 1361141cc406Sopenharmony_ci data[33] = ARTEC_COMP_LINEART; 1362141cc406Sopenharmony_ci data[37] = (s->val[OPT_NEGATIVE].w == SANE_TRUE) ? 0x0 : 0x80; 1363141cc406Sopenharmony_ci } 1364141cc406Sopenharmony_ci else if (strcmp (s->mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) 1365141cc406Sopenharmony_ci { 1366141cc406Sopenharmony_ci data[33] = ARTEC_COMP_HALFTONE; 1367141cc406Sopenharmony_ci data[37] = (s->val[OPT_NEGATIVE].w == SANE_TRUE) ? 0x0 : 0x80; 1368141cc406Sopenharmony_ci } 1369141cc406Sopenharmony_ci else if (strcmp (s->mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) 1370141cc406Sopenharmony_ci { 1371141cc406Sopenharmony_ci data[33] = ARTEC_COMP_GRAY; 1372141cc406Sopenharmony_ci data[37] = (s->val[OPT_NEGATIVE].w == SANE_TRUE) ? 0x80 : 0x0; 1373141cc406Sopenharmony_ci } 1374141cc406Sopenharmony_ci else if (strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) 1375141cc406Sopenharmony_ci { 1376141cc406Sopenharmony_ci data[33] = ARTEC_COMP_COLOR; 1377141cc406Sopenharmony_ci data[37] = (s->val[OPT_NEGATIVE].w == SANE_TRUE) ? 0x80 : 0x0; 1378141cc406Sopenharmony_ci } 1379141cc406Sopenharmony_ci 1380141cc406Sopenharmony_ci data[34] = s->params.depth; /* bits per pixel */ 1381141cc406Sopenharmony_ci 1382141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_HALFTONE_PATTERN) 1383141cc406Sopenharmony_ci { 1384141cc406Sopenharmony_ci data[35] = artec_get_str_index (halftone_pattern_list, 1385141cc406Sopenharmony_ci s->val[OPT_HALFTONE_PATTERN].s); /* halftone pattern */ 1386141cc406Sopenharmony_ci } 1387141cc406Sopenharmony_ci 1388141cc406Sopenharmony_ci /* user supplied halftone pattern not supported for now so override with */ 1389141cc406Sopenharmony_ci /* 8x8 Bayer */ 1390141cc406Sopenharmony_ci if (data[35] == 0) 1391141cc406Sopenharmony_ci { 1392141cc406Sopenharmony_ci data[35] = 4; 1393141cc406Sopenharmony_ci } 1394141cc406Sopenharmony_ci 1395141cc406Sopenharmony_ci /* NOTE: AT12 doesn't support mono according to docs. */ 1396141cc406Sopenharmony_ci data[48] = artec_get_str_index (filter_type_list, 1397141cc406Sopenharmony_ci s->val[OPT_FILTER_TYPE].s); /* filter mode */ 1398141cc406Sopenharmony_ci 1399141cc406Sopenharmony_ci if (s->hw->setwindow_cmd_size > 55) 1400141cc406Sopenharmony_ci { 1401141cc406Sopenharmony_ci data[48] = 0x2; /* DB filter type green for AT12,see above */ 1402141cc406Sopenharmony_ci 1403141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_SC_BUFFERS_LINES) 1404141cc406Sopenharmony_ci { 1405141cc406Sopenharmony_ci /* FIXME: guessing at this value, use formula instead */ 1406141cc406Sopenharmony_ci data[55] = 0x00; /* buffer full line count */ 1407141cc406Sopenharmony_ci data[56] = 0x00; /* buffer full line count */ 1408141cc406Sopenharmony_ci data[57] = 0x00; /* buffer full line count */ 1409141cc406Sopenharmony_ci data[58] = 0x0a; /* buffer full line count */ 1410141cc406Sopenharmony_ci 1411141cc406Sopenharmony_ci /* FIXME: guessing at this value, use formula instead */ 1412141cc406Sopenharmony_ci data[59] = 0x00; /* access line count */ 1413141cc406Sopenharmony_ci data[60] = 0x00; /* access line count */ 1414141cc406Sopenharmony_ci data[61] = 0x00; /* access line count */ 1415141cc406Sopenharmony_ci data[62] = 0x0a; /* access line count */ 1416141cc406Sopenharmony_ci } 1417141cc406Sopenharmony_ci 1418141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_SC_HANDLES_OFFSET) 1419141cc406Sopenharmony_ci { 1420141cc406Sopenharmony_ci /* DB : following fields : high order bit (0x80) is enable */ 1421141cc406Sopenharmony_ci /* scanner handles line offset fixup, 0 = driver handles */ 1422141cc406Sopenharmony_ci data[63] = 0x80; 1423141cc406Sopenharmony_ci } 1424141cc406Sopenharmony_ci 1425141cc406Sopenharmony_ci if ((s->hw->flags & ARTEC_FLAG_PIXEL_AVERAGING) && 1426141cc406Sopenharmony_ci (s->val[OPT_PIXEL_AVG].w)) 1427141cc406Sopenharmony_ci { 1428141cc406Sopenharmony_ci /* enable pixel average function */ 1429141cc406Sopenharmony_ci data[64] = 0x80; 1430141cc406Sopenharmony_ci } 1431141cc406Sopenharmony_ci else 1432141cc406Sopenharmony_ci { 1433141cc406Sopenharmony_ci /* disable pixel average function */ 1434141cc406Sopenharmony_ci data[64] = 0; 1435141cc406Sopenharmony_ci } 1436141cc406Sopenharmony_ci 1437141cc406Sopenharmony_ci if ((s->hw->flags & ARTEC_FLAG_ENHANCE_LINE_EDGE) && 1438141cc406Sopenharmony_ci (s->val[OPT_EDGE_ENH].w)) 1439141cc406Sopenharmony_ci { 1440141cc406Sopenharmony_ci /* enable lineart edge enhancement function */ 1441141cc406Sopenharmony_ci data[65] = 0x80; 1442141cc406Sopenharmony_ci } 1443141cc406Sopenharmony_ci else 1444141cc406Sopenharmony_ci { 1445141cc406Sopenharmony_ci /* disable lineart edge enhancement function */ 1446141cc406Sopenharmony_ci data[65] = 0; 1447141cc406Sopenharmony_ci } 1448141cc406Sopenharmony_ci 1449141cc406Sopenharmony_ci /* data is R-G-B format, 0x80 = G-B-R format (reversed) */ 1450141cc406Sopenharmony_ci data[66] = 0; 1451141cc406Sopenharmony_ci } 1452141cc406Sopenharmony_ci 1453141cc406Sopenharmony_ci DBG (50, "Set Window data : \n"); 1454141cc406Sopenharmony_ci for (counter = 0; counter < s->hw->setwindow_cmd_size; counter++) 1455141cc406Sopenharmony_ci { 1456141cc406Sopenharmony_ci DBG (50, " byte %2d = %02x \n", counter, data[counter] & 0xff); /* DB */ 1457141cc406Sopenharmony_ci } 1458141cc406Sopenharmony_ci DBG (50, "\n"); 1459141cc406Sopenharmony_ci 1460141cc406Sopenharmony_ci /* set the scan window */ 1461141cc406Sopenharmony_ci return (sanei_scsi_cmd (s->fd, write_6, 10 + 1462141cc406Sopenharmony_ci s->hw->setwindow_cmd_size, 0, 0)); 1463141cc406Sopenharmony_ci} 1464141cc406Sopenharmony_ci 1465141cc406Sopenharmony_cistatic SANE_Status 1466141cc406Sopenharmony_ciartec_start_scan (SANE_Handle handle) 1467141cc406Sopenharmony_ci{ 1468141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 1469141cc406Sopenharmony_ci char write_7[7]; 1470141cc406Sopenharmony_ci 1471141cc406Sopenharmony_ci DBG (7, "artec_start_scan()\n"); 1472141cc406Sopenharmony_ci 1473141cc406Sopenharmony_ci /* setup cmd to start scanning */ 1474141cc406Sopenharmony_ci memset (write_7, 0, 7); 1475141cc406Sopenharmony_ci write_7[0] = 0x1b; /* code to start scan */ 1476141cc406Sopenharmony_ci 1477141cc406Sopenharmony_ci /* FIXME: need to make this a flag */ 1478141cc406Sopenharmony_ci if (!strcmp (s->hw->sane.model, "AM12S")) 1479141cc406Sopenharmony_ci { 1480141cc406Sopenharmony_ci /* start the scan */ 1481141cc406Sopenharmony_ci return (sanei_scsi_cmd (s->fd, write_7, 6, 0, 0)); 1482141cc406Sopenharmony_ci } 1483141cc406Sopenharmony_ci else 1484141cc406Sopenharmony_ci { 1485141cc406Sopenharmony_ci write_7[4] = 0x01; /* need to send 1 data byte */ 1486141cc406Sopenharmony_ci 1487141cc406Sopenharmony_ci /* start the scan */ 1488141cc406Sopenharmony_ci return (sanei_scsi_cmd (s->fd, write_7, 7, 0, 0)); 1489141cc406Sopenharmony_ci } 1490141cc406Sopenharmony_ci} 1491141cc406Sopenharmony_ci 1492141cc406Sopenharmony_cistatic SANE_Status 1493141cc406Sopenharmony_ciartec_software_rgb_calibrate (SANE_Handle handle, SANE_Byte * buf, int lines) 1494141cc406Sopenharmony_ci{ 1495141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 1496141cc406Sopenharmony_ci int line, i, loop, offset; 1497141cc406Sopenharmony_ci 1498141cc406Sopenharmony_ci DBG (7, "artec_software_rgb_calibrate()\n"); 1499141cc406Sopenharmony_ci 1500141cc406Sopenharmony_ci for (line = 0; line < lines; line++) 1501141cc406Sopenharmony_ci { 1502141cc406Sopenharmony_ci i = 0; 1503141cc406Sopenharmony_ci offset = 0; 1504141cc406Sopenharmony_ci 1505141cc406Sopenharmony_ci if (s->x_resolution == 200) 1506141cc406Sopenharmony_ci { 1507141cc406Sopenharmony_ci /* skip ever 3rd byte, -= causes us to go down in count */ 1508141cc406Sopenharmony_ci if ((s->tl_x % 3) == 0) 1509141cc406Sopenharmony_ci offset -= 1; 1510141cc406Sopenharmony_ci } 1511141cc406Sopenharmony_ci else 1512141cc406Sopenharmony_ci { 1513141cc406Sopenharmony_ci /* round down to the previous pixel */ 1514141cc406Sopenharmony_ci offset += ((s->tl_x / (300 / s->x_resolution)) * 1515141cc406Sopenharmony_ci (300 / s->x_resolution)); 1516141cc406Sopenharmony_ci } 1517141cc406Sopenharmony_ci 1518141cc406Sopenharmony_ci for (loop = 0; loop < s->params.pixels_per_line; loop++) 1519141cc406Sopenharmony_ci { 1520141cc406Sopenharmony_ci if ((DBG_LEVEL == 100) && 1521141cc406Sopenharmony_ci (loop < 100)) 1522141cc406Sopenharmony_ci { 1523141cc406Sopenharmony_ci DBG (100, " %2d-%4d R (%4d,%4d): %d * %5.2f = %d\n", 1524141cc406Sopenharmony_ci line, loop, i, offset, buf[i], 1525141cc406Sopenharmony_ci s->soft_calibrate_data[ARTEC_SOFT_CALIB_RED][offset], 1526141cc406Sopenharmony_ci (int) (buf[i] * 1527141cc406Sopenharmony_ci s->soft_calibrate_data[ARTEC_SOFT_CALIB_RED][offset])); 1528141cc406Sopenharmony_ci } 1529141cc406Sopenharmony_ci buf[i] = buf[i] * 1530141cc406Sopenharmony_ci s->soft_calibrate_data[ARTEC_SOFT_CALIB_RED][offset]; 1531141cc406Sopenharmony_ci i++; 1532141cc406Sopenharmony_ci 1533141cc406Sopenharmony_ci if ((DBG_LEVEL == 100) && 1534141cc406Sopenharmony_ci (loop < 100)) 1535141cc406Sopenharmony_ci { 1536141cc406Sopenharmony_ci DBG (100, " G (%4d,%4d): %d * %5.2f = %d\n", 1537141cc406Sopenharmony_ci i, offset, buf[i], 1538141cc406Sopenharmony_ci s->soft_calibrate_data[ARTEC_SOFT_CALIB_GREEN][offset], 1539141cc406Sopenharmony_ci (int) (buf[i] * 1540141cc406Sopenharmony_ci s->soft_calibrate_data[ARTEC_SOFT_CALIB_GREEN][offset])); 1541141cc406Sopenharmony_ci } 1542141cc406Sopenharmony_ci buf[i] = buf[i] * 1543141cc406Sopenharmony_ci s->soft_calibrate_data[ARTEC_SOFT_CALIB_GREEN][offset]; 1544141cc406Sopenharmony_ci i++; 1545141cc406Sopenharmony_ci 1546141cc406Sopenharmony_ci if ((DBG_LEVEL == 100) && 1547141cc406Sopenharmony_ci (loop < 100)) 1548141cc406Sopenharmony_ci { 1549141cc406Sopenharmony_ci DBG (100, " B (%4d,%4d): %d * %5.2f = %d\n", 1550141cc406Sopenharmony_ci i, offset, buf[i], 1551141cc406Sopenharmony_ci s->soft_calibrate_data[ARTEC_SOFT_CALIB_BLUE][offset], 1552141cc406Sopenharmony_ci (int) (buf[i] * 1553141cc406Sopenharmony_ci s->soft_calibrate_data[ARTEC_SOFT_CALIB_BLUE][offset])); 1554141cc406Sopenharmony_ci } 1555141cc406Sopenharmony_ci buf[i] = buf[i] * 1556141cc406Sopenharmony_ci s->soft_calibrate_data[ARTEC_SOFT_CALIB_BLUE][offset]; 1557141cc406Sopenharmony_ci i++; 1558141cc406Sopenharmony_ci 1559141cc406Sopenharmony_ci if (s->x_resolution == 200) 1560141cc406Sopenharmony_ci { 1561141cc406Sopenharmony_ci offset += 1; 1562141cc406Sopenharmony_ci 1563141cc406Sopenharmony_ci /* skip every 3rd byte */ 1564141cc406Sopenharmony_ci if (((offset + 1) % 3) == 0) 1565141cc406Sopenharmony_ci offset += 1; 1566141cc406Sopenharmony_ci } 1567141cc406Sopenharmony_ci else 1568141cc406Sopenharmony_ci { 1569141cc406Sopenharmony_ci offset += (300 / s->x_resolution); 1570141cc406Sopenharmony_ci } 1571141cc406Sopenharmony_ci } 1572141cc406Sopenharmony_ci } 1573141cc406Sopenharmony_ci 1574141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 1575141cc406Sopenharmony_ci} 1576141cc406Sopenharmony_ci 1577141cc406Sopenharmony_cistatic SANE_Status 1578141cc406Sopenharmony_ciartec_calibrate_shading (SANE_Handle handle) 1579141cc406Sopenharmony_ci{ 1580141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 1581141cc406Sopenharmony_ci SANE_Status status; /* DB added */ 1582141cc406Sopenharmony_ci u_char buf[76800]; /* should be big enough */ 1583141cc406Sopenharmony_ci size_t len; 1584141cc406Sopenharmony_ci SANE_Word save_x_resolution; 1585141cc406Sopenharmony_ci SANE_Word save_pixels_per_line; 1586141cc406Sopenharmony_ci int i; 1587141cc406Sopenharmony_ci 1588141cc406Sopenharmony_ci DBG (7, "artec_calibrate_shading()\n"); 1589141cc406Sopenharmony_ci 1590141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_CALIBRATE_RGB) 1591141cc406Sopenharmony_ci { 1592141cc406Sopenharmony_ci /* this method scans in 4 lines each of Red, Green, and Blue */ 1593141cc406Sopenharmony_ci /* after reading line of shading data, generate data for software */ 1594141cc406Sopenharmony_ci /* calibration so we have it if user requests */ 1595141cc406Sopenharmony_ci len = 4 * 2592; /* 4 lines of data, 2592 pixels wide */ 1596141cc406Sopenharmony_ci 1597141cc406Sopenharmony_ci if ( DBG_LEVEL == 100 ) 1598141cc406Sopenharmony_ci DBG (100, "RED Software Calibration data\n"); 1599141cc406Sopenharmony_ci 1600141cc406Sopenharmony_ci read_data (s->fd, ARTEC_DATA_RED_SHADING, buf, &len); 1601141cc406Sopenharmony_ci for (i = 0; i < 2592; i++) 1602141cc406Sopenharmony_ci { 1603141cc406Sopenharmony_ci s->soft_calibrate_data[ARTEC_SOFT_CALIB_RED][i] = 1604141cc406Sopenharmony_ci 255.0 / ((buf[i] + buf[i + 2592] + buf[i + 5184] + buf[i + 7776]) / 4); 1605141cc406Sopenharmony_ci if (DBG_LEVEL == 100) 1606141cc406Sopenharmony_ci { 1607141cc406Sopenharmony_ci DBG (100, 1608141cc406Sopenharmony_ci " %4d: 255.0 / (( %3d + %3d + %3d + %3d ) / 4 ) = %5.2f\n", 1609141cc406Sopenharmony_ci i, buf[i], buf[i + 2592], buf[i + 5184], buf[i + 7776], 1610141cc406Sopenharmony_ci s->soft_calibrate_data[ARTEC_SOFT_CALIB_RED][i]); 1611141cc406Sopenharmony_ci } 1612141cc406Sopenharmony_ci } 1613141cc406Sopenharmony_ci 1614141cc406Sopenharmony_ci if (DBG_LEVEL == 100) 1615141cc406Sopenharmony_ci { 1616141cc406Sopenharmony_ci DBG (100, "GREEN Software Calibration data\n"); 1617141cc406Sopenharmony_ci } 1618141cc406Sopenharmony_ci 1619141cc406Sopenharmony_ci read_data (s->fd, ARTEC_DATA_GREEN_SHADING, buf, &len); 1620141cc406Sopenharmony_ci for (i = 0; i < 2592; i++) 1621141cc406Sopenharmony_ci { 1622141cc406Sopenharmony_ci s->soft_calibrate_data[ARTEC_SOFT_CALIB_GREEN][i] = 1623141cc406Sopenharmony_ci 255.0 / ((buf[i] + buf[i + 2592] + buf[i + 5184] + buf[i + 7776]) / 4); 1624141cc406Sopenharmony_ci if (DBG_LEVEL == 100) 1625141cc406Sopenharmony_ci { 1626141cc406Sopenharmony_ci DBG (100, 1627141cc406Sopenharmony_ci " %4d: 255.0 / (( %3d + %3d + %3d + %3d ) / 4 ) = %5.2f\n", 1628141cc406Sopenharmony_ci i, buf[i], buf[i + 2592], buf[i + 5184], buf[i + 7776], 1629141cc406Sopenharmony_ci s->soft_calibrate_data[ARTEC_SOFT_CALIB_GREEN][i]); 1630141cc406Sopenharmony_ci } 1631141cc406Sopenharmony_ci } 1632141cc406Sopenharmony_ci 1633141cc406Sopenharmony_ci if (DBG_LEVEL == 100) 1634141cc406Sopenharmony_ci { 1635141cc406Sopenharmony_ci DBG (100, "BLUE Software Calibration data\n"); 1636141cc406Sopenharmony_ci } 1637141cc406Sopenharmony_ci 1638141cc406Sopenharmony_ci read_data (s->fd, ARTEC_DATA_BLUE_SHADING, buf, &len); 1639141cc406Sopenharmony_ci for (i = 0; i < 2592; i++) 1640141cc406Sopenharmony_ci { 1641141cc406Sopenharmony_ci s->soft_calibrate_data[ARTEC_SOFT_CALIB_BLUE][i] = 1642141cc406Sopenharmony_ci 255.0 / ((buf[i] + buf[i + 2592] + buf[i + 5184] + buf[i + 7776]) / 4); 1643141cc406Sopenharmony_ci if (DBG_LEVEL == 100) 1644141cc406Sopenharmony_ci { 1645141cc406Sopenharmony_ci DBG (100, 1646141cc406Sopenharmony_ci " %4d: 255.0 / (( %3d + %3d + %3d + %3d ) / 4 ) = %5.2f\n", 1647141cc406Sopenharmony_ci i, buf[i], buf[i + 2592], buf[i + 5184], buf[i + 7776], 1648141cc406Sopenharmony_ci s->soft_calibrate_data[ARTEC_SOFT_CALIB_BLUE][i]); 1649141cc406Sopenharmony_ci } 1650141cc406Sopenharmony_ci } 1651141cc406Sopenharmony_ci } 1652141cc406Sopenharmony_ci else if (s->hw->flags & ARTEC_FLAG_CALIBRATE_DARK_WHITE) 1653141cc406Sopenharmony_ci { 1654141cc406Sopenharmony_ci /* this method scans black, then white data */ 1655141cc406Sopenharmony_ci len = 3 * 5100; /* 1 line of data, 5100 pixels wide, RGB data */ 1656141cc406Sopenharmony_ci read_data (s->fd, ARTEC_DATA_DARK_SHADING, buf, &len); 1657141cc406Sopenharmony_ci save_x_resolution = s->x_resolution; 1658141cc406Sopenharmony_ci s->x_resolution = 600; 1659141cc406Sopenharmony_ci save_pixels_per_line = s->params.pixels_per_line; 1660141cc406Sopenharmony_ci s->params.pixels_per_line = ARTEC_MAX_X (s->hw); 1661141cc406Sopenharmony_ci s->params.pixels_per_line = 600 * 8.5; /* ?this? or ?above line? */ 1662141cc406Sopenharmony_ci /* DB added wait_ready */ 1663141cc406Sopenharmony_ci status = wait_ready (s->fd); 1664141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1665141cc406Sopenharmony_ci { 1666141cc406Sopenharmony_ci DBG (1, "wait for scanner ready failed: %s\n", sane_strstatus (status)); 1667141cc406Sopenharmony_ci return status; 1668141cc406Sopenharmony_ci } 1669141cc406Sopenharmony_ci /* next line should use ARTEC_DATA_WHITE_SHADING_TRANS if using ADF */ 1670141cc406Sopenharmony_ci read_data (s->fd, ARTEC_DATA_WHITE_SHADING_OPT, buf, &len); 1671141cc406Sopenharmony_ci s->x_resolution = save_x_resolution; 1672141cc406Sopenharmony_ci s->params.pixels_per_line = save_pixels_per_line; 1673141cc406Sopenharmony_ci } 1674141cc406Sopenharmony_ci 1675141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 1676141cc406Sopenharmony_ci} 1677141cc406Sopenharmony_ci 1678141cc406Sopenharmony_ci 1679141cc406Sopenharmony_cistatic SANE_Status 1680141cc406Sopenharmony_ciend_scan (SANE_Handle handle) 1681141cc406Sopenharmony_ci{ 1682141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 1683141cc406Sopenharmony_ci /* DB 1684141cc406Sopenharmony_ci uint8_t write_6[6] = 1685141cc406Sopenharmony_ci {0x1B, 0, 0, 0, 0, 0}; 1686141cc406Sopenharmony_ci */ 1687141cc406Sopenharmony_ci 1688141cc406Sopenharmony_ci DBG (7, "end_scan()\n"); 1689141cc406Sopenharmony_ci 1690141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 1691141cc406Sopenharmony_ci 1692141cc406Sopenharmony_ci/* if (s->this_pass == 3) */ 1693141cc406Sopenharmony_ci s->this_pass = 0; 1694141cc406Sopenharmony_ci 1695141cc406Sopenharmony_ci if ((s->hw->flags & ARTEC_FLAG_RGB_LINE_OFFSET) && 1696141cc406Sopenharmony_ci (tmp_line_buf != NULL)) 1697141cc406Sopenharmony_ci { 1698141cc406Sopenharmony_ci artec_buffer_line_offset_free (); 1699141cc406Sopenharmony_ci } 1700141cc406Sopenharmony_ci 1701141cc406Sopenharmony_ci /* DB 1702141cc406Sopenharmony_ci return (sanei_scsi_cmd (s->fd, write_6, 6, 0, 0)); 1703141cc406Sopenharmony_ci */ 1704141cc406Sopenharmony_ci return abort_scan (s); 1705141cc406Sopenharmony_ci} 1706141cc406Sopenharmony_ci 1707141cc406Sopenharmony_ci 1708141cc406Sopenharmony_cistatic SANE_Status 1709141cc406Sopenharmony_ciartec_get_cap_data (ARTEC_Device * dev, int fd) 1710141cc406Sopenharmony_ci{ 1711141cc406Sopenharmony_ci int cap_model, loop; 1712141cc406Sopenharmony_ci u_char cap_buf[256]; /* buffer for cap data */ 1713141cc406Sopenharmony_ci 1714141cc406Sopenharmony_ci DBG (7, "artec_get_cap_data()\n"); 1715141cc406Sopenharmony_ci 1716141cc406Sopenharmony_ci /* DB always use the hard-coded capability info first 1717141cc406Sopenharmony_ci * if we get cap data from the scanner, we override */ 1718141cc406Sopenharmony_ci cap_model = -1; 1719141cc406Sopenharmony_ci for (loop = 0; loop < NELEMS (cap_data); loop++) 1720141cc406Sopenharmony_ci { 1721141cc406Sopenharmony_ci if (strcmp (cap_data[loop].model, dev->sane.model) == 0) 1722141cc406Sopenharmony_ci { 1723141cc406Sopenharmony_ci cap_model = loop; 1724141cc406Sopenharmony_ci } 1725141cc406Sopenharmony_ci } 1726141cc406Sopenharmony_ci 1727141cc406Sopenharmony_ci if (cap_model == -1) 1728141cc406Sopenharmony_ci { 1729141cc406Sopenharmony_ci DBG (1, "unable to identify Artec model '%s', check artec.c\n", 1730141cc406Sopenharmony_ci dev->sane.model); 1731141cc406Sopenharmony_ci return (SANE_STATUS_UNSUPPORTED); 1732141cc406Sopenharmony_ci } 1733141cc406Sopenharmony_ci 1734141cc406Sopenharmony_ci dev->x_range.min = 0; 1735141cc406Sopenharmony_ci dev->x_range.max = SANE_FIX (cap_data[cap_model].width) * MM_PER_INCH; 1736141cc406Sopenharmony_ci dev->x_range.quant = 1; 1737141cc406Sopenharmony_ci 1738141cc406Sopenharmony_ci dev->width = cap_data[cap_model].width; 1739141cc406Sopenharmony_ci 1740141cc406Sopenharmony_ci dev->y_range.min = 0; 1741141cc406Sopenharmony_ci dev->y_range.max = SANE_FIX (cap_data[cap_model].height) * MM_PER_INCH; 1742141cc406Sopenharmony_ci dev->y_range.quant = 1; 1743141cc406Sopenharmony_ci 1744141cc406Sopenharmony_ci dev->height = cap_data[cap_model].height; 1745141cc406Sopenharmony_ci 1746141cc406Sopenharmony_ci artec_str_list_to_word_list (&dev->horz_resolution_list, 1747141cc406Sopenharmony_ci cap_data[cap_model].horz_resolution_str); 1748141cc406Sopenharmony_ci 1749141cc406Sopenharmony_ci artec_str_list_to_word_list (&dev->vert_resolution_list, 1750141cc406Sopenharmony_ci cap_data[cap_model].vert_resolution_str); 1751141cc406Sopenharmony_ci 1752141cc406Sopenharmony_ci dev->contrast_range.min = 0; 1753141cc406Sopenharmony_ci dev->contrast_range.max = 255; 1754141cc406Sopenharmony_ci dev->contrast_range.quant = 1; 1755141cc406Sopenharmony_ci 1756141cc406Sopenharmony_ci dev->brightness_range.min = 0; 1757141cc406Sopenharmony_ci dev->brightness_range.max = 255; 1758141cc406Sopenharmony_ci dev->brightness_range.quant = 1; 1759141cc406Sopenharmony_ci 1760141cc406Sopenharmony_ci dev->threshold_range.min = 0; 1761141cc406Sopenharmony_ci dev->threshold_range.max = 255; 1762141cc406Sopenharmony_ci dev->threshold_range.quant = 1; 1763141cc406Sopenharmony_ci 1764141cc406Sopenharmony_ci dev->sane.type = cap_data[cap_model].type; 1765141cc406Sopenharmony_ci 1766141cc406Sopenharmony_ci dev->max_read_size = cap_data[cap_model].max_read_size; 1767141cc406Sopenharmony_ci 1768141cc406Sopenharmony_ci dev->flags = cap_data[cap_model].flags; 1769141cc406Sopenharmony_ci 1770141cc406Sopenharmony_ci switch (cap_data[cap_model].adc_bits) 1771141cc406Sopenharmony_ci { 1772141cc406Sopenharmony_ci case 8: 1773141cc406Sopenharmony_ci dev->gamma_length = 256; 1774141cc406Sopenharmony_ci break; 1775141cc406Sopenharmony_ci 1776141cc406Sopenharmony_ci case 10: 1777141cc406Sopenharmony_ci dev->gamma_length = 1024; 1778141cc406Sopenharmony_ci break; 1779141cc406Sopenharmony_ci 1780141cc406Sopenharmony_ci case 12: 1781141cc406Sopenharmony_ci dev->gamma_length = 4096; 1782141cc406Sopenharmony_ci break; 1783141cc406Sopenharmony_ci } 1784141cc406Sopenharmony_ci 1785141cc406Sopenharmony_ci dev->setwindow_cmd_size = cap_data[cap_model].setwindow_cmd_size; 1786141cc406Sopenharmony_ci 1787141cc406Sopenharmony_ci if (dev->support_cap_data_retrieve) /* DB */ 1788141cc406Sopenharmony_ci { 1789141cc406Sopenharmony_ci /* DB added reading capability data from scanner */ 1790141cc406Sopenharmony_ci char info[80]; /* for printing debugging info */ 1791141cc406Sopenharmony_ci size_t len = sizeof (cap_buf); 1792141cc406Sopenharmony_ci 1793141cc406Sopenharmony_ci /* read the capability data from the scanner */ 1794141cc406Sopenharmony_ci DBG (9, "reading capability data from scanner...\n"); 1795141cc406Sopenharmony_ci 1796141cc406Sopenharmony_ci wait_ready (fd); 1797141cc406Sopenharmony_ci 1798141cc406Sopenharmony_ci read_data (fd, ARTEC_DATA_CAPABILITY_DATA, cap_buf, &len); 1799141cc406Sopenharmony_ci 1800141cc406Sopenharmony_ci DBG (50, "scanner capability data : \n"); 1801141cc406Sopenharmony_ci strncpy (info, (const char *) &cap_buf[0], 8); 1802141cc406Sopenharmony_ci info[8] = '\0'; 1803141cc406Sopenharmony_ci DBG (50, " Vendor : %s\n", info); 1804141cc406Sopenharmony_ci strncpy (info, (const char *) &cap_buf[8], 16); 1805141cc406Sopenharmony_ci info[16] = '\0'; 1806141cc406Sopenharmony_ci DBG (50, " Device Name : %s\n", info); 1807141cc406Sopenharmony_ci strncpy (info, (const char *) &cap_buf[24], 4); 1808141cc406Sopenharmony_ci info[4] = '\0'; 1809141cc406Sopenharmony_ci DBG (50, " Version Number : %s\n", info); 1810141cc406Sopenharmony_ci sprintf (info, "%d ", cap_buf[29]); 1811141cc406Sopenharmony_ci DBG (50, " CCD Type : %s\n", info); 1812141cc406Sopenharmony_ci sprintf (info, "%d ", cap_buf[30]); 1813141cc406Sopenharmony_ci DBG (50, " AD Converter Type : %s\n", info); 1814141cc406Sopenharmony_ci sprintf (info, "%d ", (cap_buf[31] << 8) | cap_buf[32]); 1815141cc406Sopenharmony_ci DBG (50, " Buffer size : %s\n", info); 1816141cc406Sopenharmony_ci sprintf (info, "%d ", cap_buf[33]); 1817141cc406Sopenharmony_ci DBG (50, " Channels of RGB Gamma : %s\n", info); 1818141cc406Sopenharmony_ci sprintf (info, "%d ", (cap_buf[34] << 8) | cap_buf[35]); 1819141cc406Sopenharmony_ci DBG (50, " Opt. res. of R channel : %s\n", info); 1820141cc406Sopenharmony_ci sprintf (info, "%d ", (cap_buf[36] << 8) | cap_buf[37]); 1821141cc406Sopenharmony_ci DBG (50, " Opt. res. of G channel : %s\n", info); 1822141cc406Sopenharmony_ci sprintf (info, "%d ", (cap_buf[38] << 8) | cap_buf[39]); 1823141cc406Sopenharmony_ci DBG (50, " Opt. res. of B channel : %s\n", info); 1824141cc406Sopenharmony_ci sprintf (info, "%d ", (cap_buf[40] << 8) | cap_buf[41]); 1825141cc406Sopenharmony_ci DBG (50, " Min. Hor. Resolution : %s\n", info); 1826141cc406Sopenharmony_ci sprintf (info, "%d ", (cap_buf[42] << 8) | cap_buf[43]); 1827141cc406Sopenharmony_ci DBG (50, " Max. Vert. Resolution : %s\n", info); 1828141cc406Sopenharmony_ci sprintf (info, "%d ", (cap_buf[44] << 8) | cap_buf[45]); 1829141cc406Sopenharmony_ci DBG (50, " Min. Vert. Resolution : %s\n", info); 1830141cc406Sopenharmony_ci sprintf (info, "%s ", cap_buf[46] == 0x80 ? "yes" : "no"); 1831141cc406Sopenharmony_ci DBG (50, " Chunky Data Format : %s\n", info); 1832141cc406Sopenharmony_ci sprintf (info, "%s ", cap_buf[47] == 0x80 ? "yes" : "no"); 1833141cc406Sopenharmony_ci DBG (50, " RGB Data Format : %s\n", info); 1834141cc406Sopenharmony_ci sprintf (info, "%s ", cap_buf[48] == 0x80 ? "yes" : "no"); 1835141cc406Sopenharmony_ci DBG (50, " BGR Data Format : %s\n", info); 1836141cc406Sopenharmony_ci sprintf (info, "%d ", cap_buf[49]); 1837141cc406Sopenharmony_ci DBG (50, " Line Offset : %s\n", info); 1838141cc406Sopenharmony_ci sprintf (info, "%s ", cap_buf[50] == 0x80 ? "yes" : "no"); 1839141cc406Sopenharmony_ci DBG (50, " Channel Valid Sequence : %s\n", info); 1840141cc406Sopenharmony_ci sprintf (info, "%s ", cap_buf[51] == 0x80 ? "yes" : "no"); 1841141cc406Sopenharmony_ci DBG (50, " True Gray : %s\n", info); 1842141cc406Sopenharmony_ci sprintf (info, "%s ", cap_buf[52] == 0x80 ? "yes" : "no"); 1843141cc406Sopenharmony_ci DBG (50, " Force Host Not Do Shading : %s\n", info); 1844141cc406Sopenharmony_ci sprintf (info, "%s ", cap_buf[53] == 0x00 ? "AT006" : "AT010"); 1845141cc406Sopenharmony_ci DBG (50, " ASIC : %s\n", info); 1846141cc406Sopenharmony_ci sprintf (info, "%s ", cap_buf[54] == 0x82 ? "SCSI2" : 1847141cc406Sopenharmony_ci cap_buf[54] == 0x81 ? "SCSI1" : "Parallel"); 1848141cc406Sopenharmony_ci DBG (50, " Interface : %s\n", info); 1849141cc406Sopenharmony_ci sprintf (info, "%d ", (cap_buf[55] << 8) | cap_buf[56]); 1850141cc406Sopenharmony_ci DBG (50, " Phys. Area Width : %s\n", info); 1851141cc406Sopenharmony_ci sprintf (info, "%d ", (cap_buf[57] << 8) | cap_buf[58]); 1852141cc406Sopenharmony_ci DBG (50, " Phys. Area Length : %s\n", info); 1853141cc406Sopenharmony_ci 1854141cc406Sopenharmony_ci /* fill in the information we've got from the scanner */ 1855141cc406Sopenharmony_ci 1856141cc406Sopenharmony_ci dev->width = ((float) ((cap_buf[55] << 8) | cap_buf[56])) / 1000; 1857141cc406Sopenharmony_ci dev->height = ((float) ((cap_buf[57] << 8) | cap_buf[58])) / 1000; 1858141cc406Sopenharmony_ci 1859141cc406Sopenharmony_ci /* DB ----- */ 1860141cc406Sopenharmony_ci } 1861141cc406Sopenharmony_ci 1862141cc406Sopenharmony_ci DBG (9, "Scanner capability info.\n"); 1863141cc406Sopenharmony_ci DBG (9, " Vendor : %s\n", dev->sane.vendor); 1864141cc406Sopenharmony_ci DBG (9, " Model : %s\n", dev->sane.model); 1865141cc406Sopenharmony_ci DBG (9, " Type : %s\n", dev->sane.type); 1866141cc406Sopenharmony_ci DBG (5, " Width : %.2f inches\n", dev->width); 1867141cc406Sopenharmony_ci DBG (9, " Height : %.2f inches\n", dev->height); 1868141cc406Sopenharmony_ci DBG (9, " X Range(mm) : %d-%d\n", 1869141cc406Sopenharmony_ci dev->x_range.min, 1870141cc406Sopenharmony_ci (int) (SANE_UNFIX (dev->x_range.max))); 1871141cc406Sopenharmony_ci DBG (9, " Y Range(mm) : %d-%d\n", 1872141cc406Sopenharmony_ci dev->y_range.min, 1873141cc406Sopenharmony_ci (int) (SANE_UNFIX (dev->y_range.max))); 1874141cc406Sopenharmony_ci 1875141cc406Sopenharmony_ci DBG (9, " Horz. DPI : %d-%d\n", ARTEC_MIN_X (dev), ARTEC_MAX_X (dev)); 1876141cc406Sopenharmony_ci DBG (9, " Vert. DPI : %d-%d\n", ARTEC_MIN_Y (dev), ARTEC_MAX_Y (dev)); 1877141cc406Sopenharmony_ci DBG (9, " Contrast : %d-%d\n", 1878141cc406Sopenharmony_ci dev->contrast_range.min, dev->contrast_range.max); 1879141cc406Sopenharmony_ci DBG (9, " REQ Sh. Cal.: %d\n", 1880141cc406Sopenharmony_ci dev->flags & ARTEC_FLAG_CALIBRATE ? 1 : 0); 1881141cc406Sopenharmony_ci DBG (9, " REQ Ln. Offs: %d\n", 1882141cc406Sopenharmony_ci dev->flags & ARTEC_FLAG_RGB_LINE_OFFSET ? 1 : 0); 1883141cc406Sopenharmony_ci DBG (9, " REQ Ch. Shft: %d\n", 1884141cc406Sopenharmony_ci dev->flags & ARTEC_FLAG_RGB_CHAR_SHIFT ? 1 : 0); 1885141cc406Sopenharmony_ci DBG (9, " SetWind Size: %d\n", 1886141cc406Sopenharmony_ci dev->setwindow_cmd_size); 1887141cc406Sopenharmony_ci DBG (9, " Calib Method: %s\n", 1888141cc406Sopenharmony_ci dev->flags & ARTEC_FLAG_CALIBRATE_RGB ? "RGB" : 1889141cc406Sopenharmony_ci dev->flags & ARTEC_FLAG_CALIBRATE_DARK_WHITE ? "white/black" : "N/A"); 1890141cc406Sopenharmony_ci 1891141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 1892141cc406Sopenharmony_ci} 1893141cc406Sopenharmony_ci 1894141cc406Sopenharmony_cistatic SANE_Status 1895141cc406Sopenharmony_cidump_inquiry (unsigned char *result) 1896141cc406Sopenharmony_ci{ 1897141cc406Sopenharmony_ci int i; 1898141cc406Sopenharmony_ci int j; 1899141cc406Sopenharmony_ci char prt_buf[129] = ""; 1900141cc406Sopenharmony_ci char tmp_buf[129]; 1901141cc406Sopenharmony_ci 1902141cc406Sopenharmony_ci DBG (4, "dump_inquiry()\n"); 1903141cc406Sopenharmony_ci 1904141cc406Sopenharmony_ci DBG (4, " === SANE/Artec backend v%d.%d.%d ===\n", 1905141cc406Sopenharmony_ci ARTEC_MAJOR, ARTEC_MINOR, ARTEC_SUB); 1906141cc406Sopenharmony_ci DBG (4, " ===== Scanner Inquiry Block =====\n"); 1907141cc406Sopenharmony_ci for (i = 0; i < 96; i += 16) 1908141cc406Sopenharmony_ci { 1909141cc406Sopenharmony_ci sprintf (prt_buf, "0x%02x: ", i); 1910141cc406Sopenharmony_ci for (j = 0; j < 16; j++) 1911141cc406Sopenharmony_ci { 1912141cc406Sopenharmony_ci sprintf (tmp_buf, "%02x ", (int) result[i + j]); 1913141cc406Sopenharmony_ci strcat( prt_buf, tmp_buf ); 1914141cc406Sopenharmony_ci } 1915141cc406Sopenharmony_ci strcat( prt_buf, " "); 1916141cc406Sopenharmony_ci for (j = 0; j < 16; j++) 1917141cc406Sopenharmony_ci { 1918141cc406Sopenharmony_ci sprintf (tmp_buf, "%c", 1919141cc406Sopenharmony_ci isprint (result[i + j]) ? result[i + j] : '.'); 1920141cc406Sopenharmony_ci strcat( prt_buf, tmp_buf ); 1921141cc406Sopenharmony_ci } 1922141cc406Sopenharmony_ci strcat( prt_buf, "\n" ); 1923141cc406Sopenharmony_ci DBG(4, "%s", prt_buf ); 1924141cc406Sopenharmony_ci } 1925141cc406Sopenharmony_ci 1926141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 1927141cc406Sopenharmony_ci} 1928141cc406Sopenharmony_ci 1929141cc406Sopenharmony_cistatic SANE_Status 1930141cc406Sopenharmony_ciattach (const char *devname, ARTEC_Device ** devp) 1931141cc406Sopenharmony_ci{ 1932141cc406Sopenharmony_ci char result[INQ_LEN]; 1933141cc406Sopenharmony_ci char product_revision[5]; 1934141cc406Sopenharmony_ci char temp_result[33]; 1935141cc406Sopenharmony_ci char *str, *t; 1936141cc406Sopenharmony_ci int fd; 1937141cc406Sopenharmony_ci SANE_Status status; 1938141cc406Sopenharmony_ci ARTEC_Device *dev; 1939141cc406Sopenharmony_ci size_t size; 1940141cc406Sopenharmony_ci 1941141cc406Sopenharmony_ci DBG (7, "attach()\n"); 1942141cc406Sopenharmony_ci 1943141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 1944141cc406Sopenharmony_ci { 1945141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devname) == 0) 1946141cc406Sopenharmony_ci { 1947141cc406Sopenharmony_ci if (devp) 1948141cc406Sopenharmony_ci *devp = dev; 1949141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 1950141cc406Sopenharmony_ci } 1951141cc406Sopenharmony_ci } 1952141cc406Sopenharmony_ci 1953141cc406Sopenharmony_ci DBG (6, "attach: opening %s\n", devname); 1954141cc406Sopenharmony_ci 1955141cc406Sopenharmony_ci status = sanei_scsi_open (devname, &fd, sense_handler, NULL); 1956141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1957141cc406Sopenharmony_ci { 1958141cc406Sopenharmony_ci DBG (1, "attach: open failed (%s)\n", sane_strstatus (status)); 1959141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 1960141cc406Sopenharmony_ci } 1961141cc406Sopenharmony_ci 1962141cc406Sopenharmony_ci DBG (6, "attach: sending INQUIRY\n"); 1963141cc406Sopenharmony_ci size = sizeof (result); 1964141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, inquiry, sizeof (inquiry), result, &size); 1965141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD || size < 16) 1966141cc406Sopenharmony_ci { 1967141cc406Sopenharmony_ci DBG (1, "attach: inquiry failed (%s)\n", sane_strstatus (status)); 1968141cc406Sopenharmony_ci sanei_scsi_close (fd); 1969141cc406Sopenharmony_ci return (status); 1970141cc406Sopenharmony_ci } 1971141cc406Sopenharmony_ci 1972141cc406Sopenharmony_ci /* 1973141cc406Sopenharmony_ci * Check to see if this device is a scanner. 1974141cc406Sopenharmony_ci */ 1975141cc406Sopenharmony_ci if (result[0] != 0x6) 1976141cc406Sopenharmony_ci { 1977141cc406Sopenharmony_ci DBG (1, "attach: device doesn't look like a scanner at all.\n"); 1978141cc406Sopenharmony_ci sanei_scsi_close (fd); 1979141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 1980141cc406Sopenharmony_ci } 1981141cc406Sopenharmony_ci 1982141cc406Sopenharmony_ci /* 1983141cc406Sopenharmony_ci * The BlackWidow BW4800SP is actually a rebadged AT3, with the vendor 1984141cc406Sopenharmony_ci * string set to 8 spaces and the product to "Flatbed Scanner ". So, 1985141cc406Sopenharmony_ci * if we have one of these, we'll make it look like an AT3. 1986141cc406Sopenharmony_ci * 1987141cc406Sopenharmony_ci * For now, to be on the safe side, we'll also check the version number 1988141cc406Sopenharmony_ci * since BlackWidow seems to have left that intact as "1.90". 1989141cc406Sopenharmony_ci * 1990141cc406Sopenharmony_ci * Check that result[36] == 0x00 so we don't mistake a microtek scanner. 1991141cc406Sopenharmony_ci */ 1992141cc406Sopenharmony_ci if ((result[36] == 0x00) && 1993141cc406Sopenharmony_ci (strncmp (result + 32, "1.90", 4) == 0) && 1994141cc406Sopenharmony_ci (strncmp (result + 8, " ", 8) == 0) && 1995141cc406Sopenharmony_ci (strncmp (result + 16, "Flatbed Scanner ", 16) == 0)) 1996141cc406Sopenharmony_ci { 1997141cc406Sopenharmony_ci DBG (6, "Found BlackWidow BW4800SP scanner, setting up like AT3\n"); 1998141cc406Sopenharmony_ci 1999141cc406Sopenharmony_ci /* setup the vendor and product to mimic the Artec/Ultima AT3 */ 2000141cc406Sopenharmony_ci memcpy (result + 8, "ULTIMA", 6); 2001141cc406Sopenharmony_ci memcpy (result + 16, "AT3 ", 16); 2002141cc406Sopenharmony_ci } 2003141cc406Sopenharmony_ci 2004141cc406Sopenharmony_ci /* 2005141cc406Sopenharmony_ci * The Plustek 19200S is actually a rebadged AM12S, with the vendor string 2006141cc406Sopenharmony_ci * set to 8 spaces. 2007141cc406Sopenharmony_ci */ 2008141cc406Sopenharmony_ci if ((strncmp (result + 8, " ", 8) == 0) && 2009141cc406Sopenharmony_ci (strncmp (result + 16, "SCAN19200 ", 16) == 0)) 2010141cc406Sopenharmony_ci { 2011141cc406Sopenharmony_ci DBG (6, "Found Plustek 19200S scanner, setting up like AM12S\n"); 2012141cc406Sopenharmony_ci 2013141cc406Sopenharmony_ci /* setup the vendor and product to mimic the Artec/Ultima AM12S */ 2014141cc406Sopenharmony_ci memcpy (result + 8, "ULTIMA", 6); 2015141cc406Sopenharmony_ci memcpy (result + 16, "AM12S ", 16); 2016141cc406Sopenharmony_ci } 2017141cc406Sopenharmony_ci 2018141cc406Sopenharmony_ci /* 2019141cc406Sopenharmony_ci * Check to see if they have forced a vendor and/or model string and 2020141cc406Sopenharmony_ci * if so, fudge the inquiry results with that info. We do this right 2021141cc406Sopenharmony_ci * before we check the inquiry results, otherwise we might not be forcing 2022141cc406Sopenharmony_ci * anything. 2023141cc406Sopenharmony_ci */ 2024141cc406Sopenharmony_ci if (artec_vendor[0] != 0x0) 2025141cc406Sopenharmony_ci { 2026141cc406Sopenharmony_ci /* 2027141cc406Sopenharmony_ci * 1) copy the vendor string to our temp variable 2028141cc406Sopenharmony_ci * 2) append 8 spaces to make sure we have at least 8 characters 2029141cc406Sopenharmony_ci * 3) copy our fudged vendor string into the inquiry result. 2030141cc406Sopenharmony_ci */ 2031141cc406Sopenharmony_ci strcpy (temp_result, artec_vendor); 2032141cc406Sopenharmony_ci strcat (temp_result, " "); 2033141cc406Sopenharmony_ci strncpy (result + 8, temp_result, 8); 2034141cc406Sopenharmony_ci } 2035141cc406Sopenharmony_ci 2036141cc406Sopenharmony_ci if (artec_model[0] != 0x0) 2037141cc406Sopenharmony_ci { 2038141cc406Sopenharmony_ci /* 2039141cc406Sopenharmony_ci * 1) copy the model string to our temp variable 2040141cc406Sopenharmony_ci * 2) append 16 spaces to make sure we have at least 16 characters 2041141cc406Sopenharmony_ci * 3) copy our fudged model string into the inquiry result. 2042141cc406Sopenharmony_ci */ 2043141cc406Sopenharmony_ci strcpy (temp_result, artec_model); 2044141cc406Sopenharmony_ci strcat (temp_result, " "); 2045141cc406Sopenharmony_ci strncpy (result + 16, temp_result, 16); 2046141cc406Sopenharmony_ci } 2047141cc406Sopenharmony_ci 2048141cc406Sopenharmony_ci /* are we really dealing with a scanner by ULTIMA/ARTEC? */ 2049141cc406Sopenharmony_ci if ((strncmp (result + 8, "ULTIMA", 6) != 0) && 2050141cc406Sopenharmony_ci (strncmp (result + 8, "ARTEC", 5) != 0)) 2051141cc406Sopenharmony_ci { 2052141cc406Sopenharmony_ci DBG (1, "attach: device doesn't look like a Artec/ULTIMA scanner\n"); 2053141cc406Sopenharmony_ci 2054141cc406Sopenharmony_ci strncpy (temp_result, result + 8, 8); 2055141cc406Sopenharmony_ci temp_result[8] = 0x0; 2056141cc406Sopenharmony_ci DBG (1, "attach: FOUND vendor = '%s'\n", temp_result); 2057141cc406Sopenharmony_ci strncpy (temp_result, result + 16, 16); 2058141cc406Sopenharmony_ci temp_result[16] = 0x0; 2059141cc406Sopenharmony_ci DBG (1, "attach: FOUND model = '%s'\n", temp_result); 2060141cc406Sopenharmony_ci 2061141cc406Sopenharmony_ci sanei_scsi_close (fd); 2062141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 2063141cc406Sopenharmony_ci } 2064141cc406Sopenharmony_ci 2065141cc406Sopenharmony_ci /* turn this wait OFF for now since it appears to cause problems with */ 2066141cc406Sopenharmony_ci /* AT12 models */ 2067141cc406Sopenharmony_ci /* turned off by creating an "if" that can never be true */ 2068141cc406Sopenharmony_ci if ( 1 == 2 ) { 2069141cc406Sopenharmony_ci DBG (6, "attach: wait for scanner to come ready\n"); 2070141cc406Sopenharmony_ci status = wait_ready (fd); 2071141cc406Sopenharmony_ci 2072141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2073141cc406Sopenharmony_ci { 2074141cc406Sopenharmony_ci DBG (1, "attach: test unit ready failed (%s)\n", 2075141cc406Sopenharmony_ci sane_strstatus (status)); 2076141cc406Sopenharmony_ci sanei_scsi_close (fd); 2077141cc406Sopenharmony_ci return (status); 2078141cc406Sopenharmony_ci } 2079141cc406Sopenharmony_ci /* This is the end of the "if" that can never be true that in effect */ 2080141cc406Sopenharmony_ci /* comments out this wait_ready() call */ 2081141cc406Sopenharmony_ci } 2082141cc406Sopenharmony_ci /* end of "if( 1 == 2 )" */ 2083141cc406Sopenharmony_ci 2084141cc406Sopenharmony_ci dev = malloc (sizeof (*dev)); 2085141cc406Sopenharmony_ci if (!dev) 2086141cc406Sopenharmony_ci return (SANE_STATUS_NO_MEM); 2087141cc406Sopenharmony_ci 2088141cc406Sopenharmony_ci memset (dev, 0, sizeof (*dev)); 2089141cc406Sopenharmony_ci 2090141cc406Sopenharmony_ci if (DBG_LEVEL >= 4) 2091141cc406Sopenharmony_ci dump_inquiry ((unsigned char *) result); 2092141cc406Sopenharmony_ci 2093141cc406Sopenharmony_ci dev->sane.name = strdup (devname); 2094141cc406Sopenharmony_ci 2095141cc406Sopenharmony_ci /* get the model info */ 2096141cc406Sopenharmony_ci str = malloc (17); 2097141cc406Sopenharmony_ci memcpy (str, result + 16, 16); 2098141cc406Sopenharmony_ci str[16] = ' '; 2099141cc406Sopenharmony_ci t = str + 16; 2100141cc406Sopenharmony_ci while ((*t == ' ') && (t > str)) 2101141cc406Sopenharmony_ci { 2102141cc406Sopenharmony_ci *t = '\0'; 2103141cc406Sopenharmony_ci t--; 2104141cc406Sopenharmony_ci } 2105141cc406Sopenharmony_ci dev->sane.model = str; 2106141cc406Sopenharmony_ci 2107141cc406Sopenharmony_ci /* for some reason, the firmware revision is in the model info string on */ 2108141cc406Sopenharmony_ci /* the A6000C PLUS scanners instead of in it's proper place */ 2109141cc406Sopenharmony_ci if (strstr (str, "A6000C PLUS") == str) 2110141cc406Sopenharmony_ci { 2111141cc406Sopenharmony_ci str[11] = '\0'; 2112141cc406Sopenharmony_ci strncpy (product_revision, str + 12, 4); 2113141cc406Sopenharmony_ci } 2114141cc406Sopenharmony_ci else if (strstr (str, "AT3") == str) 2115141cc406Sopenharmony_ci { 2116141cc406Sopenharmony_ci str[3] = '\0'; 2117141cc406Sopenharmony_ci strncpy (product_revision, str + 8, 4); 2118141cc406Sopenharmony_ci } 2119141cc406Sopenharmony_ci else 2120141cc406Sopenharmony_ci { 2121141cc406Sopenharmony_ci /* get the product revision from it's normal place */ 2122141cc406Sopenharmony_ci strncpy (product_revision, result + 32, 4); 2123141cc406Sopenharmony_ci } 2124141cc406Sopenharmony_ci product_revision[4] = ' '; 2125141cc406Sopenharmony_ci t = strchr (product_revision, ' '); 2126141cc406Sopenharmony_ci if (t) 2127141cc406Sopenharmony_ci *t = '\0'; 2128141cc406Sopenharmony_ci else 2129141cc406Sopenharmony_ci t = "unknown revision"; 2130141cc406Sopenharmony_ci 2131141cc406Sopenharmony_ci /* get the vendor info */ 2132141cc406Sopenharmony_ci str = malloc (9); 2133141cc406Sopenharmony_ci memcpy (str, result + 8, 8); 2134141cc406Sopenharmony_ci str[8] = ' '; 2135141cc406Sopenharmony_ci t = strchr (str, ' '); 2136141cc406Sopenharmony_ci *t = '\0'; 2137141cc406Sopenharmony_ci dev->sane.vendor = str; 2138141cc406Sopenharmony_ci 2139141cc406Sopenharmony_ci DBG (5, "scanner vendor: '%s', model: '%s', revision: '%s'\n", 2140141cc406Sopenharmony_ci dev->sane.vendor, dev->sane.model, product_revision); 2141141cc406Sopenharmony_ci 2142141cc406Sopenharmony_ci /* Artec docs say if bytes 36-43 = "ULTIMA ", then supports read cap. data */ 2143141cc406Sopenharmony_ci if (strncmp (result + 36, "ULTIMA ", 8) == 0) 2144141cc406Sopenharmony_ci { 2145141cc406Sopenharmony_ci DBG (5, "scanner supports read capability data function\n"); 2146141cc406Sopenharmony_ci dev->support_cap_data_retrieve = SANE_TRUE; 2147141cc406Sopenharmony_ci } 2148141cc406Sopenharmony_ci else 2149141cc406Sopenharmony_ci { 2150141cc406Sopenharmony_ci DBG (5, "scanner does NOT support read capability data function\n"); 2151141cc406Sopenharmony_ci dev->support_cap_data_retrieve = SANE_FALSE; 2152141cc406Sopenharmony_ci } 2153141cc406Sopenharmony_ci 2154141cc406Sopenharmony_ci DBG (6, "attach: getting scanner capability data\n"); 2155141cc406Sopenharmony_ci status = artec_get_cap_data (dev, fd); 2156141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2157141cc406Sopenharmony_ci { 2158141cc406Sopenharmony_ci DBG (1, "attach: artec_get_cap_data failed (%s)\n", 2159141cc406Sopenharmony_ci sane_strstatus (status)); 2160141cc406Sopenharmony_ci sanei_scsi_close (fd); 2161141cc406Sopenharmony_ci return (status); 2162141cc406Sopenharmony_ci } 2163141cc406Sopenharmony_ci 2164141cc406Sopenharmony_ci sanei_scsi_close (fd); 2165141cc406Sopenharmony_ci 2166141cc406Sopenharmony_ci ++num_devices; 2167141cc406Sopenharmony_ci dev->next = first_dev; 2168141cc406Sopenharmony_ci first_dev = dev; 2169141cc406Sopenharmony_ci 2170141cc406Sopenharmony_ci if (devp) 2171141cc406Sopenharmony_ci *devp = dev; 2172141cc406Sopenharmony_ci 2173141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2174141cc406Sopenharmony_ci} 2175141cc406Sopenharmony_ci 2176141cc406Sopenharmony_cistatic SANE_Status 2177141cc406Sopenharmony_ciinit_options (ARTEC_Scanner * s) 2178141cc406Sopenharmony_ci{ 2179141cc406Sopenharmony_ci int i; 2180141cc406Sopenharmony_ci 2181141cc406Sopenharmony_ci DBG (7, "init_options()\n"); 2182141cc406Sopenharmony_ci 2183141cc406Sopenharmony_ci memset (s->opt, 0, sizeof (s->opt)); 2184141cc406Sopenharmony_ci memset (s->val, 0, sizeof (s->val)); 2185141cc406Sopenharmony_ci 2186141cc406Sopenharmony_ci for (i = 0; i < NUM_OPTIONS; ++i) 2187141cc406Sopenharmony_ci { 2188141cc406Sopenharmony_ci s->opt[i].size = sizeof (SANE_Word); 2189141cc406Sopenharmony_ci s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 2190141cc406Sopenharmony_ci } 2191141cc406Sopenharmony_ci 2192141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 2193141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 2194141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 2195141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 2196141cc406Sopenharmony_ci s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; 2197141cc406Sopenharmony_ci 2198141cc406Sopenharmony_ci /* "Mode" group: */ 2199141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].title = "Scan Mode"; 2200141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].desc = ""; 2201141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 2202141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].cap = 0; 2203141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2204141cc406Sopenharmony_ci 2205141cc406Sopenharmony_ci /* scan mode */ 2206141cc406Sopenharmony_ci s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; 2207141cc406Sopenharmony_ci s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 2208141cc406Sopenharmony_ci s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 2209141cc406Sopenharmony_ci s->opt[OPT_MODE].type = SANE_TYPE_STRING; 2210141cc406Sopenharmony_ci s->opt[OPT_MODE].size = max_string_size (mode_list); 2211141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2212141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint.string_list = mode_list; 2213141cc406Sopenharmony_ci s->val[OPT_MODE].s = strdup (mode_list[3]); 2214141cc406Sopenharmony_ci 2215141cc406Sopenharmony_ci /* horizontal resolution */ 2216141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 2217141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 2218141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 2219141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].type = SANE_TYPE_INT; 2220141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].unit = SANE_UNIT_DPI; 2221141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; 2222141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].constraint.word_list = s->hw->horz_resolution_list; 2223141cc406Sopenharmony_ci s->val[OPT_X_RESOLUTION].w = 100; 2224141cc406Sopenharmony_ci 2225141cc406Sopenharmony_ci /* vertical resolution */ 2226141cc406Sopenharmony_ci s->opt[OPT_Y_RESOLUTION].name = SANE_NAME_SCAN_Y_RESOLUTION; 2227141cc406Sopenharmony_ci s->opt[OPT_Y_RESOLUTION].title = SANE_TITLE_SCAN_Y_RESOLUTION; 2228141cc406Sopenharmony_ci s->opt[OPT_Y_RESOLUTION].desc = SANE_DESC_SCAN_Y_RESOLUTION; 2229141cc406Sopenharmony_ci s->opt[OPT_Y_RESOLUTION].type = SANE_TYPE_INT; 2230141cc406Sopenharmony_ci s->opt[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI; 2231141cc406Sopenharmony_ci s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; 2232141cc406Sopenharmony_ci s->opt[OPT_Y_RESOLUTION].constraint.word_list = s->hw->vert_resolution_list; 2233141cc406Sopenharmony_ci s->opt[OPT_Y_RESOLUTION].cap |= SANE_CAP_INACTIVE; 2234141cc406Sopenharmony_ci s->val[OPT_Y_RESOLUTION].w = 100; 2235141cc406Sopenharmony_ci 2236141cc406Sopenharmony_ci /* bind resolution */ 2237141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION_BIND].name = SANE_NAME_RESOLUTION_BIND; 2238141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION_BIND].title = SANE_TITLE_RESOLUTION_BIND; 2239141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION_BIND].desc = SANE_DESC_RESOLUTION_BIND; 2240141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION_BIND].type = SANE_TYPE_BOOL; 2241141cc406Sopenharmony_ci s->val[OPT_RESOLUTION_BIND].w = SANE_TRUE; 2242141cc406Sopenharmony_ci 2243141cc406Sopenharmony_ci if (!(s->hw->flags & ARTEC_FLAG_SEPARATE_RES)) 2244141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION_BIND].cap |= SANE_CAP_INACTIVE; 2245141cc406Sopenharmony_ci 2246141cc406Sopenharmony_ci /* Preview Mode */ 2247141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; 2248141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; 2249141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; 2250141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; 2251141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].unit = SANE_UNIT_NONE; 2252141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].size = sizeof (SANE_Word); 2253141cc406Sopenharmony_ci s->val[OPT_PREVIEW].w = SANE_FALSE; 2254141cc406Sopenharmony_ci 2255141cc406Sopenharmony_ci /* Grayscale Preview Mode */ 2256141cc406Sopenharmony_ci s->opt[OPT_GRAY_PREVIEW].name = SANE_NAME_GRAY_PREVIEW; 2257141cc406Sopenharmony_ci s->opt[OPT_GRAY_PREVIEW].title = SANE_TITLE_GRAY_PREVIEW; 2258141cc406Sopenharmony_ci s->opt[OPT_GRAY_PREVIEW].desc = SANE_DESC_GRAY_PREVIEW; 2259141cc406Sopenharmony_ci s->opt[OPT_GRAY_PREVIEW].type = SANE_TYPE_BOOL; 2260141cc406Sopenharmony_ci s->opt[OPT_GRAY_PREVIEW].unit = SANE_UNIT_NONE; 2261141cc406Sopenharmony_ci s->opt[OPT_GRAY_PREVIEW].size = sizeof (SANE_Word); 2262141cc406Sopenharmony_ci s->val[OPT_GRAY_PREVIEW].w = SANE_FALSE; 2263141cc406Sopenharmony_ci 2264141cc406Sopenharmony_ci /* negative */ 2265141cc406Sopenharmony_ci s->opt[OPT_NEGATIVE].name = SANE_NAME_NEGATIVE; 2266141cc406Sopenharmony_ci s->opt[OPT_NEGATIVE].title = SANE_TITLE_NEGATIVE; 2267141cc406Sopenharmony_ci s->opt[OPT_NEGATIVE].desc = "Negative Image"; 2268141cc406Sopenharmony_ci s->opt[OPT_NEGATIVE].type = SANE_TYPE_BOOL; 2269141cc406Sopenharmony_ci s->val[OPT_NEGATIVE].w = SANE_FALSE; 2270141cc406Sopenharmony_ci 2271141cc406Sopenharmony_ci if (!(s->hw->flags & ARTEC_FLAG_MBPP_NEGATIVE)) 2272141cc406Sopenharmony_ci { 2273141cc406Sopenharmony_ci s->opt[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE; 2274141cc406Sopenharmony_ci } 2275141cc406Sopenharmony_ci 2276141cc406Sopenharmony_ci /* "Geometry" group: */ 2277141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; 2278141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].desc = ""; 2279141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 2280141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; 2281141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2282141cc406Sopenharmony_ci 2283141cc406Sopenharmony_ci /* top-left x */ 2284141cc406Sopenharmony_ci s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 2285141cc406Sopenharmony_ci s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 2286141cc406Sopenharmony_ci s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 2287141cc406Sopenharmony_ci s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; 2288141cc406Sopenharmony_ci s->opt[OPT_TL_X].unit = SANE_UNIT_MM; 2289141cc406Sopenharmony_ci 2290141cc406Sopenharmony_ci s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 2291141cc406Sopenharmony_ci s->opt[OPT_TL_X].constraint.range = &s->hw->x_range; 2292141cc406Sopenharmony_ci s->val[OPT_TL_X].w = s->hw->x_range.min; 2293141cc406Sopenharmony_ci 2294141cc406Sopenharmony_ci /* top-left y */ 2295141cc406Sopenharmony_ci s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 2296141cc406Sopenharmony_ci s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 2297141cc406Sopenharmony_ci s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 2298141cc406Sopenharmony_ci s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; 2299141cc406Sopenharmony_ci s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; 2300141cc406Sopenharmony_ci 2301141cc406Sopenharmony_ci s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 2302141cc406Sopenharmony_ci s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range; 2303141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = s->hw->y_range.min; 2304141cc406Sopenharmony_ci 2305141cc406Sopenharmony_ci /* bottom-right x */ 2306141cc406Sopenharmony_ci s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 2307141cc406Sopenharmony_ci s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 2308141cc406Sopenharmony_ci s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 2309141cc406Sopenharmony_ci s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; 2310141cc406Sopenharmony_ci s->opt[OPT_BR_X].unit = SANE_UNIT_MM; 2311141cc406Sopenharmony_ci 2312141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 2313141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint.range = &s->hw->x_range; 2314141cc406Sopenharmony_ci s->val[OPT_BR_X].w = s->hw->x_range.max; 2315141cc406Sopenharmony_ci 2316141cc406Sopenharmony_ci /* bottom-right y */ 2317141cc406Sopenharmony_ci s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 2318141cc406Sopenharmony_ci s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 2319141cc406Sopenharmony_ci s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 2320141cc406Sopenharmony_ci s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; 2321141cc406Sopenharmony_ci s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; 2322141cc406Sopenharmony_ci 2323141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 2324141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range; 2325141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = s->hw->y_range.max; 2326141cc406Sopenharmony_ci 2327141cc406Sopenharmony_ci /* Enhancement group: */ 2328141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; 2329141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; 2330141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; 2331141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; 2332141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2333141cc406Sopenharmony_ci 2334141cc406Sopenharmony_ci /* filter mode */ 2335141cc406Sopenharmony_ci s->opt[OPT_FILTER_TYPE].name = "filter-type"; 2336141cc406Sopenharmony_ci s->opt[OPT_FILTER_TYPE].title = "Filter Type"; 2337141cc406Sopenharmony_ci s->opt[OPT_FILTER_TYPE].desc = "Filter Type for mono scans"; 2338141cc406Sopenharmony_ci s->opt[OPT_FILTER_TYPE].type = SANE_TYPE_STRING; 2339141cc406Sopenharmony_ci s->opt[OPT_FILTER_TYPE].size = max_string_size (filter_type_list); 2340141cc406Sopenharmony_ci s->opt[OPT_FILTER_TYPE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2341141cc406Sopenharmony_ci s->opt[OPT_FILTER_TYPE].constraint.string_list = filter_type_list; 2342141cc406Sopenharmony_ci s->val[OPT_FILTER_TYPE].s = strdup (filter_type_list[0]); 2343141cc406Sopenharmony_ci s->opt[OPT_FILTER_TYPE].cap |= SANE_CAP_INACTIVE; 2344141cc406Sopenharmony_ci 2345141cc406Sopenharmony_ci /* contrast */ 2346141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; 2347141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; 2348141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; 2349141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].type = SANE_TYPE_INT; 2350141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; 2351141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; 2352141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].constraint.range = &s->hw->brightness_range; 2353141cc406Sopenharmony_ci s->val[OPT_CONTRAST].w = 0x80; 2354141cc406Sopenharmony_ci 2355141cc406Sopenharmony_ci if (!(s->hw->flags & ARTEC_FLAG_OPT_CONTRAST)) 2356141cc406Sopenharmony_ci { 2357141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; 2358141cc406Sopenharmony_ci } 2359141cc406Sopenharmony_ci 2360141cc406Sopenharmony_ci /* brightness */ 2361141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; 2362141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; 2363141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; 2364141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; 2365141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; 2366141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; 2367141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].constraint.range = &s->hw->contrast_range; 2368141cc406Sopenharmony_ci s->val[OPT_BRIGHTNESS].w = 0x80; 2369141cc406Sopenharmony_ci 2370141cc406Sopenharmony_ci if (!(s->hw->flags & ARTEC_FLAG_OPT_BRIGHTNESS)) 2371141cc406Sopenharmony_ci { 2372141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 2373141cc406Sopenharmony_ci } 2374141cc406Sopenharmony_ci 2375141cc406Sopenharmony_ci /* threshold */ 2376141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; 2377141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; 2378141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; 2379141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; 2380141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; 2381141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; 2382141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].constraint.range = &s->hw->threshold_range; 2383141cc406Sopenharmony_ci s->val[OPT_THRESHOLD].w = 0x80; 2384141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 2385141cc406Sopenharmony_ci 2386141cc406Sopenharmony_ci /* halftone pattern */ 2387141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; 2388141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; 2389141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; 2390141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING; 2391141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].size = max_string_size (halftone_pattern_list); 2392141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2393141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].constraint.string_list = halftone_pattern_list; 2394141cc406Sopenharmony_ci s->val[OPT_HALFTONE_PATTERN].s = strdup (halftone_pattern_list[1]); 2395141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; 2396141cc406Sopenharmony_ci 2397141cc406Sopenharmony_ci /* pixel averaging */ 2398141cc406Sopenharmony_ci s->opt[OPT_PIXEL_AVG].name = "pixel-avg"; 2399141cc406Sopenharmony_ci s->opt[OPT_PIXEL_AVG].title = "Pixel Averaging"; 2400141cc406Sopenharmony_ci s->opt[OPT_PIXEL_AVG].desc = "Enable HardWare Pixel Averaging function"; 2401141cc406Sopenharmony_ci s->opt[OPT_PIXEL_AVG].type = SANE_TYPE_BOOL; 2402141cc406Sopenharmony_ci s->val[OPT_PIXEL_AVG].w = SANE_FALSE; 2403141cc406Sopenharmony_ci 2404141cc406Sopenharmony_ci if (!(s->hw->flags & ARTEC_FLAG_PIXEL_AVERAGING)) 2405141cc406Sopenharmony_ci { 2406141cc406Sopenharmony_ci s->opt[OPT_PIXEL_AVG].cap |= SANE_CAP_INACTIVE; 2407141cc406Sopenharmony_ci } 2408141cc406Sopenharmony_ci 2409141cc406Sopenharmony_ci /* lineart line edge enhancement */ 2410141cc406Sopenharmony_ci s->opt[OPT_EDGE_ENH].name = "edge-enh"; 2411141cc406Sopenharmony_ci s->opt[OPT_EDGE_ENH].title = "Line Edge Enhancement"; 2412141cc406Sopenharmony_ci s->opt[OPT_EDGE_ENH].desc = "Enable HardWare Lineart Line Edge Enhancement"; 2413141cc406Sopenharmony_ci s->opt[OPT_EDGE_ENH].type = SANE_TYPE_BOOL; 2414141cc406Sopenharmony_ci s->val[OPT_EDGE_ENH].w = SANE_FALSE; 2415141cc406Sopenharmony_ci s->opt[OPT_EDGE_ENH].cap |= SANE_CAP_INACTIVE; 2416141cc406Sopenharmony_ci 2417141cc406Sopenharmony_ci /* custom-gamma table */ 2418141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; 2419141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; 2420141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; 2421141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; 2422141cc406Sopenharmony_ci s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; 2423141cc406Sopenharmony_ci 2424141cc406Sopenharmony_ci /* grayscale gamma vector */ 2425141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; 2426141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; 2427141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; 2428141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; 2429141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; 2430141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; 2431141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR].wa = &(s->gamma_table[0][0]); 2432141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range; 2433141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].size = s->gamma_length * sizeof (SANE_Word); 2434141cc406Sopenharmony_ci 2435141cc406Sopenharmony_ci /* red gamma vector */ 2436141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; 2437141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; 2438141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; 2439141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; 2440141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; 2441141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; 2442141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR_R].wa = &(s->gamma_table[1][0]); 2443141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &(s->gamma_range); 2444141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].size = s->gamma_length * sizeof (SANE_Word); 2445141cc406Sopenharmony_ci 2446141cc406Sopenharmony_ci /* green gamma vector */ 2447141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; 2448141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; 2449141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; 2450141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; 2451141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; 2452141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; 2453141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR_G].wa = &(s->gamma_table[2][0]); 2454141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &(s->gamma_range); 2455141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].size = s->gamma_length * sizeof (SANE_Word); 2456141cc406Sopenharmony_ci 2457141cc406Sopenharmony_ci /* blue gamma vector */ 2458141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; 2459141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; 2460141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; 2461141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; 2462141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; 2463141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; 2464141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR_B].wa = &(s->gamma_table[3][0]); 2465141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &(s->gamma_range); 2466141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].size = s->gamma_length * sizeof (SANE_Word); 2467141cc406Sopenharmony_ci 2468141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_GAMMA_SINGLE) 2469141cc406Sopenharmony_ci { 2470141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 2471141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 2472141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 2473141cc406Sopenharmony_ci } 2474141cc406Sopenharmony_ci 2475141cc406Sopenharmony_ci if (!(s->hw->flags & ARTEC_FLAG_GAMMA)) 2476141cc406Sopenharmony_ci { 2477141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 2478141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 2479141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 2480141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; 2481141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 2482141cc406Sopenharmony_ci } 2483141cc406Sopenharmony_ci 2484141cc406Sopenharmony_ci /* transparency */ 2485141cc406Sopenharmony_ci s->opt[OPT_TRANSPARENCY].name = "transparency"; 2486141cc406Sopenharmony_ci s->opt[OPT_TRANSPARENCY].title = "Transparency"; 2487141cc406Sopenharmony_ci s->opt[OPT_TRANSPARENCY].desc = "Use transparency adaptor"; 2488141cc406Sopenharmony_ci s->opt[OPT_TRANSPARENCY].type = SANE_TYPE_BOOL; 2489141cc406Sopenharmony_ci s->val[OPT_TRANSPARENCY].w = SANE_FALSE; 2490141cc406Sopenharmony_ci 2491141cc406Sopenharmony_ci /* ADF */ 2492141cc406Sopenharmony_ci s->opt[OPT_ADF].name = "adf"; 2493141cc406Sopenharmony_ci s->opt[OPT_ADF].title = "ADF"; 2494141cc406Sopenharmony_ci s->opt[OPT_ADF].desc = "Use ADF"; 2495141cc406Sopenharmony_ci s->opt[OPT_ADF].type = SANE_TYPE_BOOL; 2496141cc406Sopenharmony_ci s->val[OPT_ADF].w = SANE_FALSE; 2497141cc406Sopenharmony_ci 2498141cc406Sopenharmony_ci /* Calibration group: */ 2499141cc406Sopenharmony_ci s->opt[OPT_CALIBRATION_GROUP].title = "Calibration"; 2500141cc406Sopenharmony_ci s->opt[OPT_CALIBRATION_GROUP].desc = ""; 2501141cc406Sopenharmony_ci s->opt[OPT_CALIBRATION_GROUP].type = SANE_TYPE_GROUP; 2502141cc406Sopenharmony_ci s->opt[OPT_CALIBRATION_GROUP].cap = SANE_CAP_ADVANCED; 2503141cc406Sopenharmony_ci s->opt[OPT_CALIBRATION_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2504141cc406Sopenharmony_ci 2505141cc406Sopenharmony_ci /* Calibrate Every Scan? */ 2506141cc406Sopenharmony_ci s->opt[OPT_QUALITY_CAL].name = SANE_NAME_QUALITY_CAL; 2507141cc406Sopenharmony_ci s->opt[OPT_QUALITY_CAL].title = "Hardware Calibrate Every Scan"; 2508141cc406Sopenharmony_ci s->opt[OPT_QUALITY_CAL].desc = "Perform hardware calibration on every scan"; 2509141cc406Sopenharmony_ci s->opt[OPT_QUALITY_CAL].type = SANE_TYPE_BOOL; 2510141cc406Sopenharmony_ci s->val[OPT_QUALITY_CAL].w = SANE_FALSE; 2511141cc406Sopenharmony_ci 2512141cc406Sopenharmony_ci if (!(s->hw->flags & ARTEC_FLAG_CALIBRATE)) 2513141cc406Sopenharmony_ci { 2514141cc406Sopenharmony_ci s->opt[OPT_QUALITY_CAL].cap |= SANE_CAP_INACTIVE; 2515141cc406Sopenharmony_ci } 2516141cc406Sopenharmony_ci 2517141cc406Sopenharmony_ci /* Perform Software Quality Calibration */ 2518141cc406Sopenharmony_ci s->opt[OPT_SOFTWARE_CAL].name = "software-cal"; 2519141cc406Sopenharmony_ci s->opt[OPT_SOFTWARE_CAL].title = "Software Color Calibration"; 2520141cc406Sopenharmony_ci s->opt[OPT_SOFTWARE_CAL].desc = "Perform software quality calibration in " 2521141cc406Sopenharmony_ci "addition to hardware calibration"; 2522141cc406Sopenharmony_ci s->opt[OPT_SOFTWARE_CAL].type = SANE_TYPE_BOOL; 2523141cc406Sopenharmony_ci s->val[OPT_SOFTWARE_CAL].w = SANE_FALSE; 2524141cc406Sopenharmony_ci 2525141cc406Sopenharmony_ci /* check for RGB calibration now because we have only implemented software */ 2526141cc406Sopenharmony_ci /* calibration in conjunction with hardware RGB calibration */ 2527141cc406Sopenharmony_ci if ((!(s->hw->flags & ARTEC_FLAG_CALIBRATE)) || 2528141cc406Sopenharmony_ci (!(s->hw->flags & ARTEC_FLAG_CALIBRATE_RGB))) 2529141cc406Sopenharmony_ci { 2530141cc406Sopenharmony_ci s->opt[OPT_SOFTWARE_CAL].cap |= SANE_CAP_INACTIVE; 2531141cc406Sopenharmony_ci } 2532141cc406Sopenharmony_ci 2533141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2534141cc406Sopenharmony_ci} 2535141cc406Sopenharmony_ci 2536141cc406Sopenharmony_cistatic SANE_Status 2537141cc406Sopenharmony_cido_cancel (ARTEC_Scanner * s) 2538141cc406Sopenharmony_ci{ 2539141cc406Sopenharmony_ci DBG (7, "do_cancel()\n"); 2540141cc406Sopenharmony_ci 2541141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 2542141cc406Sopenharmony_ci 2543141cc406Sopenharmony_ci /* DAL: Terminate a three pass scan properly */ 2544141cc406Sopenharmony_ci/* if (s->this_pass == 3) */ 2545141cc406Sopenharmony_ci s->this_pass = 0; 2546141cc406Sopenharmony_ci 2547141cc406Sopenharmony_ci if ((s->hw->flags & ARTEC_FLAG_RGB_LINE_OFFSET) && 2548141cc406Sopenharmony_ci (tmp_line_buf != NULL)) 2549141cc406Sopenharmony_ci { 2550141cc406Sopenharmony_ci artec_buffer_line_offset_free (); 2551141cc406Sopenharmony_ci } 2552141cc406Sopenharmony_ci 2553141cc406Sopenharmony_ci if (s->fd >= 0) 2554141cc406Sopenharmony_ci { 2555141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 2556141cc406Sopenharmony_ci s->fd = -1; 2557141cc406Sopenharmony_ci } 2558141cc406Sopenharmony_ci 2559141cc406Sopenharmony_ci return (SANE_STATUS_CANCELLED); 2560141cc406Sopenharmony_ci} 2561141cc406Sopenharmony_ci 2562141cc406Sopenharmony_ci 2563141cc406Sopenharmony_cistatic SANE_Status 2564141cc406Sopenharmony_ciattach_one (const char *dev) 2565141cc406Sopenharmony_ci{ 2566141cc406Sopenharmony_ci DBG (7, "attach_one()\n"); 2567141cc406Sopenharmony_ci 2568141cc406Sopenharmony_ci attach (dev, 0); 2569141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2570141cc406Sopenharmony_ci} 2571141cc406Sopenharmony_ci 2572141cc406Sopenharmony_ci 2573141cc406Sopenharmony_ciSANE_Status 2574141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) 2575141cc406Sopenharmony_ci{ 2576141cc406Sopenharmony_ci char dev_name[PATH_MAX], *cp; 2577141cc406Sopenharmony_ci size_t len; 2578141cc406Sopenharmony_ci FILE *fp; 2579141cc406Sopenharmony_ci 2580141cc406Sopenharmony_ci DBG_INIT (); 2581141cc406Sopenharmony_ci 2582141cc406Sopenharmony_ci DBG (1, "Artec/Ultima backend version %d.%d.%d, last mod: %s\n", 2583141cc406Sopenharmony_ci ARTEC_MAJOR, ARTEC_MINOR, ARTEC_SUB, ARTEC_LAST_MOD); 2584141cc406Sopenharmony_ci DBG (1, "http://www4.infi.net/~cpinkham/sane-artec-doc.html\n"); 2585141cc406Sopenharmony_ci 2586141cc406Sopenharmony_ci DBG (7, "sane_init()\n" ); 2587141cc406Sopenharmony_ci 2588141cc406Sopenharmony_ci devlist = 0; 2589141cc406Sopenharmony_ci /* make sure these 2 are empty */ 2590141cc406Sopenharmony_ci strcpy (artec_vendor, ""); 2591141cc406Sopenharmony_ci strcpy (artec_model, ""); 2592141cc406Sopenharmony_ci 2593141cc406Sopenharmony_ci if (version_code) 2594141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0); 2595141cc406Sopenharmony_ci 2596141cc406Sopenharmony_ci if (authorize) 2597141cc406Sopenharmony_ci DBG (7, "sane_init(), authorize %s null\n", (authorize) ? "!=" : "=="); 2598141cc406Sopenharmony_ci 2599141cc406Sopenharmony_ci fp = sanei_config_open (ARTEC_CONFIG_FILE); 2600141cc406Sopenharmony_ci if (!fp) 2601141cc406Sopenharmony_ci { 2602141cc406Sopenharmony_ci /* default to /dev/scanner instead of insisting on config file */ 2603141cc406Sopenharmony_ci attach ("/dev/scanner", 0); 2604141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2605141cc406Sopenharmony_ci } 2606141cc406Sopenharmony_ci 2607141cc406Sopenharmony_ci while (sanei_config_read (dev_name, sizeof (dev_name), fp)) 2608141cc406Sopenharmony_ci { 2609141cc406Sopenharmony_ci cp = artec_skip_whitespace (dev_name); 2610141cc406Sopenharmony_ci 2611141cc406Sopenharmony_ci /* ignore line comments and blank lines */ 2612141cc406Sopenharmony_ci if ((!*cp) || (*cp == '#')) 2613141cc406Sopenharmony_ci continue; 2614141cc406Sopenharmony_ci 2615141cc406Sopenharmony_ci len = strlen (cp); 2616141cc406Sopenharmony_ci 2617141cc406Sopenharmony_ci /* ignore empty lines */ 2618141cc406Sopenharmony_ci if (!len) 2619141cc406Sopenharmony_ci continue; 2620141cc406Sopenharmony_ci 2621141cc406Sopenharmony_ci DBG (50, "%s line: '%s', len = %lu\n", ARTEC_CONFIG_FILE, cp, 2622141cc406Sopenharmony_ci (u_long) len); 2623141cc406Sopenharmony_ci 2624141cc406Sopenharmony_ci /* check to see if they forced a vendor string in artec.conf */ 2625141cc406Sopenharmony_ci if ((strncmp (cp, "vendor", 6) == 0) && isspace (cp[6])) 2626141cc406Sopenharmony_ci { 2627141cc406Sopenharmony_ci cp += 7; 2628141cc406Sopenharmony_ci cp = artec_skip_whitespace (cp); 2629141cc406Sopenharmony_ci 2630141cc406Sopenharmony_ci strcpy (artec_vendor, cp); 2631141cc406Sopenharmony_ci DBG (5, "sane_init: Forced vendor string '%s' in %s.\n", 2632141cc406Sopenharmony_ci cp, ARTEC_CONFIG_FILE); 2633141cc406Sopenharmony_ci } 2634141cc406Sopenharmony_ci /* OK, maybe they forced the model string in artec.conf */ 2635141cc406Sopenharmony_ci else if ((strncmp (cp, "model", 5) == 0) && isspace (cp[5])) 2636141cc406Sopenharmony_ci { 2637141cc406Sopenharmony_ci cp += 6; 2638141cc406Sopenharmony_ci cp = artec_skip_whitespace (cp); 2639141cc406Sopenharmony_ci 2640141cc406Sopenharmony_ci strcpy (artec_model, cp); 2641141cc406Sopenharmony_ci DBG (5, "sane_init: Forced model string '%s' in %s.\n", 2642141cc406Sopenharmony_ci cp, ARTEC_CONFIG_FILE); 2643141cc406Sopenharmony_ci } 2644141cc406Sopenharmony_ci /* well, nothing else to do but attempt the attach */ 2645141cc406Sopenharmony_ci else 2646141cc406Sopenharmony_ci { 2647141cc406Sopenharmony_ci sanei_config_attach_matching_devices (dev_name, attach_one); 2648141cc406Sopenharmony_ci strcpy (artec_vendor, ""); 2649141cc406Sopenharmony_ci strcpy (artec_model, ""); 2650141cc406Sopenharmony_ci } 2651141cc406Sopenharmony_ci } 2652141cc406Sopenharmony_ci fclose (fp); 2653141cc406Sopenharmony_ci 2654141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2655141cc406Sopenharmony_ci} 2656141cc406Sopenharmony_ci 2657141cc406Sopenharmony_civoid 2658141cc406Sopenharmony_cisane_exit (void) 2659141cc406Sopenharmony_ci{ 2660141cc406Sopenharmony_ci ARTEC_Device *dev, *next; 2661141cc406Sopenharmony_ci 2662141cc406Sopenharmony_ci DBG (7, "sane_exit()\n"); 2663141cc406Sopenharmony_ci 2664141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = next) 2665141cc406Sopenharmony_ci { 2666141cc406Sopenharmony_ci next = dev->next; 2667141cc406Sopenharmony_ci free ((void *) dev->sane.name); 2668141cc406Sopenharmony_ci free ((void *) dev->sane.model); 2669141cc406Sopenharmony_ci free (dev); 2670141cc406Sopenharmony_ci } 2671141cc406Sopenharmony_ci 2672141cc406Sopenharmony_ci if (devlist) 2673141cc406Sopenharmony_ci free (devlist); 2674141cc406Sopenharmony_ci} 2675141cc406Sopenharmony_ci 2676141cc406Sopenharmony_ciSANE_Status 2677141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) 2678141cc406Sopenharmony_ci{ 2679141cc406Sopenharmony_ci ARTEC_Device *dev; 2680141cc406Sopenharmony_ci int i; 2681141cc406Sopenharmony_ci 2682141cc406Sopenharmony_ci DBG (7, "sane_get_devices( device_list, local_only = %d )\n", local_only ); 2683141cc406Sopenharmony_ci 2684141cc406Sopenharmony_ci if (devlist) 2685141cc406Sopenharmony_ci free (devlist); 2686141cc406Sopenharmony_ci 2687141cc406Sopenharmony_ci devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); 2688141cc406Sopenharmony_ci if (!devlist) 2689141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2690141cc406Sopenharmony_ci 2691141cc406Sopenharmony_ci i = 0; 2692141cc406Sopenharmony_ci for (dev = first_dev; i < num_devices; dev = dev->next) 2693141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 2694141cc406Sopenharmony_ci devlist[i++] = 0; 2695141cc406Sopenharmony_ci 2696141cc406Sopenharmony_ci *device_list = devlist; 2697141cc406Sopenharmony_ci 2698141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2699141cc406Sopenharmony_ci} 2700141cc406Sopenharmony_ci 2701141cc406Sopenharmony_ciSANE_Status 2702141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 2703141cc406Sopenharmony_ci{ 2704141cc406Sopenharmony_ci SANE_Status status; 2705141cc406Sopenharmony_ci ARTEC_Device *dev; 2706141cc406Sopenharmony_ci ARTEC_Scanner *s; 2707141cc406Sopenharmony_ci int i, j; 2708141cc406Sopenharmony_ci 2709141cc406Sopenharmony_ci DBG (7, "sane_open()\n"); 2710141cc406Sopenharmony_ci 2711141cc406Sopenharmony_ci if (devicename[0]) 2712141cc406Sopenharmony_ci { 2713141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 2714141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) 2715141cc406Sopenharmony_ci break; 2716141cc406Sopenharmony_ci 2717141cc406Sopenharmony_ci if (!dev) 2718141cc406Sopenharmony_ci { 2719141cc406Sopenharmony_ci status = attach (devicename, &dev); 2720141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2721141cc406Sopenharmony_ci return (status); 2722141cc406Sopenharmony_ci } 2723141cc406Sopenharmony_ci } 2724141cc406Sopenharmony_ci else 2725141cc406Sopenharmony_ci { 2726141cc406Sopenharmony_ci /* empty devicname -> use first device */ 2727141cc406Sopenharmony_ci dev = first_dev; 2728141cc406Sopenharmony_ci } 2729141cc406Sopenharmony_ci 2730141cc406Sopenharmony_ci if (!dev) 2731141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2732141cc406Sopenharmony_ci 2733141cc406Sopenharmony_ci s = malloc (sizeof (*s)); 2734141cc406Sopenharmony_ci if (!s) 2735141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2736141cc406Sopenharmony_ci memset (s, 0, sizeof (*s)); 2737141cc406Sopenharmony_ci s->fd = -1; 2738141cc406Sopenharmony_ci s->hw = dev; 2739141cc406Sopenharmony_ci s->this_pass = 0; 2740141cc406Sopenharmony_ci 2741141cc406Sopenharmony_ci s->gamma_length = s->hw->gamma_length; 2742141cc406Sopenharmony_ci s->gamma_range.min = 0; 2743141cc406Sopenharmony_ci s->gamma_range.max = s->gamma_length - 1; 2744141cc406Sopenharmony_ci s->gamma_range.quant = 0; 2745141cc406Sopenharmony_ci 2746141cc406Sopenharmony_ci /* not sure if I need this or not, it was in the umax backend though. :-) */ 2747141cc406Sopenharmony_ci for (j = 0; j < s->gamma_length; ++j) 2748141cc406Sopenharmony_ci { 2749141cc406Sopenharmony_ci s->gamma_table[0][j] = j * (s->gamma_length - 1) / s->gamma_length; 2750141cc406Sopenharmony_ci } 2751141cc406Sopenharmony_ci 2752141cc406Sopenharmony_ci for (i = 1; i < 4; i++) 2753141cc406Sopenharmony_ci { 2754141cc406Sopenharmony_ci for (j = 0; j < s->gamma_length; ++j) 2755141cc406Sopenharmony_ci { 2756141cc406Sopenharmony_ci s->gamma_table[i][j] = j; 2757141cc406Sopenharmony_ci } 2758141cc406Sopenharmony_ci } 2759141cc406Sopenharmony_ci 2760141cc406Sopenharmony_ci init_options (s); 2761141cc406Sopenharmony_ci 2762141cc406Sopenharmony_ci /* insert newly opened handle into list of open handles: */ 2763141cc406Sopenharmony_ci s->next = first_handle; 2764141cc406Sopenharmony_ci first_handle = s; 2765141cc406Sopenharmony_ci 2766141cc406Sopenharmony_ci *handle = s; 2767141cc406Sopenharmony_ci 2768141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_CALIBRATE) 2769141cc406Sopenharmony_ci { 2770141cc406Sopenharmony_ci status = sanei_scsi_open (s->hw->sane.name, &s->fd, 0, 0); 2771141cc406Sopenharmony_ci 2772141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2773141cc406Sopenharmony_ci { 2774141cc406Sopenharmony_ci DBG (1, "error opening scanner for initial calibration: %s\n", 2775141cc406Sopenharmony_ci sane_strstatus (status)); 2776141cc406Sopenharmony_ci s->fd = -1; 2777141cc406Sopenharmony_ci return status; 2778141cc406Sopenharmony_ci } 2779141cc406Sopenharmony_ci 2780141cc406Sopenharmony_ci status = artec_calibrate_shading (s); 2781141cc406Sopenharmony_ci 2782141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2783141cc406Sopenharmony_ci { 2784141cc406Sopenharmony_ci DBG (1, "initial shading calibration failed: %s\n", 2785141cc406Sopenharmony_ci sane_strstatus (status)); 2786141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 2787141cc406Sopenharmony_ci s->fd = -1; 2788141cc406Sopenharmony_ci return status; 2789141cc406Sopenharmony_ci } 2790141cc406Sopenharmony_ci 2791141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 2792141cc406Sopenharmony_ci } 2793141cc406Sopenharmony_ci 2794141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2795141cc406Sopenharmony_ci} 2796141cc406Sopenharmony_ci 2797141cc406Sopenharmony_civoid 2798141cc406Sopenharmony_cisane_close (SANE_Handle handle) 2799141cc406Sopenharmony_ci{ 2800141cc406Sopenharmony_ci ARTEC_Scanner *prev, *s; 2801141cc406Sopenharmony_ci 2802141cc406Sopenharmony_ci DBG (7, "sane_close()\n"); 2803141cc406Sopenharmony_ci 2804141cc406Sopenharmony_ci if ((DBG_LEVEL == 101) && 2805141cc406Sopenharmony_ci (debug_fd > -1)) 2806141cc406Sopenharmony_ci { 2807141cc406Sopenharmony_ci close (debug_fd); 2808141cc406Sopenharmony_ci DBG (101, "closed artec.data.raw output file\n"); 2809141cc406Sopenharmony_ci } 2810141cc406Sopenharmony_ci 2811141cc406Sopenharmony_ci /* remove handle from list of open handles: */ 2812141cc406Sopenharmony_ci prev = 0; 2813141cc406Sopenharmony_ci for (s = first_handle; s; s = s->next) 2814141cc406Sopenharmony_ci { 2815141cc406Sopenharmony_ci if (s == handle) 2816141cc406Sopenharmony_ci break; 2817141cc406Sopenharmony_ci prev = s; 2818141cc406Sopenharmony_ci } 2819141cc406Sopenharmony_ci if (!s) 2820141cc406Sopenharmony_ci { 2821141cc406Sopenharmony_ci DBG (1, "close: invalid handle %p\n", handle); 2822141cc406Sopenharmony_ci return; /* oops, not a handle we know about */ 2823141cc406Sopenharmony_ci } 2824141cc406Sopenharmony_ci 2825141cc406Sopenharmony_ci if (s->scanning) 2826141cc406Sopenharmony_ci do_cancel (handle); 2827141cc406Sopenharmony_ci 2828141cc406Sopenharmony_ci 2829141cc406Sopenharmony_ci if (prev) 2830141cc406Sopenharmony_ci prev->next = s->next; 2831141cc406Sopenharmony_ci else 2832141cc406Sopenharmony_ci first_handle = s->next; 2833141cc406Sopenharmony_ci 2834141cc406Sopenharmony_ci free (handle); 2835141cc406Sopenharmony_ci} 2836141cc406Sopenharmony_ci 2837141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 2838141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 2839141cc406Sopenharmony_ci{ 2840141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 2841141cc406Sopenharmony_ci 2842141cc406Sopenharmony_ci DBG (7, "sane_get_option_descriptor()\n"); 2843141cc406Sopenharmony_ci 2844141cc406Sopenharmony_ci if (((unsigned) option >= NUM_OPTIONS) || 2845141cc406Sopenharmony_ci (option < 0 )) 2846141cc406Sopenharmony_ci return (0); 2847141cc406Sopenharmony_ci 2848141cc406Sopenharmony_ci return (s->opt + option); 2849141cc406Sopenharmony_ci} 2850141cc406Sopenharmony_ci 2851141cc406Sopenharmony_ciSANE_Status 2852141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 2853141cc406Sopenharmony_ci SANE_Action action, void *val, SANE_Int * info) 2854141cc406Sopenharmony_ci{ 2855141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 2856141cc406Sopenharmony_ci SANE_Status status; 2857141cc406Sopenharmony_ci SANE_Word w, cap; 2858141cc406Sopenharmony_ci 2859141cc406Sopenharmony_ci DBG (7, "sane_control_option()\n"); 2860141cc406Sopenharmony_ci 2861141cc406Sopenharmony_ci if (info) 2862141cc406Sopenharmony_ci *info = 0; 2863141cc406Sopenharmony_ci 2864141cc406Sopenharmony_ci if (s->scanning) 2865141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 2866141cc406Sopenharmony_ci 2867141cc406Sopenharmony_ci if (s->this_pass) 2868141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 2869141cc406Sopenharmony_ci 2870141cc406Sopenharmony_ci if (option >= NUM_OPTIONS) 2871141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2872141cc406Sopenharmony_ci 2873141cc406Sopenharmony_ci cap = s->opt[option].cap; 2874141cc406Sopenharmony_ci 2875141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (cap)) 2876141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2877141cc406Sopenharmony_ci 2878141cc406Sopenharmony_ci if (action == SANE_ACTION_GET_VALUE) 2879141cc406Sopenharmony_ci { 2880141cc406Sopenharmony_ci DBG (13, "sane_control_option %d, get value\n", option); 2881141cc406Sopenharmony_ci 2882141cc406Sopenharmony_ci switch (option) 2883141cc406Sopenharmony_ci { 2884141cc406Sopenharmony_ci /* word options: */ 2885141cc406Sopenharmony_ci case OPT_X_RESOLUTION: 2886141cc406Sopenharmony_ci case OPT_Y_RESOLUTION: 2887141cc406Sopenharmony_ci case OPT_PREVIEW: 2888141cc406Sopenharmony_ci case OPT_GRAY_PREVIEW: 2889141cc406Sopenharmony_ci case OPT_RESOLUTION_BIND: 2890141cc406Sopenharmony_ci case OPT_NEGATIVE: 2891141cc406Sopenharmony_ci case OPT_TRANSPARENCY: 2892141cc406Sopenharmony_ci case OPT_ADF: 2893141cc406Sopenharmony_ci case OPT_TL_X: 2894141cc406Sopenharmony_ci case OPT_TL_Y: 2895141cc406Sopenharmony_ci case OPT_BR_X: 2896141cc406Sopenharmony_ci case OPT_BR_Y: 2897141cc406Sopenharmony_ci case OPT_NUM_OPTS: 2898141cc406Sopenharmony_ci case OPT_QUALITY_CAL: 2899141cc406Sopenharmony_ci case OPT_SOFTWARE_CAL: 2900141cc406Sopenharmony_ci case OPT_CONTRAST: 2901141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 2902141cc406Sopenharmony_ci case OPT_THRESHOLD: 2903141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 2904141cc406Sopenharmony_ci case OPT_PIXEL_AVG: 2905141cc406Sopenharmony_ci case OPT_EDGE_ENH: 2906141cc406Sopenharmony_ci *(SANE_Word *) val = s->val[option].w; 2907141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2908141cc406Sopenharmony_ci 2909141cc406Sopenharmony_ci /* string options: */ 2910141cc406Sopenharmony_ci case OPT_MODE: 2911141cc406Sopenharmony_ci case OPT_FILTER_TYPE: 2912141cc406Sopenharmony_ci case OPT_HALFTONE_PATTERN: 2913141cc406Sopenharmony_ci strcpy (val, s->val[option].s); 2914141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2915141cc406Sopenharmony_ci 2916141cc406Sopenharmony_ci /* word array options: */ 2917141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 2918141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 2919141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 2920141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 2921141cc406Sopenharmony_ci memcpy (val, s->val[option].wa, s->opt[option].size); 2922141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2923141cc406Sopenharmony_ci } 2924141cc406Sopenharmony_ci } 2925141cc406Sopenharmony_ci else if (action == SANE_ACTION_SET_VALUE) 2926141cc406Sopenharmony_ci { 2927141cc406Sopenharmony_ci DBG (13, "sane_control_option %d, set value\n", option); 2928141cc406Sopenharmony_ci 2929141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (cap)) 2930141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 2931141cc406Sopenharmony_ci 2932141cc406Sopenharmony_ci status = sanei_constrain_value (s->opt + option, val, info); 2933141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2934141cc406Sopenharmony_ci return (status); 2935141cc406Sopenharmony_ci 2936141cc406Sopenharmony_ci switch (option) 2937141cc406Sopenharmony_ci { 2938141cc406Sopenharmony_ci /* (mostly) side-effect-free word options: */ 2939141cc406Sopenharmony_ci case OPT_X_RESOLUTION: 2940141cc406Sopenharmony_ci case OPT_Y_RESOLUTION: 2941141cc406Sopenharmony_ci case OPT_BR_X: 2942141cc406Sopenharmony_ci case OPT_BR_Y: 2943141cc406Sopenharmony_ci case OPT_TL_X: 2944141cc406Sopenharmony_ci case OPT_TL_Y: 2945141cc406Sopenharmony_ci if (info && s->val[option].w != *(SANE_Word *) val) 2946141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 2947141cc406Sopenharmony_ci 2948141cc406Sopenharmony_ci /* fall through */ 2949141cc406Sopenharmony_ci case OPT_PREVIEW: 2950141cc406Sopenharmony_ci case OPT_GRAY_PREVIEW: 2951141cc406Sopenharmony_ci case OPT_QUALITY_CAL: 2952141cc406Sopenharmony_ci case OPT_SOFTWARE_CAL: 2953141cc406Sopenharmony_ci case OPT_NUM_OPTS: 2954141cc406Sopenharmony_ci case OPT_NEGATIVE: 2955141cc406Sopenharmony_ci case OPT_TRANSPARENCY: 2956141cc406Sopenharmony_ci case OPT_ADF: 2957141cc406Sopenharmony_ci case OPT_CONTRAST: 2958141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 2959141cc406Sopenharmony_ci case OPT_THRESHOLD: 2960141cc406Sopenharmony_ci case OPT_PIXEL_AVG: 2961141cc406Sopenharmony_ci case OPT_EDGE_ENH: 2962141cc406Sopenharmony_ci s->val[option].w = *(SANE_Word *) val; 2963141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2964141cc406Sopenharmony_ci 2965141cc406Sopenharmony_ci case OPT_MODE: 2966141cc406Sopenharmony_ci { 2967141cc406Sopenharmony_ci if (s->val[option].s) 2968141cc406Sopenharmony_ci free (s->val[option].s); 2969141cc406Sopenharmony_ci 2970141cc406Sopenharmony_ci s->val[option].s = (SANE_Char *) strdup (val); 2971141cc406Sopenharmony_ci 2972141cc406Sopenharmony_ci if (info) 2973141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 2974141cc406Sopenharmony_ci 2975141cc406Sopenharmony_ci s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; 2976141cc406Sopenharmony_ci 2977141cc406Sopenharmony_ci /* options INvisible by default */ 2978141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 2979141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 2980141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 2981141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 2982141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 2983141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; 2984141cc406Sopenharmony_ci s->opt[OPT_SOFTWARE_CAL].cap |= SANE_CAP_INACTIVE; 2985141cc406Sopenharmony_ci s->opt[OPT_EDGE_ENH].cap |= SANE_CAP_INACTIVE; 2986141cc406Sopenharmony_ci 2987141cc406Sopenharmony_ci /* options VISIBLE by default */ 2988141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; 2989141cc406Sopenharmony_ci s->opt[OPT_FILTER_TYPE].cap &= ~SANE_CAP_INACTIVE; 2990141cc406Sopenharmony_ci s->opt[OPT_NEGATIVE].cap &= ~SANE_CAP_INACTIVE; 2991141cc406Sopenharmony_ci 2992141cc406Sopenharmony_ci if (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0) 2993141cc406Sopenharmony_ci { 2994141cc406Sopenharmony_ci /* Lineart mode */ 2995141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; /* OFF */ 2996141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; 2997141cc406Sopenharmony_ci 2998141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_ENHANCE_LINE_EDGE) 2999141cc406Sopenharmony_ci s->opt[OPT_EDGE_ENH].cap &= ~SANE_CAP_INACTIVE; 3000141cc406Sopenharmony_ci } 3001141cc406Sopenharmony_ci else if (strcmp (val, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) 3002141cc406Sopenharmony_ci { 3003141cc406Sopenharmony_ci /* Halftone mode */ 3004141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_HALFTONE_PATTERN) 3005141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; 3006141cc406Sopenharmony_ci } 3007141cc406Sopenharmony_ci else if (strcmp (val, SANE_VALUE_SCAN_MODE_GRAY) == 0) 3008141cc406Sopenharmony_ci { 3009141cc406Sopenharmony_ci /* Grayscale mode */ 3010141cc406Sopenharmony_ci if (!(s->hw->flags & ARTEC_FLAG_MBPP_NEGATIVE)) 3011141cc406Sopenharmony_ci { 3012141cc406Sopenharmony_ci s->opt[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE; 3013141cc406Sopenharmony_ci } 3014141cc406Sopenharmony_ci } 3015141cc406Sopenharmony_ci else if (strcmp (val, SANE_VALUE_SCAN_MODE_COLOR) == 0) 3016141cc406Sopenharmony_ci { 3017141cc406Sopenharmony_ci /* Color mode */ 3018141cc406Sopenharmony_ci s->opt[OPT_FILTER_TYPE].cap |= SANE_CAP_INACTIVE; 3019141cc406Sopenharmony_ci s->opt[OPT_SOFTWARE_CAL].cap &= ~SANE_CAP_INACTIVE; 3020141cc406Sopenharmony_ci if (!(s->hw->flags & ARTEC_FLAG_MBPP_NEGATIVE)) 3021141cc406Sopenharmony_ci { 3022141cc406Sopenharmony_ci s->opt[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE; 3023141cc406Sopenharmony_ci } 3024141cc406Sopenharmony_ci } 3025141cc406Sopenharmony_ci } 3026141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 3027141cc406Sopenharmony_ci 3028141cc406Sopenharmony_ci case OPT_FILTER_TYPE: 3029141cc406Sopenharmony_ci case OPT_HALFTONE_PATTERN: 3030141cc406Sopenharmony_ci if (s->val[option].s) 3031141cc406Sopenharmony_ci free (s->val[option].s); 3032141cc406Sopenharmony_ci s->val[option].s = strdup (val); 3033141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 3034141cc406Sopenharmony_ci 3035141cc406Sopenharmony_ci case OPT_RESOLUTION_BIND: 3036141cc406Sopenharmony_ci if (s->val[option].w != *(SANE_Word *) val) 3037141cc406Sopenharmony_ci { 3038141cc406Sopenharmony_ci s->val[option].w = *(SANE_Word *) val; 3039141cc406Sopenharmony_ci 3040141cc406Sopenharmony_ci if (info) 3041141cc406Sopenharmony_ci { 3042141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 3043141cc406Sopenharmony_ci } 3044141cc406Sopenharmony_ci 3045141cc406Sopenharmony_ci if (s->val[option].w == SANE_FALSE) 3046141cc406Sopenharmony_ci { /* don't bind */ 3047141cc406Sopenharmony_ci s->opt[OPT_Y_RESOLUTION].cap &= ~SANE_CAP_INACTIVE; 3048141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].title = 3049141cc406Sopenharmony_ci SANE_TITLE_SCAN_X_RESOLUTION; 3050141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].name = 3051141cc406Sopenharmony_ci SANE_NAME_SCAN_RESOLUTION; 3052141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].desc = 3053141cc406Sopenharmony_ci SANE_DESC_SCAN_X_RESOLUTION; 3054141cc406Sopenharmony_ci } 3055141cc406Sopenharmony_ci else 3056141cc406Sopenharmony_ci { /* bind */ 3057141cc406Sopenharmony_ci s->opt[OPT_Y_RESOLUTION].cap |= SANE_CAP_INACTIVE; 3058141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].title = 3059141cc406Sopenharmony_ci SANE_TITLE_SCAN_RESOLUTION; 3060141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].name = 3061141cc406Sopenharmony_ci SANE_NAME_SCAN_RESOLUTION; 3062141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].desc = 3063141cc406Sopenharmony_ci SANE_DESC_SCAN_RESOLUTION; 3064141cc406Sopenharmony_ci } 3065141cc406Sopenharmony_ci } 3066141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 3067141cc406Sopenharmony_ci 3068141cc406Sopenharmony_ci /* side-effect-free word-array options: */ 3069141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 3070141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 3071141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 3072141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 3073141cc406Sopenharmony_ci memcpy (s->val[option].wa, val, s->opt[option].size); 3074141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 3075141cc406Sopenharmony_ci 3076141cc406Sopenharmony_ci /* options with side effects: */ 3077141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 3078141cc406Sopenharmony_ci w = *(SANE_Word *) val; 3079141cc406Sopenharmony_ci if (w == s->val[OPT_CUSTOM_GAMMA].w) 3080141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 3081141cc406Sopenharmony_ci 3082141cc406Sopenharmony_ci s->val[OPT_CUSTOM_GAMMA].w = w; 3083141cc406Sopenharmony_ci if (w) /* use custom_gamma_table */ 3084141cc406Sopenharmony_ci { 3085141cc406Sopenharmony_ci const char *mode = s->val[OPT_MODE].s; 3086141cc406Sopenharmony_ci 3087141cc406Sopenharmony_ci if ((strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) || 3088141cc406Sopenharmony_ci (strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) || 3089141cc406Sopenharmony_ci (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0)) 3090141cc406Sopenharmony_ci { 3091141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; 3092141cc406Sopenharmony_ci } 3093141cc406Sopenharmony_ci else if (strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) 3094141cc406Sopenharmony_ci { 3095141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; 3096141cc406Sopenharmony_ci 3097141cc406Sopenharmony_ci if (!(s->hw->flags & ARTEC_FLAG_GAMMA_SINGLE)) 3098141cc406Sopenharmony_ci { 3099141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; 3100141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; 3101141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; 3102141cc406Sopenharmony_ci } 3103141cc406Sopenharmony_ci } 3104141cc406Sopenharmony_ci } 3105141cc406Sopenharmony_ci else 3106141cc406Sopenharmony_ci /* don't use custom_gamma_table */ 3107141cc406Sopenharmony_ci { 3108141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 3109141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 3110141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 3111141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 3112141cc406Sopenharmony_ci } 3113141cc406Sopenharmony_ci 3114141cc406Sopenharmony_ci if (info) 3115141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 3116141cc406Sopenharmony_ci 3117141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 3118141cc406Sopenharmony_ci } 3119141cc406Sopenharmony_ci } 3120141cc406Sopenharmony_ci 3121141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 3122141cc406Sopenharmony_ci} 3123141cc406Sopenharmony_ci 3124141cc406Sopenharmony_cistatic void 3125141cc406Sopenharmony_ciset_pass_parameters (SANE_Handle handle) 3126141cc406Sopenharmony_ci{ 3127141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 3128141cc406Sopenharmony_ci 3129141cc406Sopenharmony_ci DBG (7, "set_pass_parameters()\n"); 3130141cc406Sopenharmony_ci 3131141cc406Sopenharmony_ci if (s->threepasscolor) 3132141cc406Sopenharmony_ci { 3133141cc406Sopenharmony_ci s->this_pass += 1; 3134141cc406Sopenharmony_ci DBG (9, "set_pass_parameters: three-pass, on %d\n", s->this_pass); 3135141cc406Sopenharmony_ci switch (s->this_pass) 3136141cc406Sopenharmony_ci { 3137141cc406Sopenharmony_ci case 1: 3138141cc406Sopenharmony_ci s->params.format = SANE_FRAME_RED; 3139141cc406Sopenharmony_ci s->params.last_frame = SANE_FALSE; 3140141cc406Sopenharmony_ci break; 3141141cc406Sopenharmony_ci case 2: 3142141cc406Sopenharmony_ci s->params.format = SANE_FRAME_GREEN; 3143141cc406Sopenharmony_ci s->params.last_frame = SANE_FALSE; 3144141cc406Sopenharmony_ci break; 3145141cc406Sopenharmony_ci case 3: 3146141cc406Sopenharmony_ci s->params.format = SANE_FRAME_BLUE; 3147141cc406Sopenharmony_ci s->params.last_frame = SANE_TRUE; 3148141cc406Sopenharmony_ci break; 3149141cc406Sopenharmony_ci default: 3150141cc406Sopenharmony_ci DBG (9, "set_pass_parameters: What?!? pass %d = filter?\n", 3151141cc406Sopenharmony_ci s->this_pass); 3152141cc406Sopenharmony_ci break; 3153141cc406Sopenharmony_ci } 3154141cc406Sopenharmony_ci } 3155141cc406Sopenharmony_ci else 3156141cc406Sopenharmony_ci s->this_pass = 0; 3157141cc406Sopenharmony_ci} 3158141cc406Sopenharmony_ci 3159141cc406Sopenharmony_ciSANE_Status 3160141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 3161141cc406Sopenharmony_ci{ 3162141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 3163141cc406Sopenharmony_ci 3164141cc406Sopenharmony_ci DBG (7, "sane_get_parameters()\n"); 3165141cc406Sopenharmony_ci 3166141cc406Sopenharmony_ci if (!s->scanning) 3167141cc406Sopenharmony_ci { 3168141cc406Sopenharmony_ci double width, height; 3169141cc406Sopenharmony_ci 3170141cc406Sopenharmony_ci memset (&s->params, 0, sizeof (s->params)); 3171141cc406Sopenharmony_ci 3172141cc406Sopenharmony_ci s->x_resolution = s->val[OPT_X_RESOLUTION].w; 3173141cc406Sopenharmony_ci s->y_resolution = s->val[OPT_Y_RESOLUTION].w; 3174141cc406Sopenharmony_ci 3175141cc406Sopenharmony_ci if ((s->val[OPT_RESOLUTION_BIND].w == SANE_TRUE) || 3176141cc406Sopenharmony_ci (s->val[OPT_PREVIEW].w == SANE_TRUE)) 3177141cc406Sopenharmony_ci { 3178141cc406Sopenharmony_ci s->y_resolution = s->x_resolution; 3179141cc406Sopenharmony_ci } 3180141cc406Sopenharmony_ci 3181141cc406Sopenharmony_ci s->tl_x = SANE_UNFIX (s->val[OPT_TL_X].w) / MM_PER_INCH 3182141cc406Sopenharmony_ci * s->x_resolution; 3183141cc406Sopenharmony_ci s->tl_y = SANE_UNFIX (s->val[OPT_TL_Y].w) / MM_PER_INCH 3184141cc406Sopenharmony_ci * s->y_resolution; 3185141cc406Sopenharmony_ci width = SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w); 3186141cc406Sopenharmony_ci height = SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w); 3187141cc406Sopenharmony_ci 3188141cc406Sopenharmony_ci if ((s->x_resolution > 0.0) && 3189141cc406Sopenharmony_ci (s->y_resolution > 0.0) && 3190141cc406Sopenharmony_ci (width > 0.0) && 3191141cc406Sopenharmony_ci (height > 0.0)) 3192141cc406Sopenharmony_ci { 3193141cc406Sopenharmony_ci s->params.pixels_per_line = width * s->x_resolution / MM_PER_INCH + 1; 3194141cc406Sopenharmony_ci s->params.lines = height * s->y_resolution / MM_PER_INCH + 1; 3195141cc406Sopenharmony_ci } 3196141cc406Sopenharmony_ci 3197141cc406Sopenharmony_ci s->onepasscolor = SANE_FALSE; 3198141cc406Sopenharmony_ci s->threepasscolor = SANE_FALSE; 3199141cc406Sopenharmony_ci s->params.last_frame = SANE_TRUE; 3200141cc406Sopenharmony_ci 3201141cc406Sopenharmony_ci if ((s->val[OPT_PREVIEW].w == SANE_TRUE) && 3202141cc406Sopenharmony_ci (s->val[OPT_GRAY_PREVIEW].w == SANE_TRUE)) 3203141cc406Sopenharmony_ci { 3204141cc406Sopenharmony_ci s->mode = SANE_VALUE_SCAN_MODE_GRAY; 3205141cc406Sopenharmony_ci } 3206141cc406Sopenharmony_ci else 3207141cc406Sopenharmony_ci { 3208141cc406Sopenharmony_ci s->mode = s->val[OPT_MODE].s; 3209141cc406Sopenharmony_ci } 3210141cc406Sopenharmony_ci 3211141cc406Sopenharmony_ci if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) || 3212141cc406Sopenharmony_ci (strcmp (s->mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0)) 3213141cc406Sopenharmony_ci { 3214141cc406Sopenharmony_ci s->params.format = SANE_FRAME_GRAY; 3215141cc406Sopenharmony_ci s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8; 3216141cc406Sopenharmony_ci s->params.depth = 1; 3217141cc406Sopenharmony_ci s->line_offset = 0; 3218141cc406Sopenharmony_ci 3219141cc406Sopenharmony_ci /* round pixels_per_line up to the next full byte of pixels */ 3220141cc406Sopenharmony_ci /* this way we don't have to do bit buffering, pixels_per_line is */ 3221141cc406Sopenharmony_ci /* what is used in the set window command. */ 3222141cc406Sopenharmony_ci /* SANE expects the last byte in a line to be padded if it's not */ 3223141cc406Sopenharmony_ci /* full, so this should not affect scans in a negative way */ 3224141cc406Sopenharmony_ci s->params.pixels_per_line = s->params.bytes_per_line * 8; 3225141cc406Sopenharmony_ci } 3226141cc406Sopenharmony_ci else if (strcmp (s->mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) 3227141cc406Sopenharmony_ci { 3228141cc406Sopenharmony_ci s->params.format = SANE_FRAME_GRAY; 3229141cc406Sopenharmony_ci s->params.bytes_per_line = s->params.pixels_per_line; 3230141cc406Sopenharmony_ci s->params.depth = 8; 3231141cc406Sopenharmony_ci s->line_offset = 0; 3232141cc406Sopenharmony_ci } 3233141cc406Sopenharmony_ci else 3234141cc406Sopenharmony_ci { 3235141cc406Sopenharmony_ci s->params.bytes_per_line = s->params.pixels_per_line; 3236141cc406Sopenharmony_ci s->params.depth = 8; 3237141cc406Sopenharmony_ci 3238141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_ONE_PASS_SCANNER) 3239141cc406Sopenharmony_ci { 3240141cc406Sopenharmony_ci s->onepasscolor = SANE_TRUE; 3241141cc406Sopenharmony_ci s->params.format = SANE_FRAME_RGB; 3242141cc406Sopenharmony_ci s->params.bytes_per_line *= 3; 3243141cc406Sopenharmony_ci 3244141cc406Sopenharmony_ci /* 3245141cc406Sopenharmony_ci * line offsets from documentation. 3246141cc406Sopenharmony_ci * (I don't yet see a common formula I can easily use) 3247141cc406Sopenharmony_ci */ 3248141cc406Sopenharmony_ci /* FIXME: figure out a cleaner way to do this... */ 3249141cc406Sopenharmony_ci s->line_offset = 0; /* default */ 3250141cc406Sopenharmony_ci if ((!strcmp (s->hw->sane.model, "AT3")) || 3251141cc406Sopenharmony_ci (!strcmp (s->hw->sane.model, "A6000C")) || 3252141cc406Sopenharmony_ci (!strcmp (s->hw->sane.model, "A6000C PLUS")) || 3253141cc406Sopenharmony_ci (!strcmp (s->hw->sane.model, "AT6"))) 3254141cc406Sopenharmony_ci { 3255141cc406Sopenharmony_ci /* formula #1 */ 3256141cc406Sopenharmony_ci /* ranges from 1 at 50dpi to 16 at 600dpi */ 3257141cc406Sopenharmony_ci s->line_offset = 8 * (s->y_resolution / 300.0); 3258141cc406Sopenharmony_ci } 3259141cc406Sopenharmony_ci else if (!strcmp (s->hw->sane.model, "AT12")) 3260141cc406Sopenharmony_ci { 3261141cc406Sopenharmony_ci /* formula #2 */ 3262141cc406Sopenharmony_ci /* ranges from 0 at 25dpi to 16 at 1200dpi */ 3263141cc406Sopenharmony_ci /***********************************************************/ 3264141cc406Sopenharmony_ci /* this should be handled in hardware for now, so leave it */ 3265141cc406Sopenharmony_ci /* sitting at zero for now. */ 3266141cc406Sopenharmony_ci /***********************************************************/ 3267141cc406Sopenharmony_ci /* 3268141cc406Sopenharmony_ci s->line_offset = 16 * ( s->y_resolution / 1200.0 ); 3269141cc406Sopenharmony_ci */ 3270141cc406Sopenharmony_ci } 3271141cc406Sopenharmony_ci else if (!strcmp (s->hw->sane.model, "AM12S")) 3272141cc406Sopenharmony_ci { 3273141cc406Sopenharmony_ci /* formula #3 */ 3274141cc406Sopenharmony_ci /* ranges from 0 at 50dpi to 8 at 1200dpi */ 3275141cc406Sopenharmony_ci s->line_offset = 8 * (s->y_resolution / 1200.0); 3276141cc406Sopenharmony_ci } 3277141cc406Sopenharmony_ci } 3278141cc406Sopenharmony_ci else 3279141cc406Sopenharmony_ci { 3280141cc406Sopenharmony_ci s->params.last_frame = SANE_FALSE; 3281141cc406Sopenharmony_ci s->threepasscolor = SANE_TRUE; 3282141cc406Sopenharmony_ci s->line_offset = 0; 3283141cc406Sopenharmony_ci } 3284141cc406Sopenharmony_ci } 3285141cc406Sopenharmony_ci } 3286141cc406Sopenharmony_ci 3287141cc406Sopenharmony_ci if (params) 3288141cc406Sopenharmony_ci *params = s->params; 3289141cc406Sopenharmony_ci 3290141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 3291141cc406Sopenharmony_ci} 3292141cc406Sopenharmony_ci 3293141cc406Sopenharmony_ci 3294141cc406Sopenharmony_ciSANE_Status 3295141cc406Sopenharmony_cisane_start (SANE_Handle handle) 3296141cc406Sopenharmony_ci{ 3297141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 3298141cc406Sopenharmony_ci SANE_Status status; 3299141cc406Sopenharmony_ci 3300141cc406Sopenharmony_ci DBG (7, "sane_start()\n"); 3301141cc406Sopenharmony_ci 3302141cc406Sopenharmony_ci if (debug_fd != -1) 3303141cc406Sopenharmony_ci { 3304141cc406Sopenharmony_ci close (debug_fd); 3305141cc406Sopenharmony_ci debug_fd = -1; 3306141cc406Sopenharmony_ci } 3307141cc406Sopenharmony_ci 3308141cc406Sopenharmony_ci if (DBG_LEVEL == 101) 3309141cc406Sopenharmony_ci { 3310141cc406Sopenharmony_ci debug_fd = open ("artec.data.raw", 3311141cc406Sopenharmony_ci O_WRONLY | O_CREAT | O_TRUNC, 0666); 3312141cc406Sopenharmony_ci if (debug_fd > -1) 3313141cc406Sopenharmony_ci DBG (101, "opened artec.data.raw output file\n"); 3314141cc406Sopenharmony_ci } 3315141cc406Sopenharmony_ci 3316141cc406Sopenharmony_ci /* First make sure we have a current parameter set. Some of the */ 3317141cc406Sopenharmony_ci /* parameters will be overwritten below, but that's OK. */ 3318141cc406Sopenharmony_ci status = sane_get_parameters (s, 0); 3319141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3320141cc406Sopenharmony_ci return status; 3321141cc406Sopenharmony_ci 3322141cc406Sopenharmony_ci /* DAL: For 3 pass colour set the current pass parameters */ 3323141cc406Sopenharmony_ci if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) && s->threepasscolor) 3324141cc406Sopenharmony_ci set_pass_parameters (s); 3325141cc406Sopenharmony_ci 3326141cc406Sopenharmony_ci /* DAL: For single pass scans and the first pass of a 3 pass scan */ 3327141cc406Sopenharmony_ci if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) != 0) || 3328141cc406Sopenharmony_ci (!s->threepasscolor) || 3329141cc406Sopenharmony_ci ((s->threepasscolor) && 3330141cc406Sopenharmony_ci (s->this_pass == 1))) 3331141cc406Sopenharmony_ci { 3332141cc406Sopenharmony_ci 3333141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_SENSE_HANDLER) 3334141cc406Sopenharmony_ci { 3335141cc406Sopenharmony_ci status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, 3336141cc406Sopenharmony_ci (void *)s); 3337141cc406Sopenharmony_ci } 3338141cc406Sopenharmony_ci else 3339141cc406Sopenharmony_ci { 3340141cc406Sopenharmony_ci status = sanei_scsi_open (s->hw->sane.name, &s->fd, 0, 0); 3341141cc406Sopenharmony_ci } 3342141cc406Sopenharmony_ci 3343141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3344141cc406Sopenharmony_ci { 3345141cc406Sopenharmony_ci DBG (1, "open of %s failed: %s\n", 3346141cc406Sopenharmony_ci s->hw->sane.name, sane_strstatus (status)); 3347141cc406Sopenharmony_ci return status; 3348141cc406Sopenharmony_ci } 3349141cc406Sopenharmony_ci 3350141cc406Sopenharmony_ci /* DB added wait_ready */ 3351141cc406Sopenharmony_ci status = wait_ready (s->fd); 3352141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3353141cc406Sopenharmony_ci { 3354141cc406Sopenharmony_ci DBG (1, "wait for scanner ready failed: %s\n", 3355141cc406Sopenharmony_ci sane_strstatus (status)); 3356141cc406Sopenharmony_ci return status; 3357141cc406Sopenharmony_ci } 3358141cc406Sopenharmony_ci } 3359141cc406Sopenharmony_ci 3360141cc406Sopenharmony_ci s->bytes_to_read = s->params.bytes_per_line * s->params.lines; 3361141cc406Sopenharmony_ci 3362141cc406Sopenharmony_ci DBG (9, "%d pixels per line, %d bytes, %d lines high, xdpi = %d, " 3363141cc406Sopenharmony_ci "ydpi = %d, btr = %lu\n", 3364141cc406Sopenharmony_ci s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines, 3365141cc406Sopenharmony_ci s->x_resolution, s->y_resolution, (u_long) s->bytes_to_read); 3366141cc406Sopenharmony_ci 3367141cc406Sopenharmony_ci /* DAL: For single pass scans and the first pass of a 3 pass scan */ 3368141cc406Sopenharmony_ci if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) != 0) || !s->threepasscolor || 3369141cc406Sopenharmony_ci (s->threepasscolor && s->this_pass == 1)) 3370141cc406Sopenharmony_ci { 3371141cc406Sopenharmony_ci 3372141cc406Sopenharmony_ci /* do a calibrate if scanner requires/recommends it */ 3373141cc406Sopenharmony_ci if ((s->hw->flags & ARTEC_FLAG_CALIBRATE) && 3374141cc406Sopenharmony_ci (s->val[OPT_QUALITY_CAL].w == SANE_TRUE)) 3375141cc406Sopenharmony_ci { 3376141cc406Sopenharmony_ci status = artec_calibrate_shading (s); 3377141cc406Sopenharmony_ci 3378141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3379141cc406Sopenharmony_ci { 3380141cc406Sopenharmony_ci DBG (1, "shading calibration failed: %s\n", 3381141cc406Sopenharmony_ci sane_strstatus (status)); 3382141cc406Sopenharmony_ci return status; 3383141cc406Sopenharmony_ci } 3384141cc406Sopenharmony_ci } 3385141cc406Sopenharmony_ci 3386141cc406Sopenharmony_ci /* DB added wait_ready */ 3387141cc406Sopenharmony_ci status = wait_ready (s->fd); 3388141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3389141cc406Sopenharmony_ci { 3390141cc406Sopenharmony_ci DBG (1, "wait for scanner ready failed: %s\n", 3391141cc406Sopenharmony_ci sane_strstatus (status)); 3392141cc406Sopenharmony_ci return status; 3393141cc406Sopenharmony_ci } 3394141cc406Sopenharmony_ci 3395141cc406Sopenharmony_ci /* send the custom gamma table if we have one */ 3396141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_GAMMA) 3397141cc406Sopenharmony_ci artec_send_gamma_table (s); 3398141cc406Sopenharmony_ci 3399141cc406Sopenharmony_ci /* now set our scan window */ 3400141cc406Sopenharmony_ci status = artec_set_scan_window (s); 3401141cc406Sopenharmony_ci 3402141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3403141cc406Sopenharmony_ci { 3404141cc406Sopenharmony_ci DBG (1, "set scan window failed: %s\n", 3405141cc406Sopenharmony_ci sane_strstatus (status)); 3406141cc406Sopenharmony_ci return status; 3407141cc406Sopenharmony_ci } 3408141cc406Sopenharmony_ci 3409141cc406Sopenharmony_ci /* DB added wait_ready */ 3410141cc406Sopenharmony_ci status = wait_ready (s->fd); 3411141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3412141cc406Sopenharmony_ci { 3413141cc406Sopenharmony_ci DBG (1, "wait for scanner ready failed: %s\n", 3414141cc406Sopenharmony_ci sane_strstatus (status)); 3415141cc406Sopenharmony_ci return status; 3416141cc406Sopenharmony_ci } 3417141cc406Sopenharmony_ci } 3418141cc406Sopenharmony_ci 3419141cc406Sopenharmony_ci /* now we can start the actual scan */ 3420141cc406Sopenharmony_ci /* DAL: For single pass scans and the first pass of a 3 pass scan */ 3421141cc406Sopenharmony_ci if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) != 0) || 3422141cc406Sopenharmony_ci (!s->threepasscolor) || 3423141cc406Sopenharmony_ci (s->this_pass == 1)) 3424141cc406Sopenharmony_ci { 3425141cc406Sopenharmony_ci /* DAL - do mode select before each scan */ 3426141cc406Sopenharmony_ci /* The mode is NOT turned off at the end of the scan */ 3427141cc406Sopenharmony_ci artec_mode_select (s); 3428141cc406Sopenharmony_ci 3429141cc406Sopenharmony_ci status = artec_start_scan (s); 3430141cc406Sopenharmony_ci 3431141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3432141cc406Sopenharmony_ci { 3433141cc406Sopenharmony_ci DBG (1, "start scan: %s\n", sane_strstatus (status)); 3434141cc406Sopenharmony_ci return status; 3435141cc406Sopenharmony_ci } 3436141cc406Sopenharmony_ci } 3437141cc406Sopenharmony_ci 3438141cc406Sopenharmony_ci s->scanning = SANE_TRUE; 3439141cc406Sopenharmony_ci 3440141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 3441141cc406Sopenharmony_ci} 3442141cc406Sopenharmony_ci 3443141cc406Sopenharmony_ci 3444141cc406Sopenharmony_ci#if 0 3445141cc406Sopenharmony_cistatic void 3446141cc406Sopenharmony_cibinout (SANE_Byte byte) 3447141cc406Sopenharmony_ci{ 3448141cc406Sopenharmony_ci SANE_Byte b = byte; 3449141cc406Sopenharmony_ci int bit; 3450141cc406Sopenharmony_ci 3451141cc406Sopenharmony_ci for (bit = 0; bit < 8; bit++) 3452141cc406Sopenharmony_ci { 3453141cc406Sopenharmony_ci DBG (9, "%d", b & 128 ? 1 : 0); 3454141cc406Sopenharmony_ci b = b << 1; 3455141cc406Sopenharmony_ci } 3456141cc406Sopenharmony_ci} 3457141cc406Sopenharmony_ci#endif 3458141cc406Sopenharmony_ci 3459141cc406Sopenharmony_cistatic SANE_Status 3460141cc406Sopenharmony_ciartec_sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) 3461141cc406Sopenharmony_ci{ 3462141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 3463141cc406Sopenharmony_ci SANE_Status status; 3464141cc406Sopenharmony_ci size_t nread; 3465141cc406Sopenharmony_ci size_t lread; 3466141cc406Sopenharmony_ci size_t bytes_read; 3467141cc406Sopenharmony_ci size_t rows_read; 3468141cc406Sopenharmony_ci size_t max_read_rows; 3469141cc406Sopenharmony_ci size_t max_ret_rows; 3470141cc406Sopenharmony_ci size_t remaining_rows; 3471141cc406Sopenharmony_ci size_t rows_available; 3472141cc406Sopenharmony_ci size_t line; 3473141cc406Sopenharmony_ci SANE_Byte temp_buf[ARTEC_MAX_READ_SIZE]; 3474141cc406Sopenharmony_ci SANE_Byte line_buf[ARTEC_MAX_READ_SIZE]; 3475141cc406Sopenharmony_ci 3476141cc406Sopenharmony_ci 3477141cc406Sopenharmony_ci DBG (7, "artec_sane_read( %p, %p, %d, %d )\n", handle, (void *) buf, max_len, *len); 3478141cc406Sopenharmony_ci 3479141cc406Sopenharmony_ci *len = 0; 3480141cc406Sopenharmony_ci 3481141cc406Sopenharmony_ci if (s->bytes_to_read == 0) 3482141cc406Sopenharmony_ci { 3483141cc406Sopenharmony_ci if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) != 0) || !s->threepasscolor || 3484141cc406Sopenharmony_ci (s->threepasscolor && s->this_pass == 3)) 3485141cc406Sopenharmony_ci { 3486141cc406Sopenharmony_ci do_cancel (s); 3487141cc406Sopenharmony_ci /* without this a 4th pass is attempted, yet do_cancel does this */ 3488141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 3489141cc406Sopenharmony_ci } 3490141cc406Sopenharmony_ci return (SANE_STATUS_EOF); 3491141cc406Sopenharmony_ci } 3492141cc406Sopenharmony_ci 3493141cc406Sopenharmony_ci if (!s->scanning) 3494141cc406Sopenharmony_ci return do_cancel (s); 3495141cc406Sopenharmony_ci 3496141cc406Sopenharmony_ci remaining_rows = (s->bytes_to_read + s->params.bytes_per_line - 1) / s->params.bytes_per_line; 3497141cc406Sopenharmony_ci max_read_rows = s->hw->max_read_size / s->params.bytes_per_line; 3498141cc406Sopenharmony_ci max_ret_rows = max_len / s->params.bytes_per_line; 3499141cc406Sopenharmony_ci 3500141cc406Sopenharmony_ci while (artec_get_status (s->fd) == 0) 3501141cc406Sopenharmony_ci { 3502141cc406Sopenharmony_ci DBG (120, "hokey loop till data available\n"); 3503141cc406Sopenharmony_ci usleep (50000); /* sleep for .05 second */ 3504141cc406Sopenharmony_ci } 3505141cc406Sopenharmony_ci 3506141cc406Sopenharmony_ci rows_read = 0; 3507141cc406Sopenharmony_ci bytes_read = 0; 3508141cc406Sopenharmony_ci while ((rows_read < max_ret_rows) && (rows_read < remaining_rows)) 3509141cc406Sopenharmony_ci { 3510141cc406Sopenharmony_ci DBG (50, "top of while loop, rr = %lu, mrr = %lu, rem = %lu\n", 3511141cc406Sopenharmony_ci (u_long) rows_read, (u_long) max_ret_rows, (u_long) remaining_rows); 3512141cc406Sopenharmony_ci 3513141cc406Sopenharmony_ci if (s->bytes_to_read - bytes_read <= s->params.bytes_per_line * max_read_rows) 3514141cc406Sopenharmony_ci { 3515141cc406Sopenharmony_ci nread = s->bytes_to_read - bytes_read; 3516141cc406Sopenharmony_ci } 3517141cc406Sopenharmony_ci else 3518141cc406Sopenharmony_ci { 3519141cc406Sopenharmony_ci nread = s->params.bytes_per_line * max_read_rows; 3520141cc406Sopenharmony_ci } 3521141cc406Sopenharmony_ci lread = nread / s->params.bytes_per_line; 3522141cc406Sopenharmony_ci 3523141cc406Sopenharmony_ci if ((max_read_rows - rows_read) < lread) 3524141cc406Sopenharmony_ci { 3525141cc406Sopenharmony_ci lread = max_read_rows - rows_read; 3526141cc406Sopenharmony_ci nread = lread * s->params.bytes_per_line; 3527141cc406Sopenharmony_ci } 3528141cc406Sopenharmony_ci 3529141cc406Sopenharmony_ci if ((max_ret_rows - rows_read) < lread) 3530141cc406Sopenharmony_ci { 3531141cc406Sopenharmony_ci lread = max_ret_rows - rows_read; 3532141cc406Sopenharmony_ci nread = lread * s->params.bytes_per_line; 3533141cc406Sopenharmony_ci } 3534141cc406Sopenharmony_ci 3535141cc406Sopenharmony_ci while ((rows_available = artec_get_status (s->fd)) == 0) 3536141cc406Sopenharmony_ci { 3537141cc406Sopenharmony_ci DBG (120, "hokey loop till data available\n"); 3538141cc406Sopenharmony_ci usleep (50000); /* sleep for .05 second */ 3539141cc406Sopenharmony_ci } 3540141cc406Sopenharmony_ci 3541141cc406Sopenharmony_ci if (rows_available < lread) 3542141cc406Sopenharmony_ci { 3543141cc406Sopenharmony_ci lread = rows_available; 3544141cc406Sopenharmony_ci nread = lread * s->params.bytes_per_line; 3545141cc406Sopenharmony_ci } 3546141cc406Sopenharmony_ci 3547141cc406Sopenharmony_ci /* This should never happen, but just in case... */ 3548141cc406Sopenharmony_ci if (nread > (s->bytes_to_read - bytes_read)) 3549141cc406Sopenharmony_ci { 3550141cc406Sopenharmony_ci nread = s->bytes_to_read - bytes_read; 3551141cc406Sopenharmony_ci lread = 1; 3552141cc406Sopenharmony_ci } 3553141cc406Sopenharmony_ci 3554141cc406Sopenharmony_ci DBG (50, "rows_available = %lu, params.lines = %d, bytes_per_line = %d\n", 3555141cc406Sopenharmony_ci (u_long) rows_available, s->params.lines, s->params.bytes_per_line); 3556141cc406Sopenharmony_ci DBG (50, "bytes_to_read = %lu, max_len = %d, max_rows = %lu\n", 3557141cc406Sopenharmony_ci (u_long) s->bytes_to_read, max_len, (u_long) max_ret_rows); 3558141cc406Sopenharmony_ci DBG (50, "nread = %lu, lread = %lu, bytes_read = %lu, rows_read = %lu\n", 3559141cc406Sopenharmony_ci (u_long) nread, (u_long) lread, (u_long) bytes_read, (u_long) rows_read); 3560141cc406Sopenharmony_ci 3561141cc406Sopenharmony_ci status = read_data (s->fd, ARTEC_DATA_IMAGE, temp_buf, &nread); 3562141cc406Sopenharmony_ci 3563141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3564141cc406Sopenharmony_ci { 3565141cc406Sopenharmony_ci end_scan (s); 3566141cc406Sopenharmony_ci do_cancel (s); 3567141cc406Sopenharmony_ci return (SANE_STATUS_IO_ERROR); 3568141cc406Sopenharmony_ci } 3569141cc406Sopenharmony_ci 3570141cc406Sopenharmony_ci if ((DBG_LEVEL == 101) && 3571141cc406Sopenharmony_ci (debug_fd > -1)) 3572141cc406Sopenharmony_ci { 3573141cc406Sopenharmony_ci write (debug_fd, temp_buf, nread); 3574141cc406Sopenharmony_ci } 3575141cc406Sopenharmony_ci 3576141cc406Sopenharmony_ci if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) && 3577141cc406Sopenharmony_ci (s->hw->flags & ARTEC_FLAG_RGB_LINE_OFFSET)) 3578141cc406Sopenharmony_ci { 3579141cc406Sopenharmony_ci for (line = 0; line < lread; line++) 3580141cc406Sopenharmony_ci { 3581141cc406Sopenharmony_ci memcpy (line_buf, 3582141cc406Sopenharmony_ci temp_buf + (line * s->params.bytes_per_line), 3583141cc406Sopenharmony_ci s->params.bytes_per_line); 3584141cc406Sopenharmony_ci 3585141cc406Sopenharmony_ci nread = s->params.bytes_per_line; 3586141cc406Sopenharmony_ci 3587141cc406Sopenharmony_ci artec_buffer_line_offset (s, s->line_offset, line_buf, &nread); 3588141cc406Sopenharmony_ci 3589141cc406Sopenharmony_ci if (nread > 0) 3590141cc406Sopenharmony_ci { 3591141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_RGB_CHAR_SHIFT) 3592141cc406Sopenharmony_ci { 3593141cc406Sopenharmony_ci artec_line_rgb_to_byte_rgb (line_buf, 3594141cc406Sopenharmony_ci s->params.pixels_per_line); 3595141cc406Sopenharmony_ci } 3596141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_IMAGE_REV_LR) 3597141cc406Sopenharmony_ci { 3598141cc406Sopenharmony_ci artec_reverse_line (s, line_buf); 3599141cc406Sopenharmony_ci } 3600141cc406Sopenharmony_ci 3601141cc406Sopenharmony_ci /* do software calibration if necessary */ 3602141cc406Sopenharmony_ci if (s->val[OPT_SOFTWARE_CAL].w) 3603141cc406Sopenharmony_ci { 3604141cc406Sopenharmony_ci artec_software_rgb_calibrate (s, line_buf, 1); 3605141cc406Sopenharmony_ci } 3606141cc406Sopenharmony_ci 3607141cc406Sopenharmony_ci memcpy (buf + bytes_read, line_buf, 3608141cc406Sopenharmony_ci s->params.bytes_per_line); 3609141cc406Sopenharmony_ci bytes_read += nread; 3610141cc406Sopenharmony_ci rows_read++; 3611141cc406Sopenharmony_ci } 3612141cc406Sopenharmony_ci } 3613141cc406Sopenharmony_ci } 3614141cc406Sopenharmony_ci else 3615141cc406Sopenharmony_ci { 3616141cc406Sopenharmony_ci if ((s->hw->flags & ARTEC_FLAG_IMAGE_REV_LR) || 3617141cc406Sopenharmony_ci ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) && 3618141cc406Sopenharmony_ci (s->hw->flags & ARTEC_FLAG_RGB_CHAR_SHIFT))) 3619141cc406Sopenharmony_ci { 3620141cc406Sopenharmony_ci for (line = 0; line < lread; line++) 3621141cc406Sopenharmony_ci { 3622141cc406Sopenharmony_ci if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) && 3623141cc406Sopenharmony_ci (s->hw->flags & ARTEC_FLAG_RGB_CHAR_SHIFT)) 3624141cc406Sopenharmony_ci { 3625141cc406Sopenharmony_ci artec_line_rgb_to_byte_rgb (temp_buf + 3626141cc406Sopenharmony_ci (line * s->params.bytes_per_line), 3627141cc406Sopenharmony_ci s->params.pixels_per_line); 3628141cc406Sopenharmony_ci } 3629141cc406Sopenharmony_ci if (s->hw->flags & ARTEC_FLAG_IMAGE_REV_LR) 3630141cc406Sopenharmony_ci { 3631141cc406Sopenharmony_ci artec_reverse_line (s, temp_buf + 3632141cc406Sopenharmony_ci (line * s->params.bytes_per_line)); 3633141cc406Sopenharmony_ci } 3634141cc406Sopenharmony_ci } 3635141cc406Sopenharmony_ci } 3636141cc406Sopenharmony_ci 3637141cc406Sopenharmony_ci /* do software calibration if necessary */ 3638141cc406Sopenharmony_ci if ((s->val[OPT_SOFTWARE_CAL].w) && 3639141cc406Sopenharmony_ci (strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) == 0)) 3640141cc406Sopenharmony_ci { 3641141cc406Sopenharmony_ci artec_software_rgb_calibrate (s, temp_buf, lread); 3642141cc406Sopenharmony_ci } 3643141cc406Sopenharmony_ci 3644141cc406Sopenharmony_ci memcpy (buf + bytes_read, temp_buf, nread); 3645141cc406Sopenharmony_ci bytes_read += nread; 3646141cc406Sopenharmony_ci rows_read += lread; 3647141cc406Sopenharmony_ci } 3648141cc406Sopenharmony_ci } 3649141cc406Sopenharmony_ci 3650141cc406Sopenharmony_ci *len = bytes_read; 3651141cc406Sopenharmony_ci s->bytes_to_read -= bytes_read; 3652141cc406Sopenharmony_ci 3653141cc406Sopenharmony_ci DBG (9, "artec_sane_read() returning, we read %lu bytes, %lu left\n", 3654141cc406Sopenharmony_ci (u_long) * len, (u_long) s->bytes_to_read); 3655141cc406Sopenharmony_ci 3656141cc406Sopenharmony_ci if ((s->bytes_to_read == 0) && 3657141cc406Sopenharmony_ci (s->hw->flags & ARTEC_FLAG_RGB_LINE_OFFSET) && 3658141cc406Sopenharmony_ci (tmp_line_buf != NULL)) 3659141cc406Sopenharmony_ci { 3660141cc406Sopenharmony_ci artec_buffer_line_offset_free (); 3661141cc406Sopenharmony_ci } 3662141cc406Sopenharmony_ci 3663141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 3664141cc406Sopenharmony_ci} 3665141cc406Sopenharmony_ci 3666141cc406Sopenharmony_ciSANE_Status 3667141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) 3668141cc406Sopenharmony_ci{ 3669141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 3670141cc406Sopenharmony_ci SANE_Status status; 3671141cc406Sopenharmony_ci int bytes_to_copy; 3672141cc406Sopenharmony_ci int loop; 3673141cc406Sopenharmony_ci 3674141cc406Sopenharmony_ci static SANE_Byte temp_buf[ARTEC_MAX_READ_SIZE]; 3675141cc406Sopenharmony_ci static int bytes_in_buf = 0; 3676141cc406Sopenharmony_ci 3677141cc406Sopenharmony_ci DBG (7, "sane_read( %p, %p, %d, %d )\n", handle, (void *) buf, max_len, *len); 3678141cc406Sopenharmony_ci DBG (9, "sane_read: bib = %d, ml = %d\n", bytes_in_buf, max_len); 3679141cc406Sopenharmony_ci 3680141cc406Sopenharmony_ci if (bytes_in_buf != 0) 3681141cc406Sopenharmony_ci { 3682141cc406Sopenharmony_ci bytes_to_copy = max_len < bytes_in_buf ? max_len : bytes_in_buf; 3683141cc406Sopenharmony_ci } 3684141cc406Sopenharmony_ci else 3685141cc406Sopenharmony_ci { 3686141cc406Sopenharmony_ci status = artec_sane_read (s, temp_buf, s->hw->max_read_size, len); 3687141cc406Sopenharmony_ci 3688141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3689141cc406Sopenharmony_ci { 3690141cc406Sopenharmony_ci return (status); 3691141cc406Sopenharmony_ci } 3692141cc406Sopenharmony_ci 3693141cc406Sopenharmony_ci bytes_in_buf = *len; 3694141cc406Sopenharmony_ci 3695141cc406Sopenharmony_ci if (*len == 0) 3696141cc406Sopenharmony_ci { 3697141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 3698141cc406Sopenharmony_ci } 3699141cc406Sopenharmony_ci 3700141cc406Sopenharmony_ci bytes_to_copy = max_len < s->hw->max_read_size ? 3701141cc406Sopenharmony_ci max_len : s->hw->max_read_size; 3702141cc406Sopenharmony_ci bytes_to_copy = *len < bytes_to_copy ? *len : bytes_to_copy; 3703141cc406Sopenharmony_ci } 3704141cc406Sopenharmony_ci 3705141cc406Sopenharmony_ci memcpy (buf, temp_buf, bytes_to_copy); 3706141cc406Sopenharmony_ci bytes_in_buf -= bytes_to_copy; 3707141cc406Sopenharmony_ci *len = bytes_to_copy; 3708141cc406Sopenharmony_ci 3709141cc406Sopenharmony_ci DBG (9, "sane_read: btc = %d, bib now = %d\n", 3710141cc406Sopenharmony_ci bytes_to_copy, bytes_in_buf); 3711141cc406Sopenharmony_ci 3712141cc406Sopenharmony_ci for (loop = 0; loop < bytes_in_buf; loop++) 3713141cc406Sopenharmony_ci { 3714141cc406Sopenharmony_ci temp_buf[loop] = temp_buf[loop + bytes_to_copy]; 3715141cc406Sopenharmony_ci } 3716141cc406Sopenharmony_ci 3717141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 3718141cc406Sopenharmony_ci} 3719141cc406Sopenharmony_ci 3720141cc406Sopenharmony_civoid 3721141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 3722141cc406Sopenharmony_ci{ 3723141cc406Sopenharmony_ci ARTEC_Scanner *s = handle; 3724141cc406Sopenharmony_ci 3725141cc406Sopenharmony_ci DBG (7, "sane_cancel()\n"); 3726141cc406Sopenharmony_ci 3727141cc406Sopenharmony_ci if (s->scanning) 3728141cc406Sopenharmony_ci { 3729141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 3730141cc406Sopenharmony_ci 3731141cc406Sopenharmony_ci abort_scan (s); 3732141cc406Sopenharmony_ci 3733141cc406Sopenharmony_ci do_cancel (s); 3734141cc406Sopenharmony_ci } 3735141cc406Sopenharmony_ci} 3736141cc406Sopenharmony_ci 3737141cc406Sopenharmony_ciSANE_Status 3738141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 3739141cc406Sopenharmony_ci{ 3740141cc406Sopenharmony_ci DBG (7, "sane_set_io_mode( %p, %d )\n", handle, non_blocking); 3741141cc406Sopenharmony_ci 3742141cc406Sopenharmony_ci return (SANE_STATUS_UNSUPPORTED); 3743141cc406Sopenharmony_ci} 3744141cc406Sopenharmony_ci 3745141cc406Sopenharmony_ciSANE_Status 3746141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd) 3747141cc406Sopenharmony_ci{ 3748141cc406Sopenharmony_ci DBG (7, "sane_get_select_fd( %p, %d )\n", handle, *fd ); 3749141cc406Sopenharmony_ci 3750141cc406Sopenharmony_ci return (SANE_STATUS_UNSUPPORTED); 3751141cc406Sopenharmony_ci} 3752