1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci Copyright (C) 1999,2000 Tom Martone 3141cc406Sopenharmony_ci This file is part of a SANE backend for Bell and Howell Copiscan II 4141cc406Sopenharmony_ci Scanners using the Remote SCSI Controller(RSC). 5141cc406Sopenharmony_ci 6141cc406Sopenharmony_ci This file is part of the SANE package. 7141cc406Sopenharmony_ci 8141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 9141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 10141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 11141cc406Sopenharmony_ci License, or (at your option) any later version. 12141cc406Sopenharmony_ci 13141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 14141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 15141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16141cc406Sopenharmony_ci General Public License for more details. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 19141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 20141cc406Sopenharmony_ci 21141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 22141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 23141cc406Sopenharmony_ci 24141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 25141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 26141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 27141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 28141cc406Sopenharmony_ci account of linking the SANE library code into it. 29141cc406Sopenharmony_ci 30141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 31141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 32141cc406Sopenharmony_ci License. 33141cc406Sopenharmony_ci 34141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 35141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 36141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 37141cc406Sopenharmony_ci 38141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 39141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 40141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 41141cc406Sopenharmony_ci 42141cc406Sopenharmony_ci*/ 43141cc406Sopenharmony_ci#include "../include/sane/config.h" 44141cc406Sopenharmony_ci#include <limits.h> 45141cc406Sopenharmony_ci#include <errno.h> 46141cc406Sopenharmony_ci#include <fcntl.h> 47141cc406Sopenharmony_ci#include <ctype.h> 48141cc406Sopenharmony_ci#include <stdlib.h> 49141cc406Sopenharmony_ci#include <string.h> 50141cc406Sopenharmony_ci#include <stdio.h> 51141cc406Sopenharmony_ci#include <unistd.h> 52141cc406Sopenharmony_ci#include <sys/types.h> 53141cc406Sopenharmony_ci#include "../include/sane/sane.h" 54141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 55141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h" 56141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 57141cc406Sopenharmony_ci 58141cc406Sopenharmony_ci#define BACKEND_NAME bh 59141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 60141cc406Sopenharmony_ci#define BUILD 4 61141cc406Sopenharmony_ci 62141cc406Sopenharmony_ci#include "bh.h" 63141cc406Sopenharmony_ci 64141cc406Sopenharmony_ci#define MIN(x,y) ((x)<(y) ? (x) : (y)) 65141cc406Sopenharmony_ci#define MAX(x,y) ((x)>(y) ? (x) : (y)) 66141cc406Sopenharmony_ci 67141cc406Sopenharmony_cistatic const SANE_Device **devlist = 0; 68141cc406Sopenharmony_cistatic int num_devices = 0; 69141cc406Sopenharmony_cistatic BH_Device *first_dev = NULL; 70141cc406Sopenharmony_cistatic BH_Scanner *first_handle = NULL; 71141cc406Sopenharmony_cistatic SANE_Char inquiry_data[255] = "Bell+Howell scanner"; 72141cc406Sopenharmony_cistatic SANE_Int disable_optional_frames = 0; 73141cc406Sopenharmony_cistatic SANE_Int fake_inquiry = 0; 74141cc406Sopenharmony_ci 75141cc406Sopenharmony_cistatic int allblank(const char *s) 76141cc406Sopenharmony_ci{ 77141cc406Sopenharmony_ci while (s && *s) 78141cc406Sopenharmony_ci if (!isspace(*s++)) 79141cc406Sopenharmony_ci return 0; 80141cc406Sopenharmony_ci 81141cc406Sopenharmony_ci return 1; 82141cc406Sopenharmony_ci} 83141cc406Sopenharmony_ci 84141cc406Sopenharmony_cistatic size_t 85141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[]) 86141cc406Sopenharmony_ci{ 87141cc406Sopenharmony_ci size_t size, max_size = 0; 88141cc406Sopenharmony_ci int i; 89141cc406Sopenharmony_ci 90141cc406Sopenharmony_ci for (i = 0; strings[i]; ++i) 91141cc406Sopenharmony_ci { 92141cc406Sopenharmony_ci size = strlen (strings[i]) + 1; 93141cc406Sopenharmony_ci if (size > max_size) 94141cc406Sopenharmony_ci max_size = size; 95141cc406Sopenharmony_ci } 96141cc406Sopenharmony_ci 97141cc406Sopenharmony_ci return max_size; 98141cc406Sopenharmony_ci} 99141cc406Sopenharmony_ci 100141cc406Sopenharmony_cistatic void 101141cc406Sopenharmony_citrim_spaces(char *s, size_t n) 102141cc406Sopenharmony_ci{ 103141cc406Sopenharmony_ci for (s += (n-1); n > 0; n--, s--) 104141cc406Sopenharmony_ci { 105141cc406Sopenharmony_ci if (*s && !isspace(*s)) 106141cc406Sopenharmony_ci break; 107141cc406Sopenharmony_ci *s = '\0'; 108141cc406Sopenharmony_ci } 109141cc406Sopenharmony_ci} 110141cc406Sopenharmony_ci 111141cc406Sopenharmony_cistatic SANE_String_Const 112141cc406Sopenharmony_ciprint_devtype (SANE_Byte devtype) 113141cc406Sopenharmony_ci{ 114141cc406Sopenharmony_ci static SANE_String devtypes[] = 115141cc406Sopenharmony_ci { 116141cc406Sopenharmony_ci "disk", 117141cc406Sopenharmony_ci "tape", 118141cc406Sopenharmony_ci "printer", 119141cc406Sopenharmony_ci "processor", 120141cc406Sopenharmony_ci "CD-writer", 121141cc406Sopenharmony_ci "CD-drive", 122141cc406Sopenharmony_ci "scanner", 123141cc406Sopenharmony_ci "optical-drive", 124141cc406Sopenharmony_ci "jukebox", 125141cc406Sopenharmony_ci "communicator" 126141cc406Sopenharmony_ci }; 127141cc406Sopenharmony_ci 128141cc406Sopenharmony_ci return (devtype > 0 && devtype < NELEMS(devtypes)) ? 129141cc406Sopenharmony_ci devtypes[devtype] : 130141cc406Sopenharmony_ci "unknown-device"; 131141cc406Sopenharmony_ci} 132141cc406Sopenharmony_ci 133141cc406Sopenharmony_cistatic SANE_String_Const 134141cc406Sopenharmony_ciprint_barcodetype (SANE_Int i) 135141cc406Sopenharmony_ci{ 136141cc406Sopenharmony_ci return (i > 0 && i < NELEMS(barcode_search_bar_list)) ? 137141cc406Sopenharmony_ci barcode_search_bar_list[i] : 138141cc406Sopenharmony_ci (SANE_String_Const) "unknown"; 139141cc406Sopenharmony_ci} 140141cc406Sopenharmony_ci 141141cc406Sopenharmony_cistatic SANE_String_Const 142141cc406Sopenharmony_ciprint_orientation (SANE_Int i) 143141cc406Sopenharmony_ci{ 144141cc406Sopenharmony_ci switch(i) 145141cc406Sopenharmony_ci { 146141cc406Sopenharmony_ci case 0: 147141cc406Sopenharmony_ci case 7: 148141cc406Sopenharmony_ci return "vertical upwards"; 149141cc406Sopenharmony_ci case 1: 150141cc406Sopenharmony_ci case 2: 151141cc406Sopenharmony_ci return "horizontal right"; 152141cc406Sopenharmony_ci case 3: 153141cc406Sopenharmony_ci case 4: 154141cc406Sopenharmony_ci return "vertical downwards"; 155141cc406Sopenharmony_ci case 5: 156141cc406Sopenharmony_ci case 6: 157141cc406Sopenharmony_ci return "horizontal left"; 158141cc406Sopenharmony_ci default: 159141cc406Sopenharmony_ci return "unknown"; 160141cc406Sopenharmony_ci } 161141cc406Sopenharmony_ci} 162141cc406Sopenharmony_ci 163141cc406Sopenharmony_cistatic SANE_String_Const 164141cc406Sopenharmony_ciprint_read_type (SANE_Int i) 165141cc406Sopenharmony_ci{ 166141cc406Sopenharmony_ci static char buf[32]; 167141cc406Sopenharmony_ci SANE_Int n; 168141cc406Sopenharmony_ci 169141cc406Sopenharmony_ci /* translate BH_SCSI_READ_TYPE_ codes to a human-readable string */ 170141cc406Sopenharmony_ci if (i == BH_SCSI_READ_TYPE_FRONT) 171141cc406Sopenharmony_ci { 172141cc406Sopenharmony_ci strcpy(buf, "front page"); 173141cc406Sopenharmony_ci } 174141cc406Sopenharmony_ci else if (i == BH_SCSI_READ_TYPE_BACK) 175141cc406Sopenharmony_ci { 176141cc406Sopenharmony_ci strcpy(buf, "back page"); 177141cc406Sopenharmony_ci } 178141cc406Sopenharmony_ci else if (i > BH_SCSI_READ_TYPE_FRONT && 179141cc406Sopenharmony_ci i <= BH_SCSI_READ_TYPE_FRONT + NUM_SECTIONS) 180141cc406Sopenharmony_ci { 181141cc406Sopenharmony_ci n = i - BH_SCSI_READ_TYPE_FRONT; 182141cc406Sopenharmony_ci sprintf(buf, "front section %d", n); 183141cc406Sopenharmony_ci } 184141cc406Sopenharmony_ci else if (i > BH_SCSI_READ_TYPE_BACK && 185141cc406Sopenharmony_ci i <= BH_SCSI_READ_TYPE_BACK + NUM_SECTIONS) 186141cc406Sopenharmony_ci { 187141cc406Sopenharmony_ci n = i - BH_SCSI_READ_TYPE_BACK; 188141cc406Sopenharmony_ci sprintf(buf, "back section %d", n); 189141cc406Sopenharmony_ci } 190141cc406Sopenharmony_ci else if (i == BH_SCSI_READ_TYPE_FRONT_BARCODE) 191141cc406Sopenharmony_ci { 192141cc406Sopenharmony_ci strcpy(buf, "front page barcode"); 193141cc406Sopenharmony_ci } 194141cc406Sopenharmony_ci else if (i == BH_SCSI_READ_TYPE_BACK_BARCODE) 195141cc406Sopenharmony_ci { 196141cc406Sopenharmony_ci strcpy(buf, "back page barcode"); 197141cc406Sopenharmony_ci } 198141cc406Sopenharmony_ci else if (i > BH_SCSI_READ_TYPE_FRONT_BARCODE && 199141cc406Sopenharmony_ci i <= BH_SCSI_READ_TYPE_FRONT_BARCODE + NUM_SECTIONS) 200141cc406Sopenharmony_ci { 201141cc406Sopenharmony_ci n = i - BH_SCSI_READ_TYPE_FRONT_BARCODE; 202141cc406Sopenharmony_ci sprintf(buf, "front barcode section %d", n); 203141cc406Sopenharmony_ci } 204141cc406Sopenharmony_ci else if (i > BH_SCSI_READ_TYPE_BACK_BARCODE && 205141cc406Sopenharmony_ci i <= BH_SCSI_READ_TYPE_BACK_BARCODE + NUM_SECTIONS) 206141cc406Sopenharmony_ci { 207141cc406Sopenharmony_ci n = i - BH_SCSI_READ_TYPE_BACK_BARCODE; 208141cc406Sopenharmony_ci sprintf(buf, "back barcode section %d", n); 209141cc406Sopenharmony_ci } 210141cc406Sopenharmony_ci else if (i == BH_SCSI_READ_TYPE_FRONT_PATCHCODE) 211141cc406Sopenharmony_ci { 212141cc406Sopenharmony_ci strcpy(buf, "front page patchcode"); 213141cc406Sopenharmony_ci } 214141cc406Sopenharmony_ci else if (i == BH_SCSI_READ_TYPE_BACK_PATCHCODE) 215141cc406Sopenharmony_ci { 216141cc406Sopenharmony_ci strcpy(buf, "back page patchcode"); 217141cc406Sopenharmony_ci } 218141cc406Sopenharmony_ci else if (i > BH_SCSI_READ_TYPE_FRONT_PATCHCODE && 219141cc406Sopenharmony_ci i <= BH_SCSI_READ_TYPE_FRONT_PATCHCODE + NUM_SECTIONS) 220141cc406Sopenharmony_ci { 221141cc406Sopenharmony_ci n = i - BH_SCSI_READ_TYPE_FRONT_PATCHCODE; 222141cc406Sopenharmony_ci sprintf(buf, "front patchcode section %d", n); 223141cc406Sopenharmony_ci } 224141cc406Sopenharmony_ci else if (i > BH_SCSI_READ_TYPE_BACK_PATCHCODE && 225141cc406Sopenharmony_ci i <= BH_SCSI_READ_TYPE_BACK_PATCHCODE + NUM_SECTIONS) 226141cc406Sopenharmony_ci { 227141cc406Sopenharmony_ci n = i - BH_SCSI_READ_TYPE_BACK_PATCHCODE; 228141cc406Sopenharmony_ci sprintf(buf, "back patchcode section %d", n); 229141cc406Sopenharmony_ci } 230141cc406Sopenharmony_ci else if (i == BH_SCSI_READ_TYPE_FRONT_ICON) 231141cc406Sopenharmony_ci { 232141cc406Sopenharmony_ci strcpy(buf, "front page icon"); 233141cc406Sopenharmony_ci } 234141cc406Sopenharmony_ci else if (i == BH_SCSI_READ_TYPE_BACK_ICON) 235141cc406Sopenharmony_ci { 236141cc406Sopenharmony_ci strcpy(buf, "back page icon"); 237141cc406Sopenharmony_ci } 238141cc406Sopenharmony_ci else if (i == BH_SCSI_READ_TYPE_SENDBARFILE) 239141cc406Sopenharmony_ci { 240141cc406Sopenharmony_ci strcpy(buf, "transmit bar/patch codes"); 241141cc406Sopenharmony_ci } 242141cc406Sopenharmony_ci else 243141cc406Sopenharmony_ci { 244141cc406Sopenharmony_ci strcpy(buf, "unknown"); 245141cc406Sopenharmony_ci } 246141cc406Sopenharmony_ci 247141cc406Sopenharmony_ci return buf; 248141cc406Sopenharmony_ci} 249141cc406Sopenharmony_ci 250141cc406Sopenharmony_cistatic SANE_Int 251141cc406Sopenharmony_ciget_rotation_id(char *s) 252141cc406Sopenharmony_ci{ 253141cc406Sopenharmony_ci SANE_Int i; 254141cc406Sopenharmony_ci 255141cc406Sopenharmony_ci for (i = 0; rotation_list[i]; i++) 256141cc406Sopenharmony_ci if (strcmp(s, rotation_list[i]) == 0) 257141cc406Sopenharmony_ci break; 258141cc406Sopenharmony_ci 259141cc406Sopenharmony_ci /* unknown strings are treated as '0' */ 260141cc406Sopenharmony_ci return rotation_list[i] ? i : 0; 261141cc406Sopenharmony_ci} 262141cc406Sopenharmony_ci 263141cc406Sopenharmony_cistatic SANE_Int 264141cc406Sopenharmony_ciget_compression_id(char *s) 265141cc406Sopenharmony_ci{ 266141cc406Sopenharmony_ci SANE_Int i; 267141cc406Sopenharmony_ci 268141cc406Sopenharmony_ci for (i = 0; compression_list[i]; i++) 269141cc406Sopenharmony_ci if (strcmp(s, compression_list[i]) == 0) 270141cc406Sopenharmony_ci break; 271141cc406Sopenharmony_ci 272141cc406Sopenharmony_ci /* unknown strings are treated as 'none' */ 273141cc406Sopenharmony_ci return compression_list[i] ? i : 0; 274141cc406Sopenharmony_ci} 275141cc406Sopenharmony_ci 276141cc406Sopenharmony_cistatic SANE_Int 277141cc406Sopenharmony_ciget_barcode_id(char *s) 278141cc406Sopenharmony_ci{ 279141cc406Sopenharmony_ci SANE_Int i; 280141cc406Sopenharmony_ci 281141cc406Sopenharmony_ci for (i = 0; barcode_search_bar_list[i]; i++) 282141cc406Sopenharmony_ci if (strcmp(s, barcode_search_bar_list[i]) == 0) 283141cc406Sopenharmony_ci break; 284141cc406Sopenharmony_ci 285141cc406Sopenharmony_ci /* unknown strings are treated as 'none' */ 286141cc406Sopenharmony_ci return barcode_search_bar_list[i] ? i : 0; 287141cc406Sopenharmony_ci} 288141cc406Sopenharmony_ci 289141cc406Sopenharmony_cistatic SANE_Int 290141cc406Sopenharmony_ciget_scan_mode_id(char *s) 291141cc406Sopenharmony_ci{ 292141cc406Sopenharmony_ci SANE_Int i; 293141cc406Sopenharmony_ci 294141cc406Sopenharmony_ci for (i = 0; scan_mode_list[i]; i++) 295141cc406Sopenharmony_ci if (strcmp(s, scan_mode_list[i]) == 0) 296141cc406Sopenharmony_ci break; 297141cc406Sopenharmony_ci 298141cc406Sopenharmony_ci /* unknown strings are treated as 'lineart' */ 299141cc406Sopenharmony_ci return scan_mode_list[i] ? i : 0; 300141cc406Sopenharmony_ci} 301141cc406Sopenharmony_ci 302141cc406Sopenharmony_cistatic SANE_Int 303141cc406Sopenharmony_ciget_paper_id(char *s) 304141cc406Sopenharmony_ci{ 305141cc406Sopenharmony_ci SANE_Int i; 306141cc406Sopenharmony_ci 307141cc406Sopenharmony_ci for (i = 0; paper_list[i]; i++) 308141cc406Sopenharmony_ci if (strcmp(s, paper_list[i]) == 0) 309141cc406Sopenharmony_ci break; 310141cc406Sopenharmony_ci 311141cc406Sopenharmony_ci /* unknown strings are treated as 'custom' */ 312141cc406Sopenharmony_ci return paper_list[i] ? i : 0; 313141cc406Sopenharmony_ci} 314141cc406Sopenharmony_ci 315141cc406Sopenharmony_cistatic SANE_Int 316141cc406Sopenharmony_ciget_barcode_search_mode(char *s) 317141cc406Sopenharmony_ci{ 318141cc406Sopenharmony_ci SANE_Int i; 319141cc406Sopenharmony_ci 320141cc406Sopenharmony_ci if (strcmp(s, "horizontal") == 0) 321141cc406Sopenharmony_ci { 322141cc406Sopenharmony_ci i = 1; 323141cc406Sopenharmony_ci } 324141cc406Sopenharmony_ci else if (strcmp(s, "vertical") == 0) 325141cc406Sopenharmony_ci { 326141cc406Sopenharmony_ci i = 2; 327141cc406Sopenharmony_ci } 328141cc406Sopenharmony_ci else if (strcmp(s, "vert-horiz") == 0) 329141cc406Sopenharmony_ci { 330141cc406Sopenharmony_ci i = 6; 331141cc406Sopenharmony_ci } 332141cc406Sopenharmony_ci else if (strcmp(s, "horiz-vert") == 0) 333141cc406Sopenharmony_ci { 334141cc406Sopenharmony_ci i = 9; 335141cc406Sopenharmony_ci } 336141cc406Sopenharmony_ci else 337141cc406Sopenharmony_ci { 338141cc406Sopenharmony_ci /* unknown strings are treated as 'horiz-vert' */ 339141cc406Sopenharmony_ci DBG(1, "get_barcode_search_mode: unrecognized string `%s'\n", s); 340141cc406Sopenharmony_ci i = 9; 341141cc406Sopenharmony_ci } 342141cc406Sopenharmony_ci 343141cc406Sopenharmony_ci return i; 344141cc406Sopenharmony_ci} 345141cc406Sopenharmony_ci 346141cc406Sopenharmony_cistatic void 347141cc406Sopenharmony_ciappendStdList(BH_Info *sc, SANE_Int res) 348141cc406Sopenharmony_ci{ 349141cc406Sopenharmony_ci /* append entry to resolution list - a SANE_WORD_LIST */ 350141cc406Sopenharmony_ci sc->resStdList[sc->resStdList[0]+1] = res; 351141cc406Sopenharmony_ci sc->resStdList[0]++; 352141cc406Sopenharmony_ci} 353141cc406Sopenharmony_ci 354141cc406Sopenharmony_cistatic void 355141cc406Sopenharmony_ciScannerDump(BH_Scanner *s) 356141cc406Sopenharmony_ci{ 357141cc406Sopenharmony_ci int i; 358141cc406Sopenharmony_ci BH_Info *info; 359141cc406Sopenharmony_ci SANE_Device *sdev; 360141cc406Sopenharmony_ci 361141cc406Sopenharmony_ci info = &s->hw->info; 362141cc406Sopenharmony_ci sdev = &s->hw->sane; 363141cc406Sopenharmony_ci 364141cc406Sopenharmony_ci DBG (1, "SANE Device: '%s' Vendor: '%s' Model: '%s' Type: '%s'\n", 365141cc406Sopenharmony_ci sdev->name, 366141cc406Sopenharmony_ci sdev->vendor, 367141cc406Sopenharmony_ci sdev->model, 368141cc406Sopenharmony_ci sdev->type); 369141cc406Sopenharmony_ci 370141cc406Sopenharmony_ci DBG (1, "Type: '%s' Vendor: '%s' Product: '%s' Revision: '%s'\n", 371141cc406Sopenharmony_ci print_devtype(info->devtype), 372141cc406Sopenharmony_ci info->vendor, 373141cc406Sopenharmony_ci info->product, 374141cc406Sopenharmony_ci info->revision); 375141cc406Sopenharmony_ci 376141cc406Sopenharmony_ci DBG (1, "Automatic Document Feeder:%s\n", 377141cc406Sopenharmony_ci info->canADF ? " <Installed>" : " <Not Installed>"); 378141cc406Sopenharmony_ci 379141cc406Sopenharmony_ci DBG (1, "Colors:%s%s\n", info->colorBandW ? " <Black and White>" : "", 380141cc406Sopenharmony_ci info->colorHalftone ? " <Halftone>" : ""); 381141cc406Sopenharmony_ci 382141cc406Sopenharmony_ci DBG (1, "Data processing:%s%s%s%s%s%s\n", 383141cc406Sopenharmony_ci info->canWhiteFrame ? " <White Frame>" : "", 384141cc406Sopenharmony_ci info->canBlackFrame ? " <Black Frame>" : "", 385141cc406Sopenharmony_ci info->canEdgeExtract ? " <Edge Extraction>" : "", 386141cc406Sopenharmony_ci info->canNoiseFilter ? " <Noise Filter>" : "", 387141cc406Sopenharmony_ci info->canSmooth ? " <Smooth>" : "", 388141cc406Sopenharmony_ci info->canLineBold ? " <Line Bolding>" : ""); 389141cc406Sopenharmony_ci 390141cc406Sopenharmony_ci DBG (1, "Compression:%s%s%s\n", 391141cc406Sopenharmony_ci info->comprG3_1D ? " <Group 3, 1D>" : "", 392141cc406Sopenharmony_ci info->comprG3_2D ? " <Group 3, 2D>" : "", 393141cc406Sopenharmony_ci info->comprG4 ? " <Group 4>" : ""); 394141cc406Sopenharmony_ci 395141cc406Sopenharmony_ci DBG (1, "Optional Features:%s%s%s%s\n", 396141cc406Sopenharmony_ci info->canBorderRecog ? " <Border Recognition>" : "", 397141cc406Sopenharmony_ci info->canBarCode ? " <BarCode Decoding>" : "", 398141cc406Sopenharmony_ci info->canIcon ? " <Icon Generation>" : "", 399141cc406Sopenharmony_ci info->canSection ? " <Section Support>" : ""); 400141cc406Sopenharmony_ci 401141cc406Sopenharmony_ci DBG (1, "Max bytes per scan-line: %d (%d pixels)\n", 402141cc406Sopenharmony_ci info->lineMaxBytes, 403141cc406Sopenharmony_ci info->lineMaxBytes * 8); 404141cc406Sopenharmony_ci 405141cc406Sopenharmony_ci DBG (1, "Basic resolution (X/Y): %d/%d\n", 406141cc406Sopenharmony_ci info->resBasicX, 407141cc406Sopenharmony_ci info->resBasicY); 408141cc406Sopenharmony_ci 409141cc406Sopenharmony_ci DBG (1, "Maximum resolution (X/Y): %d/%d\n", 410141cc406Sopenharmony_ci info->resMaxX, 411141cc406Sopenharmony_ci info->resMaxY); 412141cc406Sopenharmony_ci 413141cc406Sopenharmony_ci DBG (1, "Minimum resolution (X/Y): %d/%d\n", 414141cc406Sopenharmony_ci info->resMinX, 415141cc406Sopenharmony_ci info->resMinY); 416141cc406Sopenharmony_ci 417141cc406Sopenharmony_ci DBG (1, "Standard Resolutions:\n"); 418141cc406Sopenharmony_ci for (i = 0; i < info->resStdList[0]; i++) 419141cc406Sopenharmony_ci DBG (1, " %d\n", info->resStdList[i+1]); 420141cc406Sopenharmony_ci 421141cc406Sopenharmony_ci DBG (1, "Window Width/Height (in basic res) %d/%d (%.2f/%.2f inches)\n", 422141cc406Sopenharmony_ci info->winWidth, 423141cc406Sopenharmony_ci info->winHeight, 424141cc406Sopenharmony_ci (info->resBasicX != 0) ? ((float) info->winWidth) / info->resBasicX : 0.0, 425141cc406Sopenharmony_ci (info->resBasicY) ? ((float) info->winHeight) / info->resBasicY : 0.0); 426141cc406Sopenharmony_ci 427141cc406Sopenharmony_ci DBG (1, "Summary:%s%s%s\n", 428141cc406Sopenharmony_ci info->canDuplex ? "Duplex Scanner" : "Simplex Scanner", 429141cc406Sopenharmony_ci info->canACE ? " (ACE capable)" : "", 430141cc406Sopenharmony_ci info->canCheckADF ? " (ADF Paper Sensor capable)" : ""); 431141cc406Sopenharmony_ci 432141cc406Sopenharmony_ci sprintf(inquiry_data, "Vendor: %s Product: %s Rev: %s %s%s%s\n", 433141cc406Sopenharmony_ci info->vendor, 434141cc406Sopenharmony_ci info->product, 435141cc406Sopenharmony_ci info->revision, 436141cc406Sopenharmony_ci info->canDuplex ? "Duplex Scanner" : "Simplex Scanner", 437141cc406Sopenharmony_ci info->canACE ? " (ACE capable)" : "", 438141cc406Sopenharmony_ci info->canCheckADF ? " (ADF Paper Sensor capable)" : ""); 439141cc406Sopenharmony_ci 440141cc406Sopenharmony_ci DBG (5, "autoborder_default=%d\n", info->autoborder_default); 441141cc406Sopenharmony_ci DBG (5, "batch_default=%d\n", info->batch_default); 442141cc406Sopenharmony_ci DBG (5, "deskew_default=%d\n", info->deskew_default); 443141cc406Sopenharmony_ci DBG (5, "check_adf_default=%d\n", info->check_adf_default); 444141cc406Sopenharmony_ci DBG (5, "duplex_default=%d\n", info->duplex_default); 445141cc406Sopenharmony_ci DBG (5, "timeout_adf_default=%d\n", info->timeout_adf_default); 446141cc406Sopenharmony_ci DBG (5, "timeout_manual_default=%d\n", info->timeout_manual_default); 447141cc406Sopenharmony_ci DBG (5, "control_panel_default=%d\n", info->control_panel_default); 448141cc406Sopenharmony_ci 449141cc406Sopenharmony_ci} 450141cc406Sopenharmony_ci 451141cc406Sopenharmony_cistatic SANE_Status 452141cc406Sopenharmony_citest_unit_ready (int fd) 453141cc406Sopenharmony_ci{ 454141cc406Sopenharmony_ci static SANE_Byte cmd[6]; 455141cc406Sopenharmony_ci SANE_Status status; 456141cc406Sopenharmony_ci DBG (3, "test_unit_ready called\n"); 457141cc406Sopenharmony_ci 458141cc406Sopenharmony_ci cmd[0] = BH_SCSI_TEST_UNIT_READY; 459141cc406Sopenharmony_ci memset (cmd, 0, sizeof (cmd)); 460141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); 461141cc406Sopenharmony_ci 462141cc406Sopenharmony_ci return status; 463141cc406Sopenharmony_ci} 464141cc406Sopenharmony_ci 465141cc406Sopenharmony_cistatic SANE_Status 466141cc406Sopenharmony_ciobject_position (BH_Scanner *s) 467141cc406Sopenharmony_ci{ 468141cc406Sopenharmony_ci static SANE_Byte cmd[10]; 469141cc406Sopenharmony_ci SANE_Status status; 470141cc406Sopenharmony_ci DBG (3, "object_position called\n"); 471141cc406Sopenharmony_ci 472141cc406Sopenharmony_ci memset (cmd, 0, sizeof (cmd)); 473141cc406Sopenharmony_ci cmd[0] = BH_SCSI_OBJECT_POSITION; 474141cc406Sopenharmony_ci cmd[1] = 0x01; 475141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), 0, 0); 476141cc406Sopenharmony_ci 477141cc406Sopenharmony_ci return status; 478141cc406Sopenharmony_ci} 479141cc406Sopenharmony_ci 480141cc406Sopenharmony_cistatic SANE_Status 481141cc406Sopenharmony_ciread_barcode_data (BH_Scanner *s, FILE *fp) 482141cc406Sopenharmony_ci{ 483141cc406Sopenharmony_ci static SANE_Byte cmd[10]; 484141cc406Sopenharmony_ci SANE_Status status; 485141cc406Sopenharmony_ci SANE_Int num_found = 0; 486141cc406Sopenharmony_ci double w, l, x, y, res; 487141cc406Sopenharmony_ci struct barcode_data buf; 488141cc406Sopenharmony_ci size_t buf_size = sizeof(buf); 489141cc406Sopenharmony_ci DBG (3, "read_barcode_data called\n"); 490141cc406Sopenharmony_ci 491141cc406Sopenharmony_ci memset (&cmd, 0, sizeof (cmd)); 492141cc406Sopenharmony_ci cmd[0] = BH_SCSI_READ_SCANNED_DATA; 493141cc406Sopenharmony_ci cmd[2] = s->readlist[s->readptr]; 494141cc406Sopenharmony_ci _lto3b(buf_size, &cmd[6]); /* transfer length */ 495141cc406Sopenharmony_ci 496141cc406Sopenharmony_ci s->barcode_not_found = SANE_FALSE; 497141cc406Sopenharmony_ci do { 498141cc406Sopenharmony_ci memset (&buf, 0, sizeof(buf)); 499141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), &buf, &buf_size); 500141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 501141cc406Sopenharmony_ci break; 502141cc406Sopenharmony_ci if (s->barcode_not_found == SANE_TRUE) 503141cc406Sopenharmony_ci break; 504141cc406Sopenharmony_ci 505141cc406Sopenharmony_ci num_found++; 506141cc406Sopenharmony_ci 507141cc406Sopenharmony_ci buf.barcodedata[sizeof(buf.barcodedata)-1] = '\0'; 508141cc406Sopenharmony_ci 509141cc406Sopenharmony_ci /* calculate the bounding rectangle */ 510141cc406Sopenharmony_ci x = MIN((int) _2btol(buf.posxb), (int) _2btol(buf.posxa)); 511141cc406Sopenharmony_ci y = MIN((int) _2btol(buf.posyb), (int) _2btol(buf.posyd)); 512141cc406Sopenharmony_ci w = MAX((int) _2btol(buf.posxd), (int) _2btol(buf.posxd)) - x; 513141cc406Sopenharmony_ci l = MAX((int) _2btol(buf.posya), (int) _2btol(buf.posyc)) - y; 514141cc406Sopenharmony_ci /* convert from pixels to mm */ 515141cc406Sopenharmony_ci res = _OPT_VAL_WORD(s, OPT_RESOLUTION); 516141cc406Sopenharmony_ci if (res <= 0.0) 517141cc406Sopenharmony_ci { 518141cc406Sopenharmony_ci /* avoid divide by zero */ 519141cc406Sopenharmony_ci DBG(1, "read_barcode_data: warning: " 520141cc406Sopenharmony_ci "encountered bad resolution value '%f', replacing with '%f'\n", 521141cc406Sopenharmony_ci res, 200.0); 522141cc406Sopenharmony_ci res = 200.0; 523141cc406Sopenharmony_ci } 524141cc406Sopenharmony_ci x = x * MM_PER_INCH / res; 525141cc406Sopenharmony_ci y = y * MM_PER_INCH / res; 526141cc406Sopenharmony_ci w = w * MM_PER_INCH / res; 527141cc406Sopenharmony_ci l = l * MM_PER_INCH / res; 528141cc406Sopenharmony_ci /* add a bit of a border around the edges */ 529141cc406Sopenharmony_ci x = MAX(0.0, x - BH_DECODE_FUDGE); 530141cc406Sopenharmony_ci y = MAX(0.0, y - BH_DECODE_FUDGE); 531141cc406Sopenharmony_ci w += (BH_DECODE_FUDGE * 4); 532141cc406Sopenharmony_ci l += (BH_DECODE_FUDGE * 4); 533141cc406Sopenharmony_ci 534141cc406Sopenharmony_ci /* write the decoded barcode data into the file */ 535141cc406Sopenharmony_ci fprintf(fp, "<barcode>\n <section>%s</section>\n", 536141cc406Sopenharmony_ci print_read_type((int) s->readlist[s->readptr])); 537141cc406Sopenharmony_ci fprintf(fp, " <type>%s</type>\n <status-flag>%d</status-flag>\n", 538141cc406Sopenharmony_ci print_barcodetype((int) _2btol(buf.barcodetype)), 539141cc406Sopenharmony_ci (int) _2btol(buf.statusflag)); 540141cc406Sopenharmony_ci fprintf(fp, " <orientation>%s</orientation>\n", 541141cc406Sopenharmony_ci print_orientation((int) _2btol(buf.barcodeorientation))); 542141cc406Sopenharmony_ci fprintf(fp, " <location>\n <tl><x>%d</x><y>%d</y></tl>\n", 543141cc406Sopenharmony_ci (int) _2btol(buf.posxb), (int) _2btol(buf.posyb)); 544141cc406Sopenharmony_ci fprintf(fp, " <tr><x>%d</x><y>%d</y></tr>\n", 545141cc406Sopenharmony_ci (int) _2btol(buf.posxd), (int) _2btol(buf.posyd)); 546141cc406Sopenharmony_ci fprintf(fp, " <bl><x>%d</x><y>%d</y></bl>\n", 547141cc406Sopenharmony_ci (int) _2btol(buf.posxa), (int) _2btol(buf.posya)); 548141cc406Sopenharmony_ci fprintf(fp, " <br><x>%d</x><y>%d</y></br>\n </location>\n", 549141cc406Sopenharmony_ci (int) _2btol(buf.posxc), (int) _2btol(buf.posyc)); 550141cc406Sopenharmony_ci fprintf(fp, " <rectangle>%.2fx%.2f+%.2f+%.2f</rectangle>\n", 551141cc406Sopenharmony_ci w, l, x, y); 552141cc406Sopenharmony_ci fprintf(fp, " <search-time>%d</search-time>\n <length>%d</length>\n", 553141cc406Sopenharmony_ci (int) _2btol(buf.barcodesearchtime), 554141cc406Sopenharmony_ci (int) buf.barcodelen); 555141cc406Sopenharmony_ci fprintf(fp, " <data>%s</data>\n</barcode>\n", 556141cc406Sopenharmony_ci buf.barcodedata); 557141cc406Sopenharmony_ci } while (num_found <= BH_DECODE_TRIES); 558141cc406Sopenharmony_ci 559141cc406Sopenharmony_ci DBG (3, "read_barcode_data: found %d barcodes, returning %s\n", 560141cc406Sopenharmony_ci num_found, sane_strstatus(status)); 561141cc406Sopenharmony_ci 562141cc406Sopenharmony_ci return status; 563141cc406Sopenharmony_ci} 564141cc406Sopenharmony_ci 565141cc406Sopenharmony_cistatic SANE_Status 566141cc406Sopenharmony_ciread_icon_data (BH_Scanner *s) 567141cc406Sopenharmony_ci{ 568141cc406Sopenharmony_ci static SANE_Byte cmd[10]; 569141cc406Sopenharmony_ci SANE_Status status; 570141cc406Sopenharmony_ci struct icon_data buf; 571141cc406Sopenharmony_ci size_t buf_size = sizeof(buf); 572141cc406Sopenharmony_ci DBG (3, "read_icon_data called\n"); 573141cc406Sopenharmony_ci 574141cc406Sopenharmony_ci memset (&cmd, 0, sizeof (cmd)); 575141cc406Sopenharmony_ci cmd[0] = BH_SCSI_READ_SCANNED_DATA; 576141cc406Sopenharmony_ci cmd[2] = s->readlist[s->readptr]; 577141cc406Sopenharmony_ci _lto3b(buf_size, &cmd[6]); /* transfer length */ 578141cc406Sopenharmony_ci 579141cc406Sopenharmony_ci memset (&buf, 0, sizeof(buf)); 580141cc406Sopenharmony_ci 581141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), &buf, &buf_size); 582141cc406Sopenharmony_ci 583141cc406Sopenharmony_ci /* set the fields in the scanner handle for later reference */ 584141cc406Sopenharmony_ci s->iconwidth = _4btol(buf.iconwidth); 585141cc406Sopenharmony_ci s->iconlength = _4btol(buf.iconlength); 586141cc406Sopenharmony_ci 587141cc406Sopenharmony_ci DBG(3, "read_icon_data: windowwidth:%lu, windowlength:%lu\n", 588141cc406Sopenharmony_ci _4btol(buf.windowwidth), 589141cc406Sopenharmony_ci _4btol(buf.windowlength)); 590141cc406Sopenharmony_ci DBG(3, "read_icon_data: iconwidth:%lu, iconlength:%lu, iconwidth(bytes):%lu\n", 591141cc406Sopenharmony_ci _4btol(buf.iconwidth), 592141cc406Sopenharmony_ci _4btol(buf.iconlength), 593141cc406Sopenharmony_ci _4btol(buf.iconwidthbytes)); 594141cc406Sopenharmony_ci DBG(3, "read_icon_data: bitordering:%02x, icondatalen:%lu\n", 595141cc406Sopenharmony_ci buf.bitordering, 596141cc406Sopenharmony_ci _4btol(buf.icondatalen)); 597141cc406Sopenharmony_ci 598141cc406Sopenharmony_ci DBG (3, "read_icon_data returning %d\n", status); 599141cc406Sopenharmony_ci 600141cc406Sopenharmony_ci return status; 601141cc406Sopenharmony_ci} 602141cc406Sopenharmony_ci 603141cc406Sopenharmony_cistatic SANE_Status 604141cc406Sopenharmony_ciread_barfile (BH_Scanner *s, void *buf, size_t *buf_size) 605141cc406Sopenharmony_ci{ 606141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 607141cc406Sopenharmony_ci size_t nread; 608141cc406Sopenharmony_ci DBG (3, "read_barfile called (%lu bytes)\n", (u_long) *buf_size); 609141cc406Sopenharmony_ci 610141cc406Sopenharmony_ci if (s->barf != NULL) 611141cc406Sopenharmony_ci { 612141cc406Sopenharmony_ci /* this function needs to set InvalidBytes so it looks 613141cc406Sopenharmony_ci * like a B&H scsi EOF 614141cc406Sopenharmony_ci */ 615141cc406Sopenharmony_ci if ((nread = fread(buf, 1, *buf_size, s->barf)) < *buf_size) 616141cc406Sopenharmony_ci { 617141cc406Sopenharmony_ci /* set InvalidBytes */ 618141cc406Sopenharmony_ci s->InvalidBytes = *buf_size - nread; 619141cc406Sopenharmony_ci 620141cc406Sopenharmony_ci if (ferror(s->barf)) 621141cc406Sopenharmony_ci { 622141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 623141cc406Sopenharmony_ci fclose(s->barf); 624141cc406Sopenharmony_ci s->barf = NULL; 625141cc406Sopenharmony_ci unlink(s->barfname); 626141cc406Sopenharmony_ci } 627141cc406Sopenharmony_ci else if (feof(s->barf)) 628141cc406Sopenharmony_ci { 629141cc406Sopenharmony_ci /* it also needs to close the file and delete it when EOF is 630141cc406Sopenharmony_ci * reached. 631141cc406Sopenharmony_ci */ 632141cc406Sopenharmony_ci fclose(s->barf); 633141cc406Sopenharmony_ci s->barf = NULL; 634141cc406Sopenharmony_ci unlink(s->barfname); 635141cc406Sopenharmony_ci } 636141cc406Sopenharmony_ci } 637141cc406Sopenharmony_ci } 638141cc406Sopenharmony_ci else 639141cc406Sopenharmony_ci { 640141cc406Sopenharmony_ci /* set InvalidBytes */ 641141cc406Sopenharmony_ci s->InvalidBytes = *buf_size; 642141cc406Sopenharmony_ci } 643141cc406Sopenharmony_ci 644141cc406Sopenharmony_ci return status; 645141cc406Sopenharmony_ci} 646141cc406Sopenharmony_ci 647141cc406Sopenharmony_cistatic SANE_Status 648141cc406Sopenharmony_ciread_data (BH_Scanner *s, void *buf, size_t *buf_size) 649141cc406Sopenharmony_ci{ 650141cc406Sopenharmony_ci static SANE_Byte cmd[10]; 651141cc406Sopenharmony_ci SANE_Status status; 652141cc406Sopenharmony_ci DBG (3, "read_data called (%lu bytes)\n", (u_long) *buf_size); 653141cc406Sopenharmony_ci 654141cc406Sopenharmony_ci if (s->readlist[s->readptr] == BH_SCSI_READ_TYPE_SENDBARFILE) 655141cc406Sopenharmony_ci { 656141cc406Sopenharmony_ci /* call special barcode data read function. */ 657141cc406Sopenharmony_ci status = read_barfile(s, buf, buf_size); 658141cc406Sopenharmony_ci } 659141cc406Sopenharmony_ci else 660141cc406Sopenharmony_ci { 661141cc406Sopenharmony_ci memset (&cmd, 0, sizeof (cmd)); 662141cc406Sopenharmony_ci cmd[0] = BH_SCSI_READ_SCANNED_DATA; 663141cc406Sopenharmony_ci cmd[2] = s->readlist[s->readptr]; 664141cc406Sopenharmony_ci _lto3b(*buf_size, &cmd[6]); /* transfer length */ 665141cc406Sopenharmony_ci 666141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), buf, buf_size); 667141cc406Sopenharmony_ci } 668141cc406Sopenharmony_ci 669141cc406Sopenharmony_ci return status; 670141cc406Sopenharmony_ci} 671141cc406Sopenharmony_ci 672141cc406Sopenharmony_cistatic SANE_Status 673141cc406Sopenharmony_cimode_select_measurement (BH_Scanner *s) 674141cc406Sopenharmony_ci{ 675141cc406Sopenharmony_ci static struct { 676141cc406Sopenharmony_ci SANE_Byte cmd[6]; 677141cc406Sopenharmony_ci struct mode_page_03 mp; 678141cc406Sopenharmony_ci } select_cmd; 679141cc406Sopenharmony_ci SANE_Status status; 680141cc406Sopenharmony_ci 681141cc406Sopenharmony_ci DBG (3, "mode_select_measurement called (bmu:%d mud:%d)\n", 682141cc406Sopenharmony_ci s->bmu, s->mud); 683141cc406Sopenharmony_ci 684141cc406Sopenharmony_ci memset (&select_cmd, 0, sizeof (select_cmd)); 685141cc406Sopenharmony_ci select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; 686141cc406Sopenharmony_ci select_cmd.cmd[1] = 0x10; 687141cc406Sopenharmony_ci select_cmd.cmd[4] = sizeof(select_cmd.mp); 688141cc406Sopenharmony_ci 689141cc406Sopenharmony_ci select_cmd.mp.pagecode = BH_MODE_MEASUREMENT_PAGE_CODE; 690141cc406Sopenharmony_ci select_cmd.mp.paramlen = 0x06; 691141cc406Sopenharmony_ci select_cmd.mp.bmu = s->bmu; 692141cc406Sopenharmony_ci _lto2b(s->mud, select_cmd.mp.mud); 693141cc406Sopenharmony_ci 694141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); 695141cc406Sopenharmony_ci 696141cc406Sopenharmony_ci return status; 697141cc406Sopenharmony_ci} 698141cc406Sopenharmony_ci 699141cc406Sopenharmony_cistatic SANE_Status 700141cc406Sopenharmony_cimode_select_timeout (BH_Scanner *s) 701141cc406Sopenharmony_ci{ 702141cc406Sopenharmony_ci static struct { 703141cc406Sopenharmony_ci SANE_Byte cmd[6]; 704141cc406Sopenharmony_ci struct mode_page_20 mp; 705141cc406Sopenharmony_ci } select_cmd; 706141cc406Sopenharmony_ci SANE_Status status; 707141cc406Sopenharmony_ci 708141cc406Sopenharmony_ci DBG (3, "mode_select_timeout called\n"); 709141cc406Sopenharmony_ci 710141cc406Sopenharmony_ci memset (&select_cmd, 0, sizeof (select_cmd)); 711141cc406Sopenharmony_ci select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; 712141cc406Sopenharmony_ci select_cmd.cmd[1] = 0x10; 713141cc406Sopenharmony_ci select_cmd.cmd[4] = sizeof(select_cmd.mp); 714141cc406Sopenharmony_ci 715141cc406Sopenharmony_ci select_cmd.mp.pagecode = BH_MODE_TIMEOUT_PAGE_CODE; 716141cc406Sopenharmony_ci select_cmd.mp.paramlen = 0x06; 717141cc406Sopenharmony_ci select_cmd.mp.timeoutmanual = _OPT_VAL_WORD(s, OPT_TIMEOUT_MANUAL); 718141cc406Sopenharmony_ci select_cmd.mp.timeoutadf = _OPT_VAL_WORD(s, OPT_TIMEOUT_ADF); 719141cc406Sopenharmony_ci 720141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); 721141cc406Sopenharmony_ci 722141cc406Sopenharmony_ci return status; 723141cc406Sopenharmony_ci} 724141cc406Sopenharmony_ci 725141cc406Sopenharmony_cistatic SANE_Status 726141cc406Sopenharmony_cimode_select_icon (BH_Scanner *s) 727141cc406Sopenharmony_ci{ 728141cc406Sopenharmony_ci static struct { 729141cc406Sopenharmony_ci SANE_Byte cmd[6]; 730141cc406Sopenharmony_ci struct mode_page_21 mp; 731141cc406Sopenharmony_ci } select_cmd; 732141cc406Sopenharmony_ci SANE_Status status; 733141cc406Sopenharmony_ci 734141cc406Sopenharmony_ci DBG (3, "mode_select_icon called\n"); 735141cc406Sopenharmony_ci 736141cc406Sopenharmony_ci memset (&select_cmd, 0, sizeof (select_cmd)); 737141cc406Sopenharmony_ci select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; 738141cc406Sopenharmony_ci select_cmd.cmd[1] = 0x10; 739141cc406Sopenharmony_ci select_cmd.cmd[4] = sizeof(select_cmd.mp); 740141cc406Sopenharmony_ci 741141cc406Sopenharmony_ci select_cmd.mp.pagecode = BH_MODE_ICON_PAGE_CODE; 742141cc406Sopenharmony_ci select_cmd.mp.paramlen = 0x06; 743141cc406Sopenharmony_ci _lto2b(_OPT_VAL_WORD(s, OPT_ICON_WIDTH), select_cmd.mp.iconwidth); 744141cc406Sopenharmony_ci _lto2b(_OPT_VAL_WORD(s, OPT_ICON_LENGTH), select_cmd.mp.iconlength); 745141cc406Sopenharmony_ci 746141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); 747141cc406Sopenharmony_ci 748141cc406Sopenharmony_ci return status; 749141cc406Sopenharmony_ci} 750141cc406Sopenharmony_ci 751141cc406Sopenharmony_cistatic SANE_Status 752141cc406Sopenharmony_cimode_select_barcode_priority (BH_Scanner *s) 753141cc406Sopenharmony_ci{ 754141cc406Sopenharmony_ci static struct { 755141cc406Sopenharmony_ci SANE_Byte cmd[6]; 756141cc406Sopenharmony_ci struct mode_page_30 mp; 757141cc406Sopenharmony_ci } select_cmd; 758141cc406Sopenharmony_ci SANE_Status status; 759141cc406Sopenharmony_ci int i; 760141cc406Sopenharmony_ci 761141cc406Sopenharmony_ci DBG (3, "mode_select_barcode_priority called\n"); 762141cc406Sopenharmony_ci 763141cc406Sopenharmony_ci memset (&select_cmd, 0, sizeof (select_cmd)); 764141cc406Sopenharmony_ci select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; 765141cc406Sopenharmony_ci select_cmd.cmd[1] = 0x10; 766141cc406Sopenharmony_ci select_cmd.cmd[4] = sizeof(select_cmd.mp); 767141cc406Sopenharmony_ci 768141cc406Sopenharmony_ci select_cmd.mp.pagecode = BH_MODE_BARCODE_PRIORITY_PAGE_CODE; 769141cc406Sopenharmony_ci select_cmd.mp.paramlen = 0x06; 770141cc406Sopenharmony_ci 771141cc406Sopenharmony_ci for (i = 0; i < NUM_SEARCH_BARS; i++) 772141cc406Sopenharmony_ci { 773141cc406Sopenharmony_ci /* anything after a 'none' is ignored */ 774141cc406Sopenharmony_ci if ((select_cmd.mp.priority[i] = s->search_bars[i]) == 0) break; 775141cc406Sopenharmony_ci } 776141cc406Sopenharmony_ci 777141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); 778141cc406Sopenharmony_ci 779141cc406Sopenharmony_ci return status; 780141cc406Sopenharmony_ci} 781141cc406Sopenharmony_ci 782141cc406Sopenharmony_cistatic SANE_Status 783141cc406Sopenharmony_cimode_select_barcode_param1 (BH_Scanner *s) 784141cc406Sopenharmony_ci{ 785141cc406Sopenharmony_ci static struct { 786141cc406Sopenharmony_ci SANE_Byte cmd[6]; 787141cc406Sopenharmony_ci struct mode_page_31 mp; 788141cc406Sopenharmony_ci } select_cmd; 789141cc406Sopenharmony_ci SANE_Status status; 790141cc406Sopenharmony_ci 791141cc406Sopenharmony_ci DBG (3, "mode_select_barcode_param1 called\n"); 792141cc406Sopenharmony_ci 793141cc406Sopenharmony_ci memset (&select_cmd, 0, sizeof (select_cmd)); 794141cc406Sopenharmony_ci select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; 795141cc406Sopenharmony_ci select_cmd.cmd[1] = 0x10; 796141cc406Sopenharmony_ci select_cmd.cmd[4] = sizeof(select_cmd.mp); 797141cc406Sopenharmony_ci 798141cc406Sopenharmony_ci select_cmd.mp.pagecode = BH_MODE_BARCODE_PARAM1_PAGE_CODE; 799141cc406Sopenharmony_ci select_cmd.mp.paramlen = 0x06; 800141cc406Sopenharmony_ci 801141cc406Sopenharmony_ci _lto2b((SANE_Int)_OPT_VAL_WORD_THOUSANDTHS(s, OPT_BARCODE_HMIN), select_cmd.mp.minbarheight); 802141cc406Sopenharmony_ci select_cmd.mp.searchcount = _OPT_VAL_WORD(s, OPT_BARCODE_SEARCH_COUNT); 803141cc406Sopenharmony_ci select_cmd.mp.searchmode = 804141cc406Sopenharmony_ci get_barcode_search_mode(_OPT_VAL_STRING(s, OPT_BARCODE_SEARCH_MODE)); 805141cc406Sopenharmony_ci _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_SEARCH_TIMEOUT), select_cmd.mp.searchtimeout); 806141cc406Sopenharmony_ci 807141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); 808141cc406Sopenharmony_ci 809141cc406Sopenharmony_ci return status; 810141cc406Sopenharmony_ci} 811141cc406Sopenharmony_ci 812141cc406Sopenharmony_cistatic SANE_Status 813141cc406Sopenharmony_cimode_select_barcode_param2 (BH_Scanner *s) 814141cc406Sopenharmony_ci{ 815141cc406Sopenharmony_ci static struct { 816141cc406Sopenharmony_ci SANE_Byte cmd[6]; 817141cc406Sopenharmony_ci struct mode_page_32 mp; 818141cc406Sopenharmony_ci } select_cmd; 819141cc406Sopenharmony_ci SANE_Status status; 820141cc406Sopenharmony_ci size_t len; 821141cc406Sopenharmony_ci 822141cc406Sopenharmony_ci DBG (3, "mode_select_barcode_param2 called\n"); 823141cc406Sopenharmony_ci 824141cc406Sopenharmony_ci /* first we'll do a mode sense, then we'll overwrite with 825141cc406Sopenharmony_ci * our new values, and then do a mode select 826141cc406Sopenharmony_ci */ 827141cc406Sopenharmony_ci memset (&select_cmd, 0, sizeof (select_cmd)); 828141cc406Sopenharmony_ci select_cmd.cmd[0] = BH_SCSI_MODE_SENSE; 829141cc406Sopenharmony_ci select_cmd.cmd[2] = BH_MODE_BARCODE_PARAM2_PAGE_CODE; 830141cc406Sopenharmony_ci select_cmd.cmd[4] = sizeof(select_cmd.mp); 831141cc406Sopenharmony_ci 832141cc406Sopenharmony_ci len = sizeof(select_cmd.mp); 833141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, &select_cmd.cmd, sizeof (select_cmd.cmd), 834141cc406Sopenharmony_ci &select_cmd.mp, &len); 835141cc406Sopenharmony_ci 836141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) 837141cc406Sopenharmony_ci { 838141cc406Sopenharmony_ci DBG(8, "mode_select_barcode_param2: sensed values: relmax:%d barmin:%d barmax:%d\n", 839141cc406Sopenharmony_ci (int) _2btol(select_cmd.mp.relmax), 840141cc406Sopenharmony_ci (int) _2btol(select_cmd.mp.barmin), 841141cc406Sopenharmony_ci (int) _2btol(select_cmd.mp.barmax)); 842141cc406Sopenharmony_ci 843141cc406Sopenharmony_ci memset (&select_cmd.cmd, 0, sizeof (select_cmd.cmd)); 844141cc406Sopenharmony_ci select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; 845141cc406Sopenharmony_ci select_cmd.cmd[1] = 0x10; 846141cc406Sopenharmony_ci select_cmd.cmd[4] = sizeof(select_cmd.mp); 847141cc406Sopenharmony_ci 848141cc406Sopenharmony_ci select_cmd.mp.modedatalen = 0x00; 849141cc406Sopenharmony_ci select_cmd.mp.mediumtype = 0x00; 850141cc406Sopenharmony_ci select_cmd.mp.devicespecificparam = 0x00; 851141cc406Sopenharmony_ci select_cmd.mp.blockdescriptorlen = 0x00; 852141cc406Sopenharmony_ci 853141cc406Sopenharmony_ci select_cmd.mp.pagecode = BH_MODE_BARCODE_PARAM2_PAGE_CODE; 854141cc406Sopenharmony_ci select_cmd.mp.paramlen = 0x06; 855141cc406Sopenharmony_ci 856141cc406Sopenharmony_ci /* only overwrite the default values if the option is non-zero */ 857141cc406Sopenharmony_ci if (_OPT_VAL_WORD(s, OPT_BARCODE_RELMAX) != 0) 858141cc406Sopenharmony_ci { 859141cc406Sopenharmony_ci _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_RELMAX), select_cmd.mp.relmax); 860141cc406Sopenharmony_ci } 861141cc406Sopenharmony_ci if (_OPT_VAL_WORD(s, OPT_BARCODE_BARMIN) != 0) 862141cc406Sopenharmony_ci { 863141cc406Sopenharmony_ci _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_BARMIN), select_cmd.mp.barmin); 864141cc406Sopenharmony_ci } 865141cc406Sopenharmony_ci if (_OPT_VAL_WORD(s, OPT_BARCODE_BARMAX) != 0) 866141cc406Sopenharmony_ci { 867141cc406Sopenharmony_ci _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_BARMAX), select_cmd.mp.barmax); 868141cc406Sopenharmony_ci } 869141cc406Sopenharmony_ci 870141cc406Sopenharmony_ci DBG(8, "mode_select_barcode_param2: param values: relmax:%d barmin:%d barmax:%d\n", 871141cc406Sopenharmony_ci (int) _OPT_VAL_WORD(s, OPT_BARCODE_RELMAX), 872141cc406Sopenharmony_ci (int) _OPT_VAL_WORD(s, OPT_BARCODE_BARMIN), 873141cc406Sopenharmony_ci (int) _OPT_VAL_WORD(s, OPT_BARCODE_BARMAX)); 874141cc406Sopenharmony_ci 875141cc406Sopenharmony_ci DBG(8, "mode_select_barcode_param2: select values: relmax:%d barmin:%d barmax:%d\n", 876141cc406Sopenharmony_ci (int) _2btol(select_cmd.mp.relmax), 877141cc406Sopenharmony_ci (int) _2btol(select_cmd.mp.barmin), 878141cc406Sopenharmony_ci (int) _2btol(select_cmd.mp.barmax)); 879141cc406Sopenharmony_ci 880141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); 881141cc406Sopenharmony_ci } 882141cc406Sopenharmony_ci 883141cc406Sopenharmony_ci return status; 884141cc406Sopenharmony_ci} 885141cc406Sopenharmony_ci 886141cc406Sopenharmony_cistatic SANE_Status 887141cc406Sopenharmony_cimode_select_barcode_param3 (BH_Scanner *s) 888141cc406Sopenharmony_ci{ 889141cc406Sopenharmony_ci static struct { 890141cc406Sopenharmony_ci SANE_Byte cmd[6]; 891141cc406Sopenharmony_ci struct mode_page_33 mp; 892141cc406Sopenharmony_ci } select_cmd; 893141cc406Sopenharmony_ci SANE_Status status; 894141cc406Sopenharmony_ci size_t len; 895141cc406Sopenharmony_ci 896141cc406Sopenharmony_ci DBG (3, "mode_select_barcode_param3 called\n"); 897141cc406Sopenharmony_ci 898141cc406Sopenharmony_ci /* first we'll do a mode sense, then we'll overwrite with 899141cc406Sopenharmony_ci * our new values, and then do a mode select 900141cc406Sopenharmony_ci */ 901141cc406Sopenharmony_ci memset (&select_cmd, 0, sizeof (select_cmd)); 902141cc406Sopenharmony_ci select_cmd.cmd[0] = BH_SCSI_MODE_SENSE; 903141cc406Sopenharmony_ci select_cmd.cmd[2] = BH_MODE_BARCODE_PARAM3_PAGE_CODE; 904141cc406Sopenharmony_ci select_cmd.cmd[4] = sizeof(select_cmd.mp); 905141cc406Sopenharmony_ci 906141cc406Sopenharmony_ci len = sizeof(select_cmd.mp); 907141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, &select_cmd.cmd, sizeof (select_cmd.cmd), 908141cc406Sopenharmony_ci &select_cmd.mp, &len); 909141cc406Sopenharmony_ci 910141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) 911141cc406Sopenharmony_ci { 912141cc406Sopenharmony_ci DBG(8, "mode_select_barcode_param3: sensed values: contrast:%d patchmode:%d\n", 913141cc406Sopenharmony_ci (int) _2btol(select_cmd.mp.barcodecontrast), 914141cc406Sopenharmony_ci (int) _2btol(select_cmd.mp.patchmode)); 915141cc406Sopenharmony_ci 916141cc406Sopenharmony_ci memset (&select_cmd.cmd, 0, sizeof (select_cmd.cmd)); 917141cc406Sopenharmony_ci select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; 918141cc406Sopenharmony_ci select_cmd.cmd[1] = 0x10; 919141cc406Sopenharmony_ci select_cmd.cmd[4] = sizeof(select_cmd.mp); 920141cc406Sopenharmony_ci 921141cc406Sopenharmony_ci select_cmd.mp.modedatalen = 0x00; 922141cc406Sopenharmony_ci select_cmd.mp.mediumtype = 0x00; 923141cc406Sopenharmony_ci select_cmd.mp.devicespecificparam = 0x00; 924141cc406Sopenharmony_ci select_cmd.mp.blockdescriptorlen = 0x00; 925141cc406Sopenharmony_ci 926141cc406Sopenharmony_ci select_cmd.mp.pagecode = BH_MODE_BARCODE_PARAM3_PAGE_CODE; 927141cc406Sopenharmony_ci select_cmd.mp.paramlen = 0x06; 928141cc406Sopenharmony_ci 929141cc406Sopenharmony_ci /* only overwrite the default values if the option is non-zero */ 930141cc406Sopenharmony_ci if (_OPT_VAL_WORD(s, OPT_BARCODE_CONTRAST) != 0) 931141cc406Sopenharmony_ci { 932141cc406Sopenharmony_ci _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_CONTRAST), select_cmd.mp.barcodecontrast); 933141cc406Sopenharmony_ci } 934141cc406Sopenharmony_ci if (_OPT_VAL_WORD(s, OPT_BARCODE_PATCHMODE) != 0) 935141cc406Sopenharmony_ci { 936141cc406Sopenharmony_ci _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_PATCHMODE), select_cmd.mp.patchmode); 937141cc406Sopenharmony_ci } 938141cc406Sopenharmony_ci 939141cc406Sopenharmony_ci DBG(8, "mode_select_barcode_param3: param values: contrast:%d patchmode:%d\n", 940141cc406Sopenharmony_ci (int) _OPT_VAL_WORD(s, OPT_BARCODE_CONTRAST), 941141cc406Sopenharmony_ci (int) _OPT_VAL_WORD(s, OPT_BARCODE_PATCHMODE)); 942141cc406Sopenharmony_ci 943141cc406Sopenharmony_ci DBG(8, "mode_select_barcode_param3: select values: contrast:%d patchmode:%d\n", 944141cc406Sopenharmony_ci (int) _2btol(select_cmd.mp.barcodecontrast), 945141cc406Sopenharmony_ci (int) _2btol(select_cmd.mp.patchmode)); 946141cc406Sopenharmony_ci 947141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); 948141cc406Sopenharmony_ci } 949141cc406Sopenharmony_ci 950141cc406Sopenharmony_ci return status; 951141cc406Sopenharmony_ci} 952141cc406Sopenharmony_ci 953141cc406Sopenharmony_cistatic SANE_Status 954141cc406Sopenharmony_ciinquiry (int fd, void *buf, size_t *buf_size, SANE_Byte evpd, SANE_Byte page_code) 955141cc406Sopenharmony_ci{ 956141cc406Sopenharmony_ci static SANE_Byte cmd[6]; 957141cc406Sopenharmony_ci SANE_Status status; 958141cc406Sopenharmony_ci DBG (3, "inquiry called\n"); 959141cc406Sopenharmony_ci 960141cc406Sopenharmony_ci memset (cmd, 0, sizeof (cmd)); 961141cc406Sopenharmony_ci cmd[0] = BH_SCSI_INQUIRY; 962141cc406Sopenharmony_ci cmd[1] = evpd; 963141cc406Sopenharmony_ci cmd[2] = page_code; 964141cc406Sopenharmony_ci cmd[4] = *buf_size; 965141cc406Sopenharmony_ci 966141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, buf_size); 967141cc406Sopenharmony_ci 968141cc406Sopenharmony_ci return status; 969141cc406Sopenharmony_ci} 970141cc406Sopenharmony_ci 971141cc406Sopenharmony_cistatic SANE_Status 972141cc406Sopenharmony_ciset_window (BH_Scanner *s, SANE_Byte batchmode) 973141cc406Sopenharmony_ci{ 974141cc406Sopenharmony_ci static struct { 975141cc406Sopenharmony_ci SANE_Byte cmd[10]; 976141cc406Sopenharmony_ci SANE_Byte hdr[8]; 977141cc406Sopenharmony_ci struct window_data window; 978141cc406Sopenharmony_ci } set_window_cmd; 979141cc406Sopenharmony_ci SANE_Status status; 980141cc406Sopenharmony_ci SANE_Int width, length, i, format, rotation, deskew ; 981141cc406Sopenharmony_ci 982141cc406Sopenharmony_ci DBG (3, "set_window called\n"); 983141cc406Sopenharmony_ci 984141cc406Sopenharmony_ci /* set to thousandths for set_window */ 985141cc406Sopenharmony_ci s->bmu = BH_UNIT_INCH; 986141cc406Sopenharmony_ci s->mud = 1000; 987141cc406Sopenharmony_ci status = mode_select_measurement(s); 988141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 989141cc406Sopenharmony_ci return status; 990141cc406Sopenharmony_ci 991141cc406Sopenharmony_ci memset (&set_window_cmd, 0, sizeof (set_window_cmd)); 992141cc406Sopenharmony_ci set_window_cmd.cmd[0] = BH_SCSI_SET_WINDOW; 993141cc406Sopenharmony_ci DBG(3, "set_window: sizeof(hdr) %d, sizeof(window): %d\n", 994141cc406Sopenharmony_ci (int)sizeof(set_window_cmd.hdr), (int)sizeof(set_window_cmd.window)); 995141cc406Sopenharmony_ci 996141cc406Sopenharmony_ci _lto3b(sizeof(set_window_cmd.hdr) + sizeof(set_window_cmd.window), 997141cc406Sopenharmony_ci &set_window_cmd.cmd[6]); 998141cc406Sopenharmony_ci 999141cc406Sopenharmony_ci _lto2b(256, &set_window_cmd.hdr[6]); 1000141cc406Sopenharmony_ci 1001141cc406Sopenharmony_ci set_window_cmd.window.windowid = 0; 1002141cc406Sopenharmony_ci set_window_cmd.window.autoborder = _OPT_VAL_WORD(s, OPT_AUTOBORDER); 1003141cc406Sopenharmony_ci DBG (5, "autoborder set to=%d\n", set_window_cmd.window.autoborder); 1004141cc406Sopenharmony_ci _lto2b(_OPT_VAL_WORD(s, OPT_RESOLUTION), set_window_cmd.window.xres); 1005141cc406Sopenharmony_ci _lto2b(_OPT_VAL_WORD(s, OPT_RESOLUTION), set_window_cmd.window.yres); 1006141cc406Sopenharmony_ci _lto4b((int) _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_X), set_window_cmd.window.ulx); 1007141cc406Sopenharmony_ci _lto4b((int) _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_Y), set_window_cmd.window.uly); 1008141cc406Sopenharmony_ci 1009141cc406Sopenharmony_ci width = (SANE_Int) (_OPT_VAL_WORD_THOUSANDTHS(s, OPT_BR_X) - 1010141cc406Sopenharmony_ci _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_X)); 1011141cc406Sopenharmony_ci length = (SANE_Int) (_OPT_VAL_WORD_THOUSANDTHS(s, OPT_BR_Y) - 1012141cc406Sopenharmony_ci _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_Y)); 1013141cc406Sopenharmony_ci 1014141cc406Sopenharmony_ci _lto4b(width, set_window_cmd.window.windowwidth); 1015141cc406Sopenharmony_ci _lto4b(length, set_window_cmd.window.windowlength); 1016141cc406Sopenharmony_ci 1017141cc406Sopenharmony_ci /* brightness (1-255) 0 is default, aka 128. Ignored with ACE scanners */ 1018141cc406Sopenharmony_ci set_window_cmd.window.brightness = _OPT_VAL_WORD(s, OPT_BRIGHTNESS); 1019141cc406Sopenharmony_ci /* threshold (1-255) 0 is default, aka 128. Ignored with ACE scanners */ 1020141cc406Sopenharmony_ci set_window_cmd.window.threshold = _OPT_VAL_WORD(s, OPT_THRESHOLD); 1021141cc406Sopenharmony_ci /*!!! contrast (not used) */ 1022141cc406Sopenharmony_ci /*!!! set_window_cmd.window.contrast = _OPT_VAL_WORD(s, OPT_CONTRAST); */ 1023141cc406Sopenharmony_ci /* imagecomposition 0x00 lineart, 0x01 dithered/halftone, 0x02 grayscale*/ 1024141cc406Sopenharmony_ci set_window_cmd.window.imagecomposition = 1025141cc406Sopenharmony_ci get_scan_mode_id(_OPT_VAL_STRING(s, OPT_SCAN_MODE)); 1026141cc406Sopenharmony_ci 1027141cc406Sopenharmony_ci set_window_cmd.window.bitsperpixel = 0x01; 1028141cc406Sopenharmony_ci /*!!! halftone code (not used) */ 1029141cc406Sopenharmony_ci /*!!! halftone id (not used) */ 1030141cc406Sopenharmony_ci 1031141cc406Sopenharmony_ci set_window_cmd.window.paddingtype = 0x03; /* truncate byte */ 1032141cc406Sopenharmony_ci if (_OPT_VAL_WORD(s, OPT_NEGATIVE) == SANE_TRUE) { 1033141cc406Sopenharmony_ci /* reverse image format (valid when bitsperpixel=1) 1034141cc406Sopenharmony_ci * 0x00 normal, 0x01 reversed. This is bit 7 of paddingtype. 1035141cc406Sopenharmony_ci */ 1036141cc406Sopenharmony_ci set_window_cmd.window.paddingtype |= 0x80; 1037141cc406Sopenharmony_ci } 1038141cc406Sopenharmony_ci 1039141cc406Sopenharmony_ci set_window_cmd.window.bitordering[0] = 0x00; 1040141cc406Sopenharmony_ci 1041141cc406Sopenharmony_ci /* we must always sent plain gray data in preview mode */ 1042141cc406Sopenharmony_ci format = (_OPT_VAL_WORD(s, OPT_PREVIEW)) ? 1043141cc406Sopenharmony_ci BH_COMP_NONE : 1044141cc406Sopenharmony_ci get_compression_id(_OPT_VAL_STRING(s, OPT_COMPRESSION)); 1045141cc406Sopenharmony_ci 1046141cc406Sopenharmony_ci switch (format) 1047141cc406Sopenharmony_ci { 1048141cc406Sopenharmony_ci case BH_COMP_G31D: 1049141cc406Sopenharmony_ci set_window_cmd.window.compressiontype = 0x01; 1050141cc406Sopenharmony_ci set_window_cmd.window.compressionarg = 0x00; 1051141cc406Sopenharmony_ci set_window_cmd.window.bitordering[1] = 0x01; /* Bit ordering LSB */ 1052141cc406Sopenharmony_ci break; 1053141cc406Sopenharmony_ci case BH_COMP_G32D: 1054141cc406Sopenharmony_ci set_window_cmd.window.compressiontype = 0x02; 1055141cc406Sopenharmony_ci set_window_cmd.window.compressionarg = 0x04; 1056141cc406Sopenharmony_ci set_window_cmd.window.bitordering[1] = 0x01; /* Bit ordering LSB */ 1057141cc406Sopenharmony_ci break; 1058141cc406Sopenharmony_ci case BH_COMP_G42D: 1059141cc406Sopenharmony_ci set_window_cmd.window.compressiontype = 0x03; 1060141cc406Sopenharmony_ci set_window_cmd.window.compressionarg = 0x00; 1061141cc406Sopenharmony_ci set_window_cmd.window.bitordering[1] = 0x01; /* Bit ordering LSB */ 1062141cc406Sopenharmony_ci break; 1063141cc406Sopenharmony_ci case BH_COMP_NONE: 1064141cc406Sopenharmony_ci default: 1065141cc406Sopenharmony_ci set_window_cmd.window.compressiontype = 0x00; 1066141cc406Sopenharmony_ci set_window_cmd.window.compressionarg = 0x00; 1067141cc406Sopenharmony_ci set_window_cmd.window.bitordering[1] = 0x00; /* n/a */ 1068141cc406Sopenharmony_ci break; 1069141cc406Sopenharmony_ci } 1070141cc406Sopenharmony_ci 1071141cc406Sopenharmony_ci /* rotation and deskew settings, if autoborder is turned on */ 1072141cc406Sopenharmony_ci if(set_window_cmd.window.autoborder){ /*--- setting byte 46 of the window descriptor block only works with autoborder */ 1073141cc406Sopenharmony_ci rotation = get_rotation_id(_OPT_VAL_STRING(s, OPT_ROTATION)); 1074141cc406Sopenharmony_ci if (_OPT_VAL_WORD(s, OPT_DESKEW) == SANE_TRUE) deskew = BH_DESKEW_ENABLE; 1075141cc406Sopenharmony_ci else deskew = BH_DESKEW_DISABLE; 1076141cc406Sopenharmony_ci set_window_cmd.window.border_rotation = ( rotation | deskew ); /*--- deskew assumes autoborder */ 1077141cc406Sopenharmony_ci } 1078141cc406Sopenharmony_ci 1079141cc406Sopenharmony_ci /* remote - 0x00 ACE set in window; 0x01 ACE set by control panel */ 1080141cc406Sopenharmony_ci set_window_cmd.window.remote = _OPT_VAL_WORD(s, OPT_CONTROL_PANEL); 1081141cc406Sopenharmony_ci if (set_window_cmd.window.remote == 0x00) { 1082141cc406Sopenharmony_ci /* acefunction (ignored on non-ACE scanners) */ 1083141cc406Sopenharmony_ci set_window_cmd.window.acefunction = _OPT_VAL_WORD(s, OPT_ACE_FUNCTION); 1084141cc406Sopenharmony_ci /* acesensitivity (ignored on non-ACE scanners) */ 1085141cc406Sopenharmony_ci set_window_cmd.window.acesensitivity = _OPT_VAL_WORD(s, OPT_ACE_SENSITIVITY); 1086141cc406Sopenharmony_ci } 1087141cc406Sopenharmony_ci 1088141cc406Sopenharmony_ci set_window_cmd.window.batchmode = batchmode; 1089141cc406Sopenharmony_ci 1090141cc406Sopenharmony_ci /* fill in the section descriptor blocks */ 1091141cc406Sopenharmony_ci for (i = 0; i < s->num_sections; i++) 1092141cc406Sopenharmony_ci { 1093141cc406Sopenharmony_ci BH_SectionBlock *b; 1094141cc406Sopenharmony_ci 1095141cc406Sopenharmony_ci b = &set_window_cmd.window.sectionblock[i]; 1096141cc406Sopenharmony_ci 1097141cc406Sopenharmony_ci _lto4b(s->sections[i].left, b->ul_x); 1098141cc406Sopenharmony_ci _lto4b(s->sections[i].top, b->ul_y); 1099141cc406Sopenharmony_ci _lto4b(s->sections[i].width, b->width); 1100141cc406Sopenharmony_ci _lto4b(s->sections[i].length, b->length); 1101141cc406Sopenharmony_ci b->compressiontype = s->sections[i].compressiontype; 1102141cc406Sopenharmony_ci b->compressionarg = s->sections[i].compressionarg; 1103141cc406Sopenharmony_ci } 1104141cc406Sopenharmony_ci 1105141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, &set_window_cmd, sizeof (set_window_cmd), 0, 0); 1106141cc406Sopenharmony_ci DBG (5, "sanei_scsi_cmd executed, status=%d\n", status ); 1107141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1108141cc406Sopenharmony_ci return status; 1109141cc406Sopenharmony_ci 1110141cc406Sopenharmony_ci /* set to points for reading */ 1111141cc406Sopenharmony_ci s->bmu = BH_UNIT_POINT; 1112141cc406Sopenharmony_ci s->mud = 1; 1113141cc406Sopenharmony_ci status = mode_select_measurement(s); 1114141cc406Sopenharmony_ci 1115141cc406Sopenharmony_ci return status; 1116141cc406Sopenharmony_ci} 1117141cc406Sopenharmony_ci 1118141cc406Sopenharmony_cistatic SANE_Status 1119141cc406Sopenharmony_ciget_window (BH_Scanner *s, SANE_Int *w, SANE_Int *h, SANE_Bool backpage) 1120141cc406Sopenharmony_ci{ 1121141cc406Sopenharmony_ci SANE_Byte cmd[10]; 1122141cc406Sopenharmony_ci static struct { 1123141cc406Sopenharmony_ci SANE_Byte hdr[8]; 1124141cc406Sopenharmony_ci struct window_data window; 1125141cc406Sopenharmony_ci } get_window_data; 1126141cc406Sopenharmony_ci SANE_Status status; 1127141cc406Sopenharmony_ci SANE_Int x, y, i = 0, get_window_delay = 1; 1128141cc406Sopenharmony_ci SANE_Bool autoborder; 1129141cc406Sopenharmony_ci size_t len; 1130141cc406Sopenharmony_ci 1131141cc406Sopenharmony_ci DBG (3, "get_window called\n"); 1132141cc406Sopenharmony_ci 1133141cc406Sopenharmony_ci autoborder = _OPT_VAL_WORD(s, OPT_AUTOBORDER) == 1; 1134141cc406Sopenharmony_ci 1135141cc406Sopenharmony_ci while (1) 1136141cc406Sopenharmony_ci { 1137141cc406Sopenharmony_ci i++; 1138141cc406Sopenharmony_ci memset (&cmd, 0, sizeof (cmd)); 1139141cc406Sopenharmony_ci memset (&get_window_data, 0, sizeof (get_window_data)); 1140141cc406Sopenharmony_ci 1141141cc406Sopenharmony_ci cmd[0] = BH_SCSI_GET_WINDOW; 1142141cc406Sopenharmony_ci _lto3b(sizeof(get_window_data), &cmd[6]); 1143141cc406Sopenharmony_ci 1144141cc406Sopenharmony_ci _lto2b(256, &get_window_data.hdr[6]); 1145141cc406Sopenharmony_ci 1146141cc406Sopenharmony_ci get_window_data.window.windowid = (backpage == SANE_TRUE) ? 1 : 0; 1147141cc406Sopenharmony_ci 1148141cc406Sopenharmony_ci len = sizeof(get_window_data); 1149141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 1150141cc406Sopenharmony_ci &get_window_data, &len); 1151141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) 1152141cc406Sopenharmony_ci { 1153141cc406Sopenharmony_ci x =_4btol(get_window_data.window.ulx); 1154141cc406Sopenharmony_ci y =_4btol(get_window_data.window.uly); 1155141cc406Sopenharmony_ci *w =_4btol(get_window_data.window.windowwidth); 1156141cc406Sopenharmony_ci *h =_4btol(get_window_data.window.windowlength); 1157141cc406Sopenharmony_ci 1158141cc406Sopenharmony_ci if (autoborder) 1159141cc406Sopenharmony_ci { 1160141cc406Sopenharmony_ci /* we try repeatedly until we get the autoborder bit set */ 1161141cc406Sopenharmony_ci if (get_window_data.window.autoborder != 1 && 1162141cc406Sopenharmony_ci i < BH_AUTOBORDER_TRIES) 1163141cc406Sopenharmony_ci { 1164141cc406Sopenharmony_ci DBG (5, "waiting %d second[s], try: %d\n",get_window_delay,i); 1165141cc406Sopenharmony_ci sleep(get_window_delay); /*--- page 4-5 of B&H Copiscan 8000 ESC OEM Tech Manual */ 1166141cc406Sopenharmony_ci /*--- requires at least 50ms wait between each GET WINDOW command */ 1167141cc406Sopenharmony_ci /*--- experience shows that this can take 3 to 4 seconds */ 1168141cc406Sopenharmony_ci continue; 1169141cc406Sopenharmony_ci } 1170141cc406Sopenharmony_ci if (get_window_data.window.autoborder != 1) 1171141cc406Sopenharmony_ci { 1172141cc406Sopenharmony_ci DBG(1, "Automatic Border Detection not done within %d tries\n", 1173141cc406Sopenharmony_ci BH_AUTOBORDER_TRIES); 1174141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 1175141cc406Sopenharmony_ci } 1176141cc406Sopenharmony_ci DBG (0, "page dimension: wide:%d high:%d \n",*w,*h); 1177141cc406Sopenharmony_ci } 1178141cc406Sopenharmony_ci DBG (3, "*** Window size: %dx%d+%d+%d\n", *w, *h, x, y); 1179141cc406Sopenharmony_ci DBG (5, "*** get_window found autoborder=%02xh\n", get_window_data.window.autoborder); 1180141cc406Sopenharmony_ci DBG (5, "*** get_window found border_rotation=%02xh\n", get_window_data.window.border_rotation); 1181141cc406Sopenharmony_ci } 1182141cc406Sopenharmony_ci 1183141cc406Sopenharmony_ci /* we are 'outta here' */ 1184141cc406Sopenharmony_ci break; 1185141cc406Sopenharmony_ci } 1186141cc406Sopenharmony_ci 1187141cc406Sopenharmony_ci return status; 1188141cc406Sopenharmony_ci} 1189141cc406Sopenharmony_ci 1190141cc406Sopenharmony_cistatic SANE_Status 1191141cc406Sopenharmony_ciget_parameters (SANE_Handle handle, SANE_Parameters *params) 1192141cc406Sopenharmony_ci{ 1193141cc406Sopenharmony_ci BH_Scanner *s = handle; 1194141cc406Sopenharmony_ci SANE_Int width, length, res, comp; 1195141cc406Sopenharmony_ci double br_x, tl_x, br_y, tl_y; 1196141cc406Sopenharmony_ci SANE_Frame format; 1197141cc406Sopenharmony_ci 1198141cc406Sopenharmony_ci DBG(3, "get_parameters called\n"); 1199141cc406Sopenharmony_ci 1200141cc406Sopenharmony_ci memset (&s->params, 0, sizeof (s->params)); 1201141cc406Sopenharmony_ci 1202141cc406Sopenharmony_ci res = _OPT_VAL_WORD(s, OPT_RESOLUTION); 1203141cc406Sopenharmony_ci 1204141cc406Sopenharmony_ci /* make best-effort guess at what parameters will look like once 1205141cc406Sopenharmony_ci the scan starts. */ 1206141cc406Sopenharmony_ci 1207141cc406Sopenharmony_ci br_x = _OPT_VAL_WORD_THOUSANDTHS(s, OPT_BR_X); 1208141cc406Sopenharmony_ci br_y = _OPT_VAL_WORD_THOUSANDTHS(s, OPT_BR_Y); 1209141cc406Sopenharmony_ci tl_x = _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_X); 1210141cc406Sopenharmony_ci tl_y = _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_Y); 1211141cc406Sopenharmony_ci 1212141cc406Sopenharmony_ci width = (br_x - tl_x + 1) * res / 1000.0; 1213141cc406Sopenharmony_ci length = (br_y - tl_y + 1) * res / 1000.0; 1214141cc406Sopenharmony_ci 1215141cc406Sopenharmony_ci /* figure out the default image format for front/back pages */ 1216141cc406Sopenharmony_ci comp = get_compression_id(_OPT_VAL_STRING(s, OPT_COMPRESSION)); 1217141cc406Sopenharmony_ci switch (comp) 1218141cc406Sopenharmony_ci { 1219141cc406Sopenharmony_ci case BH_COMP_G31D: 1220141cc406Sopenharmony_ci format = SANE_FRAME_G31D; 1221141cc406Sopenharmony_ci break; 1222141cc406Sopenharmony_ci case BH_COMP_G32D: 1223141cc406Sopenharmony_ci format = SANE_FRAME_G32D; 1224141cc406Sopenharmony_ci break; 1225141cc406Sopenharmony_ci case BH_COMP_G42D: 1226141cc406Sopenharmony_ci format = SANE_FRAME_G42D; 1227141cc406Sopenharmony_ci break; 1228141cc406Sopenharmony_ci case BH_COMP_NONE: 1229141cc406Sopenharmony_ci default: 1230141cc406Sopenharmony_ci format = SANE_FRAME_GRAY; 1231141cc406Sopenharmony_ci break; 1232141cc406Sopenharmony_ci } 1233141cc406Sopenharmony_ci 1234141cc406Sopenharmony_ci if (s->scanning) 1235141cc406Sopenharmony_ci { 1236141cc406Sopenharmony_ci SANE_Int w, l, status; 1237141cc406Sopenharmony_ci SANE_Byte itemtype; 1238141cc406Sopenharmony_ci 1239141cc406Sopenharmony_ci itemtype = s->readlist[s->readptr]; 1240141cc406Sopenharmony_ci /* update parameters based on the current item */ 1241141cc406Sopenharmony_ci 1242141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 1243141cc406Sopenharmony_ci if (itemtype == BH_SCSI_READ_TYPE_FRONT) 1244141cc406Sopenharmony_ci { 1245141cc406Sopenharmony_ci DBG (3, "get_parameters: sending GET WINDOW (front)\n"); 1246141cc406Sopenharmony_ci status = get_window (s, &w, &l, SANE_FALSE); 1247141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) 1248141cc406Sopenharmony_ci { 1249141cc406Sopenharmony_ci width = w; 1250141cc406Sopenharmony_ci length = l; 1251141cc406Sopenharmony_ci } 1252141cc406Sopenharmony_ci } 1253141cc406Sopenharmony_ci else if (itemtype == BH_SCSI_READ_TYPE_BACK) 1254141cc406Sopenharmony_ci { 1255141cc406Sopenharmony_ci DBG (3, "get_parameters: sending GET WINDOW (back)\n"); 1256141cc406Sopenharmony_ci status = get_window (s, &w, &l, SANE_TRUE); 1257141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) 1258141cc406Sopenharmony_ci { 1259141cc406Sopenharmony_ci width = w; 1260141cc406Sopenharmony_ci length = l; 1261141cc406Sopenharmony_ci } 1262141cc406Sopenharmony_ci } 1263141cc406Sopenharmony_ci else if (itemtype == BH_SCSI_READ_TYPE_FRONT_ICON || 1264141cc406Sopenharmony_ci itemtype == BH_SCSI_READ_TYPE_BACK_ICON) 1265141cc406Sopenharmony_ci { 1266141cc406Sopenharmony_ci /* the icon is never compressed */ 1267141cc406Sopenharmony_ci format = SANE_FRAME_GRAY; 1268141cc406Sopenharmony_ci width = s->iconwidth; 1269141cc406Sopenharmony_ci length = s->iconlength; 1270141cc406Sopenharmony_ci } 1271141cc406Sopenharmony_ci else if (itemtype > BH_SCSI_READ_TYPE_FRONT && 1272141cc406Sopenharmony_ci itemtype <= (BH_SCSI_READ_TYPE_FRONT + NUM_SECTIONS)) 1273141cc406Sopenharmony_ci { 1274141cc406Sopenharmony_ci /* a front section */ 1275141cc406Sopenharmony_ci SANE_Int sectnum = itemtype - BH_SCSI_READ_TYPE_FRONT; 1276141cc406Sopenharmony_ci 1277141cc406Sopenharmony_ci format = s->sections[sectnum - 1].format; 1278141cc406Sopenharmony_ci /* convert from thousandths to pixels */ 1279141cc406Sopenharmony_ci width = s->sections[sectnum - 1].width * res / 1000.0; 1280141cc406Sopenharmony_ci length = s->sections[sectnum - 1].length * res / 1000.0; 1281141cc406Sopenharmony_ci } 1282141cc406Sopenharmony_ci else if (itemtype > BH_SCSI_READ_TYPE_BACK && 1283141cc406Sopenharmony_ci itemtype <= (BH_SCSI_READ_TYPE_BACK + NUM_SECTIONS)) 1284141cc406Sopenharmony_ci { 1285141cc406Sopenharmony_ci /* a back section */ 1286141cc406Sopenharmony_ci SANE_Int sectnum = itemtype - BH_SCSI_READ_TYPE_BACK; 1287141cc406Sopenharmony_ci 1288141cc406Sopenharmony_ci format = s->sections[sectnum - 1].format; 1289141cc406Sopenharmony_ci /* convert from thousandths to pixels */ 1290141cc406Sopenharmony_ci width = s->sections[sectnum - 1].width * res / 1000.0; 1291141cc406Sopenharmony_ci length = s->sections[sectnum - 1].length * res / 1000.0; 1292141cc406Sopenharmony_ci } 1293141cc406Sopenharmony_ci else if ( (itemtype >= BH_SCSI_READ_TYPE_BACK_BARCODE && 1294141cc406Sopenharmony_ci itemtype <= (BH_SCSI_READ_TYPE_BACK_BARCODE + NUM_SECTIONS)) || 1295141cc406Sopenharmony_ci (itemtype >= BH_SCSI_READ_TYPE_FRONT_BARCODE && 1296141cc406Sopenharmony_ci itemtype <= (BH_SCSI_READ_TYPE_FRONT_BARCODE + NUM_SECTIONS)) ) 1297141cc406Sopenharmony_ci { 1298141cc406Sopenharmony_ci /* decoded barcode data */ 1299141cc406Sopenharmony_ci format = SANE_FRAME_TEXT; 1300141cc406Sopenharmony_ci width = 8; 1301141cc406Sopenharmony_ci length = -1; 1302141cc406Sopenharmony_ci } 1303141cc406Sopenharmony_ci else if (itemtype == BH_SCSI_READ_TYPE_SENDBARFILE) 1304141cc406Sopenharmony_ci { 1305141cc406Sopenharmony_ci /* decoded barcode data file */ 1306141cc406Sopenharmony_ci format = SANE_FRAME_TEXT; 1307141cc406Sopenharmony_ci width = 8; 1308141cc406Sopenharmony_ci length = -1; 1309141cc406Sopenharmony_ci } 1310141cc406Sopenharmony_ci else 1311141cc406Sopenharmony_ci { 1312141cc406Sopenharmony_ci format = SANE_FRAME_GRAY; 1313141cc406Sopenharmony_ci width = 8; 1314141cc406Sopenharmony_ci length = -1; 1315141cc406Sopenharmony_ci DBG(1, "get_parameters: unrecognized read itemtype: %d\n", 1316141cc406Sopenharmony_ci itemtype); 1317141cc406Sopenharmony_ci } 1318141cc406Sopenharmony_ci 1319141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1320141cc406Sopenharmony_ci { 1321141cc406Sopenharmony_ci DBG(1, "get_parameters: failed\n"); 1322141cc406Sopenharmony_ci return status; 1323141cc406Sopenharmony_ci } 1324141cc406Sopenharmony_ci } 1325141cc406Sopenharmony_ci 1326141cc406Sopenharmony_ci if (res <= 0 || width <= 0) 1327141cc406Sopenharmony_ci { 1328141cc406Sopenharmony_ci DBG(1, "get_parameters:illegal parameters res=%d, width=%d, length=%d\n", 1329141cc406Sopenharmony_ci res, width, length); 1330141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1331141cc406Sopenharmony_ci } 1332141cc406Sopenharmony_ci 1333141cc406Sopenharmony_ci /* we disable our compression/barcode formats in preview as well 1334141cc406Sopenharmony_ci * as with the disable_optional_frames configuration option. NOTE: 1335141cc406Sopenharmony_ci * we may still be delivering 'wierd' data and lying about it being _GRAY! 1336141cc406Sopenharmony_ci */ 1337141cc406Sopenharmony_ci if (format != SANE_FRAME_GRAY && 1338141cc406Sopenharmony_ci (_OPT_VAL_WORD(s, OPT_PREVIEW) || disable_optional_frames)) 1339141cc406Sopenharmony_ci { 1340141cc406Sopenharmony_ci DBG(1, "get_parameters: warning: delivering %s data as gray", 1341141cc406Sopenharmony_ci sane_strframe(format)); 1342141cc406Sopenharmony_ci format = SANE_FRAME_GRAY; 1343141cc406Sopenharmony_ci } 1344141cc406Sopenharmony_ci 1345141cc406Sopenharmony_ci s->params.format = format; 1346141cc406Sopenharmony_ci s->params.depth = 1; 1347141cc406Sopenharmony_ci s->params.last_frame = SANE_TRUE; 1348141cc406Sopenharmony_ci s->params.pixels_per_line = width; 1349141cc406Sopenharmony_ci s->params.lines = length; 1350141cc406Sopenharmony_ci s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8; 1351141cc406Sopenharmony_ci /* The Bell and Howell truncates to the byte */ 1352141cc406Sopenharmony_ci s->params.pixels_per_line = s->params.bytes_per_line * 8; 1353141cc406Sopenharmony_ci 1354141cc406Sopenharmony_ci if (params) 1355141cc406Sopenharmony_ci *params = s->params; 1356141cc406Sopenharmony_ci 1357141cc406Sopenharmony_ci DBG (1, "get_parameters: format=%d, pixels/line=%d, bytes/line=%d, " 1358141cc406Sopenharmony_ci "lines=%d, dpi=%d\n", 1359141cc406Sopenharmony_ci (int) s->params.format, 1360141cc406Sopenharmony_ci s->params.pixels_per_line, 1361141cc406Sopenharmony_ci s->params.bytes_per_line, 1362141cc406Sopenharmony_ci s->params.lines, 1363141cc406Sopenharmony_ci res); 1364141cc406Sopenharmony_ci 1365141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1366141cc406Sopenharmony_ci} 1367141cc406Sopenharmony_ci 1368141cc406Sopenharmony_cistatic SANE_Status 1369141cc406Sopenharmony_cisection_parse(const char *val, BH_Section *sect, SANE_Int res, SANE_Int comp) 1370141cc406Sopenharmony_ci{ 1371141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_INVAL; 1372141cc406Sopenharmony_ci char buf[255+1], *x, *y, *w, *l, *f, *ep; 1373141cc406Sopenharmony_ci const char *seps = "x+:"; 1374141cc406Sopenharmony_ci double mm, fpixels; 1375141cc406Sopenharmony_ci u_long pixels; 1376141cc406Sopenharmony_ci 1377141cc406Sopenharmony_ci DBG(3, "section_parse called\n"); 1378141cc406Sopenharmony_ci 1379141cc406Sopenharmony_ci /* a section option looks something like this: 1380141cc406Sopenharmony_ci * <width>x<length>+<tl-x>+<tl-y>:<functioncodes> 1381141cc406Sopenharmony_ci * Example: 1382141cc406Sopenharmony_ci * 76.2x25.4+50.8+0:frontbar:back:front 1383141cc406Sopenharmony_ci * the width, length, tl-x, and tl-y are in mm. 1384141cc406Sopenharmony_ci * the function codes are one or more of: 1385141cc406Sopenharmony_ci * front, back, frontbar, backbar, frontpatch, backpatch 1386141cc406Sopenharmony_ci */ 1387141cc406Sopenharmony_ci if (strlen(val) > sizeof(buf) - 1) 1388141cc406Sopenharmony_ci { 1389141cc406Sopenharmony_ci DBG(1, "section_parse: option string too long\n"); 1390141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 1391141cc406Sopenharmony_ci } 1392141cc406Sopenharmony_ci else 1393141cc406Sopenharmony_ci { 1394141cc406Sopenharmony_ci do { 1395141cc406Sopenharmony_ci strcpy(buf, val); 1396141cc406Sopenharmony_ci 1397141cc406Sopenharmony_ci x = y = w = l = f = NULL; 1398141cc406Sopenharmony_ci w = strtok(buf, seps); 1399141cc406Sopenharmony_ci if (w) l = strtok(NULL, seps); 1400141cc406Sopenharmony_ci if (l) x = strtok(NULL, seps); 1401141cc406Sopenharmony_ci if (x) y = strtok(NULL, seps); 1402141cc406Sopenharmony_ci if (y) f = strtok(NULL, seps); 1403141cc406Sopenharmony_ci if (!x || !y || !w || !l) break; 1404141cc406Sopenharmony_ci 1405141cc406Sopenharmony_ci mm = strtod(x, &ep); 1406141cc406Sopenharmony_ci if (*ep != '\0' || errno == ERANGE || mm < 0.0) break; 1407141cc406Sopenharmony_ci sect->left = mm * 1000.0 / MM_PER_INCH; 1408141cc406Sopenharmony_ci 1409141cc406Sopenharmony_ci mm = strtod(y, &ep); 1410141cc406Sopenharmony_ci if (*ep != '\0' || errno == ERANGE || mm < 0.0) break; 1411141cc406Sopenharmony_ci sect->top = mm * 1000.0 / MM_PER_INCH; 1412141cc406Sopenharmony_ci 1413141cc406Sopenharmony_ci mm = strtod(w, &ep); 1414141cc406Sopenharmony_ci if (*ep != '\0' || errno == ERANGE || mm < 0.0) break; 1415141cc406Sopenharmony_ci sect->width = mm * 1000.0 / MM_PER_INCH; 1416141cc406Sopenharmony_ci /* the window width must be truncated to 16 bit points */ 1417141cc406Sopenharmony_ci fpixels = sect->width * res / 1000.0; 1418141cc406Sopenharmony_ci pixels = fpixels / 16; 1419141cc406Sopenharmony_ci sect->width = pixels * 16 * 1000 / res; 1420141cc406Sopenharmony_ci 1421141cc406Sopenharmony_ci mm = strtod(l, &ep); 1422141cc406Sopenharmony_ci if (*ep != '\0' || errno == ERANGE || mm < 0.0) break; 1423141cc406Sopenharmony_ci sect->length = mm * 1000.0 / MM_PER_INCH; 1424141cc406Sopenharmony_ci 1425141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 1426141cc406Sopenharmony_ci while (f) 1427141cc406Sopenharmony_ci { 1428141cc406Sopenharmony_ci /* parse the function modifiers and set flags */ 1429141cc406Sopenharmony_ci if (strcmp(f, "front") == 0) 1430141cc406Sopenharmony_ci sect->flags |= BH_SECTION_FRONT_IMAGE; 1431141cc406Sopenharmony_ci else if (strcmp(f, "frontbar") == 0) 1432141cc406Sopenharmony_ci sect->flags |= BH_SECTION_FRONT_BAR; 1433141cc406Sopenharmony_ci else if (strcmp(f, "frontpatch") == 0) 1434141cc406Sopenharmony_ci sect->flags |= BH_SECTION_FRONT_PATCH; 1435141cc406Sopenharmony_ci else if (strcmp(f, "back") == 0) 1436141cc406Sopenharmony_ci sect->flags |= BH_SECTION_BACK_IMAGE; 1437141cc406Sopenharmony_ci else if (strcmp(f, "backbar") == 0) 1438141cc406Sopenharmony_ci sect->flags |= BH_SECTION_BACK_BAR; 1439141cc406Sopenharmony_ci else if (strcmp(f, "backpatch") == 0) 1440141cc406Sopenharmony_ci sect->flags |= BH_SECTION_BACK_PATCH; 1441141cc406Sopenharmony_ci else if (strcmp(f, "g42d") == 0) 1442141cc406Sopenharmony_ci comp = BH_COMP_G42D; 1443141cc406Sopenharmony_ci else if (strcmp(f, "g32d") == 0) 1444141cc406Sopenharmony_ci comp = BH_COMP_G32D; 1445141cc406Sopenharmony_ci else if (strcmp(f, "g31d") == 0) 1446141cc406Sopenharmony_ci comp = BH_COMP_G31D; 1447141cc406Sopenharmony_ci else if (strcmp(f, "none") == 0) 1448141cc406Sopenharmony_ci comp = BH_COMP_NONE; 1449141cc406Sopenharmony_ci else 1450141cc406Sopenharmony_ci DBG(1, "section_parse: ignoring unrecognized function " 1451141cc406Sopenharmony_ci "code '%s'\n", f); 1452141cc406Sopenharmony_ci 1453141cc406Sopenharmony_ci f = strtok(NULL, seps); 1454141cc406Sopenharmony_ci } 1455141cc406Sopenharmony_ci 1456141cc406Sopenharmony_ci switch (comp) 1457141cc406Sopenharmony_ci { 1458141cc406Sopenharmony_ci case BH_COMP_G31D: 1459141cc406Sopenharmony_ci sect->compressiontype = 0x01; 1460141cc406Sopenharmony_ci sect->compressionarg = 0x00; 1461141cc406Sopenharmony_ci sect->format = SANE_FRAME_G31D; 1462141cc406Sopenharmony_ci break; 1463141cc406Sopenharmony_ci case BH_COMP_G32D: 1464141cc406Sopenharmony_ci sect->compressiontype = 0x02; 1465141cc406Sopenharmony_ci sect->compressionarg = 0x04; 1466141cc406Sopenharmony_ci sect->format = SANE_FRAME_G32D; 1467141cc406Sopenharmony_ci break; 1468141cc406Sopenharmony_ci case BH_COMP_G42D: 1469141cc406Sopenharmony_ci sect->compressiontype = 0x03; 1470141cc406Sopenharmony_ci sect->compressionarg = 0x00; 1471141cc406Sopenharmony_ci sect->format = SANE_FRAME_G42D; 1472141cc406Sopenharmony_ci break; 1473141cc406Sopenharmony_ci case BH_COMP_NONE: 1474141cc406Sopenharmony_ci default: 1475141cc406Sopenharmony_ci sect->compressiontype = 0x00; 1476141cc406Sopenharmony_ci sect->compressionarg = 0x00; 1477141cc406Sopenharmony_ci sect->format = SANE_FRAME_GRAY; 1478141cc406Sopenharmony_ci break; 1479141cc406Sopenharmony_ci } 1480141cc406Sopenharmony_ci 1481141cc406Sopenharmony_ci DBG(3, "section_parse: converted '%s' (mm) to " 1482141cc406Sopenharmony_ci "%ldx%ld+%ld+%ld (thousandths) " 1483141cc406Sopenharmony_ci "flags=%02x compression=[%d,%d] frame=%s\n", 1484141cc406Sopenharmony_ci val, 1485141cc406Sopenharmony_ci sect->width, sect->length, sect->left, sect->top, 1486141cc406Sopenharmony_ci sect->flags, 1487141cc406Sopenharmony_ci sect->compressiontype, sect->compressionarg, 1488141cc406Sopenharmony_ci sane_strframe(sect->format)); 1489141cc406Sopenharmony_ci 1490141cc406Sopenharmony_ci } while (0); /* perform 'loop' once */ 1491141cc406Sopenharmony_ci } 1492141cc406Sopenharmony_ci 1493141cc406Sopenharmony_ci return status; 1494141cc406Sopenharmony_ci} 1495141cc406Sopenharmony_ci 1496141cc406Sopenharmony_cistatic SANE_Status 1497141cc406Sopenharmony_cisetup_sections (BH_Scanner *s, const char *val) 1498141cc406Sopenharmony_ci{ 1499141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 1500141cc406Sopenharmony_ci SANE_Int sectnum = 0; 1501141cc406Sopenharmony_ci char buf[255+1], *section; 1502141cc406Sopenharmony_ci 1503141cc406Sopenharmony_ci DBG(3, "setup_sections called\n"); 1504141cc406Sopenharmony_ci 1505141cc406Sopenharmony_ci memset(s->sections, '\0', sizeof(s->sections)); 1506141cc406Sopenharmony_ci if (strlen(val) > sizeof(buf) - 1) 1507141cc406Sopenharmony_ci { 1508141cc406Sopenharmony_ci DBG(1, "setup_sections: option string too long\n"); 1509141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 1510141cc406Sopenharmony_ci } 1511141cc406Sopenharmony_ci else 1512141cc406Sopenharmony_ci { 1513141cc406Sopenharmony_ci strcpy(buf, val); 1514141cc406Sopenharmony_ci 1515141cc406Sopenharmony_ci section = strtok(buf, ","); 1516141cc406Sopenharmony_ci while (section != NULL && sectnum < NUM_SECTIONS) 1517141cc406Sopenharmony_ci { 1518141cc406Sopenharmony_ci if (!allblank(section)) 1519141cc406Sopenharmony_ci { 1520141cc406Sopenharmony_ci SANE_Int res = _OPT_VAL_WORD(s, OPT_RESOLUTION); 1521141cc406Sopenharmony_ci SANE_Int format = 1522141cc406Sopenharmony_ci get_compression_id(_OPT_VAL_STRING(s, OPT_COMPRESSION)); 1523141cc406Sopenharmony_ci 1524141cc406Sopenharmony_ci status = section_parse(section, &s->sections[sectnum], 1525141cc406Sopenharmony_ci res, format); 1526141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1527141cc406Sopenharmony_ci { 1528141cc406Sopenharmony_ci DBG(1, 1529141cc406Sopenharmony_ci "setup_sections: error parsing section `%s'\n", 1530141cc406Sopenharmony_ci section); 1531141cc406Sopenharmony_ci break; 1532141cc406Sopenharmony_ci } 1533141cc406Sopenharmony_ci 1534141cc406Sopenharmony_ci sectnum++; 1535141cc406Sopenharmony_ci } 1536141cc406Sopenharmony_ci section += strlen(section) + 1; 1537141cc406Sopenharmony_ci if (section > buf + strlen(val)) break; 1538141cc406Sopenharmony_ci 1539141cc406Sopenharmony_ci section = strtok(section, ","); 1540141cc406Sopenharmony_ci } 1541141cc406Sopenharmony_ci } 1542141cc406Sopenharmony_ci s->num_sections = sectnum; 1543141cc406Sopenharmony_ci 1544141cc406Sopenharmony_ci return status; 1545141cc406Sopenharmony_ci} 1546141cc406Sopenharmony_ci 1547141cc406Sopenharmony_cistatic SANE_Status 1548141cc406Sopenharmony_cistart_setup (BH_Scanner *s) 1549141cc406Sopenharmony_ci{ 1550141cc406Sopenharmony_ci SANE_Status status; 1551141cc406Sopenharmony_ci SANE_Bool duplex; 1552141cc406Sopenharmony_ci SANE_Int i, imagecnt; 1553141cc406Sopenharmony_ci SANE_Byte batchmode; 1554141cc406Sopenharmony_ci 1555141cc406Sopenharmony_ci DBG(3, "start_setup called\n"); 1556141cc406Sopenharmony_ci 1557141cc406Sopenharmony_ci duplex = _OPT_VAL_WORD(s, OPT_DUPLEX); 1558141cc406Sopenharmony_ci 1559141cc406Sopenharmony_ci /* get the _SECTION option, parse it and fill in the sections */ 1560141cc406Sopenharmony_ci status = setup_sections(s, _OPT_VAL_STRING(s, OPT_SECTION)); 1561141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1562141cc406Sopenharmony_ci { 1563141cc406Sopenharmony_ci DBG(1, "start_setup: setup_sections failed: %s\n", 1564141cc406Sopenharmony_ci sane_strstatus(status)); 1565141cc406Sopenharmony_ci return status; 1566141cc406Sopenharmony_ci } 1567141cc406Sopenharmony_ci 1568141cc406Sopenharmony_ci /* see whether we'll be decoding barcodes and 1569141cc406Sopenharmony_ci * set the barcodes flag appropriately 1570141cc406Sopenharmony_ci */ 1571141cc406Sopenharmony_ci if (s->search_bars[0] == 0) 1572141cc406Sopenharmony_ci { 1573141cc406Sopenharmony_ci s->barcodes = SANE_FALSE; 1574141cc406Sopenharmony_ci } 1575141cc406Sopenharmony_ci else 1576141cc406Sopenharmony_ci { 1577141cc406Sopenharmony_ci s->barcodes = SANE_TRUE; 1578141cc406Sopenharmony_ci } 1579141cc406Sopenharmony_ci 1580141cc406Sopenharmony_ci /* see whether we'll be handling icons (thumbnails) 1581141cc406Sopenharmony_ci * set the icons flag appropriately 1582141cc406Sopenharmony_ci */ 1583141cc406Sopenharmony_ci if (_OPT_VAL_WORD(s, OPT_ICON_WIDTH) >= 8 && 1584141cc406Sopenharmony_ci _OPT_VAL_WORD(s, OPT_ICON_LENGTH) >= 8) 1585141cc406Sopenharmony_ci { 1586141cc406Sopenharmony_ci s->icons = SANE_TRUE; 1587141cc406Sopenharmony_ci } 1588141cc406Sopenharmony_ci else 1589141cc406Sopenharmony_ci { 1590141cc406Sopenharmony_ci s->icons = SANE_FALSE; 1591141cc406Sopenharmony_ci } 1592141cc406Sopenharmony_ci 1593141cc406Sopenharmony_ci 1594141cc406Sopenharmony_ci /* calculate a new readlist for this 'batch' */ 1595141cc406Sopenharmony_ci s->readptr = s->readcnt = 0; 1596141cc406Sopenharmony_ci 1597141cc406Sopenharmony_ci /* always read the front image */ 1598141cc406Sopenharmony_ci s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT; 1599141cc406Sopenharmony_ci 1600141cc406Sopenharmony_ci /* read back page only if duplex is true */ 1601141cc406Sopenharmony_ci if (duplex == SANE_TRUE) 1602141cc406Sopenharmony_ci { 1603141cc406Sopenharmony_ci s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK; 1604141cc406Sopenharmony_ci } 1605141cc406Sopenharmony_ci 1606141cc406Sopenharmony_ci /* add image section reads to the readlist */ 1607141cc406Sopenharmony_ci for (i = 0; i < s->num_sections; i++) 1608141cc406Sopenharmony_ci { 1609141cc406Sopenharmony_ci SANE_Word flags = s->sections[i].flags; 1610141cc406Sopenharmony_ci 1611141cc406Sopenharmony_ci if (flags & BH_SECTION_FRONT_IMAGE) 1612141cc406Sopenharmony_ci s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT + i + 1; 1613141cc406Sopenharmony_ci if (flags & BH_SECTION_BACK_IMAGE) 1614141cc406Sopenharmony_ci s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK + i + 1; 1615141cc406Sopenharmony_ci } 1616141cc406Sopenharmony_ci 1617141cc406Sopenharmony_ci 1618141cc406Sopenharmony_ci /* icons (thumbnails) */ 1619141cc406Sopenharmony_ci if (s->icons) 1620141cc406Sopenharmony_ci { 1621141cc406Sopenharmony_ci s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT_ICON; 1622141cc406Sopenharmony_ci /* read back icon only if duplex is true */ 1623141cc406Sopenharmony_ci if (duplex == SANE_TRUE) 1624141cc406Sopenharmony_ci { 1625141cc406Sopenharmony_ci s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK_ICON; 1626141cc406Sopenharmony_ci } 1627141cc406Sopenharmony_ci } 1628141cc406Sopenharmony_ci 1629141cc406Sopenharmony_ci /* NOTE: It is important that all of the image data comes before 1630141cc406Sopenharmony_ci * the barcode/patchcode data. 1631141cc406Sopenharmony_ci */ 1632141cc406Sopenharmony_ci /* barcodes */ 1633141cc406Sopenharmony_ci imagecnt = s->readcnt; 1634141cc406Sopenharmony_ci if (s->barcodes) 1635141cc406Sopenharmony_ci { 1636141cc406Sopenharmony_ci if (s->num_sections == 0) 1637141cc406Sopenharmony_ci { 1638141cc406Sopenharmony_ci /* we only decode the entire page(s) if there are no 1639141cc406Sopenharmony_ci * sections defined 1640141cc406Sopenharmony_ci */ 1641141cc406Sopenharmony_ci s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT_BARCODE; 1642141cc406Sopenharmony_ci /* read back barcode only if duplex is true */ 1643141cc406Sopenharmony_ci if (duplex == SANE_TRUE) 1644141cc406Sopenharmony_ci { 1645141cc406Sopenharmony_ci s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK_BARCODE; 1646141cc406Sopenharmony_ci } 1647141cc406Sopenharmony_ci } 1648141cc406Sopenharmony_ci else 1649141cc406Sopenharmony_ci { 1650141cc406Sopenharmony_ci /* add barcode section reads to the readlist */ 1651141cc406Sopenharmony_ci for (i = 0; i < s->num_sections; i++) 1652141cc406Sopenharmony_ci { 1653141cc406Sopenharmony_ci SANE_Word flags = s->sections[i].flags; 1654141cc406Sopenharmony_ci 1655141cc406Sopenharmony_ci if (flags & BH_SECTION_FRONT_BAR) 1656141cc406Sopenharmony_ci s->readlist[s->readcnt++] = 1657141cc406Sopenharmony_ci BH_SCSI_READ_TYPE_FRONT_BARCODE + i + 1; 1658141cc406Sopenharmony_ci if (flags & BH_SECTION_BACK_BAR) 1659141cc406Sopenharmony_ci s->readlist[s->readcnt++] = 1660141cc406Sopenharmony_ci BH_SCSI_READ_TYPE_BACK_BARCODE + i + 1; 1661141cc406Sopenharmony_ci } 1662141cc406Sopenharmony_ci } 1663141cc406Sopenharmony_ci } 1664141cc406Sopenharmony_ci 1665141cc406Sopenharmony_ci /* patchcodes */ 1666141cc406Sopenharmony_ci if (s->patchcodes) 1667141cc406Sopenharmony_ci { 1668141cc406Sopenharmony_ci if (s->num_sections == 0) 1669141cc406Sopenharmony_ci { 1670141cc406Sopenharmony_ci /* we only decode the entire page(s) if there are no 1671141cc406Sopenharmony_ci * sections defined 1672141cc406Sopenharmony_ci */ 1673141cc406Sopenharmony_ci s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT_PATCHCODE; 1674141cc406Sopenharmony_ci /* read back patchcode only if duplex is true */ 1675141cc406Sopenharmony_ci if (duplex == SANE_TRUE) 1676141cc406Sopenharmony_ci { 1677141cc406Sopenharmony_ci s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK_PATCHCODE; 1678141cc406Sopenharmony_ci } 1679141cc406Sopenharmony_ci } 1680141cc406Sopenharmony_ci else 1681141cc406Sopenharmony_ci { 1682141cc406Sopenharmony_ci /* add patchcode section reads to the readlist */ 1683141cc406Sopenharmony_ci for (i = 0; i < s->num_sections; i++) 1684141cc406Sopenharmony_ci { 1685141cc406Sopenharmony_ci SANE_Word flags = s->sections[i].flags; 1686141cc406Sopenharmony_ci 1687141cc406Sopenharmony_ci if (flags & BH_SECTION_FRONT_PATCH) 1688141cc406Sopenharmony_ci s->readlist[s->readcnt++] = 1689141cc406Sopenharmony_ci BH_SCSI_READ_TYPE_FRONT_PATCHCODE + i + 1; 1690141cc406Sopenharmony_ci if (flags & BH_SECTION_BACK_PATCH) 1691141cc406Sopenharmony_ci s->readlist[s->readcnt++] = 1692141cc406Sopenharmony_ci BH_SCSI_READ_TYPE_BACK_PATCHCODE + i + 1; 1693141cc406Sopenharmony_ci } 1694141cc406Sopenharmony_ci } 1695141cc406Sopenharmony_ci } 1696141cc406Sopenharmony_ci 1697141cc406Sopenharmony_ci /* add the special item to the read list which transfers the barcode 1698141cc406Sopenharmony_ci * file that's built as a result of processing barcode and patchcode 1699141cc406Sopenharmony_ci * readitems. NOTE: this one must be last! 1700141cc406Sopenharmony_ci */ 1701141cc406Sopenharmony_ci if (s->readcnt > imagecnt) 1702141cc406Sopenharmony_ci { 1703141cc406Sopenharmony_ci s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_SENDBARFILE; 1704141cc406Sopenharmony_ci } 1705141cc406Sopenharmony_ci 1706141cc406Sopenharmony_ci if (_OPT_VAL_WORD(s, OPT_BATCH) == SANE_TRUE) 1707141cc406Sopenharmony_ci { 1708141cc406Sopenharmony_ci /* if batchmode is enabled, then call set_window to 1709141cc406Sopenharmony_ci * abort the batch (even though there might not (and probably 1710141cc406Sopenharmony_ci * isn't) a batch in progress). This avoids a batch start error 1711141cc406Sopenharmony_ci * in the case where a previous batch was not aborted. 1712141cc406Sopenharmony_ci */ 1713141cc406Sopenharmony_ci DBG(5, "start_setup: calling set_window to abort batch\n"); 1714141cc406Sopenharmony_ci set_window(s, BH_BATCH_ABORT); 1715141cc406Sopenharmony_ci 1716141cc406Sopenharmony_ci batchmode = BH_BATCH_ENABLE; 1717141cc406Sopenharmony_ci } 1718141cc406Sopenharmony_ci else 1719141cc406Sopenharmony_ci { 1720141cc406Sopenharmony_ci batchmode = BH_BATCH_DISABLE; 1721141cc406Sopenharmony_ci } 1722141cc406Sopenharmony_ci 1723141cc406Sopenharmony_ci DBG(5, "start_setup: duplex=%s, barcodes=%s, patchcodes=%s, " 1724141cc406Sopenharmony_ci "icons=%s, batch=%s\n", 1725141cc406Sopenharmony_ci (duplex == SANE_TRUE) ? "yes" : "no", 1726141cc406Sopenharmony_ci (s->barcodes == SANE_TRUE) ? "yes" : "no", 1727141cc406Sopenharmony_ci (s->patchcodes == SANE_TRUE) ? "yes" : "no", 1728141cc406Sopenharmony_ci (s->icons == SANE_TRUE) ? "yes" : "no", 1729141cc406Sopenharmony_ci (batchmode == BH_BATCH_ENABLE) ? "yes" : "no"); 1730141cc406Sopenharmony_ci DBG(5, "start_setup: sections=%d\n", s->num_sections); 1731141cc406Sopenharmony_ci for (i = 0; i < s->num_sections; i++) 1732141cc406Sopenharmony_ci { 1733141cc406Sopenharmony_ci DBG(5, "start_setup: " 1734141cc406Sopenharmony_ci "[%d] %lux%lu+%lu+%lu flags=%02x compression=[%d,%d]\n", 1735141cc406Sopenharmony_ci i+1, 1736141cc406Sopenharmony_ci s->sections[i].width, s->sections[i].length, 1737141cc406Sopenharmony_ci s->sections[i].left, s->sections[i].top, 1738141cc406Sopenharmony_ci s->sections[i].flags, 1739141cc406Sopenharmony_ci s->sections[i].compressiontype, s->sections[i].compressionarg); 1740141cc406Sopenharmony_ci } 1741141cc406Sopenharmony_ci DBG(5, "start_setup: read list length=%d\n", s->readcnt); 1742141cc406Sopenharmony_ci for (i = 0; i < s->readcnt; i++) 1743141cc406Sopenharmony_ci { 1744141cc406Sopenharmony_ci DBG(5, "start_setup: [%d] %s\n", i+1, print_read_type(s->readlist[i])); 1745141cc406Sopenharmony_ci } 1746141cc406Sopenharmony_ci 1747141cc406Sopenharmony_ci DBG(5, "start_setup: sending SET WINDOW\n"); 1748141cc406Sopenharmony_ci status = set_window(s, batchmode); 1749141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1750141cc406Sopenharmony_ci { 1751141cc406Sopenharmony_ci DBG(1, "start_setup: SET WINDOW failed: %s\n", 1752141cc406Sopenharmony_ci sane_strstatus(status)); 1753141cc406Sopenharmony_ci return status; 1754141cc406Sopenharmony_ci } 1755141cc406Sopenharmony_ci 1756141cc406Sopenharmony_ci DBG(5, "start_setup: sending mode_select_timeout\n"); 1757141cc406Sopenharmony_ci status = mode_select_timeout(s); 1758141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1759141cc406Sopenharmony_ci { 1760141cc406Sopenharmony_ci DBG(1, "start_setup: mode_select_timeout failed: %s\n", 1761141cc406Sopenharmony_ci sane_strstatus(status)); 1762141cc406Sopenharmony_ci return status; 1763141cc406Sopenharmony_ci } 1764141cc406Sopenharmony_ci 1765141cc406Sopenharmony_ci if (s->icons == SANE_TRUE) 1766141cc406Sopenharmony_ci { 1767141cc406Sopenharmony_ci DBG(5, "start_setup: sending mode_select_icon\n"); 1768141cc406Sopenharmony_ci status = mode_select_icon(s); 1769141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1770141cc406Sopenharmony_ci { 1771141cc406Sopenharmony_ci DBG(1, "start_setup: mode_select_icon failed: %s\n", 1772141cc406Sopenharmony_ci sane_strstatus(status)); 1773141cc406Sopenharmony_ci return status; 1774141cc406Sopenharmony_ci } 1775141cc406Sopenharmony_ci } 1776141cc406Sopenharmony_ci 1777141cc406Sopenharmony_ci if (s->barcodes == SANE_TRUE) 1778141cc406Sopenharmony_ci { 1779141cc406Sopenharmony_ci DBG(5, "start_setup: sending mode_select_barcode_priority\n"); 1780141cc406Sopenharmony_ci status = mode_select_barcode_priority(s); 1781141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1782141cc406Sopenharmony_ci { 1783141cc406Sopenharmony_ci DBG(1, "start_setup: mode_select_barcode_priority failed: %s\n", 1784141cc406Sopenharmony_ci sane_strstatus(status)); 1785141cc406Sopenharmony_ci return status; 1786141cc406Sopenharmony_ci } 1787141cc406Sopenharmony_ci 1788141cc406Sopenharmony_ci DBG(5, "start_setup: sending mode_select_barcode_param1\n"); 1789141cc406Sopenharmony_ci status = mode_select_barcode_param1(s); 1790141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1791141cc406Sopenharmony_ci { 1792141cc406Sopenharmony_ci DBG(1, "start_setup: mode_select_barcode_param1 failed: %s\n", 1793141cc406Sopenharmony_ci sane_strstatus(status)); 1794141cc406Sopenharmony_ci return status; 1795141cc406Sopenharmony_ci } 1796141cc406Sopenharmony_ci 1797141cc406Sopenharmony_ci DBG(5, "start_setup: sending mode_select_barcode_param2\n"); 1798141cc406Sopenharmony_ci status = mode_select_barcode_param2(s); 1799141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1800141cc406Sopenharmony_ci { 1801141cc406Sopenharmony_ci DBG(1, "start_setup: mode_select_barcode_param2 failed: %s\n", 1802141cc406Sopenharmony_ci sane_strstatus(status)); 1803141cc406Sopenharmony_ci return status; 1804141cc406Sopenharmony_ci } 1805141cc406Sopenharmony_ci 1806141cc406Sopenharmony_ci DBG(5, "start_setup: sending mode_select_barcode_param3\n"); 1807141cc406Sopenharmony_ci status = mode_select_barcode_param3(s); 1808141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1809141cc406Sopenharmony_ci { 1810141cc406Sopenharmony_ci DBG(1, "start_setup: mode_select_barcode_param3 failed: %s\n", 1811141cc406Sopenharmony_ci sane_strstatus(status)); 1812141cc406Sopenharmony_ci return status; 1813141cc406Sopenharmony_ci } 1814141cc406Sopenharmony_ci } 1815141cc406Sopenharmony_ci 1816141cc406Sopenharmony_ci return status; 1817141cc406Sopenharmony_ci} 1818141cc406Sopenharmony_ci 1819141cc406Sopenharmony_cistatic SANE_Status 1820141cc406Sopenharmony_cistart_scan (BH_Scanner *s) 1821141cc406Sopenharmony_ci{ 1822141cc406Sopenharmony_ci static SANE_Byte cmd[8]; 1823141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 1824141cc406Sopenharmony_ci SANE_Bool check_adf, duplex; 1825141cc406Sopenharmony_ci DBG (3, "start_scan called\n"); 1826141cc406Sopenharmony_ci 1827141cc406Sopenharmony_ci /* SANE front ends will call this function between 'FRAMES'. 1828141cc406Sopenharmony_ci * A single scan on the B&H may result in up to 56 different 1829141cc406Sopenharmony_ci * things to read (20 are SANE image frames, 36 are non-SANE 1830141cc406Sopenharmony_ci * data - decoded bar/patch codes). 1831141cc406Sopenharmony_ci */ 1832141cc406Sopenharmony_ci 1833141cc406Sopenharmony_ci if (s->readcnt > 1 && s->scanning == SANE_TRUE) 1834141cc406Sopenharmony_ci { 1835141cc406Sopenharmony_ci DBG(3, "start_scan: any more items in the readlist?\n"); 1836141cc406Sopenharmony_ci /* we've been reading data from this scan, so we just 1837141cc406Sopenharmony_ci * move on to the next item in the readlist without 1838141cc406Sopenharmony_ci * starting a new scan. 1839141cc406Sopenharmony_ci */ 1840141cc406Sopenharmony_ci s->readptr++; 1841141cc406Sopenharmony_ci if (s->readptr < s->readcnt) 1842141cc406Sopenharmony_ci { 1843141cc406Sopenharmony_ci SANE_Byte itemtype; 1844141cc406Sopenharmony_ci 1845141cc406Sopenharmony_ci for (; s->readptr < s->readcnt; s->readptr++) 1846141cc406Sopenharmony_ci { 1847141cc406Sopenharmony_ci 1848141cc406Sopenharmony_ci itemtype = s->readlist[s->readptr]; 1849141cc406Sopenharmony_ci 1850141cc406Sopenharmony_ci DBG(3, "start_scan: advance readlist(%d, %d)\n", 1851141cc406Sopenharmony_ci s->readptr, 1852141cc406Sopenharmony_ci (int) itemtype); 1853141cc406Sopenharmony_ci 1854141cc406Sopenharmony_ci /* 'dance' by the non-SANE data streams 1855141cc406Sopenharmony_ci * like bar/patch code data 1856141cc406Sopenharmony_ci */ 1857141cc406Sopenharmony_ci if (!BH_HAS_IMAGE_DATA(itemtype)) 1858141cc406Sopenharmony_ci { 1859141cc406Sopenharmony_ci int fd; 1860141cc406Sopenharmony_ci FILE *fp; 1861141cc406Sopenharmony_ci 1862141cc406Sopenharmony_ci strncpy(s->barfname, "/tmp/bhXXXXXX", sizeof(s->barfname)); 1863141cc406Sopenharmony_ci s->barfname[sizeof(s->barfname)-1] = '\0'; 1864141cc406Sopenharmony_ci fd = mkstemp(s->barfname); 1865141cc406Sopenharmony_ci 1866141cc406Sopenharmony_ci if (fd !=-1 && (fp = fdopen(fd, "w")) != NULL) 1867141cc406Sopenharmony_ci { 1868141cc406Sopenharmony_ci fprintf(fp, "<xml-stream>\n"); 1869141cc406Sopenharmony_ci 1870141cc406Sopenharmony_ci for (; 1871141cc406Sopenharmony_ci s->readptr < s->readcnt && 1872141cc406Sopenharmony_ci status == SANE_STATUS_GOOD; 1873141cc406Sopenharmony_ci s->readptr++) 1874141cc406Sopenharmony_ci { 1875141cc406Sopenharmony_ci if (s->readlist[s->readptr] == 1876141cc406Sopenharmony_ci BH_SCSI_READ_TYPE_SENDBARFILE) { 1877141cc406Sopenharmony_ci break; 1878141cc406Sopenharmony_ci } 1879141cc406Sopenharmony_ci status = read_barcode_data(s, fp); 1880141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) break; 1881141cc406Sopenharmony_ci } 1882141cc406Sopenharmony_ci 1883141cc406Sopenharmony_ci fprintf(fp, "</xml-stream>\n"); 1884141cc406Sopenharmony_ci 1885141cc406Sopenharmony_ci /* close file; re-open for read(setting s->barfd) */ 1886141cc406Sopenharmony_ci fclose(fp); 1887141cc406Sopenharmony_ci if ((s->barf = fopen(s->barfname, "r")) == NULL) 1888141cc406Sopenharmony_ci { 1889141cc406Sopenharmony_ci DBG(1, "sane_start: error opening barfile `%s'\n", 1890141cc406Sopenharmony_ci s->barfname); 1891141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 1892141cc406Sopenharmony_ci } 1893141cc406Sopenharmony_ci } 1894141cc406Sopenharmony_ci else 1895141cc406Sopenharmony_ci { 1896141cc406Sopenharmony_ci DBG(1, "sane_start: error opening barfile `%s'\n", 1897141cc406Sopenharmony_ci s->barfname); 1898141cc406Sopenharmony_ci if (fd !=-1) 1899141cc406Sopenharmony_ci { 1900141cc406Sopenharmony_ci close(fd); 1901141cc406Sopenharmony_ci unlink(s->barfname); 1902141cc406Sopenharmony_ci } 1903141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 1904141cc406Sopenharmony_ci } 1905141cc406Sopenharmony_ci } 1906141cc406Sopenharmony_ci else if (itemtype == BH_SCSI_READ_TYPE_FRONT_ICON || 1907141cc406Sopenharmony_ci itemtype == BH_SCSI_READ_TYPE_BACK_ICON) 1908141cc406Sopenharmony_ci { 1909141cc406Sopenharmony_ci /* read the icon header setting the iconwidth and iconlength 1910141cc406Sopenharmony_ci * to the actual values so get_parameters will have them. 1911141cc406Sopenharmony_ci * Subsequent calls to sane_read will get pure image data 1912141cc406Sopenharmony_ci * since the icon header has been consumed. 1913141cc406Sopenharmony_ci */ 1914141cc406Sopenharmony_ci 1915141cc406Sopenharmony_ci status = read_icon_data(s); 1916141cc406Sopenharmony_ci } 1917141cc406Sopenharmony_ci 1918141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) 1919141cc406Sopenharmony_ci { 1920141cc406Sopenharmony_ci /* update our parameters to reflect the new item */ 1921141cc406Sopenharmony_ci status = get_parameters (s, 0); 1922141cc406Sopenharmony_ci } 1923141cc406Sopenharmony_ci 1924141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) s->scanning = SANE_FALSE; 1925141cc406Sopenharmony_ci 1926141cc406Sopenharmony_ci return status; 1927141cc406Sopenharmony_ci } 1928141cc406Sopenharmony_ci /* if we reach here, we're finished with the readlist and 1929141cc406Sopenharmony_ci * will drop through to start a new scan 1930141cc406Sopenharmony_ci */ 1931141cc406Sopenharmony_ci } 1932141cc406Sopenharmony_ci } 1933141cc406Sopenharmony_ci 1934141cc406Sopenharmony_ci s->readptr = 0; 1935141cc406Sopenharmony_ci 1936141cc406Sopenharmony_ci check_adf = _OPT_VAL_WORD(s, OPT_CHECK_ADF); 1937141cc406Sopenharmony_ci duplex = _OPT_VAL_WORD(s, OPT_DUPLEX); 1938141cc406Sopenharmony_ci 1939141cc406Sopenharmony_ci memset (&cmd, 0, sizeof (cmd)); 1940141cc406Sopenharmony_ci cmd[0] = BH_SCSI_START_SCAN; 1941141cc406Sopenharmony_ci cmd[4] = (duplex == SANE_TRUE) ? 2 : 1; 1942141cc406Sopenharmony_ci 1943141cc406Sopenharmony_ci cmd[6] = 0; 1944141cc406Sopenharmony_ci cmd[7] = 1; 1945141cc406Sopenharmony_ci 1946141cc406Sopenharmony_ci if (check_adf) 1947141cc406Sopenharmony_ci { 1948141cc406Sopenharmony_ci status = object_position(s); 1949141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1950141cc406Sopenharmony_ci { 1951141cc406Sopenharmony_ci DBG(3, "object_position: returned %d\n", status); 1952141cc406Sopenharmony_ci return status; 1953141cc406Sopenharmony_ci } 1954141cc406Sopenharmony_ci } 1955141cc406Sopenharmony_ci 1956141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 0, 0); 1957141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) 1958141cc406Sopenharmony_ci { 1959141cc406Sopenharmony_ci s->scanning = SANE_TRUE; 1960141cc406Sopenharmony_ci 1961141cc406Sopenharmony_ci /* update our parameters, 1962141cc406Sopenharmony_ci * now that we're scanning we'll do a GET_WINDOW 1963141cc406Sopenharmony_ci */ 1964141cc406Sopenharmony_ci status = get_parameters (s, 0); 1965141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1966141cc406Sopenharmony_ci { 1967141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 1968141cc406Sopenharmony_ci } 1969141cc406Sopenharmony_ci } 1970141cc406Sopenharmony_ci 1971141cc406Sopenharmony_ci return status; 1972141cc406Sopenharmony_ci} 1973141cc406Sopenharmony_ci 1974141cc406Sopenharmony_ci/* a sensible sense handler, courtesy of Franck; 1975141cc406Sopenharmony_ci arg is a pointer to the associated BH_Scanner structure */ 1976141cc406Sopenharmony_cistatic SANE_Status 1977141cc406Sopenharmony_cisense_handler (int scsi_fd, u_char *result, void *arg) 1978141cc406Sopenharmony_ci{ 1979141cc406Sopenharmony_ci BH_Scanner *s = (BH_Scanner *) arg; 1980141cc406Sopenharmony_ci u_char sense, asc, ascq, EOM, ILI, ErrorCode, ValidData; 1981141cc406Sopenharmony_ci u_long InvalidBytes; 1982141cc406Sopenharmony_ci char *sense_str = "", *as_str = ""; 1983141cc406Sopenharmony_ci SANE_Int i; 1984141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_INVAL; 1985141cc406Sopenharmony_ci SANE_Char print_sense[(16 * 3) + 1]; 1986141cc406Sopenharmony_ci 1987141cc406Sopenharmony_ci (void) scsi_fd; /* get rid of compiler warning */ 1988141cc406Sopenharmony_ci ErrorCode = result[0] & 0x7F; 1989141cc406Sopenharmony_ci ValidData = (result[0] & 0x80) != 0; 1990141cc406Sopenharmony_ci sense = result[2] & 0x0f; /* Key */ 1991141cc406Sopenharmony_ci asc = result[12]; /* Code */ 1992141cc406Sopenharmony_ci ascq = result[13]; /* Qual */ 1993141cc406Sopenharmony_ci EOM = (result[2] & 0x40) != 0; /* End Of Media */ 1994141cc406Sopenharmony_ci ILI = (result[2] & 0x20) != 0; /* Invalid Length Indicator */ 1995141cc406Sopenharmony_ci InvalidBytes = ValidData ? _4btol(&result[3]) : 0; 1996141cc406Sopenharmony_ci 1997141cc406Sopenharmony_ci DBG(3, "sense_handler: result=%x, sense=%x, asc=%x, ascq=%x\n", 1998141cc406Sopenharmony_ci result[0], sense, asc, ascq); 1999141cc406Sopenharmony_ci DBG(3, "sense_handler: ErrorCode %02x ValidData: %d " 2000141cc406Sopenharmony_ci "EOM: %d ILI: %d InvalidBytes: %lu\n", 2001141cc406Sopenharmony_ci ErrorCode, ValidData, EOM, ILI, InvalidBytes); 2002141cc406Sopenharmony_ci 2003141cc406Sopenharmony_ci memset(print_sense, '\0', sizeof(print_sense)); 2004141cc406Sopenharmony_ci for (i = 0; i < 16; i++) 2005141cc406Sopenharmony_ci { 2006141cc406Sopenharmony_ci sprintf(print_sense + strlen(print_sense), "%02x ", result[i]); 2007141cc406Sopenharmony_ci } 2008141cc406Sopenharmony_ci DBG(5, "sense_handler: sense=%s\n", print_sense); 2009141cc406Sopenharmony_ci 2010141cc406Sopenharmony_ci if (ErrorCode != 0x70 && ErrorCode != 0x71) 2011141cc406Sopenharmony_ci { 2012141cc406Sopenharmony_ci DBG (3, "sense_handler: error code is invalid.\n"); 2013141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; /* error code is invalid */ 2014141cc406Sopenharmony_ci } 2015141cc406Sopenharmony_ci 2016141cc406Sopenharmony_ci /* handle each sense key; 2017141cc406Sopenharmony_ci * RSC supports 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x0B 2018141cc406Sopenharmony_ci */ 2019141cc406Sopenharmony_ci switch (sense) 2020141cc406Sopenharmony_ci { 2021141cc406Sopenharmony_ci case 0x00: 2022141cc406Sopenharmony_ci /* no sense */ 2023141cc406Sopenharmony_ci sense_str = "No sense."; 2024141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 2025141cc406Sopenharmony_ci if (ILI && asc == 0x00 && ascq == 0x05) 2026141cc406Sopenharmony_ci { 2027141cc406Sopenharmony_ci /* from read_data function */ 2028141cc406Sopenharmony_ci as_str = "ILI bit is set."; 2029141cc406Sopenharmony_ci if (s != NULL) 2030141cc406Sopenharmony_ci { 2031141cc406Sopenharmony_ci s->InvalidBytes = InvalidBytes; 2032141cc406Sopenharmony_ci } 2033141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 2034141cc406Sopenharmony_ci } 2035141cc406Sopenharmony_ci else if (EOM && asc == 0x00 && ascq == 0x02) 2036141cc406Sopenharmony_ci { 2037141cc406Sopenharmony_ci /* from adfStatus or startScan function */ 2038141cc406Sopenharmony_ci as_str = "Out of paper in the hopper."; 2039141cc406Sopenharmony_ci status = SANE_STATUS_NO_DOCS; 2040141cc406Sopenharmony_ci } 2041141cc406Sopenharmony_ci else if (EOM) 2042141cc406Sopenharmony_ci { 2043141cc406Sopenharmony_ci /* from adfStatus or startScan function */ 2044141cc406Sopenharmony_ci as_str = "Out of paper in the hopper."; 2045141cc406Sopenharmony_ci status = SANE_STATUS_NO_DOCS; 2046141cc406Sopenharmony_ci } 2047141cc406Sopenharmony_ci break; 2048141cc406Sopenharmony_ci case 0x01: 2049141cc406Sopenharmony_ci /* recovered error */ 2050141cc406Sopenharmony_ci sense_str = "Recovered error."; 2051141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 2052141cc406Sopenharmony_ci break; 2053141cc406Sopenharmony_ci case 0x02: 2054141cc406Sopenharmony_ci /* not ready */ 2055141cc406Sopenharmony_ci sense_str = "Not ready."; 2056141cc406Sopenharmony_ci status = SANE_STATUS_DEVICE_BUSY; 2057141cc406Sopenharmony_ci if (asc == 0x40 && ascq == 0x01) 2058141cc406Sopenharmony_ci { 2059141cc406Sopenharmony_ci as_str = "P.O.D. error: Scanner not found."; 2060141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 2061141cc406Sopenharmony_ci } 2062141cc406Sopenharmony_ci else if (asc == 0x40 && ascq == 0x02) 2063141cc406Sopenharmony_ci { 2064141cc406Sopenharmony_ci as_str = "P.O.D. error: Scanner not ready(paper in transport)."; 2065141cc406Sopenharmony_ci status = SANE_STATUS_DEVICE_BUSY; 2066141cc406Sopenharmony_ci } 2067141cc406Sopenharmony_ci else if (asc == 0x40 && ascq == 0x03) 2068141cc406Sopenharmony_ci { 2069141cc406Sopenharmony_ci as_str = "P.O.D. error: Unknown scanner."; 2070141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 2071141cc406Sopenharmony_ci } 2072141cc406Sopenharmony_ci break; 2073141cc406Sopenharmony_ci case 0x03: 2074141cc406Sopenharmony_ci /* medium error */ 2075141cc406Sopenharmony_ci sense_str = "Medium error."; 2076141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2077141cc406Sopenharmony_ci if (asc == 0x00 && ascq == 0x00) 2078141cc406Sopenharmony_ci { 2079141cc406Sopenharmony_ci as_str = "Scanner error: paper jam detected."; 2080141cc406Sopenharmony_ci status = SANE_STATUS_JAMMED; 2081141cc406Sopenharmony_ci } 2082141cc406Sopenharmony_ci break; 2083141cc406Sopenharmony_ci case 0x04: 2084141cc406Sopenharmony_ci /* hardware error */ 2085141cc406Sopenharmony_ci sense_str = "Hardware error."; 2086141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2087141cc406Sopenharmony_ci if (asc == 0x60 && ascq == 0x00) 2088141cc406Sopenharmony_ci { 2089141cc406Sopenharmony_ci as_str = "Scanner error: illumination lamps failure."; 2090141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2091141cc406Sopenharmony_ci } 2092141cc406Sopenharmony_ci else if (asc == 0x80 && ascq == 0x03) 2093141cc406Sopenharmony_ci { 2094141cc406Sopenharmony_ci as_str = "Communication error between RSC and scanner."; 2095141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2096141cc406Sopenharmony_ci } 2097141cc406Sopenharmony_ci else if (asc == 0x80 && ascq == 0x06) 2098141cc406Sopenharmony_ci { 2099141cc406Sopenharmony_ci as_str = "Scanner error: page detected but lamps are off."; 2100141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2101141cc406Sopenharmony_ci } 2102141cc406Sopenharmony_ci else if (asc == 0x80 && ascq == 0x07) 2103141cc406Sopenharmony_ci { 2104141cc406Sopenharmony_ci as_str = "Scanner error: camera white level problem."; 2105141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2106141cc406Sopenharmony_ci } 2107141cc406Sopenharmony_ci else if (asc == 0x80 && ascq == 0x08) 2108141cc406Sopenharmony_ci { 2109141cc406Sopenharmony_ci /* could be caught from start_scan or read_data */ 2110141cc406Sopenharmony_ci /* stop button pressed */ 2111141cc406Sopenharmony_ci as_str = "Scanner error: operator pressed the Stop key."; 2112141cc406Sopenharmony_ci status = SANE_STATUS_NO_DOCS; 2113141cc406Sopenharmony_ci } 2114141cc406Sopenharmony_ci else if (asc == 0x80 && ascq == 0x12) 2115141cc406Sopenharmony_ci { 2116141cc406Sopenharmony_ci as_str = "Scanner error: transport motor failure."; 2117141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2118141cc406Sopenharmony_ci } 2119141cc406Sopenharmony_ci else if (asc == 0x80 && ascq == 0x15) 2120141cc406Sopenharmony_ci { 2121141cc406Sopenharmony_ci as_str = "Scanner error: device / page sensor(s) bouncing."; 2122141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2123141cc406Sopenharmony_ci } 2124141cc406Sopenharmony_ci else if (asc == 0x80 && ascq == 0x16) 2125141cc406Sopenharmony_ci { 2126141cc406Sopenharmony_ci as_str = "Scanner error: feeder is not attached."; 2127141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2128141cc406Sopenharmony_ci } 2129141cc406Sopenharmony_ci else if (asc == 0x80 && ascq == 0x18) 2130141cc406Sopenharmony_ci { 2131141cc406Sopenharmony_ci as_str = "Scanner error: logic system general failure."; 2132141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2133141cc406Sopenharmony_ci } 2134141cc406Sopenharmony_ci else if (asc == 0x80 && ascq == 0x34) 2135141cc406Sopenharmony_ci { 2136141cc406Sopenharmony_ci as_str = "Scanner error: no dual logic communication."; 2137141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2138141cc406Sopenharmony_ci } 2139141cc406Sopenharmony_ci break; 2140141cc406Sopenharmony_ci case 0x05: 2141141cc406Sopenharmony_ci /* illegal request */ 2142141cc406Sopenharmony_ci sense_str = "Illegal request."; 2143141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 2144141cc406Sopenharmony_ci if (asc == 0x1a && ascq == 0x00) 2145141cc406Sopenharmony_ci { 2146141cc406Sopenharmony_ci as_str = "Parameter list length error."; 2147141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 2148141cc406Sopenharmony_ci } 2149141cc406Sopenharmony_ci else if (asc == 0x20 && ascq == 0x00) 2150141cc406Sopenharmony_ci { 2151141cc406Sopenharmony_ci as_str = "Invalid command operation code."; 2152141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 2153141cc406Sopenharmony_ci } 2154141cc406Sopenharmony_ci else if (asc == 0x24 && ascq == 0x00) 2155141cc406Sopenharmony_ci { 2156141cc406Sopenharmony_ci /* caught from object_position (via reverse engineering) */ 2157141cc406Sopenharmony_ci /* Not supported? */ 2158141cc406Sopenharmony_ci as_str = "Invalid field in CDB."; 2159141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 2160141cc406Sopenharmony_ci } 2161141cc406Sopenharmony_ci else if (asc == 0x25 && ascq == 0x00) 2162141cc406Sopenharmony_ci { 2163141cc406Sopenharmony_ci as_str = "Unsupported LUN."; 2164141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 2165141cc406Sopenharmony_ci } 2166141cc406Sopenharmony_ci else if (asc == 0x26 && ascq == 0x00) 2167141cc406Sopenharmony_ci { 2168141cc406Sopenharmony_ci /* caught from mode_select (as well as others) */ 2169141cc406Sopenharmony_ci /* Bar/Patch code detection support not installed */ 2170141cc406Sopenharmony_ci /* See Appendix A, Section A.5 */ 2171141cc406Sopenharmony_ci as_str = "Invalid field in parameter list."; 2172141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 2173141cc406Sopenharmony_ci } 2174141cc406Sopenharmony_ci else if (asc == 0x2c && ascq == 0x00) 2175141cc406Sopenharmony_ci { 2176141cc406Sopenharmony_ci /* we were getting this in read_data during the time 2177141cc406Sopenharmony_ci that the ADF was misbehaving. Hopefully we will 2178141cc406Sopenharmony_ci not see it anymore. 2179141cc406Sopenharmony_ci */ 2180141cc406Sopenharmony_ci as_str = "Command out of sequence."; 2181141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 2182141cc406Sopenharmony_ci } 2183141cc406Sopenharmony_ci else if (asc == 0x2c && ascq == 0x01) 2184141cc406Sopenharmony_ci { 2185141cc406Sopenharmony_ci as_str = "Too many windows defined."; 2186141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 2187141cc406Sopenharmony_ci } 2188141cc406Sopenharmony_ci else if (asc == 0x2c && ascq == 0x02) 2189141cc406Sopenharmony_ci { 2190141cc406Sopenharmony_ci as_str = "Batch start error."; 2191141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 2192141cc406Sopenharmony_ci } 2193141cc406Sopenharmony_ci else if (asc == 0x2c && ascq == 0x03) 2194141cc406Sopenharmony_ci { 2195141cc406Sopenharmony_ci as_str = "Batch abort error."; 2196141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 2197141cc406Sopenharmony_ci } 2198141cc406Sopenharmony_ci else if (asc == 0x3d && ascq == 0x00) 2199141cc406Sopenharmony_ci { 2200141cc406Sopenharmony_ci as_str = "Invalid bits in IDENTIFY message."; 2201141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 2202141cc406Sopenharmony_ci } 2203141cc406Sopenharmony_ci break; 2204141cc406Sopenharmony_ci case 0x06: 2205141cc406Sopenharmony_ci /* unit attention */ 2206141cc406Sopenharmony_ci sense_str = "Unit attention."; 2207141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2208141cc406Sopenharmony_ci if (asc == 0x04 && ascq == 0x01) 2209141cc406Sopenharmony_ci { 2210141cc406Sopenharmony_ci as_str = "Reset detected, LUN is becoming ready."; 2211141cc406Sopenharmony_ci status = SANE_STATUS_DEVICE_BUSY; 2212141cc406Sopenharmony_ci } 2213141cc406Sopenharmony_ci break; 2214141cc406Sopenharmony_ci case 0x07: 2215141cc406Sopenharmony_ci /* data protect */ 2216141cc406Sopenharmony_ci sense_str = "Data protect."; 2217141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2218141cc406Sopenharmony_ci break; 2219141cc406Sopenharmony_ci case 0x08: 2220141cc406Sopenharmony_ci /* blank check */ 2221141cc406Sopenharmony_ci sense_str = "Blank check."; 2222141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2223141cc406Sopenharmony_ci break; 2224141cc406Sopenharmony_ci case 0x09: 2225141cc406Sopenharmony_ci /* vendor specific */ 2226141cc406Sopenharmony_ci sense_str = "Vendor specific."; 2227141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2228141cc406Sopenharmony_ci break; 2229141cc406Sopenharmony_ci case 0x0A: 2230141cc406Sopenharmony_ci /* copy aborted */ 2231141cc406Sopenharmony_ci sense_str = "Copy aborted."; 2232141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2233141cc406Sopenharmony_ci break; 2234141cc406Sopenharmony_ci case 0x0B: 2235141cc406Sopenharmony_ci /* aborted command */ 2236141cc406Sopenharmony_ci sense_str = "Aborted command."; 2237141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2238141cc406Sopenharmony_ci if (asc == 0x00 && ascq == 0x00) 2239141cc406Sopenharmony_ci { 2240141cc406Sopenharmony_ci as_str = "Aborted command (unspecified error)."; 2241141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2242141cc406Sopenharmony_ci } 2243141cc406Sopenharmony_ci else if (asc == 0x08 && ascq == 0x01) 2244141cc406Sopenharmony_ci { 2245141cc406Sopenharmony_ci /* caught from start_scan */ 2246141cc406Sopenharmony_ci /* manual feed timeout */ 2247141cc406Sopenharmony_ci as_str = "SCSI Time-out, paper Time-out (SCAN command)."; 2248141cc406Sopenharmony_ci status = SANE_STATUS_NO_DOCS; 2249141cc406Sopenharmony_ci } 2250141cc406Sopenharmony_ci else if (asc == 0x47 && ascq == 0x00) 2251141cc406Sopenharmony_ci { 2252141cc406Sopenharmony_ci as_str = "SCSI parity error."; 2253141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2254141cc406Sopenharmony_ci } 2255141cc406Sopenharmony_ci else if (asc == 0x80 && ascq == 0x00) 2256141cc406Sopenharmony_ci { 2257141cc406Sopenharmony_ci as_str = "Aborted command due to memory error."; 2258141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2259141cc406Sopenharmony_ci } 2260141cc406Sopenharmony_ci else if (asc == 0x80 && ascq == 0x01) 2261141cc406Sopenharmony_ci { 2262141cc406Sopenharmony_ci /* caught from read_data */ 2263141cc406Sopenharmony_ci /* section border error; border is outside the main window */ 2264141cc406Sopenharmony_ci /* See Appendix A, Section A.4 */ 2265141cc406Sopenharmony_ci as_str = "Section Read error (out of border)."; 2266141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 2267141cc406Sopenharmony_ci } 2268141cc406Sopenharmony_ci else if (asc == 0x80 && ascq == 0x02) 2269141cc406Sopenharmony_ci { 2270141cc406Sopenharmony_ci /* caught from read_data */ 2271141cc406Sopenharmony_ci /* No code found; no barcode data is found */ 2272141cc406Sopenharmony_ci /* See Appendix A, Section A.5 */ 2273141cc406Sopenharmony_ci s->barcode_not_found = SANE_TRUE; 2274141cc406Sopenharmony_ci as_str = "No Bar/Patch Code found."; 2275141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 2276141cc406Sopenharmony_ci } 2277141cc406Sopenharmony_ci else if (asc == 0x80 && ascq == 0x03) 2278141cc406Sopenharmony_ci { 2279141cc406Sopenharmony_ci as_str = "Icon Read error (out of border)."; 2280141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 2281141cc406Sopenharmony_ci } 2282141cc406Sopenharmony_ci break; 2283141cc406Sopenharmony_ci case 0x0C: 2284141cc406Sopenharmony_ci /* equal */ 2285141cc406Sopenharmony_ci sense_str = "Equal."; 2286141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2287141cc406Sopenharmony_ci break; 2288141cc406Sopenharmony_ci case 0x0D: 2289141cc406Sopenharmony_ci /* volume overflow */ 2290141cc406Sopenharmony_ci sense_str = "Volume overflow."; 2291141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2292141cc406Sopenharmony_ci break; 2293141cc406Sopenharmony_ci case 0x0E: 2294141cc406Sopenharmony_ci /* miscompare */ 2295141cc406Sopenharmony_ci sense_str = "Miscompare."; 2296141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2297141cc406Sopenharmony_ci break; 2298141cc406Sopenharmony_ci case 0x0F: 2299141cc406Sopenharmony_ci /* reserved */ 2300141cc406Sopenharmony_ci sense_str = "Reserved."; 2301141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2302141cc406Sopenharmony_ci break; 2303141cc406Sopenharmony_ci default: 2304141cc406Sopenharmony_ci sense_str = "Unhandled case."; 2305141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 2306141cc406Sopenharmony_ci break; 2307141cc406Sopenharmony_ci } 2308141cc406Sopenharmony_ci 2309141cc406Sopenharmony_ci DBG(3, "sense_handler: '%s' '%s' return:%d\n", 2310141cc406Sopenharmony_ci sense_str, as_str, status); 2311141cc406Sopenharmony_ci 2312141cc406Sopenharmony_ci return status; 2313141cc406Sopenharmony_ci} 2314141cc406Sopenharmony_ci 2315141cc406Sopenharmony_cistatic SANE_Status 2316141cc406Sopenharmony_ciinit_options (BH_Scanner * s) 2317141cc406Sopenharmony_ci{ 2318141cc406Sopenharmony_ci int i; 2319141cc406Sopenharmony_ci DBG (3, "init_options called\n"); 2320141cc406Sopenharmony_ci 2321141cc406Sopenharmony_ci memset (s->opt, 0, sizeof (s->opt)); 2322141cc406Sopenharmony_ci memset (s->val, 0, sizeof (s->val)); 2323141cc406Sopenharmony_ci 2324141cc406Sopenharmony_ci for (i = 0; i < NUM_OPTIONS; ++i) 2325141cc406Sopenharmony_ci { 2326141cc406Sopenharmony_ci s->opt[i].size = sizeof (SANE_Word); 2327141cc406Sopenharmony_ci s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 2328141cc406Sopenharmony_ci } 2329141cc406Sopenharmony_ci 2330141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 2331141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 2332141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 2333141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 2334141cc406Sopenharmony_ci s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; 2335141cc406Sopenharmony_ci 2336141cc406Sopenharmony_ci /* "Scan Mode" group: */ 2337141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].name = ""; 2338141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE_GROUP; 2339141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].desc = ""; 2340141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 2341141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].cap = 0; 2342141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2343141cc406Sopenharmony_ci 2344141cc406Sopenharmony_ci /* Preview: */ 2345141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; 2346141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; 2347141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; 2348141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; 2349141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE; 2350141cc406Sopenharmony_ci s->val[OPT_PREVIEW].w = 0; 2351141cc406Sopenharmony_ci 2352141cc406Sopenharmony_ci /* Inquiry */ 2353141cc406Sopenharmony_ci s->opt[OPT_INQUIRY].name = SANE_NAME_INQUIRY; 2354141cc406Sopenharmony_ci s->opt[OPT_INQUIRY].title = SANE_TITLE_INQUIRY; 2355141cc406Sopenharmony_ci s->opt[OPT_INQUIRY].desc = SANE_DESC_INQUIRY; 2356141cc406Sopenharmony_ci s->opt[OPT_INQUIRY].type = SANE_TYPE_STRING; 2357141cc406Sopenharmony_ci s->opt[OPT_INQUIRY].size = sizeof(inquiry_data); 2358141cc406Sopenharmony_ci s->opt[OPT_INQUIRY].constraint_type = SANE_CONSTRAINT_NONE; 2359141cc406Sopenharmony_ci s->val[OPT_INQUIRY].s = strdup(inquiry_data); 2360141cc406Sopenharmony_ci s->opt[OPT_INQUIRY].cap = SANE_CAP_SOFT_DETECT; 2361141cc406Sopenharmony_ci 2362141cc406Sopenharmony_ci /* scan mode */ 2363141cc406Sopenharmony_ci s->opt[OPT_SCAN_MODE].name = SANE_NAME_SCAN_MODE; 2364141cc406Sopenharmony_ci s->opt[OPT_SCAN_MODE].title = SANE_TITLE_SCAN_MODE; 2365141cc406Sopenharmony_ci s->opt[OPT_SCAN_MODE].desc = SANE_DESC_SCAN_MODE; 2366141cc406Sopenharmony_ci s->opt[OPT_SCAN_MODE].type = SANE_TYPE_STRING; 2367141cc406Sopenharmony_ci s->opt[OPT_SCAN_MODE].size = max_string_size (scan_mode_list); 2368141cc406Sopenharmony_ci s->opt[OPT_SCAN_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2369141cc406Sopenharmony_ci s->opt[OPT_SCAN_MODE].constraint.string_list = scan_mode_list; 2370141cc406Sopenharmony_ci s->val[OPT_SCAN_MODE].s = strdup (scan_mode_list[0]); 2371141cc406Sopenharmony_ci 2372141cc406Sopenharmony_ci /* Standard resolutions */ 2373141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 2374141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 2375141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 2376141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; 2377141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 2378141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; 2379141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].constraint.word_list = s->hw->info.resStdList; 2380141cc406Sopenharmony_ci s->val[OPT_RESOLUTION].w = s->hw->info.res_default; 2381141cc406Sopenharmony_ci 2382141cc406Sopenharmony_ci /* compression */ 2383141cc406Sopenharmony_ci s->opt[OPT_COMPRESSION].name = SANE_NAME_COMPRESSION; 2384141cc406Sopenharmony_ci s->opt[OPT_COMPRESSION].title = SANE_TITLE_COMPRESSION; 2385141cc406Sopenharmony_ci s->opt[OPT_COMPRESSION].desc = SANE_DESC_COMPRESSION; 2386141cc406Sopenharmony_ci s->opt[OPT_COMPRESSION].type = SANE_TYPE_STRING; 2387141cc406Sopenharmony_ci s->opt[OPT_COMPRESSION].size = max_string_size (compression_list); 2388141cc406Sopenharmony_ci s->opt[OPT_COMPRESSION].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2389141cc406Sopenharmony_ci s->opt[OPT_COMPRESSION].constraint.string_list = compression_list; 2390141cc406Sopenharmony_ci s->val[OPT_COMPRESSION].s = strdup (compression_list[0]); 2391141cc406Sopenharmony_ci 2392141cc406Sopenharmony_ci if (s->hw->info.colorHalftone == SANE_FALSE) 2393141cc406Sopenharmony_ci { 2394141cc406Sopenharmony_ci s->opt[OPT_SCAN_MODE].size = max_string_size (scan_mode_min_list); 2395141cc406Sopenharmony_ci s->opt[OPT_SCAN_MODE].constraint.string_list = scan_mode_min_list; 2396141cc406Sopenharmony_ci } 2397141cc406Sopenharmony_ci 2398141cc406Sopenharmony_ci if (s->hw->info.comprG3_1D == SANE_FALSE || 2399141cc406Sopenharmony_ci s->hw->info.comprG3_2D == SANE_FALSE || 2400141cc406Sopenharmony_ci s->hw->info.comprG4 == SANE_FALSE) 2401141cc406Sopenharmony_ci { 2402141cc406Sopenharmony_ci s->opt[OPT_COMPRESSION].cap |= SANE_CAP_INACTIVE; 2403141cc406Sopenharmony_ci } 2404141cc406Sopenharmony_ci 2405141cc406Sopenharmony_ci /* "Geometry" group: */ 2406141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].name = ""; 2407141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].title = SANE_TITLE_GEOMETRY_GROUP; 2408141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].desc = ""; 2409141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 2410141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].cap = 0; 2411141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2412141cc406Sopenharmony_ci 2413141cc406Sopenharmony_ci /* Autoborder: */ 2414141cc406Sopenharmony_ci s->opt[OPT_AUTOBORDER].name = SANE_NAME_AUTOBORDER; 2415141cc406Sopenharmony_ci s->opt[OPT_AUTOBORDER].title = SANE_TITLE_AUTOBORDER; 2416141cc406Sopenharmony_ci s->opt[OPT_AUTOBORDER].desc = SANE_DESC_AUTOBORDER; 2417141cc406Sopenharmony_ci s->opt[OPT_AUTOBORDER].type = SANE_TYPE_BOOL; 2418141cc406Sopenharmony_ci s->opt[OPT_AUTOBORDER].constraint_type = SANE_CONSTRAINT_NONE; 2419141cc406Sopenharmony_ci s->val[OPT_AUTOBORDER].w = s->hw->info.autoborder_default; 2420141cc406Sopenharmony_ci 2421141cc406Sopenharmony_ci /* Paper Size */ 2422141cc406Sopenharmony_ci s->opt[OPT_PAPER_SIZE].name = SANE_NAME_PAPER_SIZE; 2423141cc406Sopenharmony_ci s->opt[OPT_PAPER_SIZE].title = SANE_TITLE_PAPER_SIZE; 2424141cc406Sopenharmony_ci s->opt[OPT_PAPER_SIZE].desc = SANE_DESC_PAPER_SIZE; 2425141cc406Sopenharmony_ci s->opt[OPT_PAPER_SIZE].type = SANE_TYPE_STRING; 2426141cc406Sopenharmony_ci s->opt[OPT_PAPER_SIZE].size = max_string_size (paper_list); 2427141cc406Sopenharmony_ci s->opt[OPT_PAPER_SIZE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2428141cc406Sopenharmony_ci s->opt[OPT_PAPER_SIZE].constraint.string_list = paper_list; 2429141cc406Sopenharmony_ci s->val[OPT_PAPER_SIZE].s = strdup (paper_list[0]); 2430141cc406Sopenharmony_ci 2431141cc406Sopenharmony_ci /* rotation */ 2432141cc406Sopenharmony_ci s->opt[OPT_ROTATION].name = SANE_NAME_ROTATION; 2433141cc406Sopenharmony_ci s->opt[OPT_ROTATION].title = SANE_TITLE_ROTATION; 2434141cc406Sopenharmony_ci s->opt[OPT_ROTATION].desc = SANE_DESC_ROTATION; 2435141cc406Sopenharmony_ci s->opt[OPT_ROTATION].type = SANE_TYPE_STRING; 2436141cc406Sopenharmony_ci s->opt[OPT_ROTATION].size = max_string_size (rotation_list); 2437141cc406Sopenharmony_ci s->opt[OPT_ROTATION].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2438141cc406Sopenharmony_ci s->opt[OPT_ROTATION].constraint.string_list = rotation_list; 2439141cc406Sopenharmony_ci s->val[OPT_ROTATION].s = strdup (rotation_list[0]); 2440141cc406Sopenharmony_ci 2441141cc406Sopenharmony_ci /* Deskew: */ 2442141cc406Sopenharmony_ci s->opt[OPT_DESKEW].name = SANE_NAME_DESKEW; 2443141cc406Sopenharmony_ci s->opt[OPT_DESKEW].title = SANE_TITLE_DESKEW; 2444141cc406Sopenharmony_ci s->opt[OPT_DESKEW].desc = SANE_DESC_DESKEW; 2445141cc406Sopenharmony_ci s->opt[OPT_DESKEW].type = SANE_TYPE_BOOL; 2446141cc406Sopenharmony_ci s->opt[OPT_DESKEW].constraint_type = SANE_CONSTRAINT_NONE; 2447141cc406Sopenharmony_ci s->val[OPT_DESKEW].w = s->hw->info.deskew_default; 2448141cc406Sopenharmony_ci 2449141cc406Sopenharmony_ci /* top-left x */ 2450141cc406Sopenharmony_ci s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 2451141cc406Sopenharmony_ci s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 2452141cc406Sopenharmony_ci s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 2453141cc406Sopenharmony_ci s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; 2454141cc406Sopenharmony_ci s->opt[OPT_TL_X].unit = SANE_UNIT_MM; 2455141cc406Sopenharmony_ci s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 2456141cc406Sopenharmony_ci s->opt[OPT_TL_X].constraint.range = &(s->hw->info.x_range); 2457141cc406Sopenharmony_ci s->val[OPT_TL_X].w = SANE_FIX(0.0); 2458141cc406Sopenharmony_ci 2459141cc406Sopenharmony_ci /* top-left y */ 2460141cc406Sopenharmony_ci s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 2461141cc406Sopenharmony_ci s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 2462141cc406Sopenharmony_ci s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 2463141cc406Sopenharmony_ci s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; 2464141cc406Sopenharmony_ci s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; 2465141cc406Sopenharmony_ci s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 2466141cc406Sopenharmony_ci s->opt[OPT_TL_Y].constraint.range = &(s->hw->info.y_range); 2467141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = SANE_FIX(0.0); 2468141cc406Sopenharmony_ci 2469141cc406Sopenharmony_ci /* bottom-right x */ 2470141cc406Sopenharmony_ci s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 2471141cc406Sopenharmony_ci s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 2472141cc406Sopenharmony_ci s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 2473141cc406Sopenharmony_ci s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; 2474141cc406Sopenharmony_ci s->opt[OPT_BR_X].unit = SANE_UNIT_MM; 2475141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 2476141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint.range = &(s->hw->info.x_range); 2477141cc406Sopenharmony_ci s->val[OPT_BR_X].w = s->hw->info.x_range.max; 2478141cc406Sopenharmony_ci 2479141cc406Sopenharmony_ci /* bottom-right y */ 2480141cc406Sopenharmony_ci s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 2481141cc406Sopenharmony_ci s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 2482141cc406Sopenharmony_ci s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 2483141cc406Sopenharmony_ci s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; 2484141cc406Sopenharmony_ci s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; 2485141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 2486141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint.range = &(s->hw->info.y_range); 2487141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = s->hw->info.y_range.max; 2488141cc406Sopenharmony_ci 2489141cc406Sopenharmony_ci if (s->hw->info.canBorderRecog == SANE_FALSE) 2490141cc406Sopenharmony_ci { 2491141cc406Sopenharmony_ci s->opt[OPT_AUTOBORDER].cap |= SANE_CAP_INACTIVE; 2492141cc406Sopenharmony_ci } 2493141cc406Sopenharmony_ci 2494141cc406Sopenharmony_ci /* "Feeder" group: */ 2495141cc406Sopenharmony_ci s->opt[OPT_FEEDER_GROUP].name = ""; 2496141cc406Sopenharmony_ci s->opt[OPT_FEEDER_GROUP].title = SANE_TITLE_FEEDER_GROUP; 2497141cc406Sopenharmony_ci s->opt[OPT_FEEDER_GROUP].desc = ""; 2498141cc406Sopenharmony_ci s->opt[OPT_FEEDER_GROUP].type = SANE_TYPE_GROUP; 2499141cc406Sopenharmony_ci s->opt[OPT_FEEDER_GROUP].cap = SANE_CAP_ADVANCED; 2500141cc406Sopenharmony_ci s->opt[OPT_FEEDER_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2501141cc406Sopenharmony_ci 2502141cc406Sopenharmony_ci /* scan source */ 2503141cc406Sopenharmony_ci s->opt[OPT_SCAN_SOURCE].name = SANE_NAME_SCAN_SOURCE; 2504141cc406Sopenharmony_ci s->opt[OPT_SCAN_SOURCE].title = SANE_TITLE_SCAN_SOURCE; 2505141cc406Sopenharmony_ci s->opt[OPT_SCAN_SOURCE].desc = SANE_DESC_SCAN_SOURCE; 2506141cc406Sopenharmony_ci s->opt[OPT_SCAN_SOURCE].type = SANE_TYPE_STRING; 2507141cc406Sopenharmony_ci s->opt[OPT_SCAN_SOURCE].size = max_string_size (scan_source_list); 2508141cc406Sopenharmony_ci s->opt[OPT_SCAN_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2509141cc406Sopenharmony_ci s->opt[OPT_SCAN_SOURCE].constraint.string_list = scan_source_list; 2510141cc406Sopenharmony_ci s->val[OPT_SCAN_SOURCE].s = strdup (scan_source_list[0]); 2511141cc406Sopenharmony_ci 2512141cc406Sopenharmony_ci /* Batch: */ 2513141cc406Sopenharmony_ci s->opt[OPT_BATCH].name = SANE_NAME_BATCH; 2514141cc406Sopenharmony_ci s->opt[OPT_BATCH].title = SANE_TITLE_BATCH; 2515141cc406Sopenharmony_ci s->opt[OPT_BATCH].desc = SANE_DESC_BATCH; 2516141cc406Sopenharmony_ci s->opt[OPT_BATCH].type = SANE_TYPE_BOOL; 2517141cc406Sopenharmony_ci s->opt[OPT_BATCH].constraint_type = SANE_CONSTRAINT_NONE; 2518141cc406Sopenharmony_ci s->val[OPT_BATCH].w = s->hw->info.batch_default; 2519141cc406Sopenharmony_ci 2520141cc406Sopenharmony_ci /* Check ADF: */ 2521141cc406Sopenharmony_ci s->opt[OPT_CHECK_ADF].name = SANE_NAME_CHECK_ADF; 2522141cc406Sopenharmony_ci s->opt[OPT_CHECK_ADF].title = SANE_TITLE_CHECK_ADF; 2523141cc406Sopenharmony_ci s->opt[OPT_CHECK_ADF].desc = SANE_DESC_CHECK_ADF; 2524141cc406Sopenharmony_ci s->opt[OPT_CHECK_ADF].type = SANE_TYPE_BOOL; 2525141cc406Sopenharmony_ci s->opt[OPT_CHECK_ADF].constraint_type = SANE_CONSTRAINT_NONE; 2526141cc406Sopenharmony_ci s->val[OPT_CHECK_ADF].w = s->hw->info.check_adf_default; 2527141cc406Sopenharmony_ci 2528141cc406Sopenharmony_ci /* Duplex: */ 2529141cc406Sopenharmony_ci s->opt[OPT_DUPLEX].name = SANE_NAME_DUPLEX; 2530141cc406Sopenharmony_ci s->opt[OPT_DUPLEX].title = SANE_TITLE_DUPLEX; 2531141cc406Sopenharmony_ci s->opt[OPT_DUPLEX].desc = SANE_DESC_DUPLEX; 2532141cc406Sopenharmony_ci s->opt[OPT_DUPLEX].type = SANE_TYPE_BOOL; 2533141cc406Sopenharmony_ci s->opt[OPT_DUPLEX].constraint_type = SANE_CONSTRAINT_NONE; 2534141cc406Sopenharmony_ci s->val[OPT_DUPLEX].w = s->hw->info.duplex_default; 2535141cc406Sopenharmony_ci 2536141cc406Sopenharmony_ci /* timeout adf */ 2537141cc406Sopenharmony_ci s->opt[OPT_TIMEOUT_ADF].name = SANE_NAME_TIMEOUT_ADF; 2538141cc406Sopenharmony_ci s->opt[OPT_TIMEOUT_ADF].title = SANE_TITLE_TIMEOUT_ADF; 2539141cc406Sopenharmony_ci s->opt[OPT_TIMEOUT_ADF].desc = SANE_DESC_TIMEOUT_ADF; 2540141cc406Sopenharmony_ci s->opt[OPT_TIMEOUT_ADF].type = SANE_TYPE_INT; 2541141cc406Sopenharmony_ci s->opt[OPT_TIMEOUT_ADF].unit = SANE_UNIT_NONE; 2542141cc406Sopenharmony_ci s->opt[OPT_TIMEOUT_ADF].constraint_type = SANE_CONSTRAINT_RANGE; 2543141cc406Sopenharmony_ci s->opt[OPT_TIMEOUT_ADF].constraint.range = &u8_range; 2544141cc406Sopenharmony_ci s->val[OPT_TIMEOUT_ADF].w = s->hw->info.timeout_adf_default; 2545141cc406Sopenharmony_ci 2546141cc406Sopenharmony_ci /* timeout manual */ 2547141cc406Sopenharmony_ci s->opt[OPT_TIMEOUT_MANUAL].name = SANE_NAME_TIMEOUT_MANUAL; 2548141cc406Sopenharmony_ci s->opt[OPT_TIMEOUT_MANUAL].title = SANE_TITLE_TIMEOUT_MANUAL; 2549141cc406Sopenharmony_ci s->opt[OPT_TIMEOUT_MANUAL].desc = SANE_DESC_TIMEOUT_MANUAL; 2550141cc406Sopenharmony_ci s->opt[OPT_TIMEOUT_MANUAL].type = SANE_TYPE_INT; 2551141cc406Sopenharmony_ci s->opt[OPT_TIMEOUT_MANUAL].unit = SANE_UNIT_NONE; 2552141cc406Sopenharmony_ci s->opt[OPT_TIMEOUT_MANUAL].constraint_type = SANE_CONSTRAINT_RANGE; 2553141cc406Sopenharmony_ci s->opt[OPT_TIMEOUT_MANUAL].constraint.range = &u8_range; 2554141cc406Sopenharmony_ci s->val[OPT_TIMEOUT_MANUAL].w = s->hw->info.timeout_manual_default; 2555141cc406Sopenharmony_ci 2556141cc406Sopenharmony_ci if (s->hw->info.canCheckADF == SANE_FALSE) 2557141cc406Sopenharmony_ci { 2558141cc406Sopenharmony_ci s->opt[OPT_CHECK_ADF].cap |= SANE_CAP_INACTIVE; 2559141cc406Sopenharmony_ci } 2560141cc406Sopenharmony_ci 2561141cc406Sopenharmony_ci if (s->hw->info.canDuplex == SANE_FALSE) 2562141cc406Sopenharmony_ci { 2563141cc406Sopenharmony_ci s->opt[OPT_DUPLEX].cap |= SANE_CAP_INACTIVE; 2564141cc406Sopenharmony_ci } 2565141cc406Sopenharmony_ci 2566141cc406Sopenharmony_ci if (s->hw->info.canADF == SANE_FALSE) 2567141cc406Sopenharmony_ci { 2568141cc406Sopenharmony_ci s->opt[OPT_TIMEOUT_ADF].cap |= SANE_CAP_INACTIVE; 2569141cc406Sopenharmony_ci } 2570141cc406Sopenharmony_ci 2571141cc406Sopenharmony_ci /* "Enhancement" group: */ 2572141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].name = ""; 2573141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_TITLE_ENHANCEMENT_GROUP; 2574141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; 2575141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; 2576141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; 2577141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2578141cc406Sopenharmony_ci 2579141cc406Sopenharmony_ci /* Control Panel: */ 2580141cc406Sopenharmony_ci s->opt[OPT_CONTROL_PANEL].name = SANE_NAME_CONTROL_PANEL; 2581141cc406Sopenharmony_ci s->opt[OPT_CONTROL_PANEL].title = SANE_TITLE_CONTROL_PANEL; 2582141cc406Sopenharmony_ci s->opt[OPT_CONTROL_PANEL].desc = SANE_DESC_CONTROL_PANEL; 2583141cc406Sopenharmony_ci s->opt[OPT_CONTROL_PANEL].type = SANE_TYPE_BOOL; 2584141cc406Sopenharmony_ci s->opt[OPT_CONTROL_PANEL].constraint_type = SANE_CONSTRAINT_NONE; 2585141cc406Sopenharmony_ci s->val[OPT_CONTROL_PANEL].w = s->hw->info.control_panel_default; 2586141cc406Sopenharmony_ci 2587141cc406Sopenharmony_ci /* Ace_Function */ 2588141cc406Sopenharmony_ci s->opt[OPT_ACE_FUNCTION].name = SANE_NAME_ACE_FUNCTION; 2589141cc406Sopenharmony_ci s->opt[OPT_ACE_FUNCTION].title = SANE_TITLE_ACE_FUNCTION; 2590141cc406Sopenharmony_ci s->opt[OPT_ACE_FUNCTION].desc = SANE_DESC_ACE_FUNCTION; 2591141cc406Sopenharmony_ci s->opt[OPT_ACE_FUNCTION].type = SANE_TYPE_INT; 2592141cc406Sopenharmony_ci s->opt[OPT_ACE_FUNCTION].unit = SANE_UNIT_NONE; 2593141cc406Sopenharmony_ci s->opt[OPT_ACE_FUNCTION].constraint_type = SANE_CONSTRAINT_RANGE; 2594141cc406Sopenharmony_ci s->opt[OPT_ACE_FUNCTION].constraint.range = &ace_function_range; 2595141cc406Sopenharmony_ci s->val[OPT_ACE_FUNCTION].w = 0; 2596141cc406Sopenharmony_ci 2597141cc406Sopenharmony_ci /* Ace_Sensitivity */ 2598141cc406Sopenharmony_ci s->opt[OPT_ACE_SENSITIVITY].name = SANE_NAME_ACE_SENSITIVITY; 2599141cc406Sopenharmony_ci s->opt[OPT_ACE_SENSITIVITY].title = SANE_TITLE_ACE_SENSITIVITY; 2600141cc406Sopenharmony_ci s->opt[OPT_ACE_SENSITIVITY].desc = SANE_DESC_ACE_SENSITIVITY; 2601141cc406Sopenharmony_ci s->opt[OPT_ACE_SENSITIVITY].type = SANE_TYPE_INT; 2602141cc406Sopenharmony_ci s->opt[OPT_ACE_SENSITIVITY].unit = SANE_UNIT_NONE; 2603141cc406Sopenharmony_ci s->opt[OPT_ACE_SENSITIVITY].constraint_type = SANE_CONSTRAINT_RANGE; 2604141cc406Sopenharmony_ci s->opt[OPT_ACE_SENSITIVITY].constraint.range = &ace_sensitivity_range; 2605141cc406Sopenharmony_ci s->val[OPT_ACE_SENSITIVITY].w = 4; 2606141cc406Sopenharmony_ci 2607141cc406Sopenharmony_ci /* Brightness */ 2608141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; 2609141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; 2610141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; 2611141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; 2612141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; 2613141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; 2614141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].constraint.range = &u8_range; 2615141cc406Sopenharmony_ci s->val[OPT_BRIGHTNESS].w = 0; 2616141cc406Sopenharmony_ci 2617141cc406Sopenharmony_ci /* Threshold */ 2618141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; 2619141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; 2620141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; 2621141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; 2622141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; 2623141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; 2624141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].constraint.range = &u8_range; 2625141cc406Sopenharmony_ci s->val[OPT_THRESHOLD].w = 0; 2626141cc406Sopenharmony_ci 2627141cc406Sopenharmony_ci /* Contrast */ 2628141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; 2629141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; 2630141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; 2631141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].type = SANE_TYPE_INT; 2632141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; 2633141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; 2634141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].constraint.range = &u8_range; 2635141cc406Sopenharmony_ci s->val[OPT_CONTRAST].w = 0; 2636141cc406Sopenharmony_ci 2637141cc406Sopenharmony_ci /* Negative: */ 2638141cc406Sopenharmony_ci s->opt[OPT_NEGATIVE].name = SANE_NAME_NEGATIVE; 2639141cc406Sopenharmony_ci s->opt[OPT_NEGATIVE].title = SANE_TITLE_NEGATIVE; 2640141cc406Sopenharmony_ci s->opt[OPT_NEGATIVE].desc = SANE_DESC_NEGATIVE; 2641141cc406Sopenharmony_ci s->opt[OPT_NEGATIVE].type = SANE_TYPE_BOOL; 2642141cc406Sopenharmony_ci s->opt[OPT_NEGATIVE].constraint_type = SANE_CONSTRAINT_NONE; 2643141cc406Sopenharmony_ci s->val[OPT_NEGATIVE].w = SANE_FALSE; 2644141cc406Sopenharmony_ci 2645141cc406Sopenharmony_ci /* Contrast is not used in any case; why did we add it? */ 2646141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; 2647141cc406Sopenharmony_ci if (s->hw->info.control_panel_default == SANE_TRUE) 2648141cc406Sopenharmony_ci { 2649141cc406Sopenharmony_ci s->opt[OPT_ACE_FUNCTION].cap |= SANE_CAP_INACTIVE; 2650141cc406Sopenharmony_ci s->opt[OPT_ACE_SENSITIVITY].cap |= SANE_CAP_INACTIVE; 2651141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 2652141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 2653141cc406Sopenharmony_ci } 2654141cc406Sopenharmony_ci else if (s->hw->info.canACE == SANE_FALSE) 2655141cc406Sopenharmony_ci { 2656141cc406Sopenharmony_ci s->opt[OPT_ACE_FUNCTION].cap |= SANE_CAP_INACTIVE; 2657141cc406Sopenharmony_ci s->opt[OPT_ACE_SENSITIVITY].cap |= SANE_CAP_INACTIVE; 2658141cc406Sopenharmony_ci } 2659141cc406Sopenharmony_ci else 2660141cc406Sopenharmony_ci { 2661141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 2662141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 2663141cc406Sopenharmony_ci } 2664141cc406Sopenharmony_ci 2665141cc406Sopenharmony_ci /* "ICON" group: */ 2666141cc406Sopenharmony_ci s->opt[OPT_ICON_GROUP].name = ""; 2667141cc406Sopenharmony_ci s->opt[OPT_ICON_GROUP].title = SANE_TITLE_ICON_GROUP; 2668141cc406Sopenharmony_ci s->opt[OPT_ICON_GROUP].desc = ""; 2669141cc406Sopenharmony_ci s->opt[OPT_ICON_GROUP].type = SANE_TYPE_GROUP; 2670141cc406Sopenharmony_ci s->opt[OPT_ICON_GROUP].cap = SANE_CAP_ADVANCED; 2671141cc406Sopenharmony_ci s->opt[OPT_ICON_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2672141cc406Sopenharmony_ci 2673141cc406Sopenharmony_ci /* Icon_Width */ 2674141cc406Sopenharmony_ci s->opt[OPT_ICON_WIDTH].name = SANE_NAME_ICON_WIDTH; 2675141cc406Sopenharmony_ci s->opt[OPT_ICON_WIDTH].title = SANE_TITLE_ICON_WIDTH; 2676141cc406Sopenharmony_ci s->opt[OPT_ICON_WIDTH].desc = SANE_DESC_ICON_WIDTH; 2677141cc406Sopenharmony_ci s->opt[OPT_ICON_WIDTH].type = SANE_TYPE_INT; 2678141cc406Sopenharmony_ci s->opt[OPT_ICON_WIDTH].unit = SANE_UNIT_PIXEL; 2679141cc406Sopenharmony_ci s->opt[OPT_ICON_WIDTH].constraint_type = SANE_CONSTRAINT_RANGE; 2680141cc406Sopenharmony_ci s->opt[OPT_ICON_WIDTH].constraint.range = &icon_range; 2681141cc406Sopenharmony_ci s->val[OPT_ICON_WIDTH].w = 0; 2682141cc406Sopenharmony_ci 2683141cc406Sopenharmony_ci /* Icon_Length */ 2684141cc406Sopenharmony_ci s->opt[OPT_ICON_LENGTH].name = SANE_NAME_ICON_LENGTH; 2685141cc406Sopenharmony_ci s->opt[OPT_ICON_LENGTH].title = SANE_TITLE_ICON_LENGTH; 2686141cc406Sopenharmony_ci s->opt[OPT_ICON_LENGTH].desc = SANE_DESC_ICON_LENGTH; 2687141cc406Sopenharmony_ci s->opt[OPT_ICON_LENGTH].type = SANE_TYPE_INT; 2688141cc406Sopenharmony_ci s->opt[OPT_ICON_LENGTH].unit = SANE_UNIT_PIXEL; 2689141cc406Sopenharmony_ci s->opt[OPT_ICON_LENGTH].constraint_type = SANE_CONSTRAINT_RANGE; 2690141cc406Sopenharmony_ci s->opt[OPT_ICON_LENGTH].constraint.range = &icon_range; 2691141cc406Sopenharmony_ci s->val[OPT_ICON_LENGTH].w = 0; 2692141cc406Sopenharmony_ci 2693141cc406Sopenharmony_ci if (s->hw->info.canIcon == SANE_FALSE) 2694141cc406Sopenharmony_ci { 2695141cc406Sopenharmony_ci s->opt[OPT_ICON_GROUP].cap |= SANE_CAP_INACTIVE; 2696141cc406Sopenharmony_ci s->opt[OPT_ICON_WIDTH].cap |= SANE_CAP_INACTIVE; 2697141cc406Sopenharmony_ci s->opt[OPT_ICON_LENGTH].cap |= SANE_CAP_INACTIVE; 2698141cc406Sopenharmony_ci } 2699141cc406Sopenharmony_ci 2700141cc406Sopenharmony_ci /* "Barcode" group: */ 2701141cc406Sopenharmony_ci s->opt[OPT_BARCODE_GROUP].name = ""; 2702141cc406Sopenharmony_ci s->opt[OPT_BARCODE_GROUP].title = SANE_TITLE_BARCODE_GROUP; 2703141cc406Sopenharmony_ci s->opt[OPT_BARCODE_GROUP].desc = ""; 2704141cc406Sopenharmony_ci s->opt[OPT_BARCODE_GROUP].type = SANE_TYPE_GROUP; 2705141cc406Sopenharmony_ci s->opt[OPT_BARCODE_GROUP].cap = SANE_CAP_ADVANCED; 2706141cc406Sopenharmony_ci s->opt[OPT_BARCODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2707141cc406Sopenharmony_ci 2708141cc406Sopenharmony_ci /* Add <name> to barcode search priority. */ 2709141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_BAR].name = SANE_NAME_BARCODE_SEARCH_BAR; 2710141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_BAR].title = SANE_TITLE_BARCODE_SEARCH_BAR; 2711141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_BAR].desc = SANE_DESC_BARCODE_SEARCH_BAR; 2712141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_BAR].type = SANE_TYPE_STRING; 2713141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_BAR].unit = SANE_UNIT_NONE; 2714141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_BAR].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2715141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_BAR].constraint.string_list = barcode_search_bar_list; 2716141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_BAR].size = max_string_size (barcode_search_bar_list); 2717141cc406Sopenharmony_ci s->val[OPT_BARCODE_SEARCH_BAR].s = strdup (barcode_search_bar_list[0]); 2718141cc406Sopenharmony_ci 2719141cc406Sopenharmony_ci /* Barcode search count (1-7, default 1). */ 2720141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_COUNT].name = SANE_NAME_BARCODE_SEARCH_COUNT; 2721141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_COUNT].title = SANE_TITLE_BARCODE_SEARCH_COUNT; 2722141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_COUNT].desc = SANE_DESC_BARCODE_SEARCH_COUNT; 2723141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_COUNT].type = SANE_TYPE_INT; 2724141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_COUNT].unit = SANE_UNIT_NONE; 2725141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_COUNT].constraint_type = SANE_CONSTRAINT_RANGE; 2726141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_COUNT].constraint.range = &barcode_search_count_range; 2727141cc406Sopenharmony_ci s->val[OPT_BARCODE_SEARCH_COUNT].w = 3; 2728141cc406Sopenharmony_ci 2729141cc406Sopenharmony_ci /* Barcode search mode. horiz-vert, horizontal, vertical, vert-horiz */ 2730141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_MODE].name = SANE_NAME_BARCODE_SEARCH_MODE; 2731141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_MODE].title = SANE_TITLE_BARCODE_SEARCH_MODE; 2732141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_MODE].desc = SANE_DESC_BARCODE_SEARCH_MODE; 2733141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_MODE].type = SANE_TYPE_STRING; 2734141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_MODE].size = max_string_size (barcode_search_mode_list); 2735141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2736141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_MODE].constraint.string_list = barcode_search_mode_list; 2737141cc406Sopenharmony_ci s->val[OPT_BARCODE_SEARCH_MODE].s = strdup(barcode_search_mode_list[0]); 2738141cc406Sopenharmony_ci 2739141cc406Sopenharmony_ci /* Patch code min height (def=5mm) */ 2740141cc406Sopenharmony_ci s->opt[OPT_BARCODE_HMIN].name = SANE_NAME_BARCODE_HMIN; 2741141cc406Sopenharmony_ci s->opt[OPT_BARCODE_HMIN].title = SANE_TITLE_BARCODE_HMIN; 2742141cc406Sopenharmony_ci s->opt[OPT_BARCODE_HMIN].desc = SANE_DESC_BARCODE_HMIN; 2743141cc406Sopenharmony_ci s->opt[OPT_BARCODE_HMIN].type = SANE_TYPE_INT; 2744141cc406Sopenharmony_ci s->opt[OPT_BARCODE_HMIN].unit = SANE_UNIT_MM; 2745141cc406Sopenharmony_ci s->opt[OPT_BARCODE_HMIN].constraint_type = SANE_CONSTRAINT_RANGE; 2746141cc406Sopenharmony_ci s->opt[OPT_BARCODE_HMIN].constraint.range = &barcode_hmin_range; 2747141cc406Sopenharmony_ci s->val[OPT_BARCODE_HMIN].w = 5; 2748141cc406Sopenharmony_ci 2749141cc406Sopenharmony_ci /* Barcode search timeout in ms (20-65535,default is 10000). */ 2750141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_TIMEOUT].name = SANE_NAME_BARCODE_SEARCH_TIMEOUT; 2751141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_TIMEOUT].title = SANE_TITLE_BARCODE_SEARCH_TIMEOUT; 2752141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_TIMEOUT].desc = SANE_DESC_BARCODE_SEARCH_TIMEOUT; 2753141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_TIMEOUT].type = SANE_TYPE_INT; 2754141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_TIMEOUT].unit = SANE_UNIT_MICROSECOND; 2755141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_TIMEOUT].constraint_type = SANE_CONSTRAINT_RANGE; 2756141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_TIMEOUT].constraint.range = &barcode_search_timeout_range; 2757141cc406Sopenharmony_ci s->val[OPT_BARCODE_SEARCH_TIMEOUT].w = 10000; 2758141cc406Sopenharmony_ci 2759141cc406Sopenharmony_ci /* Specify image sections and functions */ 2760141cc406Sopenharmony_ci s->opt[OPT_SECTION].name = SANE_NAME_SECTION; 2761141cc406Sopenharmony_ci s->opt[OPT_SECTION].title = SANE_TITLE_SECTION; 2762141cc406Sopenharmony_ci s->opt[OPT_SECTION].desc = SANE_DESC_SECTION; 2763141cc406Sopenharmony_ci s->opt[OPT_SECTION].type = SANE_TYPE_STRING; 2764141cc406Sopenharmony_ci s->opt[OPT_SECTION].unit = SANE_UNIT_NONE; 2765141cc406Sopenharmony_ci s->opt[OPT_SECTION].constraint_type = SANE_CONSTRAINT_NONE; 2766141cc406Sopenharmony_ci s->opt[OPT_SECTION].size = 255; 2767141cc406Sopenharmony_ci s->val[OPT_SECTION].s = strdup (""); 2768141cc406Sopenharmony_ci 2769141cc406Sopenharmony_ci /* Barcode_Relmax */ 2770141cc406Sopenharmony_ci s->opt[OPT_BARCODE_RELMAX].name = SANE_NAME_BARCODE_RELMAX; 2771141cc406Sopenharmony_ci s->opt[OPT_BARCODE_RELMAX].title = SANE_TITLE_BARCODE_RELMAX; 2772141cc406Sopenharmony_ci s->opt[OPT_BARCODE_RELMAX].desc = SANE_DESC_BARCODE_RELMAX; 2773141cc406Sopenharmony_ci s->opt[OPT_BARCODE_RELMAX].type = SANE_TYPE_INT; 2774141cc406Sopenharmony_ci s->opt[OPT_BARCODE_RELMAX].unit = SANE_UNIT_NONE; 2775141cc406Sopenharmony_ci s->opt[OPT_BARCODE_RELMAX].constraint_type = SANE_CONSTRAINT_RANGE; 2776141cc406Sopenharmony_ci s->opt[OPT_BARCODE_RELMAX].constraint.range = &u8_range; 2777141cc406Sopenharmony_ci s->val[OPT_BARCODE_RELMAX].w = 0; 2778141cc406Sopenharmony_ci 2779141cc406Sopenharmony_ci /* Barcode_Barmin */ 2780141cc406Sopenharmony_ci s->opt[OPT_BARCODE_BARMIN].name = SANE_NAME_BARCODE_BARMIN; 2781141cc406Sopenharmony_ci s->opt[OPT_BARCODE_BARMIN].title = SANE_TITLE_BARCODE_BARMIN; 2782141cc406Sopenharmony_ci s->opt[OPT_BARCODE_BARMIN].desc = SANE_DESC_BARCODE_BARMIN; 2783141cc406Sopenharmony_ci s->opt[OPT_BARCODE_BARMIN].type = SANE_TYPE_INT; 2784141cc406Sopenharmony_ci s->opt[OPT_BARCODE_BARMIN].unit = SANE_UNIT_NONE; 2785141cc406Sopenharmony_ci s->opt[OPT_BARCODE_BARMIN].constraint_type = SANE_CONSTRAINT_RANGE; 2786141cc406Sopenharmony_ci s->opt[OPT_BARCODE_BARMIN].constraint.range = &u8_range; 2787141cc406Sopenharmony_ci s->val[OPT_BARCODE_BARMIN].w = 0; 2788141cc406Sopenharmony_ci 2789141cc406Sopenharmony_ci /* Barcode_Barmax */ 2790141cc406Sopenharmony_ci s->opt[OPT_BARCODE_BARMAX].name = SANE_NAME_BARCODE_BARMAX; 2791141cc406Sopenharmony_ci s->opt[OPT_BARCODE_BARMAX].title = SANE_TITLE_BARCODE_BARMAX; 2792141cc406Sopenharmony_ci s->opt[OPT_BARCODE_BARMAX].desc = SANE_DESC_BARCODE_BARMAX; 2793141cc406Sopenharmony_ci s->opt[OPT_BARCODE_BARMAX].type = SANE_TYPE_INT; 2794141cc406Sopenharmony_ci s->opt[OPT_BARCODE_BARMAX].unit = SANE_UNIT_NONE; 2795141cc406Sopenharmony_ci s->opt[OPT_BARCODE_BARMAX].constraint_type = SANE_CONSTRAINT_RANGE; 2796141cc406Sopenharmony_ci s->opt[OPT_BARCODE_BARMAX].constraint.range = &u8_range; 2797141cc406Sopenharmony_ci s->val[OPT_BARCODE_BARMAX].w = 0; 2798141cc406Sopenharmony_ci 2799141cc406Sopenharmony_ci /* Barcode_Contrast */ 2800141cc406Sopenharmony_ci s->opt[OPT_BARCODE_CONTRAST].name = SANE_NAME_BARCODE_CONTRAST; 2801141cc406Sopenharmony_ci s->opt[OPT_BARCODE_CONTRAST].title = SANE_TITLE_BARCODE_CONTRAST; 2802141cc406Sopenharmony_ci s->opt[OPT_BARCODE_CONTRAST].desc = SANE_DESC_BARCODE_CONTRAST; 2803141cc406Sopenharmony_ci s->opt[OPT_BARCODE_CONTRAST].type = SANE_TYPE_INT; 2804141cc406Sopenharmony_ci s->opt[OPT_BARCODE_CONTRAST].unit = SANE_UNIT_NONE; 2805141cc406Sopenharmony_ci s->opt[OPT_BARCODE_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; 2806141cc406Sopenharmony_ci s->opt[OPT_BARCODE_CONTRAST].constraint.range = &barcode_contrast_range; 2807141cc406Sopenharmony_ci s->val[OPT_BARCODE_CONTRAST].w = 3; 2808141cc406Sopenharmony_ci 2809141cc406Sopenharmony_ci /* Barcode_Patchmode */ 2810141cc406Sopenharmony_ci s->opt[OPT_BARCODE_PATCHMODE].name = SANE_NAME_BARCODE_PATCHMODE; 2811141cc406Sopenharmony_ci s->opt[OPT_BARCODE_PATCHMODE].title = SANE_TITLE_BARCODE_PATCHMODE; 2812141cc406Sopenharmony_ci s->opt[OPT_BARCODE_PATCHMODE].desc = SANE_DESC_BARCODE_PATCHMODE; 2813141cc406Sopenharmony_ci s->opt[OPT_BARCODE_PATCHMODE].type = SANE_TYPE_INT; 2814141cc406Sopenharmony_ci s->opt[OPT_BARCODE_PATCHMODE].unit = SANE_UNIT_NONE; 2815141cc406Sopenharmony_ci s->opt[OPT_BARCODE_PATCHMODE].constraint_type = SANE_CONSTRAINT_RANGE; 2816141cc406Sopenharmony_ci s->opt[OPT_BARCODE_PATCHMODE].constraint.range = &barcode_patchmode_range; 2817141cc406Sopenharmony_ci s->val[OPT_BARCODE_PATCHMODE].w = 0; 2818141cc406Sopenharmony_ci 2819141cc406Sopenharmony_ci if (s->hw->info.canSection == SANE_FALSE) 2820141cc406Sopenharmony_ci { 2821141cc406Sopenharmony_ci s->opt[OPT_SECTION].cap |= SANE_CAP_INACTIVE; 2822141cc406Sopenharmony_ci } 2823141cc406Sopenharmony_ci 2824141cc406Sopenharmony_ci if (s->hw->info.canBarCode == SANE_FALSE) 2825141cc406Sopenharmony_ci { 2826141cc406Sopenharmony_ci s->opt[OPT_BARCODE_GROUP].cap |= SANE_CAP_INACTIVE; 2827141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_BAR].cap |= SANE_CAP_INACTIVE; 2828141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_COUNT].cap |= SANE_CAP_INACTIVE; 2829141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_MODE].cap |= SANE_CAP_INACTIVE; 2830141cc406Sopenharmony_ci s->opt[OPT_BARCODE_HMIN].cap |= SANE_CAP_INACTIVE; 2831141cc406Sopenharmony_ci s->opt[OPT_BARCODE_SEARCH_TIMEOUT].cap |= SANE_CAP_INACTIVE; 2832141cc406Sopenharmony_ci s->opt[OPT_BARCODE_RELMAX].cap |= SANE_CAP_INACTIVE; 2833141cc406Sopenharmony_ci s->opt[OPT_BARCODE_BARMIN].cap |= SANE_CAP_INACTIVE; 2834141cc406Sopenharmony_ci s->opt[OPT_BARCODE_BARMAX].cap |= SANE_CAP_INACTIVE; 2835141cc406Sopenharmony_ci s->opt[OPT_BARCODE_CONTRAST].cap |= SANE_CAP_INACTIVE; 2836141cc406Sopenharmony_ci s->opt[OPT_BARCODE_PATCHMODE].cap |= SANE_CAP_INACTIVE; 2837141cc406Sopenharmony_ci } 2838141cc406Sopenharmony_ci 2839141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2840141cc406Sopenharmony_ci} 2841141cc406Sopenharmony_ci 2842141cc406Sopenharmony_cistatic SANE_Status 2843141cc406Sopenharmony_ciattach (const char *devnam, BH_Device ** devp) 2844141cc406Sopenharmony_ci{ 2845141cc406Sopenharmony_ci SANE_Status status; 2846141cc406Sopenharmony_ci BH_Device *dev; 2847141cc406Sopenharmony_ci struct inquiry_standard_data ibuf; 2848141cc406Sopenharmony_ci struct inquiry_vpd_data vbuf; 2849141cc406Sopenharmony_ci struct inquiry_jis_data jbuf; 2850141cc406Sopenharmony_ci size_t buf_size; 2851141cc406Sopenharmony_ci int fd = -1; 2852141cc406Sopenharmony_ci double mm; 2853141cc406Sopenharmony_ci 2854141cc406Sopenharmony_ci DBG (3, "attach called\n"); 2855141cc406Sopenharmony_ci 2856141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 2857141cc406Sopenharmony_ci { 2858141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devnam) == 0) 2859141cc406Sopenharmony_ci { 2860141cc406Sopenharmony_ci if (devp) 2861141cc406Sopenharmony_ci *devp = dev; 2862141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2863141cc406Sopenharmony_ci } 2864141cc406Sopenharmony_ci } 2865141cc406Sopenharmony_ci 2866141cc406Sopenharmony_ci#ifdef FAKE_INQUIRY 2867141cc406Sopenharmony_ci if (fake_inquiry) 2868141cc406Sopenharmony_ci { 2869141cc406Sopenharmony_ci DBG (3, "attach: faking inquiry of %s\n", devnam); 2870141cc406Sopenharmony_ci 2871141cc406Sopenharmony_ci memset (&ibuf, 0, sizeof (ibuf)); 2872141cc406Sopenharmony_ci ibuf.devtype = 6; 2873141cc406Sopenharmony_ci memcpy(ibuf.vendor, "**FAKE**", 8); 2874141cc406Sopenharmony_ci memcpy(ibuf.product, "COPISCAN II 6338", 16); 2875141cc406Sopenharmony_ci memcpy(ibuf.revision, "0016", 4); 2876141cc406Sopenharmony_ci 2877141cc406Sopenharmony_ci DBG (1, "attach: reported devtype='%d', vendor='%.8s', " 2878141cc406Sopenharmony_ci "product='%.16s', revision='%.4s'\n", 2879141cc406Sopenharmony_ci ibuf.devtype, ibuf.vendor, 2880141cc406Sopenharmony_ci ibuf.product, ibuf.revision); 2881141cc406Sopenharmony_ci 2882141cc406Sopenharmony_ci memset (&vbuf, 0, sizeof (vbuf)); 2883141cc406Sopenharmony_ci memset (&jbuf, 0, sizeof (jbuf)); 2884141cc406Sopenharmony_ci } 2885141cc406Sopenharmony_ci else 2886141cc406Sopenharmony_ci#endif 2887141cc406Sopenharmony_ci { 2888141cc406Sopenharmony_ci DBG (3, "attach: opening %s\n", devnam); 2889141cc406Sopenharmony_ci status = sanei_scsi_open (devnam, &fd, sense_handler, NULL); 2890141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2891141cc406Sopenharmony_ci { 2892141cc406Sopenharmony_ci DBG (1, "attach: open failed: %s\n", sane_strstatus (status)); 2893141cc406Sopenharmony_ci return status; 2894141cc406Sopenharmony_ci } 2895141cc406Sopenharmony_ci 2896141cc406Sopenharmony_ci DBG (3, "attach: sending TEST_UNIT_READY\n"); 2897141cc406Sopenharmony_ci status = test_unit_ready (fd); 2898141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2899141cc406Sopenharmony_ci { 2900141cc406Sopenharmony_ci DBG (1, "attach: test unit ready failed (%s)\n", 2901141cc406Sopenharmony_ci sane_strstatus (status)); 2902141cc406Sopenharmony_ci sanei_scsi_close (fd); 2903141cc406Sopenharmony_ci return status; 2904141cc406Sopenharmony_ci } 2905141cc406Sopenharmony_ci 2906141cc406Sopenharmony_ci DBG (3, "attach: sending INQUIRY (standard data)\n"); 2907141cc406Sopenharmony_ci memset (&ibuf, 0, sizeof (ibuf)); 2908141cc406Sopenharmony_ci buf_size = sizeof(ibuf); 2909141cc406Sopenharmony_ci status = inquiry (fd, &ibuf, &buf_size, 0, 2910141cc406Sopenharmony_ci BH_INQUIRY_STANDARD_PAGE_CODE); 2911141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2912141cc406Sopenharmony_ci { 2913141cc406Sopenharmony_ci DBG (1, "attach: inquiry (standard data) failed: %s\n", 2914141cc406Sopenharmony_ci sane_strstatus (status)); 2915141cc406Sopenharmony_ci sanei_scsi_close (fd); 2916141cc406Sopenharmony_ci return status; 2917141cc406Sopenharmony_ci } 2918141cc406Sopenharmony_ci 2919141cc406Sopenharmony_ci DBG (1, "attach: reported devtype='%d', vendor='%.8s', " 2920141cc406Sopenharmony_ci "product='%.16s', revision='%.4s'\n", 2921141cc406Sopenharmony_ci ibuf.devtype, ibuf.vendor, 2922141cc406Sopenharmony_ci ibuf.product, ibuf.revision); 2923141cc406Sopenharmony_ci 2924141cc406Sopenharmony_ci if (ibuf.devtype != 6 2925141cc406Sopenharmony_ci || strncmp ((char *)ibuf.vendor, "B&H SCSI", 8) != 0 2926141cc406Sopenharmony_ci || strncmp ((char *)ibuf.product, "COPISCAN ", 9) != 0) 2927141cc406Sopenharmony_ci { 2928141cc406Sopenharmony_ci DBG (1, 2929141cc406Sopenharmony_ci "attach: device is not a recognized Bell and Howell scanner\n"); 2930141cc406Sopenharmony_ci sanei_scsi_close (fd); 2931141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2932141cc406Sopenharmony_ci } 2933141cc406Sopenharmony_ci 2934141cc406Sopenharmony_ci DBG (3, "attach: sending INQUIRY (vpd data)\n"); 2935141cc406Sopenharmony_ci memset (&vbuf, 0, sizeof (vbuf)); 2936141cc406Sopenharmony_ci buf_size = sizeof(vbuf); 2937141cc406Sopenharmony_ci status = inquiry (fd, &vbuf, &buf_size, 1, 2938141cc406Sopenharmony_ci BH_INQUIRY_VPD_PAGE_CODE); 2939141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2940141cc406Sopenharmony_ci { 2941141cc406Sopenharmony_ci DBG (1, "attach: inquiry (vpd data) failed: %s\n", 2942141cc406Sopenharmony_ci sane_strstatus (status)); 2943141cc406Sopenharmony_ci sanei_scsi_close (fd); 2944141cc406Sopenharmony_ci return status; 2945141cc406Sopenharmony_ci } 2946141cc406Sopenharmony_ci 2947141cc406Sopenharmony_ci DBG (3, "attach: sending INQUIRY (jis data)\n"); 2948141cc406Sopenharmony_ci memset (&jbuf, 0, sizeof (jbuf)); 2949141cc406Sopenharmony_ci buf_size = sizeof(jbuf); 2950141cc406Sopenharmony_ci status = inquiry (fd, &jbuf, &buf_size, 1, 2951141cc406Sopenharmony_ci BH_INQUIRY_JIS_PAGE_CODE); 2952141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2953141cc406Sopenharmony_ci { 2954141cc406Sopenharmony_ci DBG (1, "attach: inquiry (jis data) failed: %s\n", 2955141cc406Sopenharmony_ci sane_strstatus (status)); 2956141cc406Sopenharmony_ci sanei_scsi_close (fd); 2957141cc406Sopenharmony_ci return status; 2958141cc406Sopenharmony_ci } 2959141cc406Sopenharmony_ci 2960141cc406Sopenharmony_ci sanei_scsi_close (fd); 2961141cc406Sopenharmony_ci } 2962141cc406Sopenharmony_ci 2963141cc406Sopenharmony_ci dev = malloc (sizeof (*dev)); 2964141cc406Sopenharmony_ci if (!dev) 2965141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2966141cc406Sopenharmony_ci memset (dev, 0, sizeof (*dev)); 2967141cc406Sopenharmony_ci 2968141cc406Sopenharmony_ci 2969141cc406Sopenharmony_ci dev->info.devtype = ibuf.devtype; 2970141cc406Sopenharmony_ci sprintf(dev->info.vendor, "%.8s", ibuf.vendor); 2971141cc406Sopenharmony_ci trim_spaces(dev->info.vendor, sizeof(dev->info.vendor)); 2972141cc406Sopenharmony_ci sprintf(dev->info.product, "%.16s", ibuf.product); 2973141cc406Sopenharmony_ci trim_spaces(dev->info.product, sizeof(dev->info.product)); 2974141cc406Sopenharmony_ci sprintf(dev->info.revision, "%.4s", ibuf.revision); 2975141cc406Sopenharmony_ci trim_spaces(dev->info.revision, sizeof(dev->info.revision)); 2976141cc406Sopenharmony_ci 2977141cc406Sopenharmony_ci dev->sane.name = strdup (devnam); 2978141cc406Sopenharmony_ci dev->sane.vendor = strdup(dev->info.vendor); 2979141cc406Sopenharmony_ci dev->sane.model = strdup(dev->info.product);; 2980141cc406Sopenharmony_ci dev->sane.type = strdup(print_devtype(dev->info.devtype)); 2981141cc406Sopenharmony_ci 2982141cc406Sopenharmony_ci /* set capabilities from vpd */ 2983141cc406Sopenharmony_ci dev->info.canADF = vbuf.adf & 0x01; 2984141cc406Sopenharmony_ci dev->info.colorBandW = vbuf.imagecomposition & 0x01; 2985141cc406Sopenharmony_ci dev->info.colorHalftone = vbuf.imagecomposition & 0x02; 2986141cc406Sopenharmony_ci dev->info.canWhiteFrame = vbuf.imagedataprocessing[1] & 0x01; 2987141cc406Sopenharmony_ci dev->info.canBlackFrame = vbuf.imagedataprocessing[1] & 0x02; 2988141cc406Sopenharmony_ci dev->info.canEdgeExtract = vbuf.imagedataprocessing[1] & 0x04; 2989141cc406Sopenharmony_ci dev->info.canNoiseFilter = vbuf.imagedataprocessing[1] & 0x08; 2990141cc406Sopenharmony_ci dev->info.canSmooth = vbuf.imagedataprocessing[1] & 0x10; 2991141cc406Sopenharmony_ci dev->info.canLineBold = vbuf.imagedataprocessing[1] & 0x20; 2992141cc406Sopenharmony_ci dev->info.comprG3_1D = vbuf.compression & 0x01; 2993141cc406Sopenharmony_ci dev->info.comprG3_2D = vbuf.compression & 0x02; 2994141cc406Sopenharmony_ci dev->info.comprG4 = vbuf.compression & 0x04; 2995141cc406Sopenharmony_ci dev->info.canBorderRecog = vbuf.sizerecognition & 0x01; 2996141cc406Sopenharmony_ci dev->info.canBarCode = vbuf.optionalfeatures & 0x01; 2997141cc406Sopenharmony_ci dev->info.canIcon = vbuf.optionalfeatures & 0x02; 2998141cc406Sopenharmony_ci dev->info.canSection = vbuf.optionalfeatures & 0x04; 2999141cc406Sopenharmony_ci dev->info.lineMaxBytes = _2btol(vbuf.xmaxoutputbytes); 3000141cc406Sopenharmony_ci 3001141cc406Sopenharmony_ci#ifdef FAKE_INQUIRY 3002141cc406Sopenharmony_ci if (fake_inquiry) 3003141cc406Sopenharmony_ci { 3004141cc406Sopenharmony_ci dev->info.canADF = SANE_FALSE; 3005141cc406Sopenharmony_ci dev->info.colorBandW = SANE_TRUE; 3006141cc406Sopenharmony_ci dev->info.colorHalftone = SANE_TRUE; 3007141cc406Sopenharmony_ci dev->info.canWhiteFrame = SANE_TRUE; 3008141cc406Sopenharmony_ci dev->info.canBlackFrame = SANE_TRUE; 3009141cc406Sopenharmony_ci dev->info.canEdgeExtract = SANE_TRUE; 3010141cc406Sopenharmony_ci dev->info.canNoiseFilter = SANE_TRUE; 3011141cc406Sopenharmony_ci dev->info.canSmooth = SANE_TRUE; 3012141cc406Sopenharmony_ci dev->info.canLineBold = SANE_TRUE; 3013141cc406Sopenharmony_ci dev->info.comprG3_1D = SANE_TRUE; 3014141cc406Sopenharmony_ci dev->info.comprG3_2D = SANE_TRUE; 3015141cc406Sopenharmony_ci dev->info.comprG4 = SANE_TRUE; 3016141cc406Sopenharmony_ci dev->info.canBorderRecog = SANE_TRUE; 3017141cc406Sopenharmony_ci dev->info.canBarCode = SANE_TRUE; 3018141cc406Sopenharmony_ci dev->info.canIcon = SANE_TRUE; 3019141cc406Sopenharmony_ci dev->info.canSection = SANE_TRUE; 3020141cc406Sopenharmony_ci dev->info.lineMaxBytes = 450; 3021141cc406Sopenharmony_ci } 3022141cc406Sopenharmony_ci#endif 3023141cc406Sopenharmony_ci 3024141cc406Sopenharmony_ci /* set capabilities from jis */ 3025141cc406Sopenharmony_ci dev->info.resBasicX = _2btol(jbuf.basicxres); 3026141cc406Sopenharmony_ci dev->info.resBasicY = _2btol(jbuf.basicyres); 3027141cc406Sopenharmony_ci dev->info.resMaxX = _2btol(jbuf.maxxres); 3028141cc406Sopenharmony_ci dev->info.resMaxY = _2btol(jbuf.maxyres); 3029141cc406Sopenharmony_ci dev->info.resMinX = _2btol(jbuf.minxres); 3030141cc406Sopenharmony_ci dev->info.resMinY = _2btol(jbuf.minyres); 3031141cc406Sopenharmony_ci 3032141cc406Sopenharmony_ci /* set the length of the list to zero first, then append standard resolutions */ 3033141cc406Sopenharmony_ci dev->info.resStdList[0] = 0; 3034141cc406Sopenharmony_ci if (jbuf.standardres[0] & 0x80) appendStdList(&dev->info, 60); 3035141cc406Sopenharmony_ci if (jbuf.standardres[0] & 0x40) appendStdList(&dev->info, 75); 3036141cc406Sopenharmony_ci if (jbuf.standardres[0] & 0x20) appendStdList(&dev->info, 100); 3037141cc406Sopenharmony_ci if (jbuf.standardres[0] & 0x10) appendStdList(&dev->info, 120); 3038141cc406Sopenharmony_ci if (jbuf.standardres[0] & 0x08) appendStdList(&dev->info, 150); 3039141cc406Sopenharmony_ci if (jbuf.standardres[0] & 0x04) appendStdList(&dev->info, 160); 3040141cc406Sopenharmony_ci if (jbuf.standardres[0] & 0x02) appendStdList(&dev->info, 180); 3041141cc406Sopenharmony_ci if (jbuf.standardres[0] & 0x01) appendStdList(&dev->info, 200); 3042141cc406Sopenharmony_ci if (jbuf.standardres[1] & 0x80) appendStdList(&dev->info, 240); 3043141cc406Sopenharmony_ci if (jbuf.standardres[1] & 0x40) appendStdList(&dev->info, 300); 3044141cc406Sopenharmony_ci if (jbuf.standardres[1] & 0x20) appendStdList(&dev->info, 320); 3045141cc406Sopenharmony_ci if (jbuf.standardres[1] & 0x10) appendStdList(&dev->info, 400); 3046141cc406Sopenharmony_ci if (jbuf.standardres[1] & 0x08) appendStdList(&dev->info, 480); 3047141cc406Sopenharmony_ci if (jbuf.standardres[1] & 0x04) appendStdList(&dev->info, 600); 3048141cc406Sopenharmony_ci if (jbuf.standardres[1] & 0x02) appendStdList(&dev->info, 800); 3049141cc406Sopenharmony_ci if (jbuf.standardres[1] & 0x01) appendStdList(&dev->info, 1200); 3050141cc406Sopenharmony_ci if (dev->info.resStdList[0] == 0) 3051141cc406Sopenharmony_ci { 3052141cc406Sopenharmony_ci /* make a default standard resolutions for 200 and 300dpi */ 3053141cc406Sopenharmony_ci DBG(1, "attach: no standard resolutions reported\n"); 3054141cc406Sopenharmony_ci dev->info.resStdList[0] = 2; 3055141cc406Sopenharmony_ci dev->info.resStdList[1] = 200; 3056141cc406Sopenharmony_ci dev->info.resStdList[2] = 300; 3057141cc406Sopenharmony_ci dev->info.resBasicX = dev->info.resBasicY = 300; 3058141cc406Sopenharmony_ci } 3059141cc406Sopenharmony_ci 3060141cc406Sopenharmony_ci dev->info.winWidth = _4btol(jbuf.windowwidth); 3061141cc406Sopenharmony_ci dev->info.winHeight = _4btol(jbuf.windowlength); 3062141cc406Sopenharmony_ci 3063141cc406Sopenharmony_ci if (dev->info.winWidth <= 0) 3064141cc406Sopenharmony_ci { 3065141cc406Sopenharmony_ci dev->info.winWidth = (SANE_Int) (dev->info.resBasicX * 8.5); 3066141cc406Sopenharmony_ci DBG(1, "attach: invalid window width reported, using %d\n", dev->info.winWidth); 3067141cc406Sopenharmony_ci } 3068141cc406Sopenharmony_ci if (dev->info.winHeight <= 0) 3069141cc406Sopenharmony_ci { 3070141cc406Sopenharmony_ci dev->info.winHeight = dev->info.resBasicY * 14; 3071141cc406Sopenharmony_ci DBG(1, "attach: invalid window height reported, using %d\n", dev->info.winHeight); 3072141cc406Sopenharmony_ci } 3073141cc406Sopenharmony_ci 3074141cc406Sopenharmony_ci mm = (dev->info.resBasicX > 0) ? 3075141cc406Sopenharmony_ci ((double) dev->info.winWidth / (double) dev->info.resBasicX * MM_PER_INCH) : 3076141cc406Sopenharmony_ci 0.0; 3077141cc406Sopenharmony_ci dev->info.x_range.min = SANE_FIX(0.0); 3078141cc406Sopenharmony_ci dev->info.x_range.max = SANE_FIX(mm); 3079141cc406Sopenharmony_ci dev->info.x_range.quant = SANE_FIX(0.0); 3080141cc406Sopenharmony_ci 3081141cc406Sopenharmony_ci mm = (dev->info.resBasicY > 0) ? 3082141cc406Sopenharmony_ci ((double) dev->info.winHeight / (double) dev->info.resBasicY * MM_PER_INCH) : 3083141cc406Sopenharmony_ci 0.0; 3084141cc406Sopenharmony_ci dev->info.y_range.min = SANE_FIX(0.0); 3085141cc406Sopenharmony_ci dev->info.y_range.max = SANE_FIX(mm); 3086141cc406Sopenharmony_ci dev->info.y_range.quant = SANE_FIX(0.0); 3087141cc406Sopenharmony_ci 3088141cc406Sopenharmony_ci /* set additional discovered/guessed capabilities */ 3089141cc406Sopenharmony_ci 3090141cc406Sopenharmony_ci /* if all of the ACE capabilities are present, declare it ACE capable */ 3091141cc406Sopenharmony_ci dev->info.canACE = dev->info.canEdgeExtract && 3092141cc406Sopenharmony_ci dev->info.canNoiseFilter && 3093141cc406Sopenharmony_ci dev->info.canSmooth && 3094141cc406Sopenharmony_ci dev->info.canLineBold; 3095141cc406Sopenharmony_ci 3096141cc406Sopenharmony_ci /* if the model is known to be a duplex, declare it duplex capable */ 3097141cc406Sopenharmony_ci if (strcmp(dev->info.product, "COPISCAN II 6338") == 0) 3098141cc406Sopenharmony_ci { 3099141cc406Sopenharmony_ci dev->info.canDuplex = SANE_TRUE; 3100141cc406Sopenharmony_ci } 3101141cc406Sopenharmony_ci else 3102141cc406Sopenharmony_ci { 3103141cc406Sopenharmony_ci dev->info.canDuplex = SANE_FALSE; 3104141cc406Sopenharmony_ci } 3105141cc406Sopenharmony_ci 3106141cc406Sopenharmony_ci /* the paper sensor requires RSC revision 1.4 or higher and an 3107141cc406Sopenharmony_ci * installed feeder. NOTE: It also requires SW-4 on and the 3108141cc406Sopenharmony_ci * AccufeedPlus feeder, but we cannot discover that. 3109141cc406Sopenharmony_ci */ 3110141cc406Sopenharmony_ci if (strcmp(dev->info.revision, "0014") >= 0) 3111141cc406Sopenharmony_ci { 3112141cc406Sopenharmony_ci dev->info.canCheckADF = dev->info.canADF; 3113141cc406Sopenharmony_ci } 3114141cc406Sopenharmony_ci else 3115141cc406Sopenharmony_ci { 3116141cc406Sopenharmony_ci dev->info.canCheckADF = SANE_FALSE; 3117141cc406Sopenharmony_ci } 3118141cc406Sopenharmony_ci 3119141cc406Sopenharmony_ci /* set option defaults based on inquiry information */ 3120141cc406Sopenharmony_ci dev->info.res_default = dev->info.resBasicX; 3121141cc406Sopenharmony_ci dev->info.autoborder_default = dev->info.canBorderRecog; 3122141cc406Sopenharmony_ci dev->info.batch_default = SANE_FALSE; 3123141cc406Sopenharmony_ci dev->info.deskew_default = SANE_FALSE; 3124141cc406Sopenharmony_ci dev->info.check_adf_default = SANE_FALSE; 3125141cc406Sopenharmony_ci dev->info.duplex_default = SANE_FALSE; 3126141cc406Sopenharmony_ci dev->info.timeout_adf_default = 0; 3127141cc406Sopenharmony_ci dev->info.timeout_manual_default = 0; 3128141cc406Sopenharmony_ci dev->info.control_panel_default = dev->info.canACE; 3129141cc406Sopenharmony_ci 3130141cc406Sopenharmony_ci ++num_devices; 3131141cc406Sopenharmony_ci dev->next = first_dev; 3132141cc406Sopenharmony_ci first_dev = dev; 3133141cc406Sopenharmony_ci 3134141cc406Sopenharmony_ci if (devp) 3135141cc406Sopenharmony_ci *devp = dev; 3136141cc406Sopenharmony_ci 3137141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3138141cc406Sopenharmony_ci} 3139141cc406Sopenharmony_ci 3140141cc406Sopenharmony_cistatic SANE_Status 3141141cc406Sopenharmony_ciattach_one(const char *devnam) 3142141cc406Sopenharmony_ci{ 3143141cc406Sopenharmony_ci attach (devnam, NULL); 3144141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3145141cc406Sopenharmony_ci} 3146141cc406Sopenharmony_ci 3147141cc406Sopenharmony_ciSANE_Status 3148141cc406Sopenharmony_cisane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) 3149141cc406Sopenharmony_ci{ 3150141cc406Sopenharmony_ci char devnam[PATH_MAX] = "/dev/scanner"; 3151141cc406Sopenharmony_ci FILE *fp; 3152141cc406Sopenharmony_ci 3153141cc406Sopenharmony_ci (void) authorize; /* get rid of compiler warning */ 3154141cc406Sopenharmony_ci 3155141cc406Sopenharmony_ci DBG_INIT(); 3156141cc406Sopenharmony_ci DBG(3, "sane_init called\n"); 3157141cc406Sopenharmony_ci DBG(1, "Bell+Howell SANE backend %d.%d build %d %s endian\n", 3158141cc406Sopenharmony_ci SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD, 3159141cc406Sopenharmony_ci _is_host_little_endian() ? "little" : "big"); 3160141cc406Sopenharmony_ci 3161141cc406Sopenharmony_ci if (version_code) 3162141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 3163141cc406Sopenharmony_ci 3164141cc406Sopenharmony_ci fp = sanei_config_open(BH_CONFIG_FILE); 3165141cc406Sopenharmony_ci if (fp) 3166141cc406Sopenharmony_ci { 3167141cc406Sopenharmony_ci char line[PATH_MAX]; 3168141cc406Sopenharmony_ci const char *lp; 3169141cc406Sopenharmony_ci size_t len; 3170141cc406Sopenharmony_ci 3171141cc406Sopenharmony_ci /* read config file */ 3172141cc406Sopenharmony_ci while (sanei_config_read (line, sizeof (line), fp)) 3173141cc406Sopenharmony_ci { 3174141cc406Sopenharmony_ci if (line[0] == '#') /* ignore line comments */ 3175141cc406Sopenharmony_ci continue; 3176141cc406Sopenharmony_ci len = strlen (line); 3177141cc406Sopenharmony_ci 3178141cc406Sopenharmony_ci if (!len) 3179141cc406Sopenharmony_ci continue; /* ignore empty lines */ 3180141cc406Sopenharmony_ci 3181141cc406Sopenharmony_ci lp = sanei_config_skip_whitespace (line); 3182141cc406Sopenharmony_ci 3183141cc406Sopenharmony_ci DBG(16, 3184141cc406Sopenharmony_ci "sane_init: processing config file line '%s'\n", 3185141cc406Sopenharmony_ci line); 3186141cc406Sopenharmony_ci if (strncmp(lp, "option", 6) == 0 && 3187141cc406Sopenharmony_ci (isspace (lp[6]) || lp[6] == '\0')) 3188141cc406Sopenharmony_ci { 3189141cc406Sopenharmony_ci lp += 6; 3190141cc406Sopenharmony_ci lp = sanei_config_skip_whitespace (lp); 3191141cc406Sopenharmony_ci 3192141cc406Sopenharmony_ci if (strncmp(lp, "disable-optional-frames", 23) == 0) 3193141cc406Sopenharmony_ci { 3194141cc406Sopenharmony_ci DBG(1, "sane_init: configuration option " 3195141cc406Sopenharmony_ci "'disable-optional-frames' set\n"); 3196141cc406Sopenharmony_ci disable_optional_frames = 1; 3197141cc406Sopenharmony_ci } 3198141cc406Sopenharmony_ci else if (strncmp(lp, "fake-inquiry", 12) == 0) 3199141cc406Sopenharmony_ci { 3200141cc406Sopenharmony_ci DBG(1, "sane_init: configuration option " 3201141cc406Sopenharmony_ci "'fake-inquiry' set\n"); 3202141cc406Sopenharmony_ci fake_inquiry = 1; 3203141cc406Sopenharmony_ci } 3204141cc406Sopenharmony_ci else 3205141cc406Sopenharmony_ci { 3206141cc406Sopenharmony_ci DBG(1, "sane_init: ignoring unknown " 3207141cc406Sopenharmony_ci "configuration option '%s'\n", 3208141cc406Sopenharmony_ci lp); 3209141cc406Sopenharmony_ci } 3210141cc406Sopenharmony_ci } 3211141cc406Sopenharmony_ci else 3212141cc406Sopenharmony_ci { 3213141cc406Sopenharmony_ci DBG(16, 3214141cc406Sopenharmony_ci "sane_init: found a device: line '%s'\n", 3215141cc406Sopenharmony_ci lp); 3216141cc406Sopenharmony_ci strncpy (devnam, lp, sizeof(devnam)); 3217141cc406Sopenharmony_ci devnam[sizeof(devnam)-1] = '\0'; 3218141cc406Sopenharmony_ci 3219141cc406Sopenharmony_ci sanei_config_attach_matching_devices(devnam, 3220141cc406Sopenharmony_ci attach_one); 3221141cc406Sopenharmony_ci } 3222141cc406Sopenharmony_ci } 3223141cc406Sopenharmony_ci fclose (fp); 3224141cc406Sopenharmony_ci } 3225141cc406Sopenharmony_ci else 3226141cc406Sopenharmony_ci { 3227141cc406Sopenharmony_ci /* configure the /dev/scanner device in the absence of config file */ 3228141cc406Sopenharmony_ci sanei_config_attach_matching_devices ("/dev/scanner", attach_one); 3229141cc406Sopenharmony_ci } 3230141cc406Sopenharmony_ci 3231141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3232141cc406Sopenharmony_ci} 3233141cc406Sopenharmony_ci 3234141cc406Sopenharmony_ciSANE_Status 3235141cc406Sopenharmony_cisane_get_devices (const SANE_Device ***device_list, SANE_Bool local) 3236141cc406Sopenharmony_ci{ 3237141cc406Sopenharmony_ci BH_Device *dev; 3238141cc406Sopenharmony_ci int i; 3239141cc406Sopenharmony_ci DBG(3, "sane_get_devices called\n"); 3240141cc406Sopenharmony_ci 3241141cc406Sopenharmony_ci (void) local; /* get rid of compiler warning */ 3242141cc406Sopenharmony_ci if (devlist) 3243141cc406Sopenharmony_ci free (devlist); 3244141cc406Sopenharmony_ci devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); 3245141cc406Sopenharmony_ci if (!devlist) 3246141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 3247141cc406Sopenharmony_ci 3248141cc406Sopenharmony_ci i = 0; 3249141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 3250141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 3251141cc406Sopenharmony_ci devlist[i++] = 0; 3252141cc406Sopenharmony_ci 3253141cc406Sopenharmony_ci *device_list = devlist; 3254141cc406Sopenharmony_ci 3255141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3256141cc406Sopenharmony_ci} 3257141cc406Sopenharmony_ci 3258141cc406Sopenharmony_ciSANE_Status 3259141cc406Sopenharmony_cisane_open (SANE_String_Const devnam, SANE_Handle *handle) 3260141cc406Sopenharmony_ci{ 3261141cc406Sopenharmony_ci SANE_Status status; 3262141cc406Sopenharmony_ci BH_Device *dev; 3263141cc406Sopenharmony_ci BH_Scanner *s; 3264141cc406Sopenharmony_ci DBG(3, "sane_open called\n"); 3265141cc406Sopenharmony_ci 3266141cc406Sopenharmony_ci if (devnam[0] != '\0') 3267141cc406Sopenharmony_ci { 3268141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 3269141cc406Sopenharmony_ci { 3270141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devnam) == 0) 3271141cc406Sopenharmony_ci break; 3272141cc406Sopenharmony_ci } 3273141cc406Sopenharmony_ci 3274141cc406Sopenharmony_ci if (!dev) 3275141cc406Sopenharmony_ci { 3276141cc406Sopenharmony_ci status = attach (devnam, &dev); 3277141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3278141cc406Sopenharmony_ci return status; 3279141cc406Sopenharmony_ci } 3280141cc406Sopenharmony_ci } 3281141cc406Sopenharmony_ci else 3282141cc406Sopenharmony_ci { 3283141cc406Sopenharmony_ci dev = first_dev; 3284141cc406Sopenharmony_ci } 3285141cc406Sopenharmony_ci 3286141cc406Sopenharmony_ci if (!dev) 3287141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3288141cc406Sopenharmony_ci 3289141cc406Sopenharmony_ci s = malloc (sizeof (*s)); 3290141cc406Sopenharmony_ci if (!s) 3291141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 3292141cc406Sopenharmony_ci memset (s, 0, sizeof (*s)); 3293141cc406Sopenharmony_ci 3294141cc406Sopenharmony_ci s->fd = -1; 3295141cc406Sopenharmony_ci s->hw = dev; 3296141cc406Sopenharmony_ci 3297141cc406Sopenharmony_ci s->bmu = BH_UNIT_POINT; 3298141cc406Sopenharmony_ci s->mud = 1; 3299141cc406Sopenharmony_ci 3300141cc406Sopenharmony_ci ScannerDump(s); 3301141cc406Sopenharmony_ci 3302141cc406Sopenharmony_ci init_options (s); 3303141cc406Sopenharmony_ci 3304141cc406Sopenharmony_ci s->next = first_handle; 3305141cc406Sopenharmony_ci first_handle = s; 3306141cc406Sopenharmony_ci 3307141cc406Sopenharmony_ci /* initialize our parameters */ 3308141cc406Sopenharmony_ci get_parameters(s, 0); 3309141cc406Sopenharmony_ci 3310141cc406Sopenharmony_ci *handle = s; 3311141cc406Sopenharmony_ci 3312141cc406Sopenharmony_ci#ifdef FAKE_INQUIRY 3313141cc406Sopenharmony_ci if (fake_inquiry) 3314141cc406Sopenharmony_ci { 3315141cc406Sopenharmony_ci DBG (1, "sane_open: faking open of %s\n", 3316141cc406Sopenharmony_ci s->hw->sane.name); 3317141cc406Sopenharmony_ci } 3318141cc406Sopenharmony_ci else 3319141cc406Sopenharmony_ci#endif 3320141cc406Sopenharmony_ci { 3321141cc406Sopenharmony_ci status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, s); 3322141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3323141cc406Sopenharmony_ci { 3324141cc406Sopenharmony_ci DBG (1, "sane_open: open of %s failed: %s\n", 3325141cc406Sopenharmony_ci s->hw->sane.name, sane_strstatus (status)); 3326141cc406Sopenharmony_ci return status; 3327141cc406Sopenharmony_ci } 3328141cc406Sopenharmony_ci } 3329141cc406Sopenharmony_ci 3330141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3331141cc406Sopenharmony_ci} 3332141cc406Sopenharmony_ci 3333141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 3334141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 3335141cc406Sopenharmony_ci{ 3336141cc406Sopenharmony_ci BH_Scanner *s = handle; 3337141cc406Sopenharmony_ci DBG(3, "sane_get_option_descriptor called (option:%d)\n", option); 3338141cc406Sopenharmony_ci 3339141cc406Sopenharmony_ci if ((unsigned) option >= NUM_OPTIONS) 3340141cc406Sopenharmony_ci return 0; 3341141cc406Sopenharmony_ci 3342141cc406Sopenharmony_ci return (s->opt + option); 3343141cc406Sopenharmony_ci} 3344141cc406Sopenharmony_ci 3345141cc406Sopenharmony_ciSANE_Status 3346141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, 3347141cc406Sopenharmony_ci void *val, SANE_Word *info) 3348141cc406Sopenharmony_ci{ 3349141cc406Sopenharmony_ci BH_Scanner *s = handle; 3350141cc406Sopenharmony_ci SANE_Status status; 3351141cc406Sopenharmony_ci SANE_Word cap; 3352141cc406Sopenharmony_ci SANE_String_Const name; 3353141cc406Sopenharmony_ci 3354141cc406Sopenharmony_ci DBG(3, "sane_control_option called\n"); 3355141cc406Sopenharmony_ci 3356141cc406Sopenharmony_ci name = s->opt[option].name ? s->opt[option].name : "(nil)"; 3357141cc406Sopenharmony_ci 3358141cc406Sopenharmony_ci if (info) 3359141cc406Sopenharmony_ci *info = 0; 3360141cc406Sopenharmony_ci 3361141cc406Sopenharmony_ci if (s->scanning && action == SANE_ACTION_SET_VALUE) 3362141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 3363141cc406Sopenharmony_ci if (option >= NUM_OPTIONS) 3364141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3365141cc406Sopenharmony_ci 3366141cc406Sopenharmony_ci cap = s->opt[option].cap; 3367141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (cap)) 3368141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3369141cc406Sopenharmony_ci 3370141cc406Sopenharmony_ci if (action == SANE_ACTION_GET_VALUE) 3371141cc406Sopenharmony_ci { 3372141cc406Sopenharmony_ci DBG(16, "sane_control_option: get_value %s [#%d]\n", name, option); 3373141cc406Sopenharmony_ci switch (option) 3374141cc406Sopenharmony_ci { 3375141cc406Sopenharmony_ci /* word options: */ 3376141cc406Sopenharmony_ci case OPT_RESOLUTION: 3377141cc406Sopenharmony_ci case OPT_TL_X: 3378141cc406Sopenharmony_ci case OPT_TL_Y: 3379141cc406Sopenharmony_ci case OPT_BR_X: 3380141cc406Sopenharmony_ci case OPT_BR_Y: 3381141cc406Sopenharmony_ci case OPT_TIMEOUT_ADF: 3382141cc406Sopenharmony_ci case OPT_TIMEOUT_MANUAL: 3383141cc406Sopenharmony_ci case OPT_ACE_FUNCTION: 3384141cc406Sopenharmony_ci case OPT_ACE_SENSITIVITY: 3385141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 3386141cc406Sopenharmony_ci case OPT_THRESHOLD: 3387141cc406Sopenharmony_ci case OPT_CONTRAST: 3388141cc406Sopenharmony_ci case OPT_ICON_WIDTH: 3389141cc406Sopenharmony_ci case OPT_ICON_LENGTH: 3390141cc406Sopenharmony_ci case OPT_BARCODE_SEARCH_COUNT: 3391141cc406Sopenharmony_ci case OPT_BARCODE_HMIN: 3392141cc406Sopenharmony_ci case OPT_BARCODE_SEARCH_TIMEOUT: 3393141cc406Sopenharmony_ci case OPT_BARCODE_RELMAX: 3394141cc406Sopenharmony_ci case OPT_BARCODE_BARMIN: 3395141cc406Sopenharmony_ci case OPT_BARCODE_BARMAX: 3396141cc406Sopenharmony_ci case OPT_BARCODE_CONTRAST: 3397141cc406Sopenharmony_ci case OPT_BARCODE_PATCHMODE: 3398141cc406Sopenharmony_ci case OPT_NUM_OPTS: 3399141cc406Sopenharmony_ci *(SANE_Word *) val = s->val[option].w; 3400141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3401141cc406Sopenharmony_ci 3402141cc406Sopenharmony_ci /* string options: */ 3403141cc406Sopenharmony_ci case OPT_INQUIRY: 3404141cc406Sopenharmony_ci case OPT_SCAN_SOURCE: 3405141cc406Sopenharmony_ci case OPT_SCAN_MODE: 3406141cc406Sopenharmony_ci case OPT_COMPRESSION: 3407141cc406Sopenharmony_ci case OPT_PAPER_SIZE: 3408141cc406Sopenharmony_ci case OPT_ROTATION: 3409141cc406Sopenharmony_ci case OPT_BARCODE_SEARCH_BAR: 3410141cc406Sopenharmony_ci case OPT_BARCODE_SEARCH_MODE: 3411141cc406Sopenharmony_ci case OPT_SECTION: 3412141cc406Sopenharmony_ci strcpy (val, s->val[option].s); 3413141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3414141cc406Sopenharmony_ci 3415141cc406Sopenharmony_ci /* boolean options: */ 3416141cc406Sopenharmony_ci case OPT_PREVIEW: 3417141cc406Sopenharmony_ci case OPT_AUTOBORDER: 3418141cc406Sopenharmony_ci case OPT_DESKEW: 3419141cc406Sopenharmony_ci case OPT_BATCH: 3420141cc406Sopenharmony_ci case OPT_CHECK_ADF: 3421141cc406Sopenharmony_ci case OPT_DUPLEX: 3422141cc406Sopenharmony_ci case OPT_CONTROL_PANEL: 3423141cc406Sopenharmony_ci case OPT_NEGATIVE: 3424141cc406Sopenharmony_ci *(SANE_Word *) val = s->val[option].w; 3425141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3426141cc406Sopenharmony_ci 3427141cc406Sopenharmony_ci default: 3428141cc406Sopenharmony_ci DBG(1, "sane_control_option:invalid option number %d\n", option); 3429141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3430141cc406Sopenharmony_ci } 3431141cc406Sopenharmony_ci } 3432141cc406Sopenharmony_ci else if (action == SANE_ACTION_SET_VALUE) 3433141cc406Sopenharmony_ci { 3434141cc406Sopenharmony_ci switch (s->opt[option].type) 3435141cc406Sopenharmony_ci { 3436141cc406Sopenharmony_ci case SANE_TYPE_BOOL: 3437141cc406Sopenharmony_ci case SANE_TYPE_INT: 3438141cc406Sopenharmony_ci DBG(16, "sane_control_option: set_value %s [#%d] to %d\n", 3439141cc406Sopenharmony_ci name, option, *(SANE_Word *) val); 3440141cc406Sopenharmony_ci break; 3441141cc406Sopenharmony_ci 3442141cc406Sopenharmony_ci case SANE_TYPE_FIXED: 3443141cc406Sopenharmony_ci DBG(16, "sane_control_option: set_value %s [#%d] to %f\n", 3444141cc406Sopenharmony_ci name, option, SANE_UNFIX(*(SANE_Word *) val)); 3445141cc406Sopenharmony_ci break; 3446141cc406Sopenharmony_ci 3447141cc406Sopenharmony_ci case SANE_TYPE_STRING: 3448141cc406Sopenharmony_ci DBG(16, "sane_control_option: set_value %s [#%d] to %s\n", 3449141cc406Sopenharmony_ci name, option, (char *) val); 3450141cc406Sopenharmony_ci break; 3451141cc406Sopenharmony_ci 3452141cc406Sopenharmony_ci default: 3453141cc406Sopenharmony_ci DBG(16, "sane_control_option: set_value %s [#%d]\n", 3454141cc406Sopenharmony_ci name, option); 3455141cc406Sopenharmony_ci } 3456141cc406Sopenharmony_ci 3457141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (cap)) 3458141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3459141cc406Sopenharmony_ci 3460141cc406Sopenharmony_ci status = sanei_constrain_value (s->opt + option, val, info); 3461141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3462141cc406Sopenharmony_ci return status; 3463141cc406Sopenharmony_ci 3464141cc406Sopenharmony_ci switch (option) 3465141cc406Sopenharmony_ci { 3466141cc406Sopenharmony_ci /* (mostly) side-effect-free word options: */ 3467141cc406Sopenharmony_ci case OPT_TL_X: 3468141cc406Sopenharmony_ci case OPT_TL_Y: 3469141cc406Sopenharmony_ci case OPT_BR_X: 3470141cc406Sopenharmony_ci case OPT_BR_Y: 3471141cc406Sopenharmony_ci /* make sure that paper-size is set to custom */ 3472141cc406Sopenharmony_ci if (s->val[option].w != *(SANE_Word *) val) 3473141cc406Sopenharmony_ci { 3474141cc406Sopenharmony_ci if (info) *info |= SANE_INFO_RELOAD_PARAMS; 3475141cc406Sopenharmony_ci 3476141cc406Sopenharmony_ci if (get_paper_id(_OPT_VAL_STRING(s, OPT_PAPER_SIZE)) != 0) 3477141cc406Sopenharmony_ci { 3478141cc406Sopenharmony_ci if (info) *info |= SANE_INFO_RELOAD_OPTIONS; 3479141cc406Sopenharmony_ci 3480141cc406Sopenharmony_ci /* set paper size to 'custom' */ 3481141cc406Sopenharmony_ci free (s->val[OPT_PAPER_SIZE].s); 3482141cc406Sopenharmony_ci s->val[OPT_PAPER_SIZE].s = strdup(paper_list[0]); 3483141cc406Sopenharmony_ci } 3484141cc406Sopenharmony_ci } 3485141cc406Sopenharmony_ci /* fall through */ 3486141cc406Sopenharmony_ci case OPT_RESOLUTION: 3487141cc406Sopenharmony_ci if (info && s->val[option].w != *(SANE_Word *) val) 3488141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 3489141cc406Sopenharmony_ci /* fall through */ 3490141cc406Sopenharmony_ci case OPT_TIMEOUT_ADF: 3491141cc406Sopenharmony_ci case OPT_TIMEOUT_MANUAL: 3492141cc406Sopenharmony_ci case OPT_ACE_FUNCTION: 3493141cc406Sopenharmony_ci case OPT_ACE_SENSITIVITY: 3494141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 3495141cc406Sopenharmony_ci case OPT_THRESHOLD: 3496141cc406Sopenharmony_ci case OPT_CONTRAST: 3497141cc406Sopenharmony_ci case OPT_ICON_WIDTH: 3498141cc406Sopenharmony_ci case OPT_ICON_LENGTH: 3499141cc406Sopenharmony_ci case OPT_BARCODE_SEARCH_COUNT: 3500141cc406Sopenharmony_ci case OPT_BARCODE_HMIN: 3501141cc406Sopenharmony_ci case OPT_BARCODE_SEARCH_TIMEOUT: 3502141cc406Sopenharmony_ci case OPT_BARCODE_RELMAX: 3503141cc406Sopenharmony_ci case OPT_BARCODE_BARMIN: 3504141cc406Sopenharmony_ci case OPT_BARCODE_BARMAX: 3505141cc406Sopenharmony_ci case OPT_BARCODE_CONTRAST: 3506141cc406Sopenharmony_ci case OPT_BARCODE_PATCHMODE: 3507141cc406Sopenharmony_ci case OPT_NUM_OPTS: 3508141cc406Sopenharmony_ci s->val[option].w = *(SANE_Word *) val; 3509141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3510141cc406Sopenharmony_ci 3511141cc406Sopenharmony_ci /* string options */ 3512141cc406Sopenharmony_ci case OPT_BARCODE_SEARCH_BAR: 3513141cc406Sopenharmony_ci /*!!! we're supporting only a single barcode type via the option */ 3514141cc406Sopenharmony_ci s->search_bars[0] = get_barcode_id(val); 3515141cc406Sopenharmony_ci /* fall through */ 3516141cc406Sopenharmony_ci case OPT_SCAN_SOURCE: 3517141cc406Sopenharmony_ci case OPT_COMPRESSION: 3518141cc406Sopenharmony_ci case OPT_ROTATION: 3519141cc406Sopenharmony_ci case OPT_BARCODE_SEARCH_MODE: 3520141cc406Sopenharmony_ci case OPT_SECTION: 3521141cc406Sopenharmony_ci if (s->val[option].s) 3522141cc406Sopenharmony_ci free (s->val[option].s); 3523141cc406Sopenharmony_ci s->val[option].s = strdup (val); 3524141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3525141cc406Sopenharmony_ci 3526141cc406Sopenharmony_ci /* boolean options: */ 3527141cc406Sopenharmony_ci case OPT_AUTOBORDER: 3528141cc406Sopenharmony_ci /*!!! autoborder true disables geometry controls 3529141cc406Sopenharmony_ci * and sets them to defaults? 3530141cc406Sopenharmony_ci */ 3531141cc406Sopenharmony_ci /* fall through */ 3532141cc406Sopenharmony_ci case OPT_PREVIEW: 3533141cc406Sopenharmony_ci case OPT_BATCH: 3534141cc406Sopenharmony_ci case OPT_DESKEW: 3535141cc406Sopenharmony_ci case OPT_CHECK_ADF: 3536141cc406Sopenharmony_ci case OPT_DUPLEX: 3537141cc406Sopenharmony_ci case OPT_NEGATIVE: 3538141cc406Sopenharmony_ci s->val[option].w = *(SANE_Word *) val; 3539141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3540141cc406Sopenharmony_ci 3541141cc406Sopenharmony_ci /* options with side effects */ 3542141cc406Sopenharmony_ci case OPT_CONTROL_PANEL: 3543141cc406Sopenharmony_ci /* a boolean option */ 3544141cc406Sopenharmony_ci /* control-panel true enables/disables some enhancement controls */ 3545141cc406Sopenharmony_ci if (s->val[option].w != *(SANE_Word *) val) 3546141cc406Sopenharmony_ci { 3547141cc406Sopenharmony_ci if (info) *info |= SANE_INFO_RELOAD_OPTIONS; 3548141cc406Sopenharmony_ci 3549141cc406Sopenharmony_ci s->val[option].w = *(SANE_Word *) val; 3550141cc406Sopenharmony_ci 3551141cc406Sopenharmony_ci if (*(SANE_Word *) val == SANE_TRUE) 3552141cc406Sopenharmony_ci { 3553141cc406Sopenharmony_ci if (s->hw->info.canACE == SANE_TRUE) 3554141cc406Sopenharmony_ci { 3555141cc406Sopenharmony_ci s->opt[OPT_ACE_FUNCTION].cap |= SANE_CAP_INACTIVE; 3556141cc406Sopenharmony_ci s->opt[OPT_ACE_SENSITIVITY].cap |= SANE_CAP_INACTIVE; 3557141cc406Sopenharmony_ci } 3558141cc406Sopenharmony_ci else 3559141cc406Sopenharmony_ci { 3560141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 3561141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 3562141cc406Sopenharmony_ci } 3563141cc406Sopenharmony_ci } 3564141cc406Sopenharmony_ci else 3565141cc406Sopenharmony_ci { 3566141cc406Sopenharmony_ci if (s->hw->info.canACE == SANE_TRUE) 3567141cc406Sopenharmony_ci { 3568141cc406Sopenharmony_ci s->opt[OPT_ACE_FUNCTION].cap &= ~SANE_CAP_INACTIVE; 3569141cc406Sopenharmony_ci s->opt[OPT_ACE_SENSITIVITY].cap &= ~SANE_CAP_INACTIVE; 3570141cc406Sopenharmony_ci } 3571141cc406Sopenharmony_ci else 3572141cc406Sopenharmony_ci { 3573141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; 3574141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; 3575141cc406Sopenharmony_ci } 3576141cc406Sopenharmony_ci } 3577141cc406Sopenharmony_ci } 3578141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3579141cc406Sopenharmony_ci 3580141cc406Sopenharmony_ci case OPT_SCAN_MODE: 3581141cc406Sopenharmony_ci /* a string option */ 3582141cc406Sopenharmony_ci /* scan mode != lineart disables compression, setting it to 3583141cc406Sopenharmony_ci * 'none' 3584141cc406Sopenharmony_ci */ 3585141cc406Sopenharmony_ci if (strcmp (s->val[option].s, (SANE_String) val)) 3586141cc406Sopenharmony_ci { 3587141cc406Sopenharmony_ci if (info) *info |= SANE_INFO_RELOAD_OPTIONS; 3588141cc406Sopenharmony_ci if (get_scan_mode_id((SANE_String) val) != 0) 3589141cc406Sopenharmony_ci { 3590141cc406Sopenharmony_ci /* scan mode is not lineart, disable compression 3591141cc406Sopenharmony_ci * and set compression to 'none' 3592141cc406Sopenharmony_ci */ 3593141cc406Sopenharmony_ci s->opt[OPT_COMPRESSION].cap |= SANE_CAP_INACTIVE; 3594141cc406Sopenharmony_ci if (s->val[OPT_COMPRESSION].s && 3595141cc406Sopenharmony_ci get_compression_id(s->val[OPT_COMPRESSION].s) != 0) 3596141cc406Sopenharmony_ci { 3597141cc406Sopenharmony_ci free (s->val[OPT_COMPRESSION].s); 3598141cc406Sopenharmony_ci s->val[OPT_COMPRESSION].s = strdup(compression_list[0]); 3599141cc406Sopenharmony_ci } 3600141cc406Sopenharmony_ci } 3601141cc406Sopenharmony_ci else 3602141cc406Sopenharmony_ci { 3603141cc406Sopenharmony_ci /* scan mode is lineart, enable compression */ 3604141cc406Sopenharmony_ci s->opt[OPT_COMPRESSION].cap &= ~SANE_CAP_INACTIVE; 3605141cc406Sopenharmony_ci } 3606141cc406Sopenharmony_ci free (s->val[option].s); 3607141cc406Sopenharmony_ci s->val[option].s = strdup (val); 3608141cc406Sopenharmony_ci } 3609141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3610141cc406Sopenharmony_ci 3611141cc406Sopenharmony_ci case OPT_PAPER_SIZE: 3612141cc406Sopenharmony_ci /* a string option */ 3613141cc406Sopenharmony_ci /* changes geometry options, therefore _RELOAD_PARAMS and _RELOAD_OPTIONS */ 3614141cc406Sopenharmony_ci if (strcmp (s->val[option].s, (SANE_String) val)) 3615141cc406Sopenharmony_ci { 3616141cc406Sopenharmony_ci SANE_Int paper_id = get_paper_id((SANE_String) val); 3617141cc406Sopenharmony_ci 3618141cc406Sopenharmony_ci /* paper_id 0 is a special case (custom) that 3619141cc406Sopenharmony_ci * disables the paper size control of geometry 3620141cc406Sopenharmony_ci */ 3621141cc406Sopenharmony_ci if (paper_id != 0) 3622141cc406Sopenharmony_ci { 3623141cc406Sopenharmony_ci double left, x_max, y_max, x, y; 3624141cc406Sopenharmony_ci 3625141cc406Sopenharmony_ci x_max = SANE_UNFIX(s->hw->info.x_range.max); 3626141cc406Sopenharmony_ci y_max = SANE_UNFIX(s->hw->info.y_range.max); 3627141cc406Sopenharmony_ci /* a dimension of 0.0 (or less) is replaced with the max value */ 3628141cc406Sopenharmony_ci x = (paper_sizes[paper_id].width <= 0.0) ? x_max : 3629141cc406Sopenharmony_ci paper_sizes[paper_id].width; 3630141cc406Sopenharmony_ci y = (paper_sizes[paper_id].length <= 0.0) ? y_max : 3631141cc406Sopenharmony_ci paper_sizes[paper_id].length; 3632141cc406Sopenharmony_ci 3633141cc406Sopenharmony_ci if (info) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 3634141cc406Sopenharmony_ci 3635141cc406Sopenharmony_ci /* set geometry options based on paper size */ 3636141cc406Sopenharmony_ci /* set geometry options based on paper size */ 3637141cc406Sopenharmony_ci if (s->hw->info.canADF) 3638141cc406Sopenharmony_ci { 3639141cc406Sopenharmony_ci /* when the feeder is used the paper is centered in the 3640141cc406Sopenharmony_ci * hopper; with the manual feed it is aligned left. 3641141cc406Sopenharmony_ci */ 3642141cc406Sopenharmony_ci left = (x_max - x) / 2.0; 3643141cc406Sopenharmony_ci if (left < 0.0) left = 0.0; 3644141cc406Sopenharmony_ci } 3645141cc406Sopenharmony_ci else 3646141cc406Sopenharmony_ci { 3647141cc406Sopenharmony_ci left = 0.0; 3648141cc406Sopenharmony_ci } 3649141cc406Sopenharmony_ci 3650141cc406Sopenharmony_ci s->val[OPT_TL_X].w = SANE_FIX(left); 3651141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = SANE_FIX(0.0); 3652141cc406Sopenharmony_ci s->val[OPT_BR_X].w = SANE_FIX(MIN(x + left, x_max)); 3653141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = SANE_FIX(MIN(y, y_max)); 3654141cc406Sopenharmony_ci } 3655141cc406Sopenharmony_ci free (s->val[option].s); 3656141cc406Sopenharmony_ci s->val[option].s = strdup (val); 3657141cc406Sopenharmony_ci } 3658141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3659141cc406Sopenharmony_ci 3660141cc406Sopenharmony_ci default: 3661141cc406Sopenharmony_ci DBG(1, "sane_control_option:invalid option number %d\n", option); 3662141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3663141cc406Sopenharmony_ci } 3664141cc406Sopenharmony_ci } 3665141cc406Sopenharmony_ci 3666141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3667141cc406Sopenharmony_ci} 3668141cc406Sopenharmony_ci 3669141cc406Sopenharmony_ciSANE_Status 3670141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters *params) 3671141cc406Sopenharmony_ci{ 3672141cc406Sopenharmony_ci BH_Scanner *s = handle; 3673141cc406Sopenharmony_ci SANE_Int status = SANE_STATUS_GOOD; 3674141cc406Sopenharmony_ci 3675141cc406Sopenharmony_ci DBG(3, "sane_get_parameters called\n"); 3676141cc406Sopenharmony_ci 3677141cc406Sopenharmony_ci if (params) 3678141cc406Sopenharmony_ci { 3679141cc406Sopenharmony_ci SANE_Int res; 3680141cc406Sopenharmony_ci 3681141cc406Sopenharmony_ci if (!s->scanning) 3682141cc406Sopenharmony_ci { 3683141cc406Sopenharmony_ci /* update our parameters ONLY if we're not scanning */ 3684141cc406Sopenharmony_ci status = get_parameters(s, 0); 3685141cc406Sopenharmony_ci } 3686141cc406Sopenharmony_ci 3687141cc406Sopenharmony_ci *params = s->params; 3688141cc406Sopenharmony_ci 3689141cc406Sopenharmony_ci res = _OPT_VAL_WORD(s, OPT_RESOLUTION); 3690141cc406Sopenharmony_ci 3691141cc406Sopenharmony_ci DBG (1, "get_parameters: format=%d, pixels/line=%d, bytes/line=%d, " 3692141cc406Sopenharmony_ci "lines=%d, dpi=%d\n", 3693141cc406Sopenharmony_ci (int) s->params.format, 3694141cc406Sopenharmony_ci s->params.pixels_per_line, 3695141cc406Sopenharmony_ci s->params.bytes_per_line, 3696141cc406Sopenharmony_ci s->params.lines, 3697141cc406Sopenharmony_ci res); 3698141cc406Sopenharmony_ci } 3699141cc406Sopenharmony_ci 3700141cc406Sopenharmony_ci return status; 3701141cc406Sopenharmony_ci} 3702141cc406Sopenharmony_ci 3703141cc406Sopenharmony_ciSANE_Status 3704141cc406Sopenharmony_cisane_start (SANE_Handle handle) 3705141cc406Sopenharmony_ci{ 3706141cc406Sopenharmony_ci BH_Scanner *s = handle; 3707141cc406Sopenharmony_ci SANE_Status status; 3708141cc406Sopenharmony_ci 3709141cc406Sopenharmony_ci DBG(3, "sane_start called\n"); 3710141cc406Sopenharmony_ci s->cancelled = SANE_FALSE; 3711141cc406Sopenharmony_ci 3712141cc406Sopenharmony_ci if (s->scanning == SANE_FALSE) 3713141cc406Sopenharmony_ci { 3714141cc406Sopenharmony_ci /* get preliminary parameters */ 3715141cc406Sopenharmony_ci status = get_parameters (s, 0); 3716141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3717141cc406Sopenharmony_ci { 3718141cc406Sopenharmony_ci DBG (1, "sane_start: get_parameters failed: %s\n", 3719141cc406Sopenharmony_ci sane_strstatus (status)); 3720141cc406Sopenharmony_ci return status; 3721141cc406Sopenharmony_ci } 3722141cc406Sopenharmony_ci 3723141cc406Sopenharmony_ci /* Do the setup once per 'batch'. The SANE standard requires the 3724141cc406Sopenharmony_ci * frontend to call sane_cancel once all desired frames have been 3725141cc406Sopenharmony_ci * acquired. That is when scanning is set back to SANE_FALSE and 3726141cc406Sopenharmony_ci * the 'batch' is considered done. 3727141cc406Sopenharmony_ci */ 3728141cc406Sopenharmony_ci status = start_setup (s); 3729141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3730141cc406Sopenharmony_ci { 3731141cc406Sopenharmony_ci DBG (1, "sane_start: start_setup failed: %s\n", 3732141cc406Sopenharmony_ci sane_strstatus (status)); 3733141cc406Sopenharmony_ci return status; 3734141cc406Sopenharmony_ci } 3735141cc406Sopenharmony_ci } 3736141cc406Sopenharmony_ci 3737141cc406Sopenharmony_ci status = start_scan (s); 3738141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3739141cc406Sopenharmony_ci { 3740141cc406Sopenharmony_ci DBG (1, "sane_start: start_scan failed: %s\n", 3741141cc406Sopenharmony_ci sane_strstatus (status)); 3742141cc406Sopenharmony_ci return status; 3743141cc406Sopenharmony_ci } 3744141cc406Sopenharmony_ci 3745141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3746141cc406Sopenharmony_ci} 3747141cc406Sopenharmony_ci 3748141cc406Sopenharmony_ciSANE_Status 3749141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *len) 3750141cc406Sopenharmony_ci{ 3751141cc406Sopenharmony_ci BH_Scanner *s = handle; 3752141cc406Sopenharmony_ci SANE_Status status; 3753141cc406Sopenharmony_ci size_t nread; 3754141cc406Sopenharmony_ci 3755141cc406Sopenharmony_ci DBG(3, "sane_read called\n"); 3756141cc406Sopenharmony_ci 3757141cc406Sopenharmony_ci *len = 0; 3758141cc406Sopenharmony_ci 3759141cc406Sopenharmony_ci if (s->cancelled) { 3760141cc406Sopenharmony_ci DBG (3, "sane_read: cancelled!\n"); 3761141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 3762141cc406Sopenharmony_ci } 3763141cc406Sopenharmony_ci 3764141cc406Sopenharmony_ci if (!s->scanning) { 3765141cc406Sopenharmony_ci DBG (3, "sane_read: scanning is false!\n"); 3766141cc406Sopenharmony_ci sane_cancel(s); 3767141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 3768141cc406Sopenharmony_ci } 3769141cc406Sopenharmony_ci 3770141cc406Sopenharmony_ci nread = maxlen; 3771141cc406Sopenharmony_ci 3772141cc406Sopenharmony_ci DBG (3, "sane_read: request %lu bytes\n", (u_long) nread); 3773141cc406Sopenharmony_ci /* set InvalidBytes to 0 before read; sense_handler will set it 3774141cc406Sopenharmony_ci * to non-zero if we do the last partial read. 3775141cc406Sopenharmony_ci */ 3776141cc406Sopenharmony_ci s->InvalidBytes = 0; 3777141cc406Sopenharmony_ci status = read_data (s, buf, &nread); 3778141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3779141cc406Sopenharmony_ci { 3780141cc406Sopenharmony_ci DBG (1, "sane_read: read_data failed %s\n", 3781141cc406Sopenharmony_ci sane_strstatus(status)); 3782141cc406Sopenharmony_ci sane_cancel (s); 3783141cc406Sopenharmony_ci return status; 3784141cc406Sopenharmony_ci } 3785141cc406Sopenharmony_ci nread = maxlen - s->InvalidBytes; 3786141cc406Sopenharmony_ci DBG (3, "sane_read: got %lu bytes\n", (u_long) nread); 3787141cc406Sopenharmony_ci *len = nread; 3788141cc406Sopenharmony_ci 3789141cc406Sopenharmony_ci return (maxlen != 0 && nread == 0) ? SANE_STATUS_EOF : SANE_STATUS_GOOD; 3790141cc406Sopenharmony_ci} 3791141cc406Sopenharmony_ci 3792141cc406Sopenharmony_ciSANE_Status 3793141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 3794141cc406Sopenharmony_ci{ 3795141cc406Sopenharmony_ci#ifdef NONBLOCKSUPPORTED 3796141cc406Sopenharmony_ci BH_Scanner *s = handle; 3797141cc406Sopenharmony_ci#endif 3798141cc406Sopenharmony_ci DBG(3, "sane_set_io_mode called: non_blocking=%d\n", non_blocking); 3799141cc406Sopenharmony_ci 3800141cc406Sopenharmony_ci#ifdef NONBLOCKSUPPORTED 3801141cc406Sopenharmony_ci if (s->fd < 0) 3802141cc406Sopenharmony_ci { 3803141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3804141cc406Sopenharmony_ci } 3805141cc406Sopenharmony_ci 3806141cc406Sopenharmony_ci if (fcntl (s->fd, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) 3807141cc406Sopenharmony_ci { 3808141cc406Sopenharmony_ci DBG(1, "sane_set_io_mode: error setting io mode\n"); 3809141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 3810141cc406Sopenharmony_ci } 3811141cc406Sopenharmony_ci 3812141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3813141cc406Sopenharmony_ci#else 3814141cc406Sopenharmony_ci (void) handle; /* get rid of compiler warning */ 3815141cc406Sopenharmony_ci return (non_blocking == 1) ? SANE_STATUS_UNSUPPORTED : SANE_STATUS_GOOD; 3816141cc406Sopenharmony_ci#endif 3817141cc406Sopenharmony_ci} 3818141cc406Sopenharmony_ci 3819141cc406Sopenharmony_ciSANE_Status 3820141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int *fd) 3821141cc406Sopenharmony_ci{ 3822141cc406Sopenharmony_ci#ifdef NONBLOCKSUPPORTED 3823141cc406Sopenharmony_ci BH_Scanner *s = handle; 3824141cc406Sopenharmony_ci#endif 3825141cc406Sopenharmony_ci DBG(3, "sane_get_select_fd called\n"); 3826141cc406Sopenharmony_ci 3827141cc406Sopenharmony_ci#ifdef NONBLOCKSUPPORTED 3828141cc406Sopenharmony_ci if (s->fd < 0) 3829141cc406Sopenharmony_ci { 3830141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3831141cc406Sopenharmony_ci } 3832141cc406Sopenharmony_ci *fd = s->fd; 3833141cc406Sopenharmony_ci 3834141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3835141cc406Sopenharmony_ci#else 3836141cc406Sopenharmony_ci (void) handle; (void) fd; /* get rid of compiler warning */ 3837141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 3838141cc406Sopenharmony_ci#endif 3839141cc406Sopenharmony_ci} 3840141cc406Sopenharmony_ci 3841141cc406Sopenharmony_civoid 3842141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 3843141cc406Sopenharmony_ci{ 3844141cc406Sopenharmony_ci BH_Scanner *s = (BH_Scanner *) handle; 3845141cc406Sopenharmony_ci DBG(3, "sane_cancel called\n"); 3846141cc406Sopenharmony_ci if (s->scanning) 3847141cc406Sopenharmony_ci { 3848141cc406Sopenharmony_ci /* if batchmode is enabled, then call set_window to 3849141cc406Sopenharmony_ci * abort the batch 3850141cc406Sopenharmony_ci */ 3851141cc406Sopenharmony_ci if (_OPT_VAL_WORD(s, OPT_BATCH) == SANE_TRUE) 3852141cc406Sopenharmony_ci { 3853141cc406Sopenharmony_ci DBG(5, "sane_cancel: calling set_window to abort batch\n"); 3854141cc406Sopenharmony_ci set_window(s, BH_BATCH_ABORT); 3855141cc406Sopenharmony_ci } 3856141cc406Sopenharmony_ci } 3857141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 3858141cc406Sopenharmony_ci s->cancelled = SANE_TRUE; 3859141cc406Sopenharmony_ci} 3860141cc406Sopenharmony_ci 3861141cc406Sopenharmony_civoid 3862141cc406Sopenharmony_cisane_close (SANE_Handle handle) 3863141cc406Sopenharmony_ci{ 3864141cc406Sopenharmony_ci BH_Scanner *s = (BH_Scanner *) handle; 3865141cc406Sopenharmony_ci DBG(3, "sane_close called\n"); 3866141cc406Sopenharmony_ci 3867141cc406Sopenharmony_ci if (s->fd != -1) 3868141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 3869141cc406Sopenharmony_ci s->fd = -1; 3870141cc406Sopenharmony_ci free (s); 3871141cc406Sopenharmony_ci} 3872141cc406Sopenharmony_ci 3873141cc406Sopenharmony_civoid 3874141cc406Sopenharmony_cisane_exit (void) 3875141cc406Sopenharmony_ci{ 3876141cc406Sopenharmony_ci BH_Device *dev, *next; 3877141cc406Sopenharmony_ci DBG(3, "sane_exit called\n"); 3878141cc406Sopenharmony_ci 3879141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = next) 3880141cc406Sopenharmony_ci { 3881141cc406Sopenharmony_ci next = dev->next; 3882141cc406Sopenharmony_ci free (dev); 3883141cc406Sopenharmony_ci } 3884141cc406Sopenharmony_ci 3885141cc406Sopenharmony_ci if (devlist) 3886141cc406Sopenharmony_ci free (devlist); 3887141cc406Sopenharmony_ci} 3888