1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci Copyright (C) 2009-12 Stéphane Voltz <stef.dev@free.fr> 4141cc406Sopenharmony_ci 5141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 6141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 7141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 8141cc406Sopenharmony_ci License, or (at your option) any later version. 9141cc406Sopenharmony_ci 10141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 11141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 12141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13141cc406Sopenharmony_ci General Public License for more details. 14141cc406Sopenharmony_ci 15141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 16141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 17141cc406Sopenharmony_ci*/ 18141cc406Sopenharmony_ci/* -------------------------------------------------------------------------- 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci*/ 21141cc406Sopenharmony_ci 22141cc406Sopenharmony_ci/* ------------------------------------------------------------------------- */ 23141cc406Sopenharmony_ci/*! \mainpage Primax PagePartner Parallel Port scanner Index Page 24141cc406Sopenharmony_ci * 25141cc406Sopenharmony_ci * \section intro_sec Introduction 26141cc406Sopenharmony_ci * 27141cc406Sopenharmony_ci * This backend provides support for the Prima PagePartner sheet fed parallel 28141cc406Sopenharmony_ci * port scanner. 29141cc406Sopenharmony_ci * 30141cc406Sopenharmony_ci * \section sane_api SANE API 31141cc406Sopenharmony_ci * 32141cc406Sopenharmony_ci * \subsection sane_flow sane flow 33141cc406Sopenharmony_ci SANE FLOW 34141cc406Sopenharmony_ci - sane_init() : initialize backend, attach scanners. 35141cc406Sopenharmony_ci - sane_get_devices() : query list of scanner devices, backend must 36141cc406Sopenharmony_ci probe for new devices. 37141cc406Sopenharmony_ci - sane_open() : open a particular scanner device, adding a handle 38141cc406Sopenharmony_ci to the opened device 39141cc406Sopenharmony_ci - sane_set_io_mode() : set blocking mode 40141cc406Sopenharmony_ci - sane_get_select_fd() : get scanner fd 41141cc406Sopenharmony_ci - sane_get_option_descriptor() : get option information 42141cc406Sopenharmony_ci - sane_control_option() : change option values 43141cc406Sopenharmony_ci - sane_start() : start image acquisition 44141cc406Sopenharmony_ci - sane_get_parameters() : returns actual scan parameters for the ongoing scan 45141cc406Sopenharmony_ci - sane_read() : read image data 46141cc406Sopenharmony_ci - sane_cancel() : cancel operation, end scan 47141cc406Sopenharmony_ci - sane_close() : close opened scanner device, freeing scanner handle 48141cc406Sopenharmony_ci - sane_exit() : terminate use of backend, freeing all resources for attached 49141cc406Sopenharmony_ci devices when last frontend quits 50141cc406Sopenharmony_ci */ 51141cc406Sopenharmony_ci 52141cc406Sopenharmony_ci/** 53141cc406Sopenharmony_ci * the build number allow to know which version of the backend is running. 54141cc406Sopenharmony_ci */ 55141cc406Sopenharmony_ci#define BUILD 2301 56141cc406Sopenharmony_ci 57141cc406Sopenharmony_ci#include "p5.h" 58141cc406Sopenharmony_ci 59141cc406Sopenharmony_ci/** 60141cc406Sopenharmony_ci * Import directly the low level part needed to 61141cc406Sopenharmony_ci * operate scanner. The alternative is to prefix all public functions 62141cc406Sopenharmony_ci * with sanei_p5_ ,and have all the functions prototyped in 63141cc406Sopenharmony_ci * p5_device.h . 64141cc406Sopenharmony_ci */ 65141cc406Sopenharmony_ci#include "p5_device.c" 66141cc406Sopenharmony_ci 67141cc406Sopenharmony_ci/** 68141cc406Sopenharmony_ci * number of time the backend has been loaded by sane_init. 69141cc406Sopenharmony_ci */ 70141cc406Sopenharmony_cistatic int init_count = 0; 71141cc406Sopenharmony_ci 72141cc406Sopenharmony_ci/** 73141cc406Sopenharmony_ci * NULL terminated list of opened frontend sessions. Sessions are 74141cc406Sopenharmony_ci * inserted here on sane_open() and removed on sane_close(). 75141cc406Sopenharmony_ci */ 76141cc406Sopenharmony_cistatic P5_Session *sessions = NULL; 77141cc406Sopenharmony_ci 78141cc406Sopenharmony_ci/** 79141cc406Sopenharmony_ci * NULL terminated list of detected physical devices. 80141cc406Sopenharmony_ci * The same device may be opened several time by different sessions. 81141cc406Sopenharmony_ci * Entry are inserted here by the attach() function. 82141cc406Sopenharmony_ci * */ 83141cc406Sopenharmony_cistatic P5_Device *devices = NULL; 84141cc406Sopenharmony_ci 85141cc406Sopenharmony_ci/** 86141cc406Sopenharmony_ci * NULL terminated list of devices needed by sane_get_devices(), since 87141cc406Sopenharmony_ci * the result returned must stay consistent until next call. 88141cc406Sopenharmony_ci */ 89141cc406Sopenharmony_cistatic const SANE_Device **devlist = 0; 90141cc406Sopenharmony_ci 91141cc406Sopenharmony_ci/** 92141cc406Sopenharmony_ci * list of possible color modes 93141cc406Sopenharmony_ci */ 94141cc406Sopenharmony_cistatic SANE_String_Const mode_list[] = { 95141cc406Sopenharmony_ci SANE_I18N (COLOR_MODE), 96141cc406Sopenharmony_ci SANE_I18N (GRAY_MODE), 97141cc406Sopenharmony_ci /* SANE_I18N (LINEART_MODE), not supported yet */ 98141cc406Sopenharmony_ci 0 99141cc406Sopenharmony_ci}; 100141cc406Sopenharmony_ci 101141cc406Sopenharmony_cistatic SANE_Range x_range = { 102141cc406Sopenharmony_ci SANE_FIX (0.0), /* minimum */ 103141cc406Sopenharmony_ci SANE_FIX (216.0), /* maximum */ 104141cc406Sopenharmony_ci SANE_FIX (0.0) /* quantization */ 105141cc406Sopenharmony_ci}; 106141cc406Sopenharmony_ci 107141cc406Sopenharmony_cistatic SANE_Range y_range = { 108141cc406Sopenharmony_ci SANE_FIX (0.0), /* minimum */ 109141cc406Sopenharmony_ci SANE_FIX (299.0), /* maximum */ 110141cc406Sopenharmony_ci SANE_FIX (0.0) /* no quantization */ 111141cc406Sopenharmony_ci}; 112141cc406Sopenharmony_ci 113141cc406Sopenharmony_ci/** 114141cc406Sopenharmony_ci * finds the maximum string length in a string array. 115141cc406Sopenharmony_ci */ 116141cc406Sopenharmony_cistatic size_t 117141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[]) 118141cc406Sopenharmony_ci{ 119141cc406Sopenharmony_ci size_t size, max_size = 0; 120141cc406Sopenharmony_ci SANE_Int i; 121141cc406Sopenharmony_ci 122141cc406Sopenharmony_ci for (i = 0; strings[i]; ++i) 123141cc406Sopenharmony_ci { 124141cc406Sopenharmony_ci size = strlen (strings[i]) + 1; 125141cc406Sopenharmony_ci if (size > max_size) 126141cc406Sopenharmony_ci max_size = size; 127141cc406Sopenharmony_ci } 128141cc406Sopenharmony_ci return max_size; 129141cc406Sopenharmony_ci} 130141cc406Sopenharmony_ci 131141cc406Sopenharmony_ci/**> placeholders for decoded configuration values */ 132141cc406Sopenharmony_cistatic P5_Config p5cfg; 133141cc406Sopenharmony_ci 134141cc406Sopenharmony_ci 135141cc406Sopenharmony_ci/* ------------------------------------------------------------------------- */ 136141cc406Sopenharmony_ci 137141cc406Sopenharmony_ci/* 138141cc406Sopenharmony_ci * SANE Interface 139141cc406Sopenharmony_ci */ 140141cc406Sopenharmony_ci 141141cc406Sopenharmony_ci 142141cc406Sopenharmony_ci/** 143141cc406Sopenharmony_ci * Called by SANE initially. 144141cc406Sopenharmony_ci * 145141cc406Sopenharmony_ci * From the SANE spec: 146141cc406Sopenharmony_ci * This function must be called before any other SANE function can be 147141cc406Sopenharmony_ci * called. The behavior of a SANE backend is undefined if this 148141cc406Sopenharmony_ci * function is not called first. The version code of the backend is 149141cc406Sopenharmony_ci * returned in the value pointed to by version_code. If that pointer 150141cc406Sopenharmony_ci * is NULL, no version code is returned. Argument authorize is either 151141cc406Sopenharmony_ci * a pointer to a function that is invoked when the backend requires 152141cc406Sopenharmony_ci * authentication for a specific resource or NULL if the frontend does 153141cc406Sopenharmony_ci * not support authentication. 154141cc406Sopenharmony_ci */ 155141cc406Sopenharmony_ciSANE_Status 156141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) 157141cc406Sopenharmony_ci{ 158141cc406Sopenharmony_ci SANE_Status status; 159141cc406Sopenharmony_ci 160141cc406Sopenharmony_ci (void) authorize; /* get rid of compiler warning */ 161141cc406Sopenharmony_ci 162141cc406Sopenharmony_ci init_count++; 163141cc406Sopenharmony_ci 164141cc406Sopenharmony_ci /* init backend debug */ 165141cc406Sopenharmony_ci DBG_INIT (); 166141cc406Sopenharmony_ci DBG (DBG_info, "SANE P5 backend version %d.%d-%d\n", 167141cc406Sopenharmony_ci SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 168141cc406Sopenharmony_ci DBG (DBG_proc, "sane_init: start\n"); 169141cc406Sopenharmony_ci DBG (DBG_trace, "sane_init: init_count=%d\n", init_count); 170141cc406Sopenharmony_ci 171141cc406Sopenharmony_ci if (version_code) 172141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 173141cc406Sopenharmony_ci 174141cc406Sopenharmony_ci /* cold-plugging case : probe for already plugged devices */ 175141cc406Sopenharmony_ci status = probe_p5_devices (); 176141cc406Sopenharmony_ci 177141cc406Sopenharmony_ci DBG (DBG_proc, "sane_init: exit\n"); 178141cc406Sopenharmony_ci return status; 179141cc406Sopenharmony_ci} 180141cc406Sopenharmony_ci 181141cc406Sopenharmony_ci 182141cc406Sopenharmony_ci/** 183141cc406Sopenharmony_ci * Called by SANE to find out about supported devices. 184141cc406Sopenharmony_ci * 185141cc406Sopenharmony_ci * From the SANE spec: 186141cc406Sopenharmony_ci * This function can be used to query the list of devices that are 187141cc406Sopenharmony_ci * available. If the function executes successfully, it stores a 188141cc406Sopenharmony_ci * pointer to a NULL terminated array of pointers to SANE_Device 189141cc406Sopenharmony_ci * structures in *device_list. The returned list is guaranteed to 190141cc406Sopenharmony_ci * remain unchanged and valid until (a) another call to this function 191141cc406Sopenharmony_ci * is performed or (b) a call to sane_exit() is performed. This 192141cc406Sopenharmony_ci * function can be called repeatedly to detect when new devices become 193141cc406Sopenharmony_ci * available. If argument local_only is true, only local devices are 194141cc406Sopenharmony_ci * returned (devices directly attached to the machine that SANE is 195141cc406Sopenharmony_ci * running on). If it is false, the device list includes all remote 196141cc406Sopenharmony_ci * devices that are accessible to the SANE library. 197141cc406Sopenharmony_ci * 198141cc406Sopenharmony_ci * SANE does not require that this function is called before a 199141cc406Sopenharmony_ci * sane_open() call is performed. A device name may be specified 200141cc406Sopenharmony_ci * explicitly by a user which would make it unnecessary and 201141cc406Sopenharmony_ci * undesirable to call this function first. 202141cc406Sopenharmony_ci * @param device_list pointer where to store the device list 203141cc406Sopenharmony_ci * @param local_only SANE_TRUE if only local devices are required. 204141cc406Sopenharmony_ci * @return SANE_STATUS_GOOD when successful 205141cc406Sopenharmony_ci */ 206141cc406Sopenharmony_ciSANE_Status 207141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) 208141cc406Sopenharmony_ci{ 209141cc406Sopenharmony_ci int dev_num, devnr; 210141cc406Sopenharmony_ci struct P5_Device *device; 211141cc406Sopenharmony_ci SANE_Device *sane_device; 212141cc406Sopenharmony_ci int i; 213141cc406Sopenharmony_ci 214141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_devices: start: local_only = %s\n", 215141cc406Sopenharmony_ci local_only == SANE_TRUE ? "true" : "false"); 216141cc406Sopenharmony_ci 217141cc406Sopenharmony_ci /* free existing devlist first */ 218141cc406Sopenharmony_ci if (devlist) 219141cc406Sopenharmony_ci { 220141cc406Sopenharmony_ci for (i = 0; devlist[i] != NULL; i++) 221141cc406Sopenharmony_ci free ((void *)devlist[i]); 222141cc406Sopenharmony_ci free (devlist); 223141cc406Sopenharmony_ci devlist = NULL; 224141cc406Sopenharmony_ci } 225141cc406Sopenharmony_ci 226141cc406Sopenharmony_ci /** 227141cc406Sopenharmony_ci * Since sane_get_devices() may be called repeatedly to detect new devices, 228141cc406Sopenharmony_ci * the device detection must be run at each call. We are handling 229141cc406Sopenharmony_ci * hot-plugging : we probe for devices plugged since sane_init() was called. 230141cc406Sopenharmony_ci */ 231141cc406Sopenharmony_ci probe_p5_devices (); 232141cc406Sopenharmony_ci 233141cc406Sopenharmony_ci /* if no devices detected, just return an empty list */ 234141cc406Sopenharmony_ci if (devices == NULL) 235141cc406Sopenharmony_ci { 236141cc406Sopenharmony_ci devlist = malloc (sizeof (devlist[0])); 237141cc406Sopenharmony_ci if (!devlist) 238141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 239141cc406Sopenharmony_ci devlist[0] = NULL; 240141cc406Sopenharmony_ci *device_list = devlist; 241141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_devices: exit with no device\n"); 242141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 243141cc406Sopenharmony_ci } 244141cc406Sopenharmony_ci 245141cc406Sopenharmony_ci /* count physical devices */ 246141cc406Sopenharmony_ci devnr = 1; 247141cc406Sopenharmony_ci device = devices; 248141cc406Sopenharmony_ci while (device->next) 249141cc406Sopenharmony_ci { 250141cc406Sopenharmony_ci devnr++; 251141cc406Sopenharmony_ci device = device->next; 252141cc406Sopenharmony_ci } 253141cc406Sopenharmony_ci 254141cc406Sopenharmony_ci /* allocate room for the list, plus 1 for the NULL terminator */ 255141cc406Sopenharmony_ci devlist = malloc ((devnr + 1) * sizeof (devlist[0])); 256141cc406Sopenharmony_ci if (!devlist) 257141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 258141cc406Sopenharmony_ci 259141cc406Sopenharmony_ci *device_list = devlist; 260141cc406Sopenharmony_ci 261141cc406Sopenharmony_ci dev_num = 0; 262141cc406Sopenharmony_ci device = devices; 263141cc406Sopenharmony_ci 264141cc406Sopenharmony_ci /* we build a list of SANE_Device from the list of attached devices */ 265141cc406Sopenharmony_ci for (i = 0; i < devnr; i++) 266141cc406Sopenharmony_ci { 267141cc406Sopenharmony_ci /* add device according to local only flag */ 268141cc406Sopenharmony_ci if ((local_only == SANE_TRUE && device->local == SANE_TRUE) 269141cc406Sopenharmony_ci || local_only == SANE_FALSE) 270141cc406Sopenharmony_ci { 271141cc406Sopenharmony_ci /* allocate memory to add the device */ 272141cc406Sopenharmony_ci sane_device = malloc (sizeof (*sane_device)); 273141cc406Sopenharmony_ci if (!sane_device) 274141cc406Sopenharmony_ci { 275141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 276141cc406Sopenharmony_ci } 277141cc406Sopenharmony_ci 278141cc406Sopenharmony_ci /* copy data */ 279141cc406Sopenharmony_ci sane_device->name = device->name; 280141cc406Sopenharmony_ci sane_device->vendor = device->model->vendor; 281141cc406Sopenharmony_ci sane_device->model = device->model->product; 282141cc406Sopenharmony_ci sane_device->type = device->model->type; 283141cc406Sopenharmony_ci devlist[dev_num] = sane_device; 284141cc406Sopenharmony_ci 285141cc406Sopenharmony_ci /* increment device counter */ 286141cc406Sopenharmony_ci dev_num++; 287141cc406Sopenharmony_ci } 288141cc406Sopenharmony_ci 289141cc406Sopenharmony_ci /* go to next detected device */ 290141cc406Sopenharmony_ci device = device->next; 291141cc406Sopenharmony_ci } 292141cc406Sopenharmony_ci devlist[dev_num] = 0; 293141cc406Sopenharmony_ci 294141cc406Sopenharmony_ci *device_list = devlist; 295141cc406Sopenharmony_ci 296141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_devices: exit\n"); 297141cc406Sopenharmony_ci 298141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 299141cc406Sopenharmony_ci} 300141cc406Sopenharmony_ci 301141cc406Sopenharmony_ci 302141cc406Sopenharmony_ci/** 303141cc406Sopenharmony_ci * Called to establish connection with the session. This function will 304141cc406Sopenharmony_ci * also establish meaningful defaults and initialize the options. 305141cc406Sopenharmony_ci * 306141cc406Sopenharmony_ci * From the SANE spec: 307141cc406Sopenharmony_ci * This function is used to establish a connection to a particular 308141cc406Sopenharmony_ci * device. The name of the device to be opened is passed in argument 309141cc406Sopenharmony_ci * name. If the call completes successfully, a handle for the device 310141cc406Sopenharmony_ci * is returned in *h. As a special case, specifying a zero-length 311141cc406Sopenharmony_ci * string as the device requests opening the first available device 312141cc406Sopenharmony_ci * (if there is such a device). Another special case is to only give 313141cc406Sopenharmony_ci * the name of the backend as the device name, in this case the first 314141cc406Sopenharmony_ci * available device will also be used. 315141cc406Sopenharmony_ci * @param name name of the device to open 316141cc406Sopenharmony_ci * @param handle opaque pointer where to store the pointer of 317141cc406Sopenharmony_ci * the opened P5_Session 318141cc406Sopenharmony_ci * @return SANE_STATUS_GOOD on success 319141cc406Sopenharmony_ci */ 320141cc406Sopenharmony_ciSANE_Status 321141cc406Sopenharmony_cisane_open (SANE_String_Const name, SANE_Handle * handle) 322141cc406Sopenharmony_ci{ 323141cc406Sopenharmony_ci struct P5_Session *session = NULL; 324141cc406Sopenharmony_ci struct P5_Device *device = NULL; 325141cc406Sopenharmony_ci 326141cc406Sopenharmony_ci DBG (DBG_proc, "sane_open: start (devicename=%s)\n", name); 327141cc406Sopenharmony_ci 328141cc406Sopenharmony_ci /* check there is at least a device */ 329141cc406Sopenharmony_ci if (devices == NULL) 330141cc406Sopenharmony_ci { 331141cc406Sopenharmony_ci DBG (DBG_proc, "sane_open: exit, no device to open!\n"); 332141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 333141cc406Sopenharmony_ci } 334141cc406Sopenharmony_ci 335141cc406Sopenharmony_ci if (name[0] == 0 || strncmp (name, "p5", strlen ("p5")) == 0) 336141cc406Sopenharmony_ci { 337141cc406Sopenharmony_ci DBG (DBG_info, 338141cc406Sopenharmony_ci "sane_open: no specific device requested, using default\n"); 339141cc406Sopenharmony_ci if (devices) 340141cc406Sopenharmony_ci { 341141cc406Sopenharmony_ci device = devices; 342141cc406Sopenharmony_ci DBG (DBG_info, "sane_open: device %s used as default device\n", 343141cc406Sopenharmony_ci device->name); 344141cc406Sopenharmony_ci } 345141cc406Sopenharmony_ci } 346141cc406Sopenharmony_ci else 347141cc406Sopenharmony_ci { 348141cc406Sopenharmony_ci DBG (DBG_info, "sane_open: device %s requested\n", name); 349141cc406Sopenharmony_ci /* walk the device list until we find a matching name */ 350141cc406Sopenharmony_ci device = devices; 351141cc406Sopenharmony_ci while (device && strcmp (device->name, name) != 0) 352141cc406Sopenharmony_ci { 353141cc406Sopenharmony_ci DBG (DBG_trace, "sane_open: device %s doesn't match\n", 354141cc406Sopenharmony_ci device->name); 355141cc406Sopenharmony_ci device = device->next; 356141cc406Sopenharmony_ci } 357141cc406Sopenharmony_ci } 358141cc406Sopenharmony_ci 359141cc406Sopenharmony_ci /* check whether we have found a match or reach the end of the device list */ 360141cc406Sopenharmony_ci if (!device) 361141cc406Sopenharmony_ci { 362141cc406Sopenharmony_ci DBG (DBG_info, "sane_open: no device found\n"); 363141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 364141cc406Sopenharmony_ci } 365141cc406Sopenharmony_ci 366141cc406Sopenharmony_ci /* now we have a device, duplicate it and return it in handle */ 367141cc406Sopenharmony_ci DBG (DBG_info, "sane_open: device %s found\n", name); 368141cc406Sopenharmony_ci 369141cc406Sopenharmony_ci /* device initialization */ 370141cc406Sopenharmony_ci if (device->initialized == SANE_FALSE) 371141cc406Sopenharmony_ci { 372141cc406Sopenharmony_ci /** 373141cc406Sopenharmony_ci * call to hardware initialization function here. 374141cc406Sopenharmony_ci */ 375141cc406Sopenharmony_ci device->fd = open_pp (device->name); 376141cc406Sopenharmony_ci if (device->fd < 0) 377141cc406Sopenharmony_ci { 378141cc406Sopenharmony_ci DBG (DBG_error, "sane_open: failed to open '%s' device!\n", 379141cc406Sopenharmony_ci device->name); 380141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 381141cc406Sopenharmony_ci } 382141cc406Sopenharmony_ci 383141cc406Sopenharmony_ci /* now try to connect to scanner */ 384141cc406Sopenharmony_ci if (connect (device->fd) != SANE_TRUE) 385141cc406Sopenharmony_ci { 386141cc406Sopenharmony_ci DBG (DBG_error, "sane_open: failed to connect!\n"); 387141cc406Sopenharmony_ci close_pp (device->fd); 388141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 389141cc406Sopenharmony_ci } 390141cc406Sopenharmony_ci 391141cc406Sopenharmony_ci /* load calibration data */ 392141cc406Sopenharmony_ci restore_calibration (device); 393141cc406Sopenharmony_ci 394141cc406Sopenharmony_ci /* device link is OK now */ 395141cc406Sopenharmony_ci device->initialized = SANE_TRUE; 396141cc406Sopenharmony_ci } 397141cc406Sopenharmony_ci device->buffer = NULL; 398141cc406Sopenharmony_ci device->gain = NULL; 399141cc406Sopenharmony_ci device->offset = NULL; 400141cc406Sopenharmony_ci 401141cc406Sopenharmony_ci /* prepare handle to return */ 402141cc406Sopenharmony_ci session = (P5_Session *) malloc (sizeof (P5_Session)); 403141cc406Sopenharmony_ci if (session == NULL) 404141cc406Sopenharmony_ci { 405141cc406Sopenharmony_ci DBG (DBG_proc, "sane_open: exit OOM\n"); 406141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 407141cc406Sopenharmony_ci } 408141cc406Sopenharmony_ci 409141cc406Sopenharmony_ci /* initialize session */ 410141cc406Sopenharmony_ci session->dev = device; 411141cc406Sopenharmony_ci session->scanning = SANE_FALSE; 412141cc406Sopenharmony_ci session->non_blocking = SANE_FALSE; 413141cc406Sopenharmony_ci 414141cc406Sopenharmony_ci /* initialize SANE options for this session */ 415141cc406Sopenharmony_ci init_options (session); 416141cc406Sopenharmony_ci 417141cc406Sopenharmony_ci /* add the handle to the linked list of sessions */ 418141cc406Sopenharmony_ci session->next = sessions; 419141cc406Sopenharmony_ci sessions = session; 420141cc406Sopenharmony_ci 421141cc406Sopenharmony_ci /* store result */ 422141cc406Sopenharmony_ci *handle = session; 423141cc406Sopenharmony_ci 424141cc406Sopenharmony_ci /* exit success */ 425141cc406Sopenharmony_ci DBG (DBG_proc, "sane_open: exit\n"); 426141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 427141cc406Sopenharmony_ci} 428141cc406Sopenharmony_ci 429141cc406Sopenharmony_ci 430141cc406Sopenharmony_ci/** 431141cc406Sopenharmony_ci * Set non blocking mode. In this mode, read return immediately when 432141cc406Sopenharmony_ci * no data is available within sane_read(), instead of polling the scanner. 433141cc406Sopenharmony_ci */ 434141cc406Sopenharmony_ciSANE_Status 435141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 436141cc406Sopenharmony_ci{ 437141cc406Sopenharmony_ci P5_Session *session = (P5_Session *) handle; 438141cc406Sopenharmony_ci 439141cc406Sopenharmony_ci DBG (DBG_proc, "sane_set_io_mode: start\n"); 440141cc406Sopenharmony_ci if (session->scanning != SANE_TRUE) 441141cc406Sopenharmony_ci { 442141cc406Sopenharmony_ci DBG (DBG_error, "sane_set_io_mode: called out of a scan\n"); 443141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 444141cc406Sopenharmony_ci } 445141cc406Sopenharmony_ci session->non_blocking = non_blocking; 446141cc406Sopenharmony_ci DBG (DBG_info, "sane_set_io_mode: I/O mode set to %sblocking.\n", 447141cc406Sopenharmony_ci non_blocking ? "non " : " "); 448141cc406Sopenharmony_ci DBG (DBG_proc, "sane_set_io_mode: exit\n"); 449141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 450141cc406Sopenharmony_ci} 451141cc406Sopenharmony_ci 452141cc406Sopenharmony_ci 453141cc406Sopenharmony_ci/** 454141cc406Sopenharmony_ci * An advanced method we don't support but have to define. At SANE API 455141cc406Sopenharmony_ci * level this function is meant to provide a file descriptor on which the 456141cc406Sopenharmony_ci * frontend can do select()/poll() to wait for data. 457141cc406Sopenharmony_ci */ 458141cc406Sopenharmony_ciSANE_Status 459141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fdp) 460141cc406Sopenharmony_ci{ 461141cc406Sopenharmony_ci /* make compiler happy ... */ 462141cc406Sopenharmony_ci (void) handle; 463141cc406Sopenharmony_ci (void) fdp; 464141cc406Sopenharmony_ci 465141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_select_fd: start\n"); 466141cc406Sopenharmony_ci DBG (DBG_warn, "sane_get_select_fd: unsupported ...\n"); 467141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_select_fd: exit\n"); 468141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 469141cc406Sopenharmony_ci} 470141cc406Sopenharmony_ci 471141cc406Sopenharmony_ci 472141cc406Sopenharmony_ci/** 473141cc406Sopenharmony_ci * Returns the options we know. 474141cc406Sopenharmony_ci * 475141cc406Sopenharmony_ci * From the SANE spec: 476141cc406Sopenharmony_ci * This function is used to access option descriptors. The function 477141cc406Sopenharmony_ci * returns the option descriptor for option number n of the device 478141cc406Sopenharmony_ci * represented by handle h. Option number 0 is guaranteed to be a 479141cc406Sopenharmony_ci * valid option. Its value is an integer that specifies the number of 480141cc406Sopenharmony_ci * options that are available for device handle h (the count includes 481141cc406Sopenharmony_ci * option 0). If n is not a valid option index, the function returns 482141cc406Sopenharmony_ci * NULL. The returned option descriptor is guaranteed to remain valid 483141cc406Sopenharmony_ci * (and at the returned address) until the device is closed. 484141cc406Sopenharmony_ci */ 485141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 486141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 487141cc406Sopenharmony_ci{ 488141cc406Sopenharmony_ci struct P5_Session *session = handle; 489141cc406Sopenharmony_ci 490141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_option_descriptor: start\n"); 491141cc406Sopenharmony_ci 492141cc406Sopenharmony_ci if ((unsigned) option >= NUM_OPTIONS) 493141cc406Sopenharmony_ci return NULL; 494141cc406Sopenharmony_ci 495141cc406Sopenharmony_ci DBG (DBG_info, "sane_get_option_descriptor: \"%s\"\n", 496141cc406Sopenharmony_ci session->options[option].descriptor.name); 497141cc406Sopenharmony_ci 498141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_option_descriptor: exit\n"); 499141cc406Sopenharmony_ci return &(session->options[option].descriptor); 500141cc406Sopenharmony_ci} 501141cc406Sopenharmony_ci 502141cc406Sopenharmony_ci/** 503141cc406Sopenharmony_ci * sets automatic value for an option , called by sane_control_option after 504141cc406Sopenharmony_ci * all checks have been done */ 505141cc406Sopenharmony_cistatic SANE_Status 506141cc406Sopenharmony_ciset_automatic_value (P5_Session * s, int option, SANE_Int * myinfo) 507141cc406Sopenharmony_ci{ 508141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 509141cc406Sopenharmony_ci SANE_Int i, min; 510141cc406Sopenharmony_ci SANE_Word *dpi_list; 511141cc406Sopenharmony_ci 512141cc406Sopenharmony_ci switch (option) 513141cc406Sopenharmony_ci { 514141cc406Sopenharmony_ci case OPT_TL_X: 515141cc406Sopenharmony_ci s->options[OPT_TL_X].value.w = x_range.min; 516141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS; 517141cc406Sopenharmony_ci break; 518141cc406Sopenharmony_ci case OPT_TL_Y: 519141cc406Sopenharmony_ci s->options[OPT_TL_Y].value.w = y_range.min; 520141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS; 521141cc406Sopenharmony_ci break; 522141cc406Sopenharmony_ci case OPT_BR_X: 523141cc406Sopenharmony_ci s->options[OPT_BR_X].value.w = x_range.max; 524141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS; 525141cc406Sopenharmony_ci break; 526141cc406Sopenharmony_ci case OPT_BR_Y: 527141cc406Sopenharmony_ci s->options[OPT_BR_Y].value.w = y_range.max; 528141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS; 529141cc406Sopenharmony_ci break; 530141cc406Sopenharmony_ci case OPT_RESOLUTION: 531141cc406Sopenharmony_ci /* we set up to the lowest available dpi value */ 532141cc406Sopenharmony_ci dpi_list = 533141cc406Sopenharmony_ci (SANE_Word *) s->options[OPT_RESOLUTION].descriptor.constraint. 534141cc406Sopenharmony_ci word_list; 535141cc406Sopenharmony_ci min = 65536; 536141cc406Sopenharmony_ci for (i = 1; i < dpi_list[0]; i++) 537141cc406Sopenharmony_ci { 538141cc406Sopenharmony_ci if (dpi_list[i] < min) 539141cc406Sopenharmony_ci min = dpi_list[i]; 540141cc406Sopenharmony_ci } 541141cc406Sopenharmony_ci s->options[OPT_RESOLUTION].value.w = min; 542141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS; 543141cc406Sopenharmony_ci break; 544141cc406Sopenharmony_ci case OPT_PREVIEW: 545141cc406Sopenharmony_ci s->options[OPT_PREVIEW].value.w = SANE_FALSE; 546141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS; 547141cc406Sopenharmony_ci break; 548141cc406Sopenharmony_ci case OPT_MODE: 549141cc406Sopenharmony_ci if (s->options[OPT_MODE].value.s) 550141cc406Sopenharmony_ci free (s->options[OPT_MODE].value.s); 551141cc406Sopenharmony_ci s->options[OPT_MODE].value.s = strdup (mode_list[0]); 552141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_OPTIONS; 553141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS; 554141cc406Sopenharmony_ci break; 555141cc406Sopenharmony_ci default: 556141cc406Sopenharmony_ci DBG (DBG_warn, "set_automatic_value: can't set unknown option %d\n", 557141cc406Sopenharmony_ci option); 558141cc406Sopenharmony_ci } 559141cc406Sopenharmony_ci 560141cc406Sopenharmony_ci return status; 561141cc406Sopenharmony_ci} 562141cc406Sopenharmony_ci 563141cc406Sopenharmony_ci/** 564141cc406Sopenharmony_ci * sets an option , called by sane_control_option after all 565141cc406Sopenharmony_ci * checks have been done */ 566141cc406Sopenharmony_cistatic SANE_Status 567141cc406Sopenharmony_ciset_option_value (P5_Session * s, int option, void *val, SANE_Int * myinfo) 568141cc406Sopenharmony_ci{ 569141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 570141cc406Sopenharmony_ci SANE_Word tmpw; 571141cc406Sopenharmony_ci 572141cc406Sopenharmony_ci switch (option) 573141cc406Sopenharmony_ci { 574141cc406Sopenharmony_ci case OPT_TL_X: 575141cc406Sopenharmony_ci case OPT_BR_X: 576141cc406Sopenharmony_ci case OPT_TL_Y: 577141cc406Sopenharmony_ci case OPT_BR_Y: 578141cc406Sopenharmony_ci s->options[option].value.w = *(SANE_Word *) val; 579141cc406Sopenharmony_ci /* we ensure geometry is coherent */ 580141cc406Sopenharmony_ci /* this happens when user drags TL corner right or below the BR point */ 581141cc406Sopenharmony_ci if (s->options[OPT_BR_Y].value.w < s->options[OPT_TL_Y].value.w) 582141cc406Sopenharmony_ci { 583141cc406Sopenharmony_ci tmpw = s->options[OPT_BR_Y].value.w; 584141cc406Sopenharmony_ci s->options[OPT_BR_Y].value.w = s->options[OPT_TL_Y].value.w; 585141cc406Sopenharmony_ci s->options[OPT_TL_Y].value.w = tmpw; 586141cc406Sopenharmony_ci } 587141cc406Sopenharmony_ci if (s->options[OPT_BR_X].value.w < s->options[OPT_TL_X].value.w) 588141cc406Sopenharmony_ci { 589141cc406Sopenharmony_ci tmpw = s->options[OPT_BR_X].value.w; 590141cc406Sopenharmony_ci s->options[OPT_BR_X].value.w = s->options[OPT_TL_X].value.w; 591141cc406Sopenharmony_ci s->options[OPT_TL_X].value.w = tmpw; 592141cc406Sopenharmony_ci } 593141cc406Sopenharmony_ci 594141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS; 595141cc406Sopenharmony_ci break; 596141cc406Sopenharmony_ci 597141cc406Sopenharmony_ci case OPT_RESOLUTION: 598141cc406Sopenharmony_ci case OPT_PREVIEW: 599141cc406Sopenharmony_ci s->options[option].value.w = *(SANE_Word *) val; 600141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS; 601141cc406Sopenharmony_ci break; 602141cc406Sopenharmony_ci 603141cc406Sopenharmony_ci case OPT_MODE: 604141cc406Sopenharmony_ci if (s->options[option].value.s) 605141cc406Sopenharmony_ci free (s->options[option].value.s); 606141cc406Sopenharmony_ci s->options[option].value.s = strdup (val); 607141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 608141cc406Sopenharmony_ci break; 609141cc406Sopenharmony_ci 610141cc406Sopenharmony_ci case OPT_CALIBRATE: 611141cc406Sopenharmony_ci status = sheetfed_calibration (s->dev); 612141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_OPTIONS; 613141cc406Sopenharmony_ci break; 614141cc406Sopenharmony_ci 615141cc406Sopenharmony_ci case OPT_CLEAR_CALIBRATION: 616141cc406Sopenharmony_ci cleanup_calibration (s->dev); 617141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_OPTIONS; 618141cc406Sopenharmony_ci break; 619141cc406Sopenharmony_ci 620141cc406Sopenharmony_ci default: 621141cc406Sopenharmony_ci DBG (DBG_warn, "set_option_value: can't set unknown option %d\n", 622141cc406Sopenharmony_ci option); 623141cc406Sopenharmony_ci } 624141cc406Sopenharmony_ci return status; 625141cc406Sopenharmony_ci} 626141cc406Sopenharmony_ci 627141cc406Sopenharmony_ci/** 628141cc406Sopenharmony_ci * gets an option , called by sane_control_option after all checks 629141cc406Sopenharmony_ci * have been done */ 630141cc406Sopenharmony_cistatic SANE_Status 631141cc406Sopenharmony_ciget_option_value (P5_Session * s, int option, void *val) 632141cc406Sopenharmony_ci{ 633141cc406Sopenharmony_ci SANE_Status status; 634141cc406Sopenharmony_ci 635141cc406Sopenharmony_ci switch (option) 636141cc406Sopenharmony_ci { 637141cc406Sopenharmony_ci /* word or word equivalent options: */ 638141cc406Sopenharmony_ci case OPT_NUM_OPTS: 639141cc406Sopenharmony_ci case OPT_RESOLUTION: 640141cc406Sopenharmony_ci case OPT_PREVIEW: 641141cc406Sopenharmony_ci case OPT_TL_X: 642141cc406Sopenharmony_ci case OPT_TL_Y: 643141cc406Sopenharmony_ci case OPT_BR_X: 644141cc406Sopenharmony_ci case OPT_BR_Y: 645141cc406Sopenharmony_ci *(SANE_Word *) val = s->options[option].value.w; 646141cc406Sopenharmony_ci break; 647141cc406Sopenharmony_ci 648141cc406Sopenharmony_ci /* string options: */ 649141cc406Sopenharmony_ci case OPT_MODE: 650141cc406Sopenharmony_ci strcpy (val, s->options[option].value.s); 651141cc406Sopenharmony_ci break; 652141cc406Sopenharmony_ci 653141cc406Sopenharmony_ci /* sensor options */ 654141cc406Sopenharmony_ci case OPT_PAGE_LOADED_SW: 655141cc406Sopenharmony_ci status = test_document (s->dev->fd); 656141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) 657141cc406Sopenharmony_ci s->options[option].value.b = SANE_TRUE; 658141cc406Sopenharmony_ci else 659141cc406Sopenharmony_ci s->options[option].value.b = SANE_FALSE; 660141cc406Sopenharmony_ci *(SANE_Bool *) val = s->options[option].value.b; 661141cc406Sopenharmony_ci break; 662141cc406Sopenharmony_ci 663141cc406Sopenharmony_ci case OPT_NEED_CALIBRATION_SW: 664141cc406Sopenharmony_ci *(SANE_Bool *) val = !s->dev->calibrated; 665141cc406Sopenharmony_ci break; 666141cc406Sopenharmony_ci 667141cc406Sopenharmony_ci 668141cc406Sopenharmony_ci /* unhandled options */ 669141cc406Sopenharmony_ci default: 670141cc406Sopenharmony_ci DBG (DBG_warn, "get_option_value: can't get unknown option %d\n", 671141cc406Sopenharmony_ci option); 672141cc406Sopenharmony_ci } 673141cc406Sopenharmony_ci 674141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 675141cc406Sopenharmony_ci} 676141cc406Sopenharmony_ci 677141cc406Sopenharmony_ci/** 678141cc406Sopenharmony_ci * Gets or sets an option value. 679141cc406Sopenharmony_ci * 680141cc406Sopenharmony_ci * From the SANE spec: 681141cc406Sopenharmony_ci * This function is used to set or inquire the current value of option 682141cc406Sopenharmony_ci * number n of the device represented by handle h. The manner in which 683141cc406Sopenharmony_ci * the option is controlled is specified by parameter action. The 684141cc406Sopenharmony_ci * possible values of this parameter are described in more detail 685141cc406Sopenharmony_ci * below. The value of the option is passed through argument val. It 686141cc406Sopenharmony_ci * is a pointer to the memory that holds the option value. The memory 687141cc406Sopenharmony_ci * area pointed to by v must be big enough to hold the entire option 688141cc406Sopenharmony_ci * value (determined by member size in the corresponding option 689141cc406Sopenharmony_ci * descriptor). 690141cc406Sopenharmony_ci * 691141cc406Sopenharmony_ci * The only exception to this rule is that when setting the value of a 692141cc406Sopenharmony_ci * string option, the string pointed to by argument v may be shorter 693141cc406Sopenharmony_ci * since the backend will stop reading the option value upon 694141cc406Sopenharmony_ci * encountering the first NUL terminator in the string. If argument i 695141cc406Sopenharmony_ci * is not NULL, the value of *i will be set to provide details on how 696141cc406Sopenharmony_ci * well the request has been met. 697141cc406Sopenharmony_ci * action is SANE_ACTION_GET_VALUE, SANE_ACTION_SET_VALUE or SANE_ACTION_SET_AUTO 698141cc406Sopenharmony_ci */ 699141cc406Sopenharmony_ciSANE_Status 700141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 701141cc406Sopenharmony_ci SANE_Action action, void *val, SANE_Int * info) 702141cc406Sopenharmony_ci{ 703141cc406Sopenharmony_ci P5_Session *s = handle; 704141cc406Sopenharmony_ci SANE_Status status; 705141cc406Sopenharmony_ci SANE_Word cap; 706141cc406Sopenharmony_ci SANE_Int myinfo = 0; 707141cc406Sopenharmony_ci 708141cc406Sopenharmony_ci DBG (DBG_io2, 709141cc406Sopenharmony_ci "sane_control_option: start: action = %s, option = %s (%d)\n", 710141cc406Sopenharmony_ci (action == SANE_ACTION_GET_VALUE) ? "get" : (action == 711141cc406Sopenharmony_ci SANE_ACTION_SET_VALUE) ? 712141cc406Sopenharmony_ci "set" : (action == SANE_ACTION_SET_AUTO) ? "set_auto" : "unknown", 713141cc406Sopenharmony_ci s->options[option].descriptor.name, option); 714141cc406Sopenharmony_ci 715141cc406Sopenharmony_ci if (info) 716141cc406Sopenharmony_ci *info = 0; 717141cc406Sopenharmony_ci 718141cc406Sopenharmony_ci /* do checks before trying to apply action */ 719141cc406Sopenharmony_ci 720141cc406Sopenharmony_ci if (s->scanning) 721141cc406Sopenharmony_ci { 722141cc406Sopenharmony_ci DBG (DBG_warn, "sane_control_option: don't call this function while " 723141cc406Sopenharmony_ci "scanning (option = %s (%d))\n", 724141cc406Sopenharmony_ci s->options[option].descriptor.name, option); 725141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 726141cc406Sopenharmony_ci } 727141cc406Sopenharmony_ci 728141cc406Sopenharmony_ci /* option must be within existing range */ 729141cc406Sopenharmony_ci if (option >= NUM_OPTIONS || option < 0) 730141cc406Sopenharmony_ci { 731141cc406Sopenharmony_ci DBG (DBG_warn, 732141cc406Sopenharmony_ci "sane_control_option: option %d >= NUM_OPTIONS || option < 0\n", 733141cc406Sopenharmony_ci option); 734141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 735141cc406Sopenharmony_ci } 736141cc406Sopenharmony_ci 737141cc406Sopenharmony_ci /* don't access an inactive option */ 738141cc406Sopenharmony_ci cap = s->options[option].descriptor.cap; 739141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (cap)) 740141cc406Sopenharmony_ci { 741141cc406Sopenharmony_ci DBG (DBG_warn, "sane_control_option: option %d is inactive\n", option); 742141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 743141cc406Sopenharmony_ci } 744141cc406Sopenharmony_ci 745141cc406Sopenharmony_ci /* now checks have been done, apply action */ 746141cc406Sopenharmony_ci switch (action) 747141cc406Sopenharmony_ci { 748141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 749141cc406Sopenharmony_ci status = get_option_value (s, option, val); 750141cc406Sopenharmony_ci break; 751141cc406Sopenharmony_ci 752141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 753141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (cap)) 754141cc406Sopenharmony_ci { 755141cc406Sopenharmony_ci DBG (DBG_warn, "sane_control_option: option %d is not settable\n", 756141cc406Sopenharmony_ci option); 757141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 758141cc406Sopenharmony_ci } 759141cc406Sopenharmony_ci 760141cc406Sopenharmony_ci status = 761141cc406Sopenharmony_ci sanei_constrain_value (&s->options[option].descriptor, val, &myinfo); 762141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 763141cc406Sopenharmony_ci { 764141cc406Sopenharmony_ci DBG (DBG_warn, 765141cc406Sopenharmony_ci "sane_control_option: sanei_constrain_value returned %s\n", 766141cc406Sopenharmony_ci sane_strstatus (status)); 767141cc406Sopenharmony_ci return status; 768141cc406Sopenharmony_ci } 769141cc406Sopenharmony_ci 770141cc406Sopenharmony_ci /* return immediately if no change */ 771141cc406Sopenharmony_ci if (s->options[option].descriptor.type == SANE_TYPE_INT 772141cc406Sopenharmony_ci && *(SANE_Word *) val == s->options[option].value.w) 773141cc406Sopenharmony_ci { 774141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 775141cc406Sopenharmony_ci } 776141cc406Sopenharmony_ci else 777141cc406Sopenharmony_ci { /* apply change */ 778141cc406Sopenharmony_ci status = set_option_value (s, option, val, &myinfo); 779141cc406Sopenharmony_ci } 780141cc406Sopenharmony_ci break; 781141cc406Sopenharmony_ci 782141cc406Sopenharmony_ci case SANE_ACTION_SET_AUTO: 783141cc406Sopenharmony_ci /* sets automatic values */ 784141cc406Sopenharmony_ci if (!(cap & SANE_CAP_AUTOMATIC)) 785141cc406Sopenharmony_ci { 786141cc406Sopenharmony_ci DBG (DBG_warn, 787141cc406Sopenharmony_ci "sane_control_option: option %d is not autosettable\n", 788141cc406Sopenharmony_ci option); 789141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 790141cc406Sopenharmony_ci } 791141cc406Sopenharmony_ci 792141cc406Sopenharmony_ci status = set_automatic_value (s, option, &myinfo); 793141cc406Sopenharmony_ci break; 794141cc406Sopenharmony_ci 795141cc406Sopenharmony_ci default: 796141cc406Sopenharmony_ci DBG (DBG_error, "sane_control_option: invalid action %d\n", action); 797141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 798141cc406Sopenharmony_ci break; 799141cc406Sopenharmony_ci } 800141cc406Sopenharmony_ci 801141cc406Sopenharmony_ci if (info) 802141cc406Sopenharmony_ci *info = myinfo; 803141cc406Sopenharmony_ci 804141cc406Sopenharmony_ci DBG (DBG_io2, "sane_control_option: exit\n"); 805141cc406Sopenharmony_ci return status; 806141cc406Sopenharmony_ci} 807141cc406Sopenharmony_ci 808141cc406Sopenharmony_ci/** 809141cc406Sopenharmony_ci * Called by SANE when a page acquisition operation is to be started. 810141cc406Sopenharmony_ci * @param handle opaque handle to a frontend session 811141cc406Sopenharmony_ci * @return SANE_STATUS_GOOD on success, SANE_STATUS_BUSY if the device is 812141cc406Sopenharmony_ci * in use by another session or SANE_STATUS_WARMING_UP if the device is 813141cc406Sopenharmony_ci * warming up. In this case the fronted as to call sane_start again until 814141cc406Sopenharmony_ci * warming up is done. Any other values returned are error status. 815141cc406Sopenharmony_ci */ 816141cc406Sopenharmony_ciSANE_Status 817141cc406Sopenharmony_cisane_start (SANE_Handle handle) 818141cc406Sopenharmony_ci{ 819141cc406Sopenharmony_ci struct P5_Session *session = handle; 820141cc406Sopenharmony_ci int status = SANE_STATUS_GOOD; 821141cc406Sopenharmony_ci P5_Device *dev = session->dev; 822141cc406Sopenharmony_ci 823141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: start\n"); 824141cc406Sopenharmony_ci 825141cc406Sopenharmony_ci /* if already scanning, tell we're busy */ 826141cc406Sopenharmony_ci if (session->scanning == SANE_TRUE) 827141cc406Sopenharmony_ci { 828141cc406Sopenharmony_ci DBG (DBG_info, "sane_start: device is already scanning\n"); 829141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 830141cc406Sopenharmony_ci } 831141cc406Sopenharmony_ci 832141cc406Sopenharmony_ci /* check that the device has been initialized */ 833141cc406Sopenharmony_ci if (dev->initialized == SANE_FALSE) 834141cc406Sopenharmony_ci { 835141cc406Sopenharmony_ci DBG (DBG_error, "sane_start: device is not initialized\n"); 836141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 837141cc406Sopenharmony_ci } 838141cc406Sopenharmony_ci 839141cc406Sopenharmony_ci /* check if there is a document */ 840141cc406Sopenharmony_ci status = test_document (dev->fd); 841141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 842141cc406Sopenharmony_ci { 843141cc406Sopenharmony_ci DBG (DBG_error, "sane_start: device is already scanning\n"); 844141cc406Sopenharmony_ci return status; 845141cc406Sopenharmony_ci } 846141cc406Sopenharmony_ci 847141cc406Sopenharmony_ci /* we compute all the scan parameters so that */ 848141cc406Sopenharmony_ci /* we will be able to set up the registers correctly */ 849141cc406Sopenharmony_ci compute_parameters (session); 850141cc406Sopenharmony_ci 851141cc406Sopenharmony_ci /* move to scan area if needed */ 852141cc406Sopenharmony_ci if (dev->ystart > 0) 853141cc406Sopenharmony_ci { 854141cc406Sopenharmony_ci status = move (dev); 855141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 856141cc406Sopenharmony_ci { 857141cc406Sopenharmony_ci DBG (DBG_error, "sane_start: failed to move to scan area\n"); 858141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 859141cc406Sopenharmony_ci } 860141cc406Sopenharmony_ci } 861141cc406Sopenharmony_ci 862141cc406Sopenharmony_ci /* send scan command */ 863141cc406Sopenharmony_ci status = start_scan (dev, dev->mode, dev->ydpi, dev->xstart, dev->pixels); 864141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 865141cc406Sopenharmony_ci { 866141cc406Sopenharmony_ci DBG (DBG_error, "sane_start: failed to start scan\n"); 867141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 868141cc406Sopenharmony_ci } 869141cc406Sopenharmony_ci 870141cc406Sopenharmony_ci /* allocates work buffer */ 871141cc406Sopenharmony_ci if (dev->buffer != NULL) 872141cc406Sopenharmony_ci { 873141cc406Sopenharmony_ci free (dev->buffer); 874141cc406Sopenharmony_ci } 875141cc406Sopenharmony_ci 876141cc406Sopenharmony_ci dev->position = 0; 877141cc406Sopenharmony_ci dev->top = 0; 878141cc406Sopenharmony_ci /* compute amount of lines needed for lds correction */ 879141cc406Sopenharmony_ci dev->bottom = dev->bytes_per_line * 2 * dev->lds; 880141cc406Sopenharmony_ci /* computes buffer size, 66 color lines plus eventual amount needed for lds */ 881141cc406Sopenharmony_ci dev->size = dev->pixels * 3 * 66 + dev->bottom; 882141cc406Sopenharmony_ci dev->buffer = (uint8_t *) malloc (dev->size); 883141cc406Sopenharmony_ci if (dev->buffer == NULL) 884141cc406Sopenharmony_ci { 885141cc406Sopenharmony_ci DBG (DBG_error, "sane_start: failed to allocate %lu bytes\n", (unsigned long)dev->size); 886141cc406Sopenharmony_ci sane_cancel (handle); 887141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 888141cc406Sopenharmony_ci } 889141cc406Sopenharmony_ci 890141cc406Sopenharmony_ci /* return now the scan has been initiated */ 891141cc406Sopenharmony_ci session->scanning = SANE_TRUE; 892141cc406Sopenharmony_ci session->sent = 0; 893141cc406Sopenharmony_ci 894141cc406Sopenharmony_ci DBG (DBG_io, "sane_start: to_send=%d\n", session->to_send); 895141cc406Sopenharmony_ci DBG (DBG_io, "sane_start: size=%lu\n", (unsigned long)dev->size); 896141cc406Sopenharmony_ci DBG (DBG_io, "sane_start: top=%lu\n", (unsigned long)dev->top); 897141cc406Sopenharmony_ci DBG (DBG_io, "sane_start: bottom=%lu\n", (unsigned long)dev->bottom); 898141cc406Sopenharmony_ci DBG (DBG_io, "sane_start: position=%lu\n", (unsigned long)dev->position); 899141cc406Sopenharmony_ci 900141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: exit\n"); 901141cc406Sopenharmony_ci return status; 902141cc406Sopenharmony_ci} 903141cc406Sopenharmony_ci 904141cc406Sopenharmony_ci/** @brief compute scan parameters 905141cc406Sopenharmony_ci * This function computes two set of parameters. The one for the SANE's standard 906141cc406Sopenharmony_ci * and the other for the hardware. Among these parameters are the bit depth, total 907141cc406Sopenharmony_ci * number of lines, total number of columns, extra line to read for data reordering... 908141cc406Sopenharmony_ci * @param session fronted session to compute final scan parameters 909141cc406Sopenharmony_ci * @return SANE_STATUS_GOOD on success 910141cc406Sopenharmony_ci */ 911141cc406Sopenharmony_cistatic SANE_Status 912141cc406Sopenharmony_cicompute_parameters (P5_Session * session) 913141cc406Sopenharmony_ci{ 914141cc406Sopenharmony_ci P5_Device *dev = session->dev; 915141cc406Sopenharmony_ci SANE_Int dpi; /* dpi for scan */ 916141cc406Sopenharmony_ci SANE_String mode; 917141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 918141cc406Sopenharmony_ci 919141cc406Sopenharmony_ci int tl_x, tl_y, br_x, br_y; 920141cc406Sopenharmony_ci 921141cc406Sopenharmony_ci mode = session->options[OPT_MODE].value.s; 922141cc406Sopenharmony_ci dpi = session->options[OPT_RESOLUTION].value.w; 923141cc406Sopenharmony_ci 924141cc406Sopenharmony_ci /* scan coordinates */ 925141cc406Sopenharmony_ci tl_x = SANE_UNFIX (session->options[OPT_TL_X].value.w); 926141cc406Sopenharmony_ci tl_y = SANE_UNFIX (session->options[OPT_TL_Y].value.w); 927141cc406Sopenharmony_ci br_x = SANE_UNFIX (session->options[OPT_BR_X].value.w); 928141cc406Sopenharmony_ci br_y = SANE_UNFIX (session->options[OPT_BR_Y].value.w); 929141cc406Sopenharmony_ci 930141cc406Sopenharmony_ci /* only single pass scanning supported */ 931141cc406Sopenharmony_ci session->params.last_frame = SANE_TRUE; 932141cc406Sopenharmony_ci 933141cc406Sopenharmony_ci /* gray modes */ 934141cc406Sopenharmony_ci if (strcmp (mode, GRAY_MODE) == 0) 935141cc406Sopenharmony_ci { 936141cc406Sopenharmony_ci session->params.format = SANE_FRAME_GRAY; 937141cc406Sopenharmony_ci dev->mode = MODE_GRAY; 938141cc406Sopenharmony_ci dev->lds = 0; 939141cc406Sopenharmony_ci } 940141cc406Sopenharmony_ci else if (strcmp (mode, LINEART_MODE) == 0) 941141cc406Sopenharmony_ci { 942141cc406Sopenharmony_ci session->params.format = SANE_FRAME_GRAY; 943141cc406Sopenharmony_ci dev->mode = MODE_LINEART; 944141cc406Sopenharmony_ci dev->lds = 0; 945141cc406Sopenharmony_ci } 946141cc406Sopenharmony_ci else 947141cc406Sopenharmony_ci { 948141cc406Sopenharmony_ci /* Color */ 949141cc406Sopenharmony_ci session->params.format = SANE_FRAME_RGB; 950141cc406Sopenharmony_ci dev->mode = MODE_COLOR; 951141cc406Sopenharmony_ci dev->lds = (dev->model->lds * dpi) / dev->model->max_ydpi; 952141cc406Sopenharmony_ci } 953141cc406Sopenharmony_ci 954141cc406Sopenharmony_ci /* SANE level values */ 955141cc406Sopenharmony_ci session->params.lines = ((br_y - tl_y) * dpi) / MM_PER_INCH; 956141cc406Sopenharmony_ci if (session->params.lines == 0) 957141cc406Sopenharmony_ci session->params.lines = 1; 958141cc406Sopenharmony_ci session->params.pixels_per_line = ((br_x - tl_x) * dpi) / MM_PER_INCH; 959141cc406Sopenharmony_ci if (session->params.pixels_per_line == 0) 960141cc406Sopenharmony_ci session->params.pixels_per_line = 1; 961141cc406Sopenharmony_ci 962141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: pixels_per_line =%d\n", 963141cc406Sopenharmony_ci session->params.pixels_per_line); 964141cc406Sopenharmony_ci 965141cc406Sopenharmony_ci if (strcmp (mode, LINEART_MODE) == 0) 966141cc406Sopenharmony_ci { 967141cc406Sopenharmony_ci session->params.depth = 1; 968141cc406Sopenharmony_ci /* in lineart, having pixels multiple of 8 avoids a costly test */ 969141cc406Sopenharmony_ci /* at each bit to see we must go to the next byte */ 970141cc406Sopenharmony_ci /* TODO : implement this requirement in sane_control_option */ 971141cc406Sopenharmony_ci session->params.pixels_per_line = 972141cc406Sopenharmony_ci ((session->params.pixels_per_line + 7) / 8) * 8; 973141cc406Sopenharmony_ci } 974141cc406Sopenharmony_ci else 975141cc406Sopenharmony_ci session->params.depth = 8; 976141cc406Sopenharmony_ci 977141cc406Sopenharmony_ci /* width needs to be even */ 978141cc406Sopenharmony_ci if (session->params.pixels_per_line & 1) 979141cc406Sopenharmony_ci session->params.pixels_per_line++; 980141cc406Sopenharmony_ci 981141cc406Sopenharmony_ci /* Hardware settings : they can differ from the ones at SANE level */ 982141cc406Sopenharmony_ci /* for instance the effective DPI used by a sensor may be higher */ 983141cc406Sopenharmony_ci /* than the one needed for the SANE scan parameters */ 984141cc406Sopenharmony_ci dev->lines = session->params.lines; 985141cc406Sopenharmony_ci dev->pixels = session->params.pixels_per_line; 986141cc406Sopenharmony_ci 987141cc406Sopenharmony_ci /* motor and sensor DPI */ 988141cc406Sopenharmony_ci dev->xdpi = dpi; 989141cc406Sopenharmony_ci dev->ydpi = dpi; 990141cc406Sopenharmony_ci 991141cc406Sopenharmony_ci /* handle bounds of motor's dpi range */ 992141cc406Sopenharmony_ci if (dev->ydpi > dev->model->max_ydpi) 993141cc406Sopenharmony_ci { 994141cc406Sopenharmony_ci dev->ydpi = dev->model->max_ydpi; 995141cc406Sopenharmony_ci dev->lines = (dev->lines * dev->model->max_ydpi) / dpi; 996141cc406Sopenharmony_ci if (dev->lines == 0) 997141cc406Sopenharmony_ci dev->lines = 1; 998141cc406Sopenharmony_ci 999141cc406Sopenharmony_ci /* round number of lines */ 1000141cc406Sopenharmony_ci session->params.lines = 1001141cc406Sopenharmony_ci (session->params.lines / dev->lines) * dev->lines; 1002141cc406Sopenharmony_ci if (session->params.lines == 0) 1003141cc406Sopenharmony_ci session->params.lines = 1; 1004141cc406Sopenharmony_ci } 1005141cc406Sopenharmony_ci if (dev->ydpi < dev->model->min_ydpi) 1006141cc406Sopenharmony_ci { 1007141cc406Sopenharmony_ci dev->ydpi = dev->model->min_ydpi; 1008141cc406Sopenharmony_ci dev->lines = (dev->lines * dev->model->min_ydpi) / dpi; 1009141cc406Sopenharmony_ci } 1010141cc406Sopenharmony_ci 1011141cc406Sopenharmony_ci /* hardware values */ 1012141cc406Sopenharmony_ci dev->xstart = 1013141cc406Sopenharmony_ci ((SANE_UNFIX (dev->model->x_offset) + tl_x) * dpi) / MM_PER_INCH; 1014141cc406Sopenharmony_ci dev->ystart = 1015141cc406Sopenharmony_ci ((SANE_UNFIX (dev->model->y_offset) + tl_y) * dev->ydpi) / MM_PER_INCH; 1016141cc406Sopenharmony_ci 1017141cc406Sopenharmony_ci /* take lds correction into account when moving to scan area */ 1018141cc406Sopenharmony_ci if (dev->ystart > 2 * dev->lds) 1019141cc406Sopenharmony_ci dev->ystart -= 2 * dev->lds; 1020141cc406Sopenharmony_ci 1021141cc406Sopenharmony_ci 1022141cc406Sopenharmony_ci /* computes bytes per line */ 1023141cc406Sopenharmony_ci session->params.bytes_per_line = session->params.pixels_per_line; 1024141cc406Sopenharmony_ci dev->bytes_per_line = dev->pixels; 1025141cc406Sopenharmony_ci if (session->params.format == SANE_FRAME_RGB) 1026141cc406Sopenharmony_ci { 1027141cc406Sopenharmony_ci dev->bytes_per_line *= 3; 1028141cc406Sopenharmony_ci } 1029141cc406Sopenharmony_ci 1030141cc406Sopenharmony_ci /* in lineart mode we adjust bytes_per_line needed by frontend */ 1031141cc406Sopenharmony_ci /* we do that here because we needed sent/to_send to be as if */ 1032141cc406Sopenharmony_ci /* there was no lineart */ 1033141cc406Sopenharmony_ci if (session->params.depth == 1) 1034141cc406Sopenharmony_ci { 1035141cc406Sopenharmony_ci session->params.bytes_per_line = 1036141cc406Sopenharmony_ci (session->params.bytes_per_line + 7) / 8; 1037141cc406Sopenharmony_ci } 1038141cc406Sopenharmony_ci 1039141cc406Sopenharmony_ci session->params.bytes_per_line = dev->bytes_per_line; 1040141cc406Sopenharmony_ci session->to_send = session->params.bytes_per_line * session->params.lines; 1041141cc406Sopenharmony_ci session->params.bytes_per_line = dev->bytes_per_line; 1042141cc406Sopenharmony_ci 1043141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: bytes_per_line =%d\n", 1044141cc406Sopenharmony_ci session->params.bytes_per_line); 1045141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: depth =%d\n", 1046141cc406Sopenharmony_ci session->params.depth); 1047141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: lines =%d\n", 1048141cc406Sopenharmony_ci session->params.lines); 1049141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: image size =%d\n", 1050141cc406Sopenharmony_ci session->to_send); 1051141cc406Sopenharmony_ci 1052141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: xstart =%d\n", dev->xstart); 1053141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: ystart =%d\n", dev->ystart); 1054141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: dev lines =%d\n", dev->lines); 1055141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: dev bytes per line=%d\n", 1056141cc406Sopenharmony_ci dev->bytes_per_line); 1057141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: dev pixels =%d\n", dev->pixels); 1058141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: lds =%d\n", dev->lds); 1059141cc406Sopenharmony_ci 1060141cc406Sopenharmony_ci return status; 1061141cc406Sopenharmony_ci} 1062141cc406Sopenharmony_ci 1063141cc406Sopenharmony_ci 1064141cc406Sopenharmony_ci/** 1065141cc406Sopenharmony_ci * Called by SANE to retrieve information about the type of data 1066141cc406Sopenharmony_ci * that the current scan will return. 1067141cc406Sopenharmony_ci * 1068141cc406Sopenharmony_ci * From the SANE spec: 1069141cc406Sopenharmony_ci * This function is used to obtain the current scan parameters. The 1070141cc406Sopenharmony_ci * returned parameters are guaranteed to be accurate between the time 1071141cc406Sopenharmony_ci * a scan has been started (sane_start() has been called) and the 1072141cc406Sopenharmony_ci * completion of that request. Outside of that window, the returned 1073141cc406Sopenharmony_ci * values are best-effort estimates of what the parameters will be 1074141cc406Sopenharmony_ci * when sane_start() gets invoked. 1075141cc406Sopenharmony_ci * 1076141cc406Sopenharmony_ci * Calling this function before a scan has actually started allows, 1077141cc406Sopenharmony_ci * for example, to get an estimate of how big the scanned image will 1078141cc406Sopenharmony_ci * be. The parameters passed to this function are the handle of the 1079141cc406Sopenharmony_ci * device for which the parameters should be obtained and a pointer 1080141cc406Sopenharmony_ci * to a parameter structure. 1081141cc406Sopenharmony_ci */ 1082141cc406Sopenharmony_ciSANE_Status 1083141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 1084141cc406Sopenharmony_ci{ 1085141cc406Sopenharmony_ci SANE_Status status; 1086141cc406Sopenharmony_ci struct P5_Session *session = (struct P5_Session *) handle; 1087141cc406Sopenharmony_ci 1088141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_parameters: start\n"); 1089141cc406Sopenharmony_ci 1090141cc406Sopenharmony_ci /* call parameters computing function */ 1091141cc406Sopenharmony_ci status = compute_parameters (session); 1092141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD && params) 1093141cc406Sopenharmony_ci *params = session->params; 1094141cc406Sopenharmony_ci 1095141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_parameters: exit\n"); 1096141cc406Sopenharmony_ci return status; 1097141cc406Sopenharmony_ci} 1098141cc406Sopenharmony_ci 1099141cc406Sopenharmony_ci 1100141cc406Sopenharmony_ci/** 1101141cc406Sopenharmony_ci * Called by SANE to read data. 1102141cc406Sopenharmony_ci * 1103141cc406Sopenharmony_ci * From the SANE spec: 1104141cc406Sopenharmony_ci * This function is used to read image data from the device 1105141cc406Sopenharmony_ci * represented by handle h. Argument buf is a pointer to a memory 1106141cc406Sopenharmony_ci * area that is at least maxlen bytes long. The number of bytes 1107141cc406Sopenharmony_ci * returned is stored in *len. A backend must set this to zero when 1108141cc406Sopenharmony_ci * the call fails (i.e., when a status other than SANE_STATUS_GOOD is 1109141cc406Sopenharmony_ci * returned). 1110141cc406Sopenharmony_ci * 1111141cc406Sopenharmony_ci * When the call succeeds, the number of bytes returned can be 1112141cc406Sopenharmony_ci * anywhere in the range from 0 to maxlen bytes. 1113141cc406Sopenharmony_ci * 1114141cc406Sopenharmony_ci * Returned data is read from working buffer. 1115141cc406Sopenharmony_ci */ 1116141cc406Sopenharmony_ciSANE_Status 1117141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, 1118141cc406Sopenharmony_ci SANE_Int max_len, SANE_Int * len) 1119141cc406Sopenharmony_ci{ 1120141cc406Sopenharmony_ci struct P5_Session *session = (struct P5_Session *) handle; 1121141cc406Sopenharmony_ci struct P5_Device *dev = session->dev; 1122141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 1123141cc406Sopenharmony_ci int count; 1124141cc406Sopenharmony_ci int size, lines; 1125141cc406Sopenharmony_ci SANE_Bool x2; 1126141cc406Sopenharmony_ci SANE_Int i; 1127141cc406Sopenharmony_ci 1128141cc406Sopenharmony_ci DBG (DBG_proc, "sane_read: start\n"); 1129141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: up to %d bytes required by frontend\n", max_len); 1130141cc406Sopenharmony_ci 1131141cc406Sopenharmony_ci /* some sanity checks first to protect from would be buggy frontends */ 1132141cc406Sopenharmony_ci if (!session) 1133141cc406Sopenharmony_ci { 1134141cc406Sopenharmony_ci DBG (DBG_error, "sane_read: handle is null!\n"); 1135141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1136141cc406Sopenharmony_ci } 1137141cc406Sopenharmony_ci 1138141cc406Sopenharmony_ci if (!buf) 1139141cc406Sopenharmony_ci { 1140141cc406Sopenharmony_ci DBG (DBG_error, "sane_read: buf is null!\n"); 1141141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1142141cc406Sopenharmony_ci } 1143141cc406Sopenharmony_ci 1144141cc406Sopenharmony_ci if (!len) 1145141cc406Sopenharmony_ci { 1146141cc406Sopenharmony_ci DBG (DBG_error, "sane_read: len is null!\n"); 1147141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1148141cc406Sopenharmony_ci } 1149141cc406Sopenharmony_ci 1150141cc406Sopenharmony_ci /* no data read yet */ 1151141cc406Sopenharmony_ci *len = 0; 1152141cc406Sopenharmony_ci 1153141cc406Sopenharmony_ci /* check if session is scanning */ 1154141cc406Sopenharmony_ci if (!session->scanning) 1155141cc406Sopenharmony_ci { 1156141cc406Sopenharmony_ci DBG (DBG_warn, 1157141cc406Sopenharmony_ci "sane_read: scan was cancelled, is over or has not been initiated yet\n"); 1158141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 1159141cc406Sopenharmony_ci } 1160141cc406Sopenharmony_ci 1161141cc406Sopenharmony_ci /* check for EOF, must be done before any physical read */ 1162141cc406Sopenharmony_ci if (session->sent >= session->to_send) 1163141cc406Sopenharmony_ci { 1164141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: end of scan reached\n"); 1165141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1166141cc406Sopenharmony_ci } 1167141cc406Sopenharmony_ci 1168141cc406Sopenharmony_ci /* if working buffer is empty, we do a physical data read */ 1169141cc406Sopenharmony_ci if (dev->top <= dev->bottom) 1170141cc406Sopenharmony_ci { 1171141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: physical data read\n"); 1172141cc406Sopenharmony_ci /* check is there is data available. In case of non-blocking mode we return 1173141cc406Sopenharmony_ci * as soon it is detected there is no data yet. Reads must by done line by 1174141cc406Sopenharmony_ci * line, so we read only when count is bigger than bytes per line 1175141cc406Sopenharmony_ci * */ 1176141cc406Sopenharmony_ci count = available_bytes (dev->fd); 1177141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: count=%d bytes\n", count); 1178141cc406Sopenharmony_ci if (count < dev->bytes_per_line && session->non_blocking == SANE_TRUE) 1179141cc406Sopenharmony_ci { 1180141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: scanner hasn't enough data available\n"); 1181141cc406Sopenharmony_ci DBG (DBG_proc, "sane_read: exit\n"); 1182141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1183141cc406Sopenharmony_ci } 1184141cc406Sopenharmony_ci 1185141cc406Sopenharmony_ci /* now we can wait for data here */ 1186141cc406Sopenharmony_ci while (count < dev->bytes_per_line) 1187141cc406Sopenharmony_ci { 1188141cc406Sopenharmony_ci /* test if document left the feeder, so we have to terminate the scan */ 1189141cc406Sopenharmony_ci status = test_document (dev->fd); 1190141cc406Sopenharmony_ci if (status == SANE_STATUS_NO_DOCS) 1191141cc406Sopenharmony_ci { 1192141cc406Sopenharmony_ci session->to_send = session->sent; 1193141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1194141cc406Sopenharmony_ci } 1195141cc406Sopenharmony_ci 1196141cc406Sopenharmony_ci /* don't call scanner too often */ 1197141cc406Sopenharmony_ci usleep (10000); 1198141cc406Sopenharmony_ci count = available_bytes (dev->fd); 1199141cc406Sopenharmony_ci } 1200141cc406Sopenharmony_ci 1201141cc406Sopenharmony_ci /** compute size of physical data to read 1202141cc406Sopenharmony_ci * on first read, position will be 0, while it will be 'bottom' 1203141cc406Sopenharmony_ci * for the subsequent reads. 1204141cc406Sopenharmony_ci * We try to read a complete buffer */ 1205141cc406Sopenharmony_ci size = dev->size - dev->position; 1206141cc406Sopenharmony_ci 1207141cc406Sopenharmony_ci if (session->to_send - session->sent < size) 1208141cc406Sopenharmony_ci { 1209141cc406Sopenharmony_ci /* not enough data left, so read remainder of scan */ 1210141cc406Sopenharmony_ci size = session->to_send - session->sent; 1211141cc406Sopenharmony_ci } 1212141cc406Sopenharmony_ci 1213141cc406Sopenharmony_ci /* 600 dpi is 300x600 physical, and 400 is 200x400 */ 1214141cc406Sopenharmony_ci if (dev->ydpi > dev->model->max_xdpi) 1215141cc406Sopenharmony_ci { 1216141cc406Sopenharmony_ci x2 = SANE_TRUE; 1217141cc406Sopenharmony_ci } 1218141cc406Sopenharmony_ci else 1219141cc406Sopenharmony_ci { 1220141cc406Sopenharmony_ci x2 = SANE_FALSE; 1221141cc406Sopenharmony_ci } 1222141cc406Sopenharmony_ci lines = read_line (dev, 1223141cc406Sopenharmony_ci dev->buffer + dev->position, 1224141cc406Sopenharmony_ci dev->bytes_per_line, 1225141cc406Sopenharmony_ci size / dev->bytes_per_line, 1226141cc406Sopenharmony_ci SANE_TRUE, x2, dev->mode, dev->calibrated); 1227141cc406Sopenharmony_ci 1228141cc406Sopenharmony_ci /* handle document end detection TODO try to recover the partial 1229141cc406Sopenharmony_ci * buffer already read before EOD */ 1230141cc406Sopenharmony_ci if (lines == -1) 1231141cc406Sopenharmony_ci { 1232141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: error reading line\n"); 1233141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1234141cc406Sopenharmony_ci } 1235141cc406Sopenharmony_ci 1236141cc406Sopenharmony_ci /* gather lines until we have more than needed for lds */ 1237141cc406Sopenharmony_ci dev->position += lines * dev->bytes_per_line; 1238141cc406Sopenharmony_ci dev->top = dev->position; 1239141cc406Sopenharmony_ci if (dev->position > dev->bottom) 1240141cc406Sopenharmony_ci { 1241141cc406Sopenharmony_ci dev->position = dev->bottom; 1242141cc406Sopenharmony_ci } 1243141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: size =%lu\n", (unsigned long)dev->size); 1244141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: bottom =%lu\n", (unsigned long)dev->bottom); 1245141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: position=%lu\n", (unsigned long)dev->position); 1246141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: top =%lu\n", (unsigned long)dev->top); 1247141cc406Sopenharmony_ci } /* end of physical data reading */ 1248141cc406Sopenharmony_ci 1249141cc406Sopenharmony_ci /* logical data reading */ 1250141cc406Sopenharmony_ci /* check if there data available in working buffer */ 1251141cc406Sopenharmony_ci if (dev->position < dev->top && dev->position >= dev->bottom) 1252141cc406Sopenharmony_ci { 1253141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: logical data read\n"); 1254141cc406Sopenharmony_ci /* we have more data in internal buffer than asked , 1255141cc406Sopenharmony_ci * then send only max data */ 1256141cc406Sopenharmony_ci size = dev->top - dev->position; 1257141cc406Sopenharmony_ci if (max_len < size) 1258141cc406Sopenharmony_ci { 1259141cc406Sopenharmony_ci *len = max_len; 1260141cc406Sopenharmony_ci } 1261141cc406Sopenharmony_ci else 1262141cc406Sopenharmony_ci /* if we don't have enough, send all what we have */ 1263141cc406Sopenharmony_ci { 1264141cc406Sopenharmony_ci *len = dev->top - dev->position; 1265141cc406Sopenharmony_ci } 1266141cc406Sopenharmony_ci 1267141cc406Sopenharmony_ci /* data copy */ 1268141cc406Sopenharmony_ci if (dev->lds == 0) 1269141cc406Sopenharmony_ci { 1270141cc406Sopenharmony_ci memcpy (buf, dev->buffer + dev->position, *len); 1271141cc406Sopenharmony_ci } 1272141cc406Sopenharmony_ci else 1273141cc406Sopenharmony_ci { 1274141cc406Sopenharmony_ci /* compute count of bytes for lds */ 1275141cc406Sopenharmony_ci count = dev->lds * dev->bytes_per_line; 1276141cc406Sopenharmony_ci 1277141cc406Sopenharmony_ci /* adjust for lds as we copy data to frontend */ 1278141cc406Sopenharmony_ci for (i = 0; i < *len; i++) 1279141cc406Sopenharmony_ci { 1280141cc406Sopenharmony_ci switch ((dev->position + i) % 3) 1281141cc406Sopenharmony_ci { 1282141cc406Sopenharmony_ci /* red */ 1283141cc406Sopenharmony_ci case 0: 1284141cc406Sopenharmony_ci buf[i] = dev->buffer[dev->position + i - 2 * count]; 1285141cc406Sopenharmony_ci break; 1286141cc406Sopenharmony_ci /* green */ 1287141cc406Sopenharmony_ci case 1: 1288141cc406Sopenharmony_ci buf[i] = dev->buffer[dev->position + i - count]; 1289141cc406Sopenharmony_ci break; 1290141cc406Sopenharmony_ci /* blue */ 1291141cc406Sopenharmony_ci default: 1292141cc406Sopenharmony_ci buf[i] = dev->buffer[dev->position + i]; 1293141cc406Sopenharmony_ci break; 1294141cc406Sopenharmony_ci } 1295141cc406Sopenharmony_ci } 1296141cc406Sopenharmony_ci } 1297141cc406Sopenharmony_ci dev->position += *len; 1298141cc406Sopenharmony_ci 1299141cc406Sopenharmony_ci /* update byte accounting */ 1300141cc406Sopenharmony_ci session->sent += *len; 1301141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: sent %d bytes from buffer to frontend\n", 1302141cc406Sopenharmony_ci *len); 1303141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1304141cc406Sopenharmony_ci } 1305141cc406Sopenharmony_ci 1306141cc406Sopenharmony_ci /* check if we exhausted working buffer */ 1307141cc406Sopenharmony_ci if (dev->position >= dev->top && dev->position >= dev->bottom) 1308141cc406Sopenharmony_ci { 1309141cc406Sopenharmony_ci /* copy extra lines needed for lds in next buffer */ 1310141cc406Sopenharmony_ci if (dev->position > dev->bottom && dev->lds > 0) 1311141cc406Sopenharmony_ci { 1312141cc406Sopenharmony_ci memcpy (dev->buffer, 1313141cc406Sopenharmony_ci dev->buffer + dev->position - dev->bottom, dev->bottom); 1314141cc406Sopenharmony_ci } 1315141cc406Sopenharmony_ci 1316141cc406Sopenharmony_ci /* restart buffer */ 1317141cc406Sopenharmony_ci dev->position = dev->bottom; 1318141cc406Sopenharmony_ci dev->top = 0; 1319141cc406Sopenharmony_ci } 1320141cc406Sopenharmony_ci 1321141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: size =%lu\n", (unsigned long)dev->size); 1322141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: bottom =%lu\n", (unsigned long)dev->bottom); 1323141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: position=%lu\n", (unsigned long)dev->position); 1324141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: top =%lu\n", (unsigned long)dev->top); 1325141cc406Sopenharmony_ci 1326141cc406Sopenharmony_ci DBG (DBG_proc, "sane_read: exit\n"); 1327141cc406Sopenharmony_ci return status; 1328141cc406Sopenharmony_ci} 1329141cc406Sopenharmony_ci 1330141cc406Sopenharmony_ci 1331141cc406Sopenharmony_ci/** 1332141cc406Sopenharmony_ci * Cancels a scan. 1333141cc406Sopenharmony_ci * 1334141cc406Sopenharmony_ci * From the SANE spec: 1335141cc406Sopenharmony_ci * This function is used to immediately or as quickly as possible 1336141cc406Sopenharmony_ci * cancel the currently pending operation of the device represented by 1337141cc406Sopenharmony_ci * handle h. This function can be called at any time (as long as 1338141cc406Sopenharmony_ci * handle h is a valid handle) but usually affects long-running 1339141cc406Sopenharmony_ci * operations only (such as image is acquisition). It is safe to call 1340141cc406Sopenharmony_ci * this function asynchronously (e.g., from within a signal handler). 1341141cc406Sopenharmony_ci * It is important to note that completion of this operation does not 1342141cc406Sopenharmony_ci * imply that the currently pending operation has been cancelled. It 1343141cc406Sopenharmony_ci * only guarantees that cancellation has been initiated. Cancellation 1344141cc406Sopenharmony_ci * completes only when the cancelled call returns (typically with a 1345141cc406Sopenharmony_ci * status value of SANE_STATUS_CANCELLED). Since the SANE API does 1346141cc406Sopenharmony_ci * not require any other operations to be re-entrant, this implies 1347141cc406Sopenharmony_ci * that a frontend must not call any other operation until the 1348141cc406Sopenharmony_ci * cancelled operation has returned. 1349141cc406Sopenharmony_ci */ 1350141cc406Sopenharmony_civoid 1351141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 1352141cc406Sopenharmony_ci{ 1353141cc406Sopenharmony_ci P5_Session *session = handle; 1354141cc406Sopenharmony_ci 1355141cc406Sopenharmony_ci DBG (DBG_proc, "sane_cancel: start\n"); 1356141cc406Sopenharmony_ci 1357141cc406Sopenharmony_ci /* if scanning, abort and park head */ 1358141cc406Sopenharmony_ci if (session->scanning == SANE_TRUE) 1359141cc406Sopenharmony_ci { 1360141cc406Sopenharmony_ci /* detects if we are called after the scan is finished, 1361141cc406Sopenharmony_ci * or if the scan is aborted */ 1362141cc406Sopenharmony_ci if (session->sent < session->to_send) 1363141cc406Sopenharmony_ci { 1364141cc406Sopenharmony_ci DBG (DBG_info, "sane_cancel: aborting scan.\n"); 1365141cc406Sopenharmony_ci /* device hasn't finished scan, we are aborting it 1366141cc406Sopenharmony_ci * and we may have to do something specific for it here */ 1367141cc406Sopenharmony_ci } 1368141cc406Sopenharmony_ci else 1369141cc406Sopenharmony_ci { 1370141cc406Sopenharmony_ci DBG (DBG_info, "sane_cancel: cleaning up after scan.\n"); 1371141cc406Sopenharmony_ci } 1372141cc406Sopenharmony_ci session->scanning = SANE_FALSE; 1373141cc406Sopenharmony_ci } 1374141cc406Sopenharmony_ci eject (session->dev->fd); 1375141cc406Sopenharmony_ci 1376141cc406Sopenharmony_ci DBG (DBG_proc, "sane_cancel: exit\n"); 1377141cc406Sopenharmony_ci} 1378141cc406Sopenharmony_ci 1379141cc406Sopenharmony_ci 1380141cc406Sopenharmony_ci/** 1381141cc406Sopenharmony_ci * Ends use of the session. 1382141cc406Sopenharmony_ci * 1383141cc406Sopenharmony_ci * From the SANE spec: 1384141cc406Sopenharmony_ci * This function terminates the association between the device handle 1385141cc406Sopenharmony_ci * passed in argument h and the device it represents. If the device is 1386141cc406Sopenharmony_ci * presently active, a call to sane_cancel() is performed first. After 1387141cc406Sopenharmony_ci * this function returns, handle h must not be used anymore. 1388141cc406Sopenharmony_ci * 1389141cc406Sopenharmony_ci * Handle resources are free'd before disposing the handle. But devices 1390141cc406Sopenharmony_ci * resources must not be mdofied, since it could be used or reused until 1391141cc406Sopenharmony_ci * sane_exit() is called. 1392141cc406Sopenharmony_ci */ 1393141cc406Sopenharmony_civoid 1394141cc406Sopenharmony_cisane_close (SANE_Handle handle) 1395141cc406Sopenharmony_ci{ 1396141cc406Sopenharmony_ci P5_Session *prev, *session; 1397141cc406Sopenharmony_ci 1398141cc406Sopenharmony_ci DBG (DBG_proc, "sane_close: start\n"); 1399141cc406Sopenharmony_ci 1400141cc406Sopenharmony_ci /* remove handle from list of open handles: */ 1401141cc406Sopenharmony_ci prev = NULL; 1402141cc406Sopenharmony_ci for (session = sessions; session; session = session->next) 1403141cc406Sopenharmony_ci { 1404141cc406Sopenharmony_ci if (session == handle) 1405141cc406Sopenharmony_ci break; 1406141cc406Sopenharmony_ci prev = session; 1407141cc406Sopenharmony_ci } 1408141cc406Sopenharmony_ci if (!session) 1409141cc406Sopenharmony_ci { 1410141cc406Sopenharmony_ci DBG (DBG_error0, "close: invalid handle %p\n", handle); 1411141cc406Sopenharmony_ci return; /* oops, not a handle we know about */ 1412141cc406Sopenharmony_ci } 1413141cc406Sopenharmony_ci 1414141cc406Sopenharmony_ci /* cancel any active scan */ 1415141cc406Sopenharmony_ci if (session->scanning == SANE_TRUE) 1416141cc406Sopenharmony_ci { 1417141cc406Sopenharmony_ci sane_cancel (handle); 1418141cc406Sopenharmony_ci } 1419141cc406Sopenharmony_ci 1420141cc406Sopenharmony_ci if (prev) 1421141cc406Sopenharmony_ci prev->next = session->next; 1422141cc406Sopenharmony_ci else 1423141cc406Sopenharmony_ci sessions = session->next; 1424141cc406Sopenharmony_ci 1425141cc406Sopenharmony_ci /* close low level device */ 1426141cc406Sopenharmony_ci if (session->dev->initialized == SANE_TRUE) 1427141cc406Sopenharmony_ci { 1428141cc406Sopenharmony_ci if (session->dev->calibrated == SANE_TRUE) 1429141cc406Sopenharmony_ci { 1430141cc406Sopenharmony_ci save_calibration (session->dev); 1431141cc406Sopenharmony_ci } 1432141cc406Sopenharmony_ci disconnect (session->dev->fd); 1433141cc406Sopenharmony_ci close_pp (session->dev->fd); 1434141cc406Sopenharmony_ci session->dev->fd = -1; 1435141cc406Sopenharmony_ci session->dev->initialized = SANE_FALSE; 1436141cc406Sopenharmony_ci 1437141cc406Sopenharmony_ci /* free device data */ 1438141cc406Sopenharmony_ci if (session->dev->buffer != NULL) 1439141cc406Sopenharmony_ci { 1440141cc406Sopenharmony_ci free (session->dev->buffer); 1441141cc406Sopenharmony_ci } 1442141cc406Sopenharmony_ci if (session->dev->buffer != NULL) 1443141cc406Sopenharmony_ci { 1444141cc406Sopenharmony_ci free (session->dev->gain); 1445141cc406Sopenharmony_ci free (session->dev->offset); 1446141cc406Sopenharmony_ci } 1447141cc406Sopenharmony_ci if (session->dev->calibrated == SANE_TRUE) 1448141cc406Sopenharmony_ci { 1449141cc406Sopenharmony_ci cleanup_calibration (session->dev); 1450141cc406Sopenharmony_ci } 1451141cc406Sopenharmony_ci } 1452141cc406Sopenharmony_ci 1453141cc406Sopenharmony_ci /* free per session data */ 1454141cc406Sopenharmony_ci free (session->options[OPT_MODE].value.s); 1455141cc406Sopenharmony_ci free ((void *)session->options[OPT_RESOLUTION].descriptor.constraint.word_list); 1456141cc406Sopenharmony_ci 1457141cc406Sopenharmony_ci free (session); 1458141cc406Sopenharmony_ci 1459141cc406Sopenharmony_ci DBG (DBG_proc, "sane_close: exit\n"); 1460141cc406Sopenharmony_ci} 1461141cc406Sopenharmony_ci 1462141cc406Sopenharmony_ci 1463141cc406Sopenharmony_ci/** 1464141cc406Sopenharmony_ci * Terminates the backend. 1465141cc406Sopenharmony_ci * 1466141cc406Sopenharmony_ci * From the SANE spec: 1467141cc406Sopenharmony_ci * This function must be called to terminate use of a backend. The 1468141cc406Sopenharmony_ci * function will first close all device handles that still might be 1469141cc406Sopenharmony_ci * open (it is recommended to close device handles explicitly through 1470141cc406Sopenharmony_ci * a call to sane_close(), but backends are required to release all 1471141cc406Sopenharmony_ci * resources upon a call to this function). After this function 1472141cc406Sopenharmony_ci * returns, no function other than sane_init() may be called 1473141cc406Sopenharmony_ci * (regardless of the status value returned by sane_exit(). Neglecting 1474141cc406Sopenharmony_ci * to call this function may result in some resources not being 1475141cc406Sopenharmony_ci * released properly. 1476141cc406Sopenharmony_ci */ 1477141cc406Sopenharmony_civoid 1478141cc406Sopenharmony_cisane_exit (void) 1479141cc406Sopenharmony_ci{ 1480141cc406Sopenharmony_ci struct P5_Session *session, *next; 1481141cc406Sopenharmony_ci struct P5_Device *dev, *nextdev; 1482141cc406Sopenharmony_ci int i; 1483141cc406Sopenharmony_ci 1484141cc406Sopenharmony_ci DBG (DBG_proc, "sane_exit: start\n"); 1485141cc406Sopenharmony_ci init_count--; 1486141cc406Sopenharmony_ci 1487141cc406Sopenharmony_ci if (init_count > 0) 1488141cc406Sopenharmony_ci { 1489141cc406Sopenharmony_ci DBG (DBG_info, 1490141cc406Sopenharmony_ci "sane_exit: still %d fronteds to leave before effective exit.\n", 1491141cc406Sopenharmony_ci init_count); 1492141cc406Sopenharmony_ci return; 1493141cc406Sopenharmony_ci } 1494141cc406Sopenharmony_ci 1495141cc406Sopenharmony_ci /* free session structs */ 1496141cc406Sopenharmony_ci for (session = sessions; session; session = next) 1497141cc406Sopenharmony_ci { 1498141cc406Sopenharmony_ci next = session->next; 1499141cc406Sopenharmony_ci sane_close ((SANE_Handle *) session); 1500141cc406Sopenharmony_ci free (session); 1501141cc406Sopenharmony_ci } 1502141cc406Sopenharmony_ci sessions = NULL; 1503141cc406Sopenharmony_ci 1504141cc406Sopenharmony_ci /* free devices structs */ 1505141cc406Sopenharmony_ci for (dev = devices; dev; dev = nextdev) 1506141cc406Sopenharmony_ci { 1507141cc406Sopenharmony_ci nextdev = dev->next; 1508141cc406Sopenharmony_ci free (dev->name); 1509141cc406Sopenharmony_ci free (dev); 1510141cc406Sopenharmony_ci } 1511141cc406Sopenharmony_ci devices = NULL; 1512141cc406Sopenharmony_ci 1513141cc406Sopenharmony_ci /* now list of devices */ 1514141cc406Sopenharmony_ci if (devlist) 1515141cc406Sopenharmony_ci { 1516141cc406Sopenharmony_ci i = 0; 1517141cc406Sopenharmony_ci while ((SANE_Device *) devlist[i]) 1518141cc406Sopenharmony_ci { 1519141cc406Sopenharmony_ci free ((SANE_Device *) devlist[i]); 1520141cc406Sopenharmony_ci i++; 1521141cc406Sopenharmony_ci } 1522141cc406Sopenharmony_ci free (devlist); 1523141cc406Sopenharmony_ci devlist = NULL; 1524141cc406Sopenharmony_ci } 1525141cc406Sopenharmony_ci 1526141cc406Sopenharmony_ci DBG (DBG_proc, "sane_exit: exit\n"); 1527141cc406Sopenharmony_ci} 1528141cc406Sopenharmony_ci 1529141cc406Sopenharmony_ci 1530141cc406Sopenharmony_ci/** @brief probe for all supported devices 1531141cc406Sopenharmony_ci * This functions tries to probe if any of the supported devices of 1532141cc406Sopenharmony_ci * the backend is present. Each detected device will be added to the 1533141cc406Sopenharmony_ci * 'devices' list 1534141cc406Sopenharmony_ci */ 1535141cc406Sopenharmony_cistatic SANE_Status 1536141cc406Sopenharmony_ciprobe_p5_devices (void) 1537141cc406Sopenharmony_ci{ 1538141cc406Sopenharmony_ci /**> configuration structure used during attach */ 1539141cc406Sopenharmony_ci SANEI_Config config; 1540141cc406Sopenharmony_ci /**> list of configuration options */ 1541141cc406Sopenharmony_ci SANE_Option_Descriptor *cfg_options[NUM_CFG_OPTIONS]; 1542141cc406Sopenharmony_ci /**> placeholders pointers for option values */ 1543141cc406Sopenharmony_ci void *values[NUM_CFG_OPTIONS]; 1544141cc406Sopenharmony_ci int i; 1545141cc406Sopenharmony_ci SANE_Status status; 1546141cc406Sopenharmony_ci 1547141cc406Sopenharmony_ci DBG (DBG_proc, "probe_p5_devices: start\n"); 1548141cc406Sopenharmony_ci 1549141cc406Sopenharmony_ci /* initialize configuration options */ 1550141cc406Sopenharmony_ci cfg_options[CFG_MODEL_NAME] = 1551141cc406Sopenharmony_ci (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); 1552141cc406Sopenharmony_ci cfg_options[CFG_MODEL_NAME]->name = "modelname"; 1553141cc406Sopenharmony_ci cfg_options[CFG_MODEL_NAME]->desc = "user provided scanner's model name"; 1554141cc406Sopenharmony_ci cfg_options[CFG_MODEL_NAME]->type = SANE_TYPE_INT; 1555141cc406Sopenharmony_ci cfg_options[CFG_MODEL_NAME]->unit = SANE_UNIT_NONE; 1556141cc406Sopenharmony_ci cfg_options[CFG_MODEL_NAME]->size = sizeof (SANE_Word); 1557141cc406Sopenharmony_ci cfg_options[CFG_MODEL_NAME]->cap = SANE_CAP_SOFT_SELECT; 1558141cc406Sopenharmony_ci cfg_options[CFG_MODEL_NAME]->constraint_type = SANE_CONSTRAINT_NONE; 1559141cc406Sopenharmony_ci values[CFG_MODEL_NAME] = &p5cfg.modelname; 1560141cc406Sopenharmony_ci 1561141cc406Sopenharmony_ci /* set configuration options structure */ 1562141cc406Sopenharmony_ci config.descriptors = cfg_options; 1563141cc406Sopenharmony_ci config.values = values; 1564141cc406Sopenharmony_ci config.count = NUM_CFG_OPTIONS; 1565141cc406Sopenharmony_ci 1566141cc406Sopenharmony_ci /* generic configure and attach function */ 1567141cc406Sopenharmony_ci status = sanei_configure_attach (P5_CONFIG_FILE, &config, 1568141cc406Sopenharmony_ci config_attach, NULL); 1569141cc406Sopenharmony_ci /* free allocated options */ 1570141cc406Sopenharmony_ci for (i = 0; i < NUM_CFG_OPTIONS; i++) 1571141cc406Sopenharmony_ci { 1572141cc406Sopenharmony_ci free (cfg_options[i]); 1573141cc406Sopenharmony_ci } 1574141cc406Sopenharmony_ci 1575141cc406Sopenharmony_ci DBG (DBG_proc, "probe_p5_devices: end\n"); 1576141cc406Sopenharmony_ci return status; 1577141cc406Sopenharmony_ci} 1578141cc406Sopenharmony_ci 1579141cc406Sopenharmony_ci/** This function is called by sanei_configure_attach to try 1580141cc406Sopenharmony_ci * to attach the backend to a device specified by the configuration file. 1581141cc406Sopenharmony_ci * 1582141cc406Sopenharmony_ci * @param config configuration structure filled with values read 1583141cc406Sopenharmony_ci * from configuration file 1584141cc406Sopenharmony_ci * @param devname name of the device to try to attach to, it is 1585141cc406Sopenharmony_ci * the unprocessed line of the configuration file 1586141cc406Sopenharmony_ci * 1587141cc406Sopenharmony_ci * @return status SANE_STATUS_GOOD if no errors (even if no matching 1588141cc406Sopenharmony_ci * devices found) 1589141cc406Sopenharmony_ci * SANE_STATUS_INVAL in case of error 1590141cc406Sopenharmony_ci */ 1591141cc406Sopenharmony_cistatic SANE_Status 1592141cc406Sopenharmony_ciconfig_attach (SANEI_Config __sane_unused__ * config, const char *devname, 1593141cc406Sopenharmony_ci void __sane_unused__ *data) 1594141cc406Sopenharmony_ci{ 1595141cc406Sopenharmony_ci /* currently, the config is a global variable so config is useless here */ 1596141cc406Sopenharmony_ci /* the correct thing would be to have a generic sanei_attach_matching_devices 1597141cc406Sopenharmony_ci * using an attach function with a config parameter */ 1598141cc406Sopenharmony_ci (void) config; 1599141cc406Sopenharmony_ci 1600141cc406Sopenharmony_ci /* the devname has been processed and is ready to be used 1601141cc406Sopenharmony_ci * directly. The config struct contains all the configuration data for 1602141cc406Sopenharmony_ci * the corresponding device. Since there is no resources common to each 1603141cc406Sopenharmony_ci * backends regarding parallel port, we can directly call the attach 1604141cc406Sopenharmony_ci * function. */ 1605141cc406Sopenharmony_ci attach_p5 (devname, config); 1606141cc406Sopenharmony_ci 1607141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1608141cc406Sopenharmony_ci} 1609141cc406Sopenharmony_ci 1610141cc406Sopenharmony_ci/** @brief try to attach to a device by its name 1611141cc406Sopenharmony_ci * The attach tries to open the given device and match it 1612141cc406Sopenharmony_ci * with devices handled by the backend. The configuration parameter 1613141cc406Sopenharmony_ci * contains the values of the already parsed configuration options 1614141cc406Sopenharmony_ci * from the conf file. 1615141cc406Sopenharmony_ci * @param config configuration structure filled with values read 1616141cc406Sopenharmony_ci * from configuration file 1617141cc406Sopenharmony_ci * @param devicename name of the device to try to attach to, it is 1618141cc406Sopenharmony_ci * the unprocessed line of the configuration file 1619141cc406Sopenharmony_ci * 1620141cc406Sopenharmony_ci * @return status SANE_STATUS_GOOD if no errors (even if no matching 1621141cc406Sopenharmony_ci * devices found) 1622141cc406Sopenharmony_ci * SANE_STATUS_NOM_MEM if there isn't enough memory to allocate the 1623141cc406Sopenharmony_ci * device structure 1624141cc406Sopenharmony_ci * SANE_STATUS_UNSUPPORTED if the device if unknown by the backend 1625141cc406Sopenharmony_ci * SANE_STATUS_INVAL in case of other error 1626141cc406Sopenharmony_ci */ 1627141cc406Sopenharmony_cistatic SANE_Status 1628141cc406Sopenharmony_ciattach_p5 (const char *devicename, SANEI_Config * config) 1629141cc406Sopenharmony_ci{ 1630141cc406Sopenharmony_ci struct P5_Device *device; 1631141cc406Sopenharmony_ci struct P5_Model *model; 1632141cc406Sopenharmony_ci 1633141cc406Sopenharmony_ci DBG (DBG_proc, "attach(%s): start\n", devicename); 1634141cc406Sopenharmony_ci if(config==NULL) 1635141cc406Sopenharmony_ci { 1636141cc406Sopenharmony_ci DBG (DBG_warn, "attach: config is NULL\n"); 1637141cc406Sopenharmony_ci } 1638141cc406Sopenharmony_ci 1639141cc406Sopenharmony_ci /* search if we already have it attached */ 1640141cc406Sopenharmony_ci for (device = devices; device; device = device->next) 1641141cc406Sopenharmony_ci { 1642141cc406Sopenharmony_ci if (strcmp (device->name, devicename) == 0) 1643141cc406Sopenharmony_ci { 1644141cc406Sopenharmony_ci DBG (DBG_info, "attach: device already attached\n"); 1645141cc406Sopenharmony_ci DBG (DBG_proc, "attach: exit\n"); 1646141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1647141cc406Sopenharmony_ci } 1648141cc406Sopenharmony_ci } 1649141cc406Sopenharmony_ci 1650141cc406Sopenharmony_ci /** 1651141cc406Sopenharmony_ci * do physical probe of the device here. In case the device is recognized, 1652141cc406Sopenharmony_ci * we allocate a device struct and give it options and model. 1653141cc406Sopenharmony_ci * Else we return SANE_STATUS_UNSUPPORTED. 1654141cc406Sopenharmony_ci */ 1655141cc406Sopenharmony_ci model = probe (devicename); 1656141cc406Sopenharmony_ci if (model == NULL) 1657141cc406Sopenharmony_ci { 1658141cc406Sopenharmony_ci DBG (DBG_info, 1659141cc406Sopenharmony_ci "attach: device %s is not managed by the backend\n", devicename); 1660141cc406Sopenharmony_ci DBG (DBG_proc, "attach: exit\n"); 1661141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1662141cc406Sopenharmony_ci } 1663141cc406Sopenharmony_ci 1664141cc406Sopenharmony_ci /* allocate device struct */ 1665141cc406Sopenharmony_ci device = malloc (sizeof (*device)); 1666141cc406Sopenharmony_ci if (device == NULL) 1667141cc406Sopenharmony_ci { 1668141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1669141cc406Sopenharmony_ci DBG (DBG_proc, "attach: exit\n"); 1670141cc406Sopenharmony_ci } 1671141cc406Sopenharmony_ci memset (device, 0, sizeof (*device)); 1672141cc406Sopenharmony_ci device->model = model; 1673141cc406Sopenharmony_ci 1674141cc406Sopenharmony_ci /* name of the device */ 1675141cc406Sopenharmony_ci device->name = strdup (devicename); 1676141cc406Sopenharmony_ci 1677141cc406Sopenharmony_ci DBG (DBG_info, "attach: found %s %s %s at %s\n", 1678141cc406Sopenharmony_ci device->model->vendor, device->model->product, device->model->type, 1679141cc406Sopenharmony_ci device->name); 1680141cc406Sopenharmony_ci 1681141cc406Sopenharmony_ci /* we insert new device at start of the chained list */ 1682141cc406Sopenharmony_ci /* head of the list becomes the next, and start is replaced */ 1683141cc406Sopenharmony_ci /* with the new session struct */ 1684141cc406Sopenharmony_ci device->next = devices; 1685141cc406Sopenharmony_ci devices = device; 1686141cc406Sopenharmony_ci 1687141cc406Sopenharmony_ci /* initialization is done at sane_open */ 1688141cc406Sopenharmony_ci device->initialized = SANE_FALSE; 1689141cc406Sopenharmony_ci device->calibrated = SANE_FALSE; 1690141cc406Sopenharmony_ci 1691141cc406Sopenharmony_ci DBG (DBG_proc, "attach: exit\n"); 1692141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1693141cc406Sopenharmony_ci} 1694141cc406Sopenharmony_ci 1695141cc406Sopenharmony_ci 1696141cc406Sopenharmony_ci/** @brief set initial value for the scanning options 1697141cc406Sopenharmony_ci * for each sessions, control options are initialized based on the capability 1698141cc406Sopenharmony_ci * of the model of the physical device. 1699141cc406Sopenharmony_ci * @param session scanner session to initialize options 1700141cc406Sopenharmony_ci * @return SANE_STATUS_GOOD on success 1701141cc406Sopenharmony_ci */ 1702141cc406Sopenharmony_cistatic SANE_Status 1703141cc406Sopenharmony_ciinit_options (struct P5_Session *session) 1704141cc406Sopenharmony_ci{ 1705141cc406Sopenharmony_ci SANE_Int option, i, min, idx; 1706141cc406Sopenharmony_ci SANE_Word *dpi_list; 1707141cc406Sopenharmony_ci P5_Model *model = session->dev->model; 1708141cc406Sopenharmony_ci 1709141cc406Sopenharmony_ci DBG (DBG_proc, "init_options: start\n"); 1710141cc406Sopenharmony_ci 1711141cc406Sopenharmony_ci /* we first initialize each options with a default value */ 1712141cc406Sopenharmony_ci memset (session->options, 0, sizeof (session->options[OPT_NUM_OPTS])); 1713141cc406Sopenharmony_ci for (option = 0; option < NUM_OPTIONS; option++) 1714141cc406Sopenharmony_ci { 1715141cc406Sopenharmony_ci session->options[option].descriptor.size = sizeof (SANE_Word); 1716141cc406Sopenharmony_ci session->options[option].descriptor.cap = 1717141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 1718141cc406Sopenharmony_ci } 1719141cc406Sopenharmony_ci 1720141cc406Sopenharmony_ci /* we set up all the options listed in the P5_Option enum */ 1721141cc406Sopenharmony_ci 1722141cc406Sopenharmony_ci /* last option / end of list marker */ 1723141cc406Sopenharmony_ci session->options[OPT_NUM_OPTS].descriptor.name = SANE_NAME_NUM_OPTIONS; 1724141cc406Sopenharmony_ci session->options[OPT_NUM_OPTS].descriptor.title = SANE_TITLE_NUM_OPTIONS; 1725141cc406Sopenharmony_ci session->options[OPT_NUM_OPTS].descriptor.desc = SANE_DESC_NUM_OPTIONS; 1726141cc406Sopenharmony_ci session->options[OPT_NUM_OPTS].descriptor.type = SANE_TYPE_INT; 1727141cc406Sopenharmony_ci session->options[OPT_NUM_OPTS].descriptor.cap = SANE_CAP_SOFT_DETECT; 1728141cc406Sopenharmony_ci session->options[OPT_NUM_OPTS].value.w = NUM_OPTIONS; 1729141cc406Sopenharmony_ci 1730141cc406Sopenharmony_ci /* "Standard" group: */ 1731141cc406Sopenharmony_ci session->options[OPT_STANDARD_GROUP].descriptor.title = SANE_TITLE_STANDARD; 1732141cc406Sopenharmony_ci session->options[OPT_STANDARD_GROUP].descriptor.name = SANE_NAME_STANDARD; 1733141cc406Sopenharmony_ci session->options[OPT_STANDARD_GROUP].descriptor.desc = SANE_DESC_STANDARD; 1734141cc406Sopenharmony_ci session->options[OPT_STANDARD_GROUP].descriptor.type = SANE_TYPE_GROUP; 1735141cc406Sopenharmony_ci session->options[OPT_STANDARD_GROUP].descriptor.size = 0; 1736141cc406Sopenharmony_ci session->options[OPT_STANDARD_GROUP].descriptor.cap = 0; 1737141cc406Sopenharmony_ci session->options[OPT_STANDARD_GROUP].descriptor.constraint_type = 1738141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE; 1739141cc406Sopenharmony_ci 1740141cc406Sopenharmony_ci /* scan mode */ 1741141cc406Sopenharmony_ci session->options[OPT_MODE].descriptor.name = SANE_NAME_SCAN_MODE; 1742141cc406Sopenharmony_ci session->options[OPT_MODE].descriptor.title = SANE_TITLE_SCAN_MODE; 1743141cc406Sopenharmony_ci session->options[OPT_MODE].descriptor.desc = SANE_DESC_SCAN_MODE; 1744141cc406Sopenharmony_ci session->options[OPT_MODE].descriptor.type = SANE_TYPE_STRING; 1745141cc406Sopenharmony_ci session->options[OPT_MODE].descriptor.cap |= SANE_CAP_AUTOMATIC; 1746141cc406Sopenharmony_ci session->options[OPT_MODE].descriptor.constraint_type = 1747141cc406Sopenharmony_ci SANE_CONSTRAINT_STRING_LIST; 1748141cc406Sopenharmony_ci session->options[OPT_MODE].descriptor.size = max_string_size (mode_list); 1749141cc406Sopenharmony_ci session->options[OPT_MODE].descriptor.constraint.string_list = mode_list; 1750141cc406Sopenharmony_ci session->options[OPT_MODE].value.s = strdup (mode_list[0]); 1751141cc406Sopenharmony_ci 1752141cc406Sopenharmony_ci /* preview */ 1753141cc406Sopenharmony_ci session->options[OPT_PREVIEW].descriptor.name = SANE_NAME_PREVIEW; 1754141cc406Sopenharmony_ci session->options[OPT_PREVIEW].descriptor.title = SANE_TITLE_PREVIEW; 1755141cc406Sopenharmony_ci session->options[OPT_PREVIEW].descriptor.desc = SANE_DESC_PREVIEW; 1756141cc406Sopenharmony_ci session->options[OPT_PREVIEW].descriptor.type = SANE_TYPE_BOOL; 1757141cc406Sopenharmony_ci session->options[OPT_PREVIEW].descriptor.cap |= SANE_CAP_AUTOMATIC; 1758141cc406Sopenharmony_ci session->options[OPT_PREVIEW].descriptor.unit = SANE_UNIT_NONE; 1759141cc406Sopenharmony_ci session->options[OPT_PREVIEW].descriptor.constraint_type = 1760141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE; 1761141cc406Sopenharmony_ci session->options[OPT_PREVIEW].value.w = SANE_FALSE; 1762141cc406Sopenharmony_ci 1763141cc406Sopenharmony_ci /** @brief build resolution list 1764141cc406Sopenharmony_ci * We merge xdpi and ydpi list to provide only one resolution option control. 1765141cc406Sopenharmony_ci * This is the most common case for backends and fronteds and give 'square' 1766141cc406Sopenharmony_ci * pixels. The SANE API allow to control x and y dpi independently, but this is 1767141cc406Sopenharmony_ci * rarely done and may confuse both frontends and users. In case a dpi value exists 1768141cc406Sopenharmony_ci * for one but not for the other, the backend will have to crop data so that the 1769141cc406Sopenharmony_ci * frontend is unaffected. A common case is that motor resolution (ydpi) is higher 1770141cc406Sopenharmony_ci * than sensor resolution (xdpi), so scan lines must be scaled up to keep square 1771141cc406Sopenharmony_ci * pixel when doing sane_read(). 1772141cc406Sopenharmony_ci * TODO this deserves a dedicated function and some unit testing 1773141cc406Sopenharmony_ci */ 1774141cc406Sopenharmony_ci 1775141cc406Sopenharmony_ci /* find minimum first */ 1776141cc406Sopenharmony_ci min = 65535; 1777141cc406Sopenharmony_ci for (i = 0; i < MAX_RESOLUTIONS && model->xdpi_values[i] > 0; i++) 1778141cc406Sopenharmony_ci { 1779141cc406Sopenharmony_ci if (model->xdpi_values[i] < min) 1780141cc406Sopenharmony_ci min = model->xdpi_values[i]; 1781141cc406Sopenharmony_ci } 1782141cc406Sopenharmony_ci for (i = 0; i < MAX_RESOLUTIONS && model->ydpi_values[i] > 0; i++) 1783141cc406Sopenharmony_ci { 1784141cc406Sopenharmony_ci if (model->ydpi_values[i] < min) 1785141cc406Sopenharmony_ci min = model->ydpi_values[i]; 1786141cc406Sopenharmony_ci } 1787141cc406Sopenharmony_ci 1788141cc406Sopenharmony_ci dpi_list = malloc ((MAX_RESOLUTIONS * 2 + 1) * sizeof (SANE_Word)); 1789141cc406Sopenharmony_ci if (!dpi_list) 1790141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1791141cc406Sopenharmony_ci dpi_list[1] = min; 1792141cc406Sopenharmony_ci idx = 2; 1793141cc406Sopenharmony_ci 1794141cc406Sopenharmony_ci /* find any value greater than the last used min and 1795141cc406Sopenharmony_ci * less than the max value 1796141cc406Sopenharmony_ci */ 1797141cc406Sopenharmony_ci do 1798141cc406Sopenharmony_ci { 1799141cc406Sopenharmony_ci min = 65535; 1800141cc406Sopenharmony_ci for (i = 0; i < MAX_RESOLUTIONS && model->xdpi_values[i] > 0; i++) 1801141cc406Sopenharmony_ci { 1802141cc406Sopenharmony_ci if (model->xdpi_values[i] < min 1803141cc406Sopenharmony_ci && model->xdpi_values[i] > dpi_list[idx - 1]) 1804141cc406Sopenharmony_ci min = model->xdpi_values[i]; 1805141cc406Sopenharmony_ci } 1806141cc406Sopenharmony_ci for (i = 0; i < MAX_RESOLUTIONS && model->ydpi_values[i] > 0; i++) 1807141cc406Sopenharmony_ci { 1808141cc406Sopenharmony_ci if (model->ydpi_values[i] < min 1809141cc406Sopenharmony_ci && model->ydpi_values[i] > dpi_list[idx - 1]) 1810141cc406Sopenharmony_ci min = model->ydpi_values[i]; 1811141cc406Sopenharmony_ci } 1812141cc406Sopenharmony_ci if (min < 65535) 1813141cc406Sopenharmony_ci { 1814141cc406Sopenharmony_ci dpi_list[idx] = min; 1815141cc406Sopenharmony_ci idx++; 1816141cc406Sopenharmony_ci } 1817141cc406Sopenharmony_ci } 1818141cc406Sopenharmony_ci while (min != 65535); 1819141cc406Sopenharmony_ci dpi_list[idx] = 0; 1820141cc406Sopenharmony_ci /* the count of different resolution is put at the beginning */ 1821141cc406Sopenharmony_ci dpi_list[0] = idx - 1; 1822141cc406Sopenharmony_ci 1823141cc406Sopenharmony_ci session->options[OPT_RESOLUTION].descriptor.name = 1824141cc406Sopenharmony_ci SANE_NAME_SCAN_RESOLUTION; 1825141cc406Sopenharmony_ci session->options[OPT_RESOLUTION].descriptor.title = 1826141cc406Sopenharmony_ci SANE_TITLE_SCAN_RESOLUTION; 1827141cc406Sopenharmony_ci session->options[OPT_RESOLUTION].descriptor.desc = 1828141cc406Sopenharmony_ci SANE_DESC_SCAN_RESOLUTION; 1829141cc406Sopenharmony_ci session->options[OPT_RESOLUTION].descriptor.type = SANE_TYPE_INT; 1830141cc406Sopenharmony_ci session->options[OPT_RESOLUTION].descriptor.cap |= SANE_CAP_AUTOMATIC; 1831141cc406Sopenharmony_ci session->options[OPT_RESOLUTION].descriptor.unit = SANE_UNIT_DPI; 1832141cc406Sopenharmony_ci session->options[OPT_RESOLUTION].descriptor.constraint_type = 1833141cc406Sopenharmony_ci SANE_CONSTRAINT_WORD_LIST; 1834141cc406Sopenharmony_ci session->options[OPT_RESOLUTION].descriptor.constraint.word_list = dpi_list; 1835141cc406Sopenharmony_ci 1836141cc406Sopenharmony_ci /* initial value is lowest available dpi */ 1837141cc406Sopenharmony_ci session->options[OPT_RESOLUTION].value.w = min; 1838141cc406Sopenharmony_ci 1839141cc406Sopenharmony_ci /* "Geometry" group: */ 1840141cc406Sopenharmony_ci session->options[OPT_GEOMETRY_GROUP].descriptor.title = SANE_TITLE_GEOMETRY; 1841141cc406Sopenharmony_ci session->options[OPT_GEOMETRY_GROUP].descriptor.name = SANE_NAME_GEOMETRY; 1842141cc406Sopenharmony_ci session->options[OPT_GEOMETRY_GROUP].descriptor.desc = SANE_DESC_GEOMETRY; 1843141cc406Sopenharmony_ci session->options[OPT_GEOMETRY_GROUP].descriptor.type = SANE_TYPE_GROUP; 1844141cc406Sopenharmony_ci session->options[OPT_GEOMETRY_GROUP].descriptor.cap = SANE_CAP_ADVANCED; 1845141cc406Sopenharmony_ci session->options[OPT_GEOMETRY_GROUP].descriptor.size = 0; 1846141cc406Sopenharmony_ci session->options[OPT_GEOMETRY_GROUP].descriptor.constraint_type = 1847141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE; 1848141cc406Sopenharmony_ci 1849141cc406Sopenharmony_ci /* adapt the constraint range to the detected model */ 1850141cc406Sopenharmony_ci x_range.max = model->x_size; 1851141cc406Sopenharmony_ci y_range.max = model->y_size; 1852141cc406Sopenharmony_ci 1853141cc406Sopenharmony_ci /* top-left x */ 1854141cc406Sopenharmony_ci session->options[OPT_TL_X].descriptor.name = SANE_NAME_SCAN_TL_X; 1855141cc406Sopenharmony_ci session->options[OPT_TL_X].descriptor.title = SANE_TITLE_SCAN_TL_X; 1856141cc406Sopenharmony_ci session->options[OPT_TL_X].descriptor.desc = SANE_DESC_SCAN_TL_X; 1857141cc406Sopenharmony_ci session->options[OPT_TL_X].descriptor.type = SANE_TYPE_FIXED; 1858141cc406Sopenharmony_ci session->options[OPT_TL_X].descriptor.cap |= SANE_CAP_AUTOMATIC; 1859141cc406Sopenharmony_ci session->options[OPT_TL_X].descriptor.unit = SANE_UNIT_MM; 1860141cc406Sopenharmony_ci session->options[OPT_TL_X].descriptor.constraint_type = 1861141cc406Sopenharmony_ci SANE_CONSTRAINT_RANGE; 1862141cc406Sopenharmony_ci session->options[OPT_TL_X].descriptor.constraint.range = &x_range; 1863141cc406Sopenharmony_ci session->options[OPT_TL_X].value.w = 0; 1864141cc406Sopenharmony_ci 1865141cc406Sopenharmony_ci /* top-left y */ 1866141cc406Sopenharmony_ci session->options[OPT_TL_Y].descriptor.name = SANE_NAME_SCAN_TL_Y; 1867141cc406Sopenharmony_ci session->options[OPT_TL_Y].descriptor.title = SANE_TITLE_SCAN_TL_Y; 1868141cc406Sopenharmony_ci session->options[OPT_TL_Y].descriptor.desc = SANE_DESC_SCAN_TL_Y; 1869141cc406Sopenharmony_ci session->options[OPT_TL_Y].descriptor.type = SANE_TYPE_FIXED; 1870141cc406Sopenharmony_ci session->options[OPT_TL_Y].descriptor.cap |= SANE_CAP_AUTOMATIC; 1871141cc406Sopenharmony_ci session->options[OPT_TL_Y].descriptor.unit = SANE_UNIT_MM; 1872141cc406Sopenharmony_ci session->options[OPT_TL_Y].descriptor.constraint_type = 1873141cc406Sopenharmony_ci SANE_CONSTRAINT_RANGE; 1874141cc406Sopenharmony_ci session->options[OPT_TL_Y].descriptor.constraint.range = &y_range; 1875141cc406Sopenharmony_ci session->options[OPT_TL_Y].value.w = 0; 1876141cc406Sopenharmony_ci 1877141cc406Sopenharmony_ci /* bottom-right x */ 1878141cc406Sopenharmony_ci session->options[OPT_BR_X].descriptor.name = SANE_NAME_SCAN_BR_X; 1879141cc406Sopenharmony_ci session->options[OPT_BR_X].descriptor.title = SANE_TITLE_SCAN_BR_X; 1880141cc406Sopenharmony_ci session->options[OPT_BR_X].descriptor.desc = SANE_DESC_SCAN_BR_X; 1881141cc406Sopenharmony_ci session->options[OPT_BR_X].descriptor.type = SANE_TYPE_FIXED; 1882141cc406Sopenharmony_ci session->options[OPT_BR_X].descriptor.cap |= SANE_CAP_AUTOMATIC; 1883141cc406Sopenharmony_ci session->options[OPT_BR_X].descriptor.unit = SANE_UNIT_MM; 1884141cc406Sopenharmony_ci session->options[OPT_BR_X].descriptor.constraint_type = 1885141cc406Sopenharmony_ci SANE_CONSTRAINT_RANGE; 1886141cc406Sopenharmony_ci session->options[OPT_BR_X].descriptor.constraint.range = &x_range; 1887141cc406Sopenharmony_ci session->options[OPT_BR_X].value.w = x_range.max; 1888141cc406Sopenharmony_ci 1889141cc406Sopenharmony_ci /* bottom-right y */ 1890141cc406Sopenharmony_ci session->options[OPT_BR_Y].descriptor.name = SANE_NAME_SCAN_BR_Y; 1891141cc406Sopenharmony_ci session->options[OPT_BR_Y].descriptor.title = SANE_TITLE_SCAN_BR_Y; 1892141cc406Sopenharmony_ci session->options[OPT_BR_Y].descriptor.desc = SANE_DESC_SCAN_BR_Y; 1893141cc406Sopenharmony_ci session->options[OPT_BR_Y].descriptor.type = SANE_TYPE_FIXED; 1894141cc406Sopenharmony_ci session->options[OPT_BR_Y].descriptor.cap |= SANE_CAP_AUTOMATIC; 1895141cc406Sopenharmony_ci session->options[OPT_BR_Y].descriptor.unit = SANE_UNIT_MM; 1896141cc406Sopenharmony_ci session->options[OPT_BR_Y].descriptor.constraint_type = 1897141cc406Sopenharmony_ci SANE_CONSTRAINT_RANGE; 1898141cc406Sopenharmony_ci session->options[OPT_BR_Y].descriptor.constraint.range = &y_range; 1899141cc406Sopenharmony_ci session->options[OPT_BR_Y].value.w = y_range.max; 1900141cc406Sopenharmony_ci 1901141cc406Sopenharmony_ci /* sensor group */ 1902141cc406Sopenharmony_ci session->options[OPT_SENSOR_GROUP].descriptor.name = SANE_NAME_SENSORS; 1903141cc406Sopenharmony_ci session->options[OPT_SENSOR_GROUP].descriptor.title = SANE_TITLE_SENSORS; 1904141cc406Sopenharmony_ci session->options[OPT_SENSOR_GROUP].descriptor.desc = SANE_DESC_SENSORS; 1905141cc406Sopenharmony_ci session->options[OPT_SENSOR_GROUP].descriptor.type = SANE_TYPE_GROUP; 1906141cc406Sopenharmony_ci session->options[OPT_SENSOR_GROUP].descriptor.constraint_type = 1907141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE; 1908141cc406Sopenharmony_ci 1909141cc406Sopenharmony_ci /* page loaded sensor */ 1910141cc406Sopenharmony_ci session->options[OPT_PAGE_LOADED_SW].descriptor.name = 1911141cc406Sopenharmony_ci SANE_NAME_PAGE_LOADED; 1912141cc406Sopenharmony_ci session->options[OPT_PAGE_LOADED_SW].descriptor.title = 1913141cc406Sopenharmony_ci SANE_TITLE_PAGE_LOADED; 1914141cc406Sopenharmony_ci session->options[OPT_PAGE_LOADED_SW].descriptor.desc = 1915141cc406Sopenharmony_ci SANE_DESC_PAGE_LOADED; 1916141cc406Sopenharmony_ci session->options[OPT_PAGE_LOADED_SW].descriptor.type = SANE_TYPE_BOOL; 1917141cc406Sopenharmony_ci session->options[OPT_PAGE_LOADED_SW].descriptor.unit = SANE_UNIT_NONE; 1918141cc406Sopenharmony_ci session->options[OPT_PAGE_LOADED_SW].descriptor.cap = 1919141cc406Sopenharmony_ci SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 1920141cc406Sopenharmony_ci session->options[OPT_PAGE_LOADED_SW].value.b = 0; 1921141cc406Sopenharmony_ci 1922141cc406Sopenharmony_ci /* calibration needed */ 1923141cc406Sopenharmony_ci session->options[OPT_NEED_CALIBRATION_SW].descriptor.name = 1924141cc406Sopenharmony_ci "need-calibration"; 1925141cc406Sopenharmony_ci session->options[OPT_NEED_CALIBRATION_SW].descriptor.title = 1926141cc406Sopenharmony_ci SANE_I18N ("Need calibration"); 1927141cc406Sopenharmony_ci session->options[OPT_NEED_CALIBRATION_SW].descriptor.desc = 1928141cc406Sopenharmony_ci SANE_I18N ("The scanner needs calibration for the current settings"); 1929141cc406Sopenharmony_ci session->options[OPT_NEED_CALIBRATION_SW].descriptor.type = SANE_TYPE_BOOL; 1930141cc406Sopenharmony_ci session->options[OPT_NEED_CALIBRATION_SW].descriptor.unit = SANE_UNIT_NONE; 1931141cc406Sopenharmony_ci session->options[OPT_NEED_CALIBRATION_SW].descriptor.cap = 1932141cc406Sopenharmony_ci SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 1933141cc406Sopenharmony_ci session->options[OPT_NEED_CALIBRATION_SW].value.b = 0; 1934141cc406Sopenharmony_ci 1935141cc406Sopenharmony_ci /* button group */ 1936141cc406Sopenharmony_ci session->options[OPT_BUTTON_GROUP].descriptor.name = "Buttons"; 1937141cc406Sopenharmony_ci session->options[OPT_BUTTON_GROUP].descriptor.title = SANE_I18N ("Buttons"); 1938141cc406Sopenharmony_ci session->options[OPT_BUTTON_GROUP].descriptor.desc = SANE_I18N ("Buttons"); 1939141cc406Sopenharmony_ci session->options[OPT_BUTTON_GROUP].descriptor.type = SANE_TYPE_GROUP; 1940141cc406Sopenharmony_ci session->options[OPT_BUTTON_GROUP].descriptor.constraint_type = 1941141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE; 1942141cc406Sopenharmony_ci 1943141cc406Sopenharmony_ci /* calibrate button */ 1944141cc406Sopenharmony_ci session->options[OPT_CALIBRATE].descriptor.name = "calibrate"; 1945141cc406Sopenharmony_ci session->options[OPT_CALIBRATE].descriptor.title = SANE_I18N ("Calibrate"); 1946141cc406Sopenharmony_ci session->options[OPT_CALIBRATE].descriptor.desc = 1947141cc406Sopenharmony_ci SANE_I18N ("Start calibration using special sheet"); 1948141cc406Sopenharmony_ci session->options[OPT_CALIBRATE].descriptor.type = SANE_TYPE_BUTTON; 1949141cc406Sopenharmony_ci session->options[OPT_CALIBRATE].descriptor.unit = SANE_UNIT_NONE; 1950141cc406Sopenharmony_ci session->options[OPT_CALIBRATE].descriptor.cap = 1951141cc406Sopenharmony_ci SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED | 1952141cc406Sopenharmony_ci SANE_CAP_AUTOMATIC; 1953141cc406Sopenharmony_ci session->options[OPT_CALIBRATE].value.b = 0; 1954141cc406Sopenharmony_ci 1955141cc406Sopenharmony_ci /* clear calibration cache button */ 1956141cc406Sopenharmony_ci session->options[OPT_CLEAR_CALIBRATION].descriptor.name = "clear"; 1957141cc406Sopenharmony_ci session->options[OPT_CLEAR_CALIBRATION].descriptor.title = 1958141cc406Sopenharmony_ci SANE_I18N ("Clear calibration"); 1959141cc406Sopenharmony_ci session->options[OPT_CLEAR_CALIBRATION].descriptor.desc = 1960141cc406Sopenharmony_ci SANE_I18N ("Clear calibration cache"); 1961141cc406Sopenharmony_ci session->options[OPT_CLEAR_CALIBRATION].descriptor.type = SANE_TYPE_BUTTON; 1962141cc406Sopenharmony_ci session->options[OPT_CLEAR_CALIBRATION].descriptor.unit = SANE_UNIT_NONE; 1963141cc406Sopenharmony_ci session->options[OPT_CLEAR_CALIBRATION].descriptor.cap = 1964141cc406Sopenharmony_ci SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED | 1965141cc406Sopenharmony_ci SANE_CAP_AUTOMATIC; 1966141cc406Sopenharmony_ci session->options[OPT_CLEAR_CALIBRATION].value.b = 0; 1967141cc406Sopenharmony_ci 1968141cc406Sopenharmony_ci /* until work on calibration isfinished */ 1969141cc406Sopenharmony_ci DISABLE (OPT_CALIBRATE); 1970141cc406Sopenharmony_ci DISABLE (OPT_CLEAR_CALIBRATION); 1971141cc406Sopenharmony_ci 1972141cc406Sopenharmony_ci DBG (DBG_proc, "init_options: exit\n"); 1973141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1974141cc406Sopenharmony_ci} 1975141cc406Sopenharmony_ci 1976141cc406Sopenharmony_ci/** @brief physical probe of a device 1977141cc406Sopenharmony_ci * This function probes for a scanning device using the given name. If the 1978141cc406Sopenharmony_ci * device is managed, a model structure describing the device will be returned. 1979141cc406Sopenharmony_ci * @param devicename low level device to access to probe hardware 1980141cc406Sopenharmony_ci * @return NULL is the device is unsupported, or a model struct describing the 1981141cc406Sopenharmony_ci * device. 1982141cc406Sopenharmony_ci */ 1983141cc406Sopenharmony_ciP5_Model * 1984141cc406Sopenharmony_ciprobe (const char *devicename) 1985141cc406Sopenharmony_ci{ 1986141cc406Sopenharmony_ci int fd; 1987141cc406Sopenharmony_ci 1988141cc406Sopenharmony_ci /* open parallel port device */ 1989141cc406Sopenharmony_ci fd = open_pp (devicename); 1990141cc406Sopenharmony_ci if (fd < 0) 1991141cc406Sopenharmony_ci { 1992141cc406Sopenharmony_ci DBG (DBG_error, "probe: failed to open '%s' device!\n", devicename); 1993141cc406Sopenharmony_ci return NULL; 1994141cc406Sopenharmony_ci } 1995141cc406Sopenharmony_ci 1996141cc406Sopenharmony_ci /* now try to connect to scanner */ 1997141cc406Sopenharmony_ci if (connect (fd) != SANE_TRUE) 1998141cc406Sopenharmony_ci { 1999141cc406Sopenharmony_ci DBG (DBG_error, "probe: failed to connect!\n"); 2000141cc406Sopenharmony_ci close_pp (fd); 2001141cc406Sopenharmony_ci return NULL; 2002141cc406Sopenharmony_ci } 2003141cc406Sopenharmony_ci 2004141cc406Sopenharmony_ci /* set up for memory test */ 2005141cc406Sopenharmony_ci write_reg (fd, REG1, 0x00); 2006141cc406Sopenharmony_ci write_reg (fd, REG7, 0x00); 2007141cc406Sopenharmony_ci write_reg (fd, REG0, 0x00); 2008141cc406Sopenharmony_ci write_reg (fd, REG1, 0x00); 2009141cc406Sopenharmony_ci write_reg (fd, REGF, 0x80); 2010141cc406Sopenharmony_ci if (memtest (fd, 0x0100) != SANE_TRUE) 2011141cc406Sopenharmony_ci { 2012141cc406Sopenharmony_ci disconnect (fd); 2013141cc406Sopenharmony_ci close_pp (fd); 2014141cc406Sopenharmony_ci DBG (DBG_error, "probe: memory test failed!\n"); 2015141cc406Sopenharmony_ci return NULL; 2016141cc406Sopenharmony_ci } 2017141cc406Sopenharmony_ci else 2018141cc406Sopenharmony_ci { 2019141cc406Sopenharmony_ci DBG (DBG_info, "memtest() OK...\n"); 2020141cc406Sopenharmony_ci } 2021141cc406Sopenharmony_ci write_reg (fd, REG7, 0x00); 2022141cc406Sopenharmony_ci 2023141cc406Sopenharmony_ci /* check for document presence 0xC6: present, 0xC3 no document */ 2024141cc406Sopenharmony_ci test_document (fd); 2025141cc406Sopenharmony_ci 2026141cc406Sopenharmony_ci /* release device and parport for next uses */ 2027141cc406Sopenharmony_ci disconnect (fd); 2028141cc406Sopenharmony_ci close_pp (fd); 2029141cc406Sopenharmony_ci 2030141cc406Sopenharmony_ci /* for there is only one supported model, so we use hardcoded values */ 2031141cc406Sopenharmony_ci DBG (DBG_proc, "probe: exit\n"); 2032141cc406Sopenharmony_ci return &pagepartner_model; 2033141cc406Sopenharmony_ci} 2034141cc406Sopenharmony_ci 2035141cc406Sopenharmony_ci 2036141cc406Sopenharmony_ci/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ 2037