1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci Copyright (C) 2002 Frank Zago (sane at zago dot net) 4141cc406Sopenharmony_ci Copyright (C) 2002 Other SANE contributors 5141cc406Sopenharmony_ci 6141cc406Sopenharmony_ci This file is part of the SANE package. 7141cc406Sopenharmony_ci 8141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 9141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 10141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 11141cc406Sopenharmony_ci License, or (at your option) any later version. 12141cc406Sopenharmony_ci 13141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 14141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 15141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16141cc406Sopenharmony_ci General Public License for more details. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 19141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 20141cc406Sopenharmony_ci 21141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 22141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 23141cc406Sopenharmony_ci 24141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 25141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 26141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 27141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 28141cc406Sopenharmony_ci account of linking the SANE library code into it. 29141cc406Sopenharmony_ci 30141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 31141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 32141cc406Sopenharmony_ci License. 33141cc406Sopenharmony_ci 34141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 35141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 36141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 37141cc406Sopenharmony_ci 38141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 39141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 40141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 41141cc406Sopenharmony_ci*/ 42141cc406Sopenharmony_ci 43141cc406Sopenharmony_ci/* 44141cc406Sopenharmony_ci Sceptre S1200 SCSI scanner (sometimes also called S120) 45141cc406Sopenharmony_ci*/ 46141cc406Sopenharmony_ci 47141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 48141cc406Sopenharmony_ci 49141cc406Sopenharmony_ci#define BUILD 10 /* 2002-03-21 */ 50141cc406Sopenharmony_ci#define BACKEND_NAME sceptre 51141cc406Sopenharmony_ci#define SCEPTRE_CONFIG_FILE "sceptre.conf" 52141cc406Sopenharmony_ci 53141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 54141cc406Sopenharmony_ci 55141cc406Sopenharmony_ci 56141cc406Sopenharmony_ci#include "../include/sane/config.h" 57141cc406Sopenharmony_ci 58141cc406Sopenharmony_ci#include <errno.h> 59141cc406Sopenharmony_ci#include <fcntl.h> 60141cc406Sopenharmony_ci#include <limits.h> 61141cc406Sopenharmony_ci#include <signal.h> 62141cc406Sopenharmony_ci#include <stdio.h> 63141cc406Sopenharmony_ci#include <stdlib.h> 64141cc406Sopenharmony_ci#include <string.h> 65141cc406Sopenharmony_ci#include <sys/types.h> 66141cc406Sopenharmony_ci#include <sys/wait.h> 67141cc406Sopenharmony_ci#include <unistd.h> 68141cc406Sopenharmony_ci 69141cc406Sopenharmony_ci#include "../include/sane/sane.h" 70141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 71141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 72141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h" 73141cc406Sopenharmony_ci#include "../include/sane/sanei_debug.h" 74141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 75141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 76141cc406Sopenharmony_ci#include "../include/lassert.h" 77141cc406Sopenharmony_ci 78141cc406Sopenharmony_ci#include "sceptre.h" 79141cc406Sopenharmony_ci 80141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 81141cc406Sopenharmony_ci 82141cc406Sopenharmony_cistatic const SANE_String scan_mode_list[] = { LINEART_STR, HALFTONE_STR, 83141cc406Sopenharmony_ci GRAY_STR, COLOR_STR, NULL 84141cc406Sopenharmony_ci}; 85141cc406Sopenharmony_ci 86141cc406Sopenharmony_cistatic const SANE_Range gamma_range = { 87141cc406Sopenharmony_ci 0, /* minimum */ 88141cc406Sopenharmony_ci 255, /* maximum */ 89141cc406Sopenharmony_ci 0 /* quantization */ 90141cc406Sopenharmony_ci}; 91141cc406Sopenharmony_ci 92141cc406Sopenharmony_cistatic const SANE_Range threshold_range = { 93141cc406Sopenharmony_ci 0, /* minimum */ 94141cc406Sopenharmony_ci 255, /* maximum */ 95141cc406Sopenharmony_ci 0 /* quantization */ 96141cc406Sopenharmony_ci}; 97141cc406Sopenharmony_ci 98141cc406Sopenharmony_cistatic const SANE_Range halftone_range = { 99141cc406Sopenharmony_ci 1, /* minimum */ 100141cc406Sopenharmony_ci 4, /* maximum */ 101141cc406Sopenharmony_ci 0 /* quantization */ 102141cc406Sopenharmony_ci}; 103141cc406Sopenharmony_ci 104141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 105141cc406Sopenharmony_ci 106141cc406Sopenharmony_ci#define NUM_OF_RES 15 107141cc406Sopenharmony_ci/* Table of supported resolution and number of lines of color shifting. */ 108141cc406Sopenharmony_cistatic const SANE_Word resolutions_list[NUM_OF_RES + 1] = { 109141cc406Sopenharmony_ci NUM_OF_RES, 10, 25, 30, 45, 75, 90, 150, 300, 450, 600, 750, 900, 1050, 110141cc406Sopenharmony_ci 1125, 1200 111141cc406Sopenharmony_ci}; 112141cc406Sopenharmony_ci 113141cc406Sopenharmony_cistatic const SANE_Word color_shift_list[NUM_OF_RES + 1] = { 114141cc406Sopenharmony_ci NUM_OF_RES, 0, 0, 0, 0, 1, 1, 2, 4, 6, 8, 10, 12, 14, 15, 16 115141cc406Sopenharmony_ci}; 116141cc406Sopenharmony_ci 117141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 118141cc406Sopenharmony_ci 119141cc406Sopenharmony_ci/* Define the supported scanners and their characteristics. */ 120141cc406Sopenharmony_cistatic const struct scanners_supported scanners[] = { 121141cc406Sopenharmony_ci /* { 6, "KINPO ", "Vividscan S600 ", "KINPO", "S600" }, */ 122141cc406Sopenharmony_ci {6, "KINPO ", "Vividscan S120 ", "Sceptre", "S1200"} 123141cc406Sopenharmony_ci}; 124141cc406Sopenharmony_ci 125141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 126141cc406Sopenharmony_ci 127141cc406Sopenharmony_ci/* List of scanner attached. */ 128141cc406Sopenharmony_cistatic Sceptre_Scanner *first_dev = NULL; 129141cc406Sopenharmony_cistatic int num_devices = 0; 130141cc406Sopenharmony_cistatic const SANE_Device **devlist = NULL; 131141cc406Sopenharmony_ci 132141cc406Sopenharmony_ci 133141cc406Sopenharmony_ci/* Local functions. */ 134141cc406Sopenharmony_ci 135141cc406Sopenharmony_ci/* Display a buffer in the log. */ 136141cc406Sopenharmony_cistatic void 137141cc406Sopenharmony_cihexdump (int level, const char *comment, unsigned char *p, int l) 138141cc406Sopenharmony_ci{ 139141cc406Sopenharmony_ci int i; 140141cc406Sopenharmony_ci char line[128]; 141141cc406Sopenharmony_ci char *ptr; 142141cc406Sopenharmony_ci 143141cc406Sopenharmony_ci DBG (level, "%s\n", comment); 144141cc406Sopenharmony_ci ptr = line; 145141cc406Sopenharmony_ci for (i = 0; i < l; i++, p++) 146141cc406Sopenharmony_ci { 147141cc406Sopenharmony_ci if ((i % 16) == 0) 148141cc406Sopenharmony_ci { 149141cc406Sopenharmony_ci if (ptr != line) 150141cc406Sopenharmony_ci { 151141cc406Sopenharmony_ci *ptr = '\0'; 152141cc406Sopenharmony_ci DBG (level, "%s\n", line); 153141cc406Sopenharmony_ci ptr = line; 154141cc406Sopenharmony_ci } 155141cc406Sopenharmony_ci sprintf (ptr, "%3.3d:", i); 156141cc406Sopenharmony_ci ptr += 4; 157141cc406Sopenharmony_ci } 158141cc406Sopenharmony_ci sprintf (ptr, " %2.2x", *p); 159141cc406Sopenharmony_ci ptr += 3; 160141cc406Sopenharmony_ci } 161141cc406Sopenharmony_ci *ptr = '\0'; 162141cc406Sopenharmony_ci DBG (level, "%s\n", line); 163141cc406Sopenharmony_ci} 164141cc406Sopenharmony_ci 165141cc406Sopenharmony_ci/* Initialize a scanner entry. Return an allocated scanner with some 166141cc406Sopenharmony_ci * preset values. */ 167141cc406Sopenharmony_cistatic Sceptre_Scanner * 168141cc406Sopenharmony_cisceptre_init (void) 169141cc406Sopenharmony_ci{ 170141cc406Sopenharmony_ci Sceptre_Scanner *dev; 171141cc406Sopenharmony_ci 172141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_init: enter\n"); 173141cc406Sopenharmony_ci 174141cc406Sopenharmony_ci /* Allocate a new scanner entry. */ 175141cc406Sopenharmony_ci dev = malloc (sizeof (Sceptre_Scanner)); 176141cc406Sopenharmony_ci if (dev == NULL) 177141cc406Sopenharmony_ci { 178141cc406Sopenharmony_ci return NULL; 179141cc406Sopenharmony_ci } 180141cc406Sopenharmony_ci 181141cc406Sopenharmony_ci memset (dev, 0, sizeof (Sceptre_Scanner)); 182141cc406Sopenharmony_ci 183141cc406Sopenharmony_ci /* Allocate the buffer used to transfer the SCSI data. */ 184141cc406Sopenharmony_ci dev->buffer_size = 64 * 1024; 185141cc406Sopenharmony_ci dev->buffer = malloc (dev->buffer_size); 186141cc406Sopenharmony_ci if (dev->buffer == NULL) 187141cc406Sopenharmony_ci { 188141cc406Sopenharmony_ci free (dev); 189141cc406Sopenharmony_ci return NULL; 190141cc406Sopenharmony_ci } 191141cc406Sopenharmony_ci 192141cc406Sopenharmony_ci dev->sfd = -1; 193141cc406Sopenharmony_ci 194141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_init: exit\n"); 195141cc406Sopenharmony_ci 196141cc406Sopenharmony_ci return (dev); 197141cc406Sopenharmony_ci} 198141cc406Sopenharmony_ci 199141cc406Sopenharmony_ci/* Closes an open scanner. */ 200141cc406Sopenharmony_cistatic void 201141cc406Sopenharmony_cisceptre_close (Sceptre_Scanner * dev) 202141cc406Sopenharmony_ci{ 203141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_close: enter\n"); 204141cc406Sopenharmony_ci 205141cc406Sopenharmony_ci if (dev->sfd != -1) 206141cc406Sopenharmony_ci { 207141cc406Sopenharmony_ci sanei_scsi_close (dev->sfd); 208141cc406Sopenharmony_ci dev->sfd = -1; 209141cc406Sopenharmony_ci } 210141cc406Sopenharmony_ci 211141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_close: exit\n"); 212141cc406Sopenharmony_ci} 213141cc406Sopenharmony_ci 214141cc406Sopenharmony_ci/* Frees the memory used by a scanner. */ 215141cc406Sopenharmony_cistatic void 216141cc406Sopenharmony_cisceptre_free (Sceptre_Scanner * dev) 217141cc406Sopenharmony_ci{ 218141cc406Sopenharmony_ci int i; 219141cc406Sopenharmony_ci 220141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_free: enter\n"); 221141cc406Sopenharmony_ci 222141cc406Sopenharmony_ci if (dev == NULL) 223141cc406Sopenharmony_ci return; 224141cc406Sopenharmony_ci 225141cc406Sopenharmony_ci sceptre_close (dev); 226141cc406Sopenharmony_ci if (dev->devicename) 227141cc406Sopenharmony_ci { 228141cc406Sopenharmony_ci free (dev->devicename); 229141cc406Sopenharmony_ci } 230141cc406Sopenharmony_ci if (dev->buffer) 231141cc406Sopenharmony_ci { 232141cc406Sopenharmony_ci free (dev->buffer); 233141cc406Sopenharmony_ci } 234141cc406Sopenharmony_ci if (dev->image) 235141cc406Sopenharmony_ci { 236141cc406Sopenharmony_ci free (dev->image); 237141cc406Sopenharmony_ci } 238141cc406Sopenharmony_ci for (i = 1; i < OPT_NUM_OPTIONS; i++) 239141cc406Sopenharmony_ci { 240141cc406Sopenharmony_ci if (dev->opt[i].type == SANE_TYPE_STRING && dev->val[i].s) 241141cc406Sopenharmony_ci { 242141cc406Sopenharmony_ci free (dev->val[i].s); 243141cc406Sopenharmony_ci } 244141cc406Sopenharmony_ci } 245141cc406Sopenharmony_ci 246141cc406Sopenharmony_ci free (dev); 247141cc406Sopenharmony_ci 248141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_free: exit\n"); 249141cc406Sopenharmony_ci} 250141cc406Sopenharmony_ci 251141cc406Sopenharmony_ci/* Inquiry a device and returns TRUE if is supported. */ 252141cc406Sopenharmony_cistatic int 253141cc406Sopenharmony_cisceptre_identify_scanner (Sceptre_Scanner * dev) 254141cc406Sopenharmony_ci{ 255141cc406Sopenharmony_ci CDB cdb; 256141cc406Sopenharmony_ci SANE_Status status; 257141cc406Sopenharmony_ci size_t size; 258141cc406Sopenharmony_ci int i; 259141cc406Sopenharmony_ci 260141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_identify_scanner: enter\n"); 261141cc406Sopenharmony_ci 262141cc406Sopenharmony_ci size = 36; 263141cc406Sopenharmony_ci MKSCSI_INQUIRY (cdb, size); 264141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 265141cc406Sopenharmony_ci NULL, 0, dev->buffer, &size); 266141cc406Sopenharmony_ci 267141cc406Sopenharmony_ci if (status) 268141cc406Sopenharmony_ci { 269141cc406Sopenharmony_ci DBG (DBG_error, 270141cc406Sopenharmony_ci "sceptre_identify_scanner: inquiry failed with status %s\n", 271141cc406Sopenharmony_ci sane_strstatus (status)); 272141cc406Sopenharmony_ci return (SANE_FALSE); 273141cc406Sopenharmony_ci } 274141cc406Sopenharmony_ci 275141cc406Sopenharmony_ci if (size < 36) 276141cc406Sopenharmony_ci { 277141cc406Sopenharmony_ci DBG (DBG_error, 278141cc406Sopenharmony_ci "sceptre_identify_scanner: not enough data to identify device\n"); 279141cc406Sopenharmony_ci return (SANE_FALSE); 280141cc406Sopenharmony_ci } 281141cc406Sopenharmony_ci 282141cc406Sopenharmony_ci dev->scsi_type = dev->buffer[0] & 0x1f; 283141cc406Sopenharmony_ci memcpy (dev->scsi_vendor, dev->buffer + 0x08, 0x08); 284141cc406Sopenharmony_ci dev->scsi_vendor[0x08] = 0; 285141cc406Sopenharmony_ci memcpy (dev->scsi_product, dev->buffer + 0x10, 0x010); 286141cc406Sopenharmony_ci dev->scsi_product[0x10] = 0; 287141cc406Sopenharmony_ci memcpy (dev->scsi_version, dev->buffer + 0x20, 0x04); 288141cc406Sopenharmony_ci dev->scsi_version[0x04] = 0; 289141cc406Sopenharmony_ci 290141cc406Sopenharmony_ci DBG (DBG_info, "device is \"%s\" \"%s\" \"%s\"\n", 291141cc406Sopenharmony_ci dev->scsi_vendor, dev->scsi_product, dev->scsi_version); 292141cc406Sopenharmony_ci 293141cc406Sopenharmony_ci /* Lookup through the supported scanners table to find if this 294141cc406Sopenharmony_ci * backend supports that one. */ 295141cc406Sopenharmony_ci for (i = 0; i < NELEMS (scanners); i++) 296141cc406Sopenharmony_ci { 297141cc406Sopenharmony_ci if (dev->scsi_type == scanners[i].scsi_type && 298141cc406Sopenharmony_ci strcmp (dev->scsi_vendor, scanners[i].scsi_vendor) == 0 && 299141cc406Sopenharmony_ci strcmp (dev->scsi_product, scanners[i].scsi_product) == 0) 300141cc406Sopenharmony_ci { 301141cc406Sopenharmony_ci 302141cc406Sopenharmony_ci DBG (DBG_error, "sceptre_identify_scanner: scanner supported\n"); 303141cc406Sopenharmony_ci 304141cc406Sopenharmony_ci dev->scnum = i; 305141cc406Sopenharmony_ci 306141cc406Sopenharmony_ci return (SANE_TRUE); 307141cc406Sopenharmony_ci } 308141cc406Sopenharmony_ci } 309141cc406Sopenharmony_ci 310141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_identify_scanner: exit\n"); 311141cc406Sopenharmony_ci 312141cc406Sopenharmony_ci return (SANE_FALSE); 313141cc406Sopenharmony_ci} 314141cc406Sopenharmony_ci 315141cc406Sopenharmony_ci/* Return the number of bytes left to read. */ 316141cc406Sopenharmony_cistatic SANE_Status 317141cc406Sopenharmony_cisceptre_get_status (Sceptre_Scanner * dev, size_t * data_left) 318141cc406Sopenharmony_ci{ 319141cc406Sopenharmony_ci size_t size; 320141cc406Sopenharmony_ci CDB cdb; 321141cc406Sopenharmony_ci SANE_Status status; 322141cc406Sopenharmony_ci 323141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_get_status: enter\n"); 324141cc406Sopenharmony_ci 325141cc406Sopenharmony_ci /* Get status. */ 326141cc406Sopenharmony_ci size = 0x10; 327141cc406Sopenharmony_ci MKSCSI_GET_DATA_BUFFER_STATUS (cdb, 1, size); 328141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 329141cc406Sopenharmony_ci NULL, 0, dev->buffer, &size); 330141cc406Sopenharmony_ci 331141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 332141cc406Sopenharmony_ci { 333141cc406Sopenharmony_ci DBG (DBG_error, "sceptre_get_status: cannot get buffer status\n"); 334141cc406Sopenharmony_ci *data_left = 0; 335141cc406Sopenharmony_ci return (SANE_STATUS_IO_ERROR); 336141cc406Sopenharmony_ci } 337141cc406Sopenharmony_ci 338141cc406Sopenharmony_ci if (size != 16) 339141cc406Sopenharmony_ci { 340141cc406Sopenharmony_ci DBG (DBG_error, 341141cc406Sopenharmony_ci "sceptre_get_status: invalid data size returned (%ld)\n", 342141cc406Sopenharmony_ci (long) size); 343141cc406Sopenharmony_ci return (SANE_STATUS_IO_ERROR); 344141cc406Sopenharmony_ci } 345141cc406Sopenharmony_ci 346141cc406Sopenharmony_ci hexdump (DBG_info2, "GET BUFFER STATUS result", dev->buffer, 16); 347141cc406Sopenharmony_ci 348141cc406Sopenharmony_ci /* Read the size left. The scanner returns the rest of the 349141cc406Sopenharmony_ci * bytes to read, not just what's in its buffers. */ 350141cc406Sopenharmony_ci *data_left = B32TOI (&dev->buffer[8]); 351141cc406Sopenharmony_ci 352141cc406Sopenharmony_ci if (dev->raster_real == 0) 353141cc406Sopenharmony_ci { 354141cc406Sopenharmony_ci /* First call. Set the correct parameters. */ 355141cc406Sopenharmony_ci dev->raster_real = B16TOI (&dev->buffer[12]) * 3; 356141cc406Sopenharmony_ci dev->params.lines = B16TOI (&dev->buffer[12]); 357141cc406Sopenharmony_ci dev->params.pixels_per_line = B16TOI (&dev->buffer[14]); 358141cc406Sopenharmony_ci } 359141cc406Sopenharmony_ci 360141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_get_status: exit, data_left=%ld\n", 361141cc406Sopenharmony_ci (long) *data_left); 362141cc406Sopenharmony_ci 363141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 364141cc406Sopenharmony_ci} 365141cc406Sopenharmony_ci 366141cc406Sopenharmony_ci/* 367141cc406Sopenharmony_ci * Adjust the rasters. This function is used during a color scan, 368141cc406Sopenharmony_ci * because the scanner does not present a format sane can interpret 369141cc406Sopenharmony_ci * directly. 370141cc406Sopenharmony_ci * 371141cc406Sopenharmony_ci * The scanner sends the colors by rasters (R then G then B), whereas 372141cc406Sopenharmony_ci * sane is waiting for a group of 3 bytes per color. To make things 373141cc406Sopenharmony_ci * funnier, the rasters are shifted. This shift factor depends on the 374141cc406Sopenharmony_ci * resolution used. The format of those raster is: 375141cc406Sopenharmony_ci * R...R RG...RG RGB...RGB BG...GB B...B 376141cc406Sopenharmony_ci * 377141cc406Sopenharmony_ci * So this function reorders all that mess. It gets the input from 378141cc406Sopenharmony_ci * dev->buffer and write the output in dev->image. size_in the the 379141cc406Sopenharmony_ci * length of the valid data in dev->buffer. 380141cc406Sopenharmony_ci */ 381141cc406Sopenharmony_cistatic void 382141cc406Sopenharmony_cisceptre_adjust_raster (Sceptre_Scanner * dev, size_t size_in) 383141cc406Sopenharmony_ci{ 384141cc406Sopenharmony_ci int nb_rasters; /* number of rasters in dev->buffer */ 385141cc406Sopenharmony_ci 386141cc406Sopenharmony_ci int raster; /* current raster number in buffer */ 387141cc406Sopenharmony_ci int line; /* line number for that raster */ 388141cc406Sopenharmony_ci int colour; /* colour for that raster */ 389141cc406Sopenharmony_ci size_t offset; 390141cc406Sopenharmony_ci 391141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_adjust_raster: enter\n"); 392141cc406Sopenharmony_ci 393141cc406Sopenharmony_ci assert (dev->scan_mode == SCEPTRE_COLOR); 394141cc406Sopenharmony_ci assert ((size_in % dev->params.bytes_per_line) == 0); 395141cc406Sopenharmony_ci 396141cc406Sopenharmony_ci if (size_in == 0) 397141cc406Sopenharmony_ci { 398141cc406Sopenharmony_ci return; 399141cc406Sopenharmony_ci } 400141cc406Sopenharmony_ci 401141cc406Sopenharmony_ci /* 402141cc406Sopenharmony_ci * The color coding is one line for each color (in the RGB order). 403141cc406Sopenharmony_ci * Recombine that stuff to create a RGB value for each pixel. 404141cc406Sopenharmony_ci */ 405141cc406Sopenharmony_ci 406141cc406Sopenharmony_ci nb_rasters = size_in / dev->raster_size; 407141cc406Sopenharmony_ci 408141cc406Sopenharmony_ci for (raster = 0; raster < nb_rasters; raster++) 409141cc406Sopenharmony_ci { 410141cc406Sopenharmony_ci 411141cc406Sopenharmony_ci /* 412141cc406Sopenharmony_ci * Find the color to which this raster belongs to. 413141cc406Sopenharmony_ci * 0 = red 414141cc406Sopenharmony_ci * 1 = green 415141cc406Sopenharmony_ci * 2 = blue 416141cc406Sopenharmony_ci * 417141cc406Sopenharmony_ci * When blue comes, it always finishes the current line; 418141cc406Sopenharmony_ci */ 419141cc406Sopenharmony_ci line = 0; 420141cc406Sopenharmony_ci if (dev->raster_num < dev->color_shift) 421141cc406Sopenharmony_ci { 422141cc406Sopenharmony_ci colour = 0; /* Red */ 423141cc406Sopenharmony_ci line = dev->raster_num; 424141cc406Sopenharmony_ci } 425141cc406Sopenharmony_ci else if (dev->raster_num < (3 * dev->color_shift)) 426141cc406Sopenharmony_ci { 427141cc406Sopenharmony_ci /* even = red, odd = green */ 428141cc406Sopenharmony_ci colour = (dev->raster_num - dev->color_shift) % 2; 429141cc406Sopenharmony_ci if (colour) 430141cc406Sopenharmony_ci { 431141cc406Sopenharmony_ci /* Green */ 432141cc406Sopenharmony_ci line = (dev->raster_num - dev->color_shift) / 2; 433141cc406Sopenharmony_ci } 434141cc406Sopenharmony_ci else 435141cc406Sopenharmony_ci { 436141cc406Sopenharmony_ci /* Red */ 437141cc406Sopenharmony_ci line = (dev->raster_num + dev->color_shift) / 2; 438141cc406Sopenharmony_ci } 439141cc406Sopenharmony_ci } 440141cc406Sopenharmony_ci else if (dev->raster_num >= dev->raster_real - dev->color_shift) 441141cc406Sopenharmony_ci { 442141cc406Sopenharmony_ci /* Blue */ 443141cc406Sopenharmony_ci colour = 2; 444141cc406Sopenharmony_ci line = dev->line; 445141cc406Sopenharmony_ci } 446141cc406Sopenharmony_ci else if (dev->raster_num >= dev->raster_real - 3 * dev->color_shift) 447141cc406Sopenharmony_ci { 448141cc406Sopenharmony_ci /* Green or Blue */ 449141cc406Sopenharmony_ci colour = 450141cc406Sopenharmony_ci (dev->raster_real - dev->raster_num - dev->color_shift) % 2 + 1; 451141cc406Sopenharmony_ci if (colour == 1) 452141cc406Sopenharmony_ci { 453141cc406Sopenharmony_ci /* Green */ 454141cc406Sopenharmony_ci line = dev->line + dev->color_shift; 455141cc406Sopenharmony_ci } 456141cc406Sopenharmony_ci else 457141cc406Sopenharmony_ci { 458141cc406Sopenharmony_ci /* Blue */ 459141cc406Sopenharmony_ci line = dev->line; 460141cc406Sopenharmony_ci } 461141cc406Sopenharmony_ci } 462141cc406Sopenharmony_ci else 463141cc406Sopenharmony_ci { 464141cc406Sopenharmony_ci colour = (dev->raster_num - 3 * dev->color_shift) % 3; 465141cc406Sopenharmony_ci switch (colour) 466141cc406Sopenharmony_ci { 467141cc406Sopenharmony_ci case 0: 468141cc406Sopenharmony_ci /* Red */ 469141cc406Sopenharmony_ci line = (dev->raster_num + 3 * dev->color_shift) / 3; 470141cc406Sopenharmony_ci break; 471141cc406Sopenharmony_ci case 1: 472141cc406Sopenharmony_ci /* Green */ 473141cc406Sopenharmony_ci line = dev->raster_num / 3; 474141cc406Sopenharmony_ci break; 475141cc406Sopenharmony_ci case 2: 476141cc406Sopenharmony_ci /* Blue */ 477141cc406Sopenharmony_ci line = (dev->raster_num - 3 * dev->color_shift) / 3; 478141cc406Sopenharmony_ci break; 479141cc406Sopenharmony_ci } 480141cc406Sopenharmony_ci } 481141cc406Sopenharmony_ci 482141cc406Sopenharmony_ci /* Adjust the line number relative to the image. */ 483141cc406Sopenharmony_ci line -= dev->line; 484141cc406Sopenharmony_ci 485141cc406Sopenharmony_ci offset = dev->image_end + line * dev->params.bytes_per_line; 486141cc406Sopenharmony_ci 487141cc406Sopenharmony_ci assert (offset <= (dev->image_size - dev->raster_size)); 488141cc406Sopenharmony_ci 489141cc406Sopenharmony_ci /* Copy the raster to the temporary image. */ 490141cc406Sopenharmony_ci { 491141cc406Sopenharmony_ci int i; 492141cc406Sopenharmony_ci unsigned char *src = dev->buffer + raster * dev->raster_size; 493141cc406Sopenharmony_ci unsigned char *dest = dev->image + offset + colour; 494141cc406Sopenharmony_ci 495141cc406Sopenharmony_ci for (i = 0; i < dev->raster_size; i++) 496141cc406Sopenharmony_ci { 497141cc406Sopenharmony_ci *dest = *src; 498141cc406Sopenharmony_ci src++; 499141cc406Sopenharmony_ci dest += 3; 500141cc406Sopenharmony_ci } 501141cc406Sopenharmony_ci } 502141cc406Sopenharmony_ci 503141cc406Sopenharmony_ci if (colour == 2) 504141cc406Sopenharmony_ci { 505141cc406Sopenharmony_ci /* This blue raster completes a new line */ 506141cc406Sopenharmony_ci dev->line++; 507141cc406Sopenharmony_ci dev->image_end += dev->params.bytes_per_line; 508141cc406Sopenharmony_ci } 509141cc406Sopenharmony_ci 510141cc406Sopenharmony_ci dev->raster_num++; 511141cc406Sopenharmony_ci } 512141cc406Sopenharmony_ci 513141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_adjust_raster: exit\n"); 514141cc406Sopenharmony_ci} 515141cc406Sopenharmony_ci 516141cc406Sopenharmony_ci/* SCSI sense handler. Callback for SANE. 517141cc406Sopenharmony_ci * 518141cc406Sopenharmony_ci * Since this scanner does not have REQUEST SENSE, it is always an 519141cc406Sopenharmony_ci * error if this function is called.*/ 520141cc406Sopenharmony_cistatic SANE_Status 521141cc406Sopenharmony_cisceptre_sense_handler (int scsi_fd, unsigned char __sane_unused__ *result, void __sane_unused__ *arg) 522141cc406Sopenharmony_ci{ 523141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_sense_handler (scsi_fd = %d)\n", scsi_fd); 524141cc406Sopenharmony_ci 525141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 526141cc406Sopenharmony_ci} 527141cc406Sopenharmony_ci 528141cc406Sopenharmony_ci/* Attach a scanner to this backend. */ 529141cc406Sopenharmony_cistatic SANE_Status 530141cc406Sopenharmony_ciattach_scanner (const char *devicename, Sceptre_Scanner ** devp) 531141cc406Sopenharmony_ci{ 532141cc406Sopenharmony_ci Sceptre_Scanner *dev; 533141cc406Sopenharmony_ci int sfd; 534141cc406Sopenharmony_ci 535141cc406Sopenharmony_ci DBG (DBG_sane_proc, "attach_scanner: %s\n", devicename); 536141cc406Sopenharmony_ci 537141cc406Sopenharmony_ci if (devp) 538141cc406Sopenharmony_ci *devp = NULL; 539141cc406Sopenharmony_ci 540141cc406Sopenharmony_ci /* Check if we know this device name. */ 541141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 542141cc406Sopenharmony_ci { 543141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) 544141cc406Sopenharmony_ci { 545141cc406Sopenharmony_ci if (devp) 546141cc406Sopenharmony_ci { 547141cc406Sopenharmony_ci *devp = dev; 548141cc406Sopenharmony_ci } 549141cc406Sopenharmony_ci DBG (DBG_info, "device is already known\n"); 550141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 551141cc406Sopenharmony_ci } 552141cc406Sopenharmony_ci } 553141cc406Sopenharmony_ci 554141cc406Sopenharmony_ci /* Allocate a new scanner entry. */ 555141cc406Sopenharmony_ci dev = sceptre_init (); 556141cc406Sopenharmony_ci if (dev == NULL) 557141cc406Sopenharmony_ci { 558141cc406Sopenharmony_ci DBG (DBG_error, "ERROR: not enough memory\n"); 559141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 560141cc406Sopenharmony_ci } 561141cc406Sopenharmony_ci 562141cc406Sopenharmony_ci DBG (DBG_info, "attach_scanner: opening %s\n", devicename); 563141cc406Sopenharmony_ci 564141cc406Sopenharmony_ci if (sanei_scsi_open (devicename, &sfd, sceptre_sense_handler, dev) != 0) 565141cc406Sopenharmony_ci { 566141cc406Sopenharmony_ci DBG (DBG_error, "ERROR: attach_scanner: open failed\n"); 567141cc406Sopenharmony_ci sceptre_free (dev); 568141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 569141cc406Sopenharmony_ci } 570141cc406Sopenharmony_ci 571141cc406Sopenharmony_ci /* Fill some scanner specific values. */ 572141cc406Sopenharmony_ci dev->devicename = strdup (devicename); 573141cc406Sopenharmony_ci dev->sfd = sfd; 574141cc406Sopenharmony_ci 575141cc406Sopenharmony_ci /* Now, check that it is a scanner we support. */ 576141cc406Sopenharmony_ci if (sceptre_identify_scanner (dev) == SANE_FALSE) 577141cc406Sopenharmony_ci { 578141cc406Sopenharmony_ci DBG (DBG_error, 579141cc406Sopenharmony_ci "ERROR: attach_scanner: scanner-identification failed\n"); 580141cc406Sopenharmony_ci sceptre_free (dev); 581141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 582141cc406Sopenharmony_ci } 583141cc406Sopenharmony_ci 584141cc406Sopenharmony_ci sceptre_close (dev); 585141cc406Sopenharmony_ci 586141cc406Sopenharmony_ci /* Set the default options for that scanner. */ 587141cc406Sopenharmony_ci dev->sane.name = dev->devicename; 588141cc406Sopenharmony_ci dev->sane.vendor = scanners[dev->scnum].real_vendor; 589141cc406Sopenharmony_ci dev->sane.model = scanners[dev->scnum].real_product; 590141cc406Sopenharmony_ci dev->sane.type = SANE_I18N ("flatbed scanner"); 591141cc406Sopenharmony_ci 592141cc406Sopenharmony_ci dev->resolution_range.min = SANE_FIX (50); 593141cc406Sopenharmony_ci dev->resolution_range.max = SANE_FIX (1200); 594141cc406Sopenharmony_ci dev->resolution_range.quant = SANE_FIX (1); 595141cc406Sopenharmony_ci 596141cc406Sopenharmony_ci /* 597141cc406Sopenharmony_ci * The S1200 has an area of 8.5 inches / 11.7 inches. (A4 like) 598141cc406Sopenharmony_ci * That's roughly 215*297 mm 599141cc406Sopenharmony_ci * The values are coded by 600141cc406Sopenharmony_ci * size in inch * 600 dpi. 601141cc406Sopenharmony_ci * The maximums are: 602141cc406Sopenharmony_ci * X: 8.5 inches * 600 = 5100 dots 603141cc406Sopenharmony_ci * Y: 11.7 inches * 600 = 7020 604141cc406Sopenharmony_ci * (although the windows driver stops at 7019) 605141cc406Sopenharmony_ci * 606141cc406Sopenharmony_ci * The values are stored in mm. Inches sucks anyway. 607141cc406Sopenharmony_ci * X: 5078 dots (22 dots lost) 608141cc406Sopenharmony_ci * Y: 7015 dots (5 dots lost) 609141cc406Sopenharmony_ci * 610141cc406Sopenharmony_ci * There seems to be a minimum area, but yet to be determined. 611141cc406Sopenharmony_ci */ 612141cc406Sopenharmony_ci dev->x_range.min = SANE_FIX (0); 613141cc406Sopenharmony_ci dev->x_range.max = SANE_FIX (215.90); /* in mm */ 614141cc406Sopenharmony_ci dev->x_range.quant = 0; 615141cc406Sopenharmony_ci 616141cc406Sopenharmony_ci dev->y_range.min = SANE_FIX (0); 617141cc406Sopenharmony_ci dev->y_range.max = SANE_FIX (297.14); /* in mm */ 618141cc406Sopenharmony_ci dev->y_range.quant = SANE_FIX (0); 619141cc406Sopenharmony_ci 620141cc406Sopenharmony_ci /* Link the scanner with the others. */ 621141cc406Sopenharmony_ci dev->next = first_dev; 622141cc406Sopenharmony_ci first_dev = dev; 623141cc406Sopenharmony_ci 624141cc406Sopenharmony_ci if (devp) 625141cc406Sopenharmony_ci { 626141cc406Sopenharmony_ci *devp = dev; 627141cc406Sopenharmony_ci } 628141cc406Sopenharmony_ci 629141cc406Sopenharmony_ci num_devices++; 630141cc406Sopenharmony_ci 631141cc406Sopenharmony_ci DBG (DBG_proc, "attach_scanner: exit\n"); 632141cc406Sopenharmony_ci 633141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 634141cc406Sopenharmony_ci} 635141cc406Sopenharmony_ci 636141cc406Sopenharmony_cistatic SANE_Status 637141cc406Sopenharmony_ciattach_one (const char *dev) 638141cc406Sopenharmony_ci{ 639141cc406Sopenharmony_ci attach_scanner (dev, NULL); 640141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 641141cc406Sopenharmony_ci} 642141cc406Sopenharmony_ci 643141cc406Sopenharmony_ci/* Reset the options for that scanner. */ 644141cc406Sopenharmony_cistatic void 645141cc406Sopenharmony_cisceptre_init_options (Sceptre_Scanner * dev) 646141cc406Sopenharmony_ci{ 647141cc406Sopenharmony_ci int i; 648141cc406Sopenharmony_ci 649141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_init_options: enter\n"); 650141cc406Sopenharmony_ci 651141cc406Sopenharmony_ci /* Pre-initialize the options. */ 652141cc406Sopenharmony_ci memset (dev->opt, 0, sizeof (dev->opt)); 653141cc406Sopenharmony_ci memset (dev->val, 0, sizeof (dev->val)); 654141cc406Sopenharmony_ci 655141cc406Sopenharmony_ci for (i = 0; i < OPT_NUM_OPTIONS; ++i) 656141cc406Sopenharmony_ci { 657141cc406Sopenharmony_ci dev->opt[i].size = sizeof (SANE_Word); 658141cc406Sopenharmony_ci dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 659141cc406Sopenharmony_ci } 660141cc406Sopenharmony_ci 661141cc406Sopenharmony_ci /* Number of options. */ 662141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; 663141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 664141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 665141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 666141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 667141cc406Sopenharmony_ci dev->val[OPT_NUM_OPTS].w = OPT_NUM_OPTIONS; 668141cc406Sopenharmony_ci 669141cc406Sopenharmony_ci /* Mode group */ 670141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode"); 671141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].desc = ""; /* not valid for a group */ 672141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 673141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].cap = 0; 674141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].size = 0; 675141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 676141cc406Sopenharmony_ci 677141cc406Sopenharmony_ci /* Scanner supported modes */ 678141cc406Sopenharmony_ci dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; 679141cc406Sopenharmony_ci dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 680141cc406Sopenharmony_ci dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 681141cc406Sopenharmony_ci dev->opt[OPT_MODE].type = SANE_TYPE_STRING; 682141cc406Sopenharmony_ci dev->opt[OPT_MODE].size = 30; /* should define yet another max_string_size() */ 683141cc406Sopenharmony_ci dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 684141cc406Sopenharmony_ci dev->opt[OPT_MODE].constraint.string_list = 685141cc406Sopenharmony_ci (SANE_String_Const *) scan_mode_list; 686141cc406Sopenharmony_ci dev->val[OPT_MODE].s = (SANE_Char *) strdup (scan_mode_list[0]); 687141cc406Sopenharmony_ci 688141cc406Sopenharmony_ci /* Common resolution */ 689141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 690141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 691141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 692141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; 693141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 694141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; 695141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].constraint.word_list = resolutions_list; 696141cc406Sopenharmony_ci dev->val[OPT_RESOLUTION].w = 150; 697141cc406Sopenharmony_ci 698141cc406Sopenharmony_ci /* Geometry group */ 699141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); 700141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].desc = ""; /* not valid for a group */ 701141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 702141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; 703141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].size = 0; 704141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 705141cc406Sopenharmony_ci 706141cc406Sopenharmony_ci /* Upper left X */ 707141cc406Sopenharmony_ci dev->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 708141cc406Sopenharmony_ci dev->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 709141cc406Sopenharmony_ci dev->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 710141cc406Sopenharmony_ci dev->opt[OPT_TL_X].type = SANE_TYPE_FIXED; 711141cc406Sopenharmony_ci dev->opt[OPT_TL_X].unit = SANE_UNIT_MM; 712141cc406Sopenharmony_ci dev->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 713141cc406Sopenharmony_ci dev->opt[OPT_TL_X].constraint.range = &(dev->x_range); 714141cc406Sopenharmony_ci dev->val[OPT_TL_X].w = dev->x_range.min; 715141cc406Sopenharmony_ci 716141cc406Sopenharmony_ci /* Upper left Y */ 717141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 718141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 719141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 720141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; 721141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].unit = SANE_UNIT_MM; 722141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 723141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].constraint.range = &(dev->y_range); 724141cc406Sopenharmony_ci dev->val[OPT_TL_Y].w = dev->y_range.min; 725141cc406Sopenharmony_ci 726141cc406Sopenharmony_ci /* bottom-right x */ 727141cc406Sopenharmony_ci dev->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 728141cc406Sopenharmony_ci dev->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 729141cc406Sopenharmony_ci dev->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 730141cc406Sopenharmony_ci dev->opt[OPT_BR_X].type = SANE_TYPE_FIXED; 731141cc406Sopenharmony_ci dev->opt[OPT_BR_X].unit = SANE_UNIT_MM; 732141cc406Sopenharmony_ci dev->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 733141cc406Sopenharmony_ci dev->opt[OPT_BR_X].constraint.range = &(dev->x_range); 734141cc406Sopenharmony_ci dev->val[OPT_BR_X].w = dev->x_range.max; 735141cc406Sopenharmony_ci 736141cc406Sopenharmony_ci /* bottom-right y */ 737141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 738141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 739141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 740141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; 741141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].unit = SANE_UNIT_MM; 742141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 743141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].constraint.range = &(dev->y_range); 744141cc406Sopenharmony_ci dev->val[OPT_BR_Y].w = dev->y_range.max; 745141cc406Sopenharmony_ci 746141cc406Sopenharmony_ci /* Enhancement group */ 747141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); 748141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].desc = ""; /* not valid for a group */ 749141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; 750141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].cap = 0; 751141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].size = 0; 752141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 753141cc406Sopenharmony_ci 754141cc406Sopenharmony_ci /* custom-gamma table */ 755141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; 756141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; 757141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; 758141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; 759141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; 760141cc406Sopenharmony_ci dev->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; 761141cc406Sopenharmony_ci 762141cc406Sopenharmony_ci /* red gamma vector */ 763141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; 764141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; 765141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; 766141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; 767141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 768141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; 769141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].size = GAMMA_LENGTH * sizeof (SANE_Word); 770141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; 771141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range; 772141cc406Sopenharmony_ci dev->val[OPT_GAMMA_VECTOR_R].wa = dev->gamma_R; 773141cc406Sopenharmony_ci 774141cc406Sopenharmony_ci /* green gamma vector */ 775141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; 776141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; 777141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; 778141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; 779141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 780141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; 781141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].size = GAMMA_LENGTH * sizeof (SANE_Word); 782141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; 783141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range; 784141cc406Sopenharmony_ci dev->val[OPT_GAMMA_VECTOR_G].wa = dev->gamma_G; 785141cc406Sopenharmony_ci 786141cc406Sopenharmony_ci /* blue gamma vector */ 787141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; 788141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; 789141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; 790141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; 791141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 792141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; 793141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].size = GAMMA_LENGTH * sizeof (SANE_Word); 794141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; 795141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range; 796141cc406Sopenharmony_ci dev->val[OPT_GAMMA_VECTOR_B].wa = dev->gamma_B; 797141cc406Sopenharmony_ci 798141cc406Sopenharmony_ci /* Threshold */ 799141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; 800141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; 801141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; 802141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; 803141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; 804141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].size = sizeof (SANE_Int); 805141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 806141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; 807141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].constraint.range = &threshold_range; 808141cc406Sopenharmony_ci dev->val[OPT_THRESHOLD].w = 128; 809141cc406Sopenharmony_ci 810141cc406Sopenharmony_ci /* Halftone pattern */ 811141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; 812141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; 813141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; 814141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_INT; 815141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].size = sizeof (SANE_Int); 816141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; 817141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_RANGE; 818141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].constraint.range = &halftone_range; 819141cc406Sopenharmony_ci dev->val[OPT_HALFTONE_PATTERN].w = 1; 820141cc406Sopenharmony_ci 821141cc406Sopenharmony_ci /* preview */ 822141cc406Sopenharmony_ci dev->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; 823141cc406Sopenharmony_ci dev->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; 824141cc406Sopenharmony_ci dev->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; 825141cc406Sopenharmony_ci dev->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; 826141cc406Sopenharmony_ci dev->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 827141cc406Sopenharmony_ci dev->val[OPT_PREVIEW].w = SANE_FALSE; 828141cc406Sopenharmony_ci 829141cc406Sopenharmony_ci /* Lastly, set the default mode. This might change some values 830141cc406Sopenharmony_ci * previously set here. */ 831141cc406Sopenharmony_ci sane_control_option (dev, OPT_MODE, SANE_ACTION_SET_VALUE, 832141cc406Sopenharmony_ci (SANE_String *) COLOR_STR, NULL); 833141cc406Sopenharmony_ci 834141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_init_options: leave\n"); 835141cc406Sopenharmony_ci} 836141cc406Sopenharmony_ci 837141cc406Sopenharmony_ci/* Wait until the scanner is ready. 838141cc406Sopenharmony_ci * 839141cc406Sopenharmony_ci * The only reason I know the scanner is not ready is because it is 840141cc406Sopenharmony_ci * moving the CCD. 841141cc406Sopenharmony_ci */ 842141cc406Sopenharmony_cistatic SANE_Status 843141cc406Sopenharmony_cisceptre_wait_scanner (Sceptre_Scanner * dev) 844141cc406Sopenharmony_ci{ 845141cc406Sopenharmony_ci SANE_Status status; 846141cc406Sopenharmony_ci int timeout; 847141cc406Sopenharmony_ci CDB cdb; 848141cc406Sopenharmony_ci size_t size; 849141cc406Sopenharmony_ci 850141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_wait_scanner: enter\n"); 851141cc406Sopenharmony_ci 852141cc406Sopenharmony_ci MKSCSI_TEST_UNIT_READY (cdb); 853141cc406Sopenharmony_ci cdb.data[4] = 1; /* returns one byte. Non standard SCSI. */ 854141cc406Sopenharmony_ci 855141cc406Sopenharmony_ci /* Set the timeout to 120 seconds. */ 856141cc406Sopenharmony_ci timeout = 120; 857141cc406Sopenharmony_ci 858141cc406Sopenharmony_ci while (timeout > 0) 859141cc406Sopenharmony_ci { 860141cc406Sopenharmony_ci 861141cc406Sopenharmony_ci /* test unit ready */ 862141cc406Sopenharmony_ci size = 1; /* read one info byte */ 863141cc406Sopenharmony_ci status = 864141cc406Sopenharmony_ci sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 865141cc406Sopenharmony_ci NULL, 0, dev->buffer, &size); 866141cc406Sopenharmony_ci 867141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD || size != 1) 868141cc406Sopenharmony_ci { 869141cc406Sopenharmony_ci DBG (DBG_error, "sceptre_wait_scanner: TUR failed\n"); 870141cc406Sopenharmony_ci return (SANE_STATUS_IO_ERROR); 871141cc406Sopenharmony_ci } 872141cc406Sopenharmony_ci 873141cc406Sopenharmony_ci /* Apparently the scanner returns only 2 values: 874141cc406Sopenharmony_ci * 0x00 - ready 875141cc406Sopenharmony_ci * 0xff - not ready 876141cc406Sopenharmony_ci */ 877141cc406Sopenharmony_ci if (dev->buffer[0] != 0x00) 878141cc406Sopenharmony_ci { 879141cc406Sopenharmony_ci sleep (1); /* wait 1 seconds */ 880141cc406Sopenharmony_ci timeout--; 881141cc406Sopenharmony_ci } 882141cc406Sopenharmony_ci else 883141cc406Sopenharmony_ci { 884141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 885141cc406Sopenharmony_ci } 886141cc406Sopenharmony_ci }; 887141cc406Sopenharmony_ci 888141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_wait_scanner: scanner not ready\n"); 889141cc406Sopenharmony_ci return (SANE_STATUS_IO_ERROR); 890141cc406Sopenharmony_ci} 891141cc406Sopenharmony_ci 892141cc406Sopenharmony_ci/* Diagnostic the scanner. */ 893141cc406Sopenharmony_cistatic SANE_Status 894141cc406Sopenharmony_cisceptre_do_diag (Sceptre_Scanner * dev) 895141cc406Sopenharmony_ci{ 896141cc406Sopenharmony_ci SANE_Status status; 897141cc406Sopenharmony_ci CDB cdb; 898141cc406Sopenharmony_ci size_t size; 899141cc406Sopenharmony_ci 900141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_receive_diag enter\n"); 901141cc406Sopenharmony_ci 902141cc406Sopenharmony_ci /* SEND DIAGNOSTIC. */ 903141cc406Sopenharmony_ci MKSCSI_SEND_DIAG (cdb, 0); 904141cc406Sopenharmony_ci 905141cc406Sopenharmony_ci /* The windows driver sets that field. This is non standard. */ 906141cc406Sopenharmony_ci cdb.data[2] = 0x80; 907141cc406Sopenharmony_ci 908141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); 909141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 910141cc406Sopenharmony_ci { 911141cc406Sopenharmony_ci DBG (DBG_error, "sceptre_do_diag: exit, status=%d\n", status); 912141cc406Sopenharmony_ci return (status); 913141cc406Sopenharmony_ci } 914141cc406Sopenharmony_ci 915141cc406Sopenharmony_ci /* RECEIVE DIAGNOSTIC */ 916141cc406Sopenharmony_ci 917141cc406Sopenharmony_ci /* The windows driver ask for 3 byte. This is non standard 918141cc406Sopenharmony_ci * SCSI. The page returned should be at least 4 bytes. */ 919141cc406Sopenharmony_ci size = 3; 920141cc406Sopenharmony_ci MKSCSI_RECEIVE_DIAG (cdb, 0, size); 921141cc406Sopenharmony_ci 922141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 923141cc406Sopenharmony_ci NULL, 0, dev->buffer, &size); 924141cc406Sopenharmony_ci 925141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 926141cc406Sopenharmony_ci { 927141cc406Sopenharmony_ci DBG (DBG_error, "sceptre_do_diag: exit, status=%d\n", status); 928141cc406Sopenharmony_ci return (status); 929141cc406Sopenharmony_ci } 930141cc406Sopenharmony_ci 931141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_receive_diag exit\n"); 932141cc406Sopenharmony_ci 933141cc406Sopenharmony_ci return (status); 934141cc406Sopenharmony_ci} 935141cc406Sopenharmony_ci 936141cc406Sopenharmony_ci/* I'm not sure if the command sent is really set mode. The SCSI 937141cc406Sopenharmony_ci * command used is MODE SELECT, but no data is sent. Again, this is 938141cc406Sopenharmony_ci * not standard. */ 939141cc406Sopenharmony_cistatic SANE_Status 940141cc406Sopenharmony_cisceptre_set_mode (Sceptre_Scanner * dev) 941141cc406Sopenharmony_ci{ 942141cc406Sopenharmony_ci SANE_Status status; 943141cc406Sopenharmony_ci CDB cdb; 944141cc406Sopenharmony_ci size_t size; 945141cc406Sopenharmony_ci 946141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_set_mode: enter\n"); 947141cc406Sopenharmony_ci 948141cc406Sopenharmony_ci size = 0x18; 949141cc406Sopenharmony_ci MKSCSI_MODE_SELECT (cdb, 1, 0, size); 950141cc406Sopenharmony_ci 951141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); 952141cc406Sopenharmony_ci 953141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_set_mode: exit, status=%d\n", status); 954141cc406Sopenharmony_ci 955141cc406Sopenharmony_ci return (status); 956141cc406Sopenharmony_ci} 957141cc406Sopenharmony_ci 958141cc406Sopenharmony_ci/* Start a scan. */ 959141cc406Sopenharmony_cistatic SANE_Status 960141cc406Sopenharmony_cisceptre_scan (Sceptre_Scanner * dev) 961141cc406Sopenharmony_ci{ 962141cc406Sopenharmony_ci CDB cdb; 963141cc406Sopenharmony_ci SANE_Status status; 964141cc406Sopenharmony_ci 965141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_scan: enter\n"); 966141cc406Sopenharmony_ci 967141cc406Sopenharmony_ci MKSCSI_SCAN (cdb); 968141cc406Sopenharmony_ci 969141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); 970141cc406Sopenharmony_ci 971141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_scan: exit, status=%d\n", status); 972141cc406Sopenharmony_ci 973141cc406Sopenharmony_ci return status; 974141cc406Sopenharmony_ci} 975141cc406Sopenharmony_ci 976141cc406Sopenharmony_ci/* Set a window. */ 977141cc406Sopenharmony_cistatic SANE_Status 978141cc406Sopenharmony_cisceptre_set_window (Sceptre_Scanner * dev) 979141cc406Sopenharmony_ci{ 980141cc406Sopenharmony_ci size_t size; 981141cc406Sopenharmony_ci CDB cdb; 982141cc406Sopenharmony_ci unsigned char window[82]; 983141cc406Sopenharmony_ci SANE_Status status; 984141cc406Sopenharmony_ci 985141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_set_window: enter\n"); 986141cc406Sopenharmony_ci 987141cc406Sopenharmony_ci size = sizeof (window); 988141cc406Sopenharmony_ci MKSCSI_SET_WINDOW (cdb, size); 989141cc406Sopenharmony_ci 990141cc406Sopenharmony_ci memset (window, 0, size); 991141cc406Sopenharmony_ci 992141cc406Sopenharmony_ci /* size of the parameters (74 = 0x4a bytes) */ 993141cc406Sopenharmony_ci window[7] = sizeof (window) - 8; 994141cc406Sopenharmony_ci 995141cc406Sopenharmony_ci /* X and Y resolution */ 996141cc406Sopenharmony_ci Ito16 (dev->resolution, &window[10]); 997141cc406Sopenharmony_ci Ito16 (dev->resolution, &window[12]); 998141cc406Sopenharmony_ci 999141cc406Sopenharmony_ci /* Upper Left (X,Y) */ 1000141cc406Sopenharmony_ci Ito32 (dev->x_tl, &window[14]); 1001141cc406Sopenharmony_ci Ito32 (dev->y_tl, &window[18]); 1002141cc406Sopenharmony_ci 1003141cc406Sopenharmony_ci /* Width and length */ 1004141cc406Sopenharmony_ci Ito32 (dev->width, &window[22]); 1005141cc406Sopenharmony_ci Ito32 (dev->length, &window[26]); 1006141cc406Sopenharmony_ci 1007141cc406Sopenharmony_ci /* Image Composition, Halftone and Depth */ 1008141cc406Sopenharmony_ci switch (dev->scan_mode) 1009141cc406Sopenharmony_ci { 1010141cc406Sopenharmony_ci case SCEPTRE_LINEART: 1011141cc406Sopenharmony_ci window[31] = dev->val[OPT_THRESHOLD].w; 1012141cc406Sopenharmony_ci window[33] = 0; 1013141cc406Sopenharmony_ci window[34] = 1; 1014141cc406Sopenharmony_ci window[36] = 0; 1015141cc406Sopenharmony_ci break; 1016141cc406Sopenharmony_ci case SCEPTRE_HALFTONE: 1017141cc406Sopenharmony_ci window[31] = 0x80; 1018141cc406Sopenharmony_ci window[33] = 0; 1019141cc406Sopenharmony_ci window[34] = 1; 1020141cc406Sopenharmony_ci window[36] = dev->val[OPT_HALFTONE_PATTERN].w; 1021141cc406Sopenharmony_ci break; 1022141cc406Sopenharmony_ci case SCEPTRE_GRAYSCALE: 1023141cc406Sopenharmony_ci window[31] = 0x80; 1024141cc406Sopenharmony_ci window[33] = 2; 1025141cc406Sopenharmony_ci window[34] = 8; 1026141cc406Sopenharmony_ci window[36] = 0; 1027141cc406Sopenharmony_ci break; 1028141cc406Sopenharmony_ci case SCEPTRE_COLOR: 1029141cc406Sopenharmony_ci window[31] = 0x80; 1030141cc406Sopenharmony_ci window[33] = 5; 1031141cc406Sopenharmony_ci window[34] = 24; 1032141cc406Sopenharmony_ci window[36] = 0; 1033141cc406Sopenharmony_ci break; 1034141cc406Sopenharmony_ci } 1035141cc406Sopenharmony_ci 1036141cc406Sopenharmony_ci /* Unknown parameters. They look constant in the windows driver. */ 1037141cc406Sopenharmony_ci window[30] = 0x04; 1038141cc406Sopenharmony_ci window[32] = 0x04; 1039141cc406Sopenharmony_ci window[37] = 0x80; /* RIF, although it looks unused. */ 1040141cc406Sopenharmony_ci 1041141cc406Sopenharmony_ci hexdump (DBG_info2, "windows", window, sizeof (window)); 1042141cc406Sopenharmony_ci 1043141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 1044141cc406Sopenharmony_ci window, sizeof (window), NULL, NULL); 1045141cc406Sopenharmony_ci 1046141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_set_window: exit, status=%d\n", status); 1047141cc406Sopenharmony_ci 1048141cc406Sopenharmony_ci return status; 1049141cc406Sopenharmony_ci} 1050141cc406Sopenharmony_ci 1051141cc406Sopenharmony_ci/* Read the image from the scanner and fill the temporary buffer with it. */ 1052141cc406Sopenharmony_cistatic SANE_Status 1053141cc406Sopenharmony_cisceptre_fill_image (Sceptre_Scanner * dev) 1054141cc406Sopenharmony_ci{ 1055141cc406Sopenharmony_ci SANE_Status status; 1056141cc406Sopenharmony_ci size_t size; 1057141cc406Sopenharmony_ci CDB cdb; 1058141cc406Sopenharmony_ci size_t data_left; 1059141cc406Sopenharmony_ci 1060141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_fill_image: enter\n"); 1061141cc406Sopenharmony_ci 1062141cc406Sopenharmony_ci assert (dev->image_begin == dev->image_end); 1063141cc406Sopenharmony_ci assert (dev->real_bytes_left > 0); 1064141cc406Sopenharmony_ci 1065141cc406Sopenharmony_ci /* Copy the complete lines, plus the imcompletes 1066141cc406Sopenharmony_ci * ones. We don't keep the real end of data used 1067141cc406Sopenharmony_ci * in image, so we copy the biggest possible. 1068141cc406Sopenharmony_ci * 1069141cc406Sopenharmony_ci * This is a no-op for non color images. 1070141cc406Sopenharmony_ci */ 1071141cc406Sopenharmony_ci memmove (dev->image, dev->image + dev->image_begin, dev->raster_ahead); 1072141cc406Sopenharmony_ci dev->image_begin = 0; 1073141cc406Sopenharmony_ci dev->image_end = 0; 1074141cc406Sopenharmony_ci 1075141cc406Sopenharmony_ci while (dev->real_bytes_left) 1076141cc406Sopenharmony_ci { 1077141cc406Sopenharmony_ci 1078141cc406Sopenharmony_ci if ((status = sceptre_get_status (dev, &data_left)) != SANE_STATUS_GOOD) 1079141cc406Sopenharmony_ci { 1080141cc406Sopenharmony_ci return (status); 1081141cc406Sopenharmony_ci } 1082141cc406Sopenharmony_ci 1083141cc406Sopenharmony_ci /* 1084141cc406Sopenharmony_ci * Try to read the maximum number of bytes. 1085141cc406Sopenharmony_ci */ 1086141cc406Sopenharmony_ci size = data_left; 1087141cc406Sopenharmony_ci if (size > dev->real_bytes_left) 1088141cc406Sopenharmony_ci { 1089141cc406Sopenharmony_ci size = dev->real_bytes_left; 1090141cc406Sopenharmony_ci } 1091141cc406Sopenharmony_ci if (size > dev->image_size - dev->raster_ahead - dev->image_end) 1092141cc406Sopenharmony_ci { 1093141cc406Sopenharmony_ci size = dev->image_size - dev->raster_ahead - dev->image_end; 1094141cc406Sopenharmony_ci } 1095141cc406Sopenharmony_ci if (size > dev->buffer_size) 1096141cc406Sopenharmony_ci { 1097141cc406Sopenharmony_ci size = dev->buffer_size; 1098141cc406Sopenharmony_ci } 1099141cc406Sopenharmony_ci 1100141cc406Sopenharmony_ci /* Round down to a multiple of line size. */ 1101141cc406Sopenharmony_ci size = size - (size % dev->params.bytes_per_line); 1102141cc406Sopenharmony_ci 1103141cc406Sopenharmony_ci if (size == 0) 1104141cc406Sopenharmony_ci { 1105141cc406Sopenharmony_ci /* Probably reached the end of the buffer. 1106141cc406Sopenharmony_ci * Check, just in case. */ 1107141cc406Sopenharmony_ci assert (dev->image_end != 0); 1108141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 1109141cc406Sopenharmony_ci } 1110141cc406Sopenharmony_ci 1111141cc406Sopenharmony_ci DBG (DBG_info, "sceptre_fill_image: to read = %ld bytes (bpl=%d)\n", 1112141cc406Sopenharmony_ci (long) size, dev->params.bytes_per_line); 1113141cc406Sopenharmony_ci 1114141cc406Sopenharmony_ci MKSCSI_READ_10 (cdb, 0, 0, size); 1115141cc406Sopenharmony_ci 1116141cc406Sopenharmony_ci hexdump (DBG_info2, "sceptre_fill_image: READ_10 CDB", cdb.data, 10); 1117141cc406Sopenharmony_ci 1118141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 1119141cc406Sopenharmony_ci NULL, 0, dev->buffer, &size); 1120141cc406Sopenharmony_ci 1121141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1122141cc406Sopenharmony_ci { 1123141cc406Sopenharmony_ci DBG (DBG_error, 1124141cc406Sopenharmony_ci "sceptre_fill_image: cannot read from the scanner\n"); 1125141cc406Sopenharmony_ci return status; 1126141cc406Sopenharmony_ci } 1127141cc406Sopenharmony_ci 1128141cc406Sopenharmony_ci DBG (DBG_info, "sceptre_fill_image: real bytes left = %ld\n", 1129141cc406Sopenharmony_ci (long)dev->real_bytes_left); 1130141cc406Sopenharmony_ci 1131141cc406Sopenharmony_ci switch (dev->scan_mode) 1132141cc406Sopenharmony_ci { 1133141cc406Sopenharmony_ci case SCEPTRE_COLOR: 1134141cc406Sopenharmony_ci sceptre_adjust_raster (dev, size); 1135141cc406Sopenharmony_ci break; 1136141cc406Sopenharmony_ci case SCEPTRE_LINEART: 1137141cc406Sopenharmony_ci case SCEPTRE_HALFTONE: 1138141cc406Sopenharmony_ci { 1139141cc406Sopenharmony_ci /* Invert black and white. */ 1140141cc406Sopenharmony_ci unsigned char *src = dev->buffer; 1141141cc406Sopenharmony_ci unsigned char *dest = dev->image + dev->image_end; 1142141cc406Sopenharmony_ci size_t i; 1143141cc406Sopenharmony_ci for (i = 0; i < size; i++) 1144141cc406Sopenharmony_ci { 1145141cc406Sopenharmony_ci *dest = *src ^ 0xff; 1146141cc406Sopenharmony_ci dest++; 1147141cc406Sopenharmony_ci src++; 1148141cc406Sopenharmony_ci } 1149141cc406Sopenharmony_ci dev->image_end += size; 1150141cc406Sopenharmony_ci } 1151141cc406Sopenharmony_ci break; 1152141cc406Sopenharmony_ci default: 1153141cc406Sopenharmony_ci memcpy (dev->image + dev->image_end, dev->buffer, size); 1154141cc406Sopenharmony_ci dev->image_end += size; 1155141cc406Sopenharmony_ci } 1156141cc406Sopenharmony_ci 1157141cc406Sopenharmony_ci dev->real_bytes_left -= size; 1158141cc406Sopenharmony_ci } 1159141cc406Sopenharmony_ci 1160141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); /* unreachable */ 1161141cc406Sopenharmony_ci} 1162141cc406Sopenharmony_ci 1163141cc406Sopenharmony_ci/* Copy from the raw buffer to the buffer given by the backend. 1164141cc406Sopenharmony_ci * 1165141cc406Sopenharmony_ci * len in input is the maximum length available in buf, and, in 1166141cc406Sopenharmony_ci * output, is the length written into buf. 1167141cc406Sopenharmony_ci */ 1168141cc406Sopenharmony_cistatic void 1169141cc406Sopenharmony_cisceptre_copy_raw_to_frontend (Sceptre_Scanner * dev, SANE_Byte * buf, 1170141cc406Sopenharmony_ci size_t * len) 1171141cc406Sopenharmony_ci{ 1172141cc406Sopenharmony_ci size_t size; 1173141cc406Sopenharmony_ci 1174141cc406Sopenharmony_ci size = dev->image_end - dev->image_begin; 1175141cc406Sopenharmony_ci if (size > *len) 1176141cc406Sopenharmony_ci { 1177141cc406Sopenharmony_ci size = *len; 1178141cc406Sopenharmony_ci } 1179141cc406Sopenharmony_ci *len = size; 1180141cc406Sopenharmony_ci 1181141cc406Sopenharmony_ci memcpy (buf, dev->image + dev->image_begin, size); 1182141cc406Sopenharmony_ci 1183141cc406Sopenharmony_ci dev->image_begin += size; 1184141cc406Sopenharmony_ci} 1185141cc406Sopenharmony_ci 1186141cc406Sopenharmony_ci/* Stop a scan. */ 1187141cc406Sopenharmony_cistatic SANE_Status 1188141cc406Sopenharmony_cido_cancel (Sceptre_Scanner * dev) 1189141cc406Sopenharmony_ci{ 1190141cc406Sopenharmony_ci DBG (DBG_sane_proc, "do_cancel enter\n"); 1191141cc406Sopenharmony_ci 1192141cc406Sopenharmony_ci if (dev->scanning == SANE_TRUE) 1193141cc406Sopenharmony_ci { 1194141cc406Sopenharmony_ci 1195141cc406Sopenharmony_ci /* Reposition the CCD. */ 1196141cc406Sopenharmony_ci dev->x_tl = 0; 1197141cc406Sopenharmony_ci dev->x_tl = 0; 1198141cc406Sopenharmony_ci dev->width = 0; 1199141cc406Sopenharmony_ci dev->length = 0; 1200141cc406Sopenharmony_ci sceptre_set_window (dev); 1201141cc406Sopenharmony_ci sceptre_scan (dev); 1202141cc406Sopenharmony_ci 1203141cc406Sopenharmony_ci sceptre_close (dev); 1204141cc406Sopenharmony_ci } 1205141cc406Sopenharmony_ci 1206141cc406Sopenharmony_ci dev->scanning = SANE_FALSE; 1207141cc406Sopenharmony_ci 1208141cc406Sopenharmony_ci DBG (DBG_sane_proc, "do_cancel exit\n"); 1209141cc406Sopenharmony_ci 1210141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 1211141cc406Sopenharmony_ci} 1212141cc406Sopenharmony_ci 1213141cc406Sopenharmony_ci/* Start a scan. */ 1214141cc406Sopenharmony_cistatic const SANE_Word gamma_init[GAMMA_LENGTH] = { 1215141cc406Sopenharmony_ci 0x00, 0x06, 0x0A, 0x0D, 0x10, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 1216141cc406Sopenharmony_ci 0x21, 0x23, 0x25, 0x27, 1217141cc406Sopenharmony_ci 0x28, 0x2A, 0x2C, 0x2D, 0x2F, 0x30, 0x32, 0x33, 0x35, 0x36, 0x38, 0x39, 1218141cc406Sopenharmony_ci 0x3A, 0x3C, 0x3D, 0x3F, 1219141cc406Sopenharmony_ci 0x40, 0x41, 0x43, 0x44, 0x45, 0x46, 0x48, 0x49, 0x4A, 0x4B, 0x4D, 0x4E, 1220141cc406Sopenharmony_ci 0x4F, 0x50, 0x51, 0x53, 1221141cc406Sopenharmony_ci 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 1222141cc406Sopenharmony_ci 0x61, 0x62, 0x63, 0x64, 1223141cc406Sopenharmony_ci 0x65, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 1224141cc406Sopenharmony_ci 0x72, 0x73, 0x74, 0x75, 1225141cc406Sopenharmony_ci 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7D, 0x7E, 0x7F, 0x80, 1226141cc406Sopenharmony_ci 0x81, 0x82, 0x83, 0x84, 1227141cc406Sopenharmony_ci 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 1228141cc406Sopenharmony_ci 0x90, 0x91, 0x92, 0x92, 1229141cc406Sopenharmony_ci 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 1230141cc406Sopenharmony_ci 0x9E, 0x9F, 0x9F, 0xA0, 1231141cc406Sopenharmony_ci 0xA1, 0xA2, 0xA3, 0xA4, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xA9, 0xAA, 1232141cc406Sopenharmony_ci 0xAB, 0xAC, 0xAD, 0xAD, 1233141cc406Sopenharmony_ci 0xAE, 0xAF, 0xB0, 0xB1, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB5, 0xB6, 0xB7, 1234141cc406Sopenharmony_ci 0xB8, 0xB9, 0xB9, 0xBA, 1235141cc406Sopenharmony_ci 0xBB, 0xBC, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC0, 0xC1, 0xC2, 0xC3, 0xC3, 1236141cc406Sopenharmony_ci 0xC4, 0xC5, 0xC6, 0xC6, 1237141cc406Sopenharmony_ci 0xC7, 0xC8, 0xC9, 0xC9, 0xCA, 0xCB, 0xCC, 0xCC, 0xCD, 0xCE, 0xCF, 0xCF, 1238141cc406Sopenharmony_ci 0xD0, 0xD1, 0xD2, 0xD2, 1239141cc406Sopenharmony_ci 0xD3, 0xD4, 0xD5, 0xD5, 0xD6, 0xD7, 0xD7, 0xD8, 0xD9, 0xDA, 0xDA, 0xDB, 1240141cc406Sopenharmony_ci 0xDC, 0xDC, 0xDD, 0xDE, 1241141cc406Sopenharmony_ci 0xDF, 0xDF, 0xE0, 0xE1, 0xE1, 0xE2, 0xE3, 0xE4, 0xE4, 0xE5, 0xE6, 0xE6, 1242141cc406Sopenharmony_ci 0xE7, 0xE8, 0xE8, 0xE9, 1243141cc406Sopenharmony_ci 0xEA, 0xEB, 0xEB, 0xEC, 0xED, 0xED, 0xEE, 0xEF, 0xEF, 0xF0, 0xF1, 0xF1, 1244141cc406Sopenharmony_ci 0xF2, 0xF3, 0xF4, 0xF4, 1245141cc406Sopenharmony_ci 0xF5, 0xF6, 0xF6, 0xF7, 0xF8, 0xF8, 0xF9, 0xFA, 0xFA, 0xFB, 0xFC, 0xFC, 1246141cc406Sopenharmony_ci 0xFD, 0xFE, 0xFE, 0xFF 1247141cc406Sopenharmony_ci}; 1248141cc406Sopenharmony_ci 1249141cc406Sopenharmony_cistatic SANE_Status 1250141cc406Sopenharmony_cisceptre_send_gamma (Sceptre_Scanner * dev) 1251141cc406Sopenharmony_ci{ 1252141cc406Sopenharmony_ci CDB cdb; 1253141cc406Sopenharmony_ci int i; 1254141cc406Sopenharmony_ci struct 1255141cc406Sopenharmony_ci { 1256141cc406Sopenharmony_ci unsigned char gamma_R[GAMMA_LENGTH]; 1257141cc406Sopenharmony_ci unsigned char gamma_G[GAMMA_LENGTH]; 1258141cc406Sopenharmony_ci unsigned char gamma_B[GAMMA_LENGTH]; 1259141cc406Sopenharmony_ci } 1260141cc406Sopenharmony_ci param; 1261141cc406Sopenharmony_ci size_t size; 1262141cc406Sopenharmony_ci SANE_Status status; 1263141cc406Sopenharmony_ci 1264141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_send_gamma: enter\n"); 1265141cc406Sopenharmony_ci 1266141cc406Sopenharmony_ci size = sizeof (param); 1267141cc406Sopenharmony_ci 1268141cc406Sopenharmony_ci assert (size == 0x300); 1269141cc406Sopenharmony_ci 1270141cc406Sopenharmony_ci MKSCSI_SEND_10 (cdb, 0x03, 0x02, size); 1271141cc406Sopenharmony_ci 1272141cc406Sopenharmony_ci if (dev->val[OPT_CUSTOM_GAMMA].w) 1273141cc406Sopenharmony_ci { 1274141cc406Sopenharmony_ci /* Use the custom gamma. */ 1275141cc406Sopenharmony_ci for (i = 0; i < GAMMA_LENGTH; i++) 1276141cc406Sopenharmony_ci { 1277141cc406Sopenharmony_ci param.gamma_R[i] = dev->gamma_R[i]; 1278141cc406Sopenharmony_ci param.gamma_G[i] = dev->gamma_G[i]; 1279141cc406Sopenharmony_ci param.gamma_B[i] = dev->gamma_B[i]; 1280141cc406Sopenharmony_ci } 1281141cc406Sopenharmony_ci } 1282141cc406Sopenharmony_ci else 1283141cc406Sopenharmony_ci { 1284141cc406Sopenharmony_ci for (i = 0; i < GAMMA_LENGTH; i++) 1285141cc406Sopenharmony_ci { 1286141cc406Sopenharmony_ci param.gamma_R[i] = gamma_init[i]; 1287141cc406Sopenharmony_ci param.gamma_G[i] = gamma_init[i]; 1288141cc406Sopenharmony_ci param.gamma_B[i] = gamma_init[i]; 1289141cc406Sopenharmony_ci } 1290141cc406Sopenharmony_ci } 1291141cc406Sopenharmony_ci 1292141cc406Sopenharmony_ci hexdump (DBG_info2, "gamma", param.gamma_R, 3 * GAMMA_LENGTH); 1293141cc406Sopenharmony_ci 1294141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 1295141cc406Sopenharmony_ci ¶m, sizeof (param), NULL, NULL); 1296141cc406Sopenharmony_ci 1297141cc406Sopenharmony_ci DBG (DBG_proc, "sceptre_send_gamma: exit, status=%d\n", status); 1298141cc406Sopenharmony_ci 1299141cc406Sopenharmony_ci return (status); 1300141cc406Sopenharmony_ci} 1301141cc406Sopenharmony_ci 1302141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 1303141cc406Sopenharmony_ci 1304141cc406Sopenharmony_ci/* Entry points */ 1305141cc406Sopenharmony_ci 1306141cc406Sopenharmony_ciSANE_Status 1307141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) 1308141cc406Sopenharmony_ci{ 1309141cc406Sopenharmony_ci FILE *fp; 1310141cc406Sopenharmony_ci char dev_name[PATH_MAX]; 1311141cc406Sopenharmony_ci size_t len; 1312141cc406Sopenharmony_ci 1313141cc406Sopenharmony_ci DBG_INIT (); 1314141cc406Sopenharmony_ci 1315141cc406Sopenharmony_ci DBG (DBG_proc, "sane_init: enter\n"); 1316141cc406Sopenharmony_ci 1317141cc406Sopenharmony_ci DBG (DBG_error, "This is sane-sceptre version %d.%d-%d\n", SANE_CURRENT_MAJOR, 1318141cc406Sopenharmony_ci SANE_CURRENT_MINOR, BUILD); 1319141cc406Sopenharmony_ci DBG (DBG_error, "(C) 2002 by Frank Zago\n"); 1320141cc406Sopenharmony_ci 1321141cc406Sopenharmony_ci if (version_code) 1322141cc406Sopenharmony_ci { 1323141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 1324141cc406Sopenharmony_ci } 1325141cc406Sopenharmony_ci 1326141cc406Sopenharmony_ci fp = sanei_config_open (SCEPTRE_CONFIG_FILE); 1327141cc406Sopenharmony_ci if (!fp) 1328141cc406Sopenharmony_ci { 1329141cc406Sopenharmony_ci /* default to /dev/scanner instead of insisting on config file */ 1330141cc406Sopenharmony_ci attach_scanner ("/dev/scanner", 0); 1331141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1332141cc406Sopenharmony_ci } 1333141cc406Sopenharmony_ci 1334141cc406Sopenharmony_ci while (sanei_config_read (dev_name, sizeof (dev_name), fp)) 1335141cc406Sopenharmony_ci { 1336141cc406Sopenharmony_ci if (dev_name[0] == '#') /* ignore line comments */ 1337141cc406Sopenharmony_ci continue; 1338141cc406Sopenharmony_ci len = strlen (dev_name); 1339141cc406Sopenharmony_ci 1340141cc406Sopenharmony_ci if (!len) 1341141cc406Sopenharmony_ci continue; /* ignore empty lines */ 1342141cc406Sopenharmony_ci 1343141cc406Sopenharmony_ci sanei_config_attach_matching_devices (dev_name, attach_one); 1344141cc406Sopenharmony_ci } 1345141cc406Sopenharmony_ci 1346141cc406Sopenharmony_ci fclose (fp); 1347141cc406Sopenharmony_ci 1348141cc406Sopenharmony_ci DBG (DBG_proc, "sane_init: leave\n"); 1349141cc406Sopenharmony_ci 1350141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1351141cc406Sopenharmony_ci} 1352141cc406Sopenharmony_ci 1353141cc406Sopenharmony_ciSANE_Status 1354141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) 1355141cc406Sopenharmony_ci{ 1356141cc406Sopenharmony_ci Sceptre_Scanner *dev; 1357141cc406Sopenharmony_ci int i; 1358141cc406Sopenharmony_ci 1359141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_devices: enter\n"); 1360141cc406Sopenharmony_ci 1361141cc406Sopenharmony_ci if (devlist) 1362141cc406Sopenharmony_ci free (devlist); 1363141cc406Sopenharmony_ci 1364141cc406Sopenharmony_ci devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); 1365141cc406Sopenharmony_ci if (!devlist) 1366141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1367141cc406Sopenharmony_ci 1368141cc406Sopenharmony_ci i = 0; 1369141cc406Sopenharmony_ci for (dev = first_dev; i < num_devices; dev = dev->next) 1370141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 1371141cc406Sopenharmony_ci devlist[i++] = 0; 1372141cc406Sopenharmony_ci 1373141cc406Sopenharmony_ci *device_list = devlist; 1374141cc406Sopenharmony_ci 1375141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_devices: exit\n"); 1376141cc406Sopenharmony_ci 1377141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1378141cc406Sopenharmony_ci} 1379141cc406Sopenharmony_ci 1380141cc406Sopenharmony_ciSANE_Status 1381141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 1382141cc406Sopenharmony_ci{ 1383141cc406Sopenharmony_ci Sceptre_Scanner *dev; 1384141cc406Sopenharmony_ci SANE_Status status; 1385141cc406Sopenharmony_ci 1386141cc406Sopenharmony_ci DBG (DBG_proc, "sane_open: enter\n"); 1387141cc406Sopenharmony_ci 1388141cc406Sopenharmony_ci /* search for devicename */ 1389141cc406Sopenharmony_ci if (devicename[0]) 1390141cc406Sopenharmony_ci { 1391141cc406Sopenharmony_ci DBG (DBG_info, "sane_open: devicename=%s\n", devicename); 1392141cc406Sopenharmony_ci 1393141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 1394141cc406Sopenharmony_ci { 1395141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) 1396141cc406Sopenharmony_ci { 1397141cc406Sopenharmony_ci break; 1398141cc406Sopenharmony_ci } 1399141cc406Sopenharmony_ci } 1400141cc406Sopenharmony_ci 1401141cc406Sopenharmony_ci if (!dev) 1402141cc406Sopenharmony_ci { 1403141cc406Sopenharmony_ci status = attach_scanner (devicename, &dev); 1404141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1405141cc406Sopenharmony_ci { 1406141cc406Sopenharmony_ci return status; 1407141cc406Sopenharmony_ci } 1408141cc406Sopenharmony_ci } 1409141cc406Sopenharmony_ci } 1410141cc406Sopenharmony_ci else 1411141cc406Sopenharmony_ci { 1412141cc406Sopenharmony_ci DBG (DBG_sane_info, "sane_open: no devicename, opening first device\n"); 1413141cc406Sopenharmony_ci dev = first_dev; /* empty devicename -> use first device */ 1414141cc406Sopenharmony_ci } 1415141cc406Sopenharmony_ci 1416141cc406Sopenharmony_ci if (!dev) 1417141cc406Sopenharmony_ci { 1418141cc406Sopenharmony_ci DBG (DBG_error, "No scanner found\n"); 1419141cc406Sopenharmony_ci 1420141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1421141cc406Sopenharmony_ci } 1422141cc406Sopenharmony_ci 1423141cc406Sopenharmony_ci sceptre_init_options (dev); 1424141cc406Sopenharmony_ci 1425141cc406Sopenharmony_ci /* Initialize the gamma table. */ 1426141cc406Sopenharmony_ci memcpy (dev->gamma_R, gamma_init, dev->opt[OPT_GAMMA_VECTOR_R].size); 1427141cc406Sopenharmony_ci memcpy (dev->gamma_G, gamma_init, dev->opt[OPT_GAMMA_VECTOR_G].size); 1428141cc406Sopenharmony_ci memcpy (dev->gamma_B, gamma_init, dev->opt[OPT_GAMMA_VECTOR_B].size); 1429141cc406Sopenharmony_ci 1430141cc406Sopenharmony_ci *handle = dev; 1431141cc406Sopenharmony_ci 1432141cc406Sopenharmony_ci DBG (DBG_proc, "sane_open: exit\n"); 1433141cc406Sopenharmony_ci 1434141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1435141cc406Sopenharmony_ci} 1436141cc406Sopenharmony_ci 1437141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 1438141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 1439141cc406Sopenharmony_ci{ 1440141cc406Sopenharmony_ci Sceptre_Scanner *dev = handle; 1441141cc406Sopenharmony_ci 1442141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_option_descriptor: enter, option %d\n", option); 1443141cc406Sopenharmony_ci 1444141cc406Sopenharmony_ci if ((unsigned) option >= OPT_NUM_OPTIONS) 1445141cc406Sopenharmony_ci { 1446141cc406Sopenharmony_ci return NULL; 1447141cc406Sopenharmony_ci } 1448141cc406Sopenharmony_ci 1449141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_option_descriptor: exit\n"); 1450141cc406Sopenharmony_ci 1451141cc406Sopenharmony_ci return dev->opt + option; 1452141cc406Sopenharmony_ci} 1453141cc406Sopenharmony_ci 1454141cc406Sopenharmony_ciSANE_Status 1455141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 1456141cc406Sopenharmony_ci SANE_Action action, void *val, SANE_Int * info) 1457141cc406Sopenharmony_ci{ 1458141cc406Sopenharmony_ci Sceptre_Scanner *dev = handle; 1459141cc406Sopenharmony_ci SANE_Status status; 1460141cc406Sopenharmony_ci SANE_Word cap; 1461141cc406Sopenharmony_ci 1462141cc406Sopenharmony_ci DBG (DBG_proc, "sane_control_option: enter, option %d, action %d\n", 1463141cc406Sopenharmony_ci option, action); 1464141cc406Sopenharmony_ci 1465141cc406Sopenharmony_ci if (info) 1466141cc406Sopenharmony_ci { 1467141cc406Sopenharmony_ci *info = 0; 1468141cc406Sopenharmony_ci } 1469141cc406Sopenharmony_ci 1470141cc406Sopenharmony_ci if (dev->scanning) 1471141cc406Sopenharmony_ci { 1472141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1473141cc406Sopenharmony_ci } 1474141cc406Sopenharmony_ci 1475141cc406Sopenharmony_ci if (option < 0 || option >= OPT_NUM_OPTIONS) 1476141cc406Sopenharmony_ci { 1477141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1478141cc406Sopenharmony_ci } 1479141cc406Sopenharmony_ci 1480141cc406Sopenharmony_ci cap = dev->opt[option].cap; 1481141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (cap)) 1482141cc406Sopenharmony_ci { 1483141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1484141cc406Sopenharmony_ci } 1485141cc406Sopenharmony_ci 1486141cc406Sopenharmony_ci if (action == SANE_ACTION_GET_VALUE) 1487141cc406Sopenharmony_ci { 1488141cc406Sopenharmony_ci 1489141cc406Sopenharmony_ci switch (option) 1490141cc406Sopenharmony_ci { 1491141cc406Sopenharmony_ci /* word options */ 1492141cc406Sopenharmony_ci case OPT_NUM_OPTS: 1493141cc406Sopenharmony_ci case OPT_RESOLUTION: 1494141cc406Sopenharmony_ci case OPT_TL_X: 1495141cc406Sopenharmony_ci case OPT_TL_Y: 1496141cc406Sopenharmony_ci case OPT_BR_X: 1497141cc406Sopenharmony_ci case OPT_BR_Y: 1498141cc406Sopenharmony_ci case OPT_THRESHOLD: 1499141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 1500141cc406Sopenharmony_ci case OPT_HALFTONE_PATTERN: 1501141cc406Sopenharmony_ci case OPT_PREVIEW: 1502141cc406Sopenharmony_ci 1503141cc406Sopenharmony_ci *(SANE_Word *) val = dev->val[option].w; 1504141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1505141cc406Sopenharmony_ci 1506141cc406Sopenharmony_ci /* string options */ 1507141cc406Sopenharmony_ci case OPT_MODE: 1508141cc406Sopenharmony_ci strcpy (val, dev->val[option].s); 1509141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1510141cc406Sopenharmony_ci 1511141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 1512141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 1513141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 1514141cc406Sopenharmony_ci memcpy (val, dev->val[option].wa, dev->opt[option].size); 1515141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1516141cc406Sopenharmony_ci 1517141cc406Sopenharmony_ci default: 1518141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1519141cc406Sopenharmony_ci } 1520141cc406Sopenharmony_ci } 1521141cc406Sopenharmony_ci else if (action == SANE_ACTION_SET_VALUE) 1522141cc406Sopenharmony_ci { 1523141cc406Sopenharmony_ci 1524141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (cap)) 1525141cc406Sopenharmony_ci { 1526141cc406Sopenharmony_ci DBG (DBG_error, "could not set option, not settable\n"); 1527141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1528141cc406Sopenharmony_ci } 1529141cc406Sopenharmony_ci 1530141cc406Sopenharmony_ci status = sanei_constrain_value (dev->opt + option, val, info); 1531141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1532141cc406Sopenharmony_ci { 1533141cc406Sopenharmony_ci DBG (DBG_error, "could not set option, invalid value\n"); 1534141cc406Sopenharmony_ci return status; 1535141cc406Sopenharmony_ci } 1536141cc406Sopenharmony_ci 1537141cc406Sopenharmony_ci switch (option) 1538141cc406Sopenharmony_ci { 1539141cc406Sopenharmony_ci 1540141cc406Sopenharmony_ci /* Side-effect options */ 1541141cc406Sopenharmony_ci case OPT_TL_X: 1542141cc406Sopenharmony_ci case OPT_TL_Y: 1543141cc406Sopenharmony_ci case OPT_BR_X: 1544141cc406Sopenharmony_ci case OPT_BR_Y: 1545141cc406Sopenharmony_ci case OPT_RESOLUTION: 1546141cc406Sopenharmony_ci if (info) 1547141cc406Sopenharmony_ci { 1548141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 1549141cc406Sopenharmony_ci } 1550141cc406Sopenharmony_ci dev->val[option].w = *(SANE_Word *) val; 1551141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1552141cc406Sopenharmony_ci 1553141cc406Sopenharmony_ci /* Side-effect free options */ 1554141cc406Sopenharmony_ci case OPT_THRESHOLD: 1555141cc406Sopenharmony_ci case OPT_HALFTONE_PATTERN: 1556141cc406Sopenharmony_ci case OPT_PREVIEW: 1557141cc406Sopenharmony_ci dev->val[option].w = *(SANE_Word *) val; 1558141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1559141cc406Sopenharmony_ci 1560141cc406Sopenharmony_ci case OPT_MODE: 1561141cc406Sopenharmony_ci free (dev->val[OPT_MODE].s); 1562141cc406Sopenharmony_ci dev->val[OPT_MODE].s = (SANE_Char *) strdup (val); 1563141cc406Sopenharmony_ci 1564141cc406Sopenharmony_ci /* Set default options for the scan modes. */ 1565141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 1566141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; 1567141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1568141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1569141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1570141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; 1571141cc406Sopenharmony_ci 1572141cc406Sopenharmony_ci if (strcmp (dev->val[OPT_MODE].s, LINEART_STR) == 0) 1573141cc406Sopenharmony_ci { 1574141cc406Sopenharmony_ci dev->scan_mode = SCEPTRE_LINEART; 1575141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; 1576141cc406Sopenharmony_ci } 1577141cc406Sopenharmony_ci else if (strcmp (dev->val[OPT_MODE].s, HALFTONE_STR) == 0) 1578141cc406Sopenharmony_ci { 1579141cc406Sopenharmony_ci dev->scan_mode = SCEPTRE_HALFTONE; 1580141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; 1581141cc406Sopenharmony_ci } 1582141cc406Sopenharmony_ci else if (strcmp (dev->val[OPT_MODE].s, GRAY_STR) == 0) 1583141cc406Sopenharmony_ci { 1584141cc406Sopenharmony_ci dev->scan_mode = SCEPTRE_GRAYSCALE; 1585141cc406Sopenharmony_ci } 1586141cc406Sopenharmony_ci else if (strcmp (dev->val[OPT_MODE].s, COLOR_STR) == 0) 1587141cc406Sopenharmony_ci { 1588141cc406Sopenharmony_ci dev->scan_mode = SCEPTRE_COLOR; 1589141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; 1590141cc406Sopenharmony_ci if (dev->val[OPT_CUSTOM_GAMMA].w) 1591141cc406Sopenharmony_ci { 1592141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; 1593141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; 1594141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; 1595141cc406Sopenharmony_ci } 1596141cc406Sopenharmony_ci } 1597141cc406Sopenharmony_ci 1598141cc406Sopenharmony_ci if (info) 1599141cc406Sopenharmony_ci { 1600141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 1601141cc406Sopenharmony_ci } 1602141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1603141cc406Sopenharmony_ci 1604141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 1605141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 1606141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 1607141cc406Sopenharmony_ci memcpy (dev->val[option].wa, val, dev->opt[option].size); 1608141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1609141cc406Sopenharmony_ci 1610141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 1611141cc406Sopenharmony_ci dev->val[OPT_CUSTOM_GAMMA].w = *(SANE_Word *) val; 1612141cc406Sopenharmony_ci if (dev->val[OPT_CUSTOM_GAMMA].w) 1613141cc406Sopenharmony_ci { 1614141cc406Sopenharmony_ci /* use custom_gamma_table */ 1615141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; 1616141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; 1617141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; 1618141cc406Sopenharmony_ci } 1619141cc406Sopenharmony_ci else 1620141cc406Sopenharmony_ci { 1621141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1622141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1623141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1624141cc406Sopenharmony_ci } 1625141cc406Sopenharmony_ci if (info) 1626141cc406Sopenharmony_ci { 1627141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 1628141cc406Sopenharmony_ci } 1629141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1630141cc406Sopenharmony_ci 1631141cc406Sopenharmony_ci default: 1632141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1633141cc406Sopenharmony_ci } 1634141cc406Sopenharmony_ci } 1635141cc406Sopenharmony_ci 1636141cc406Sopenharmony_ci DBG (DBG_proc, "sane_control_option: exit, bad\n"); 1637141cc406Sopenharmony_ci 1638141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1639141cc406Sopenharmony_ci} 1640141cc406Sopenharmony_ci 1641141cc406Sopenharmony_ciSANE_Status 1642141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 1643141cc406Sopenharmony_ci{ 1644141cc406Sopenharmony_ci Sceptre_Scanner *dev = handle; 1645141cc406Sopenharmony_ci int x_dpi; /* X-Resolution */ 1646141cc406Sopenharmony_ci 1647141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_parameters: enter\n"); 1648141cc406Sopenharmony_ci 1649141cc406Sopenharmony_ci if (!(dev->scanning)) 1650141cc406Sopenharmony_ci { 1651141cc406Sopenharmony_ci /* Prepare the parameters for the caller. */ 1652141cc406Sopenharmony_ci memset (&dev->params, 0, sizeof (SANE_Parameters)); 1653141cc406Sopenharmony_ci 1654141cc406Sopenharmony_ci if (dev->val[OPT_PREVIEW].w == SANE_TRUE) 1655141cc406Sopenharmony_ci { 1656141cc406Sopenharmony_ci dev->resolution = 30; /* Windows TWAIN does 32 */ 1657141cc406Sopenharmony_ci dev->x_tl = 0; 1658141cc406Sopenharmony_ci dev->y_tl = 0; 1659141cc406Sopenharmony_ci dev->x_br = mmToIlu (SANE_UNFIX (dev->x_range.max)); 1660141cc406Sopenharmony_ci dev->y_br = mmToIlu (SANE_UNFIX (dev->y_range.max)); 1661141cc406Sopenharmony_ci } 1662141cc406Sopenharmony_ci else 1663141cc406Sopenharmony_ci { 1664141cc406Sopenharmony_ci /* Setup the parameters for the scan. These values will be re-used 1665141cc406Sopenharmony_ci * in the SET WINDOWS command. */ 1666141cc406Sopenharmony_ci dev->resolution = dev->val[OPT_RESOLUTION].w; 1667141cc406Sopenharmony_ci 1668141cc406Sopenharmony_ci dev->x_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w)); 1669141cc406Sopenharmony_ci dev->y_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_Y].w)); 1670141cc406Sopenharmony_ci dev->x_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w)); 1671141cc406Sopenharmony_ci dev->y_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_Y].w)); 1672141cc406Sopenharmony_ci } 1673141cc406Sopenharmony_ci 1674141cc406Sopenharmony_ci /* Check the corners are OK. */ 1675141cc406Sopenharmony_ci if (dev->x_tl > dev->x_br) 1676141cc406Sopenharmony_ci { 1677141cc406Sopenharmony_ci int s; 1678141cc406Sopenharmony_ci s = dev->x_tl; 1679141cc406Sopenharmony_ci dev->x_tl = dev->x_br; 1680141cc406Sopenharmony_ci dev->x_br = s; 1681141cc406Sopenharmony_ci } 1682141cc406Sopenharmony_ci if (dev->y_tl > dev->y_br) 1683141cc406Sopenharmony_ci { 1684141cc406Sopenharmony_ci int s; 1685141cc406Sopenharmony_ci s = dev->y_tl; 1686141cc406Sopenharmony_ci dev->y_tl = dev->y_br; 1687141cc406Sopenharmony_ci dev->y_br = s; 1688141cc406Sopenharmony_ci } 1689141cc406Sopenharmony_ci 1690141cc406Sopenharmony_ci dev->width = dev->x_br - dev->x_tl; 1691141cc406Sopenharmony_ci dev->length = dev->y_br - dev->y_tl; 1692141cc406Sopenharmony_ci 1693141cc406Sopenharmony_ci /* 1694141cc406Sopenharmony_ci * Adjust the "X Resolution". The sceptre S1200 ignores the 1695141cc406Sopenharmony_ci * Y-Resolution parameter in the windows block. X-Resolution 1696141cc406Sopenharmony_ci * is used instead. However the limits are not the same for X 1697141cc406Sopenharmony_ci * (600 dpi) and Y (1200 dpi). 1698141cc406Sopenharmony_ci */ 1699141cc406Sopenharmony_ci x_dpi = dev->resolution; 1700141cc406Sopenharmony_ci if (x_dpi > 600) 1701141cc406Sopenharmony_ci { 1702141cc406Sopenharmony_ci x_dpi = 600; 1703141cc406Sopenharmony_ci } 1704141cc406Sopenharmony_ci 1705141cc406Sopenharmony_ci /* Set depth */ 1706141cc406Sopenharmony_ci switch (dev->scan_mode) 1707141cc406Sopenharmony_ci { 1708141cc406Sopenharmony_ci case SCEPTRE_LINEART: 1709141cc406Sopenharmony_ci dev->params.format = SANE_FRAME_GRAY; 1710141cc406Sopenharmony_ci dev->depth = 1; 1711141cc406Sopenharmony_ci break; 1712141cc406Sopenharmony_ci case SCEPTRE_HALFTONE: 1713141cc406Sopenharmony_ci dev->params.format = SANE_FRAME_GRAY; 1714141cc406Sopenharmony_ci dev->depth = 1; 1715141cc406Sopenharmony_ci break; 1716141cc406Sopenharmony_ci case SCEPTRE_GRAYSCALE: 1717141cc406Sopenharmony_ci dev->params.format = SANE_FRAME_GRAY; 1718141cc406Sopenharmony_ci dev->depth = 8; 1719141cc406Sopenharmony_ci break; 1720141cc406Sopenharmony_ci case SCEPTRE_COLOR: 1721141cc406Sopenharmony_ci dev->params.format = SANE_FRAME_RGB; 1722141cc406Sopenharmony_ci dev->depth = 8; 1723141cc406Sopenharmony_ci break; 1724141cc406Sopenharmony_ci } 1725141cc406Sopenharmony_ci 1726141cc406Sopenharmony_ci /* this scanner does only one pass */ 1727141cc406Sopenharmony_ci dev->params.last_frame = SANE_TRUE; 1728141cc406Sopenharmony_ci dev->params.depth = dev->depth; 1729141cc406Sopenharmony_ci 1730141cc406Sopenharmony_ci /* Compute the number of pixels, bytes per lines and lines. */ 1731141cc406Sopenharmony_ci switch (dev->scan_mode) 1732141cc406Sopenharmony_ci { 1733141cc406Sopenharmony_ci case SCEPTRE_LINEART: 1734141cc406Sopenharmony_ci case SCEPTRE_HALFTONE: 1735141cc406Sopenharmony_ci dev->params.pixels_per_line = (dev->width * x_dpi) / 600; 1736141cc406Sopenharmony_ci dev->params.pixels_per_line &= ~0x7; /* round down to 8 */ 1737141cc406Sopenharmony_ci 1738141cc406Sopenharmony_ci dev->params.bytes_per_line = (dev->params.pixels_per_line) / 8; 1739141cc406Sopenharmony_ci 1740141cc406Sopenharmony_ci dev->params.lines = ((dev->length * dev->resolution) / 600); 1741141cc406Sopenharmony_ci if ((dev->params.lines) * 600 != (dev->length * dev->resolution)) 1742141cc406Sopenharmony_ci { 1743141cc406Sopenharmony_ci /* Round up lines to 2. */ 1744141cc406Sopenharmony_ci dev->params.lines &= ~1; 1745141cc406Sopenharmony_ci dev->params.lines += 2; 1746141cc406Sopenharmony_ci } 1747141cc406Sopenharmony_ci 1748141cc406Sopenharmony_ci break; 1749141cc406Sopenharmony_ci 1750141cc406Sopenharmony_ci case SCEPTRE_GRAYSCALE: 1751141cc406Sopenharmony_ci case SCEPTRE_COLOR: 1752141cc406Sopenharmony_ci /* pixels_per_line rounding rules: 1753141cc406Sopenharmony_ci * 2n + [0.0 .. 1.0] -> round to 2n 1754141cc406Sopenharmony_ci * 2n + ]1.0 .. 2.0] -> round to 2n + 2 1755141cc406Sopenharmony_ci */ 1756141cc406Sopenharmony_ci dev->params.pixels_per_line = (dev->width * x_dpi) / 600; 1757141cc406Sopenharmony_ci if (dev->params.pixels_per_line & 1) 1758141cc406Sopenharmony_ci { 1759141cc406Sopenharmony_ci if ((dev->params.pixels_per_line * 600) == (dev->width * x_dpi)) 1760141cc406Sopenharmony_ci { 1761141cc406Sopenharmony_ci /* 2n */ 1762141cc406Sopenharmony_ci dev->params.pixels_per_line--; 1763141cc406Sopenharmony_ci } 1764141cc406Sopenharmony_ci else 1765141cc406Sopenharmony_ci { 1766141cc406Sopenharmony_ci /* 2n+2 */ 1767141cc406Sopenharmony_ci dev->params.pixels_per_line++; 1768141cc406Sopenharmony_ci } 1769141cc406Sopenharmony_ci } 1770141cc406Sopenharmony_ci 1771141cc406Sopenharmony_ci dev->params.bytes_per_line = dev->params.pixels_per_line; 1772141cc406Sopenharmony_ci if (dev->scan_mode == SCEPTRE_COLOR) 1773141cc406Sopenharmony_ci dev->params.bytes_per_line *= 3; 1774141cc406Sopenharmony_ci 1775141cc406Sopenharmony_ci /* lines number rounding rules: 1776141cc406Sopenharmony_ci * 2n + [0.0 .. 2.0[ -> round to 2n 1777141cc406Sopenharmony_ci * 1778141cc406Sopenharmony_ci * Note: the rounding is often incorrect at high 1779141cc406Sopenharmony_ci * resolution (ag more than 300dpi) 1780141cc406Sopenharmony_ci */ 1781141cc406Sopenharmony_ci dev->params.lines = (dev->length * dev->resolution) / 600; 1782141cc406Sopenharmony_ci dev->params.lines &= ~1; 1783141cc406Sopenharmony_ci 1784141cc406Sopenharmony_ci break; 1785141cc406Sopenharmony_ci } 1786141cc406Sopenharmony_ci 1787141cc406Sopenharmony_ci /* Find the proper color shifting parameter. */ 1788141cc406Sopenharmony_ci if (dev->scan_mode == SCEPTRE_COLOR) 1789141cc406Sopenharmony_ci { 1790141cc406Sopenharmony_ci int i = 1; 1791141cc406Sopenharmony_ci while (resolutions_list[i] != dev->resolution) 1792141cc406Sopenharmony_ci { 1793141cc406Sopenharmony_ci i++; 1794141cc406Sopenharmony_ci } 1795141cc406Sopenharmony_ci dev->color_shift = color_shift_list[i]; 1796141cc406Sopenharmony_ci } 1797141cc406Sopenharmony_ci else 1798141cc406Sopenharmony_ci { 1799141cc406Sopenharmony_ci dev->color_shift = 0; 1800141cc406Sopenharmony_ci } 1801141cc406Sopenharmony_ci 1802141cc406Sopenharmony_ci DBG (DBG_proc, "color_shift = %d\n", dev->color_shift); 1803141cc406Sopenharmony_ci 1804141cc406Sopenharmony_ci dev->bytes_left = dev->params.lines * dev->params.bytes_per_line; 1805141cc406Sopenharmony_ci } 1806141cc406Sopenharmony_ci 1807141cc406Sopenharmony_ci /* Return the current values. */ 1808141cc406Sopenharmony_ci if (params) 1809141cc406Sopenharmony_ci { 1810141cc406Sopenharmony_ci *params = (dev->params); 1811141cc406Sopenharmony_ci } 1812141cc406Sopenharmony_ci 1813141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_parameters: exit\n"); 1814141cc406Sopenharmony_ci 1815141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1816141cc406Sopenharmony_ci} 1817141cc406Sopenharmony_ci 1818141cc406Sopenharmony_ciSANE_Status 1819141cc406Sopenharmony_cisane_start (SANE_Handle handle) 1820141cc406Sopenharmony_ci{ 1821141cc406Sopenharmony_ci Sceptre_Scanner *dev = handle; 1822141cc406Sopenharmony_ci SANE_Status status; 1823141cc406Sopenharmony_ci 1824141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: enter\n"); 1825141cc406Sopenharmony_ci 1826141cc406Sopenharmony_ci if (!(dev->scanning)) 1827141cc406Sopenharmony_ci { 1828141cc406Sopenharmony_ci 1829141cc406Sopenharmony_ci sane_get_parameters (dev, NULL); 1830141cc406Sopenharmony_ci 1831141cc406Sopenharmony_ci if (dev->image) 1832141cc406Sopenharmony_ci { 1833141cc406Sopenharmony_ci free (dev->image); 1834141cc406Sopenharmony_ci } 1835141cc406Sopenharmony_ci /* Compute the length necessary in image. The first part will store 1836141cc406Sopenharmony_ci * the complete lines, and the rest is used to stored ahead 1837141cc406Sopenharmony_ci * rasters. 1838141cc406Sopenharmony_ci */ 1839141cc406Sopenharmony_ci dev->raster_ahead = 1840141cc406Sopenharmony_ci (2 * dev->color_shift + 1) * dev->params.bytes_per_line; 1841141cc406Sopenharmony_ci dev->image_size = dev->buffer_size + dev->raster_ahead; 1842141cc406Sopenharmony_ci dev->image = malloc (dev->image_size); 1843141cc406Sopenharmony_ci if (dev->image == NULL) 1844141cc406Sopenharmony_ci { 1845141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1846141cc406Sopenharmony_ci } 1847141cc406Sopenharmony_ci dev->image_begin = 0; 1848141cc406Sopenharmony_ci dev->image_end = 0; 1849141cc406Sopenharmony_ci 1850141cc406Sopenharmony_ci dev->raster_size = dev->params.bytes_per_line / 3; 1851141cc406Sopenharmony_ci dev->raster_num = 0; 1852141cc406Sopenharmony_ci dev->raster_real = 0; 1853141cc406Sopenharmony_ci dev->line = 0; 1854141cc406Sopenharmony_ci 1855141cc406Sopenharmony_ci /* Open again the scanner. */ 1856141cc406Sopenharmony_ci if (sanei_scsi_open 1857141cc406Sopenharmony_ci (dev->devicename, &(dev->sfd), sceptre_sense_handler, dev) != 0) 1858141cc406Sopenharmony_ci { 1859141cc406Sopenharmony_ci DBG (DBG_error, "ERROR: sane_start: open failed\n"); 1860141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1861141cc406Sopenharmony_ci } 1862141cc406Sopenharmony_ci 1863141cc406Sopenharmony_ci /* The scanner must be ready. */ 1864141cc406Sopenharmony_ci status = sceptre_wait_scanner (dev); 1865141cc406Sopenharmony_ci if (status) 1866141cc406Sopenharmony_ci { 1867141cc406Sopenharmony_ci sceptre_close (dev); 1868141cc406Sopenharmony_ci return status; 1869141cc406Sopenharmony_ci } 1870141cc406Sopenharmony_ci 1871141cc406Sopenharmony_ci status = sceptre_do_diag (dev); 1872141cc406Sopenharmony_ci if (status) 1873141cc406Sopenharmony_ci { 1874141cc406Sopenharmony_ci sceptre_close (dev); 1875141cc406Sopenharmony_ci return status; 1876141cc406Sopenharmony_ci } 1877141cc406Sopenharmony_ci 1878141cc406Sopenharmony_ci status = sceptre_set_mode (dev); 1879141cc406Sopenharmony_ci if (status) 1880141cc406Sopenharmony_ci { 1881141cc406Sopenharmony_ci sceptre_close (dev); 1882141cc406Sopenharmony_ci return status; 1883141cc406Sopenharmony_ci } 1884141cc406Sopenharmony_ci 1885141cc406Sopenharmony_ci status = sceptre_set_window (dev); 1886141cc406Sopenharmony_ci if (status) 1887141cc406Sopenharmony_ci { 1888141cc406Sopenharmony_ci sceptre_close (dev); 1889141cc406Sopenharmony_ci return status; 1890141cc406Sopenharmony_ci } 1891141cc406Sopenharmony_ci 1892141cc406Sopenharmony_ci status = sceptre_send_gamma (dev); 1893141cc406Sopenharmony_ci if (status) 1894141cc406Sopenharmony_ci { 1895141cc406Sopenharmony_ci sceptre_close (dev); 1896141cc406Sopenharmony_ci return status; 1897141cc406Sopenharmony_ci } 1898141cc406Sopenharmony_ci 1899141cc406Sopenharmony_ci status = sceptre_scan (dev); 1900141cc406Sopenharmony_ci if (status) 1901141cc406Sopenharmony_ci { 1902141cc406Sopenharmony_ci sceptre_close (dev); 1903141cc406Sopenharmony_ci return status; 1904141cc406Sopenharmony_ci } 1905141cc406Sopenharmony_ci 1906141cc406Sopenharmony_ci status = sceptre_get_status (dev, &dev->real_bytes_left); 1907141cc406Sopenharmony_ci if (status) 1908141cc406Sopenharmony_ci { 1909141cc406Sopenharmony_ci sceptre_close (dev); 1910141cc406Sopenharmony_ci return status; 1911141cc406Sopenharmony_ci } 1912141cc406Sopenharmony_ci 1913141cc406Sopenharmony_ci } 1914141cc406Sopenharmony_ci 1915141cc406Sopenharmony_ci dev->bytes_left = dev->params.bytes_per_line * dev->params.lines; 1916141cc406Sopenharmony_ci 1917141cc406Sopenharmony_ci dev->scanning = SANE_TRUE; 1918141cc406Sopenharmony_ci 1919141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: exit\n"); 1920141cc406Sopenharmony_ci 1921141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1922141cc406Sopenharmony_ci} 1923141cc406Sopenharmony_ci 1924141cc406Sopenharmony_ciSANE_Status 1925141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, 1926141cc406Sopenharmony_ci SANE_Int * len) 1927141cc406Sopenharmony_ci{ 1928141cc406Sopenharmony_ci SANE_Status status; 1929141cc406Sopenharmony_ci Sceptre_Scanner *dev = handle; 1930141cc406Sopenharmony_ci size_t size; 1931141cc406Sopenharmony_ci int buf_offset; /* offset into buf */ 1932141cc406Sopenharmony_ci 1933141cc406Sopenharmony_ci DBG (DBG_proc, "sane_read: enter\n"); 1934141cc406Sopenharmony_ci 1935141cc406Sopenharmony_ci *len = 0; 1936141cc406Sopenharmony_ci 1937141cc406Sopenharmony_ci if (!(dev->scanning)) 1938141cc406Sopenharmony_ci { 1939141cc406Sopenharmony_ci /* OOPS, not scanning */ 1940141cc406Sopenharmony_ci return do_cancel (dev); 1941141cc406Sopenharmony_ci } 1942141cc406Sopenharmony_ci 1943141cc406Sopenharmony_ci if (dev->bytes_left <= 0) 1944141cc406Sopenharmony_ci { 1945141cc406Sopenharmony_ci return (SANE_STATUS_EOF); 1946141cc406Sopenharmony_ci } 1947141cc406Sopenharmony_ci 1948141cc406Sopenharmony_ci buf_offset = 0; 1949141cc406Sopenharmony_ci 1950141cc406Sopenharmony_ci do 1951141cc406Sopenharmony_ci { 1952141cc406Sopenharmony_ci if (dev->image_begin == dev->image_end) 1953141cc406Sopenharmony_ci { 1954141cc406Sopenharmony_ci /* Fill image */ 1955141cc406Sopenharmony_ci status = sceptre_fill_image (dev); 1956141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1957141cc406Sopenharmony_ci { 1958141cc406Sopenharmony_ci return (status); 1959141cc406Sopenharmony_ci } 1960141cc406Sopenharmony_ci } 1961141cc406Sopenharmony_ci 1962141cc406Sopenharmony_ci /* Something must have been read */ 1963141cc406Sopenharmony_ci if (dev->image_begin == dev->image_end) 1964141cc406Sopenharmony_ci { 1965141cc406Sopenharmony_ci DBG (DBG_info, "sane_read: nothing read\n"); 1966141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1967141cc406Sopenharmony_ci } 1968141cc406Sopenharmony_ci 1969141cc406Sopenharmony_ci /* Copy the data to the frontend buffer. */ 1970141cc406Sopenharmony_ci size = max_len - buf_offset; 1971141cc406Sopenharmony_ci if (size > dev->bytes_left) 1972141cc406Sopenharmony_ci { 1973141cc406Sopenharmony_ci size = dev->bytes_left; 1974141cc406Sopenharmony_ci } 1975141cc406Sopenharmony_ci sceptre_copy_raw_to_frontend (dev, buf + buf_offset, &size); 1976141cc406Sopenharmony_ci 1977141cc406Sopenharmony_ci buf_offset += size; 1978141cc406Sopenharmony_ci 1979141cc406Sopenharmony_ci dev->bytes_left -= size; 1980141cc406Sopenharmony_ci *len += size; 1981141cc406Sopenharmony_ci 1982141cc406Sopenharmony_ci } 1983141cc406Sopenharmony_ci while ((buf_offset != max_len) && dev->bytes_left); 1984141cc406Sopenharmony_ci 1985141cc406Sopenharmony_ci DBG (DBG_info, "sane_read: leave, bytes_left=%ld\n", (long)dev->bytes_left); 1986141cc406Sopenharmony_ci 1987141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1988141cc406Sopenharmony_ci} 1989141cc406Sopenharmony_ci 1990141cc406Sopenharmony_ciSANE_Status 1991141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) 1992141cc406Sopenharmony_ci{ 1993141cc406Sopenharmony_ci SANE_Status status; 1994141cc406Sopenharmony_ci Sceptre_Scanner *dev = handle; 1995141cc406Sopenharmony_ci 1996141cc406Sopenharmony_ci DBG (DBG_proc, "sane_set_io_mode: enter\n"); 1997141cc406Sopenharmony_ci 1998141cc406Sopenharmony_ci if (dev->scanning == SANE_FALSE) 1999141cc406Sopenharmony_ci { 2000141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 2001141cc406Sopenharmony_ci } 2002141cc406Sopenharmony_ci 2003141cc406Sopenharmony_ci if (non_blocking == SANE_FALSE) 2004141cc406Sopenharmony_ci { 2005141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 2006141cc406Sopenharmony_ci } 2007141cc406Sopenharmony_ci else 2008141cc406Sopenharmony_ci { 2009141cc406Sopenharmony_ci status = SANE_STATUS_UNSUPPORTED; 2010141cc406Sopenharmony_ci } 2011141cc406Sopenharmony_ci 2012141cc406Sopenharmony_ci DBG (DBG_proc, "sane_set_io_mode: exit\n"); 2013141cc406Sopenharmony_ci 2014141cc406Sopenharmony_ci return status; 2015141cc406Sopenharmony_ci} 2016141cc406Sopenharmony_ci 2017141cc406Sopenharmony_ciSANE_Status 2018141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd) 2019141cc406Sopenharmony_ci{ 2020141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_select_fd: enter\n"); 2021141cc406Sopenharmony_ci 2022141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_select_fd: exit\n"); 2023141cc406Sopenharmony_ci 2024141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 2025141cc406Sopenharmony_ci} 2026141cc406Sopenharmony_ci 2027141cc406Sopenharmony_civoid 2028141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 2029141cc406Sopenharmony_ci{ 2030141cc406Sopenharmony_ci Sceptre_Scanner *dev = handle; 2031141cc406Sopenharmony_ci 2032141cc406Sopenharmony_ci DBG (DBG_proc, "sane_cancel: enter\n"); 2033141cc406Sopenharmony_ci 2034141cc406Sopenharmony_ci do_cancel (dev); 2035141cc406Sopenharmony_ci 2036141cc406Sopenharmony_ci DBG (DBG_proc, "sane_cancel: exit\n"); 2037141cc406Sopenharmony_ci} 2038141cc406Sopenharmony_ci 2039141cc406Sopenharmony_civoid 2040141cc406Sopenharmony_cisane_close (SANE_Handle handle) 2041141cc406Sopenharmony_ci{ 2042141cc406Sopenharmony_ci Sceptre_Scanner *dev = handle; 2043141cc406Sopenharmony_ci Sceptre_Scanner *dev_tmp; 2044141cc406Sopenharmony_ci 2045141cc406Sopenharmony_ci DBG (DBG_proc, "sane_close: enter\n"); 2046141cc406Sopenharmony_ci 2047141cc406Sopenharmony_ci do_cancel (dev); 2048141cc406Sopenharmony_ci sceptre_close (dev); 2049141cc406Sopenharmony_ci 2050141cc406Sopenharmony_ci /* Unlink dev. */ 2051141cc406Sopenharmony_ci if (first_dev == dev) 2052141cc406Sopenharmony_ci { 2053141cc406Sopenharmony_ci first_dev = dev->next; 2054141cc406Sopenharmony_ci } 2055141cc406Sopenharmony_ci else 2056141cc406Sopenharmony_ci { 2057141cc406Sopenharmony_ci dev_tmp = first_dev; 2058141cc406Sopenharmony_ci while (dev_tmp->next && dev_tmp->next != dev) 2059141cc406Sopenharmony_ci { 2060141cc406Sopenharmony_ci dev_tmp = dev_tmp->next; 2061141cc406Sopenharmony_ci } 2062141cc406Sopenharmony_ci if (dev_tmp->next != NULL) 2063141cc406Sopenharmony_ci { 2064141cc406Sopenharmony_ci dev_tmp->next = dev_tmp->next->next; 2065141cc406Sopenharmony_ci } 2066141cc406Sopenharmony_ci } 2067141cc406Sopenharmony_ci 2068141cc406Sopenharmony_ci sceptre_free (dev); 2069141cc406Sopenharmony_ci num_devices--; 2070141cc406Sopenharmony_ci 2071141cc406Sopenharmony_ci DBG (DBG_proc, "sane_close: exit\n"); 2072141cc406Sopenharmony_ci} 2073141cc406Sopenharmony_ci 2074141cc406Sopenharmony_civoid 2075141cc406Sopenharmony_cisane_exit (void) 2076141cc406Sopenharmony_ci{ 2077141cc406Sopenharmony_ci DBG (DBG_proc, "sane_exit: enter\n"); 2078141cc406Sopenharmony_ci 2079141cc406Sopenharmony_ci while (first_dev) 2080141cc406Sopenharmony_ci { 2081141cc406Sopenharmony_ci sane_close (first_dev); 2082141cc406Sopenharmony_ci } 2083141cc406Sopenharmony_ci 2084141cc406Sopenharmony_ci if (devlist) 2085141cc406Sopenharmony_ci { 2086141cc406Sopenharmony_ci free (devlist); 2087141cc406Sopenharmony_ci devlist = NULL; 2088141cc406Sopenharmony_ci } 2089141cc406Sopenharmony_ci 2090141cc406Sopenharmony_ci DBG (DBG_proc, "sane_exit: exit\n"); 2091141cc406Sopenharmony_ci} 2092