1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci Copyright (C) 2001, Marcio Luis Teixeira 4141cc406Sopenharmony_ci 5141cc406Sopenharmony_ci Parts copyright (C) 1996, 1997 Andreas Beck 6141cc406Sopenharmony_ci Parts copyright (C) 2000, 2001 Michael Herder <crapsite@gmx.net> 7141cc406Sopenharmony_ci Parts copyright (C) 2001 Henning Meier-Geinitz <henning@meier-geinitz.de> 8141cc406Sopenharmony_ci Parts copyright (C) 2006 Patrick Lessard 9141cc406Sopenharmony_ci 10141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 11141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 12141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 13141cc406Sopenharmony_ci License, or (at your option) any later version. 14141cc406Sopenharmony_ci 15141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 16141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 17141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18141cc406Sopenharmony_ci General Public License for more details. 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 21141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 22141cc406Sopenharmony_ci 23141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 24141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 25141cc406Sopenharmony_ci 26141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 27141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 28141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 29141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 30141cc406Sopenharmony_ci account of linking the SANE library code into it. 31141cc406Sopenharmony_ci 32141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 33141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 34141cc406Sopenharmony_ci License. 35141cc406Sopenharmony_ci 36141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 37141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 38141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 39141cc406Sopenharmony_ci 40141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 41141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 42141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. */ 43141cc406Sopenharmony_ci 44141cc406Sopenharmony_ci#define BUILD 2 45141cc406Sopenharmony_ci#define MM_IN_INCH 25.4 46141cc406Sopenharmony_ci 47141cc406Sopenharmony_ci#include "../include/sane/config.h" 48141cc406Sopenharmony_ci 49141cc406Sopenharmony_ci#include <stdlib.h> 50141cc406Sopenharmony_ci#include <string.h> 51141cc406Sopenharmony_ci#include <stdio.h> 52141cc406Sopenharmony_ci#include <unistd.h> 53141cc406Sopenharmony_ci#include <fcntl.h> 54141cc406Sopenharmony_ci#include <sys/ioctl.h> 55141cc406Sopenharmony_ci 56141cc406Sopenharmony_ci#include "../include/sane/sane.h" 57141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 58141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 59141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 60141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h" 61141cc406Sopenharmony_ci#include "../include/sane/sanei_pv8630.h" 62141cc406Sopenharmony_ci 63141cc406Sopenharmony_ci#define BACKEND_NAME umax1220u 64141cc406Sopenharmony_ci#define UMAX_CONFIG_FILE "umax1220u.conf" 65141cc406Sopenharmony_ci 66141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 67141cc406Sopenharmony_ci 68141cc406Sopenharmony_ci#include "umax1220u-common.c" 69141cc406Sopenharmony_ci 70141cc406Sopenharmony_citypedef struct Umax_Device 71141cc406Sopenharmony_ci{ 72141cc406Sopenharmony_ci struct Umax_Device *next; 73141cc406Sopenharmony_ci SANE_String name; 74141cc406Sopenharmony_ci SANE_Device sane; 75141cc406Sopenharmony_ci} 76141cc406Sopenharmony_ciUmax_Device; 77141cc406Sopenharmony_ci 78141cc406Sopenharmony_citypedef struct Umax_Scanner 79141cc406Sopenharmony_ci{ 80141cc406Sopenharmony_ci struct Umax_Scanner *next; 81141cc406Sopenharmony_ci Umax_Device *device; 82141cc406Sopenharmony_ci UMAX_Handle scan; 83141cc406Sopenharmony_ci} 84141cc406Sopenharmony_ciUmax_Scanner; 85141cc406Sopenharmony_ci 86141cc406Sopenharmony_cistatic int num_devices = 0; 87141cc406Sopenharmony_cistatic const SANE_Device **devlist = NULL; 88141cc406Sopenharmony_cistatic Umax_Device *first_dev = NULL; 89141cc406Sopenharmony_cistatic Umax_Scanner *first_handle = NULL; 90141cc406Sopenharmony_ci 91141cc406Sopenharmony_cistatic SANE_Parameters parms = { 92141cc406Sopenharmony_ci SANE_FRAME_RGB, 93141cc406Sopenharmony_ci 0, 94141cc406Sopenharmony_ci 0, /* Number of bytes returned per scan line: */ 95141cc406Sopenharmony_ci 0, /* Number of pixels per scan line. */ 96141cc406Sopenharmony_ci 0, /* Number of lines for the current scan. */ 97141cc406Sopenharmony_ci 8 /* Number of bits per sample. */ 98141cc406Sopenharmony_ci}; 99141cc406Sopenharmony_ci 100141cc406Sopenharmony_cistruct _SANE_Option 101141cc406Sopenharmony_ci{ 102141cc406Sopenharmony_ci SANE_Option_Descriptor *descriptor; 103141cc406Sopenharmony_ci SANE_Status (*callback) (struct _SANE_Option * option, SANE_Handle handle, 104141cc406Sopenharmony_ci SANE_Action action, void *value, 105141cc406Sopenharmony_ci SANE_Int * info); 106141cc406Sopenharmony_ci}; 107141cc406Sopenharmony_ci 108141cc406Sopenharmony_citypedef struct _SANE_Option SANE_Option; 109141cc406Sopenharmony_ci 110141cc406Sopenharmony_cistatic SANE_Word getNumberOfOptions (void); /* Forward declaration */ 111141cc406Sopenharmony_ci 112141cc406Sopenharmony_ci/* 113141cc406Sopenharmony_ciThis read-only option returns the number of options available for 114141cc406Sopenharmony_cithe device. It should be the first option in the options array 115141cc406Sopenharmony_cideclared below. 116141cc406Sopenharmony_ci*/ 117141cc406Sopenharmony_ci 118141cc406Sopenharmony_cistatic SANE_Option_Descriptor optionNumOptionsDescriptor = { 119141cc406Sopenharmony_ci SANE_NAME_NUM_OPTIONS, 120141cc406Sopenharmony_ci SANE_TITLE_NUM_OPTIONS, 121141cc406Sopenharmony_ci SANE_DESC_NUM_OPTIONS, 122141cc406Sopenharmony_ci SANE_TYPE_INT, 123141cc406Sopenharmony_ci SANE_UNIT_NONE, 124141cc406Sopenharmony_ci sizeof (SANE_Word), 125141cc406Sopenharmony_ci SANE_CAP_SOFT_DETECT, 126141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 127141cc406Sopenharmony_ci {NULL} 128141cc406Sopenharmony_ci}; 129141cc406Sopenharmony_ci 130141cc406Sopenharmony_cistatic SANE_Status 131141cc406Sopenharmony_cioptionNumOptionsCallback (SANE_Option * option, SANE_Handle handle, 132141cc406Sopenharmony_ci SANE_Action action, void *value, SANE_Int * info) 133141cc406Sopenharmony_ci{ 134141cc406Sopenharmony_ci (void) option; 135141cc406Sopenharmony_ci (void) handle; 136141cc406Sopenharmony_ci (void) info; /* Eliminate warning about unused parameters */ 137141cc406Sopenharmony_ci 138141cc406Sopenharmony_ci if (action != SANE_ACTION_GET_VALUE) 139141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 140141cc406Sopenharmony_ci *(SANE_Word *) value = getNumberOfOptions (); 141141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 142141cc406Sopenharmony_ci} 143141cc406Sopenharmony_ci 144141cc406Sopenharmony_ci/* 145141cc406Sopenharmony_ciThis option lets the user select the scan resolution. The UMAX 146141cc406Sopenharmony_ciscanner only supports the following resolutions: 75, 150, 300 and 147141cc406Sopenharmony_ci600 148141cc406Sopenharmony_ci*/ 149141cc406Sopenharmony_ci 150141cc406Sopenharmony_cistatic const SANE_Word optionResolutionList[] = { 151141cc406Sopenharmony_ci 4, /* Number of elements */ 152141cc406Sopenharmony_ci 75, 150, 300, 600 /* Resolution list */ 153141cc406Sopenharmony_ci}; 154141cc406Sopenharmony_ci 155141cc406Sopenharmony_cistatic SANE_Option_Descriptor optionResolutionDescriptor = { 156141cc406Sopenharmony_ci SANE_NAME_SCAN_RESOLUTION, 157141cc406Sopenharmony_ci SANE_TITLE_SCAN_RESOLUTION, 158141cc406Sopenharmony_ci SANE_DESC_SCAN_RESOLUTION, 159141cc406Sopenharmony_ci SANE_TYPE_INT, 160141cc406Sopenharmony_ci SANE_UNIT_DPI, 161141cc406Sopenharmony_ci sizeof (SANE_Word), 162141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC, 163141cc406Sopenharmony_ci SANE_CONSTRAINT_WORD_LIST, 164141cc406Sopenharmony_ci {(const SANE_String_Const *) optionResolutionList} 165141cc406Sopenharmony_ci}; 166141cc406Sopenharmony_ci 167141cc406Sopenharmony_cistatic SANE_Word optionResolutionValue = 75; 168141cc406Sopenharmony_ci 169141cc406Sopenharmony_cistatic SANE_Status 170141cc406Sopenharmony_cioptionResolutionCallback (SANE_Option * option, SANE_Handle handle, 171141cc406Sopenharmony_ci SANE_Action action, void *value, SANE_Int * info) 172141cc406Sopenharmony_ci{ 173141cc406Sopenharmony_ci SANE_Status status; 174141cc406Sopenharmony_ci SANE_Word autoValue = 75; 175141cc406Sopenharmony_ci 176141cc406Sopenharmony_ci (void) handle; /* Eliminate warning about unused parameters */ 177141cc406Sopenharmony_ci 178141cc406Sopenharmony_ci switch (action) 179141cc406Sopenharmony_ci { 180141cc406Sopenharmony_ci case SANE_ACTION_SET_AUTO: 181141cc406Sopenharmony_ci status = 182141cc406Sopenharmony_ci sanei_constrain_value (option->descriptor, (void *) &autoValue, info); 183141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 184141cc406Sopenharmony_ci return status; 185141cc406Sopenharmony_ci optionResolutionValue = autoValue; 186141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 187141cc406Sopenharmony_ci break; 188141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 189141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 190141cc406Sopenharmony_ci optionResolutionValue = *(SANE_Word *) value; 191141cc406Sopenharmony_ci break; 192141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 193141cc406Sopenharmony_ci *(SANE_Word *) value = optionResolutionValue; 194141cc406Sopenharmony_ci break; 195141cc406Sopenharmony_ci } 196141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 197141cc406Sopenharmony_ci} 198141cc406Sopenharmony_ci 199141cc406Sopenharmony_ci/* 200141cc406Sopenharmony_ciThis option lets the user select a gray scale scan 201141cc406Sopenharmony_ci*/ 202141cc406Sopenharmony_cistatic SANE_Word optionGrayscaleValue = SANE_FALSE; 203141cc406Sopenharmony_ci 204141cc406Sopenharmony_cistatic SANE_Option_Descriptor optionGrayscaleDescriptor = { 205141cc406Sopenharmony_ci "gray", 206141cc406Sopenharmony_ci SANE_I18N ("Grayscale scan"), 207141cc406Sopenharmony_ci SANE_I18N ("Do a grayscale rather than color scan"), 208141cc406Sopenharmony_ci SANE_TYPE_BOOL, 209141cc406Sopenharmony_ci SANE_UNIT_NONE, 210141cc406Sopenharmony_ci sizeof (SANE_Word), 211141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, 212141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 213141cc406Sopenharmony_ci {NULL} 214141cc406Sopenharmony_ci}; 215141cc406Sopenharmony_ci 216141cc406Sopenharmony_cistatic SANE_Status 217141cc406Sopenharmony_cioptionGrayscaleCallback (SANE_Option * option, SANE_Handle handle, 218141cc406Sopenharmony_ci SANE_Action action, void *value, SANE_Int * info) 219141cc406Sopenharmony_ci{ 220141cc406Sopenharmony_ci (void) handle; 221141cc406Sopenharmony_ci (void) option; /* Eliminate warning about unused parameters */ 222141cc406Sopenharmony_ci 223141cc406Sopenharmony_ci switch (action) 224141cc406Sopenharmony_ci { 225141cc406Sopenharmony_ci case SANE_ACTION_SET_AUTO: 226141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 227141cc406Sopenharmony_ci break; 228141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 229141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 230141cc406Sopenharmony_ci optionGrayscaleValue = *(SANE_Bool *) value; 231141cc406Sopenharmony_ci break; 232141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 233141cc406Sopenharmony_ci *(SANE_Word *) value = optionGrayscaleValue; 234141cc406Sopenharmony_ci break; 235141cc406Sopenharmony_ci } 236141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 237141cc406Sopenharmony_ci} 238141cc406Sopenharmony_ci 239141cc406Sopenharmony_ci/* 240141cc406Sopenharmony_ciThis option is a button that allows the user to turn off the 241141cc406Sopenharmony_cilamp in the UMAX scanner 242141cc406Sopenharmony_ci*/ 243141cc406Sopenharmony_ci 244141cc406Sopenharmony_cistatic SANE_Option_Descriptor optionLampOffDescriptor = { 245141cc406Sopenharmony_ci "lamp-off", 246141cc406Sopenharmony_ci SANE_I18N ("Lamp off"), 247141cc406Sopenharmony_ci SANE_I18N ("Turn off scanner lamp"), 248141cc406Sopenharmony_ci SANE_TYPE_BUTTON, 249141cc406Sopenharmony_ci SANE_UNIT_NONE, 250141cc406Sopenharmony_ci 0, 251141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT, 252141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 253141cc406Sopenharmony_ci {NULL} 254141cc406Sopenharmony_ci}; 255141cc406Sopenharmony_ci 256141cc406Sopenharmony_cistatic SANE_Status 257141cc406Sopenharmony_cioptionLampOffCallback (SANE_Option * option, SANE_Handle handle, 258141cc406Sopenharmony_ci SANE_Action action, void *value, SANE_Int * info) 259141cc406Sopenharmony_ci{ 260141cc406Sopenharmony_ci Umax_Scanner *scanner = handle; 261141cc406Sopenharmony_ci SANE_Status res = SANE_STATUS_GOOD; 262141cc406Sopenharmony_ci 263141cc406Sopenharmony_ci /* Eliminate warnings about unused parameters */ 264141cc406Sopenharmony_ci (void) option; 265141cc406Sopenharmony_ci (void) handle; 266141cc406Sopenharmony_ci (void) info; 267141cc406Sopenharmony_ci (void) value; 268141cc406Sopenharmony_ci 269141cc406Sopenharmony_ci if (action != SANE_ACTION_SET_VALUE) 270141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 271141cc406Sopenharmony_ci 272141cc406Sopenharmony_ci res = UMAX_set_lamp_state (&scanner->scan, UMAX_LAMP_OFF); 273141cc406Sopenharmony_ci 274141cc406Sopenharmony_ci return res; 275141cc406Sopenharmony_ci} 276141cc406Sopenharmony_ci 277141cc406Sopenharmony_cistatic const SANE_Range widthRange = { 278141cc406Sopenharmony_ci 0, /* minimum */ 279141cc406Sopenharmony_ci SANE_FIX (UMAX_MAX_WIDTH * MM_IN_INCH / 600), /* maximum */ 280141cc406Sopenharmony_ci 0 /* quantization */ 281141cc406Sopenharmony_ci}; 282141cc406Sopenharmony_ci 283141cc406Sopenharmony_cistatic const SANE_Range heightRange = { 284141cc406Sopenharmony_ci 0, /* minimum */ 285141cc406Sopenharmony_ci SANE_FIX (UMAX_MAX_HEIGHT * MM_IN_INCH / 600), /* maximum */ 286141cc406Sopenharmony_ci 0 /* quantization */ 287141cc406Sopenharmony_ci}; 288141cc406Sopenharmony_ci 289141cc406Sopenharmony_ci/* 290141cc406Sopenharmony_ciThis option controls the top-left-x corner of the scan 291141cc406Sopenharmony_ci*/ 292141cc406Sopenharmony_ci 293141cc406Sopenharmony_cistatic SANE_Fixed optionTopLeftXValue = 0; 294141cc406Sopenharmony_ci 295141cc406Sopenharmony_cistatic SANE_Option_Descriptor optionTopLeftXDescriptor = { 296141cc406Sopenharmony_ci SANE_NAME_SCAN_TL_X, 297141cc406Sopenharmony_ci SANE_TITLE_SCAN_TL_X, 298141cc406Sopenharmony_ci SANE_DESC_SCAN_TL_X, 299141cc406Sopenharmony_ci SANE_TYPE_FIXED, 300141cc406Sopenharmony_ci SANE_UNIT_MM, 301141cc406Sopenharmony_ci sizeof (SANE_Fixed), 302141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, 303141cc406Sopenharmony_ci SANE_CONSTRAINT_RANGE, 304141cc406Sopenharmony_ci {(const SANE_String_Const *) & widthRange} 305141cc406Sopenharmony_ci}; 306141cc406Sopenharmony_ci 307141cc406Sopenharmony_cistatic SANE_Status 308141cc406Sopenharmony_cioptionTopLeftXCallback (SANE_Option * option, SANE_Handle handle, 309141cc406Sopenharmony_ci SANE_Action action, void *value, SANE_Int * info) 310141cc406Sopenharmony_ci{ 311141cc406Sopenharmony_ci (void) option; 312141cc406Sopenharmony_ci (void) handle; 313141cc406Sopenharmony_ci (void) value; /* Eliminate warning about unused parameters */ 314141cc406Sopenharmony_ci 315141cc406Sopenharmony_ci switch (action) 316141cc406Sopenharmony_ci { 317141cc406Sopenharmony_ci case SANE_ACTION_SET_AUTO: 318141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 319141cc406Sopenharmony_ci break; 320141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 321141cc406Sopenharmony_ci optionTopLeftXValue = *(SANE_Fixed *) value; 322141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 323141cc406Sopenharmony_ci break; 324141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 325141cc406Sopenharmony_ci *(SANE_Fixed *) value = optionTopLeftXValue; 326141cc406Sopenharmony_ci break; 327141cc406Sopenharmony_ci } 328141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 329141cc406Sopenharmony_ci} 330141cc406Sopenharmony_ci 331141cc406Sopenharmony_ci/* 332141cc406Sopenharmony_ciThis option controls the top-left-y corner of the scan 333141cc406Sopenharmony_ci*/ 334141cc406Sopenharmony_ci 335141cc406Sopenharmony_cistatic SANE_Fixed optionTopLeftYValue = 0; 336141cc406Sopenharmony_ci 337141cc406Sopenharmony_cistatic SANE_Option_Descriptor optionTopLeftYDescriptor = { 338141cc406Sopenharmony_ci SANE_NAME_SCAN_TL_Y, 339141cc406Sopenharmony_ci SANE_TITLE_SCAN_TL_Y, 340141cc406Sopenharmony_ci SANE_DESC_SCAN_TL_Y, 341141cc406Sopenharmony_ci SANE_TYPE_FIXED, 342141cc406Sopenharmony_ci SANE_UNIT_MM, 343141cc406Sopenharmony_ci sizeof (SANE_Fixed), 344141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, 345141cc406Sopenharmony_ci SANE_CONSTRAINT_RANGE, 346141cc406Sopenharmony_ci {(const SANE_String_Const *) & heightRange} 347141cc406Sopenharmony_ci}; 348141cc406Sopenharmony_ci 349141cc406Sopenharmony_cistatic SANE_Status 350141cc406Sopenharmony_cioptionTopLeftYCallback (SANE_Option * option, SANE_Handle handle, 351141cc406Sopenharmony_ci SANE_Action action, void *value, SANE_Int * info) 352141cc406Sopenharmony_ci{ 353141cc406Sopenharmony_ci /* Eliminate warnings about unused parameters */ 354141cc406Sopenharmony_ci (void) option; 355141cc406Sopenharmony_ci (void) handle; 356141cc406Sopenharmony_ci 357141cc406Sopenharmony_ci switch (action) 358141cc406Sopenharmony_ci { 359141cc406Sopenharmony_ci case SANE_ACTION_SET_AUTO: 360141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 361141cc406Sopenharmony_ci break; 362141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 363141cc406Sopenharmony_ci optionTopLeftYValue = *(SANE_Fixed *) value; 364141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 365141cc406Sopenharmony_ci break; 366141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 367141cc406Sopenharmony_ci *(SANE_Fixed *) value = optionTopLeftYValue; 368141cc406Sopenharmony_ci break; 369141cc406Sopenharmony_ci } 370141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 371141cc406Sopenharmony_ci} 372141cc406Sopenharmony_ci 373141cc406Sopenharmony_ci/* 374141cc406Sopenharmony_ciThis option controls the bot-right-x corner of the scan 375141cc406Sopenharmony_ci*/ 376141cc406Sopenharmony_ci 377141cc406Sopenharmony_cistatic SANE_Fixed optionBotRightXValue 378141cc406Sopenharmony_ci = SANE_FIX (UMAX_MAX_WIDTH * MM_IN_INCH / 600); 379141cc406Sopenharmony_ci 380141cc406Sopenharmony_cistatic SANE_Option_Descriptor optionBotRightXDescriptor = { 381141cc406Sopenharmony_ci SANE_NAME_SCAN_BR_X, 382141cc406Sopenharmony_ci SANE_TITLE_SCAN_BR_X, 383141cc406Sopenharmony_ci SANE_DESC_SCAN_BR_X, 384141cc406Sopenharmony_ci SANE_TYPE_FIXED, 385141cc406Sopenharmony_ci SANE_UNIT_MM, 386141cc406Sopenharmony_ci sizeof (SANE_Fixed), 387141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, 388141cc406Sopenharmony_ci SANE_CONSTRAINT_RANGE, 389141cc406Sopenharmony_ci {(const SANE_String_Const *) & widthRange} 390141cc406Sopenharmony_ci}; 391141cc406Sopenharmony_ci 392141cc406Sopenharmony_cistatic SANE_Status 393141cc406Sopenharmony_cioptionBotRightXCallback (SANE_Option * option, SANE_Handle handle, 394141cc406Sopenharmony_ci SANE_Action action, void *value, SANE_Int * info) 395141cc406Sopenharmony_ci{ 396141cc406Sopenharmony_ci /* Eliminate warnings about unused parameters */ 397141cc406Sopenharmony_ci (void) option; 398141cc406Sopenharmony_ci (void) handle; 399141cc406Sopenharmony_ci 400141cc406Sopenharmony_ci switch (action) 401141cc406Sopenharmony_ci { 402141cc406Sopenharmony_ci case SANE_ACTION_SET_AUTO: 403141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 404141cc406Sopenharmony_ci break; 405141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 406141cc406Sopenharmony_ci optionBotRightXValue = *(SANE_Fixed *) value; 407141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 408141cc406Sopenharmony_ci break; 409141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 410141cc406Sopenharmony_ci *(SANE_Fixed *) value = optionBotRightXValue; 411141cc406Sopenharmony_ci break; 412141cc406Sopenharmony_ci } 413141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 414141cc406Sopenharmony_ci} 415141cc406Sopenharmony_ci 416141cc406Sopenharmony_ci/* 417141cc406Sopenharmony_ciThis option controls the bot-right-y corner of the scan 418141cc406Sopenharmony_ci*/ 419141cc406Sopenharmony_ci 420141cc406Sopenharmony_cistatic SANE_Fixed optionBotRightYValue 421141cc406Sopenharmony_ci = SANE_FIX (UMAX_MAX_HEIGHT * MM_IN_INCH / 600); 422141cc406Sopenharmony_ci 423141cc406Sopenharmony_cistatic SANE_Option_Descriptor optionBotRightYDescriptor = { 424141cc406Sopenharmony_ci SANE_NAME_SCAN_BR_Y, 425141cc406Sopenharmony_ci SANE_TITLE_SCAN_BR_Y, 426141cc406Sopenharmony_ci SANE_DESC_SCAN_BR_Y, 427141cc406Sopenharmony_ci SANE_TYPE_FIXED, 428141cc406Sopenharmony_ci SANE_UNIT_MM, 429141cc406Sopenharmony_ci sizeof (SANE_Fixed), 430141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, 431141cc406Sopenharmony_ci SANE_CONSTRAINT_RANGE, 432141cc406Sopenharmony_ci {(const SANE_String_Const *) & heightRange} 433141cc406Sopenharmony_ci}; 434141cc406Sopenharmony_ci 435141cc406Sopenharmony_cistatic SANE_Status 436141cc406Sopenharmony_cioptionBotRightYCallback (SANE_Option * option, SANE_Handle handle, 437141cc406Sopenharmony_ci SANE_Action action, void *value, SANE_Int * info) 438141cc406Sopenharmony_ci{ 439141cc406Sopenharmony_ci /* Eliminate warnings about unused parameters */ 440141cc406Sopenharmony_ci (void) option; 441141cc406Sopenharmony_ci (void) handle; 442141cc406Sopenharmony_ci 443141cc406Sopenharmony_ci switch (action) 444141cc406Sopenharmony_ci { 445141cc406Sopenharmony_ci case SANE_ACTION_SET_AUTO: 446141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 447141cc406Sopenharmony_ci break; 448141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 449141cc406Sopenharmony_ci optionBotRightYValue = *(SANE_Fixed *) value; 450141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 451141cc406Sopenharmony_ci break; 452141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 453141cc406Sopenharmony_ci *(SANE_Fixed *) value = optionBotRightYValue; 454141cc406Sopenharmony_ci break; 455141cc406Sopenharmony_ci } 456141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 457141cc406Sopenharmony_ci} 458141cc406Sopenharmony_ci 459141cc406Sopenharmony_ci/* 460141cc406Sopenharmony_ciThe following array binds the option descriptors to 461141cc406Sopenharmony_citheir respective callback routines 462141cc406Sopenharmony_ci*/ 463141cc406Sopenharmony_ci 464141cc406Sopenharmony_cistatic SANE_Option so[] = { 465141cc406Sopenharmony_ci {&optionNumOptionsDescriptor, optionNumOptionsCallback}, 466141cc406Sopenharmony_ci {&optionResolutionDescriptor, optionResolutionCallback}, 467141cc406Sopenharmony_ci {&optionGrayscaleDescriptor, optionGrayscaleCallback}, 468141cc406Sopenharmony_ci {&optionTopLeftXDescriptor, optionTopLeftXCallback}, 469141cc406Sopenharmony_ci {&optionTopLeftYDescriptor, optionTopLeftYCallback}, 470141cc406Sopenharmony_ci {&optionBotRightXDescriptor, optionBotRightXCallback}, 471141cc406Sopenharmony_ci {&optionBotRightYDescriptor, optionBotRightYCallback}, 472141cc406Sopenharmony_ci {&optionLampOffDescriptor, optionLampOffCallback} 473141cc406Sopenharmony_ci}; 474141cc406Sopenharmony_ci 475141cc406Sopenharmony_cistatic SANE_Word 476141cc406Sopenharmony_cigetNumberOfOptions (void) 477141cc406Sopenharmony_ci{ 478141cc406Sopenharmony_ci return NELEMS (so); 479141cc406Sopenharmony_ci} 480141cc406Sopenharmony_ci 481141cc406Sopenharmony_ci/* 482141cc406Sopenharmony_ciThis routine dispatches the control message to the appropriate 483141cc406Sopenharmony_cicallback routine, it outght to be called by sane_control_option 484141cc406Sopenharmony_ciafter any driver specific validation. 485141cc406Sopenharmony_ci*/ 486141cc406Sopenharmony_cistatic SANE_Status 487141cc406Sopenharmony_cidispatch_control_option (SANE_Handle handle, SANE_Int option, 488141cc406Sopenharmony_ci SANE_Action action, void *value, SANE_Int * info) 489141cc406Sopenharmony_ci{ 490141cc406Sopenharmony_ci SANE_Option *op = so + option; 491141cc406Sopenharmony_ci SANE_Int myinfo = 0; 492141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 493141cc406Sopenharmony_ci 494141cc406Sopenharmony_ci if (option < 0 || option >= NELEMS (so)) 495141cc406Sopenharmony_ci return SANE_STATUS_INVAL; /* Unknown option ... */ 496141cc406Sopenharmony_ci 497141cc406Sopenharmony_ci if ((action == SANE_ACTION_SET_VALUE) && 498141cc406Sopenharmony_ci ((op->descriptor->cap & SANE_CAP_SOFT_SELECT) == 0)) 499141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 500141cc406Sopenharmony_ci 501141cc406Sopenharmony_ci if ((action == SANE_ACTION_GET_VALUE) && 502141cc406Sopenharmony_ci ((op->descriptor->cap & SANE_CAP_SOFT_DETECT) == 0)) 503141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 504141cc406Sopenharmony_ci 505141cc406Sopenharmony_ci if ((action == SANE_ACTION_SET_AUTO) && 506141cc406Sopenharmony_ci ((op->descriptor->cap & SANE_CAP_AUTOMATIC) == 0)) 507141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 508141cc406Sopenharmony_ci 509141cc406Sopenharmony_ci if (action == SANE_ACTION_SET_VALUE) 510141cc406Sopenharmony_ci { 511141cc406Sopenharmony_ci status = sanei_constrain_value (op->descriptor, value, &myinfo); 512141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 513141cc406Sopenharmony_ci return status; 514141cc406Sopenharmony_ci } 515141cc406Sopenharmony_ci 516141cc406Sopenharmony_ci status = (op->callback) (op, handle, action, value, &myinfo); 517141cc406Sopenharmony_ci 518141cc406Sopenharmony_ci if (info) 519141cc406Sopenharmony_ci *info = myinfo; 520141cc406Sopenharmony_ci 521141cc406Sopenharmony_ci return status; 522141cc406Sopenharmony_ci} 523141cc406Sopenharmony_ci 524141cc406Sopenharmony_cistatic SANE_Status 525141cc406Sopenharmony_ciattach_scanner (const char *devicename, Umax_Device ** devp) 526141cc406Sopenharmony_ci{ 527141cc406Sopenharmony_ci UMAX_Handle scan; 528141cc406Sopenharmony_ci Umax_Device *dev; 529141cc406Sopenharmony_ci SANE_Status status; 530141cc406Sopenharmony_ci 531141cc406Sopenharmony_ci DBG (3, "attach_scanner: %s\n", devicename); 532141cc406Sopenharmony_ci 533141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 534141cc406Sopenharmony_ci { 535141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) 536141cc406Sopenharmony_ci { 537141cc406Sopenharmony_ci if (devp) 538141cc406Sopenharmony_ci *devp = dev; 539141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 540141cc406Sopenharmony_ci } 541141cc406Sopenharmony_ci } 542141cc406Sopenharmony_ci 543141cc406Sopenharmony_ci dev = malloc (sizeof (*dev)); 544141cc406Sopenharmony_ci if (!dev) 545141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 546141cc406Sopenharmony_ci memset (dev, '\0', sizeof (Umax_Device)); /* clear structure */ 547141cc406Sopenharmony_ci 548141cc406Sopenharmony_ci DBG (4, "attach_scanner: opening %s\n", devicename); 549141cc406Sopenharmony_ci 550141cc406Sopenharmony_ci status = UMAX_open_device (&scan, devicename); 551141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 552141cc406Sopenharmony_ci { 553141cc406Sopenharmony_ci DBG (1, "ERROR: attach_scanner: opening %s failed\n", devicename); 554141cc406Sopenharmony_ci free (dev); 555141cc406Sopenharmony_ci return status; 556141cc406Sopenharmony_ci } 557141cc406Sopenharmony_ci dev->name = strdup (devicename); 558141cc406Sopenharmony_ci dev->sane.name = dev->name; 559141cc406Sopenharmony_ci dev->sane.vendor = "UMAX"; 560141cc406Sopenharmony_ci dev->sane.model = UMAX_get_device_name (&scan); 561141cc406Sopenharmony_ci dev->sane.type = "flatbed scanner"; 562141cc406Sopenharmony_ci UMAX_close_device (&scan); 563141cc406Sopenharmony_ci 564141cc406Sopenharmony_ci ++num_devices; 565141cc406Sopenharmony_ci dev->next = first_dev; 566141cc406Sopenharmony_ci first_dev = dev; 567141cc406Sopenharmony_ci 568141cc406Sopenharmony_ci if (devp) 569141cc406Sopenharmony_ci *devp = dev; 570141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 571141cc406Sopenharmony_ci} 572141cc406Sopenharmony_ci 573141cc406Sopenharmony_ci/* callback function for sanei_usb_attach_matching_devices 574141cc406Sopenharmony_ci*/ 575141cc406Sopenharmony_cistatic SANE_Status 576141cc406Sopenharmony_ciattach_one (const char *name) 577141cc406Sopenharmony_ci{ 578141cc406Sopenharmony_ci attach_scanner (name, 0); 579141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 580141cc406Sopenharmony_ci} 581141cc406Sopenharmony_ci 582141cc406Sopenharmony_ci/* This file implements a SANE backend for the UMAX Astra 1220U scanner. 583141cc406Sopenharmony_ci */ 584141cc406Sopenharmony_ciSANE_Status 585141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) 586141cc406Sopenharmony_ci{ 587141cc406Sopenharmony_ci char config_line[PATH_MAX]; 588141cc406Sopenharmony_ci size_t len; 589141cc406Sopenharmony_ci FILE *fp; 590141cc406Sopenharmony_ci 591141cc406Sopenharmony_ci DBG_INIT (); 592141cc406Sopenharmony_ci 593141cc406Sopenharmony_ci DBG (2, "sane_init: version_code %s 0, authorize %s 0\n", 594141cc406Sopenharmony_ci version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!="); 595141cc406Sopenharmony_ci DBG (1, "sane_init: SANE umax1220u backend version %d.%d.%d from %s\n", 596141cc406Sopenharmony_ci SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD, PACKAGE_STRING); 597141cc406Sopenharmony_ci 598141cc406Sopenharmony_ci if (version_code) 599141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 600141cc406Sopenharmony_ci 601141cc406Sopenharmony_ci sanei_usb_init (); 602141cc406Sopenharmony_ci sanei_pv8630_init (); 603141cc406Sopenharmony_ci 604141cc406Sopenharmony_ci fp = sanei_config_open (UMAX_CONFIG_FILE); 605141cc406Sopenharmony_ci if (!fp) 606141cc406Sopenharmony_ci { 607141cc406Sopenharmony_ci /* no config-file: try /dev/scanner and /dev/usbscanner. */ 608141cc406Sopenharmony_ci attach_scanner ("/dev/scanner", 0); 609141cc406Sopenharmony_ci attach_scanner ("/dev/usbscanner", 0); 610141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 611141cc406Sopenharmony_ci } 612141cc406Sopenharmony_ci 613141cc406Sopenharmony_ci DBG (3, "reading configure file %s\n", UMAX_CONFIG_FILE); 614141cc406Sopenharmony_ci 615141cc406Sopenharmony_ci while (sanei_config_read (config_line, sizeof (config_line), fp)) 616141cc406Sopenharmony_ci { 617141cc406Sopenharmony_ci if (config_line[0] == '#') 618141cc406Sopenharmony_ci continue; /* ignore line comments */ 619141cc406Sopenharmony_ci 620141cc406Sopenharmony_ci len = strlen (config_line); 621141cc406Sopenharmony_ci 622141cc406Sopenharmony_ci if (!len) 623141cc406Sopenharmony_ci continue; /* ignore empty lines */ 624141cc406Sopenharmony_ci 625141cc406Sopenharmony_ci DBG (4, "attach_matching_devices(%s)\n", config_line); 626141cc406Sopenharmony_ci sanei_usb_attach_matching_devices (config_line, attach_one); 627141cc406Sopenharmony_ci } 628141cc406Sopenharmony_ci 629141cc406Sopenharmony_ci DBG (4, "finished reading configure file\n"); 630141cc406Sopenharmony_ci 631141cc406Sopenharmony_ci fclose (fp); 632141cc406Sopenharmony_ci 633141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 634141cc406Sopenharmony_ci} 635141cc406Sopenharmony_ci 636141cc406Sopenharmony_civoid 637141cc406Sopenharmony_cisane_exit (void) 638141cc406Sopenharmony_ci{ 639141cc406Sopenharmony_ci Umax_Device *dev, *next; 640141cc406Sopenharmony_ci 641141cc406Sopenharmony_ci DBG (3, "sane_exit\n"); 642141cc406Sopenharmony_ci 643141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = next) 644141cc406Sopenharmony_ci { 645141cc406Sopenharmony_ci next = dev->next; 646141cc406Sopenharmony_ci free (dev->name); 647141cc406Sopenharmony_ci free (dev); 648141cc406Sopenharmony_ci } 649141cc406Sopenharmony_ci 650141cc406Sopenharmony_ci if (devlist) 651141cc406Sopenharmony_ci free (devlist); 652141cc406Sopenharmony_ci return; 653141cc406Sopenharmony_ci} 654141cc406Sopenharmony_ci 655141cc406Sopenharmony_ciSANE_Status 656141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) 657141cc406Sopenharmony_ci{ 658141cc406Sopenharmony_ci Umax_Device *dev; 659141cc406Sopenharmony_ci int i; 660141cc406Sopenharmony_ci 661141cc406Sopenharmony_ci DBG (3, "sane_get_devices(local_only = %d)\n", local_only); 662141cc406Sopenharmony_ci 663141cc406Sopenharmony_ci if (devlist) 664141cc406Sopenharmony_ci free (devlist); 665141cc406Sopenharmony_ci 666141cc406Sopenharmony_ci devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); 667141cc406Sopenharmony_ci if (!devlist) 668141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 669141cc406Sopenharmony_ci 670141cc406Sopenharmony_ci i = 0; 671141cc406Sopenharmony_ci 672141cc406Sopenharmony_ci for (dev = first_dev; i < num_devices; dev = dev->next) 673141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 674141cc406Sopenharmony_ci 675141cc406Sopenharmony_ci devlist[i++] = 0; 676141cc406Sopenharmony_ci 677141cc406Sopenharmony_ci *device_list = devlist; 678141cc406Sopenharmony_ci 679141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 680141cc406Sopenharmony_ci} 681141cc406Sopenharmony_ci 682141cc406Sopenharmony_ciSANE_Status 683141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 684141cc406Sopenharmony_ci{ 685141cc406Sopenharmony_ci Umax_Device *dev; 686141cc406Sopenharmony_ci SANE_Status status; 687141cc406Sopenharmony_ci Umax_Scanner *scanner; 688141cc406Sopenharmony_ci 689141cc406Sopenharmony_ci DBG (3, "sane_open\n"); 690141cc406Sopenharmony_ci 691141cc406Sopenharmony_ci if (devicename[0]) /* search for devicename */ 692141cc406Sopenharmony_ci { 693141cc406Sopenharmony_ci DBG (4, "sane_open: devicename=%s\n", devicename); 694141cc406Sopenharmony_ci 695141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 696141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) 697141cc406Sopenharmony_ci break; 698141cc406Sopenharmony_ci 699141cc406Sopenharmony_ci if (!dev) 700141cc406Sopenharmony_ci { 701141cc406Sopenharmony_ci status = attach_scanner (devicename, &dev); 702141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 703141cc406Sopenharmony_ci return status; 704141cc406Sopenharmony_ci } 705141cc406Sopenharmony_ci } 706141cc406Sopenharmony_ci else 707141cc406Sopenharmony_ci { 708141cc406Sopenharmony_ci DBG (2, "sane_open: no devicename, opening first device\n"); 709141cc406Sopenharmony_ci dev = first_dev; 710141cc406Sopenharmony_ci } 711141cc406Sopenharmony_ci 712141cc406Sopenharmony_ci if (!dev) 713141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 714141cc406Sopenharmony_ci 715141cc406Sopenharmony_ci scanner = malloc (sizeof (*scanner)); 716141cc406Sopenharmony_ci if (!scanner) 717141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 718141cc406Sopenharmony_ci 719141cc406Sopenharmony_ci memset (scanner, 0, sizeof (*scanner)); 720141cc406Sopenharmony_ci scanner->device = dev; 721141cc406Sopenharmony_ci 722141cc406Sopenharmony_ci status = UMAX_open_device (&scanner->scan, dev->sane.name); 723141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 724141cc406Sopenharmony_ci { 725141cc406Sopenharmony_ci free (scanner); 726141cc406Sopenharmony_ci return status; 727141cc406Sopenharmony_ci } 728141cc406Sopenharmony_ci 729141cc406Sopenharmony_ci *handle = scanner; 730141cc406Sopenharmony_ci 731141cc406Sopenharmony_ci /* insert newly opened handle into list of open handles: */ 732141cc406Sopenharmony_ci scanner->next = first_handle; 733141cc406Sopenharmony_ci 734141cc406Sopenharmony_ci first_handle = scanner; 735141cc406Sopenharmony_ci 736141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 737141cc406Sopenharmony_ci} 738141cc406Sopenharmony_ci 739141cc406Sopenharmony_civoid 740141cc406Sopenharmony_cisane_close (SANE_Handle handle) 741141cc406Sopenharmony_ci{ 742141cc406Sopenharmony_ci Umax_Scanner *prev, *scanner; 743141cc406Sopenharmony_ci 744141cc406Sopenharmony_ci DBG (3, "sane_close\n"); 745141cc406Sopenharmony_ci 746141cc406Sopenharmony_ci if (!first_handle) 747141cc406Sopenharmony_ci { 748141cc406Sopenharmony_ci DBG (1, "ERROR: sane_close: no handles opened\n"); 749141cc406Sopenharmony_ci return; 750141cc406Sopenharmony_ci } 751141cc406Sopenharmony_ci 752141cc406Sopenharmony_ci /* remove handle from list of open handles: */ 753141cc406Sopenharmony_ci 754141cc406Sopenharmony_ci prev = NULL; 755141cc406Sopenharmony_ci 756141cc406Sopenharmony_ci for (scanner = first_handle; scanner; scanner = scanner->next) 757141cc406Sopenharmony_ci { 758141cc406Sopenharmony_ci if (scanner == handle) 759141cc406Sopenharmony_ci break; 760141cc406Sopenharmony_ci 761141cc406Sopenharmony_ci prev = scanner; 762141cc406Sopenharmony_ci } 763141cc406Sopenharmony_ci 764141cc406Sopenharmony_ci if (!scanner) 765141cc406Sopenharmony_ci { 766141cc406Sopenharmony_ci DBG (1, "ERROR: sane_close: invalid handle %p\n", handle); 767141cc406Sopenharmony_ci return; /* oops, not a handle we know about */ 768141cc406Sopenharmony_ci } 769141cc406Sopenharmony_ci 770141cc406Sopenharmony_ci if (prev) 771141cc406Sopenharmony_ci prev->next = scanner->next; 772141cc406Sopenharmony_ci else 773141cc406Sopenharmony_ci first_handle = scanner->next; 774141cc406Sopenharmony_ci 775141cc406Sopenharmony_ci UMAX_close_device (&scanner->scan); 776141cc406Sopenharmony_ci 777141cc406Sopenharmony_ci free (scanner); 778141cc406Sopenharmony_ci} 779141cc406Sopenharmony_ci 780141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 781141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 782141cc406Sopenharmony_ci{ 783141cc406Sopenharmony_ci (void) handle; /* Eliminate compiler warning */ 784141cc406Sopenharmony_ci 785141cc406Sopenharmony_ci DBG (3, "sane_get_option_descriptor: option = %d\n", option); 786141cc406Sopenharmony_ci if (option < 0 || option >= NELEMS (so)) 787141cc406Sopenharmony_ci return NULL; 788141cc406Sopenharmony_ci return so[option].descriptor; 789141cc406Sopenharmony_ci} 790141cc406Sopenharmony_ci 791141cc406Sopenharmony_ciSANE_Status 792141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 793141cc406Sopenharmony_ci SANE_Action action, void *value, SANE_Int * info) 794141cc406Sopenharmony_ci{ 795141cc406Sopenharmony_ci (void) handle; /* Eliminate compiler warning */ 796141cc406Sopenharmony_ci 797141cc406Sopenharmony_ci DBG (3, 798141cc406Sopenharmony_ci "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n", 799141cc406Sopenharmony_ci handle, option, action, value, (void*) info); 800141cc406Sopenharmony_ci 801141cc406Sopenharmony_ci return dispatch_control_option (handle, option, action, value, info); 802141cc406Sopenharmony_ci} 803141cc406Sopenharmony_ci 804141cc406Sopenharmony_ciSANE_Status 805141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 806141cc406Sopenharmony_ci{ 807141cc406Sopenharmony_ci int rc = SANE_STATUS_GOOD; 808141cc406Sopenharmony_ci int w = 809141cc406Sopenharmony_ci SANE_UNFIX (optionBotRightXValue - 810141cc406Sopenharmony_ci optionTopLeftXValue) / MM_IN_INCH * optionResolutionValue; 811141cc406Sopenharmony_ci int h = 812141cc406Sopenharmony_ci SANE_UNFIX (optionBotRightYValue - 813141cc406Sopenharmony_ci optionTopLeftYValue) / MM_IN_INCH * optionResolutionValue; 814141cc406Sopenharmony_ci 815141cc406Sopenharmony_ci (void) handle; /* Eliminate compiler warning */ 816141cc406Sopenharmony_ci 817141cc406Sopenharmony_ci DBG (3, "sane_get_parameters\n"); 818141cc406Sopenharmony_ci parms.depth = 8; 819141cc406Sopenharmony_ci parms.last_frame = SANE_TRUE; 820141cc406Sopenharmony_ci parms.pixels_per_line = w; 821141cc406Sopenharmony_ci parms.lines = h; 822141cc406Sopenharmony_ci 823141cc406Sopenharmony_ci if (optionGrayscaleValue == SANE_TRUE) 824141cc406Sopenharmony_ci { 825141cc406Sopenharmony_ci parms.format = SANE_FRAME_GRAY; 826141cc406Sopenharmony_ci parms.bytes_per_line = w; 827141cc406Sopenharmony_ci } 828141cc406Sopenharmony_ci else 829141cc406Sopenharmony_ci { 830141cc406Sopenharmony_ci parms.format = SANE_FRAME_RGB; 831141cc406Sopenharmony_ci parms.bytes_per_line = w * 3; 832141cc406Sopenharmony_ci } 833141cc406Sopenharmony_ci *params = parms; 834141cc406Sopenharmony_ci return rc; 835141cc406Sopenharmony_ci} 836141cc406Sopenharmony_ci 837141cc406Sopenharmony_ciSANE_Status 838141cc406Sopenharmony_cisane_start (SANE_Handle handle) 839141cc406Sopenharmony_ci{ 840141cc406Sopenharmony_ci Umax_Scanner *scanner = handle; 841141cc406Sopenharmony_ci SANE_Status res; 842141cc406Sopenharmony_ci 843141cc406Sopenharmony_ci DBG (3, "sane_start\n"); 844141cc406Sopenharmony_ci 845141cc406Sopenharmony_ci res = UMAX_set_scan_parameters (&scanner->scan, 846141cc406Sopenharmony_ci optionGrayscaleValue == SANE_FALSE, 847141cc406Sopenharmony_ci SANE_UNFIX (optionTopLeftXValue) / 848141cc406Sopenharmony_ci MM_IN_INCH * 600, 849141cc406Sopenharmony_ci SANE_UNFIX (optionTopLeftYValue) / 850141cc406Sopenharmony_ci MM_IN_INCH * 600, 851141cc406Sopenharmony_ci SANE_UNFIX (optionBotRightXValue - 852141cc406Sopenharmony_ci optionTopLeftXValue) / 853141cc406Sopenharmony_ci MM_IN_INCH * optionResolutionValue, 854141cc406Sopenharmony_ci SANE_UNFIX (optionBotRightYValue - 855141cc406Sopenharmony_ci optionTopLeftYValue) / 856141cc406Sopenharmony_ci MM_IN_INCH * optionResolutionValue, 857141cc406Sopenharmony_ci optionResolutionValue, 858141cc406Sopenharmony_ci optionResolutionValue); 859141cc406Sopenharmony_ci 860141cc406Sopenharmony_ci if (res != SANE_STATUS_GOOD) 861141cc406Sopenharmony_ci return res; 862141cc406Sopenharmony_ci 863141cc406Sopenharmony_ci if (scanner->scan.model == ASTRA_1220U) 864141cc406Sopenharmony_ci return UMAX_start_scan (&scanner->scan); 865141cc406Sopenharmony_ci else 866141cc406Sopenharmony_ci return UMAX_start_scan_2100U (&scanner->scan); 867141cc406Sopenharmony_ci} 868141cc406Sopenharmony_ci 869141cc406Sopenharmony_ciSANE_Status 870141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * data, 871141cc406Sopenharmony_ci SANE_Int max_length, SANE_Int * length) 872141cc406Sopenharmony_ci{ 873141cc406Sopenharmony_ci Umax_Scanner *scanner = handle; 874141cc406Sopenharmony_ci SANE_Status res; 875141cc406Sopenharmony_ci int len; 876141cc406Sopenharmony_ci unsigned char rgb[3]; 877141cc406Sopenharmony_ci 878141cc406Sopenharmony_ci len = *length = 0; 879141cc406Sopenharmony_ci 880141cc406Sopenharmony_ci if (!data || !length) 881141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 882141cc406Sopenharmony_ci 883141cc406Sopenharmony_ci if (scanner->scan.done) 884141cc406Sopenharmony_ci { 885141cc406Sopenharmony_ci res = UMAX_finish_scan (&scanner->scan); 886141cc406Sopenharmony_ci 887141cc406Sopenharmony_ci if (scanner->scan.model == ASTRA_1220U) 888141cc406Sopenharmony_ci res = UMAX_park_head (&scanner->scan); 889141cc406Sopenharmony_ci else 890141cc406Sopenharmony_ci res = UMAX_park_head_2100U (&scanner->scan); 891141cc406Sopenharmony_ci 892141cc406Sopenharmony_ci return SANE_STATUS_EOF; 893141cc406Sopenharmony_ci } 894141cc406Sopenharmony_ci 895141cc406Sopenharmony_ci DBG (3, "sane_read: max_length = %d\n", max_length); 896141cc406Sopenharmony_ci 897141cc406Sopenharmony_ci if (optionGrayscaleValue == SANE_FALSE) 898141cc406Sopenharmony_ci { 899141cc406Sopenharmony_ci while (!scanner->scan.done && (max_length >= 3)) 900141cc406Sopenharmony_ci { 901141cc406Sopenharmony_ci res = UMAX_get_rgb (&scanner->scan, rgb); 902141cc406Sopenharmony_ci if (res != SANE_STATUS_GOOD) 903141cc406Sopenharmony_ci { 904141cc406Sopenharmony_ci *length = 0; 905141cc406Sopenharmony_ci return res; 906141cc406Sopenharmony_ci } 907141cc406Sopenharmony_ci *data++ = rgb[0]; 908141cc406Sopenharmony_ci *data++ = rgb[1]; 909141cc406Sopenharmony_ci *data++ = rgb[2]; 910141cc406Sopenharmony_ci max_length -= 3; 911141cc406Sopenharmony_ci len += 3; 912141cc406Sopenharmony_ci } 913141cc406Sopenharmony_ci } 914141cc406Sopenharmony_ci else 915141cc406Sopenharmony_ci { 916141cc406Sopenharmony_ci while (!scanner->scan.done && max_length) 917141cc406Sopenharmony_ci { 918141cc406Sopenharmony_ci res = UMAX_get_rgb (&scanner->scan, rgb); 919141cc406Sopenharmony_ci if (res != SANE_STATUS_GOOD) 920141cc406Sopenharmony_ci { 921141cc406Sopenharmony_ci *length = 0; 922141cc406Sopenharmony_ci return res; 923141cc406Sopenharmony_ci } 924141cc406Sopenharmony_ci *data++ = rgb[0]; 925141cc406Sopenharmony_ci max_length--; 926141cc406Sopenharmony_ci len++; 927141cc406Sopenharmony_ci } 928141cc406Sopenharmony_ci } 929141cc406Sopenharmony_ci 930141cc406Sopenharmony_ci *length = len; 931141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 932141cc406Sopenharmony_ci} 933141cc406Sopenharmony_ci 934141cc406Sopenharmony_civoid 935141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 936141cc406Sopenharmony_ci{ 937141cc406Sopenharmony_ci DBG (3, "sane_cancel: handle = %p\n", handle); 938141cc406Sopenharmony_ci DBG (3, "sane_cancel: canceling is unsupported in this backend\n"); 939141cc406Sopenharmony_ci} 940141cc406Sopenharmony_ci 941141cc406Sopenharmony_ciSANE_Status 942141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 943141cc406Sopenharmony_ci{ 944141cc406Sopenharmony_ci DBG (3, "sane_set_io_mode: handle = %p, non_blocking = %d\n", handle, 945141cc406Sopenharmony_ci non_blocking); 946141cc406Sopenharmony_ci if (non_blocking != SANE_FALSE) 947141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 948141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 949141cc406Sopenharmony_ci} 950141cc406Sopenharmony_ci 951141cc406Sopenharmony_ciSANE_Status 952141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd) 953141cc406Sopenharmony_ci{ 954141cc406Sopenharmony_ci DBG (3, "sane_get_select_fd: handle = %p, fd %s 0\n", handle, 955141cc406Sopenharmony_ci fd ? "!=" : "="); 956141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 957141cc406Sopenharmony_ci} 958