1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci Copyright (C) 2002 Frank Zago (sane at zago dot net) 4141cc406Sopenharmony_ci 5141cc406Sopenharmony_ci This file is part of the SANE package. 6141cc406Sopenharmony_ci 7141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 8141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 9141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 10141cc406Sopenharmony_ci License, or (at your option) any later version. 11141cc406Sopenharmony_ci 12141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 13141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 14141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15141cc406Sopenharmony_ci General Public License for more details. 16141cc406Sopenharmony_ci 17141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 18141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 21141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 22141cc406Sopenharmony_ci 23141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 24141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 25141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 26141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 27141cc406Sopenharmony_ci account of linking the SANE library code into it. 28141cc406Sopenharmony_ci 29141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 30141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 31141cc406Sopenharmony_ci License. 32141cc406Sopenharmony_ci 33141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 34141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 35141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 36141cc406Sopenharmony_ci 37141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 38141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 39141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 40141cc406Sopenharmony_ci*/ 41141cc406Sopenharmony_ci 42141cc406Sopenharmony_ci/* 43141cc406Sopenharmony_ci Some Relisys scanners AVEC and RELI series 44141cc406Sopenharmony_ci*/ 45141cc406Sopenharmony_ci 46141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 47141cc406Sopenharmony_ci 48141cc406Sopenharmony_ci#define BUILD 10 /* 2004/02/08 */ 49141cc406Sopenharmony_ci#define BACKEND_NAME teco1 50141cc406Sopenharmony_ci#define TECO_CONFIG_FILE "teco1.conf" 51141cc406Sopenharmony_ci 52141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 53141cc406Sopenharmony_ci 54141cc406Sopenharmony_ci#include "../include/sane/config.h" 55141cc406Sopenharmony_ci 56141cc406Sopenharmony_ci#include <errno.h> 57141cc406Sopenharmony_ci#include <fcntl.h> 58141cc406Sopenharmony_ci#include <limits.h> 59141cc406Sopenharmony_ci#include <signal.h> 60141cc406Sopenharmony_ci#include <stdio.h> 61141cc406Sopenharmony_ci#include <stdlib.h> 62141cc406Sopenharmony_ci#include <string.h> 63141cc406Sopenharmony_ci#include <sys/types.h> 64141cc406Sopenharmony_ci#include <sys/wait.h> 65141cc406Sopenharmony_ci#include <unistd.h> 66141cc406Sopenharmony_ci 67141cc406Sopenharmony_ci#include "../include/sane/sane.h" 68141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 69141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 70141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h" 71141cc406Sopenharmony_ci#include "../include/sane/sanei_debug.h" 72141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 73141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 74141cc406Sopenharmony_ci#include "../include/lassert.h" 75141cc406Sopenharmony_ci 76141cc406Sopenharmony_ci#include "teco1.h" 77141cc406Sopenharmony_ci 78141cc406Sopenharmony_ci#undef sim 79141cc406Sopenharmony_ci#ifdef sim 80141cc406Sopenharmony_ci#define sanei_scsi_cmd2(a, b, c, d, e, f, g) SANE_STATUS_GOOD 81141cc406Sopenharmony_ci#define sanei_scsi_open(a, b, c, d) 0 82141cc406Sopenharmony_ci#define sanei_scsi_cmd(a, b, c, d, e) SANE_STATUS_GOOD 83141cc406Sopenharmony_ci#define sanei_scsi_close(a) SANE_STATUS_GOOD 84141cc406Sopenharmony_ci#endif 85141cc406Sopenharmony_ci 86141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 87141cc406Sopenharmony_ci 88141cc406Sopenharmony_ci/* Lists of possible scan modes. */ 89141cc406Sopenharmony_cistatic SANE_String_Const scan_mode_list[] = { 90141cc406Sopenharmony_ci BLACK_WHITE_STR, 91141cc406Sopenharmony_ci GRAY_STR, 92141cc406Sopenharmony_ci COLOR_STR, 93141cc406Sopenharmony_ci NULL 94141cc406Sopenharmony_ci}; 95141cc406Sopenharmony_ci 96141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 97141cc406Sopenharmony_ci 98141cc406Sopenharmony_ci/* Minimum and maximum width and length supported. */ 99141cc406Sopenharmony_cistatic SANE_Range x_range = { SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0 }; 100141cc406Sopenharmony_cistatic SANE_Range y_range = { SANE_FIX (0), SANE_FIX (14 * MM_PER_INCH), 0 }; 101141cc406Sopenharmony_ci 102141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 103141cc406Sopenharmony_ci 104141cc406Sopenharmony_ci/* Gamma range */ 105141cc406Sopenharmony_cistatic const SANE_Range gamma_range = { 106141cc406Sopenharmony_ci 0, /* minimum */ 107141cc406Sopenharmony_ci 255, /* maximum */ 108141cc406Sopenharmony_ci 0 /* quantization */ 109141cc406Sopenharmony_ci}; 110141cc406Sopenharmony_ci 111141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 112141cc406Sopenharmony_ci 113141cc406Sopenharmony_ci/* List of dithering options. */ 114141cc406Sopenharmony_cistatic SANE_String_Const dither_list[] = { 115141cc406Sopenharmony_ci "Line art", 116141cc406Sopenharmony_ci "2x2", 117141cc406Sopenharmony_ci "3x3", 118141cc406Sopenharmony_ci "4x4 bayer", 119141cc406Sopenharmony_ci "4x4 smooth", 120141cc406Sopenharmony_ci "8x8 bayer", 121141cc406Sopenharmony_ci "8x8 smooth", 122141cc406Sopenharmony_ci "8x8 horizontal", 123141cc406Sopenharmony_ci "8x8 vertical", 124141cc406Sopenharmony_ci NULL 125141cc406Sopenharmony_ci}; 126141cc406Sopenharmony_cistatic const int dither_val[] = { 127141cc406Sopenharmony_ci 0x00, 128141cc406Sopenharmony_ci 0x01, 129141cc406Sopenharmony_ci 0x02, 130141cc406Sopenharmony_ci 0x03, 131141cc406Sopenharmony_ci 0x04, 132141cc406Sopenharmony_ci 0x05, 133141cc406Sopenharmony_ci 0x06, 134141cc406Sopenharmony_ci 0x07, 135141cc406Sopenharmony_ci 0x08 136141cc406Sopenharmony_ci}; 137141cc406Sopenharmony_ci 138141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 139141cc406Sopenharmony_ci 140141cc406Sopenharmony_cistatic const SANE_Range threshold_range = { 141141cc406Sopenharmony_ci 0, /* minimum */ 142141cc406Sopenharmony_ci 255, /* maximum */ 143141cc406Sopenharmony_ci 0 /* quantization */ 144141cc406Sopenharmony_ci}; 145141cc406Sopenharmony_ci 146141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 147141cc406Sopenharmony_ci 148141cc406Sopenharmony_ci/* Define the supported scanners and their characteristics. */ 149141cc406Sopenharmony_cistatic const struct scanners_supported scanners[] = { 150141cc406Sopenharmony_ci {6, "TECO VM3510", /* *fake id*, see teco_identify_scanner */ 151141cc406Sopenharmony_ci TECO_VM3510, 152141cc406Sopenharmony_ci "Dextra", "DF-600P", 153141cc406Sopenharmony_ci {1, 600, 1}, /* resolution */ 154141cc406Sopenharmony_ci 300, 600, /* max x and Y res */ 155141cc406Sopenharmony_ci 3, /* color 3 pass */ 156141cc406Sopenharmony_ci 256, /* number of bytes per gamma color */ 157141cc406Sopenharmony_ci 80 /* number of bytes in a window */ 158141cc406Sopenharmony_ci }, 159141cc406Sopenharmony_ci 160141cc406Sopenharmony_ci {6, "TECO VM353A", 161141cc406Sopenharmony_ci TECO_VM353A, 162141cc406Sopenharmony_ci "Relisys", "RELI 2412", 163141cc406Sopenharmony_ci {1, 1200, 1}, /* resolution */ 164141cc406Sopenharmony_ci 300, 1200, /* max x and Y resolution */ 165141cc406Sopenharmony_ci 1, /* color 1 pass */ 166141cc406Sopenharmony_ci 256, /* number of bytes per gamma color */ 167141cc406Sopenharmony_ci 99 /* number of bytes in a window */ 168141cc406Sopenharmony_ci }, 169141cc406Sopenharmony_ci 170141cc406Sopenharmony_ci {6, "TECO VM3520", 171141cc406Sopenharmony_ci TECO_VM3520, 172141cc406Sopenharmony_ci "Relisys", "AVEC Colour Office 2400", 173141cc406Sopenharmony_ci {1, 600, 1}, /* resolution */ 174141cc406Sopenharmony_ci 300, 600, /* max x and Y resolution */ 175141cc406Sopenharmony_ci 3, /* color 3 pass */ 176141cc406Sopenharmony_ci 256, /* number of bytes per gamma color */ 177141cc406Sopenharmony_ci 99 /* number of bytes in a window */ 178141cc406Sopenharmony_ci }, 179141cc406Sopenharmony_ci 180141cc406Sopenharmony_ci {6, "TECO VM352A", 181141cc406Sopenharmony_ci TECO_VM3520, /* same as AVEC 2400 */ 182141cc406Sopenharmony_ci "Relisys", "AVEC Colour 2412", 183141cc406Sopenharmony_ci {1, 600, 1}, 184141cc406Sopenharmony_ci 300, 600, 185141cc406Sopenharmony_ci 3, 186141cc406Sopenharmony_ci 256, 187141cc406Sopenharmony_ci 99 188141cc406Sopenharmony_ci }, 189141cc406Sopenharmony_ci 190141cc406Sopenharmony_ci {6, "TECO VM4540", 191141cc406Sopenharmony_ci TECO_VM4540, 192141cc406Sopenharmony_ci "Relisys", "RELI 4816", 193141cc406Sopenharmony_ci {1, 1600, 1}, /* resolution */ 194141cc406Sopenharmony_ci 400, 1600, /* max x and Y resolution */ 195141cc406Sopenharmony_ci 1, /* color 1 pass */ 196141cc406Sopenharmony_ci 256, /* number of bytes per gamma color */ 197141cc406Sopenharmony_ci 99 /* number of bytes in a window */ 198141cc406Sopenharmony_ci }, 199141cc406Sopenharmony_ci 200141cc406Sopenharmony_ci {6, "TECO VM4542", 201141cc406Sopenharmony_ci TECO_VM4542, 202141cc406Sopenharmony_ci "Relisys", "RELI 4830", 203141cc406Sopenharmony_ci {1, 400, 1}, /* resolution */ 204141cc406Sopenharmony_ci 400, 400, /* max x and Y resolution */ 205141cc406Sopenharmony_ci 1, /* color 1 pass */ 206141cc406Sopenharmony_ci 1024, /* number of bytes per gamma color */ 207141cc406Sopenharmony_ci 99 /* number of bytes in a window */ 208141cc406Sopenharmony_ci } 209141cc406Sopenharmony_ci}; 210141cc406Sopenharmony_ci 211141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 212141cc406Sopenharmony_ci 213141cc406Sopenharmony_ci/* List of scanner attached. */ 214141cc406Sopenharmony_cistatic Teco_Scanner *first_dev = NULL; 215141cc406Sopenharmony_cistatic int num_devices = 0; 216141cc406Sopenharmony_cistatic const SANE_Device **devlist = NULL; 217141cc406Sopenharmony_ci 218141cc406Sopenharmony_ci 219141cc406Sopenharmony_ci/* Local functions. */ 220141cc406Sopenharmony_ci 221141cc406Sopenharmony_ci/* Display a buffer in the log. */ 222141cc406Sopenharmony_cistatic void 223141cc406Sopenharmony_cihexdump (int level, const char *comment, unsigned char *p, int l) 224141cc406Sopenharmony_ci{ 225141cc406Sopenharmony_ci int i; 226141cc406Sopenharmony_ci char line[128]; 227141cc406Sopenharmony_ci char *ptr; 228141cc406Sopenharmony_ci char asc_buf[17]; 229141cc406Sopenharmony_ci char *asc_ptr; 230141cc406Sopenharmony_ci 231141cc406Sopenharmony_ci DBG (level, "%s\n", comment); 232141cc406Sopenharmony_ci 233141cc406Sopenharmony_ci ptr = line; 234141cc406Sopenharmony_ci *ptr = '\0'; 235141cc406Sopenharmony_ci asc_ptr = asc_buf; 236141cc406Sopenharmony_ci *asc_ptr = '\0'; 237141cc406Sopenharmony_ci 238141cc406Sopenharmony_ci for (i = 0; i < l; i++, p++) 239141cc406Sopenharmony_ci { 240141cc406Sopenharmony_ci if ((i % 16) == 0) 241141cc406Sopenharmony_ci { 242141cc406Sopenharmony_ci if (ptr != line) 243141cc406Sopenharmony_ci { 244141cc406Sopenharmony_ci DBG (level, "%s %s\n", line, asc_buf); 245141cc406Sopenharmony_ci ptr = line; 246141cc406Sopenharmony_ci *ptr = '\0'; 247141cc406Sopenharmony_ci asc_ptr = asc_buf; 248141cc406Sopenharmony_ci *asc_ptr = '\0'; 249141cc406Sopenharmony_ci } 250141cc406Sopenharmony_ci sprintf (ptr, "%3.3d:", i); 251141cc406Sopenharmony_ci ptr += 4; 252141cc406Sopenharmony_ci } 253141cc406Sopenharmony_ci ptr += sprintf (ptr, " %2.2x", *p); 254141cc406Sopenharmony_ci if (*p >= 32 && *p <= 127) 255141cc406Sopenharmony_ci { 256141cc406Sopenharmony_ci asc_ptr += sprintf (asc_ptr, "%c", *p); 257141cc406Sopenharmony_ci } 258141cc406Sopenharmony_ci else 259141cc406Sopenharmony_ci { 260141cc406Sopenharmony_ci asc_ptr += sprintf (asc_ptr, "."); 261141cc406Sopenharmony_ci } 262141cc406Sopenharmony_ci } 263141cc406Sopenharmony_ci *ptr = '\0'; 264141cc406Sopenharmony_ci DBG (level, "%s %s\n", line, asc_buf); 265141cc406Sopenharmony_ci} 266141cc406Sopenharmony_ci 267141cc406Sopenharmony_ci/* Returns the length of the longest string, including the terminating 268141cc406Sopenharmony_ci * character. */ 269141cc406Sopenharmony_cistatic size_t 270141cc406Sopenharmony_cimax_string_size (SANE_String_Const strings[]) 271141cc406Sopenharmony_ci{ 272141cc406Sopenharmony_ci size_t size, max_size = 0; 273141cc406Sopenharmony_ci int i; 274141cc406Sopenharmony_ci 275141cc406Sopenharmony_ci for (i = 0; strings[i]; ++i) 276141cc406Sopenharmony_ci { 277141cc406Sopenharmony_ci size = strlen (strings[i]) + 1; 278141cc406Sopenharmony_ci if (size > max_size) 279141cc406Sopenharmony_ci { 280141cc406Sopenharmony_ci max_size = size; 281141cc406Sopenharmony_ci } 282141cc406Sopenharmony_ci } 283141cc406Sopenharmony_ci 284141cc406Sopenharmony_ci return max_size; 285141cc406Sopenharmony_ci} 286141cc406Sopenharmony_ci 287141cc406Sopenharmony_ci/* Lookup a string list from one array and return its index. */ 288141cc406Sopenharmony_cistatic int 289141cc406Sopenharmony_ciget_string_list_index (SANE_String_Const list[], SANE_String_Const name) 290141cc406Sopenharmony_ci{ 291141cc406Sopenharmony_ci int index; 292141cc406Sopenharmony_ci 293141cc406Sopenharmony_ci index = 0; 294141cc406Sopenharmony_ci while (list[index] != NULL) 295141cc406Sopenharmony_ci { 296141cc406Sopenharmony_ci if (strcmp (list[index], name) == 0) 297141cc406Sopenharmony_ci { 298141cc406Sopenharmony_ci return (index); 299141cc406Sopenharmony_ci } 300141cc406Sopenharmony_ci index++; 301141cc406Sopenharmony_ci } 302141cc406Sopenharmony_ci 303141cc406Sopenharmony_ci DBG (DBG_error, "name %s not found in list\n", name); 304141cc406Sopenharmony_ci 305141cc406Sopenharmony_ci assert (0 == 1); /* bug in backend, core dump */ 306141cc406Sopenharmony_ci 307141cc406Sopenharmony_ci return (-1); 308141cc406Sopenharmony_ci} 309141cc406Sopenharmony_ci 310141cc406Sopenharmony_ci/* Initialize a scanner entry. Return an allocated scanner with some 311141cc406Sopenharmony_ci * preset values. */ 312141cc406Sopenharmony_cistatic Teco_Scanner * 313141cc406Sopenharmony_citeco_init (void) 314141cc406Sopenharmony_ci{ 315141cc406Sopenharmony_ci Teco_Scanner *dev; 316141cc406Sopenharmony_ci 317141cc406Sopenharmony_ci DBG (DBG_proc, "teco_init: enter\n"); 318141cc406Sopenharmony_ci 319141cc406Sopenharmony_ci /* Allocate a new scanner entry. */ 320141cc406Sopenharmony_ci dev = malloc (sizeof (Teco_Scanner)); 321141cc406Sopenharmony_ci if (dev == NULL) 322141cc406Sopenharmony_ci { 323141cc406Sopenharmony_ci return NULL; 324141cc406Sopenharmony_ci } 325141cc406Sopenharmony_ci 326141cc406Sopenharmony_ci memset (dev, 0, sizeof (Teco_Scanner)); 327141cc406Sopenharmony_ci 328141cc406Sopenharmony_ci /* Allocate the buffer used to transfer the SCSI data. */ 329141cc406Sopenharmony_ci dev->buffer_size = 64 * 1024; 330141cc406Sopenharmony_ci dev->buffer = malloc (dev->buffer_size); 331141cc406Sopenharmony_ci if (dev->buffer == NULL) 332141cc406Sopenharmony_ci { 333141cc406Sopenharmony_ci free (dev); 334141cc406Sopenharmony_ci return NULL; 335141cc406Sopenharmony_ci } 336141cc406Sopenharmony_ci 337141cc406Sopenharmony_ci /* Allocate a buffer to store the temporary image. */ 338141cc406Sopenharmony_ci dev->image_size = 64 * 1024; /* enough for 1 line at max res */ 339141cc406Sopenharmony_ci dev->image = malloc (dev->image_size); 340141cc406Sopenharmony_ci if (dev->image == NULL) 341141cc406Sopenharmony_ci { 342141cc406Sopenharmony_ci free (dev->buffer); 343141cc406Sopenharmony_ci free (dev); 344141cc406Sopenharmony_ci return NULL; 345141cc406Sopenharmony_ci } 346141cc406Sopenharmony_ci 347141cc406Sopenharmony_ci dev->sfd = -1; 348141cc406Sopenharmony_ci 349141cc406Sopenharmony_ci DBG (DBG_proc, "teco_init: exit\n"); 350141cc406Sopenharmony_ci 351141cc406Sopenharmony_ci return (dev); 352141cc406Sopenharmony_ci} 353141cc406Sopenharmony_ci 354141cc406Sopenharmony_ci/* Closes an open scanner. */ 355141cc406Sopenharmony_cistatic void 356141cc406Sopenharmony_citeco_close (Teco_Scanner * dev) 357141cc406Sopenharmony_ci{ 358141cc406Sopenharmony_ci DBG (DBG_proc, "teco_close: enter\n"); 359141cc406Sopenharmony_ci 360141cc406Sopenharmony_ci if (dev->sfd != -1) 361141cc406Sopenharmony_ci { 362141cc406Sopenharmony_ci sanei_scsi_close (dev->sfd); 363141cc406Sopenharmony_ci dev->sfd = -1; 364141cc406Sopenharmony_ci } 365141cc406Sopenharmony_ci 366141cc406Sopenharmony_ci DBG (DBG_proc, "teco_close: exit\n"); 367141cc406Sopenharmony_ci} 368141cc406Sopenharmony_ci 369141cc406Sopenharmony_ci/* Frees the memory used by a scanner. */ 370141cc406Sopenharmony_cistatic void 371141cc406Sopenharmony_citeco_free (Teco_Scanner * dev) 372141cc406Sopenharmony_ci{ 373141cc406Sopenharmony_ci int i; 374141cc406Sopenharmony_ci 375141cc406Sopenharmony_ci DBG (DBG_proc, "teco_free: enter\n"); 376141cc406Sopenharmony_ci 377141cc406Sopenharmony_ci if (dev == NULL) 378141cc406Sopenharmony_ci return; 379141cc406Sopenharmony_ci 380141cc406Sopenharmony_ci teco_close (dev); 381141cc406Sopenharmony_ci if (dev->devicename) 382141cc406Sopenharmony_ci { 383141cc406Sopenharmony_ci free (dev->devicename); 384141cc406Sopenharmony_ci } 385141cc406Sopenharmony_ci if (dev->buffer) 386141cc406Sopenharmony_ci { 387141cc406Sopenharmony_ci free (dev->buffer); 388141cc406Sopenharmony_ci } 389141cc406Sopenharmony_ci if (dev->image) 390141cc406Sopenharmony_ci { 391141cc406Sopenharmony_ci free (dev->image); 392141cc406Sopenharmony_ci } 393141cc406Sopenharmony_ci for (i = 1; i < OPT_NUM_OPTIONS; i++) 394141cc406Sopenharmony_ci { 395141cc406Sopenharmony_ci if (dev->opt[i].type == SANE_TYPE_STRING && dev->val[i].s) 396141cc406Sopenharmony_ci { 397141cc406Sopenharmony_ci free (dev->val[i].s); 398141cc406Sopenharmony_ci } 399141cc406Sopenharmony_ci } 400141cc406Sopenharmony_ci 401141cc406Sopenharmony_ci free (dev); 402141cc406Sopenharmony_ci 403141cc406Sopenharmony_ci DBG (DBG_proc, "teco_free: exit\n"); 404141cc406Sopenharmony_ci} 405141cc406Sopenharmony_ci 406141cc406Sopenharmony_ci/* Inquiry a device and returns TRUE if is supported. */ 407141cc406Sopenharmony_cistatic int 408141cc406Sopenharmony_citeco_identify_scanner (Teco_Scanner * dev) 409141cc406Sopenharmony_ci{ 410141cc406Sopenharmony_ci CDB cdb; 411141cc406Sopenharmony_ci SANE_Status status; 412141cc406Sopenharmony_ci size_t size; 413141cc406Sopenharmony_ci int i; 414141cc406Sopenharmony_ci 415141cc406Sopenharmony_ci DBG (DBG_proc, "teco_identify_scanner: enter\n"); 416141cc406Sopenharmony_ci 417141cc406Sopenharmony_ci size = 5; 418141cc406Sopenharmony_ci MKSCSI_INQUIRY (cdb, size); 419141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 420141cc406Sopenharmony_ci NULL, 0, dev->buffer, &size); 421141cc406Sopenharmony_ci 422141cc406Sopenharmony_ci if (status) 423141cc406Sopenharmony_ci { 424141cc406Sopenharmony_ci DBG (DBG_error, 425141cc406Sopenharmony_ci "teco_identify_scanner: inquiry failed with status %s\n", 426141cc406Sopenharmony_ci sane_strstatus (status)); 427141cc406Sopenharmony_ci return (SANE_FALSE); 428141cc406Sopenharmony_ci } 429141cc406Sopenharmony_ci 430141cc406Sopenharmony_ci#ifdef sim 431141cc406Sopenharmony_ci { 432141cc406Sopenharmony_ci#if 1 433141cc406Sopenharmony_ci /* vm3510 / Dextra DF-600P */ 434141cc406Sopenharmony_ci unsigned char table[] = { 435141cc406Sopenharmony_ci 0x06, 0x00, 0x02, 0x02, 0x24, 0x00, 0x00, 0x10, 0x44, 0x46, 436141cc406Sopenharmony_ci 0x2D, 0x36, 0x30, 0x30, 0x4D, 0x20, 0x20, 0x20, 0x20, 0x20, 437141cc406Sopenharmony_ci 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 438141cc406Sopenharmony_ci 0x20, 0x20, 0x31, 0x2E, 0x31, 0x37, 0x31, 0x2E, 0x31, 0x37, 439141cc406Sopenharmony_ci 0x02 440141cc406Sopenharmony_ci }; 441141cc406Sopenharmony_ci#endif 442141cc406Sopenharmony_ci 443141cc406Sopenharmony_ci#if 0 444141cc406Sopenharmony_ci /* vm4542 */ 445141cc406Sopenharmony_ci unsigned char table[] = { 446141cc406Sopenharmony_ci 0x06, 0x00, 0x02, 0x02, 0x30, 0x00, 0x00, 0x10, 0x52, 0x45, 0x4c, 0x49, 447141cc406Sopenharmony_ci 0x53, 0x59, 0x53, 0x20, 0x52, 0x45, 0x4c, 0x49, 0x20, 0x34, 0x38, 448141cc406Sopenharmony_ci 0x33, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x2e, 449141cc406Sopenharmony_ci 0x30, 0x33, 0x31, 0x2e, 0x30, 0x33, 0x02, 0x00, 0x54, 0x45, 0x43, 450141cc406Sopenharmony_ci 0x4f, 0x20, 0x56, 0x4d, 0x34, 0x35, 0x34, 0x32 451141cc406Sopenharmony_ci }; 452141cc406Sopenharmony_ci#endif 453141cc406Sopenharmony_ci memcpy (dev->buffer, table, sizeof (table)); 454141cc406Sopenharmony_ci } 455141cc406Sopenharmony_ci#endif 456141cc406Sopenharmony_ci 457141cc406Sopenharmony_ci size = dev->buffer[4] + 5; /* total length of the inquiry data */ 458141cc406Sopenharmony_ci 459141cc406Sopenharmony_ci MKSCSI_INQUIRY (cdb, size); 460141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 461141cc406Sopenharmony_ci NULL, 0, dev->buffer, &size); 462141cc406Sopenharmony_ci 463141cc406Sopenharmony_ci if (status) 464141cc406Sopenharmony_ci { 465141cc406Sopenharmony_ci DBG (DBG_error, 466141cc406Sopenharmony_ci "teco_identify_scanner: inquiry failed with status %s\n", 467141cc406Sopenharmony_ci sane_strstatus (status)); 468141cc406Sopenharmony_ci return (SANE_FALSE); 469141cc406Sopenharmony_ci } 470141cc406Sopenharmony_ci 471141cc406Sopenharmony_ci /* Hack to recognize the dextra as a TECO scanner. */ 472141cc406Sopenharmony_ci if (memcmp (dev->buffer + 0x08, "DF-600M ", 8) == 0) 473141cc406Sopenharmony_ci { 474141cc406Sopenharmony_ci memcpy (dev->buffer + 0x29, "\0TECO VM3510", 12); 475141cc406Sopenharmony_ci dev->buffer[4] = 0x30; /* change length */ 476141cc406Sopenharmony_ci size = 0x35; 477141cc406Sopenharmony_ci } 478141cc406Sopenharmony_ci 479141cc406Sopenharmony_ci if (size < 53) 480141cc406Sopenharmony_ci { 481141cc406Sopenharmony_ci DBG (DBG_error, 482141cc406Sopenharmony_ci "teco_identify_scanner: not enough data to identify device\n"); 483141cc406Sopenharmony_ci return (SANE_FALSE); 484141cc406Sopenharmony_ci } 485141cc406Sopenharmony_ci 486141cc406Sopenharmony_ci hexdump (DBG_info2, "inquiry", dev->buffer, size); 487141cc406Sopenharmony_ci 488141cc406Sopenharmony_ci dev->scsi_type = dev->buffer[0] & 0x1f; 489141cc406Sopenharmony_ci memcpy (dev->scsi_vendor, dev->buffer + 0x08, 0x08); 490141cc406Sopenharmony_ci dev->scsi_vendor[0x08] = 0; 491141cc406Sopenharmony_ci memcpy (dev->scsi_product, dev->buffer + 0x10, 0x010); 492141cc406Sopenharmony_ci dev->scsi_product[0x10] = 0; 493141cc406Sopenharmony_ci memcpy (dev->scsi_version, dev->buffer + 0x20, 0x04); 494141cc406Sopenharmony_ci dev->scsi_version[0x04] = 0; 495141cc406Sopenharmony_ci memcpy (dev->scsi_teco_name, dev->buffer + 0x2A, 0x0B); 496141cc406Sopenharmony_ci dev->scsi_teco_name[0x0B] = 0; 497141cc406Sopenharmony_ci 498141cc406Sopenharmony_ci DBG (DBG_info, "device is \"%s\" \"%s\" \"%s\" \"%s\"\n", 499141cc406Sopenharmony_ci dev->scsi_vendor, dev->scsi_product, dev->scsi_version, 500141cc406Sopenharmony_ci dev->scsi_teco_name); 501141cc406Sopenharmony_ci 502141cc406Sopenharmony_ci /* Lookup through the supported scanners table to find if this 503141cc406Sopenharmony_ci * backend supports that one. */ 504141cc406Sopenharmony_ci for (i = 0; i < NELEMS (scanners); i++) 505141cc406Sopenharmony_ci { 506141cc406Sopenharmony_ci 507141cc406Sopenharmony_ci if (dev->scsi_type == scanners[i].scsi_type && 508141cc406Sopenharmony_ci strcmp (dev->scsi_teco_name, scanners[i].scsi_teco_name) == 0) 509141cc406Sopenharmony_ci { 510141cc406Sopenharmony_ci 511141cc406Sopenharmony_ci DBG (DBG_error, "teco_identify_scanner: scanner supported\n"); 512141cc406Sopenharmony_ci 513141cc406Sopenharmony_ci dev->def = &(scanners[i]); 514141cc406Sopenharmony_ci 515141cc406Sopenharmony_ci return (SANE_TRUE); 516141cc406Sopenharmony_ci } 517141cc406Sopenharmony_ci } 518141cc406Sopenharmony_ci 519141cc406Sopenharmony_ci DBG (DBG_proc, "teco_identify_scanner: exit, device not supported\n"); 520141cc406Sopenharmony_ci 521141cc406Sopenharmony_ci return (SANE_FALSE); 522141cc406Sopenharmony_ci} 523141cc406Sopenharmony_ci 524141cc406Sopenharmony_ci/* Get the inquiry page 0x82. */ 525141cc406Sopenharmony_cistatic int 526141cc406Sopenharmony_citeco_get_inquiry_82 (Teco_Scanner * dev) 527141cc406Sopenharmony_ci{ 528141cc406Sopenharmony_ci CDB cdb; 529141cc406Sopenharmony_ci SANE_Status status; 530141cc406Sopenharmony_ci size_t size; 531141cc406Sopenharmony_ci 532141cc406Sopenharmony_ci DBG (DBG_proc, "teco_get_inquiry_82: enter\n"); 533141cc406Sopenharmony_ci 534141cc406Sopenharmony_ci size = 0x4; 535141cc406Sopenharmony_ci MKSCSI_INQUIRY (cdb, size); 536141cc406Sopenharmony_ci cdb.data[1] = 1; /* evpd */ 537141cc406Sopenharmony_ci cdb.data[2] = 0x82; /* page code number */ 538141cc406Sopenharmony_ci 539141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 540141cc406Sopenharmony_ci NULL, 0, dev->buffer, &size); 541141cc406Sopenharmony_ci 542141cc406Sopenharmony_ci if (status) 543141cc406Sopenharmony_ci { 544141cc406Sopenharmony_ci DBG (DBG_error, 545141cc406Sopenharmony_ci "teco_get_inquiry_82: inquiry page 0x82 failed with status %s\n", 546141cc406Sopenharmony_ci sane_strstatus (status)); 547141cc406Sopenharmony_ci return (SANE_FALSE); 548141cc406Sopenharmony_ci } 549141cc406Sopenharmony_ci 550141cc406Sopenharmony_ci size = dev->buffer[3] + 4; 551141cc406Sopenharmony_ci MKSCSI_INQUIRY (cdb, size); 552141cc406Sopenharmony_ci cdb.data[1] = 1; /* evpd */ 553141cc406Sopenharmony_ci cdb.data[2] = 0x82; /* page code number */ 554141cc406Sopenharmony_ci 555141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 556141cc406Sopenharmony_ci NULL, 0, dev->buffer, &size); 557141cc406Sopenharmony_ci 558141cc406Sopenharmony_ci if (status) 559141cc406Sopenharmony_ci { 560141cc406Sopenharmony_ci DBG (DBG_error, 561141cc406Sopenharmony_ci "teco_get_inquiry_82: inquiry page 0x82 failed with status %s\n", 562141cc406Sopenharmony_ci sane_strstatus (status)); 563141cc406Sopenharmony_ci return (SANE_FALSE); 564141cc406Sopenharmony_ci } 565141cc406Sopenharmony_ci 566141cc406Sopenharmony_ci hexdump (DBG_info2, "inquiry page 0x82", dev->buffer, size); 567141cc406Sopenharmony_ci 568141cc406Sopenharmony_ci DBG (DBG_proc, "teco_get_inquiry_82: leave\n"); 569141cc406Sopenharmony_ci 570141cc406Sopenharmony_ci return (status); 571141cc406Sopenharmony_ci} 572141cc406Sopenharmony_ci 573141cc406Sopenharmony_ci/* SCSI sense handler. Callback for SANE. 574141cc406Sopenharmony_ci * These scanners never set asc or ascq. */ 575141cc406Sopenharmony_cistatic SANE_Status 576141cc406Sopenharmony_citeco_sense_handler (int __sane_unused__ scsi_fd, unsigned char *result, void __sane_unused__ *arg) 577141cc406Sopenharmony_ci{ 578141cc406Sopenharmony_ci int sensekey; 579141cc406Sopenharmony_ci int len; 580141cc406Sopenharmony_ci 581141cc406Sopenharmony_ci DBG (DBG_proc, "teco_sense_handler: enter\n"); 582141cc406Sopenharmony_ci 583141cc406Sopenharmony_ci sensekey = get_RS_sense_key (result); 584141cc406Sopenharmony_ci len = 7 + get_RS_additional_length (result); 585141cc406Sopenharmony_ci 586141cc406Sopenharmony_ci hexdump (DBG_info2, "sense", result, len); 587141cc406Sopenharmony_ci 588141cc406Sopenharmony_ci if (get_RS_error_code (result) != 0x70) 589141cc406Sopenharmony_ci { 590141cc406Sopenharmony_ci DBG (DBG_error, 591141cc406Sopenharmony_ci "teco_sense_handler: invalid sense key error code (%d)\n", 592141cc406Sopenharmony_ci get_RS_error_code (result)); 593141cc406Sopenharmony_ci 594141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 595141cc406Sopenharmony_ci } 596141cc406Sopenharmony_ci 597141cc406Sopenharmony_ci if (len < 14) 598141cc406Sopenharmony_ci { 599141cc406Sopenharmony_ci DBG (DBG_error, "teco_sense_handler: sense too short, no ASC/ASCQ\n"); 600141cc406Sopenharmony_ci 601141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 602141cc406Sopenharmony_ci } 603141cc406Sopenharmony_ci 604141cc406Sopenharmony_ci DBG (DBG_sense, "teco_sense_handler: sense=%d\n", sensekey); 605141cc406Sopenharmony_ci 606141cc406Sopenharmony_ci if (sensekey == 0x00) 607141cc406Sopenharmony_ci { 608141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 609141cc406Sopenharmony_ci } 610141cc406Sopenharmony_ci 611141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 612141cc406Sopenharmony_ci} 613141cc406Sopenharmony_ci 614141cc406Sopenharmony_ci/* Send the mode select to the scanner. */ 615141cc406Sopenharmony_cistatic int 616141cc406Sopenharmony_citeco_mode_select (Teco_Scanner * dev) 617141cc406Sopenharmony_ci{ 618141cc406Sopenharmony_ci CDB cdb; 619141cc406Sopenharmony_ci SANE_Status status; 620141cc406Sopenharmony_ci size_t size; 621141cc406Sopenharmony_ci unsigned char select[24] = { 622141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 623141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 624141cc406Sopenharmony_ci 0x03, 0x06, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00 625141cc406Sopenharmony_ci }; 626141cc406Sopenharmony_ci 627141cc406Sopenharmony_ci DBG (DBG_proc, "teco_mode_select: enter\n"); 628141cc406Sopenharmony_ci 629141cc406Sopenharmony_ci size = 24; 630141cc406Sopenharmony_ci MKSCSI_MODE_SELECT (cdb, 1, 0, size); 631141cc406Sopenharmony_ci 632141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 633141cc406Sopenharmony_ci select, size, NULL, NULL); 634141cc406Sopenharmony_ci 635141cc406Sopenharmony_ci DBG (DBG_proc, "teco_mode_select: exit\n"); 636141cc406Sopenharmony_ci 637141cc406Sopenharmony_ci return (status); 638141cc406Sopenharmony_ci} 639141cc406Sopenharmony_ci 640141cc406Sopenharmony_ci/* Set a window. */ 641141cc406Sopenharmony_cistatic SANE_Status 642141cc406Sopenharmony_citeco_set_window (Teco_Scanner * dev) 643141cc406Sopenharmony_ci{ 644141cc406Sopenharmony_ci size_t size; /* significant size of window */ 645141cc406Sopenharmony_ci CDB cdb; 646141cc406Sopenharmony_ci unsigned char window[99]; 647141cc406Sopenharmony_ci SANE_Status status; 648141cc406Sopenharmony_ci int i; 649141cc406Sopenharmony_ci 650141cc406Sopenharmony_ci DBG (DBG_proc, "teco_set_window: enter\n"); 651141cc406Sopenharmony_ci 652141cc406Sopenharmony_ci size = dev->def->window_size; 653141cc406Sopenharmony_ci 654141cc406Sopenharmony_ci MKSCSI_SET_WINDOW (cdb, size); 655141cc406Sopenharmony_ci 656141cc406Sopenharmony_ci memset (window, 0, size); 657141cc406Sopenharmony_ci 658141cc406Sopenharmony_ci /* size of the windows descriptor block */ 659141cc406Sopenharmony_ci window[7] = size - 8; 660141cc406Sopenharmony_ci 661141cc406Sopenharmony_ci /* X and Y resolution */ 662141cc406Sopenharmony_ci Ito16 (dev->x_resolution, &window[10]); 663141cc406Sopenharmony_ci Ito16 (dev->y_resolution, &window[12]); 664141cc406Sopenharmony_ci 665141cc406Sopenharmony_ci /* Upper Left (X,Y) */ 666141cc406Sopenharmony_ci Ito32 (dev->x_tl, &window[14]); 667141cc406Sopenharmony_ci Ito32 (dev->y_tl, &window[18]); 668141cc406Sopenharmony_ci 669141cc406Sopenharmony_ci /* Width and length */ 670141cc406Sopenharmony_ci Ito32 (dev->width, &window[22]); 671141cc406Sopenharmony_ci Ito32 (dev->length, &window[26]); 672141cc406Sopenharmony_ci 673141cc406Sopenharmony_ci /* Image Composition */ 674141cc406Sopenharmony_ci switch (dev->scan_mode) 675141cc406Sopenharmony_ci { 676141cc406Sopenharmony_ci case TECO_BW: 677141cc406Sopenharmony_ci window[33] = 0x00; 678141cc406Sopenharmony_ci i = get_string_list_index (dither_list, dev->val[OPT_DITHER].s); 679141cc406Sopenharmony_ci window[36] = dither_val[i]; 680141cc406Sopenharmony_ci break; 681141cc406Sopenharmony_ci case TECO_GRAYSCALE: 682141cc406Sopenharmony_ci window[33] = 0x02; 683141cc406Sopenharmony_ci break; 684141cc406Sopenharmony_ci case TECO_COLOR: 685141cc406Sopenharmony_ci window[33] = 0x05; 686141cc406Sopenharmony_ci break; 687141cc406Sopenharmony_ci } 688141cc406Sopenharmony_ci 689141cc406Sopenharmony_ci /* Depth */ 690141cc406Sopenharmony_ci window[34] = dev->depth; 691141cc406Sopenharmony_ci 692141cc406Sopenharmony_ci /* Unknown - invariants */ 693141cc406Sopenharmony_ci window[31] = 0x80; 694141cc406Sopenharmony_ci window[37] = 0x80; 695141cc406Sopenharmony_ci window[55] = 0x80; 696141cc406Sopenharmony_ci window[57] = 0x80; 697141cc406Sopenharmony_ci window[59] = 0x80; 698141cc406Sopenharmony_ci window[61] = 0x80; 699141cc406Sopenharmony_ci window[65] = 0x80; 700141cc406Sopenharmony_ci window[67] = 0x80; 701141cc406Sopenharmony_ci window[69] = 0x80; 702141cc406Sopenharmony_ci window[71] = 0x80; 703141cc406Sopenharmony_ci window[73] = 0x80; 704141cc406Sopenharmony_ci window[75] = 0x80; 705141cc406Sopenharmony_ci window[77] = 0x80; 706141cc406Sopenharmony_ci window[79] = 0x80; 707141cc406Sopenharmony_ci window[85] = 0xff; 708141cc406Sopenharmony_ci window[89] = 0xff; 709141cc406Sopenharmony_ci window[93] = 0xff; 710141cc406Sopenharmony_ci window[97] = 0xff; 711141cc406Sopenharmony_ci 712141cc406Sopenharmony_ci hexdump (DBG_info2, "windows", window, size); 713141cc406Sopenharmony_ci 714141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 715141cc406Sopenharmony_ci window, size, NULL, NULL); 716141cc406Sopenharmony_ci 717141cc406Sopenharmony_ci DBG (DBG_proc, "teco_set_window: exit, status=%d\n", status); 718141cc406Sopenharmony_ci 719141cc406Sopenharmony_ci return status; 720141cc406Sopenharmony_ci} 721141cc406Sopenharmony_ci 722141cc406Sopenharmony_ci/* Return the number of byte that can be read. */ 723141cc406Sopenharmony_cistatic SANE_Status 724141cc406Sopenharmony_ciget_filled_data_length (Teco_Scanner * dev, size_t * to_read) 725141cc406Sopenharmony_ci{ 726141cc406Sopenharmony_ci size_t size; 727141cc406Sopenharmony_ci CDB cdb; 728141cc406Sopenharmony_ci SANE_Status status; 729141cc406Sopenharmony_ci 730141cc406Sopenharmony_ci DBG (DBG_proc, "get_filled_data_length: enter\n"); 731141cc406Sopenharmony_ci 732141cc406Sopenharmony_ci *to_read = 0; 733141cc406Sopenharmony_ci 734141cc406Sopenharmony_ci size = 0x12; 735141cc406Sopenharmony_ci MKSCSI_GET_DATA_BUFFER_STATUS (cdb, 1, size); 736141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 737141cc406Sopenharmony_ci NULL, 0, dev->buffer, &size); 738141cc406Sopenharmony_ci 739141cc406Sopenharmony_ci if (size < 0x10) 740141cc406Sopenharmony_ci { 741141cc406Sopenharmony_ci DBG (DBG_error, 742141cc406Sopenharmony_ci "get_filled_data_length: not enough data returned (%ld)\n", 743141cc406Sopenharmony_ci (long) size); 744141cc406Sopenharmony_ci } 745141cc406Sopenharmony_ci 746141cc406Sopenharmony_ci hexdump (DBG_info2, "get_filled_data_length return", dev->buffer, size); 747141cc406Sopenharmony_ci 748141cc406Sopenharmony_ci *to_read = B24TOI (&dev->buffer[9]); 749141cc406Sopenharmony_ci 750141cc406Sopenharmony_ci DBG (DBG_info, "%d %d - %d %d\n", 751141cc406Sopenharmony_ci dev->params.lines, B16TOI (&dev->buffer[12]), 752141cc406Sopenharmony_ci dev->params.bytes_per_line, B16TOI (&dev->buffer[14])); 753141cc406Sopenharmony_ci 754141cc406Sopenharmony_ci if (dev->real_bytes_left == 0) 755141cc406Sopenharmony_ci { 756141cc406Sopenharmony_ci /* Beginning of a scan. */ 757141cc406Sopenharmony_ci dev->params.lines = B16TOI (&dev->buffer[12]); 758141cc406Sopenharmony_ci 759141cc406Sopenharmony_ci switch (dev->scan_mode) 760141cc406Sopenharmony_ci { 761141cc406Sopenharmony_ci case TECO_BW: 762141cc406Sopenharmony_ci dev->params.bytes_per_line = B16TOI (&dev->buffer[14]); 763141cc406Sopenharmony_ci dev->params.pixels_per_line = dev->params.bytes_per_line * 8; 764141cc406Sopenharmony_ci break; 765141cc406Sopenharmony_ci 766141cc406Sopenharmony_ci case TECO_GRAYSCALE: 767141cc406Sopenharmony_ci dev->params.pixels_per_line = B16TOI (&dev->buffer[14]); 768141cc406Sopenharmony_ci dev->params.bytes_per_line = dev->params.pixels_per_line; 769141cc406Sopenharmony_ci break; 770141cc406Sopenharmony_ci 771141cc406Sopenharmony_ci case TECO_COLOR: 772141cc406Sopenharmony_ci dev->params.pixels_per_line = B16TOI (&dev->buffer[14]); 773141cc406Sopenharmony_ci if (dev->def->pass == 3) 774141cc406Sopenharmony_ci { 775141cc406Sopenharmony_ci dev->params.bytes_per_line = dev->params.pixels_per_line; 776141cc406Sopenharmony_ci } 777141cc406Sopenharmony_ci else 778141cc406Sopenharmony_ci { 779141cc406Sopenharmony_ci dev->params.bytes_per_line = dev->params.pixels_per_line * 3; 780141cc406Sopenharmony_ci } 781141cc406Sopenharmony_ci break; 782141cc406Sopenharmony_ci } 783141cc406Sopenharmony_ci } 784141cc406Sopenharmony_ci 785141cc406Sopenharmony_ci DBG (DBG_info, "get_filled_data_length: to read = %ld\n", (long) *to_read); 786141cc406Sopenharmony_ci 787141cc406Sopenharmony_ci DBG (DBG_proc, "get_filled_data_length: exit, status=%d\n", status); 788141cc406Sopenharmony_ci 789141cc406Sopenharmony_ci return (status); 790141cc406Sopenharmony_ci} 791141cc406Sopenharmony_ci 792141cc406Sopenharmony_ci/* Start a scan. */ 793141cc406Sopenharmony_cistatic SANE_Status 794141cc406Sopenharmony_citeco_scan (Teco_Scanner * dev) 795141cc406Sopenharmony_ci{ 796141cc406Sopenharmony_ci CDB cdb; 797141cc406Sopenharmony_ci SANE_Status status; 798141cc406Sopenharmony_ci 799141cc406Sopenharmony_ci DBG (DBG_proc, "teco_scan: enter\n"); 800141cc406Sopenharmony_ci 801141cc406Sopenharmony_ci MKSCSI_SCAN (cdb); 802141cc406Sopenharmony_ci 803141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); 804141cc406Sopenharmony_ci 805141cc406Sopenharmony_ci DBG (DBG_proc, "teco_scan: exit, status=%d\n", status); 806141cc406Sopenharmony_ci 807141cc406Sopenharmony_ci return status; 808141cc406Sopenharmony_ci} 809141cc406Sopenharmony_ci 810141cc406Sopenharmony_ci#if 0 811141cc406Sopenharmony_ci/* Do some vendor specific stuff. */ 812141cc406Sopenharmony_cistatic SANE_Status 813141cc406Sopenharmony_citeco_vendor_spec (Teco_Scanner * dev) 814141cc406Sopenharmony_ci{ 815141cc406Sopenharmony_ci CDB cdb; 816141cc406Sopenharmony_ci SANE_Status status; 817141cc406Sopenharmony_ci size_t size; 818141cc406Sopenharmony_ci 819141cc406Sopenharmony_ci DBG (DBG_proc, "teco_vendor_spec: enter\n"); 820141cc406Sopenharmony_ci 821141cc406Sopenharmony_ci size = 0x7800; 822141cc406Sopenharmony_ci 823141cc406Sopenharmony_ci cdb.data[0] = 0x09; 824141cc406Sopenharmony_ci cdb.data[1] = 0; 825141cc406Sopenharmony_ci cdb.data[2] = 0; 826141cc406Sopenharmony_ci cdb.data[3] = (size >> 8) & 0xff; 827141cc406Sopenharmony_ci cdb.data[4] = (size >> 0) & 0xff; 828141cc406Sopenharmony_ci cdb.data[5] = 0; 829141cc406Sopenharmony_ci cdb.len = 6; 830141cc406Sopenharmony_ci 831141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 832141cc406Sopenharmony_ci NULL, 0, dev->buffer, &size); 833141cc406Sopenharmony_ci 834141cc406Sopenharmony_ci /*hexdump (DBG_info2, "calibration:", dev->buffer, size); */ 835141cc406Sopenharmony_ci 836141cc406Sopenharmony_ci cdb.data[0] = 0x0E; 837141cc406Sopenharmony_ci cdb.data[1] = 0; 838141cc406Sopenharmony_ci cdb.data[2] = 0; 839141cc406Sopenharmony_ci cdb.data[3] = 0; 840141cc406Sopenharmony_ci cdb.data[4] = 0; 841141cc406Sopenharmony_ci cdb.data[5] = 0; 842141cc406Sopenharmony_ci cdb.len = 6; 843141cc406Sopenharmony_ci 844141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); 845141cc406Sopenharmony_ci 846141cc406Sopenharmony_ci return status; 847141cc406Sopenharmony_ci} 848141cc406Sopenharmony_ci#endif 849141cc406Sopenharmony_ci 850141cc406Sopenharmony_ci/* Send the gamma 851141cc406Sopenharmony_ci * The order is RGB. The last color is unused. 852141cc406Sopenharmony_ci * G is also the gray gamma (if gray scan). 853141cc406Sopenharmony_ci * 854141cc406Sopenharmony_ci * Some scanner have 4 tables of 256 bytes, and some 4 tables of 1024 bytes. 855141cc406Sopenharmony_ci */ 856141cc406Sopenharmony_cistatic SANE_Status 857141cc406Sopenharmony_citeco_send_gamma (Teco_Scanner * dev) 858141cc406Sopenharmony_ci{ 859141cc406Sopenharmony_ci CDB cdb; 860141cc406Sopenharmony_ci SANE_Status status; 861141cc406Sopenharmony_ci struct 862141cc406Sopenharmony_ci { 863141cc406Sopenharmony_ci unsigned char gamma[4 * MAX_GAMMA_LENGTH]; 864141cc406Sopenharmony_ci } 865141cc406Sopenharmony_ci param; 866141cc406Sopenharmony_ci size_t i; 867141cc406Sopenharmony_ci size_t size; 868141cc406Sopenharmony_ci 869141cc406Sopenharmony_ci DBG (DBG_proc, "teco_send_gamma: enter\n"); 870141cc406Sopenharmony_ci 871141cc406Sopenharmony_ci size = 4 * GAMMA_LENGTH; 872141cc406Sopenharmony_ci MKSCSI_SEND_10 (cdb, 0x03, 0x02, size); 873141cc406Sopenharmony_ci 874141cc406Sopenharmony_ci if (dev->val[OPT_CUSTOM_GAMMA].w) 875141cc406Sopenharmony_ci { 876141cc406Sopenharmony_ci /* Use the custom gamma. */ 877141cc406Sopenharmony_ci if (dev->scan_mode == TECO_GRAYSCALE) 878141cc406Sopenharmony_ci { 879141cc406Sopenharmony_ci /* Gray */ 880141cc406Sopenharmony_ci for (i = 0; i < GAMMA_LENGTH; i++) 881141cc406Sopenharmony_ci { 882141cc406Sopenharmony_ci param.gamma[0 * GAMMA_LENGTH + i] = 0; 883141cc406Sopenharmony_ci param.gamma[1 * GAMMA_LENGTH + i] = dev->gamma_GRAY[i]; 884141cc406Sopenharmony_ci param.gamma[2 * GAMMA_LENGTH + i] = 0; 885141cc406Sopenharmony_ci param.gamma[3 * GAMMA_LENGTH + i] = 0; 886141cc406Sopenharmony_ci } 887141cc406Sopenharmony_ci } 888141cc406Sopenharmony_ci else 889141cc406Sopenharmony_ci { 890141cc406Sopenharmony_ci /* Color */ 891141cc406Sopenharmony_ci for (i = 0; i < GAMMA_LENGTH; i++) 892141cc406Sopenharmony_ci { 893141cc406Sopenharmony_ci param.gamma[0 * GAMMA_LENGTH + i] = dev->gamma_R[i]; 894141cc406Sopenharmony_ci param.gamma[1 * GAMMA_LENGTH + i] = dev->gamma_G[i]; 895141cc406Sopenharmony_ci param.gamma[2 * GAMMA_LENGTH + i] = dev->gamma_B[i]; 896141cc406Sopenharmony_ci param.gamma[3 * GAMMA_LENGTH + i] = 0; 897141cc406Sopenharmony_ci } 898141cc406Sopenharmony_ci } 899141cc406Sopenharmony_ci } 900141cc406Sopenharmony_ci else 901141cc406Sopenharmony_ci { 902141cc406Sopenharmony_ci if (dev->scan_mode == TECO_BW) 903141cc406Sopenharmony_ci { 904141cc406Sopenharmony_ci /* Map threshold from a 0..255 scale to a 905141cc406Sopenharmony_ci * 0..GAMMA_LENGTH scale. */ 906141cc406Sopenharmony_ci unsigned int threshold = 907141cc406Sopenharmony_ci dev->val[OPT_THRESHOLD].w * (GAMMA_LENGTH / 256); 908141cc406Sopenharmony_ci 909141cc406Sopenharmony_ci for (i = 0; i < GAMMA_LENGTH; i++) 910141cc406Sopenharmony_ci { 911141cc406Sopenharmony_ci param.gamma[0 * GAMMA_LENGTH + i] = 0; 912141cc406Sopenharmony_ci if (i < threshold) 913141cc406Sopenharmony_ci param.gamma[1 * GAMMA_LENGTH + i] = 0; 914141cc406Sopenharmony_ci else 915141cc406Sopenharmony_ci param.gamma[1 * GAMMA_LENGTH + i] = 255; 916141cc406Sopenharmony_ci param.gamma[2 * GAMMA_LENGTH + i] = 0; 917141cc406Sopenharmony_ci param.gamma[3 * GAMMA_LENGTH + i] = 0; 918141cc406Sopenharmony_ci } 919141cc406Sopenharmony_ci } 920141cc406Sopenharmony_ci else 921141cc406Sopenharmony_ci { 922141cc406Sopenharmony_ci 923141cc406Sopenharmony_ci /* 924141cc406Sopenharmony_ci * Shift is 1 for GAMMA_LENGTH == 256 925141cc406Sopenharmony_ci * and 4 for GAMMA_LENGTH == 1024 926141cc406Sopenharmony_ci */ 927141cc406Sopenharmony_ci int shift = GAMMA_LENGTH >> 8; 928141cc406Sopenharmony_ci 929141cc406Sopenharmony_ci for (i = 0; i < GAMMA_LENGTH; i++) 930141cc406Sopenharmony_ci { 931141cc406Sopenharmony_ci param.gamma[0 * GAMMA_LENGTH + i] = i / shift; 932141cc406Sopenharmony_ci param.gamma[1 * GAMMA_LENGTH + i] = i / shift; 933141cc406Sopenharmony_ci param.gamma[2 * GAMMA_LENGTH + i] = i / shift; 934141cc406Sopenharmony_ci param.gamma[3 * GAMMA_LENGTH + i] = 0; 935141cc406Sopenharmony_ci } 936141cc406Sopenharmony_ci } 937141cc406Sopenharmony_ci } 938141cc406Sopenharmony_ci 939141cc406Sopenharmony_ci hexdump (DBG_info2, "teco_send_gamma:", cdb.data, cdb.len); 940141cc406Sopenharmony_ci 941141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 942141cc406Sopenharmony_ci ¶m, size, NULL, NULL); 943141cc406Sopenharmony_ci 944141cc406Sopenharmony_ci DBG (DBG_proc, "teco_send_gamma: exit, status=%d\n", status); 945141cc406Sopenharmony_ci 946141cc406Sopenharmony_ci return (status); 947141cc406Sopenharmony_ci} 948141cc406Sopenharmony_ci 949141cc406Sopenharmony_ci/* Attach a scanner to this backend. */ 950141cc406Sopenharmony_cistatic SANE_Status 951141cc406Sopenharmony_ciattach_scanner (const char *devicename, Teco_Scanner ** devp) 952141cc406Sopenharmony_ci{ 953141cc406Sopenharmony_ci Teco_Scanner *dev; 954141cc406Sopenharmony_ci int sfd; 955141cc406Sopenharmony_ci 956141cc406Sopenharmony_ci DBG (DBG_sane_proc, "attach_scanner: %s\n", devicename); 957141cc406Sopenharmony_ci 958141cc406Sopenharmony_ci if (devp) 959141cc406Sopenharmony_ci *devp = NULL; 960141cc406Sopenharmony_ci 961141cc406Sopenharmony_ci /* Check if we know this device name. */ 962141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 963141cc406Sopenharmony_ci { 964141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) 965141cc406Sopenharmony_ci { 966141cc406Sopenharmony_ci if (devp) 967141cc406Sopenharmony_ci { 968141cc406Sopenharmony_ci *devp = dev; 969141cc406Sopenharmony_ci } 970141cc406Sopenharmony_ci DBG (DBG_info, "device is already known\n"); 971141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 972141cc406Sopenharmony_ci } 973141cc406Sopenharmony_ci } 974141cc406Sopenharmony_ci 975141cc406Sopenharmony_ci /* Allocate a new scanner entry. */ 976141cc406Sopenharmony_ci dev = teco_init (); 977141cc406Sopenharmony_ci if (dev == NULL) 978141cc406Sopenharmony_ci { 979141cc406Sopenharmony_ci DBG (DBG_error, "ERROR: not enough memory\n"); 980141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 981141cc406Sopenharmony_ci } 982141cc406Sopenharmony_ci 983141cc406Sopenharmony_ci DBG (DBG_info, "attach_scanner: opening %s\n", devicename); 984141cc406Sopenharmony_ci 985141cc406Sopenharmony_ci if (sanei_scsi_open (devicename, &sfd, teco_sense_handler, dev) != 0) 986141cc406Sopenharmony_ci { 987141cc406Sopenharmony_ci DBG (DBG_error, "ERROR: attach_scanner: open failed\n"); 988141cc406Sopenharmony_ci teco_free (dev); 989141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 990141cc406Sopenharmony_ci } 991141cc406Sopenharmony_ci 992141cc406Sopenharmony_ci /* Fill some scanner specific values. */ 993141cc406Sopenharmony_ci dev->devicename = strdup (devicename); 994141cc406Sopenharmony_ci dev->sfd = sfd; 995141cc406Sopenharmony_ci 996141cc406Sopenharmony_ci /* Now, check that it is a scanner we support. */ 997141cc406Sopenharmony_ci if (teco_identify_scanner (dev) == SANE_FALSE) 998141cc406Sopenharmony_ci { 999141cc406Sopenharmony_ci DBG (DBG_error, 1000141cc406Sopenharmony_ci "ERROR: attach_scanner: scanner-identification failed\n"); 1001141cc406Sopenharmony_ci teco_free (dev); 1002141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1003141cc406Sopenharmony_ci } 1004141cc406Sopenharmony_ci 1005141cc406Sopenharmony_ci /* Get the page 0x82. It doesn't appear to be useful yet. */ 1006141cc406Sopenharmony_ci teco_get_inquiry_82 (dev); 1007141cc406Sopenharmony_ci 1008141cc406Sopenharmony_ci teco_close (dev); 1009141cc406Sopenharmony_ci 1010141cc406Sopenharmony_ci /* Set the default options for that scanner. */ 1011141cc406Sopenharmony_ci dev->sane.name = dev->devicename; 1012141cc406Sopenharmony_ci dev->sane.vendor = dev->def->real_vendor; 1013141cc406Sopenharmony_ci dev->sane.model = dev->def->real_product; 1014141cc406Sopenharmony_ci dev->sane.type = "flatbed scanner"; 1015141cc406Sopenharmony_ci 1016141cc406Sopenharmony_ci /* Link the scanner with the others. */ 1017141cc406Sopenharmony_ci dev->next = first_dev; 1018141cc406Sopenharmony_ci first_dev = dev; 1019141cc406Sopenharmony_ci 1020141cc406Sopenharmony_ci if (devp) 1021141cc406Sopenharmony_ci { 1022141cc406Sopenharmony_ci *devp = dev; 1023141cc406Sopenharmony_ci } 1024141cc406Sopenharmony_ci 1025141cc406Sopenharmony_ci num_devices++; 1026141cc406Sopenharmony_ci 1027141cc406Sopenharmony_ci DBG (DBG_proc, "attach_scanner: exit\n"); 1028141cc406Sopenharmony_ci 1029141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1030141cc406Sopenharmony_ci} 1031141cc406Sopenharmony_ci 1032141cc406Sopenharmony_cistatic SANE_Status 1033141cc406Sopenharmony_ciattach_one (const char *dev) 1034141cc406Sopenharmony_ci{ 1035141cc406Sopenharmony_ci attach_scanner (dev, NULL); 1036141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1037141cc406Sopenharmony_ci} 1038141cc406Sopenharmony_ci 1039141cc406Sopenharmony_ci/* Reset the options for that scanner. */ 1040141cc406Sopenharmony_cistatic void 1041141cc406Sopenharmony_citeco_init_options (Teco_Scanner * dev) 1042141cc406Sopenharmony_ci{ 1043141cc406Sopenharmony_ci int i; 1044141cc406Sopenharmony_ci 1045141cc406Sopenharmony_ci /* Pre-initialize the options. */ 1046141cc406Sopenharmony_ci memset (dev->opt, 0, sizeof (dev->opt)); 1047141cc406Sopenharmony_ci memset (dev->val, 0, sizeof (dev->val)); 1048141cc406Sopenharmony_ci 1049141cc406Sopenharmony_ci for (i = 0; i < OPT_NUM_OPTIONS; ++i) 1050141cc406Sopenharmony_ci { 1051141cc406Sopenharmony_ci dev->opt[i].size = sizeof (SANE_Word); 1052141cc406Sopenharmony_ci dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 1053141cc406Sopenharmony_ci } 1054141cc406Sopenharmony_ci 1055141cc406Sopenharmony_ci /* Number of options. */ 1056141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].name = ""; 1057141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 1058141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 1059141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 1060141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 1061141cc406Sopenharmony_ci dev->val[OPT_NUM_OPTS].w = OPT_NUM_OPTIONS; 1062141cc406Sopenharmony_ci 1063141cc406Sopenharmony_ci /* Mode group */ 1064141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE; 1065141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].desc = ""; /* not valid for a group */ 1066141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 1067141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].cap = 0; 1068141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].size = 0; 1069141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1070141cc406Sopenharmony_ci 1071141cc406Sopenharmony_ci /* Scanner supported modes */ 1072141cc406Sopenharmony_ci dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; 1073141cc406Sopenharmony_ci dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 1074141cc406Sopenharmony_ci dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 1075141cc406Sopenharmony_ci dev->opt[OPT_MODE].type = SANE_TYPE_STRING; 1076141cc406Sopenharmony_ci dev->opt[OPT_MODE].size = max_string_size (scan_mode_list); 1077141cc406Sopenharmony_ci dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1078141cc406Sopenharmony_ci dev->opt[OPT_MODE].constraint.string_list = scan_mode_list; 1079141cc406Sopenharmony_ci dev->val[OPT_MODE].s = (SANE_Char *) strdup (""); /* will be set later */ 1080141cc406Sopenharmony_ci 1081141cc406Sopenharmony_ci /* X and Y resolution */ 1082141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 1083141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 1084141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 1085141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; 1086141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 1087141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; 1088141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].constraint.range = &dev->def->res_range; 1089141cc406Sopenharmony_ci dev->val[OPT_RESOLUTION].w = 100; 1090141cc406Sopenharmony_ci 1091141cc406Sopenharmony_ci /* Geometry group */ 1092141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); 1093141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].desc = ""; /* not valid for a group */ 1094141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 1095141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].cap = 0; 1096141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].size = 0; 1097141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1098141cc406Sopenharmony_ci 1099141cc406Sopenharmony_ci /* Upper left X */ 1100141cc406Sopenharmony_ci dev->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 1101141cc406Sopenharmony_ci dev->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 1102141cc406Sopenharmony_ci dev->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 1103141cc406Sopenharmony_ci dev->opt[OPT_TL_X].type = SANE_TYPE_FIXED; 1104141cc406Sopenharmony_ci dev->opt[OPT_TL_X].unit = SANE_UNIT_MM; 1105141cc406Sopenharmony_ci dev->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 1106141cc406Sopenharmony_ci dev->opt[OPT_TL_X].constraint.range = &x_range; 1107141cc406Sopenharmony_ci dev->val[OPT_TL_X].w = x_range.min; 1108141cc406Sopenharmony_ci 1109141cc406Sopenharmony_ci /* Upper left Y */ 1110141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 1111141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 1112141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 1113141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; 1114141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].unit = SANE_UNIT_MM; 1115141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 1116141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].constraint.range = &y_range; 1117141cc406Sopenharmony_ci dev->val[OPT_TL_Y].w = y_range.min; 1118141cc406Sopenharmony_ci 1119141cc406Sopenharmony_ci /* Bottom-right x */ 1120141cc406Sopenharmony_ci dev->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 1121141cc406Sopenharmony_ci dev->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 1122141cc406Sopenharmony_ci dev->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 1123141cc406Sopenharmony_ci dev->opt[OPT_BR_X].type = SANE_TYPE_FIXED; 1124141cc406Sopenharmony_ci dev->opt[OPT_BR_X].unit = SANE_UNIT_MM; 1125141cc406Sopenharmony_ci dev->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 1126141cc406Sopenharmony_ci dev->opt[OPT_BR_X].constraint.range = &x_range; 1127141cc406Sopenharmony_ci dev->val[OPT_BR_X].w = x_range.max; 1128141cc406Sopenharmony_ci 1129141cc406Sopenharmony_ci /* Bottom-right y */ 1130141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 1131141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 1132141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 1133141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; 1134141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].unit = SANE_UNIT_MM; 1135141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 1136141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].constraint.range = &y_range; 1137141cc406Sopenharmony_ci dev->val[OPT_BR_Y].w = y_range.max; 1138141cc406Sopenharmony_ci 1139141cc406Sopenharmony_ci /* Enhancement group */ 1140141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); 1141141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].desc = ""; /* not valid for a group */ 1142141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; 1143141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; 1144141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].size = 0; 1145141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1146141cc406Sopenharmony_ci 1147141cc406Sopenharmony_ci /* Halftone pattern */ 1148141cc406Sopenharmony_ci dev->opt[OPT_DITHER].name = "dither"; 1149141cc406Sopenharmony_ci dev->opt[OPT_DITHER].title = SANE_I18N ("Dither"); 1150141cc406Sopenharmony_ci dev->opt[OPT_DITHER].desc = SANE_I18N ("Dither"); 1151141cc406Sopenharmony_ci dev->opt[OPT_DITHER].type = SANE_TYPE_STRING; 1152141cc406Sopenharmony_ci dev->opt[OPT_DITHER].size = max_string_size (dither_list); 1153141cc406Sopenharmony_ci dev->opt[OPT_DITHER].cap |= SANE_CAP_INACTIVE; 1154141cc406Sopenharmony_ci dev->opt[OPT_DITHER].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1155141cc406Sopenharmony_ci dev->opt[OPT_DITHER].constraint.string_list = dither_list; 1156141cc406Sopenharmony_ci dev->val[OPT_DITHER].s = strdup (dither_list[0]); 1157141cc406Sopenharmony_ci 1158141cc406Sopenharmony_ci /* custom-gamma table */ 1159141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; 1160141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; 1161141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; 1162141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; 1163141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; 1164141cc406Sopenharmony_ci dev->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; 1165141cc406Sopenharmony_ci 1166141cc406Sopenharmony_ci /* red gamma vector */ 1167141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; 1168141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; 1169141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; 1170141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; 1171141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1172141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; 1173141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].size = GAMMA_LENGTH * sizeof (SANE_Word); 1174141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; 1175141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range; 1176141cc406Sopenharmony_ci dev->val[OPT_GAMMA_VECTOR_R].wa = dev->gamma_R; 1177141cc406Sopenharmony_ci 1178141cc406Sopenharmony_ci /* green and gamma vector */ 1179141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; 1180141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; 1181141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; 1182141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; 1183141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1184141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; 1185141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].size = GAMMA_LENGTH * sizeof (SANE_Word); 1186141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; 1187141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range; 1188141cc406Sopenharmony_ci dev->val[OPT_GAMMA_VECTOR_G].wa = dev->gamma_G; 1189141cc406Sopenharmony_ci 1190141cc406Sopenharmony_ci /* blue gamma vector */ 1191141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; 1192141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; 1193141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; 1194141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; 1195141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1196141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; 1197141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].size = GAMMA_LENGTH * sizeof (SANE_Word); 1198141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; 1199141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range; 1200141cc406Sopenharmony_ci dev->val[OPT_GAMMA_VECTOR_B].wa = dev->gamma_B; 1201141cc406Sopenharmony_ci 1202141cc406Sopenharmony_ci /* grayscale gamma vector */ 1203141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_GRAY].name = SANE_NAME_GAMMA_VECTOR; 1204141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_GRAY].title = SANE_TITLE_GAMMA_VECTOR; 1205141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_GRAY].desc = SANE_DESC_GAMMA_VECTOR; 1206141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_GRAY].type = SANE_TYPE_INT; 1207141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; 1208141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_GRAY].unit = SANE_UNIT_NONE; 1209141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_GRAY].size = GAMMA_LENGTH * sizeof (SANE_Word); 1210141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_GRAY].constraint_type = SANE_CONSTRAINT_RANGE; 1211141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_GRAY].constraint.range = &gamma_range; 1212141cc406Sopenharmony_ci dev->val[OPT_GAMMA_VECTOR_GRAY].wa = dev->gamma_GRAY; 1213141cc406Sopenharmony_ci 1214141cc406Sopenharmony_ci /* Threshold */ 1215141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; 1216141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; 1217141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; 1218141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; 1219141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; 1220141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].size = sizeof (SANE_Int); 1221141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 1222141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; 1223141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].constraint.range = &threshold_range; 1224141cc406Sopenharmony_ci dev->val[OPT_THRESHOLD].w = 128; 1225141cc406Sopenharmony_ci 1226141cc406Sopenharmony_ci /* preview */ 1227141cc406Sopenharmony_ci dev->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; 1228141cc406Sopenharmony_ci dev->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; 1229141cc406Sopenharmony_ci dev->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; 1230141cc406Sopenharmony_ci dev->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; 1231141cc406Sopenharmony_ci dev->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 1232141cc406Sopenharmony_ci dev->val[OPT_PREVIEW].w = SANE_FALSE; 1233141cc406Sopenharmony_ci 1234141cc406Sopenharmony_ci /* Lastly, set the default scan mode. This might change some 1235141cc406Sopenharmony_ci * values previously set here. */ 1236141cc406Sopenharmony_ci sane_control_option (dev, OPT_MODE, SANE_ACTION_SET_VALUE, 1237141cc406Sopenharmony_ci (SANE_String_Const *) scan_mode_list[0], NULL); 1238141cc406Sopenharmony_ci} 1239141cc406Sopenharmony_ci 1240141cc406Sopenharmony_ci/* 1241141cc406Sopenharmony_ci * Wait until the scanner is ready. 1242141cc406Sopenharmony_ci */ 1243141cc406Sopenharmony_cistatic SANE_Status 1244141cc406Sopenharmony_citeco_wait_scanner (Teco_Scanner * dev) 1245141cc406Sopenharmony_ci{ 1246141cc406Sopenharmony_ci SANE_Status status; 1247141cc406Sopenharmony_ci int timeout; 1248141cc406Sopenharmony_ci CDB cdb; 1249141cc406Sopenharmony_ci 1250141cc406Sopenharmony_ci DBG (DBG_proc, "teco_wait_scanner: enter\n"); 1251141cc406Sopenharmony_ci 1252141cc406Sopenharmony_ci MKSCSI_TEST_UNIT_READY (cdb); 1253141cc406Sopenharmony_ci 1254141cc406Sopenharmony_ci /* Set the timeout to 60 seconds. */ 1255141cc406Sopenharmony_ci timeout = 60; 1256141cc406Sopenharmony_ci 1257141cc406Sopenharmony_ci while (timeout > 0) 1258141cc406Sopenharmony_ci { 1259141cc406Sopenharmony_ci 1260141cc406Sopenharmony_ci /* test unit ready */ 1261141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 1262141cc406Sopenharmony_ci NULL, 0, NULL, NULL); 1263141cc406Sopenharmony_ci 1264141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) 1265141cc406Sopenharmony_ci { 1266141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1267141cc406Sopenharmony_ci } 1268141cc406Sopenharmony_ci 1269141cc406Sopenharmony_ci sleep (1); 1270141cc406Sopenharmony_ci }; 1271141cc406Sopenharmony_ci 1272141cc406Sopenharmony_ci DBG (DBG_proc, "teco_wait_scanner: scanner not ready\n"); 1273141cc406Sopenharmony_ci return (SANE_STATUS_IO_ERROR); 1274141cc406Sopenharmony_ci} 1275141cc406Sopenharmony_ci 1276141cc406Sopenharmony_ci/* Read the image from the scanner and fill the temporary buffer with it. */ 1277141cc406Sopenharmony_cistatic SANE_Status 1278141cc406Sopenharmony_citeco_fill_image (Teco_Scanner * dev) 1279141cc406Sopenharmony_ci{ 1280141cc406Sopenharmony_ci SANE_Status status; 1281141cc406Sopenharmony_ci size_t size; 1282141cc406Sopenharmony_ci CDB cdb; 1283141cc406Sopenharmony_ci unsigned char *image; 1284141cc406Sopenharmony_ci 1285141cc406Sopenharmony_ci DBG (DBG_proc, "teco_fill_image: enter\n"); 1286141cc406Sopenharmony_ci 1287141cc406Sopenharmony_ci assert (dev->image_begin == dev->image_end); 1288141cc406Sopenharmony_ci assert (dev->real_bytes_left > 0); 1289141cc406Sopenharmony_ci 1290141cc406Sopenharmony_ci dev->image_begin = 0; 1291141cc406Sopenharmony_ci dev->image_end = 0; 1292141cc406Sopenharmony_ci 1293141cc406Sopenharmony_ci while (dev->real_bytes_left) 1294141cc406Sopenharmony_ci { 1295141cc406Sopenharmony_ci /* 1296141cc406Sopenharmony_ci * Try to read the maximum number of bytes. 1297141cc406Sopenharmony_ci */ 1298141cc406Sopenharmony_ci size = 0; 1299141cc406Sopenharmony_ci while (size == 0) 1300141cc406Sopenharmony_ci { 1301141cc406Sopenharmony_ci status = get_filled_data_length (dev, &size); 1302141cc406Sopenharmony_ci if (status) 1303141cc406Sopenharmony_ci return (status); 1304141cc406Sopenharmony_ci if (size == 0) 1305141cc406Sopenharmony_ci usleep (100000); /* sleep 1/10th of second */ 1306141cc406Sopenharmony_ci } 1307141cc406Sopenharmony_ci 1308141cc406Sopenharmony_ci if (size > dev->real_bytes_left) 1309141cc406Sopenharmony_ci size = dev->real_bytes_left; 1310141cc406Sopenharmony_ci if (size > dev->image_size - dev->image_end) 1311141cc406Sopenharmony_ci size = dev->image_size - dev->image_end; 1312141cc406Sopenharmony_ci 1313141cc406Sopenharmony_ci /* Always read a multiple of a line. */ 1314141cc406Sopenharmony_ci size = size - (size % dev->params.bytes_per_line); 1315141cc406Sopenharmony_ci 1316141cc406Sopenharmony_ci if (size == 0) 1317141cc406Sopenharmony_ci { 1318141cc406Sopenharmony_ci /* Probably reached the end of the buffer. 1319141cc406Sopenharmony_ci * Check, just in case. */ 1320141cc406Sopenharmony_ci assert (dev->image_end != 0); 1321141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 1322141cc406Sopenharmony_ci } 1323141cc406Sopenharmony_ci 1324141cc406Sopenharmony_ci DBG (DBG_info, "teco_fill_image: to read = %ld bytes (bpl=%d)\n", 1325141cc406Sopenharmony_ci (long) size, dev->params.bytes_per_line); 1326141cc406Sopenharmony_ci 1327141cc406Sopenharmony_ci MKSCSI_READ_10 (cdb, 0, 0, size); 1328141cc406Sopenharmony_ci 1329141cc406Sopenharmony_ci hexdump (DBG_info2, "teco_fill_image: READ_10 CDB", cdb.data, 10); 1330141cc406Sopenharmony_ci 1331141cc406Sopenharmony_ci image = dev->image + dev->image_end; 1332141cc406Sopenharmony_ci 1333141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 1334141cc406Sopenharmony_ci NULL, 0, image, &size); 1335141cc406Sopenharmony_ci 1336141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1337141cc406Sopenharmony_ci { 1338141cc406Sopenharmony_ci DBG (DBG_error, "teco_fill_image: cannot read from the scanner\n"); 1339141cc406Sopenharmony_ci return status; 1340141cc406Sopenharmony_ci } 1341141cc406Sopenharmony_ci 1342141cc406Sopenharmony_ci /* The size this scanner returns is always a multiple of lines. */ 1343141cc406Sopenharmony_ci assert ((size % dev->params.bytes_per_line) == 0); 1344141cc406Sopenharmony_ci 1345141cc406Sopenharmony_ci DBG (DBG_info, "teco_fill_image: real bytes left = %ld\n", 1346141cc406Sopenharmony_ci (long) dev->real_bytes_left); 1347141cc406Sopenharmony_ci 1348141cc406Sopenharmony_ci if (dev->scan_mode == TECO_COLOR) 1349141cc406Sopenharmony_ci { 1350141cc406Sopenharmony_ci if (dev->def->pass == 1) 1351141cc406Sopenharmony_ci { 1352141cc406Sopenharmony_ci 1353141cc406Sopenharmony_ci /* Reorder the lines. The scanner gives color by color for 1354141cc406Sopenharmony_ci * each line. */ 1355141cc406Sopenharmony_ci unsigned char *src = image; 1356141cc406Sopenharmony_ci int nb_lines = size / dev->params.bytes_per_line; 1357141cc406Sopenharmony_ci int i, j; 1358141cc406Sopenharmony_ci 1359141cc406Sopenharmony_ci for (i = 0; i < nb_lines; i++) 1360141cc406Sopenharmony_ci { 1361141cc406Sopenharmony_ci 1362141cc406Sopenharmony_ci unsigned char *dest = dev->buffer; 1363141cc406Sopenharmony_ci 1364141cc406Sopenharmony_ci for (j = 0; j < dev->params.pixels_per_line; j++) 1365141cc406Sopenharmony_ci { 1366141cc406Sopenharmony_ci *dest = src[j + 0 * dev->params.pixels_per_line]; 1367141cc406Sopenharmony_ci dest++; 1368141cc406Sopenharmony_ci *dest = src[j + 1 * dev->params.pixels_per_line]; 1369141cc406Sopenharmony_ci dest++; 1370141cc406Sopenharmony_ci *dest = src[j + 2 * dev->params.pixels_per_line]; 1371141cc406Sopenharmony_ci dest++; 1372141cc406Sopenharmony_ci } 1373141cc406Sopenharmony_ci 1374141cc406Sopenharmony_ci /* Copy the line back. */ 1375141cc406Sopenharmony_ci memcpy (src, dev->buffer, dev->params.bytes_per_line); 1376141cc406Sopenharmony_ci 1377141cc406Sopenharmony_ci src += dev->params.bytes_per_line; 1378141cc406Sopenharmony_ci } 1379141cc406Sopenharmony_ci } 1380141cc406Sopenharmony_ci } 1381141cc406Sopenharmony_ci 1382141cc406Sopenharmony_ci dev->image_end += size; 1383141cc406Sopenharmony_ci dev->real_bytes_left -= size; 1384141cc406Sopenharmony_ci } 1385141cc406Sopenharmony_ci 1386141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); /* unreachable */ 1387141cc406Sopenharmony_ci} 1388141cc406Sopenharmony_ci 1389141cc406Sopenharmony_ci/* Copy from the raw buffer to the buffer given by the backend. 1390141cc406Sopenharmony_ci * 1391141cc406Sopenharmony_ci * len in input is the maximum length available in buf, and, in 1392141cc406Sopenharmony_ci * output, is the length written into buf. 1393141cc406Sopenharmony_ci */ 1394141cc406Sopenharmony_cistatic void 1395141cc406Sopenharmony_citeco_copy_raw_to_frontend (Teco_Scanner * dev, SANE_Byte * buf, size_t * len) 1396141cc406Sopenharmony_ci{ 1397141cc406Sopenharmony_ci size_t size; 1398141cc406Sopenharmony_ci 1399141cc406Sopenharmony_ci size = dev->image_end - dev->image_begin; 1400141cc406Sopenharmony_ci if (size > *len) 1401141cc406Sopenharmony_ci { 1402141cc406Sopenharmony_ci size = *len; 1403141cc406Sopenharmony_ci } 1404141cc406Sopenharmony_ci *len = size; 1405141cc406Sopenharmony_ci 1406141cc406Sopenharmony_ci switch (dev->scan_mode) 1407141cc406Sopenharmony_ci { 1408141cc406Sopenharmony_ci case TECO_BW: 1409141cc406Sopenharmony_ci { 1410141cc406Sopenharmony_ci /* Invert black and white. */ 1411141cc406Sopenharmony_ci unsigned char *src = dev->image + dev->image_begin; 1412141cc406Sopenharmony_ci size_t i; 1413141cc406Sopenharmony_ci 1414141cc406Sopenharmony_ci for (i = 0; i < size; i++) 1415141cc406Sopenharmony_ci { 1416141cc406Sopenharmony_ci *buf = *src ^ 0xff; 1417141cc406Sopenharmony_ci src++; 1418141cc406Sopenharmony_ci buf++; 1419141cc406Sopenharmony_ci } 1420141cc406Sopenharmony_ci } 1421141cc406Sopenharmony_ci break; 1422141cc406Sopenharmony_ci 1423141cc406Sopenharmony_ci case TECO_GRAYSCALE: 1424141cc406Sopenharmony_ci case TECO_COLOR: 1425141cc406Sopenharmony_ci memcpy (buf, dev->image + dev->image_begin, size); 1426141cc406Sopenharmony_ci break; 1427141cc406Sopenharmony_ci } 1428141cc406Sopenharmony_ci 1429141cc406Sopenharmony_ci dev->image_begin += size; 1430141cc406Sopenharmony_ci} 1431141cc406Sopenharmony_ci 1432141cc406Sopenharmony_ci/* Stop a scan. */ 1433141cc406Sopenharmony_cistatic SANE_Status 1434141cc406Sopenharmony_cido_cancel (Teco_Scanner * dev) 1435141cc406Sopenharmony_ci{ 1436141cc406Sopenharmony_ci DBG (DBG_sane_proc, "do_cancel enter\n"); 1437141cc406Sopenharmony_ci 1438141cc406Sopenharmony_ci if (dev->scanning == SANE_TRUE) 1439141cc406Sopenharmony_ci { 1440141cc406Sopenharmony_ci 1441141cc406Sopenharmony_ci /* Reset the scanner */ 1442141cc406Sopenharmony_ci dev->x_resolution = 300; 1443141cc406Sopenharmony_ci dev->y_resolution = 300; 1444141cc406Sopenharmony_ci dev->x_tl = 0; 1445141cc406Sopenharmony_ci dev->y_tl = 0; 1446141cc406Sopenharmony_ci dev->width = 0; 1447141cc406Sopenharmony_ci dev->length = 0; 1448141cc406Sopenharmony_ci 1449141cc406Sopenharmony_ci teco_set_window (dev); 1450141cc406Sopenharmony_ci 1451141cc406Sopenharmony_ci teco_scan (dev); 1452141cc406Sopenharmony_ci 1453141cc406Sopenharmony_ci teco_close (dev); 1454141cc406Sopenharmony_ci } 1455141cc406Sopenharmony_ci 1456141cc406Sopenharmony_ci dev->scanning = SANE_FALSE; 1457141cc406Sopenharmony_ci 1458141cc406Sopenharmony_ci DBG (DBG_sane_proc, "do_cancel exit\n"); 1459141cc406Sopenharmony_ci 1460141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 1461141cc406Sopenharmony_ci} 1462141cc406Sopenharmony_ci 1463141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 1464141cc406Sopenharmony_ci 1465141cc406Sopenharmony_ci/* Sane entry points */ 1466141cc406Sopenharmony_ci 1467141cc406Sopenharmony_ciSANE_Status 1468141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) 1469141cc406Sopenharmony_ci{ 1470141cc406Sopenharmony_ci FILE *fp; 1471141cc406Sopenharmony_ci char dev_name[PATH_MAX]; 1472141cc406Sopenharmony_ci size_t len; 1473141cc406Sopenharmony_ci 1474141cc406Sopenharmony_ci DBG_INIT (); 1475141cc406Sopenharmony_ci 1476141cc406Sopenharmony_ci DBG (DBG_sane_init, "sane_init\n"); 1477141cc406Sopenharmony_ci 1478141cc406Sopenharmony_ci DBG (DBG_error, "This is sane-teco1 version %d.%d-%d\n", SANE_CURRENT_MAJOR, 1479141cc406Sopenharmony_ci SANE_CURRENT_MINOR, BUILD); 1480141cc406Sopenharmony_ci DBG (DBG_error, "(C) 2002 by Frank Zago\n"); 1481141cc406Sopenharmony_ci 1482141cc406Sopenharmony_ci if (version_code) 1483141cc406Sopenharmony_ci { 1484141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 1485141cc406Sopenharmony_ci } 1486141cc406Sopenharmony_ci 1487141cc406Sopenharmony_ci fp = sanei_config_open (TECO_CONFIG_FILE); 1488141cc406Sopenharmony_ci if (!fp) 1489141cc406Sopenharmony_ci { 1490141cc406Sopenharmony_ci /* default to /dev/scanner instead of insisting on config file */ 1491141cc406Sopenharmony_ci attach_scanner ("/dev/scanner", 0); 1492141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1493141cc406Sopenharmony_ci } 1494141cc406Sopenharmony_ci 1495141cc406Sopenharmony_ci while (sanei_config_read (dev_name, sizeof (dev_name), fp)) 1496141cc406Sopenharmony_ci { 1497141cc406Sopenharmony_ci if (dev_name[0] == '#') /* ignore line comments */ 1498141cc406Sopenharmony_ci continue; 1499141cc406Sopenharmony_ci len = strlen (dev_name); 1500141cc406Sopenharmony_ci 1501141cc406Sopenharmony_ci if (!len) 1502141cc406Sopenharmony_ci continue; /* ignore empty lines */ 1503141cc406Sopenharmony_ci 1504141cc406Sopenharmony_ci sanei_config_attach_matching_devices (dev_name, attach_one); 1505141cc406Sopenharmony_ci } 1506141cc406Sopenharmony_ci 1507141cc406Sopenharmony_ci fclose (fp); 1508141cc406Sopenharmony_ci 1509141cc406Sopenharmony_ci DBG (DBG_proc, "sane_init: leave\n"); 1510141cc406Sopenharmony_ci 1511141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1512141cc406Sopenharmony_ci} 1513141cc406Sopenharmony_ci 1514141cc406Sopenharmony_ciSANE_Status 1515141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) 1516141cc406Sopenharmony_ci{ 1517141cc406Sopenharmony_ci Teco_Scanner *dev; 1518141cc406Sopenharmony_ci int i; 1519141cc406Sopenharmony_ci 1520141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_devices: enter\n"); 1521141cc406Sopenharmony_ci 1522141cc406Sopenharmony_ci if (devlist) 1523141cc406Sopenharmony_ci free (devlist); 1524141cc406Sopenharmony_ci 1525141cc406Sopenharmony_ci devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); 1526141cc406Sopenharmony_ci if (!devlist) 1527141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1528141cc406Sopenharmony_ci 1529141cc406Sopenharmony_ci i = 0; 1530141cc406Sopenharmony_ci for (dev = first_dev; i < num_devices; dev = dev->next) 1531141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 1532141cc406Sopenharmony_ci devlist[i++] = 0; 1533141cc406Sopenharmony_ci 1534141cc406Sopenharmony_ci *device_list = devlist; 1535141cc406Sopenharmony_ci 1536141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_devices: exit\n"); 1537141cc406Sopenharmony_ci 1538141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1539141cc406Sopenharmony_ci} 1540141cc406Sopenharmony_ci 1541141cc406Sopenharmony_ciSANE_Status 1542141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 1543141cc406Sopenharmony_ci{ 1544141cc406Sopenharmony_ci Teco_Scanner *dev; 1545141cc406Sopenharmony_ci SANE_Status status; 1546141cc406Sopenharmony_ci 1547141cc406Sopenharmony_ci DBG (DBG_proc, "sane_open: enter\n"); 1548141cc406Sopenharmony_ci 1549141cc406Sopenharmony_ci /* search for devicename */ 1550141cc406Sopenharmony_ci if (devicename[0]) 1551141cc406Sopenharmony_ci { 1552141cc406Sopenharmony_ci DBG (DBG_info, "sane_open: devicename=%s\n", devicename); 1553141cc406Sopenharmony_ci 1554141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 1555141cc406Sopenharmony_ci { 1556141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) 1557141cc406Sopenharmony_ci { 1558141cc406Sopenharmony_ci break; 1559141cc406Sopenharmony_ci } 1560141cc406Sopenharmony_ci } 1561141cc406Sopenharmony_ci 1562141cc406Sopenharmony_ci if (!dev) 1563141cc406Sopenharmony_ci { 1564141cc406Sopenharmony_ci status = attach_scanner (devicename, &dev); 1565141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1566141cc406Sopenharmony_ci { 1567141cc406Sopenharmony_ci return status; 1568141cc406Sopenharmony_ci } 1569141cc406Sopenharmony_ci } 1570141cc406Sopenharmony_ci } 1571141cc406Sopenharmony_ci else 1572141cc406Sopenharmony_ci { 1573141cc406Sopenharmony_ci DBG (DBG_sane_info, "sane_open: no devicename, opening first device\n"); 1574141cc406Sopenharmony_ci dev = first_dev; /* empty devicename -> use first device */ 1575141cc406Sopenharmony_ci } 1576141cc406Sopenharmony_ci 1577141cc406Sopenharmony_ci if (!dev) 1578141cc406Sopenharmony_ci { 1579141cc406Sopenharmony_ci DBG (DBG_error, "No scanner found\n"); 1580141cc406Sopenharmony_ci 1581141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1582141cc406Sopenharmony_ci } 1583141cc406Sopenharmony_ci 1584141cc406Sopenharmony_ci teco_init_options (dev); 1585141cc406Sopenharmony_ci 1586141cc406Sopenharmony_ci /* Initialize the gamma table. */ 1587141cc406Sopenharmony_ci { 1588141cc406Sopenharmony_ci /* 1589141cc406Sopenharmony_ci * Shift is 1 for GAMMA_LENGTH == 256 1590141cc406Sopenharmony_ci * and 4 for GAMMA_LENGTH == 1024 1591141cc406Sopenharmony_ci */ 1592141cc406Sopenharmony_ci int shift = GAMMA_LENGTH >> 8; 1593141cc406Sopenharmony_ci size_t i; 1594141cc406Sopenharmony_ci 1595141cc406Sopenharmony_ci for (i = 0; i < GAMMA_LENGTH; i++) 1596141cc406Sopenharmony_ci { 1597141cc406Sopenharmony_ci dev->gamma_R[i] = i / shift; 1598141cc406Sopenharmony_ci dev->gamma_G[i] = i / shift; 1599141cc406Sopenharmony_ci dev->gamma_B[i] = i / shift; 1600141cc406Sopenharmony_ci dev->gamma_GRAY[i] = i / shift; 1601141cc406Sopenharmony_ci } 1602141cc406Sopenharmony_ci } 1603141cc406Sopenharmony_ci 1604141cc406Sopenharmony_ci *handle = dev; 1605141cc406Sopenharmony_ci 1606141cc406Sopenharmony_ci DBG (DBG_proc, "sane_open: exit\n"); 1607141cc406Sopenharmony_ci 1608141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1609141cc406Sopenharmony_ci} 1610141cc406Sopenharmony_ci 1611141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 1612141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 1613141cc406Sopenharmony_ci{ 1614141cc406Sopenharmony_ci Teco_Scanner *dev = handle; 1615141cc406Sopenharmony_ci 1616141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_option_descriptor: enter, option %d\n", option); 1617141cc406Sopenharmony_ci 1618141cc406Sopenharmony_ci if ((unsigned) option >= OPT_NUM_OPTIONS) 1619141cc406Sopenharmony_ci { 1620141cc406Sopenharmony_ci return NULL; 1621141cc406Sopenharmony_ci } 1622141cc406Sopenharmony_ci 1623141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_option_descriptor: exit\n"); 1624141cc406Sopenharmony_ci 1625141cc406Sopenharmony_ci return dev->opt + option; 1626141cc406Sopenharmony_ci} 1627141cc406Sopenharmony_ci 1628141cc406Sopenharmony_ciSANE_Status 1629141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 1630141cc406Sopenharmony_ci SANE_Action action, void *val, SANE_Int * info) 1631141cc406Sopenharmony_ci{ 1632141cc406Sopenharmony_ci Teco_Scanner *dev = handle; 1633141cc406Sopenharmony_ci SANE_Status status; 1634141cc406Sopenharmony_ci SANE_Word cap; 1635141cc406Sopenharmony_ci SANE_String_Const name; 1636141cc406Sopenharmony_ci 1637141cc406Sopenharmony_ci DBG (DBG_proc, "sane_control_option: enter, option %d, action %d\n", 1638141cc406Sopenharmony_ci option, action); 1639141cc406Sopenharmony_ci 1640141cc406Sopenharmony_ci if (info) 1641141cc406Sopenharmony_ci { 1642141cc406Sopenharmony_ci *info = 0; 1643141cc406Sopenharmony_ci } 1644141cc406Sopenharmony_ci 1645141cc406Sopenharmony_ci if (dev->scanning) 1646141cc406Sopenharmony_ci { 1647141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1648141cc406Sopenharmony_ci } 1649141cc406Sopenharmony_ci 1650141cc406Sopenharmony_ci if (option < 0 || option >= OPT_NUM_OPTIONS) 1651141cc406Sopenharmony_ci { 1652141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1653141cc406Sopenharmony_ci } 1654141cc406Sopenharmony_ci 1655141cc406Sopenharmony_ci cap = dev->opt[option].cap; 1656141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (cap)) 1657141cc406Sopenharmony_ci { 1658141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1659141cc406Sopenharmony_ci } 1660141cc406Sopenharmony_ci 1661141cc406Sopenharmony_ci name = dev->opt[option].name; 1662141cc406Sopenharmony_ci if (!name) 1663141cc406Sopenharmony_ci { 1664141cc406Sopenharmony_ci name = "(no name)"; 1665141cc406Sopenharmony_ci } 1666141cc406Sopenharmony_ci if (action == SANE_ACTION_GET_VALUE) 1667141cc406Sopenharmony_ci { 1668141cc406Sopenharmony_ci 1669141cc406Sopenharmony_ci switch (option) 1670141cc406Sopenharmony_ci { 1671141cc406Sopenharmony_ci /* word options */ 1672141cc406Sopenharmony_ci case OPT_NUM_OPTS: 1673141cc406Sopenharmony_ci case OPT_RESOLUTION: 1674141cc406Sopenharmony_ci case OPT_TL_Y: 1675141cc406Sopenharmony_ci case OPT_BR_Y: 1676141cc406Sopenharmony_ci case OPT_TL_X: 1677141cc406Sopenharmony_ci case OPT_BR_X: 1678141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 1679141cc406Sopenharmony_ci case OPT_THRESHOLD: 1680141cc406Sopenharmony_ci case OPT_PREVIEW: 1681141cc406Sopenharmony_ci *(SANE_Word *) val = dev->val[option].w; 1682141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1683141cc406Sopenharmony_ci 1684141cc406Sopenharmony_ci /* string options */ 1685141cc406Sopenharmony_ci case OPT_MODE: 1686141cc406Sopenharmony_ci case OPT_DITHER: 1687141cc406Sopenharmony_ci strcpy (val, dev->val[option].s); 1688141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1689141cc406Sopenharmony_ci 1690141cc406Sopenharmony_ci /* Gamma */ 1691141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 1692141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 1693141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 1694141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_GRAY: 1695141cc406Sopenharmony_ci memcpy (val, dev->val[option].wa, dev->opt[option].size); 1696141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1697141cc406Sopenharmony_ci 1698141cc406Sopenharmony_ci default: 1699141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1700141cc406Sopenharmony_ci } 1701141cc406Sopenharmony_ci } 1702141cc406Sopenharmony_ci else if (action == SANE_ACTION_SET_VALUE) 1703141cc406Sopenharmony_ci { 1704141cc406Sopenharmony_ci 1705141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (cap)) 1706141cc406Sopenharmony_ci { 1707141cc406Sopenharmony_ci DBG (DBG_error, "could not set option, not settable\n"); 1708141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1709141cc406Sopenharmony_ci } 1710141cc406Sopenharmony_ci 1711141cc406Sopenharmony_ci status = sanei_constrain_value (dev->opt + option, val, info); 1712141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1713141cc406Sopenharmony_ci { 1714141cc406Sopenharmony_ci DBG (DBG_error, "could not set option, invalid value\n"); 1715141cc406Sopenharmony_ci return status; 1716141cc406Sopenharmony_ci } 1717141cc406Sopenharmony_ci 1718141cc406Sopenharmony_ci switch (option) 1719141cc406Sopenharmony_ci { 1720141cc406Sopenharmony_ci 1721141cc406Sopenharmony_ci /* Numeric side-effect options */ 1722141cc406Sopenharmony_ci case OPT_TL_Y: 1723141cc406Sopenharmony_ci case OPT_BR_Y: 1724141cc406Sopenharmony_ci case OPT_TL_X: 1725141cc406Sopenharmony_ci case OPT_BR_X: 1726141cc406Sopenharmony_ci case OPT_RESOLUTION: 1727141cc406Sopenharmony_ci if (info) 1728141cc406Sopenharmony_ci { 1729141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 1730141cc406Sopenharmony_ci } 1731141cc406Sopenharmony_ci dev->val[option].w = *(SANE_Word *) val; 1732141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1733141cc406Sopenharmony_ci 1734141cc406Sopenharmony_ci /* Numeric side-effect free options */ 1735141cc406Sopenharmony_ci case OPT_THRESHOLD: 1736141cc406Sopenharmony_ci case OPT_PREVIEW: 1737141cc406Sopenharmony_ci dev->val[option].w = *(SANE_Word *) val; 1738141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1739141cc406Sopenharmony_ci 1740141cc406Sopenharmony_ci /* String side-effect free options */ 1741141cc406Sopenharmony_ci case OPT_DITHER: 1742141cc406Sopenharmony_ci free (dev->val[option].s); 1743141cc406Sopenharmony_ci dev->val[option].s = (SANE_String) strdup (val); 1744141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1745141cc406Sopenharmony_ci 1746141cc406Sopenharmony_ci /* String side-effect options */ 1747141cc406Sopenharmony_ci case OPT_MODE: 1748141cc406Sopenharmony_ci if (strcmp (dev->val[option].s, val) == 0) 1749141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1750141cc406Sopenharmony_ci 1751141cc406Sopenharmony_ci free (dev->val[OPT_MODE].s); 1752141cc406Sopenharmony_ci dev->val[OPT_MODE].s = (SANE_Char *) strdup (val); 1753141cc406Sopenharmony_ci 1754141cc406Sopenharmony_ci dev->opt[OPT_DITHER].cap |= SANE_CAP_INACTIVE; 1755141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; 1756141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1757141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1758141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1759141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; 1760141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 1761141cc406Sopenharmony_ci 1762141cc406Sopenharmony_ci if (strcmp (dev->val[OPT_MODE].s, BLACK_WHITE_STR) == 0) 1763141cc406Sopenharmony_ci { 1764141cc406Sopenharmony_ci dev->depth = 8; 1765141cc406Sopenharmony_ci dev->scan_mode = TECO_BW; 1766141cc406Sopenharmony_ci dev->opt[OPT_DITHER].cap &= ~SANE_CAP_INACTIVE; 1767141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; 1768141cc406Sopenharmony_ci } 1769141cc406Sopenharmony_ci else if (strcmp (dev->val[OPT_MODE].s, GRAY_STR) == 0) 1770141cc406Sopenharmony_ci { 1771141cc406Sopenharmony_ci dev->scan_mode = TECO_GRAYSCALE; 1772141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; 1773141cc406Sopenharmony_ci if (dev->val[OPT_CUSTOM_GAMMA].w) 1774141cc406Sopenharmony_ci { 1775141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_GRAY].cap &= ~SANE_CAP_INACTIVE; 1776141cc406Sopenharmony_ci } 1777141cc406Sopenharmony_ci dev->depth = 8; 1778141cc406Sopenharmony_ci } 1779141cc406Sopenharmony_ci else if (strcmp (dev->val[OPT_MODE].s, COLOR_STR) == 0) 1780141cc406Sopenharmony_ci { 1781141cc406Sopenharmony_ci dev->scan_mode = TECO_COLOR; 1782141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; 1783141cc406Sopenharmony_ci if (dev->val[OPT_CUSTOM_GAMMA].w) 1784141cc406Sopenharmony_ci { 1785141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; 1786141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; 1787141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; 1788141cc406Sopenharmony_ci } 1789141cc406Sopenharmony_ci dev->depth = 8; 1790141cc406Sopenharmony_ci } 1791141cc406Sopenharmony_ci 1792141cc406Sopenharmony_ci if (info) 1793141cc406Sopenharmony_ci { 1794141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 1795141cc406Sopenharmony_ci } 1796141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1797141cc406Sopenharmony_ci 1798141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 1799141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 1800141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 1801141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_GRAY: 1802141cc406Sopenharmony_ci memcpy (dev->val[option].wa, val, dev->opt[option].size); 1803141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1804141cc406Sopenharmony_ci 1805141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 1806141cc406Sopenharmony_ci dev->val[OPT_CUSTOM_GAMMA].w = *(SANE_Word *) val; 1807141cc406Sopenharmony_ci if (dev->val[OPT_CUSTOM_GAMMA].w) 1808141cc406Sopenharmony_ci { 1809141cc406Sopenharmony_ci /* use custom_gamma_table */ 1810141cc406Sopenharmony_ci if (dev->scan_mode == TECO_GRAYSCALE) 1811141cc406Sopenharmony_ci { 1812141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_GRAY].cap &= ~SANE_CAP_INACTIVE; 1813141cc406Sopenharmony_ci } 1814141cc406Sopenharmony_ci else 1815141cc406Sopenharmony_ci { 1816141cc406Sopenharmony_ci /* color mode */ 1817141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; 1818141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; 1819141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; 1820141cc406Sopenharmony_ci } 1821141cc406Sopenharmony_ci } 1822141cc406Sopenharmony_ci else 1823141cc406Sopenharmony_ci { 1824141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1825141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1826141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1827141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; 1828141cc406Sopenharmony_ci } 1829141cc406Sopenharmony_ci if (info) 1830141cc406Sopenharmony_ci { 1831141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 1832141cc406Sopenharmony_ci } 1833141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1834141cc406Sopenharmony_ci 1835141cc406Sopenharmony_ci default: 1836141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1837141cc406Sopenharmony_ci } 1838141cc406Sopenharmony_ci } 1839141cc406Sopenharmony_ci 1840141cc406Sopenharmony_ci DBG (DBG_proc, "sane_control_option: exit, bad\n"); 1841141cc406Sopenharmony_ci 1842141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1843141cc406Sopenharmony_ci} 1844141cc406Sopenharmony_ci 1845141cc406Sopenharmony_ciSANE_Status 1846141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 1847141cc406Sopenharmony_ci{ 1848141cc406Sopenharmony_ci Teco_Scanner *dev = handle; 1849141cc406Sopenharmony_ci 1850141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_parameters: enter\n"); 1851141cc406Sopenharmony_ci 1852141cc406Sopenharmony_ci if (!(dev->scanning)) 1853141cc406Sopenharmony_ci { 1854141cc406Sopenharmony_ci 1855141cc406Sopenharmony_ci /* Setup the parameters for the scan. These values will be re-used 1856141cc406Sopenharmony_ci * in the SET WINDOWS command. */ 1857141cc406Sopenharmony_ci if (dev->val[OPT_PREVIEW].w == SANE_TRUE) 1858141cc406Sopenharmony_ci { 1859141cc406Sopenharmony_ci dev->x_resolution = 22; 1860141cc406Sopenharmony_ci dev->y_resolution = 22; 1861141cc406Sopenharmony_ci dev->x_tl = 0; 1862141cc406Sopenharmony_ci dev->y_tl = 0; 1863141cc406Sopenharmony_ci dev->x_br = mmToIlu (SANE_UNFIX (x_range.max)); 1864141cc406Sopenharmony_ci dev->y_br = mmToIlu (SANE_UNFIX (y_range.max)); 1865141cc406Sopenharmony_ci } 1866141cc406Sopenharmony_ci else 1867141cc406Sopenharmony_ci { 1868141cc406Sopenharmony_ci dev->x_resolution = dev->val[OPT_RESOLUTION].w; 1869141cc406Sopenharmony_ci dev->y_resolution = dev->val[OPT_RESOLUTION].w; 1870141cc406Sopenharmony_ci if (dev->x_resolution > dev->def->x_resolution_max) 1871141cc406Sopenharmony_ci { 1872141cc406Sopenharmony_ci dev->x_resolution = dev->def->x_resolution_max; 1873141cc406Sopenharmony_ci } 1874141cc406Sopenharmony_ci 1875141cc406Sopenharmony_ci dev->x_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w)); 1876141cc406Sopenharmony_ci dev->y_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_Y].w)); 1877141cc406Sopenharmony_ci dev->x_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w)); 1878141cc406Sopenharmony_ci dev->y_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_Y].w)); 1879141cc406Sopenharmony_ci } 1880141cc406Sopenharmony_ci 1881141cc406Sopenharmony_ci /* Check the corners are OK. */ 1882141cc406Sopenharmony_ci if (dev->x_tl > dev->x_br) 1883141cc406Sopenharmony_ci { 1884141cc406Sopenharmony_ci int s; 1885141cc406Sopenharmony_ci s = dev->x_tl; 1886141cc406Sopenharmony_ci dev->x_tl = dev->x_br; 1887141cc406Sopenharmony_ci dev->x_br = s; 1888141cc406Sopenharmony_ci } 1889141cc406Sopenharmony_ci if (dev->y_tl > dev->y_br) 1890141cc406Sopenharmony_ci { 1891141cc406Sopenharmony_ci int s; 1892141cc406Sopenharmony_ci s = dev->y_tl; 1893141cc406Sopenharmony_ci dev->y_tl = dev->y_br; 1894141cc406Sopenharmony_ci dev->y_br = s; 1895141cc406Sopenharmony_ci } 1896141cc406Sopenharmony_ci 1897141cc406Sopenharmony_ci dev->width = dev->x_br - dev->x_tl; 1898141cc406Sopenharmony_ci dev->length = dev->y_br - dev->y_tl; 1899141cc406Sopenharmony_ci 1900141cc406Sopenharmony_ci /* Prepare the parameters for the caller. */ 1901141cc406Sopenharmony_ci memset (&dev->params, 0, sizeof (SANE_Parameters)); 1902141cc406Sopenharmony_ci 1903141cc406Sopenharmony_ci dev->params.last_frame = SANE_TRUE; 1904141cc406Sopenharmony_ci 1905141cc406Sopenharmony_ci switch (dev->scan_mode) 1906141cc406Sopenharmony_ci { 1907141cc406Sopenharmony_ci case TECO_BW: 1908141cc406Sopenharmony_ci dev->params.format = SANE_FRAME_GRAY; 1909141cc406Sopenharmony_ci dev->params.pixels_per_line = 1910141cc406Sopenharmony_ci ((dev->width * dev->x_resolution) / 300) & ~0x7; 1911141cc406Sopenharmony_ci dev->params.bytes_per_line = dev->params.pixels_per_line / 8; 1912141cc406Sopenharmony_ci dev->params.depth = 1; 1913141cc406Sopenharmony_ci dev->pass = 1; 1914141cc406Sopenharmony_ci break; 1915141cc406Sopenharmony_ci case TECO_GRAYSCALE: 1916141cc406Sopenharmony_ci dev->params.format = SANE_FRAME_GRAY; 1917141cc406Sopenharmony_ci dev->params.pixels_per_line = 1918141cc406Sopenharmony_ci ((dev->width * dev->x_resolution) / 300); 1919141cc406Sopenharmony_ci dev->params.bytes_per_line = dev->params.pixels_per_line; 1920141cc406Sopenharmony_ci dev->params.depth = 8; 1921141cc406Sopenharmony_ci dev->pass = 1; 1922141cc406Sopenharmony_ci break; 1923141cc406Sopenharmony_ci case TECO_COLOR: 1924141cc406Sopenharmony_ci dev->params.format = SANE_FRAME_RGB; 1925141cc406Sopenharmony_ci dev->params.pixels_per_line = 1926141cc406Sopenharmony_ci ((dev->width * dev->x_resolution) / 300); 1927141cc406Sopenharmony_ci dev->pass = dev->def->pass; 1928141cc406Sopenharmony_ci dev->params.bytes_per_line = dev->params.pixels_per_line * 3; 1929141cc406Sopenharmony_ci dev->params.depth = 8; 1930141cc406Sopenharmony_ci break; 1931141cc406Sopenharmony_ci } 1932141cc406Sopenharmony_ci 1933141cc406Sopenharmony_ci dev->params.lines = (dev->length * dev->y_resolution) / 300; 1934141cc406Sopenharmony_ci } 1935141cc406Sopenharmony_ci 1936141cc406Sopenharmony_ci /* Return the current values. */ 1937141cc406Sopenharmony_ci if (params) 1938141cc406Sopenharmony_ci { 1939141cc406Sopenharmony_ci *params = (dev->params); 1940141cc406Sopenharmony_ci } 1941141cc406Sopenharmony_ci 1942141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_parameters: exit\n"); 1943141cc406Sopenharmony_ci 1944141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1945141cc406Sopenharmony_ci} 1946141cc406Sopenharmony_ci 1947141cc406Sopenharmony_ciSANE_Status 1948141cc406Sopenharmony_cisane_start (SANE_Handle handle) 1949141cc406Sopenharmony_ci{ 1950141cc406Sopenharmony_ci Teco_Scanner *dev = handle; 1951141cc406Sopenharmony_ci SANE_Status status; 1952141cc406Sopenharmony_ci size_t size; 1953141cc406Sopenharmony_ci 1954141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: enter\n"); 1955141cc406Sopenharmony_ci 1956141cc406Sopenharmony_ci if (!(dev->scanning)) 1957141cc406Sopenharmony_ci { 1958141cc406Sopenharmony_ci 1959141cc406Sopenharmony_ci /* Open again the scanner. */ 1960141cc406Sopenharmony_ci if (sanei_scsi_open 1961141cc406Sopenharmony_ci (dev->devicename, &(dev->sfd), teco_sense_handler, dev) != 0) 1962141cc406Sopenharmony_ci { 1963141cc406Sopenharmony_ci DBG (DBG_error, "ERROR: sane_start: open failed\n"); 1964141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1965141cc406Sopenharmony_ci } 1966141cc406Sopenharmony_ci 1967141cc406Sopenharmony_ci /* Set the correct parameters. */ 1968141cc406Sopenharmony_ci sane_get_parameters (dev, NULL); 1969141cc406Sopenharmony_ci 1970141cc406Sopenharmony_ci /* The scanner must be ready. */ 1971141cc406Sopenharmony_ci status = teco_wait_scanner (dev); 1972141cc406Sopenharmony_ci if (status) 1973141cc406Sopenharmony_ci { 1974141cc406Sopenharmony_ci teco_close (dev); 1975141cc406Sopenharmony_ci return status; 1976141cc406Sopenharmony_ci } 1977141cc406Sopenharmony_ci 1978141cc406Sopenharmony_ci status = teco_mode_select (dev); 1979141cc406Sopenharmony_ci if (status) 1980141cc406Sopenharmony_ci { 1981141cc406Sopenharmony_ci teco_close (dev); 1982141cc406Sopenharmony_ci return status; 1983141cc406Sopenharmony_ci } 1984141cc406Sopenharmony_ci 1985141cc406Sopenharmony_ci if (dev->scan_mode == TECO_COLOR) 1986141cc406Sopenharmony_ci { 1987141cc406Sopenharmony_ci dev->pass = dev->def->pass; 1988141cc406Sopenharmony_ci } 1989141cc406Sopenharmony_ci else 1990141cc406Sopenharmony_ci { 1991141cc406Sopenharmony_ci dev->pass = 1; 1992141cc406Sopenharmony_ci } 1993141cc406Sopenharmony_ci 1994141cc406Sopenharmony_ci if (dev->def->tecoref != TECO_VM3510) 1995141cc406Sopenharmony_ci { 1996141cc406Sopenharmony_ci status = teco_set_window (dev); 1997141cc406Sopenharmony_ci if (status) 1998141cc406Sopenharmony_ci { 1999141cc406Sopenharmony_ci teco_close (dev); 2000141cc406Sopenharmony_ci return status; 2001141cc406Sopenharmony_ci } 2002141cc406Sopenharmony_ci 2003141cc406Sopenharmony_ci dev->real_bytes_left = 0; 2004141cc406Sopenharmony_ci status = get_filled_data_length (dev, &size); 2005141cc406Sopenharmony_ci if (status) 2006141cc406Sopenharmony_ci { 2007141cc406Sopenharmony_ci teco_close (dev); 2008141cc406Sopenharmony_ci return status; 2009141cc406Sopenharmony_ci } 2010141cc406Sopenharmony_ci } 2011141cc406Sopenharmony_ci 2012141cc406Sopenharmony_ci#if 0 2013141cc406Sopenharmony_ci /* The windows driver does that, but some scanners don't like it. */ 2014141cc406Sopenharmony_ci teco_vendor_spec (dev); 2015141cc406Sopenharmony_ci if (status) 2016141cc406Sopenharmony_ci { 2017141cc406Sopenharmony_ci teco_close (dev); 2018141cc406Sopenharmony_ci return status; 2019141cc406Sopenharmony_ci } 2020141cc406Sopenharmony_ci#endif 2021141cc406Sopenharmony_ci 2022141cc406Sopenharmony_ci status = teco_send_gamma (dev); 2023141cc406Sopenharmony_ci if (status) 2024141cc406Sopenharmony_ci { 2025141cc406Sopenharmony_ci teco_close (dev); 2026141cc406Sopenharmony_ci return status; 2027141cc406Sopenharmony_ci } 2028141cc406Sopenharmony_ci 2029141cc406Sopenharmony_ci status = teco_set_window (dev); 2030141cc406Sopenharmony_ci if (status) 2031141cc406Sopenharmony_ci { 2032141cc406Sopenharmony_ci teco_close (dev); 2033141cc406Sopenharmony_ci return status; 2034141cc406Sopenharmony_ci } 2035141cc406Sopenharmony_ci 2036141cc406Sopenharmony_ci status = teco_scan (dev); 2037141cc406Sopenharmony_ci if (status) 2038141cc406Sopenharmony_ci { 2039141cc406Sopenharmony_ci teco_close (dev); 2040141cc406Sopenharmony_ci return status; 2041141cc406Sopenharmony_ci } 2042141cc406Sopenharmony_ci 2043141cc406Sopenharmony_ci if (dev->def->tecoref == TECO_VM3510) 2044141cc406Sopenharmony_ci { 2045141cc406Sopenharmony_ci dev->real_bytes_left = 0; 2046141cc406Sopenharmony_ci status = get_filled_data_length (dev, &size); 2047141cc406Sopenharmony_ci if (status) 2048141cc406Sopenharmony_ci { 2049141cc406Sopenharmony_ci teco_close (dev); 2050141cc406Sopenharmony_ci return status; 2051141cc406Sopenharmony_ci } 2052141cc406Sopenharmony_ci } 2053141cc406Sopenharmony_ci } 2054141cc406Sopenharmony_ci else 2055141cc406Sopenharmony_ci { 2056141cc406Sopenharmony_ci /* Scan has already started. */ 2057141cc406Sopenharmony_ci dev->pass--; 2058141cc406Sopenharmony_ci } 2059141cc406Sopenharmony_ci 2060141cc406Sopenharmony_ci /* Set the frame parameter. */ 2061141cc406Sopenharmony_ci if (dev->scan_mode == TECO_COLOR && dev->def->pass > 1) 2062141cc406Sopenharmony_ci { 2063141cc406Sopenharmony_ci SANE_Frame frames[] = { 0, SANE_FRAME_BLUE, 2064141cc406Sopenharmony_ci SANE_FRAME_GREEN, SANE_FRAME_RED 2065141cc406Sopenharmony_ci }; 2066141cc406Sopenharmony_ci dev->params.format = frames[dev->pass]; 2067141cc406Sopenharmony_ci } 2068141cc406Sopenharmony_ci 2069141cc406Sopenharmony_ci /* Is it the last frame? */ 2070141cc406Sopenharmony_ci if (dev->pass > 1) 2071141cc406Sopenharmony_ci { 2072141cc406Sopenharmony_ci dev->params.last_frame = SANE_FALSE; 2073141cc406Sopenharmony_ci } 2074141cc406Sopenharmony_ci else 2075141cc406Sopenharmony_ci { 2076141cc406Sopenharmony_ci dev->params.last_frame = SANE_TRUE; 2077141cc406Sopenharmony_ci } 2078141cc406Sopenharmony_ci 2079141cc406Sopenharmony_ci dev->image_end = 0; 2080141cc406Sopenharmony_ci dev->image_begin = 0; 2081141cc406Sopenharmony_ci 2082141cc406Sopenharmony_ci dev->bytes_left = dev->params.bytes_per_line * dev->params.lines; 2083141cc406Sopenharmony_ci dev->real_bytes_left = dev->params.bytes_per_line * dev->params.lines; 2084141cc406Sopenharmony_ci 2085141cc406Sopenharmony_ci dev->scanning = SANE_TRUE; 2086141cc406Sopenharmony_ci 2087141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: exit\n"); 2088141cc406Sopenharmony_ci 2089141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2090141cc406Sopenharmony_ci} 2091141cc406Sopenharmony_ci 2092141cc406Sopenharmony_ciSANE_Status 2093141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, 2094141cc406Sopenharmony_ci SANE_Int * len) 2095141cc406Sopenharmony_ci{ 2096141cc406Sopenharmony_ci SANE_Status status; 2097141cc406Sopenharmony_ci Teco_Scanner *dev = handle; 2098141cc406Sopenharmony_ci size_t size; 2099141cc406Sopenharmony_ci int buf_offset; /* offset into buf */ 2100141cc406Sopenharmony_ci 2101141cc406Sopenharmony_ci DBG (DBG_proc, "sane_read: enter\n"); 2102141cc406Sopenharmony_ci 2103141cc406Sopenharmony_ci *len = 0; 2104141cc406Sopenharmony_ci 2105141cc406Sopenharmony_ci if (!(dev->scanning)) 2106141cc406Sopenharmony_ci { 2107141cc406Sopenharmony_ci /* OOPS, not scanning */ 2108141cc406Sopenharmony_ci return do_cancel (dev); 2109141cc406Sopenharmony_ci } 2110141cc406Sopenharmony_ci 2111141cc406Sopenharmony_ci if (dev->bytes_left <= 0) 2112141cc406Sopenharmony_ci { 2113141cc406Sopenharmony_ci return (SANE_STATUS_EOF); 2114141cc406Sopenharmony_ci } 2115141cc406Sopenharmony_ci 2116141cc406Sopenharmony_ci buf_offset = 0; 2117141cc406Sopenharmony_ci 2118141cc406Sopenharmony_ci do 2119141cc406Sopenharmony_ci { 2120141cc406Sopenharmony_ci if (dev->image_begin == dev->image_end) 2121141cc406Sopenharmony_ci { 2122141cc406Sopenharmony_ci /* Fill image */ 2123141cc406Sopenharmony_ci status = teco_fill_image (dev); 2124141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2125141cc406Sopenharmony_ci { 2126141cc406Sopenharmony_ci return (status); 2127141cc406Sopenharmony_ci } 2128141cc406Sopenharmony_ci } 2129141cc406Sopenharmony_ci 2130141cc406Sopenharmony_ci /* Something must have been read */ 2131141cc406Sopenharmony_ci if (dev->image_begin == dev->image_end) 2132141cc406Sopenharmony_ci { 2133141cc406Sopenharmony_ci DBG (DBG_info, "sane_read: nothing read\n"); 2134141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2135141cc406Sopenharmony_ci } 2136141cc406Sopenharmony_ci 2137141cc406Sopenharmony_ci /* Copy the data to the frontend buffer. */ 2138141cc406Sopenharmony_ci size = max_len - buf_offset; 2139141cc406Sopenharmony_ci if (size > dev->bytes_left) 2140141cc406Sopenharmony_ci { 2141141cc406Sopenharmony_ci size = dev->bytes_left; 2142141cc406Sopenharmony_ci } 2143141cc406Sopenharmony_ci teco_copy_raw_to_frontend (dev, buf + buf_offset, &size); 2144141cc406Sopenharmony_ci 2145141cc406Sopenharmony_ci buf_offset += size; 2146141cc406Sopenharmony_ci 2147141cc406Sopenharmony_ci dev->bytes_left -= size; 2148141cc406Sopenharmony_ci *len += size; 2149141cc406Sopenharmony_ci 2150141cc406Sopenharmony_ci } 2151141cc406Sopenharmony_ci while ((buf_offset != max_len) && dev->bytes_left); 2152141cc406Sopenharmony_ci 2153141cc406Sopenharmony_ci DBG (DBG_info, "sane_read: leave, bytes_left=%ld\n", 2154141cc406Sopenharmony_ci (long) dev->bytes_left); 2155141cc406Sopenharmony_ci 2156141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2157141cc406Sopenharmony_ci} 2158141cc406Sopenharmony_ci 2159141cc406Sopenharmony_ciSANE_Status 2160141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) 2161141cc406Sopenharmony_ci{ 2162141cc406Sopenharmony_ci SANE_Status status; 2163141cc406Sopenharmony_ci Teco_Scanner *dev = handle; 2164141cc406Sopenharmony_ci 2165141cc406Sopenharmony_ci DBG (DBG_proc, "sane_set_io_mode: enter\n"); 2166141cc406Sopenharmony_ci 2167141cc406Sopenharmony_ci if (dev->scanning == SANE_FALSE) 2168141cc406Sopenharmony_ci { 2169141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2170141cc406Sopenharmony_ci } 2171141cc406Sopenharmony_ci 2172141cc406Sopenharmony_ci if (non_blocking == SANE_FALSE) 2173141cc406Sopenharmony_ci { 2174141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 2175141cc406Sopenharmony_ci } 2176141cc406Sopenharmony_ci else 2177141cc406Sopenharmony_ci { 2178141cc406Sopenharmony_ci status = SANE_STATUS_UNSUPPORTED; 2179141cc406Sopenharmony_ci } 2180141cc406Sopenharmony_ci 2181141cc406Sopenharmony_ci DBG (DBG_proc, "sane_set_io_mode: exit\n"); 2182141cc406Sopenharmony_ci 2183141cc406Sopenharmony_ci return status; 2184141cc406Sopenharmony_ci} 2185141cc406Sopenharmony_ci 2186141cc406Sopenharmony_ciSANE_Status 2187141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ *fd) 2188141cc406Sopenharmony_ci{ 2189141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_select_fd: enter\n"); 2190141cc406Sopenharmony_ci 2191141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_select_fd: exit\n"); 2192141cc406Sopenharmony_ci 2193141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 2194141cc406Sopenharmony_ci} 2195141cc406Sopenharmony_ci 2196141cc406Sopenharmony_civoid 2197141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 2198141cc406Sopenharmony_ci{ 2199141cc406Sopenharmony_ci Teco_Scanner *dev = handle; 2200141cc406Sopenharmony_ci 2201141cc406Sopenharmony_ci DBG (DBG_proc, "sane_cancel: enter\n"); 2202141cc406Sopenharmony_ci 2203141cc406Sopenharmony_ci do_cancel (dev); 2204141cc406Sopenharmony_ci 2205141cc406Sopenharmony_ci DBG (DBG_proc, "sane_cancel: exit\n"); 2206141cc406Sopenharmony_ci} 2207141cc406Sopenharmony_ci 2208141cc406Sopenharmony_civoid 2209141cc406Sopenharmony_cisane_close (SANE_Handle handle) 2210141cc406Sopenharmony_ci{ 2211141cc406Sopenharmony_ci Teco_Scanner *dev = handle; 2212141cc406Sopenharmony_ci Teco_Scanner *dev_tmp; 2213141cc406Sopenharmony_ci 2214141cc406Sopenharmony_ci DBG (DBG_proc, "sane_close: enter\n"); 2215141cc406Sopenharmony_ci 2216141cc406Sopenharmony_ci do_cancel (dev); 2217141cc406Sopenharmony_ci teco_close (dev); 2218141cc406Sopenharmony_ci 2219141cc406Sopenharmony_ci /* Unlink dev. */ 2220141cc406Sopenharmony_ci if (first_dev == dev) 2221141cc406Sopenharmony_ci { 2222141cc406Sopenharmony_ci first_dev = dev->next; 2223141cc406Sopenharmony_ci } 2224141cc406Sopenharmony_ci else 2225141cc406Sopenharmony_ci { 2226141cc406Sopenharmony_ci dev_tmp = first_dev; 2227141cc406Sopenharmony_ci while (dev_tmp->next && dev_tmp->next != dev) 2228141cc406Sopenharmony_ci { 2229141cc406Sopenharmony_ci dev_tmp = dev_tmp->next; 2230141cc406Sopenharmony_ci } 2231141cc406Sopenharmony_ci if (dev_tmp->next != NULL) 2232141cc406Sopenharmony_ci { 2233141cc406Sopenharmony_ci dev_tmp->next = dev_tmp->next->next; 2234141cc406Sopenharmony_ci } 2235141cc406Sopenharmony_ci } 2236141cc406Sopenharmony_ci 2237141cc406Sopenharmony_ci teco_free (dev); 2238141cc406Sopenharmony_ci num_devices--; 2239141cc406Sopenharmony_ci 2240141cc406Sopenharmony_ci DBG (DBG_proc, "sane_close: exit\n"); 2241141cc406Sopenharmony_ci} 2242141cc406Sopenharmony_ci 2243141cc406Sopenharmony_civoid 2244141cc406Sopenharmony_cisane_exit (void) 2245141cc406Sopenharmony_ci{ 2246141cc406Sopenharmony_ci DBG (DBG_proc, "sane_exit: enter\n"); 2247141cc406Sopenharmony_ci 2248141cc406Sopenharmony_ci while (first_dev) 2249141cc406Sopenharmony_ci { 2250141cc406Sopenharmony_ci sane_close (first_dev); 2251141cc406Sopenharmony_ci } 2252141cc406Sopenharmony_ci 2253141cc406Sopenharmony_ci if (devlist) 2254141cc406Sopenharmony_ci { 2255141cc406Sopenharmony_ci free (devlist); 2256141cc406Sopenharmony_ci devlist = NULL; 2257141cc406Sopenharmony_ci } 2258141cc406Sopenharmony_ci 2259141cc406Sopenharmony_ci DBG (DBG_proc, "sane_exit: exit\n"); 2260141cc406Sopenharmony_ci} 2261