1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci This file (C) 1997 Ingo Schneider 4141cc406Sopenharmony_ci (C) 1998 Karl Anders Øygard 5141cc406Sopenharmony_ci 6141cc406Sopenharmony_ci This file is part of the SANE package. 7141cc406Sopenharmony_ci 8141cc406Sopenharmony_ci SANE is free software; you can redistribute it and/or modify it under 9141cc406Sopenharmony_ci the terms of the GNU General Public License as published by the Free 10141cc406Sopenharmony_ci Software Foundation; either version 2 of the License, or (at your 11141cc406Sopenharmony_ci option) any later version. 12141cc406Sopenharmony_ci 13141cc406Sopenharmony_ci SANE is distributed in the hope that it will be useful, but WITHOUT 14141cc406Sopenharmony_ci ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15141cc406Sopenharmony_ci FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16141cc406Sopenharmony_ci for more details. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 19141cc406Sopenharmony_ci along with sane; see the file COPYING. 20141cc406Sopenharmony_ci If not, see <https://www.gnu.org/licenses/>. 21141cc406Sopenharmony_ci 22141cc406Sopenharmony_ci This file implements a SANE backend for AGFA Focus flatbed scanners. */ 23141cc406Sopenharmony_ci 24141cc406Sopenharmony_ci#include "../include/sane/config.h" 25141cc406Sopenharmony_ci 26141cc406Sopenharmony_ci#include <signal.h> 27141cc406Sopenharmony_ci#include <errno.h> 28141cc406Sopenharmony_ci#include <fcntl.h> 29141cc406Sopenharmony_ci#include <stdlib.h> 30141cc406Sopenharmony_ci#include <unistd.h> 31141cc406Sopenharmony_ci#include <string.h> 32141cc406Sopenharmony_ci#include <sys/types.h> 33141cc406Sopenharmony_ci 34141cc406Sopenharmony_ci#include "../include/sane/sane.h" 35141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 36141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 37141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 38141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h" 39141cc406Sopenharmony_ci#include "../include/sane/sanei_thread.h" 40141cc406Sopenharmony_ci 41141cc406Sopenharmony_ci#define BACKEND_NAME agfafocus 42141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 43141cc406Sopenharmony_ci 44141cc406Sopenharmony_ci#include "agfafocus.h" 45141cc406Sopenharmony_ci 46141cc406Sopenharmony_ci#ifndef PATH_MAX 47141cc406Sopenharmony_ci# define PATH_MAX 1024 48141cc406Sopenharmony_ci#endif 49141cc406Sopenharmony_ci 50141cc406Sopenharmony_ci 51141cc406Sopenharmony_ci#undef Byte 52141cc406Sopenharmony_ci#define Byte SANE_Byte 53141cc406Sopenharmony_ci 54141cc406Sopenharmony_cistatic const SANE_Device **devlist = 0; 55141cc406Sopenharmony_cistatic int num_devices; 56141cc406Sopenharmony_cistatic AgfaFocus_Device *agfafocus_devices; 57141cc406Sopenharmony_ci 58141cc406Sopenharmony_cistatic const SANE_String_Const focus_mode_list[] = 59141cc406Sopenharmony_ci{ 60141cc406Sopenharmony_ci "Lineart", "Gray (6 bit)", 61141cc406Sopenharmony_ci 0 62141cc406Sopenharmony_ci}; 63141cc406Sopenharmony_ci 64141cc406Sopenharmony_cistatic const SANE_String_Const focusii_mode_list[] = 65141cc406Sopenharmony_ci{ 66141cc406Sopenharmony_ci "Lineart", "Gray (6 bit)", "Gray (8 bit)", 67141cc406Sopenharmony_ci 0 68141cc406Sopenharmony_ci}; 69141cc406Sopenharmony_ci 70141cc406Sopenharmony_cistatic const SANE_String_Const focuscolor_mode_list[] = 71141cc406Sopenharmony_ci{ 72141cc406Sopenharmony_ci "Lineart", "Gray (6 bit)", "Gray (8 bit)", "Color (18 bit)", "Color (24 bit)", 73141cc406Sopenharmony_ci 0 74141cc406Sopenharmony_ci}; 75141cc406Sopenharmony_ci 76141cc406Sopenharmony_cistatic const SANE_String_Const halftone_list[] = 77141cc406Sopenharmony_ci{ 78141cc406Sopenharmony_ci "None", "Dispersed dot 4x4", "Round (Clustered dot 4x4)", "Diamond (Clustered dot 4x4)", 79141cc406Sopenharmony_ci 0 80141cc406Sopenharmony_ci}; 81141cc406Sopenharmony_ci 82141cc406Sopenharmony_cistatic const SANE_String_Const halftone_upload_list[] = 83141cc406Sopenharmony_ci{ 84141cc406Sopenharmony_ci "None", "Dispersed dot 4x4", "Round (Clustered dot 4x4)", "Diamond (Clustered dot 4x4)", 85141cc406Sopenharmony_ci 0 86141cc406Sopenharmony_ci}; 87141cc406Sopenharmony_ci 88141cc406Sopenharmony_cistatic const SANE_String_Const source_list[] = 89141cc406Sopenharmony_ci{ 90141cc406Sopenharmony_ci "Opaque/Normal", "Transparency", 91141cc406Sopenharmony_ci 0 92141cc406Sopenharmony_ci}; 93141cc406Sopenharmony_ci 94141cc406Sopenharmony_cistatic const SANE_String_Const quality_list[] = 95141cc406Sopenharmony_ci{ 96141cc406Sopenharmony_ci "Low", "Normal", "High", 97141cc406Sopenharmony_ci 0 98141cc406Sopenharmony_ci}; 99141cc406Sopenharmony_ci 100141cc406Sopenharmony_cistatic size_t 101141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[]) 102141cc406Sopenharmony_ci{ 103141cc406Sopenharmony_ci size_t size, max_size = 0; 104141cc406Sopenharmony_ci int i; 105141cc406Sopenharmony_ci DBG (11, ">> max_string_size\n"); 106141cc406Sopenharmony_ci 107141cc406Sopenharmony_ci for (i = 0; strings[i]; ++i) 108141cc406Sopenharmony_ci { 109141cc406Sopenharmony_ci size = strlen (strings[i]) + 1; 110141cc406Sopenharmony_ci if (size > max_size) 111141cc406Sopenharmony_ci max_size = size; 112141cc406Sopenharmony_ci } 113141cc406Sopenharmony_ci 114141cc406Sopenharmony_ci DBG (11, "<< max_string_size\n"); 115141cc406Sopenharmony_ci return max_size; 116141cc406Sopenharmony_ci} 117141cc406Sopenharmony_ci 118141cc406Sopenharmony_ci/* sets loc_s bytes long value at offset loc in scsi command to value size */ 119141cc406Sopenharmony_cistatic void 120141cc406Sopenharmony_ciset_size (Byte * loc, int loc_s, size_t size) 121141cc406Sopenharmony_ci{ 122141cc406Sopenharmony_ci int i; 123141cc406Sopenharmony_ci 124141cc406Sopenharmony_ci for (i = 0; i < loc_s; i++) 125141cc406Sopenharmony_ci { 126141cc406Sopenharmony_ci loc[loc_s - i - 1] = (size >> (i * 8)) & 0xff; 127141cc406Sopenharmony_ci } 128141cc406Sopenharmony_ci} 129141cc406Sopenharmony_ci 130141cc406Sopenharmony_ci/* gets loc_s bytes long value from loc in scsi command */ 131141cc406Sopenharmony_cistatic int 132141cc406Sopenharmony_ciget_size (Byte * loc, int loc_s) 133141cc406Sopenharmony_ci{ 134141cc406Sopenharmony_ci int i; 135141cc406Sopenharmony_ci int j = 0; 136141cc406Sopenharmony_ci 137141cc406Sopenharmony_ci for (i = 0; i < loc_s; i++) 138141cc406Sopenharmony_ci { 139141cc406Sopenharmony_ci j = (j << 8) + (loc[i] & 0xff); 140141cc406Sopenharmony_ci } 141141cc406Sopenharmony_ci 142141cc406Sopenharmony_ci return j; 143141cc406Sopenharmony_ci} 144141cc406Sopenharmony_ci 145141cc406Sopenharmony_cistatic long 146141cc406Sopenharmony_cireserve_unit (int fd) 147141cc406Sopenharmony_ci{ 148141cc406Sopenharmony_ci struct 149141cc406Sopenharmony_ci { 150141cc406Sopenharmony_ci /* Command */ 151141cc406Sopenharmony_ci Byte cmd; 152141cc406Sopenharmony_ci Byte lun; 153141cc406Sopenharmony_ci Byte res[2]; 154141cc406Sopenharmony_ci Byte tr_len; 155141cc406Sopenharmony_ci Byte ctrl; 156141cc406Sopenharmony_ci } 157141cc406Sopenharmony_ci scsi_reserve; 158141cc406Sopenharmony_ci 159141cc406Sopenharmony_ci memset (&scsi_reserve, 0, sizeof (scsi_reserve)); 160141cc406Sopenharmony_ci 161141cc406Sopenharmony_ci scsi_reserve.cmd = 0x16; /* RELEASE */ 162141cc406Sopenharmony_ci 163141cc406Sopenharmony_ci DBG (3, "reserve_unit()\n"); 164141cc406Sopenharmony_ci return sanei_scsi_cmd (fd, &scsi_reserve, sizeof (scsi_reserve), 0, 0); 165141cc406Sopenharmony_ci} 166141cc406Sopenharmony_ci 167141cc406Sopenharmony_cistatic long 168141cc406Sopenharmony_cirelease_unit (int fd) 169141cc406Sopenharmony_ci{ 170141cc406Sopenharmony_ci struct 171141cc406Sopenharmony_ci { 172141cc406Sopenharmony_ci /* Command */ 173141cc406Sopenharmony_ci Byte cmd; 174141cc406Sopenharmony_ci Byte lun; 175141cc406Sopenharmony_ci Byte res[2]; 176141cc406Sopenharmony_ci Byte tr_len; 177141cc406Sopenharmony_ci Byte ctrl; 178141cc406Sopenharmony_ci } 179141cc406Sopenharmony_ci scsi_release; 180141cc406Sopenharmony_ci 181141cc406Sopenharmony_ci memset (&scsi_release, 0, sizeof (scsi_release)); 182141cc406Sopenharmony_ci 183141cc406Sopenharmony_ci scsi_release.cmd = 0x17; /* RELEASE */ 184141cc406Sopenharmony_ci 185141cc406Sopenharmony_ci DBG (3, "release_unit()\n"); 186141cc406Sopenharmony_ci return sanei_scsi_cmd (fd, &scsi_release, sizeof (scsi_release), 0, 0); 187141cc406Sopenharmony_ci} 188141cc406Sopenharmony_ci 189141cc406Sopenharmony_cistatic SANE_Status 190141cc406Sopenharmony_citest_ready (int fd) 191141cc406Sopenharmony_ci{ 192141cc406Sopenharmony_ci SANE_Status status; 193141cc406Sopenharmony_ci int try; 194141cc406Sopenharmony_ci 195141cc406Sopenharmony_ci struct 196141cc406Sopenharmony_ci { 197141cc406Sopenharmony_ci /* Command */ 198141cc406Sopenharmony_ci Byte cmd; 199141cc406Sopenharmony_ci Byte lun; 200141cc406Sopenharmony_ci Byte res[2]; 201141cc406Sopenharmony_ci Byte tr_len; 202141cc406Sopenharmony_ci Byte ctrl; 203141cc406Sopenharmony_ci } 204141cc406Sopenharmony_ci scsi_test_ready; 205141cc406Sopenharmony_ci 206141cc406Sopenharmony_ci memset (&scsi_test_ready, 0, sizeof (scsi_test_ready)); 207141cc406Sopenharmony_ci 208141cc406Sopenharmony_ci scsi_test_ready.cmd = 0x00; /* TEST UNIT READY */ 209141cc406Sopenharmony_ci 210141cc406Sopenharmony_ci for (try = 0; try < 1000; ++try) 211141cc406Sopenharmony_ci { 212141cc406Sopenharmony_ci DBG (3, "test_ready: sending TEST_UNIT_READY\n"); 213141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, &scsi_test_ready, sizeof (scsi_test_ready), 214141cc406Sopenharmony_ci 0, 0); 215141cc406Sopenharmony_ci 216141cc406Sopenharmony_ci switch (status) 217141cc406Sopenharmony_ci { 218141cc406Sopenharmony_ci case SANE_STATUS_DEVICE_BUSY: 219141cc406Sopenharmony_ci usleep (100000); /* retry after 100ms */ 220141cc406Sopenharmony_ci break; 221141cc406Sopenharmony_ci 222141cc406Sopenharmony_ci case SANE_STATUS_GOOD: 223141cc406Sopenharmony_ci return status; 224141cc406Sopenharmony_ci 225141cc406Sopenharmony_ci default: 226141cc406Sopenharmony_ci DBG (1, "test_ready: test unit ready failed (%s)\n", 227141cc406Sopenharmony_ci sane_strstatus (status)); 228141cc406Sopenharmony_ci return status; 229141cc406Sopenharmony_ci } 230141cc406Sopenharmony_ci } 231141cc406Sopenharmony_ci 232141cc406Sopenharmony_ci DBG (1, "test_ready: timed out after %d attempts\n", try); 233141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 234141cc406Sopenharmony_ci} 235141cc406Sopenharmony_ci 236141cc406Sopenharmony_cistatic SANE_Status 237141cc406Sopenharmony_cisense_handler (int scsi_fd, u_char *result, void *arg) 238141cc406Sopenharmony_ci{ 239141cc406Sopenharmony_ci (void) scsi_fd; /* silence gcc */ 240141cc406Sopenharmony_ci (void) arg; /* silence gcc */ 241141cc406Sopenharmony_ci 242141cc406Sopenharmony_ci if (result[0]) 243141cc406Sopenharmony_ci { 244141cc406Sopenharmony_ci DBG (0, "sense_handler() : sense code = %02x\n", result[0]); 245141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 246141cc406Sopenharmony_ci } 247141cc406Sopenharmony_ci else 248141cc406Sopenharmony_ci { 249141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 250141cc406Sopenharmony_ci } 251141cc406Sopenharmony_ci} 252141cc406Sopenharmony_ci 253141cc406Sopenharmony_cistatic SANE_Status 254141cc406Sopenharmony_cistop_scan (int fd) 255141cc406Sopenharmony_ci{ 256141cc406Sopenharmony_ci (void) fd; /* silence gcc */ 257141cc406Sopenharmony_ci 258141cc406Sopenharmony_ci /* XXX don't know how to stop the scanner. To be tested ! */ 259141cc406Sopenharmony_ci#if 0 260141cc406Sopenharmony_ci const Byte scsi_rewind[] = 261141cc406Sopenharmony_ci { 262141cc406Sopenharmony_ci 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 263141cc406Sopenharmony_ci }; 264141cc406Sopenharmony_ci DBG (1, "Trying to stop scanner...\n"); 265141cc406Sopenharmony_ci return sanei_scsi_cmd (fd, scsi_rewind, sizeof (scsi_rewind), 0, 0); 266141cc406Sopenharmony_ci#else 267141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 268141cc406Sopenharmony_ci#endif 269141cc406Sopenharmony_ci} 270141cc406Sopenharmony_ci 271141cc406Sopenharmony_ci 272141cc406Sopenharmony_cistatic SANE_Status 273141cc406Sopenharmony_cistart_scan (int fd, SANE_Bool cont) 274141cc406Sopenharmony_ci{ 275141cc406Sopenharmony_ci struct 276141cc406Sopenharmony_ci { 277141cc406Sopenharmony_ci /* Command */ 278141cc406Sopenharmony_ci Byte cmd; 279141cc406Sopenharmony_ci Byte lun; 280141cc406Sopenharmony_ci Byte res[2]; 281141cc406Sopenharmony_ci Byte tr_len; 282141cc406Sopenharmony_ci Byte ctrl; 283141cc406Sopenharmony_ci 284141cc406Sopenharmony_ci /* Data */ 285141cc406Sopenharmony_ci Byte wid; 286141cc406Sopenharmony_ci } 287141cc406Sopenharmony_ci scsi_start_scan; 288141cc406Sopenharmony_ci 289141cc406Sopenharmony_ci memset (&scsi_start_scan, 0, sizeof (scsi_start_scan)); 290141cc406Sopenharmony_ci 291141cc406Sopenharmony_ci scsi_start_scan.cmd = 0x1b; /* SCAN */ 292141cc406Sopenharmony_ci scsi_start_scan.tr_len = 1; 293141cc406Sopenharmony_ci scsi_start_scan.wid = 0; 294141cc406Sopenharmony_ci scsi_start_scan.ctrl = (cont == SANE_TRUE) ? 0x80 : 0x00; 295141cc406Sopenharmony_ci 296141cc406Sopenharmony_ci DBG (1, "Starting scanner ...\n"); 297141cc406Sopenharmony_ci return sanei_scsi_cmd (fd, &scsi_start_scan, sizeof (scsi_start_scan), 0, 0); 298141cc406Sopenharmony_ci} 299141cc406Sopenharmony_ci 300141cc406Sopenharmony_cistatic void 301141cc406Sopenharmony_ciwait_ready (int fd) 302141cc406Sopenharmony_ci{ 303141cc406Sopenharmony_ci struct 304141cc406Sopenharmony_ci { 305141cc406Sopenharmony_ci Byte bytes[2]; /* Total # of bytes */ 306141cc406Sopenharmony_ci Byte scan[2]; /* ms to complete - driver sleep time */ 307141cc406Sopenharmony_ci } result; 308141cc406Sopenharmony_ci 309141cc406Sopenharmony_ci size_t size = sizeof (result); 310141cc406Sopenharmony_ci SANE_Status status; 311141cc406Sopenharmony_ci 312141cc406Sopenharmony_ci struct { 313141cc406Sopenharmony_ci Byte cmd; 314141cc406Sopenharmony_ci Byte lun; 315141cc406Sopenharmony_ci Byte data_type; 316141cc406Sopenharmony_ci Byte re1[3]; 317141cc406Sopenharmony_ci Byte tr_len[3]; 318141cc406Sopenharmony_ci Byte ctrl; 319141cc406Sopenharmony_ci } cmd; 320141cc406Sopenharmony_ci 321141cc406Sopenharmony_ci memset (&cmd, 0, sizeof (cmd)); 322141cc406Sopenharmony_ci 323141cc406Sopenharmony_ci cmd.cmd = 0x28; /* READ */ 324141cc406Sopenharmony_ci cmd.data_type = 0x80; /* get scan time */ 325141cc406Sopenharmony_ci 326141cc406Sopenharmony_ci set_size (cmd.tr_len, 3, sizeof (result)); 327141cc406Sopenharmony_ci 328141cc406Sopenharmony_ci while (1) 329141cc406Sopenharmony_ci { 330141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), 331141cc406Sopenharmony_ci &result, &size); 332141cc406Sopenharmony_ci 333141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD || size != sizeof (result)) 334141cc406Sopenharmony_ci { 335141cc406Sopenharmony_ci /* 336141cc406Sopenharmony_ci Command failed, the assembler code of the windows scan library 337141cc406Sopenharmony_ci ignores this condition, and so do I 338141cc406Sopenharmony_ci */ 339141cc406Sopenharmony_ci break; 340141cc406Sopenharmony_ci } 341141cc406Sopenharmony_ci else 342141cc406Sopenharmony_ci { 343141cc406Sopenharmony_ci /* left is the amount of seconds left till the scanner is 344141cc406Sopenharmony_ci ready * 100 */ 345141cc406Sopenharmony_ci int left = get_size (result.scan, 2); 346141cc406Sopenharmony_ci 347141cc406Sopenharmony_ci DBG (1, "wait_ready() : %d left...\n", left); 348141cc406Sopenharmony_ci 349141cc406Sopenharmony_ci if (!left) 350141cc406Sopenharmony_ci break; 351141cc406Sopenharmony_ci /* We delay only for half the given time */ 352141cc406Sopenharmony_ci else if (left < 200) 353141cc406Sopenharmony_ci usleep (left * 5000); 354141cc406Sopenharmony_ci else 355141cc406Sopenharmony_ci sleep (left / 200); 356141cc406Sopenharmony_ci } 357141cc406Sopenharmony_ci } 358141cc406Sopenharmony_ci 359141cc406Sopenharmony_ci return; 360141cc406Sopenharmony_ci} 361141cc406Sopenharmony_ci 362141cc406Sopenharmony_cistatic SANE_Status 363141cc406Sopenharmony_ciget_read_sizes (int fd, int *lines_available, int *bpl, int *total_lines) 364141cc406Sopenharmony_ci{ 365141cc406Sopenharmony_ci struct { 366141cc406Sopenharmony_ci Byte reserved1[8]; 367141cc406Sopenharmony_ci Byte line_width[2]; 368141cc406Sopenharmony_ci Byte total_lines[2]; 369141cc406Sopenharmony_ci Byte cur_line[2]; 370141cc406Sopenharmony_ci Byte lines_this_block[2]; 371141cc406Sopenharmony_ci Byte reserved[8]; 372141cc406Sopenharmony_ci } read_sizes; 373141cc406Sopenharmony_ci 374141cc406Sopenharmony_ci const Byte scsi_read[] = 375141cc406Sopenharmony_ci { 376141cc406Sopenharmony_ci 0x28, 0x00, /* opcode, lun */ 377141cc406Sopenharmony_ci 0x81, /* data type 81 == read time left */ 378141cc406Sopenharmony_ci 0x00, 0x00, 0x00, /* reserved */ 379141cc406Sopenharmony_ci 0x00, 0x00, sizeof (read_sizes), /* transfer length */ 380141cc406Sopenharmony_ci 0x00, /* control byte */ 381141cc406Sopenharmony_ci }; 382141cc406Sopenharmony_ci 383141cc406Sopenharmony_ci size_t size = sizeof (read_sizes); 384141cc406Sopenharmony_ci SANE_Status status; 385141cc406Sopenharmony_ci 386141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, scsi_read, sizeof (scsi_read), &read_sizes, &size); 387141cc406Sopenharmony_ci 388141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD || size != sizeof (read_sizes)) 389141cc406Sopenharmony_ci { 390141cc406Sopenharmony_ci /* Command failed */ 391141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 392141cc406Sopenharmony_ci } 393141cc406Sopenharmony_ci else 394141cc406Sopenharmony_ci { 395141cc406Sopenharmony_ci *lines_available = get_size (read_sizes.lines_this_block, 2); 396141cc406Sopenharmony_ci *bpl = get_size (read_sizes.cur_line, 2); 397141cc406Sopenharmony_ci if (total_lines) 398141cc406Sopenharmony_ci *total_lines = get_size (read_sizes.total_lines, 2); 399141cc406Sopenharmony_ci } 400141cc406Sopenharmony_ci 401141cc406Sopenharmony_ci DBG (1, "get_read_sizes() : %d of %d, %d\n", 402141cc406Sopenharmony_ci *lines_available, total_lines ? *total_lines : -1, *bpl); 403141cc406Sopenharmony_ci 404141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 405141cc406Sopenharmony_ci} 406141cc406Sopenharmony_ci 407141cc406Sopenharmony_cistatic SANE_Status 408141cc406Sopenharmony_ciset_window (AgfaFocus_Scanner * s) 409141cc406Sopenharmony_ci/* This function sets and sends the window for scanning */ 410141cc406Sopenharmony_ci{ 411141cc406Sopenharmony_ci double pixels_per_mm = (double) s->val[OPT_RESOLUTION].w / MM_PER_INCH; 412141cc406Sopenharmony_ci 413141cc406Sopenharmony_ci SANE_Bool auto_bright = s->val[OPT_AUTO_BRIGHTNESS].b; 414141cc406Sopenharmony_ci SANE_Bool auto_contr = s->val[OPT_AUTO_CONTRAST].b; 415141cc406Sopenharmony_ci 416141cc406Sopenharmony_ci /* ranges down 255 (dark) down to 1(bright) */ 417141cc406Sopenharmony_ci int brightness = auto_bright ? 0 : (SANE_UNFIX (s->val[OPT_BRIGHTNESS].w) 418141cc406Sopenharmony_ci * -1.27 + 128.5); 419141cc406Sopenharmony_ci /* ranges from 1 (little contrast) up to 255 (much contrast) */ 420141cc406Sopenharmony_ci int contrast = auto_contr ? 0 : (SANE_UNFIX (s->val[OPT_CONTRAST].w) 421141cc406Sopenharmony_ci * 1.27 + 128.5); 422141cc406Sopenharmony_ci 423141cc406Sopenharmony_ci int width; 424141cc406Sopenharmony_ci 425141cc406Sopenharmony_ci /* ranges from 40 (dark) down to 0 (bright) */ 426141cc406Sopenharmony_ci int bright_adjust = (SANE_UNFIX (s->val[OPT_BRIGHTNESS].w) * -20.0) / 100.0 + 20.0; 427141cc406Sopenharmony_ci 428141cc406Sopenharmony_ci /* ranges from 20 (little contrast) down to -20 = 235 (much contrast) */ 429141cc406Sopenharmony_ci int contr_adjust = (SANE_UNFIX (s->val[OPT_CONTRAST].w) * -20.0) / 100.0; 430141cc406Sopenharmony_ci 431141cc406Sopenharmony_ci /* Warning ! The following structure SEEMS to be a valid SCSI-2 SET_WINDOW 432141cc406Sopenharmony_ci command. But e.g. the limits for the window are only 2 Bytes instead 433141cc406Sopenharmony_ci of 4. The scanner was built at about 1990, so SCSI-2 wasn't available 434141cc406Sopenharmony_ci for development... */ 435141cc406Sopenharmony_ci 436141cc406Sopenharmony_ci struct 437141cc406Sopenharmony_ci { 438141cc406Sopenharmony_ci Byte cmd; 439141cc406Sopenharmony_ci Byte lun; 440141cc406Sopenharmony_ci Byte re1[4]; 441141cc406Sopenharmony_ci Byte tr_len[3]; 442141cc406Sopenharmony_ci Byte ctrl; 443141cc406Sopenharmony_ci 444141cc406Sopenharmony_ci Byte re2[6]; 445141cc406Sopenharmony_ci Byte wd_len[2]; 446141cc406Sopenharmony_ci 447141cc406Sopenharmony_ci struct 448141cc406Sopenharmony_ci { 449141cc406Sopenharmony_ci Byte wid; /* Window ID */ 450141cc406Sopenharmony_ci Byte autobit; /* Window creation */ 451141cc406Sopenharmony_ci 452141cc406Sopenharmony_ci Byte x_axis_res[2]; /* X resolution */ 453141cc406Sopenharmony_ci Byte y_axis_res[2]; /* X resolution */ 454141cc406Sopenharmony_ci 455141cc406Sopenharmony_ci Byte x_axis_ul[2]; /* X upper left */ 456141cc406Sopenharmony_ci Byte y_axis_ul[2]; /* Y upper left */ 457141cc406Sopenharmony_ci 458141cc406Sopenharmony_ci Byte wwidth[2]; /* Width */ 459141cc406Sopenharmony_ci Byte wlength[2]; /* Length */ 460141cc406Sopenharmony_ci 461141cc406Sopenharmony_ci Byte contrast; /* Contrast */ 462141cc406Sopenharmony_ci Byte dummy1; 463141cc406Sopenharmony_ci Byte intensity; /* Intensity */ 464141cc406Sopenharmony_ci 465141cc406Sopenharmony_ci Byte image_comp; /* Image composition (0, 2, 5) */ 466141cc406Sopenharmony_ci Byte bpp; /* Bits per pixel */ 467141cc406Sopenharmony_ci 468141cc406Sopenharmony_ci Byte tonecurve; /* Tone curve (0 - 8) */ 469141cc406Sopenharmony_ci Byte ht_pattern; /* Halftone pattern */ 470141cc406Sopenharmony_ci Byte paddingtype; /* Padding type */ 471141cc406Sopenharmony_ci 472141cc406Sopenharmony_ci Byte bitordering[2]; /* Bit ordering (0 = left to right) */ 473141cc406Sopenharmony_ci Byte comprtype; /* Compression type */ 474141cc406Sopenharmony_ci Byte comprarg; /* Compression argument */ 475141cc406Sopenharmony_ci 476141cc406Sopenharmony_ci Byte dummy2[6]; 477141cc406Sopenharmony_ci Byte edge; /* Sharpening (0 - 7) */ 478141cc406Sopenharmony_ci Byte dummy3; 479141cc406Sopenharmony_ci 480141cc406Sopenharmony_ci Byte bright_adjust; /* */ 481141cc406Sopenharmony_ci Byte contr_adjust; /* */ 482141cc406Sopenharmony_ci 483141cc406Sopenharmony_ci Byte imagewidthtruncation; /* */ 484141cc406Sopenharmony_ci 485141cc406Sopenharmony_ci Byte dummy4; 486141cc406Sopenharmony_ci Byte quality_type; /* 0 normal, 1 high, 255 low */ 487141cc406Sopenharmony_ci Byte red_att; 488141cc406Sopenharmony_ci Byte green_att; 489141cc406Sopenharmony_ci Byte blue_att; 490141cc406Sopenharmony_ci 491141cc406Sopenharmony_ci Byte dummy5[5]; 492141cc406Sopenharmony_ci Byte color_planes; 493141cc406Sopenharmony_ci Byte orig_type; 494141cc406Sopenharmony_ci Byte fixturetype; 495141cc406Sopenharmony_ci Byte exposure[2]; 496141cc406Sopenharmony_ci Byte defocus[2]; 497141cc406Sopenharmony_ci Byte dummy6[4]; 498141cc406Sopenharmony_ci Byte descreen_factor; 499141cc406Sopenharmony_ci 500141cc406Sopenharmony_ci Byte packing_word_length; 501141cc406Sopenharmony_ci Byte packing_number_of_pixels; 502141cc406Sopenharmony_ci Byte packing_color_mode; 503141cc406Sopenharmony_ci Byte strokenab; 504141cc406Sopenharmony_ci Byte rotatenab; 505141cc406Sopenharmony_ci Byte autostrokenab; 506141cc406Sopenharmony_ci Byte dummy7; 507141cc406Sopenharmony_ci } 508141cc406Sopenharmony_ci wd; 509141cc406Sopenharmony_ci 510141cc406Sopenharmony_ci } 511141cc406Sopenharmony_ci cmd; 512141cc406Sopenharmony_ci 513141cc406Sopenharmony_ci memset (&cmd, 0, sizeof (cmd)); 514141cc406Sopenharmony_ci 515141cc406Sopenharmony_ci cmd.cmd = 0x24; /* SET WINDOW PARAMETERS */ 516141cc406Sopenharmony_ci 517141cc406Sopenharmony_ci switch (s->hw->type) 518141cc406Sopenharmony_ci { 519141cc406Sopenharmony_ci case AGFAGRAY64: 520141cc406Sopenharmony_ci case AGFALINEART: 521141cc406Sopenharmony_ci case AGFAGRAY256: 522141cc406Sopenharmony_ci set_size (cmd.tr_len, 3, 36 + 8); 523141cc406Sopenharmony_ci set_size (cmd.wd_len, 2, 36); 524141cc406Sopenharmony_ci break; 525141cc406Sopenharmony_ci 526141cc406Sopenharmony_ci case AGFACOLOR: 527141cc406Sopenharmony_ci set_size (cmd.tr_len, 3, 65 + 8); 528141cc406Sopenharmony_ci set_size (cmd.wd_len, 2, 65); 529141cc406Sopenharmony_ci break; 530141cc406Sopenharmony_ci } 531141cc406Sopenharmony_ci 532141cc406Sopenharmony_ci /* Resolution. Original comment in German: Aufloesung */ 533141cc406Sopenharmony_ci set_size (cmd.wd.x_axis_res, 2, s->val[OPT_RESOLUTION].w); 534141cc406Sopenharmony_ci set_size (cmd.wd.y_axis_res, 2, s->val[OPT_RESOLUTION].w); 535141cc406Sopenharmony_ci 536141cc406Sopenharmony_ci /* Scan window position/size. Original comment in German: 537141cc406Sopenharmony_ci Fensterposition / Groesse */ 538141cc406Sopenharmony_ci set_size (cmd.wd.x_axis_ul, 2, 539141cc406Sopenharmony_ci SANE_UNFIX (s->val[OPT_TL_X].w) * pixels_per_mm + 0.5); 540141cc406Sopenharmony_ci set_size (cmd.wd.y_axis_ul, 2, 541141cc406Sopenharmony_ci SANE_UNFIX (s->val[OPT_TL_Y].w) * pixels_per_mm + 0.5); 542141cc406Sopenharmony_ci 543141cc406Sopenharmony_ci width = (SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w) * pixels_per_mm) + 0.5; 544141cc406Sopenharmony_ci 545141cc406Sopenharmony_ci if (s->bpp == 1 && width % 8) 546141cc406Sopenharmony_ci width += 8 - width % 8; 547141cc406Sopenharmony_ci 548141cc406Sopenharmony_ci set_size (cmd.wd.wwidth, 2, width); 549141cc406Sopenharmony_ci set_size (cmd.wd.wlength, 2, SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w) 550141cc406Sopenharmony_ci * pixels_per_mm + 0.5); 551141cc406Sopenharmony_ci 552141cc406Sopenharmony_ci cmd.wd.bpp = s->bpp; 553141cc406Sopenharmony_ci 554141cc406Sopenharmony_ci if (s->mode == COLOR18BIT || 555141cc406Sopenharmony_ci s->mode == COLOR24BIT) 556141cc406Sopenharmony_ci { 557141cc406Sopenharmony_ci cmd.wd.paddingtype = 3; 558141cc406Sopenharmony_ci cmd.wd.ht_pattern = 3; 559141cc406Sopenharmony_ci 560141cc406Sopenharmony_ci cmd.wd.red_att = s->r_att; 561141cc406Sopenharmony_ci cmd.wd.blue_att = s->g_att; 562141cc406Sopenharmony_ci cmd.wd.green_att = s->b_att; 563141cc406Sopenharmony_ci cmd.wd.color_planes = 0x0e; 564141cc406Sopenharmony_ci 565141cc406Sopenharmony_ci set_size (cmd.wd.exposure, 2, s->exposure); 566141cc406Sopenharmony_ci 567141cc406Sopenharmony_ci cmd.wd.packing_word_length = 1; 568141cc406Sopenharmony_ci cmd.wd.packing_number_of_pixels = 1; 569141cc406Sopenharmony_ci cmd.wd.packing_color_mode = 2; 570141cc406Sopenharmony_ci 571141cc406Sopenharmony_ci if (s->bpp == 6) 572141cc406Sopenharmony_ci cmd.wd.edge = s->edge; 573141cc406Sopenharmony_ci 574141cc406Sopenharmony_ci DBG (3, 575141cc406Sopenharmony_ci "Setting parameters: imc %d, bpp %d, res %d, exp %d, attenuation [%d, %d, %d], edge %d\n", 576141cc406Sopenharmony_ci s->image_composition, s->bpp, s->val[OPT_RESOLUTION].w, 577141cc406Sopenharmony_ci s->exposure, cmd.wd.red_att, cmd.wd.blue_att, cmd.wd.green_att, s->edge); 578141cc406Sopenharmony_ci } 579141cc406Sopenharmony_ci else 580141cc406Sopenharmony_ci { 581141cc406Sopenharmony_ci if (s->bpp == 1) 582141cc406Sopenharmony_ci cmd.wd.ht_pattern = s->halftone; 583141cc406Sopenharmony_ci else 584141cc406Sopenharmony_ci cmd.wd.ht_pattern = 3; 585141cc406Sopenharmony_ci 586141cc406Sopenharmony_ci cmd.wd.intensity = brightness; 587141cc406Sopenharmony_ci cmd.wd.contrast = contrast; 588141cc406Sopenharmony_ci 589141cc406Sopenharmony_ci cmd.wd.contr_adjust = contr_adjust; 590141cc406Sopenharmony_ci cmd.wd.bright_adjust = bright_adjust; 591141cc406Sopenharmony_ci 592141cc406Sopenharmony_ci cmd.wd.tonecurve = s->tonecurve; 593141cc406Sopenharmony_ci cmd.wd.paddingtype = 3; 594141cc406Sopenharmony_ci cmd.wd.edge = s->edge; 595141cc406Sopenharmony_ci 596141cc406Sopenharmony_ci if (s->lin_log) 597141cc406Sopenharmony_ci cmd.wd.dummy3 = 0x02; 598141cc406Sopenharmony_ci 599141cc406Sopenharmony_ci DBG (3, 600141cc406Sopenharmony_ci "Setting parameters: imc %d, bpp %d, res %d, bri %d, con %d, bad %d, cad %d, ht %d, edge %d\n", 601141cc406Sopenharmony_ci s->image_composition, s->bpp, s->val[OPT_RESOLUTION].w, 602141cc406Sopenharmony_ci brightness, contrast, bright_adjust, contr_adjust, s->halftone, s->edge); 603141cc406Sopenharmony_ci } 604141cc406Sopenharmony_ci 605141cc406Sopenharmony_ci cmd.wd.image_comp = s->image_composition; 606141cc406Sopenharmony_ci cmd.wd.quality_type = s->quality; 607141cc406Sopenharmony_ci cmd.wd.orig_type = s->original; 608141cc406Sopenharmony_ci 609141cc406Sopenharmony_ci return sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 0, 0); 610141cc406Sopenharmony_ci} 611141cc406Sopenharmony_ci 612141cc406Sopenharmony_ci/* Tell scanner to scan more data. */ 613141cc406Sopenharmony_ci 614141cc406Sopenharmony_cistatic SANE_Status 615141cc406Sopenharmony_cirequest_more_data (AgfaFocus_Scanner * s) 616141cc406Sopenharmony_ci{ 617141cc406Sopenharmony_ci SANE_Status status; 618141cc406Sopenharmony_ci int lines_available; 619141cc406Sopenharmony_ci int bytes_per_line; 620141cc406Sopenharmony_ci 621141cc406Sopenharmony_ci status = start_scan (s->fd, SANE_TRUE); 622141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 623141cc406Sopenharmony_ci return status; 624141cc406Sopenharmony_ci 625141cc406Sopenharmony_ci if (!s->hw->disconnect) 626141cc406Sopenharmony_ci wait_ready (s->fd); 627141cc406Sopenharmony_ci 628141cc406Sopenharmony_ci status = get_read_sizes (s->fd, &lines_available, &bytes_per_line, 0); 629141cc406Sopenharmony_ci 630141cc406Sopenharmony_ci if (!lines_available) 631141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 632141cc406Sopenharmony_ci 633141cc406Sopenharmony_ci s->lines_available = lines_available; 634141cc406Sopenharmony_ci 635141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 636141cc406Sopenharmony_ci} 637141cc406Sopenharmony_ci 638141cc406Sopenharmony_cistatic SANE_Status 639141cc406Sopenharmony_ciupload_dither_matrix (AgfaFocus_Scanner * s, int rows, int cols, int *dither_matrix) 640141cc406Sopenharmony_ci{ 641141cc406Sopenharmony_ci struct { 642141cc406Sopenharmony_ci Byte cmd; 643141cc406Sopenharmony_ci Byte lun; 644141cc406Sopenharmony_ci Byte data_type; 645141cc406Sopenharmony_ci Byte re1[3]; 646141cc406Sopenharmony_ci Byte tr_len[3]; 647141cc406Sopenharmony_ci Byte ctrl; 648141cc406Sopenharmony_ci 649141cc406Sopenharmony_ci struct { 650141cc406Sopenharmony_ci Byte nrrows[2]; 651141cc406Sopenharmony_ci Byte nrcols[2]; 652141cc406Sopenharmony_ci 653141cc406Sopenharmony_ci struct { 654141cc406Sopenharmony_ci Byte data[2]; 655141cc406Sopenharmony_ci } element[256]; 656141cc406Sopenharmony_ci } wd; 657141cc406Sopenharmony_ci } cmd; 658141cc406Sopenharmony_ci 659141cc406Sopenharmony_ci SANE_Status status; 660141cc406Sopenharmony_ci int i; 661141cc406Sopenharmony_ci 662141cc406Sopenharmony_ci memset (&cmd, 0, sizeof (cmd)); 663141cc406Sopenharmony_ci 664141cc406Sopenharmony_ci cmd.cmd = 0x2a; /* WRITE */ 665141cc406Sopenharmony_ci cmd.data_type = 0x81; /* upload dither matrix */ 666141cc406Sopenharmony_ci 667141cc406Sopenharmony_ci set_size (cmd.tr_len, 3, 4 + (2 * rows * cols)); 668141cc406Sopenharmony_ci set_size (cmd.wd.nrrows, 2, rows); 669141cc406Sopenharmony_ci set_size (cmd.wd.nrcols, 2, cols); 670141cc406Sopenharmony_ci 671141cc406Sopenharmony_ci for (i = 0; i < cols * rows; ++i) 672141cc406Sopenharmony_ci set_size (cmd.wd.element[i].data, 2, dither_matrix[i]); 673141cc406Sopenharmony_ci 674141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 0, 0); 675141cc406Sopenharmony_ci 676141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 677141cc406Sopenharmony_ci /* Command failed */ 678141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 679141cc406Sopenharmony_ci 680141cc406Sopenharmony_ci DBG (1, "upload_dither_matrix(): uploaded dither matrix: %d, %d\n", rows, cols); 681141cc406Sopenharmony_ci 682141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 683141cc406Sopenharmony_ci} 684141cc406Sopenharmony_ci 685141cc406Sopenharmony_ci#if 0 686141cc406Sopenharmony_cistatic SANE_Status 687141cc406Sopenharmony_ciupload_tonecurve (AgfaFocus_Scanner * s, int color_type, int input, int output, int dither_matrix[256]) 688141cc406Sopenharmony_ci{ 689141cc406Sopenharmony_ci struct { 690141cc406Sopenharmony_ci Byte cmd; 691141cc406Sopenharmony_ci Byte lun; 692141cc406Sopenharmony_ci Byte re1[4]; 693141cc406Sopenharmony_ci Byte tr_len[3]; 694141cc406Sopenharmony_ci Byte ctrl; 695141cc406Sopenharmony_ci 696141cc406Sopenharmony_ci Byte re2[6]; 697141cc406Sopenharmony_ci Byte wd_len[2]; 698141cc406Sopenharmony_ci 699141cc406Sopenharmony_ci struct { 700141cc406Sopenharmony_ci Byte color_type[2]; 701141cc406Sopenharmony_ci Byte nrinput[2]; 702141cc406Sopenharmony_ci Byte nroutput[2]; 703141cc406Sopenharmony_ci 704141cc406Sopenharmony_ci struct { 705141cc406Sopenharmony_ci Byte data[2]; 706141cc406Sopenharmony_ci } outputval[256]; 707141cc406Sopenharmony_ci } wd; 708141cc406Sopenharmony_ci } cmd; 709141cc406Sopenharmony_ci 710141cc406Sopenharmony_ci SANE_Status status; 711141cc406Sopenharmony_ci int i, j; 712141cc406Sopenharmony_ci 713141cc406Sopenharmony_ci memset (&cmd, 0, sizeof (cmd)); 714141cc406Sopenharmony_ci 715141cc406Sopenharmony_ci cmd.cmd = 0x80; 716141cc406Sopenharmony_ci 717141cc406Sopenharmony_ci set_size (cmd.tr_len, 3, sizeof (cmd.wd)); 718141cc406Sopenharmony_ci set_size (cmd.wd.nrrows, 2, rows); 719141cc406Sopenharmony_ci set_size (cmd.wd.nrrows, 2, cols); 720141cc406Sopenharmony_ci 721141cc406Sopenharmony_ci for (i = 0; i < cols; ++i) 722141cc406Sopenharmony_ci for (j = 0; j < rows; ++j) 723141cc406Sopenharmony_ci set_size (cmd.wd.element[j + i * rows].data, 2, dither_matrix[j + i * rows]); 724141cc406Sopenharmony_ci 725141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 0, 0); 726141cc406Sopenharmony_ci 727141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 728141cc406Sopenharmony_ci /* * Command failed * */ 729141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 730141cc406Sopenharmony_ci 731141cc406Sopenharmony_ci DBG (1, "upload_dither_matrix(): uploaded dither matrix\n"); 732141cc406Sopenharmony_ci 733141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 734141cc406Sopenharmony_ci} 735141cc406Sopenharmony_ci#endif 736141cc406Sopenharmony_ci 737141cc406Sopenharmony_ci/* May only be called when there is at least one row of data to 738141cc406Sopenharmony_ci be read. 739141cc406Sopenharmony_ci 740141cc406Sopenharmony_ci Original comment in German: Darf nur aufgerufen werden, wenn 741141cc406Sopenharmony_ci wirklich noch Zeilen zu scannen/lesen sind ! */ 742141cc406Sopenharmony_cistatic SANE_Status 743141cc406Sopenharmony_ciread_data (AgfaFocus_Scanner * s, SANE_Byte *buf, int lines, int bpl) 744141cc406Sopenharmony_ci{ 745141cc406Sopenharmony_ci struct { 746141cc406Sopenharmony_ci Byte cmd; 747141cc406Sopenharmony_ci Byte lun; 748141cc406Sopenharmony_ci Byte re1[4]; 749141cc406Sopenharmony_ci Byte tr_len[3]; 750141cc406Sopenharmony_ci Byte ctrl; 751141cc406Sopenharmony_ci } cmd; 752141cc406Sopenharmony_ci 753141cc406Sopenharmony_ci SANE_Status status; 754141cc406Sopenharmony_ci size_t size; 755141cc406Sopenharmony_ci unsigned int i; 756141cc406Sopenharmony_ci 757141cc406Sopenharmony_ci memset (&cmd, 0, sizeof (cmd)); 758141cc406Sopenharmony_ci 759141cc406Sopenharmony_ci cmd.cmd = 0x28; /* READ */ 760141cc406Sopenharmony_ci 761141cc406Sopenharmony_ci set_size (cmd.tr_len, 3, lines); 762141cc406Sopenharmony_ci size = lines * bpl; 763141cc406Sopenharmony_ci 764141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), buf, &size); 765141cc406Sopenharmony_ci 766141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 767141cc406Sopenharmony_ci { 768141cc406Sopenharmony_ci DBG (1, "sanei_scsi_cmd() = %d\n", status); 769141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 770141cc406Sopenharmony_ci } 771141cc406Sopenharmony_ci 772141cc406Sopenharmony_ci if (size != ((unsigned int) lines * bpl)) 773141cc406Sopenharmony_ci { 774141cc406Sopenharmony_ci DBG (1, "sanei_scsi_cmd(): got %lu bytes, expected %d\n", 775141cc406Sopenharmony_ci (u_long) size, lines * bpl); 776141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 777141cc406Sopenharmony_ci } 778141cc406Sopenharmony_ci 779141cc406Sopenharmony_ci DBG (1, "Got %lu bytes\n", (u_long) size); 780141cc406Sopenharmony_ci 781141cc406Sopenharmony_ci /* Reverse: */ 782141cc406Sopenharmony_ci if (s->bpp != 1) 783141cc406Sopenharmony_ci { 784141cc406Sopenharmony_ci if (s->bpp != 6) 785141cc406Sopenharmony_ci for (i = 0; i < size; i++) 786141cc406Sopenharmony_ci buf[i] = 255 - buf[i]; 787141cc406Sopenharmony_ci else 788141cc406Sopenharmony_ci for (i = 0; i < size; i++) 789141cc406Sopenharmony_ci buf[i] = 255 - ((buf[i] * 256.0f) / 64.0f); 790141cc406Sopenharmony_ci } 791141cc406Sopenharmony_ci 792141cc406Sopenharmony_ci s->lines_available -= lines; 793141cc406Sopenharmony_ci 794141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 795141cc406Sopenharmony_ci} 796141cc406Sopenharmony_ci 797141cc406Sopenharmony_ci 798141cc406Sopenharmony_cistatic SANE_Status 799141cc406Sopenharmony_ciattach (const char *devname, AgfaFocus_Device ** devp) 800141cc406Sopenharmony_ci{ 801141cc406Sopenharmony_ci#define ATTACH_SCSI_INQ_LEN 55 802141cc406Sopenharmony_ci const Byte scsi_inquiry[] = 803141cc406Sopenharmony_ci { 804141cc406Sopenharmony_ci 0x12, 0x00, 0x00, 0x00, ATTACH_SCSI_INQ_LEN, 0x00 805141cc406Sopenharmony_ci }; 806141cc406Sopenharmony_ci Byte result[ATTACH_SCSI_INQ_LEN]; 807141cc406Sopenharmony_ci 808141cc406Sopenharmony_ci int fd; 809141cc406Sopenharmony_ci AgfaFocus_Device *dev; 810141cc406Sopenharmony_ci SANE_Status status; 811141cc406Sopenharmony_ci size_t size; 812141cc406Sopenharmony_ci int i; 813141cc406Sopenharmony_ci 814141cc406Sopenharmony_ci for (dev = agfafocus_devices; dev; dev = dev->next) 815141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devname) == 0) 816141cc406Sopenharmony_ci { 817141cc406Sopenharmony_ci if (devp) 818141cc406Sopenharmony_ci *devp = dev; 819141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 820141cc406Sopenharmony_ci } 821141cc406Sopenharmony_ci 822141cc406Sopenharmony_ci DBG (3, "attach: opening %s\n", devname); 823141cc406Sopenharmony_ci status = sanei_scsi_open (devname, &fd, sense_handler, 0); 824141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 825141cc406Sopenharmony_ci { 826141cc406Sopenharmony_ci DBG (1, "attach: open failed (%s)\n", sane_strstatus (status)); 827141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 828141cc406Sopenharmony_ci } 829141cc406Sopenharmony_ci 830141cc406Sopenharmony_ci DBG (4, "attach: sending INQUIRY\n"); 831141cc406Sopenharmony_ci size = sizeof (result); 832141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, scsi_inquiry, sizeof (scsi_inquiry), 833141cc406Sopenharmony_ci result, &size); 834141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD || size != ATTACH_SCSI_INQ_LEN) 835141cc406Sopenharmony_ci { 836141cc406Sopenharmony_ci DBG (1, "attach: inquiry failed (%s)\n", sane_strstatus (status)); 837141cc406Sopenharmony_ci sanei_scsi_close (fd); 838141cc406Sopenharmony_ci return status; 839141cc406Sopenharmony_ci } 840141cc406Sopenharmony_ci 841141cc406Sopenharmony_ci status = test_ready (fd); 842141cc406Sopenharmony_ci sanei_scsi_close (fd); 843141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 844141cc406Sopenharmony_ci return status; 845141cc406Sopenharmony_ci 846141cc406Sopenharmony_ci /* The structure send by the scanner after inquiry is not SCSI-2 847141cc406Sopenharmony_ci compatible. The standard manufacturer/model fields are no ASCII 848141cc406Sopenharmony_ci strings, but ? At offset 36 my SIEMENS scanner identifies as an 849141cc406Sopenharmony_ci AGFA one ?! */ 850141cc406Sopenharmony_ci 851141cc406Sopenharmony_ci if (result[0] != 6 || strncmp ((char *)result + 36, "AGFA0", 5)) 852141cc406Sopenharmony_ci { 853141cc406Sopenharmony_ci DBG (1, "attach: device doesn't look like a Siemens 9036 scanner\n"); 854141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 855141cc406Sopenharmony_ci } 856141cc406Sopenharmony_ci 857141cc406Sopenharmony_ci DBG (4, "Inquiry data:\n"); 858141cc406Sopenharmony_ci DBG (4, "-----------\n"); 859141cc406Sopenharmony_ci for (i = 5; i < 55; i += 10) 860141cc406Sopenharmony_ci DBG (4, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 861141cc406Sopenharmony_ci result[i], result[i + 1], result[i + 2], result[i + 3], result[i + 4], 862141cc406Sopenharmony_ci result[i + 5], result[i + 6], result[i + 7], result[i + 8], 863141cc406Sopenharmony_ci result[i + 9]); 864141cc406Sopenharmony_ci 865141cc406Sopenharmony_ci dev = malloc (sizeof (*dev)); 866141cc406Sopenharmony_ci 867141cc406Sopenharmony_ci if (!dev) 868141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 869141cc406Sopenharmony_ci 870141cc406Sopenharmony_ci memset (dev, 0, sizeof (*dev)); 871141cc406Sopenharmony_ci 872141cc406Sopenharmony_ci dev->sane.name = strdup (devname); 873141cc406Sopenharmony_ci if (!strncmp ((char *)result + 36, "AGFA01", 6)) { 874141cc406Sopenharmony_ci dev->sane.vendor = "AGFA"; 875141cc406Sopenharmony_ci dev->sane.model = "Focus GS Scanner (6 bit)"; 876141cc406Sopenharmony_ci dev->upload_user_defines = SANE_TRUE; 877141cc406Sopenharmony_ci dev->type = AGFAGRAY64; 878141cc406Sopenharmony_ci } else if (!strncmp ((char *)result + 36, "AGFA02", 6)) { 879141cc406Sopenharmony_ci dev->sane.vendor = "AGFA"; 880141cc406Sopenharmony_ci dev->sane.model = "Focus Lineart Scanner"; 881141cc406Sopenharmony_ci dev->upload_user_defines = SANE_FALSE; 882141cc406Sopenharmony_ci dev->type = AGFALINEART; 883141cc406Sopenharmony_ci } else if (!strncmp ((char *)result + 36, "AGFA03", 6)) { 884141cc406Sopenharmony_ci dev->sane.vendor = "AGFA"; 885141cc406Sopenharmony_ci dev->sane.model = "Focus II"; 886141cc406Sopenharmony_ci dev->upload_user_defines = SANE_TRUE; 887141cc406Sopenharmony_ci dev->type = AGFAGRAY256; 888141cc406Sopenharmony_ci } else if (!strncmp ((char *)result + 36, "AGFA04", 6)) { 889141cc406Sopenharmony_ci dev->sane.vendor = "AGFA"; 890141cc406Sopenharmony_ci dev->sane.model = "Focus Color"; 891141cc406Sopenharmony_ci dev->upload_user_defines = SANE_TRUE; 892141cc406Sopenharmony_ci dev->type = AGFACOLOR; 893141cc406Sopenharmony_ci } else { 894141cc406Sopenharmony_ci free (dev); 895141cc406Sopenharmony_ci DBG (1, "attach: device looks like an AGFA scanner, but wasn't recognised\n"); 896141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 897141cc406Sopenharmony_ci } 898141cc406Sopenharmony_ci dev->sane.type = "flatbed scanner"; 899141cc406Sopenharmony_ci 900141cc406Sopenharmony_ci dev->transparent = result[45] & 0x80 ? SANE_TRUE : SANE_FALSE; 901141cc406Sopenharmony_ci dev->analoglog = result[46] & 0x80 ? SANE_TRUE : SANE_FALSE; 902141cc406Sopenharmony_ci dev->tos5 = result[46] & 0x05 ? SANE_TRUE : SANE_FALSE; 903141cc406Sopenharmony_ci dev->quality = result[47] & 0x40 ? SANE_TRUE : SANE_FALSE; 904141cc406Sopenharmony_ci dev->disconnect = result[47] & 0x80 ? SANE_TRUE : SANE_FALSE; 905141cc406Sopenharmony_ci 906141cc406Sopenharmony_ci DBG (4, "\n"); 907141cc406Sopenharmony_ci DBG (4, "scan modes:\n"); 908141cc406Sopenharmony_ci DBG (4, "-----------\n"); 909141cc406Sopenharmony_ci DBG (4, "three pass color mode: %s\n", dev->type >= AGFACOLOR ? "yes" : "no"); 910141cc406Sopenharmony_ci DBG (4, "8 bit gray mode: %s\n", dev->type >= AGFAGRAY64 ? "yes" : "no"); 911141cc406Sopenharmony_ci DBG (4, "uploadable matrices: %s\n", dev->upload_user_defines ? "yes" : "no"); 912141cc406Sopenharmony_ci DBG (4, "transparency: %s\n", dev->transparent ? "yes" : "no"); 913141cc406Sopenharmony_ci DBG (4, "disconnect: %s\n", dev->disconnect ? "yes" : "no"); 914141cc406Sopenharmony_ci DBG (4, "quality calibration: %s\n", dev->quality ? "yes" : "no"); 915141cc406Sopenharmony_ci 916141cc406Sopenharmony_ci dev->handle = 0; 917141cc406Sopenharmony_ci 918141cc406Sopenharmony_ci DBG (3, "attach: found AgfaFocus scanner model\n"); 919141cc406Sopenharmony_ci 920141cc406Sopenharmony_ci ++num_devices; 921141cc406Sopenharmony_ci dev->next = agfafocus_devices; 922141cc406Sopenharmony_ci agfafocus_devices = dev; 923141cc406Sopenharmony_ci 924141cc406Sopenharmony_ci if (devp) 925141cc406Sopenharmony_ci *devp = dev; 926141cc406Sopenharmony_ci 927141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 928141cc406Sopenharmony_ci} 929141cc406Sopenharmony_ci 930141cc406Sopenharmony_cistatic SANE_Status 931141cc406Sopenharmony_cido_eof (AgfaFocus_Scanner *s) 932141cc406Sopenharmony_ci{ 933141cc406Sopenharmony_ci if (s->pipe >= 0) 934141cc406Sopenharmony_ci { 935141cc406Sopenharmony_ci close (s->pipe); 936141cc406Sopenharmony_ci s->pipe = -1; 937141cc406Sopenharmony_ci } 938141cc406Sopenharmony_ci return SANE_STATUS_EOF; 939141cc406Sopenharmony_ci} 940141cc406Sopenharmony_ci 941141cc406Sopenharmony_ci 942141cc406Sopenharmony_cistatic SANE_Status 943141cc406Sopenharmony_cido_cancel (AgfaFocus_Scanner * s) 944141cc406Sopenharmony_ci{ 945141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 946141cc406Sopenharmony_ci s->pass = 0; 947141cc406Sopenharmony_ci 948141cc406Sopenharmony_ci do_eof (s); 949141cc406Sopenharmony_ci 950141cc406Sopenharmony_ci if (sanei_thread_is_valid (s->reader_pid)) 951141cc406Sopenharmony_ci { 952141cc406Sopenharmony_ci int exit_status; 953141cc406Sopenharmony_ci 954141cc406Sopenharmony_ci /* ensure child knows it's time to stop: */ 955141cc406Sopenharmony_ci sanei_thread_kill (s->reader_pid); 956141cc406Sopenharmony_ci sanei_thread_waitpid (s->reader_pid, &exit_status); 957141cc406Sopenharmony_ci sanei_thread_invalidate(s->reader_pid); 958141cc406Sopenharmony_ci } 959141cc406Sopenharmony_ci 960141cc406Sopenharmony_ci if (s->fd >= 0) 961141cc406Sopenharmony_ci { 962141cc406Sopenharmony_ci stop_scan (s->fd); 963141cc406Sopenharmony_ci release_unit (s->fd); 964141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 965141cc406Sopenharmony_ci s->fd = -1; 966141cc406Sopenharmony_ci } 967141cc406Sopenharmony_ci 968141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 969141cc406Sopenharmony_ci} 970141cc406Sopenharmony_ci 971141cc406Sopenharmony_ci 972141cc406Sopenharmony_cistatic SANE_Status 973141cc406Sopenharmony_ciinit_options (AgfaFocus_Scanner * s) 974141cc406Sopenharmony_ci{ 975141cc406Sopenharmony_ci int i; 976141cc406Sopenharmony_ci 977141cc406Sopenharmony_ci /* Hardware Limitations: must be static ! */ 978141cc406Sopenharmony_ci static const SANE_Int dpi_list[] = 979141cc406Sopenharmony_ci {8, 100, 200, 300, 400, 500, 600, 700, 800}; 980141cc406Sopenharmony_ci 981141cc406Sopenharmony_ci static const SANE_Range percentage_range = 982141cc406Sopenharmony_ci { 983141cc406Sopenharmony_ci SANE_FIX(-100), /* minimum */ 984141cc406Sopenharmony_ci SANE_FIX(100), /* maximum */ 985141cc406Sopenharmony_ci SANE_FIX(1) /* quantization */ 986141cc406Sopenharmony_ci }; 987141cc406Sopenharmony_ci 988141cc406Sopenharmony_ci static const SANE_Range sharpen_range = 989141cc406Sopenharmony_ci {0, 7, 1}; 990141cc406Sopenharmony_ci static const SANE_Range exposure_range = 991141cc406Sopenharmony_ci {0, 100, 0}; 992141cc406Sopenharmony_ci static const SANE_Range attenuation_range = 993141cc406Sopenharmony_ci { 994141cc406Sopenharmony_ci SANE_FIX(0), /* minimum */ 995141cc406Sopenharmony_ci SANE_FIX(100), /* maximum */ 996141cc406Sopenharmony_ci SANE_FIX(1) /* quantization */ 997141cc406Sopenharmony_ci }; 998141cc406Sopenharmony_ci 999141cc406Sopenharmony_ci 1000141cc406Sopenharmony_ci static const SANE_Range x_range = 1001141cc406Sopenharmony_ci {0, SANE_FIX (8.27 * MM_PER_INCH), 0}; 1002141cc406Sopenharmony_ci static const SANE_Range y_range = 1003141cc406Sopenharmony_ci {0, SANE_FIX (12.72 * MM_PER_INCH), 0}; 1004141cc406Sopenharmony_ci 1005141cc406Sopenharmony_ci /* ------ */ 1006141cc406Sopenharmony_ci 1007141cc406Sopenharmony_ci memset (s->opt, 0, sizeof (s->opt)); 1008141cc406Sopenharmony_ci memset (s->val, 0, sizeof (s->val)); 1009141cc406Sopenharmony_ci 1010141cc406Sopenharmony_ci for (i = 0; i < NUM_OPTIONS; ++i) 1011141cc406Sopenharmony_ci { 1012141cc406Sopenharmony_ci s->opt[i].size = sizeof (SANE_Word); 1013141cc406Sopenharmony_ci s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 1014141cc406Sopenharmony_ci } 1015141cc406Sopenharmony_ci 1016141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 1017141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 1018141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 1019141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 1020141cc406Sopenharmony_ci s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; 1021141cc406Sopenharmony_ci 1022141cc406Sopenharmony_ci /* "Mode" group: */ 1023141cc406Sopenharmony_ci 1024141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].title = "Scan Mode"; 1025141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].desc = ""; 1026141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 1027141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].cap = 0; 1028141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1029141cc406Sopenharmony_ci 1030141cc406Sopenharmony_ci /* scan mode */ 1031141cc406Sopenharmony_ci s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; 1032141cc406Sopenharmony_ci s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 1033141cc406Sopenharmony_ci s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 1034141cc406Sopenharmony_ci s->opt[OPT_MODE].type = SANE_TYPE_STRING; 1035141cc406Sopenharmony_ci 1036141cc406Sopenharmony_ci switch (s->hw->type) 1037141cc406Sopenharmony_ci { 1038141cc406Sopenharmony_ci case AGFACOLOR: 1039141cc406Sopenharmony_ci s->opt[OPT_MODE].size = max_string_size (focuscolor_mode_list); 1040141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint.string_list = focuscolor_mode_list; 1041141cc406Sopenharmony_ci s->val[OPT_MODE].s = strdup (focuscolor_mode_list[0]); 1042141cc406Sopenharmony_ci break; 1043141cc406Sopenharmony_ci case AGFAGRAY256: 1044141cc406Sopenharmony_ci s->opt[OPT_MODE].size = max_string_size (focusii_mode_list); 1045141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint.string_list = focusii_mode_list; 1046141cc406Sopenharmony_ci s->val[OPT_MODE].s = strdup (focusii_mode_list[0]); 1047141cc406Sopenharmony_ci break; 1048141cc406Sopenharmony_ci default: 1049141cc406Sopenharmony_ci s->opt[OPT_MODE].size = max_string_size (focus_mode_list); 1050141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint.string_list = focus_mode_list; 1051141cc406Sopenharmony_ci s->val[OPT_MODE].s = strdup (focus_mode_list[0]); 1052141cc406Sopenharmony_ci break; 1053141cc406Sopenharmony_ci } 1054141cc406Sopenharmony_ci 1055141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1056141cc406Sopenharmony_ci 1057141cc406Sopenharmony_ci /* resolution */ 1058141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 1059141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 1060141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 1061141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; 1062141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 1063141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; 1064141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].constraint.word_list = dpi_list; 1065141cc406Sopenharmony_ci s->val[OPT_RESOLUTION].w = 100; 1066141cc406Sopenharmony_ci 1067141cc406Sopenharmony_ci s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; 1068141cc406Sopenharmony_ci s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; 1069141cc406Sopenharmony_ci s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; 1070141cc406Sopenharmony_ci s->opt[OPT_SOURCE].type = SANE_TYPE_STRING; 1071141cc406Sopenharmony_ci s->opt[OPT_SOURCE].unit = SANE_UNIT_NONE; 1072141cc406Sopenharmony_ci if (!s->hw->transparent) 1073141cc406Sopenharmony_ci s->opt[OPT_SOURCE].cap |= SANE_CAP_INACTIVE; 1074141cc406Sopenharmony_ci else 1075141cc406Sopenharmony_ci s->opt[OPT_SOURCE].cap &= ~SANE_CAP_INACTIVE; 1076141cc406Sopenharmony_ci s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1077141cc406Sopenharmony_ci s->opt[OPT_SOURCE].constraint.string_list = source_list; 1078141cc406Sopenharmony_ci s->opt[OPT_SOURCE].size = max_string_size (source_list); 1079141cc406Sopenharmony_ci s->val[OPT_SOURCE].s = strdup (source_list[0]); 1080141cc406Sopenharmony_ci 1081141cc406Sopenharmony_ci /* "Geometry" group: */ 1082141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; 1083141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].desc = ""; 1084141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 1085141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; 1086141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1087141cc406Sopenharmony_ci 1088141cc406Sopenharmony_ci /* top-left x */ 1089141cc406Sopenharmony_ci s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 1090141cc406Sopenharmony_ci s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 1091141cc406Sopenharmony_ci s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 1092141cc406Sopenharmony_ci s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; 1093141cc406Sopenharmony_ci s->opt[OPT_TL_X].unit = SANE_UNIT_MM; 1094141cc406Sopenharmony_ci s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 1095141cc406Sopenharmony_ci s->opt[OPT_TL_X].constraint.range = &x_range; 1096141cc406Sopenharmony_ci s->val[OPT_TL_X].w = 0; 1097141cc406Sopenharmony_ci 1098141cc406Sopenharmony_ci /* top-left y */ 1099141cc406Sopenharmony_ci s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 1100141cc406Sopenharmony_ci s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 1101141cc406Sopenharmony_ci s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 1102141cc406Sopenharmony_ci s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; 1103141cc406Sopenharmony_ci s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; 1104141cc406Sopenharmony_ci s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 1105141cc406Sopenharmony_ci s->opt[OPT_TL_Y].constraint.range = &y_range; 1106141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = 0; 1107141cc406Sopenharmony_ci 1108141cc406Sopenharmony_ci /* bottom-right x */ 1109141cc406Sopenharmony_ci s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 1110141cc406Sopenharmony_ci s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 1111141cc406Sopenharmony_ci s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 1112141cc406Sopenharmony_ci s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; 1113141cc406Sopenharmony_ci s->opt[OPT_BR_X].unit = SANE_UNIT_MM; 1114141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 1115141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint.range = &x_range; 1116141cc406Sopenharmony_ci s->val[OPT_BR_X].w = x_range.max; 1117141cc406Sopenharmony_ci 1118141cc406Sopenharmony_ci /* bottom-right y */ 1119141cc406Sopenharmony_ci s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 1120141cc406Sopenharmony_ci s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 1121141cc406Sopenharmony_ci s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 1122141cc406Sopenharmony_ci s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; 1123141cc406Sopenharmony_ci s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; 1124141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 1125141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint.range = &y_range; 1126141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = y_range.max; 1127141cc406Sopenharmony_ci 1128141cc406Sopenharmony_ci /* "Enhancement" group: */ 1129141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; 1130141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; 1131141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; 1132141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; 1133141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1134141cc406Sopenharmony_ci 1135141cc406Sopenharmony_ci /* exposure */ 1136141cc406Sopenharmony_ci s->opt[OPT_EXPOSURE].name = "exposure"; 1137141cc406Sopenharmony_ci s->opt[OPT_EXPOSURE].title = "Exposure"; 1138141cc406Sopenharmony_ci s->opt[OPT_EXPOSURE].desc = "Analog exposure control."; 1139141cc406Sopenharmony_ci s->opt[OPT_EXPOSURE].type = SANE_TYPE_INT; 1140141cc406Sopenharmony_ci s->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; 1141141cc406Sopenharmony_ci s->opt[OPT_EXPOSURE].unit = SANE_UNIT_PERCENT; 1142141cc406Sopenharmony_ci s->opt[OPT_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE; 1143141cc406Sopenharmony_ci s->opt[OPT_EXPOSURE].constraint.range = &exposure_range; 1144141cc406Sopenharmony_ci s->val[OPT_EXPOSURE].w = 23; 1145141cc406Sopenharmony_ci 1146141cc406Sopenharmony_ci /* brightness automatic correct */ 1147141cc406Sopenharmony_ci s->opt[OPT_AUTO_BRIGHTNESS].name = "adjust-bright"; 1148141cc406Sopenharmony_ci s->opt[OPT_AUTO_BRIGHTNESS].title = "Automatic brightness correction"; 1149141cc406Sopenharmony_ci s->opt[OPT_AUTO_BRIGHTNESS].desc = "Turns on automatic brightness correction of " 1150141cc406Sopenharmony_ci "the acquired image. This makes the scanner do a two pass scan to analyse the " 1151141cc406Sopenharmony_ci "brightness of the image before it's scanned."; 1152141cc406Sopenharmony_ci s->opt[OPT_AUTO_BRIGHTNESS].type = SANE_TYPE_BOOL; 1153141cc406Sopenharmony_ci s->val[OPT_AUTO_BRIGHTNESS].b = SANE_FALSE; 1154141cc406Sopenharmony_ci 1155141cc406Sopenharmony_ci /* contrast automatic correct */ 1156141cc406Sopenharmony_ci s->opt[OPT_AUTO_CONTRAST].name = "adjust-contr"; 1157141cc406Sopenharmony_ci s->opt[OPT_AUTO_CONTRAST].title = "Automatic contrast correction"; 1158141cc406Sopenharmony_ci s->opt[OPT_AUTO_CONTRAST].desc = "Turns on automatic contrast correction of " 1159141cc406Sopenharmony_ci "the acquired image. This makes the scanner do a two pass scan to analyse " 1160141cc406Sopenharmony_ci "the contrast of the image to be scanned."; 1161141cc406Sopenharmony_ci s->opt[OPT_AUTO_CONTRAST].type = SANE_TYPE_BOOL; 1162141cc406Sopenharmony_ci s->val[OPT_AUTO_CONTRAST].b = SANE_FALSE; 1163141cc406Sopenharmony_ci 1164141cc406Sopenharmony_ci /* brightness */ 1165141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; 1166141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; 1167141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].desc = "Controls the brightness of the acquired image. " 1168141cc406Sopenharmony_ci "When automatic brightness is enabled, this can be used to adjust the selected brightness."; 1169141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED; 1170141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT; 1171141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; 1172141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].constraint.range = &percentage_range; 1173141cc406Sopenharmony_ci s->val[OPT_BRIGHTNESS].w = 0; 1174141cc406Sopenharmony_ci 1175141cc406Sopenharmony_ci /* contrast */ 1176141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; 1177141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; 1178141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].desc = "Controls the contrast of the acquired image. " 1179141cc406Sopenharmony_ci "When automatic contrast is enabled, this can be used to adjust the selected contrast."; 1180141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].type = SANE_TYPE_FIXED; 1181141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].unit = SANE_UNIT_PERCENT; 1182141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; 1183141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].constraint.range = &percentage_range; 1184141cc406Sopenharmony_ci s->val[OPT_CONTRAST].w = 0; 1185141cc406Sopenharmony_ci 1186141cc406Sopenharmony_ci /* halftone patterns */ 1187141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; 1188141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; 1189141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; 1190141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING; 1191141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].size = 32; 1192141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1193141cc406Sopenharmony_ci if (s->hw->upload_user_defines) 1194141cc406Sopenharmony_ci { 1195141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].constraint.string_list = halftone_upload_list; 1196141cc406Sopenharmony_ci s->val[OPT_HALFTONE_PATTERN].s = strdup (halftone_upload_list[0]); 1197141cc406Sopenharmony_ci } 1198141cc406Sopenharmony_ci else 1199141cc406Sopenharmony_ci { 1200141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].constraint.string_list = halftone_list; 1201141cc406Sopenharmony_ci s->val[OPT_HALFTONE_PATTERN].s = strdup (halftone_list[0]); 1202141cc406Sopenharmony_ci } 1203141cc406Sopenharmony_ci 1204141cc406Sopenharmony_ci /* red-attenuation */ 1205141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_RED].name = "red-attenuation"; 1206141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_RED].title = "Red attenuation"; 1207141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_RED].desc = "Controls the red attenuation of the acquired image. " 1208141cc406Sopenharmony_ci "Higher values mean less impact on scanned image."; 1209141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_RED].type = SANE_TYPE_FIXED; 1210141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_RED].cap |= SANE_CAP_INACTIVE; 1211141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_RED].unit = SANE_UNIT_PERCENT; 1212141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_RED].constraint_type = SANE_CONSTRAINT_RANGE; 1213141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_RED].constraint.range = &attenuation_range; 1214141cc406Sopenharmony_ci s->val[OPT_ATTENUATION_RED].w = SANE_FIX (50.0); 1215141cc406Sopenharmony_ci 1216141cc406Sopenharmony_ci /* green-attenuation */ 1217141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_GREEN].name = "green-attenuation"; 1218141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_GREEN].title = "Green attenuation"; 1219141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_GREEN].desc = "Controls the green attenuation of the acquired image. " 1220141cc406Sopenharmony_ci "Higher values mean less impact on scanned image."; 1221141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_GREEN].type = SANE_TYPE_FIXED; 1222141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_GREEN].cap |= SANE_CAP_INACTIVE; 1223141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_GREEN].unit = SANE_UNIT_PERCENT; 1224141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_GREEN].constraint_type = SANE_CONSTRAINT_RANGE; 1225141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_GREEN].constraint.range = &attenuation_range; 1226141cc406Sopenharmony_ci s->val[OPT_ATTENUATION_GREEN].w = SANE_FIX (50.0); 1227141cc406Sopenharmony_ci 1228141cc406Sopenharmony_ci /* blue-attenuation */ 1229141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_BLUE].name = "blue-attenuation"; 1230141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_BLUE].title = "Blue attenuation"; 1231141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_BLUE].desc = "Controls the blue attenuation of the acquired image. " 1232141cc406Sopenharmony_ci "Higher values mean less impact on scanned image."; 1233141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_BLUE].type = SANE_TYPE_FIXED; 1234141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_BLUE].cap |= SANE_CAP_INACTIVE; 1235141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_BLUE].unit = SANE_UNIT_PERCENT; 1236141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_BLUE].constraint_type = SANE_CONSTRAINT_RANGE; 1237141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_BLUE].constraint.range = &attenuation_range; 1238141cc406Sopenharmony_ci s->val[OPT_ATTENUATION_BLUE].w = SANE_FIX (50.0); 1239141cc406Sopenharmony_ci 1240141cc406Sopenharmony_ci /* quality-calibration */ 1241141cc406Sopenharmony_ci s->opt[OPT_QUALITY].name = SANE_NAME_QUALITY_CAL; 1242141cc406Sopenharmony_ci s->opt[OPT_QUALITY].title = SANE_TITLE_QUALITY_CAL; 1243141cc406Sopenharmony_ci s->opt[OPT_QUALITY].desc = "Controls the calibration that will be done in the " 1244141cc406Sopenharmony_ci "scanner. Less calibration result in faster scanner times."; 1245141cc406Sopenharmony_ci s->opt[OPT_QUALITY].type = SANE_TYPE_STRING; 1246141cc406Sopenharmony_ci s->opt[OPT_QUALITY].size = 32; 1247141cc406Sopenharmony_ci if (!s->hw->quality) 1248141cc406Sopenharmony_ci s->opt[OPT_QUALITY].cap |= SANE_CAP_INACTIVE; 1249141cc406Sopenharmony_ci else 1250141cc406Sopenharmony_ci s->opt[OPT_QUALITY].cap &= ~SANE_CAP_INACTIVE; 1251141cc406Sopenharmony_ci s->opt[OPT_QUALITY].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1252141cc406Sopenharmony_ci s->opt[OPT_QUALITY].constraint.string_list = quality_list; 1253141cc406Sopenharmony_ci s->val[OPT_QUALITY].s = strdup (quality_list[1]); 1254141cc406Sopenharmony_ci 1255141cc406Sopenharmony_ci /* sharpening */ 1256141cc406Sopenharmony_ci s->opt[OPT_SHARPEN].name = "sharpen"; 1257141cc406Sopenharmony_ci s->opt[OPT_SHARPEN].title = "Sharpening"; 1258141cc406Sopenharmony_ci s->opt[OPT_SHARPEN].desc = "Controls the sharpening that will be " 1259141cc406Sopenharmony_ci "done by the video processor in the scanner."; 1260141cc406Sopenharmony_ci s->opt[OPT_SHARPEN].type = SANE_TYPE_INT; 1261141cc406Sopenharmony_ci s->opt[OPT_SHARPEN].unit = SANE_UNIT_NONE; 1262141cc406Sopenharmony_ci s->opt[OPT_SHARPEN].constraint_type = SANE_CONSTRAINT_RANGE; 1263141cc406Sopenharmony_ci s->opt[OPT_SHARPEN].constraint.range = &sharpen_range; 1264141cc406Sopenharmony_ci s->val[OPT_SHARPEN].w = 1; 1265141cc406Sopenharmony_ci 1266141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1267141cc406Sopenharmony_ci} 1268141cc406Sopenharmony_ci 1269141cc406Sopenharmony_cistatic SANE_Status 1270141cc406Sopenharmony_ciattach_one (const char *dev) 1271141cc406Sopenharmony_ci{ 1272141cc406Sopenharmony_ci attach (dev, 0); 1273141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1274141cc406Sopenharmony_ci} 1275141cc406Sopenharmony_ci 1276141cc406Sopenharmony_ciSANE_Status 1277141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) 1278141cc406Sopenharmony_ci{ 1279141cc406Sopenharmony_ci char dev_name[PATH_MAX]; 1280141cc406Sopenharmony_ci size_t len; 1281141cc406Sopenharmony_ci FILE *fp; 1282141cc406Sopenharmony_ci 1283141cc406Sopenharmony_ci (void) authorize; /* silence gcc */ 1284141cc406Sopenharmony_ci 1285141cc406Sopenharmony_ci DBG_INIT (); 1286141cc406Sopenharmony_ci 1287141cc406Sopenharmony_ci sanei_thread_init (); 1288141cc406Sopenharmony_ci 1289141cc406Sopenharmony_ci if (version_code) 1290141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0); 1291141cc406Sopenharmony_ci 1292141cc406Sopenharmony_ci fp = sanei_config_open ("agfafocus.conf"); 1293141cc406Sopenharmony_ci if (!fp) 1294141cc406Sopenharmony_ci { 1295141cc406Sopenharmony_ci /* default to /dev/scanner instead of insisting on config file */ 1296141cc406Sopenharmony_ci attach ("/dev/scanner", 0); 1297141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1298141cc406Sopenharmony_ci } 1299141cc406Sopenharmony_ci 1300141cc406Sopenharmony_ci while (sanei_config_read (dev_name, sizeof (dev_name), fp)) 1301141cc406Sopenharmony_ci { 1302141cc406Sopenharmony_ci if (dev_name[0] == '#') /* ignore line comments */ 1303141cc406Sopenharmony_ci continue; 1304141cc406Sopenharmony_ci len = strlen (dev_name); 1305141cc406Sopenharmony_ci 1306141cc406Sopenharmony_ci if (!len) 1307141cc406Sopenharmony_ci continue; /* ignore empty lines */ 1308141cc406Sopenharmony_ci 1309141cc406Sopenharmony_ci sanei_config_attach_matching_devices (dev_name, attach_one); 1310141cc406Sopenharmony_ci } 1311141cc406Sopenharmony_ci fclose (fp); 1312141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1313141cc406Sopenharmony_ci} 1314141cc406Sopenharmony_ci 1315141cc406Sopenharmony_civoid 1316141cc406Sopenharmony_cisane_exit (void) 1317141cc406Sopenharmony_ci{ 1318141cc406Sopenharmony_ci AgfaFocus_Device *dev, *next; 1319141cc406Sopenharmony_ci 1320141cc406Sopenharmony_ci for (dev = agfafocus_devices; dev; dev = next) 1321141cc406Sopenharmony_ci { 1322141cc406Sopenharmony_ci next = dev->next; 1323141cc406Sopenharmony_ci if (dev->handle) 1324141cc406Sopenharmony_ci sane_close (dev->handle); 1325141cc406Sopenharmony_ci free (dev); 1326141cc406Sopenharmony_ci } 1327141cc406Sopenharmony_ci 1328141cc406Sopenharmony_ci if (devlist) 1329141cc406Sopenharmony_ci free (devlist); 1330141cc406Sopenharmony_ci} 1331141cc406Sopenharmony_ci 1332141cc406Sopenharmony_ciSANE_Status 1333141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) 1334141cc406Sopenharmony_ci{ 1335141cc406Sopenharmony_ci AgfaFocus_Device *dev; 1336141cc406Sopenharmony_ci int i; 1337141cc406Sopenharmony_ci 1338141cc406Sopenharmony_ci (void) local_only; /* silence gcc */ 1339141cc406Sopenharmony_ci 1340141cc406Sopenharmony_ci if (devlist) 1341141cc406Sopenharmony_ci free (devlist); 1342141cc406Sopenharmony_ci 1343141cc406Sopenharmony_ci devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); 1344141cc406Sopenharmony_ci if (!devlist) 1345141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1346141cc406Sopenharmony_ci 1347141cc406Sopenharmony_ci for (dev = agfafocus_devices, i = 0; i < num_devices; dev = dev->next) 1348141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 1349141cc406Sopenharmony_ci devlist[i++] = 0; 1350141cc406Sopenharmony_ci 1351141cc406Sopenharmony_ci *device_list = devlist; 1352141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1353141cc406Sopenharmony_ci} 1354141cc406Sopenharmony_ci 1355141cc406Sopenharmony_ciSANE_Status 1356141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 1357141cc406Sopenharmony_ci{ 1358141cc406Sopenharmony_ci AgfaFocus_Device *dev; 1359141cc406Sopenharmony_ci SANE_Status status; 1360141cc406Sopenharmony_ci AgfaFocus_Scanner *s; 1361141cc406Sopenharmony_ci 1362141cc406Sopenharmony_ci if (devicename[0]) 1363141cc406Sopenharmony_ci { 1364141cc406Sopenharmony_ci status = attach (devicename, &dev); 1365141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1366141cc406Sopenharmony_ci return status; 1367141cc406Sopenharmony_ci } 1368141cc406Sopenharmony_ci else 1369141cc406Sopenharmony_ci { 1370141cc406Sopenharmony_ci /* empty devicname -> use first device */ 1371141cc406Sopenharmony_ci dev = agfafocus_devices; 1372141cc406Sopenharmony_ci } 1373141cc406Sopenharmony_ci 1374141cc406Sopenharmony_ci if (!dev) 1375141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1376141cc406Sopenharmony_ci 1377141cc406Sopenharmony_ci if (dev->handle) 1378141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1379141cc406Sopenharmony_ci 1380141cc406Sopenharmony_ci s = malloc (sizeof (*s)); 1381141cc406Sopenharmony_ci if (!s) 1382141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1383141cc406Sopenharmony_ci 1384141cc406Sopenharmony_ci memset (s, 0, sizeof (*s)); 1385141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 1386141cc406Sopenharmony_ci 1387141cc406Sopenharmony_ci s->fd = -1; 1388141cc406Sopenharmony_ci s->hw = dev; 1389141cc406Sopenharmony_ci s->hw->handle = s; 1390141cc406Sopenharmony_ci 1391141cc406Sopenharmony_ci init_options (s); 1392141cc406Sopenharmony_ci 1393141cc406Sopenharmony_ci *handle = s; 1394141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1395141cc406Sopenharmony_ci} 1396141cc406Sopenharmony_ci 1397141cc406Sopenharmony_civoid 1398141cc406Sopenharmony_cisane_close (SANE_Handle handle) 1399141cc406Sopenharmony_ci{ 1400141cc406Sopenharmony_ci AgfaFocus_Scanner *s = handle; 1401141cc406Sopenharmony_ci 1402141cc406Sopenharmony_ci if (s->scanning) 1403141cc406Sopenharmony_ci do_cancel (handle); 1404141cc406Sopenharmony_ci 1405141cc406Sopenharmony_ci s->hw->handle = 0; 1406141cc406Sopenharmony_ci 1407141cc406Sopenharmony_ci free (handle); 1408141cc406Sopenharmony_ci} 1409141cc406Sopenharmony_ci 1410141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 1411141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 1412141cc406Sopenharmony_ci{ 1413141cc406Sopenharmony_ci AgfaFocus_Scanner *s = handle; 1414141cc406Sopenharmony_ci 1415141cc406Sopenharmony_ci if ((unsigned) option >= NUM_OPTIONS) 1416141cc406Sopenharmony_ci return 0; 1417141cc406Sopenharmony_ci return s->opt + option; 1418141cc406Sopenharmony_ci} 1419141cc406Sopenharmony_ci 1420141cc406Sopenharmony_ciSANE_Status 1421141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 1422141cc406Sopenharmony_ci SANE_Action action, void *val, SANE_Int * info) 1423141cc406Sopenharmony_ci{ 1424141cc406Sopenharmony_ci AgfaFocus_Scanner *s = handle; 1425141cc406Sopenharmony_ci SANE_Status status; 1426141cc406Sopenharmony_ci 1427141cc406Sopenharmony_ci if (info) 1428141cc406Sopenharmony_ci *info = 0; 1429141cc406Sopenharmony_ci 1430141cc406Sopenharmony_ci if (s->scanning) 1431141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1432141cc406Sopenharmony_ci 1433141cc406Sopenharmony_ci if (option >= NUM_OPTIONS || !SANE_OPTION_IS_ACTIVE (s->opt[option].cap)) 1434141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1435141cc406Sopenharmony_ci 1436141cc406Sopenharmony_ci if (action == SANE_ACTION_GET_VALUE) 1437141cc406Sopenharmony_ci { 1438141cc406Sopenharmony_ci switch (option) 1439141cc406Sopenharmony_ci { 1440141cc406Sopenharmony_ci case OPT_RESOLUTION: 1441141cc406Sopenharmony_ci case OPT_TL_X: 1442141cc406Sopenharmony_ci case OPT_TL_Y: 1443141cc406Sopenharmony_ci case OPT_BR_X: 1444141cc406Sopenharmony_ci case OPT_BR_Y: 1445141cc406Sopenharmony_ci case OPT_NUM_OPTS: 1446141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 1447141cc406Sopenharmony_ci case OPT_CONTRAST: 1448141cc406Sopenharmony_ci case OPT_SHARPEN: 1449141cc406Sopenharmony_ci case OPT_EXPOSURE: 1450141cc406Sopenharmony_ci case OPT_ATTENUATION_RED: 1451141cc406Sopenharmony_ci case OPT_ATTENUATION_GREEN: 1452141cc406Sopenharmony_ci case OPT_ATTENUATION_BLUE: 1453141cc406Sopenharmony_ci *(SANE_Word *) val = s->val[option].w; 1454141cc406Sopenharmony_ci break; 1455141cc406Sopenharmony_ci case OPT_AUTO_BRIGHTNESS: 1456141cc406Sopenharmony_ci case OPT_AUTO_CONTRAST: 1457141cc406Sopenharmony_ci *(SANE_Bool *) val = s->val[option].b; 1458141cc406Sopenharmony_ci break; 1459141cc406Sopenharmony_ci case OPT_MODE: 1460141cc406Sopenharmony_ci case OPT_HALFTONE_PATTERN: 1461141cc406Sopenharmony_ci case OPT_QUALITY: 1462141cc406Sopenharmony_ci case OPT_SOURCE: 1463141cc406Sopenharmony_ci strcpy (val, s->val[option].s); 1464141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 1465141cc406Sopenharmony_ci default: 1466141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1467141cc406Sopenharmony_ci } 1468141cc406Sopenharmony_ci 1469141cc406Sopenharmony_ci } 1470141cc406Sopenharmony_ci else if (action == SANE_ACTION_SET_VALUE) 1471141cc406Sopenharmony_ci { 1472141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (s->opt[option].cap)) 1473141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1474141cc406Sopenharmony_ci 1475141cc406Sopenharmony_ci status = sanei_constrain_value (s->opt + option, val, info); 1476141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1477141cc406Sopenharmony_ci return status; 1478141cc406Sopenharmony_ci 1479141cc406Sopenharmony_ci switch (option) 1480141cc406Sopenharmony_ci { 1481141cc406Sopenharmony_ci case OPT_RESOLUTION: 1482141cc406Sopenharmony_ci case OPT_TL_X: 1483141cc406Sopenharmony_ci case OPT_TL_Y: 1484141cc406Sopenharmony_ci case OPT_BR_X: 1485141cc406Sopenharmony_ci case OPT_BR_Y: 1486141cc406Sopenharmony_ci if (info) 1487141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 1488141cc406Sopenharmony_ci // fall through 1489141cc406Sopenharmony_ci case OPT_SHARPEN: 1490141cc406Sopenharmony_ci case OPT_EXPOSURE: 1491141cc406Sopenharmony_ci case OPT_ATTENUATION_RED: 1492141cc406Sopenharmony_ci case OPT_ATTENUATION_GREEN: 1493141cc406Sopenharmony_ci case OPT_ATTENUATION_BLUE: 1494141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 1495141cc406Sopenharmony_ci case OPT_CONTRAST: 1496141cc406Sopenharmony_ci s->val[option].w = *(SANE_Word *) val; 1497141cc406Sopenharmony_ci break; 1498141cc406Sopenharmony_ci case OPT_AUTO_BRIGHTNESS: 1499141cc406Sopenharmony_ci case OPT_AUTO_CONTRAST: 1500141cc406Sopenharmony_ci s->val[option].b = *(SANE_Bool *) val; 1501141cc406Sopenharmony_ci break; 1502141cc406Sopenharmony_ci case OPT_MODE: 1503141cc406Sopenharmony_ci if (strcmp (s->val[option].s, (SANE_String) val)) 1504141cc406Sopenharmony_ci { 1505141cc406Sopenharmony_ci if (info) 1506141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 1507141cc406Sopenharmony_ci 1508141cc406Sopenharmony_ci if (s->val[option].s) 1509141cc406Sopenharmony_ci free (s->val[option].s); 1510141cc406Sopenharmony_ci 1511141cc406Sopenharmony_ci s->val[option].s = strdup (val); 1512141cc406Sopenharmony_ci 1513141cc406Sopenharmony_ci if (strcmp (s->val[option].s, "Gray (6 bit)") == 0) 1514141cc406Sopenharmony_ci s->mode = GRAY6BIT; 1515141cc406Sopenharmony_ci else if (strcmp (s->val[option].s, "Gray (8 bit)") == 0) 1516141cc406Sopenharmony_ci s->mode = GRAY8BIT; 1517141cc406Sopenharmony_ci else if (strcmp (s->val[option].s, "Color (18 bit)") == 0) 1518141cc406Sopenharmony_ci s->mode = COLOR18BIT; 1519141cc406Sopenharmony_ci else if (strcmp (s->val[option].s, "Color (24 bit)") == 0) 1520141cc406Sopenharmony_ci s->mode = COLOR24BIT; 1521141cc406Sopenharmony_ci else 1522141cc406Sopenharmony_ci s->mode = LINEART; 1523141cc406Sopenharmony_ci 1524141cc406Sopenharmony_ci switch (s->mode) 1525141cc406Sopenharmony_ci { 1526141cc406Sopenharmony_ci case LINEART: 1527141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; 1528141cc406Sopenharmony_ci s->opt[OPT_SHARPEN].cap &= ~SANE_CAP_INACTIVE; 1529141cc406Sopenharmony_ci s->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; 1530141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_RED].cap |= SANE_CAP_INACTIVE; 1531141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_GREEN].cap |= SANE_CAP_INACTIVE; 1532141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_BLUE].cap |= SANE_CAP_INACTIVE; 1533141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; 1534141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; 1535141cc406Sopenharmony_ci s->opt[OPT_AUTO_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; 1536141cc406Sopenharmony_ci s->opt[OPT_AUTO_CONTRAST].cap &= ~SANE_CAP_INACTIVE; 1537141cc406Sopenharmony_ci break; 1538141cc406Sopenharmony_ci 1539141cc406Sopenharmony_ci case GRAY6BIT: 1540141cc406Sopenharmony_ci s->opt[OPT_SHARPEN].cap &= ~SANE_CAP_INACTIVE; 1541141cc406Sopenharmony_ci s->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; 1542141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_RED].cap |= SANE_CAP_INACTIVE; 1543141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_GREEN].cap |= SANE_CAP_INACTIVE; 1544141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_BLUE].cap |= SANE_CAP_INACTIVE; 1545141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; 1546141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; 1547141cc406Sopenharmony_ci s->opt[OPT_AUTO_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; 1548141cc406Sopenharmony_ci s->opt[OPT_AUTO_CONTRAST].cap &= ~SANE_CAP_INACTIVE; 1549141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; 1550141cc406Sopenharmony_ci break; 1551141cc406Sopenharmony_ci 1552141cc406Sopenharmony_ci case GRAY8BIT: 1553141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; 1554141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; 1555141cc406Sopenharmony_ci s->opt[OPT_AUTO_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; 1556141cc406Sopenharmony_ci s->opt[OPT_AUTO_CONTRAST].cap &= ~SANE_CAP_INACTIVE; 1557141cc406Sopenharmony_ci s->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; 1558141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_RED].cap |= SANE_CAP_INACTIVE; 1559141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_GREEN].cap |= SANE_CAP_INACTIVE; 1560141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_BLUE].cap |= SANE_CAP_INACTIVE; 1561141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; 1562141cc406Sopenharmony_ci s->opt[OPT_SHARPEN].cap |= SANE_CAP_INACTIVE; 1563141cc406Sopenharmony_ci break; 1564141cc406Sopenharmony_ci 1565141cc406Sopenharmony_ci case COLOR18BIT: 1566141cc406Sopenharmony_ci s->opt[OPT_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; 1567141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_RED].cap &= ~SANE_CAP_INACTIVE; 1568141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_GREEN].cap &= ~SANE_CAP_INACTIVE; 1569141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_BLUE].cap &= ~SANE_CAP_INACTIVE; 1570141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 1571141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; 1572141cc406Sopenharmony_ci s->opt[OPT_AUTO_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 1573141cc406Sopenharmony_ci s->opt[OPT_AUTO_CONTRAST].cap |= SANE_CAP_INACTIVE; 1574141cc406Sopenharmony_ci s->opt[OPT_SHARPEN].cap &= ~SANE_CAP_INACTIVE; 1575141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; 1576141cc406Sopenharmony_ci break; 1577141cc406Sopenharmony_ci 1578141cc406Sopenharmony_ci case COLOR24BIT: 1579141cc406Sopenharmony_ci s->opt[OPT_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; 1580141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_RED].cap &= ~SANE_CAP_INACTIVE; 1581141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_GREEN].cap &= ~SANE_CAP_INACTIVE; 1582141cc406Sopenharmony_ci s->opt[OPT_ATTENUATION_BLUE].cap &= ~SANE_CAP_INACTIVE; 1583141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 1584141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; 1585141cc406Sopenharmony_ci s->opt[OPT_AUTO_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 1586141cc406Sopenharmony_ci s->opt[OPT_AUTO_CONTRAST].cap |= SANE_CAP_INACTIVE; 1587141cc406Sopenharmony_ci s->opt[OPT_SHARPEN].cap |= SANE_CAP_INACTIVE; 1588141cc406Sopenharmony_ci s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; 1589141cc406Sopenharmony_ci break; 1590141cc406Sopenharmony_ci } 1591141cc406Sopenharmony_ci } 1592141cc406Sopenharmony_ci break; 1593141cc406Sopenharmony_ci case OPT_SOURCE: 1594141cc406Sopenharmony_ci case OPT_QUALITY: 1595141cc406Sopenharmony_ci case OPT_HALFTONE_PATTERN: 1596141cc406Sopenharmony_ci if (info && strcmp (s->val[option].s, (SANE_String) val)) 1597141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 1598141cc406Sopenharmony_ci if (s->val[option].s) 1599141cc406Sopenharmony_ci free (s->val[option].s); 1600141cc406Sopenharmony_ci s->val[option].s = strdup (val); 1601141cc406Sopenharmony_ci break; 1602141cc406Sopenharmony_ci default: 1603141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1604141cc406Sopenharmony_ci } 1605141cc406Sopenharmony_ci 1606141cc406Sopenharmony_ci } 1607141cc406Sopenharmony_ci else 1608141cc406Sopenharmony_ci { 1609141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1610141cc406Sopenharmony_ci } 1611141cc406Sopenharmony_ci 1612141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1613141cc406Sopenharmony_ci} 1614141cc406Sopenharmony_ci 1615141cc406Sopenharmony_ciSANE_Status 1616141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 1617141cc406Sopenharmony_ci{ 1618141cc406Sopenharmony_ci AgfaFocus_Scanner *s = handle; 1619141cc406Sopenharmony_ci 1620141cc406Sopenharmony_ci if (!s->scanning) 1621141cc406Sopenharmony_ci { 1622141cc406Sopenharmony_ci double width, height, dpi; 1623141cc406Sopenharmony_ci const char *quality; 1624141cc406Sopenharmony_ci const char *original; 1625141cc406Sopenharmony_ci 1626141cc406Sopenharmony_ci memset (&s->params, 0, sizeof (s->params)); 1627141cc406Sopenharmony_ci 1628141cc406Sopenharmony_ci width = SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w); 1629141cc406Sopenharmony_ci height = SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w); 1630141cc406Sopenharmony_ci dpi = s->val[OPT_RESOLUTION].w; 1631141cc406Sopenharmony_ci 1632141cc406Sopenharmony_ci /* make best-effort guess at what parameters will look like once 1633141cc406Sopenharmony_ci scanning starts. */ 1634141cc406Sopenharmony_ci if (dpi > 0.0 && width > 0.0 && height > 0.0) 1635141cc406Sopenharmony_ci { 1636141cc406Sopenharmony_ci double dots_per_mm = dpi / MM_PER_INCH; 1637141cc406Sopenharmony_ci 1638141cc406Sopenharmony_ci s->params.pixels_per_line = width * dots_per_mm + 0.5; 1639141cc406Sopenharmony_ci s->params.lines = height * dots_per_mm + 0.5; 1640141cc406Sopenharmony_ci } 1641141cc406Sopenharmony_ci 1642141cc406Sopenharmony_ci /* Should we specify calibration quality? */ 1643141cc406Sopenharmony_ci 1644141cc406Sopenharmony_ci if (SANE_OPTION_IS_ACTIVE (s->opt[OPT_QUALITY].cap)) 1645141cc406Sopenharmony_ci { 1646141cc406Sopenharmony_ci DBG(3, " -------------- setting quality\n"); 1647141cc406Sopenharmony_ci quality = s->val[OPT_QUALITY].s; 1648141cc406Sopenharmony_ci if (strcmp (quality, "Low") == 0 ) 1649141cc406Sopenharmony_ci s->quality = 255; 1650141cc406Sopenharmony_ci else if (strcmp (quality, "High") == 0) 1651141cc406Sopenharmony_ci s->quality = 1; 1652141cc406Sopenharmony_ci else 1653141cc406Sopenharmony_ci s->quality = 0; 1654141cc406Sopenharmony_ci } 1655141cc406Sopenharmony_ci else 1656141cc406Sopenharmony_ci s->quality = 0; 1657141cc406Sopenharmony_ci 1658141cc406Sopenharmony_ci /* Should we select source type? */ 1659141cc406Sopenharmony_ci 1660141cc406Sopenharmony_ci if (SANE_OPTION_IS_ACTIVE (s->opt[OPT_SOURCE].cap)) 1661141cc406Sopenharmony_ci { 1662141cc406Sopenharmony_ci DBG(3, " -------------- setting source\n"); 1663141cc406Sopenharmony_ci original = s->val[OPT_SOURCE].s; 1664141cc406Sopenharmony_ci if (strcmp (original, "Transparency") == 0) 1665141cc406Sopenharmony_ci s->original = 0; 1666141cc406Sopenharmony_ci else 1667141cc406Sopenharmony_ci s->original = 1; 1668141cc406Sopenharmony_ci } 1669141cc406Sopenharmony_ci else 1670141cc406Sopenharmony_ci s->original = 0; 1671141cc406Sopenharmony_ci 1672141cc406Sopenharmony_ci s->exposure = ((s->val[OPT_EXPOSURE].w * (255.0f - 80.0f)) / 100.0f) + 80.0f; 1673141cc406Sopenharmony_ci s->r_att = (SANE_UNFIX (s->val[OPT_ATTENUATION_RED].w) * 20.0f) / 100.0f; 1674141cc406Sopenharmony_ci s->g_att = (SANE_UNFIX (s->val[OPT_ATTENUATION_GREEN].w) * 20.0f) / 100.0f; 1675141cc406Sopenharmony_ci s->b_att = (SANE_UNFIX (s->val[OPT_ATTENUATION_BLUE].w) * 20.0f) / 100.0f; 1676141cc406Sopenharmony_ci s->tonecurve = 0; 1677141cc406Sopenharmony_ci 1678141cc406Sopenharmony_ci switch (s->mode) 1679141cc406Sopenharmony_ci { 1680141cc406Sopenharmony_ci case LINEART: 1681141cc406Sopenharmony_ci { 1682141cc406Sopenharmony_ci const char *halftone; 1683141cc406Sopenharmony_ci 1684141cc406Sopenharmony_ci s->image_composition = 0; 1685141cc406Sopenharmony_ci 1686141cc406Sopenharmony_ci /* in 1 bpp mode, lines need to be 8 pixel length */ 1687141cc406Sopenharmony_ci 1688141cc406Sopenharmony_ci if (s->params.pixels_per_line % 8) 1689141cc406Sopenharmony_ci s->params.pixels_per_line += 8 - (s->params.pixels_per_line % 8); 1690141cc406Sopenharmony_ci 1691141cc406Sopenharmony_ci s->params.format = SANE_FRAME_GRAY; 1692141cc406Sopenharmony_ci s->params.bytes_per_line = s->params.pixels_per_line / 8; 1693141cc406Sopenharmony_ci s->bpp = s->params.depth = 1; 1694141cc406Sopenharmony_ci 1695141cc406Sopenharmony_ci halftone = s->val[OPT_HALFTONE_PATTERN].s; 1696141cc406Sopenharmony_ci if (strcmp (halftone, "1") == 0 ) 1697141cc406Sopenharmony_ci s->halftone = 1; 1698141cc406Sopenharmony_ci else if (strcmp (halftone, "Dispersed dot 4x4") == 0) 1699141cc406Sopenharmony_ci s->halftone = 2; 1700141cc406Sopenharmony_ci else if (strcmp (halftone, "Round (Clustered dot 4x4)") == 0) 1701141cc406Sopenharmony_ci s->halftone = 3; 1702141cc406Sopenharmony_ci else if (strcmp (halftone, "Diamond (Clustered dot 4x4)") == 0) 1703141cc406Sopenharmony_ci s->halftone = 4; 1704141cc406Sopenharmony_ci else if (strcmp (halftone, "User defined") == 0) 1705141cc406Sopenharmony_ci s->halftone = 5; 1706141cc406Sopenharmony_ci else 1707141cc406Sopenharmony_ci s->halftone = 0; 1708141cc406Sopenharmony_ci 1709141cc406Sopenharmony_ci s->edge = s->val[OPT_SHARPEN].w; 1710141cc406Sopenharmony_ci } 1711141cc406Sopenharmony_ci break; 1712141cc406Sopenharmony_ci 1713141cc406Sopenharmony_ci case GRAY6BIT: 1714141cc406Sopenharmony_ci s->image_composition = 2; 1715141cc406Sopenharmony_ci 1716141cc406Sopenharmony_ci s->params.format = SANE_FRAME_GRAY; 1717141cc406Sopenharmony_ci s->params.bytes_per_line = s->params.pixels_per_line; 1718141cc406Sopenharmony_ci s->bpp = 6; 1719141cc406Sopenharmony_ci s->params.depth = 8; 1720141cc406Sopenharmony_ci s->edge = s->val[OPT_SHARPEN].w; 1721141cc406Sopenharmony_ci 1722141cc406Sopenharmony_ci break; 1723141cc406Sopenharmony_ci 1724141cc406Sopenharmony_ci case GRAY8BIT: 1725141cc406Sopenharmony_ci s->image_composition = 2; 1726141cc406Sopenharmony_ci 1727141cc406Sopenharmony_ci s->params.format = SANE_FRAME_GRAY; 1728141cc406Sopenharmony_ci s->params.bytes_per_line = s->params.pixels_per_line; 1729141cc406Sopenharmony_ci s->bpp = s->params.depth = 8; 1730141cc406Sopenharmony_ci 1731141cc406Sopenharmony_ci break; 1732141cc406Sopenharmony_ci 1733141cc406Sopenharmony_ci case COLOR18BIT: 1734141cc406Sopenharmony_ci s->image_composition = 5; 1735141cc406Sopenharmony_ci 1736141cc406Sopenharmony_ci s->params.format = SANE_FRAME_RED; 1737141cc406Sopenharmony_ci s->params.bytes_per_line = s->params.pixels_per_line; 1738141cc406Sopenharmony_ci s->bpp = 6; 1739141cc406Sopenharmony_ci s->params.depth = 8; 1740141cc406Sopenharmony_ci s->edge = s->val[OPT_SHARPEN].w; 1741141cc406Sopenharmony_ci 1742141cc406Sopenharmony_ci break; 1743141cc406Sopenharmony_ci 1744141cc406Sopenharmony_ci case COLOR24BIT: 1745141cc406Sopenharmony_ci s->image_composition = 5; 1746141cc406Sopenharmony_ci 1747141cc406Sopenharmony_ci s->params.format = SANE_FRAME_RED; 1748141cc406Sopenharmony_ci s->params.bytes_per_line = s->params.pixels_per_line; 1749141cc406Sopenharmony_ci s->bpp = s->params.depth = 8; 1750141cc406Sopenharmony_ci 1751141cc406Sopenharmony_ci break; 1752141cc406Sopenharmony_ci } 1753141cc406Sopenharmony_ci 1754141cc406Sopenharmony_ci s->pass = 0; 1755141cc406Sopenharmony_ci 1756141cc406Sopenharmony_ci /*s->params.bytes_per_line = 1757141cc406Sopenharmony_ci (s->params.pixels_per_line + (8 - s->params.depth)) 1758141cc406Sopenharmony_ci / (8 / s->params.depth);*/ 1759141cc406Sopenharmony_ci } 1760141cc406Sopenharmony_ci else 1761141cc406Sopenharmony_ci if (s->mode == COLOR18BIT || 1762141cc406Sopenharmony_ci s->mode == COLOR24BIT) 1763141cc406Sopenharmony_ci s->params.format = SANE_FRAME_RED + s->pass; 1764141cc406Sopenharmony_ci 1765141cc406Sopenharmony_ci s->params.last_frame = (s->params.format != SANE_FRAME_RED && s->params.format != SANE_FRAME_GREEN); 1766141cc406Sopenharmony_ci 1767141cc406Sopenharmony_ci if (params) 1768141cc406Sopenharmony_ci *params = s->params; 1769141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1770141cc406Sopenharmony_ci} 1771141cc406Sopenharmony_ci 1772141cc406Sopenharmony_ci/* This function is executed as a child process. The reason this is 1773141cc406Sopenharmony_ci executed as a subprocess is because some (most?) generic SCSI 1774141cc406Sopenharmony_ci interfaces block a SCSI request until it has completed. With a 1775141cc406Sopenharmony_ci subprocess, we can let it block waiting for the request to finish 1776141cc406Sopenharmony_ci while the main process can go about to do more important things 1777141cc406Sopenharmony_ci (such as recognizing when the user presses a cancel button). 1778141cc406Sopenharmony_ci 1779141cc406Sopenharmony_ci 1780141cc406Sopenharmony_ci WARNING: Since this is executed as a subprocess, it's NOT possible 1781141cc406Sopenharmony_ci to update any of the variables in the main process (in particular 1782141cc406Sopenharmony_ci the scanner state cannot be updated). */ 1783141cc406Sopenharmony_cistatic int 1784141cc406Sopenharmony_cireader_process (void *scanner) 1785141cc406Sopenharmony_ci{ 1786141cc406Sopenharmony_ci AgfaFocus_Scanner *s = (AgfaFocus_Scanner *) scanner; 1787141cc406Sopenharmony_ci int fd = s->reader_pipe; 1788141cc406Sopenharmony_ci 1789141cc406Sopenharmony_ci SANE_Status status; 1790141cc406Sopenharmony_ci SANE_Byte *data; 1791141cc406Sopenharmony_ci int lines_read = 0; 1792141cc406Sopenharmony_ci int lines_per_buffer; 1793141cc406Sopenharmony_ci int bytes_per_line = 0, total_lines = 0; 1794141cc406Sopenharmony_ci int i; 1795141cc406Sopenharmony_ci sigset_t sigterm_set; 1796141cc406Sopenharmony_ci sigset_t ignore_set; 1797141cc406Sopenharmony_ci struct SIGACTION act; 1798141cc406Sopenharmony_ci 1799141cc406Sopenharmony_ci if (sanei_thread_is_forked()) close (s->pipe); 1800141cc406Sopenharmony_ci 1801141cc406Sopenharmony_ci sigfillset (&ignore_set); 1802141cc406Sopenharmony_ci sigdelset (&ignore_set, SIGTERM); 1803141cc406Sopenharmony_ci#if defined (__APPLE__) && defined (__MACH__) 1804141cc406Sopenharmony_ci sigdelset (&ignore_set, SIGUSR2); 1805141cc406Sopenharmony_ci#endif 1806141cc406Sopenharmony_ci sigprocmask (SIG_SETMASK, &ignore_set, 0); 1807141cc406Sopenharmony_ci 1808141cc406Sopenharmony_ci memset (&act, 0, sizeof (act)); 1809141cc406Sopenharmony_ci sigaction (SIGTERM, &act, 0); 1810141cc406Sopenharmony_ci 1811141cc406Sopenharmony_ci sigemptyset (&sigterm_set); 1812141cc406Sopenharmony_ci sigaddset (&sigterm_set, SIGTERM); 1813141cc406Sopenharmony_ci 1814141cc406Sopenharmony_ci if (!s->hw->disconnect) 1815141cc406Sopenharmony_ci wait_ready (s->fd); 1816141cc406Sopenharmony_ci 1817141cc406Sopenharmony_ci status = get_read_sizes (s->fd, &s->lines_available, &bytes_per_line, &total_lines); 1818141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1819141cc406Sopenharmony_ci { 1820141cc406Sopenharmony_ci DBG (1, "open: get_read_sizes() failed: %s\n", 1821141cc406Sopenharmony_ci sane_strstatus (status)); 1822141cc406Sopenharmony_ci do_cancel (s); 1823141cc406Sopenharmony_ci close (fd); 1824141cc406Sopenharmony_ci return 1; 1825141cc406Sopenharmony_ci } 1826141cc406Sopenharmony_ci 1827141cc406Sopenharmony_ci if (!s->lines_available || !bytes_per_line || !total_lines || bytes_per_line < s->params.bytes_per_line) 1828141cc406Sopenharmony_ci { 1829141cc406Sopenharmony_ci DBG (1, "open: invalid sizes: %d, %d, %d\n", 1830141cc406Sopenharmony_ci s->lines_available, bytes_per_line, total_lines); 1831141cc406Sopenharmony_ci do_cancel (s); 1832141cc406Sopenharmony_ci close (fd); 1833141cc406Sopenharmony_ci return 1; 1834141cc406Sopenharmony_ci } 1835141cc406Sopenharmony_ci 1836141cc406Sopenharmony_ci lines_per_buffer = sanei_scsi_max_request_size / bytes_per_line; 1837141cc406Sopenharmony_ci if (!lines_per_buffer) 1838141cc406Sopenharmony_ci { 1839141cc406Sopenharmony_ci close (fd); 1840141cc406Sopenharmony_ci return 2; /* resolution is too high */ 1841141cc406Sopenharmony_ci } 1842141cc406Sopenharmony_ci 1843141cc406Sopenharmony_ci data = malloc (lines_per_buffer * bytes_per_line); 1844141cc406Sopenharmony_ci if (!data) 1845141cc406Sopenharmony_ci { 1846141cc406Sopenharmony_ci DBG (1, "open malloc(%lu) failed.\n", (u_long) lines_per_buffer * bytes_per_line); 1847141cc406Sopenharmony_ci do_cancel (s); 1848141cc406Sopenharmony_ci close (fd); 1849141cc406Sopenharmony_ci return 1; 1850141cc406Sopenharmony_ci } 1851141cc406Sopenharmony_ci 1852141cc406Sopenharmony_ci while (lines_read < s->params.lines) 1853141cc406Sopenharmony_ci { 1854141cc406Sopenharmony_ci int lines = lines_per_buffer; 1855141cc406Sopenharmony_ci 1856141cc406Sopenharmony_ci if (s->lines_available == 0) 1857141cc406Sopenharmony_ci { 1858141cc406Sopenharmony_ci /* No lines in scanner? Scan some more */ 1859141cc406Sopenharmony_ci status = request_more_data (s); 1860141cc406Sopenharmony_ci 1861141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1862141cc406Sopenharmony_ci { 1863141cc406Sopenharmony_ci close (fd); 1864141cc406Sopenharmony_ci return 1; 1865141cc406Sopenharmony_ci } 1866141cc406Sopenharmony_ci } 1867141cc406Sopenharmony_ci 1868141cc406Sopenharmony_ci /* We only request as many lines as there are already scanned */ 1869141cc406Sopenharmony_ci if (lines > s->lines_available) 1870141cc406Sopenharmony_ci lines = s->lines_available; 1871141cc406Sopenharmony_ci 1872141cc406Sopenharmony_ci DBG (1, "Requesting %d lines, in scanner: %d, total: %d\n", lines, 1873141cc406Sopenharmony_ci s->lines_available, s->params.lines); 1874141cc406Sopenharmony_ci 1875141cc406Sopenharmony_ci status = read_data (s, data, lines, bytes_per_line); 1876141cc406Sopenharmony_ci 1877141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1878141cc406Sopenharmony_ci { 1879141cc406Sopenharmony_ci DBG (1, "sane_read: read_data() failed (%s)\n", 1880141cc406Sopenharmony_ci sane_strstatus (status)); 1881141cc406Sopenharmony_ci do_cancel (s); 1882141cc406Sopenharmony_ci close (fd); 1883141cc406Sopenharmony_ci return 1; 1884141cc406Sopenharmony_ci } 1885141cc406Sopenharmony_ci 1886141cc406Sopenharmony_ci /* Sometimes the scanner will return more bytes per line than 1887141cc406Sopenharmony_ci requested, so we copy only what we wanted. */ 1888141cc406Sopenharmony_ci 1889141cc406Sopenharmony_ci for (i = 0; i < lines; i++) 1890141cc406Sopenharmony_ci if (write (fd, data + i * bytes_per_line, s->params.bytes_per_line) != s->params.bytes_per_line) 1891141cc406Sopenharmony_ci { 1892141cc406Sopenharmony_ci do_cancel (s); 1893141cc406Sopenharmony_ci close (fd); 1894141cc406Sopenharmony_ci return 1; 1895141cc406Sopenharmony_ci } 1896141cc406Sopenharmony_ci 1897141cc406Sopenharmony_ci lines_read += lines; 1898141cc406Sopenharmony_ci } 1899141cc406Sopenharmony_ci 1900141cc406Sopenharmony_ci close (fd); 1901141cc406Sopenharmony_ci return 0; 1902141cc406Sopenharmony_ci} 1903141cc406Sopenharmony_ci 1904141cc406Sopenharmony_ciSANE_Status 1905141cc406Sopenharmony_cisane_start (SANE_Handle handle) 1906141cc406Sopenharmony_ci{ 1907141cc406Sopenharmony_ci AgfaFocus_Scanner *s = handle; 1908141cc406Sopenharmony_ci SANE_Status status; 1909141cc406Sopenharmony_ci int fds[2]; 1910141cc406Sopenharmony_ci 1911141cc406Sopenharmony_ci /* First make sure we have a current parameter set. Some of the 1912141cc406Sopenharmony_ci parameters will be overwritten below, but that's OK. */ 1913141cc406Sopenharmony_ci 1914141cc406Sopenharmony_ci status = sane_get_parameters (s, 0); 1915141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1916141cc406Sopenharmony_ci return status; 1917141cc406Sopenharmony_ci 1918141cc406Sopenharmony_ci /* don't initialise scanner if we're doing a three-pass scan */ 1919141cc406Sopenharmony_ci 1920141cc406Sopenharmony_ci if (s->pass == 0) 1921141cc406Sopenharmony_ci { 1922141cc406Sopenharmony_ci if (s->fd < 0) 1923141cc406Sopenharmony_ci { 1924141cc406Sopenharmony_ci status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, 0); 1925141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1926141cc406Sopenharmony_ci { 1927141cc406Sopenharmony_ci DBG (1, "open: open of %s failed: %s\n", 1928141cc406Sopenharmony_ci s->hw->sane.name, sane_strstatus (status)); 1929141cc406Sopenharmony_ci s->fd = -1; 1930141cc406Sopenharmony_ci return status; 1931141cc406Sopenharmony_ci } 1932141cc406Sopenharmony_ci } 1933141cc406Sopenharmony_ci 1934141cc406Sopenharmony_ci status = test_ready (s->fd); 1935141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1936141cc406Sopenharmony_ci { 1937141cc406Sopenharmony_ci DBG (1, "open: test_ready() failed: %s\n", sane_strstatus (status)); 1938141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 1939141cc406Sopenharmony_ci s->fd = -1; 1940141cc406Sopenharmony_ci return status; 1941141cc406Sopenharmony_ci } 1942141cc406Sopenharmony_ci 1943141cc406Sopenharmony_ci status = reserve_unit (s->fd); 1944141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1945141cc406Sopenharmony_ci { 1946141cc406Sopenharmony_ci DBG (1, "open: reserve_unit() failed: %s\n", sane_strstatus (status)); 1947141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 1948141cc406Sopenharmony_ci s->fd = -1; 1949141cc406Sopenharmony_ci return status; 1950141cc406Sopenharmony_ci } 1951141cc406Sopenharmony_ci 1952141cc406Sopenharmony_ci status = set_window (s); 1953141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1954141cc406Sopenharmony_ci { 1955141cc406Sopenharmony_ci DBG (1, "open: set_window() failed: %s\n", sane_strstatus (status)); 1956141cc406Sopenharmony_ci release_unit (s->fd); 1957141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 1958141cc406Sopenharmony_ci s->fd = -1; 1959141cc406Sopenharmony_ci return status; 1960141cc406Sopenharmony_ci } 1961141cc406Sopenharmony_ci 1962141cc406Sopenharmony_ci { 1963141cc406Sopenharmony_ci int matrix[256] = { 1964141cc406Sopenharmony_ci 2, 60, 16, 56, 3, 57, 13, 53, 1965141cc406Sopenharmony_ci 34, 18, 48, 32, 35, 19, 45, 29, 1966141cc406Sopenharmony_ci 10, 50, 6, 63, 11, 51, 7, 61, 1967141cc406Sopenharmony_ci 42, 26, 38, 22, 43, 27, 39, 23, 1968141cc406Sopenharmony_ci 4, 58, 14, 54, 1, 59, 15, 55, 1969141cc406Sopenharmony_ci 36, 20, 46, 30, 33, 17, 47, 31, 1970141cc406Sopenharmony_ci 12, 52, 8, 62, 9, 49, 5, 63, 1971141cc406Sopenharmony_ci 44, 28, 40, 24, 41, 25, 37, 21 1972141cc406Sopenharmony_ci }; 1973141cc406Sopenharmony_ci 1974141cc406Sopenharmony_ci status = upload_dither_matrix (s, 8, 8, matrix); 1975141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1976141cc406Sopenharmony_ci { 1977141cc406Sopenharmony_ci DBG (1, "open: upload_dither_matrix() failed: %s\n", sane_strstatus (status)); 1978141cc406Sopenharmony_ci release_unit (s->fd); 1979141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 1980141cc406Sopenharmony_ci s->fd = -1; 1981141cc406Sopenharmony_ci return status; 1982141cc406Sopenharmony_ci } 1983141cc406Sopenharmony_ci } 1984141cc406Sopenharmony_ci 1985141cc406Sopenharmony_ci s->scanning = SANE_TRUE; 1986141cc406Sopenharmony_ci 1987141cc406Sopenharmony_ci status = start_scan (s->fd, SANE_FALSE); 1988141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1989141cc406Sopenharmony_ci { 1990141cc406Sopenharmony_ci DBG (1, "open: start_scan() failed: %s\n", sane_strstatus (status)); 1991141cc406Sopenharmony_ci do_cancel (s); 1992141cc406Sopenharmony_ci return status; 1993141cc406Sopenharmony_ci } 1994141cc406Sopenharmony_ci } 1995141cc406Sopenharmony_ci else 1996141cc406Sopenharmony_ci { 1997141cc406Sopenharmony_ci /* continue three-pass scan */ 1998141cc406Sopenharmony_ci 1999141cc406Sopenharmony_ci status = start_scan (s->fd, SANE_TRUE); 2000141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2001141cc406Sopenharmony_ci { 2002141cc406Sopenharmony_ci DBG (1, "open: start_scan() failed: %s\n", sane_strstatus (status)); 2003141cc406Sopenharmony_ci do_cancel (s); 2004141cc406Sopenharmony_ci return status; 2005141cc406Sopenharmony_ci } 2006141cc406Sopenharmony_ci } 2007141cc406Sopenharmony_ci 2008141cc406Sopenharmony_ci if (pipe (fds) < 0) 2009141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2010141cc406Sopenharmony_ci 2011141cc406Sopenharmony_ci s->pipe = fds[0]; 2012141cc406Sopenharmony_ci s->reader_pipe = fds[1]; 2013141cc406Sopenharmony_ci s->reader_pid = sanei_thread_begin (reader_process, (void *) s); 2014141cc406Sopenharmony_ci 2015141cc406Sopenharmony_ci if (sanei_thread_is_forked()) close (s->reader_pipe); 2016141cc406Sopenharmony_ci 2017141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2018141cc406Sopenharmony_ci} 2019141cc406Sopenharmony_ci 2020141cc406Sopenharmony_ciSANE_Status 2021141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, 2022141cc406Sopenharmony_ci SANE_Int * len) 2023141cc406Sopenharmony_ci{ 2024141cc406Sopenharmony_ci AgfaFocus_Scanner *s = handle; 2025141cc406Sopenharmony_ci ssize_t nread; 2026141cc406Sopenharmony_ci 2027141cc406Sopenharmony_ci *len = 0; 2028141cc406Sopenharmony_ci 2029141cc406Sopenharmony_ci nread = read (s->pipe, buf, max_len); 2030141cc406Sopenharmony_ci DBG (3, "read %ld bytes\n", (long) nread); 2031141cc406Sopenharmony_ci 2032141cc406Sopenharmony_ci if (!s->scanning) 2033141cc406Sopenharmony_ci return do_cancel (s); 2034141cc406Sopenharmony_ci 2035141cc406Sopenharmony_ci if (nread < 0) { 2036141cc406Sopenharmony_ci if (errno == EAGAIN) { 2037141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2038141cc406Sopenharmony_ci } else { 2039141cc406Sopenharmony_ci do_cancel (s); 2040141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2041141cc406Sopenharmony_ci } 2042141cc406Sopenharmony_ci } 2043141cc406Sopenharmony_ci 2044141cc406Sopenharmony_ci *len = nread; 2045141cc406Sopenharmony_ci 2046141cc406Sopenharmony_ci if (nread == 0) { 2047141cc406Sopenharmony_ci s->pass++; 2048141cc406Sopenharmony_ci return do_eof (s); 2049141cc406Sopenharmony_ci } 2050141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2051141cc406Sopenharmony_ci} 2052141cc406Sopenharmony_ci 2053141cc406Sopenharmony_civoid 2054141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 2055141cc406Sopenharmony_ci{ 2056141cc406Sopenharmony_ci AgfaFocus_Scanner *s = handle; 2057141cc406Sopenharmony_ci 2058141cc406Sopenharmony_ci if (sanei_thread_is_valid (s->reader_pid)) 2059141cc406Sopenharmony_ci sanei_thread_kill (s->reader_pid); 2060141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 2061141cc406Sopenharmony_ci} 2062141cc406Sopenharmony_ci 2063141cc406Sopenharmony_ciSANE_Status 2064141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 2065141cc406Sopenharmony_ci{ 2066141cc406Sopenharmony_ci AgfaFocus_Scanner *s = handle; 2067141cc406Sopenharmony_ci 2068141cc406Sopenharmony_ci if (!s->scanning) 2069141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2070141cc406Sopenharmony_ci 2071141cc406Sopenharmony_ci if (fcntl (s->pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) 2072141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2073141cc406Sopenharmony_ci 2074141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2075141cc406Sopenharmony_ci} 2076141cc406Sopenharmony_ci 2077141cc406Sopenharmony_ciSANE_Status 2078141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd) 2079141cc406Sopenharmony_ci{ 2080141cc406Sopenharmony_ci AgfaFocus_Scanner *s = handle; 2081141cc406Sopenharmony_ci 2082141cc406Sopenharmony_ci if (!s->scanning) 2083141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2084141cc406Sopenharmony_ci 2085141cc406Sopenharmony_ci *fd = s->pipe; 2086141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2087141cc406Sopenharmony_ci} 2088