1141cc406Sopenharmony_ci/* 2141cc406Sopenharmony_ci Copyright (C) 2008, Panasonic Russia Ltd. 3141cc406Sopenharmony_ci Copyright (C) 2010-2011, m. allan noah 4141cc406Sopenharmony_ci*/ 5141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 6141cc406Sopenharmony_ci Panasonic KV-S1020C / KV-S1025C USB scanners. 7141cc406Sopenharmony_ci*/ 8141cc406Sopenharmony_ci 9141cc406Sopenharmony_ci#define DEBUG_NOT_STATIC 10141cc406Sopenharmony_ci 11141cc406Sopenharmony_ci#include "../include/sane/config.h" 12141cc406Sopenharmony_ci 13141cc406Sopenharmony_ci#include <errno.h> 14141cc406Sopenharmony_ci#include <fcntl.h> 15141cc406Sopenharmony_ci#include <limits.h> 16141cc406Sopenharmony_ci#include <signal.h> 17141cc406Sopenharmony_ci#include <stdio.h> 18141cc406Sopenharmony_ci#include <stdlib.h> 19141cc406Sopenharmony_ci#include <string.h> 20141cc406Sopenharmony_ci#include <sys/types.h> 21141cc406Sopenharmony_ci#include <sys/wait.h> 22141cc406Sopenharmony_ci#include <unistd.h> 23141cc406Sopenharmony_ci 24141cc406Sopenharmony_ci#include "../include/sane/sane.h" 25141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 26141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 27141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h" 28141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 29141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 30141cc406Sopenharmony_ci#include "../include/lassert.h" 31141cc406Sopenharmony_ci 32141cc406Sopenharmony_ci#include "kvs1025.h" 33141cc406Sopenharmony_ci#include "kvs1025_low.h" 34141cc406Sopenharmony_ci 35141cc406Sopenharmony_ci#include "../include/sane/sanei_debug.h" 36141cc406Sopenharmony_ci 37141cc406Sopenharmony_ci/* SANE backend operations, see SANE Standard for details 38141cc406Sopenharmony_ci https://sane-project.gitlab.io/standard/ */ 39141cc406Sopenharmony_ci 40141cc406Sopenharmony_ci/* Init the KV-S1025 SANE backend. This function must be called before any other 41141cc406Sopenharmony_ci SANE function can be called. */ 42141cc406Sopenharmony_ciSANE_Status 43141cc406Sopenharmony_cisane_init (SANE_Int * version_code, 44141cc406Sopenharmony_ci SANE_Auth_Callback __sane_unused__ authorize) 45141cc406Sopenharmony_ci{ 46141cc406Sopenharmony_ci SANE_Status status; 47141cc406Sopenharmony_ci 48141cc406Sopenharmony_ci DBG_INIT (); 49141cc406Sopenharmony_ci 50141cc406Sopenharmony_ci DBG (DBG_sane_init, "sane_init\n"); 51141cc406Sopenharmony_ci 52141cc406Sopenharmony_ci DBG (DBG_error, 53141cc406Sopenharmony_ci "This is panasonic KV-S1020C / KV-S1025C version %d.%d build %d\n", 54141cc406Sopenharmony_ci SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, V_BUILD); 55141cc406Sopenharmony_ci 56141cc406Sopenharmony_ci if (version_code) 57141cc406Sopenharmony_ci { 58141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, V_BUILD); 59141cc406Sopenharmony_ci } 60141cc406Sopenharmony_ci 61141cc406Sopenharmony_ci /* Initialize USB */ 62141cc406Sopenharmony_ci sanei_usb_init (); 63141cc406Sopenharmony_ci 64141cc406Sopenharmony_ci status = kv_enum_devices (); 65141cc406Sopenharmony_ci if (status) 66141cc406Sopenharmony_ci return status; 67141cc406Sopenharmony_ci 68141cc406Sopenharmony_ci DBG (DBG_proc, "sane_init: leave\n"); 69141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 70141cc406Sopenharmony_ci} 71141cc406Sopenharmony_ci 72141cc406Sopenharmony_ci/* Terminate the KV-S1025 SANE backend */ 73141cc406Sopenharmony_civoid 74141cc406Sopenharmony_cisane_exit (void) 75141cc406Sopenharmony_ci{ 76141cc406Sopenharmony_ci DBG (DBG_proc, "sane_exit: enter\n"); 77141cc406Sopenharmony_ci 78141cc406Sopenharmony_ci kv_exit (); 79141cc406Sopenharmony_ci 80141cc406Sopenharmony_ci DBG (DBG_proc, "sane_exit: exit\n"); 81141cc406Sopenharmony_ci} 82141cc406Sopenharmony_ci 83141cc406Sopenharmony_ci/* Get device list */ 84141cc406Sopenharmony_ciSANE_Status 85141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, 86141cc406Sopenharmony_ci SANE_Bool __sane_unused__ local_only) 87141cc406Sopenharmony_ci{ 88141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_devices: enter\n"); 89141cc406Sopenharmony_ci kv_get_devices_list (device_list); 90141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_devices: leave\n"); 91141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 92141cc406Sopenharmony_ci} 93141cc406Sopenharmony_ci 94141cc406Sopenharmony_ci/* Open device, return the device handle */ 95141cc406Sopenharmony_ciSANE_Status 96141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 97141cc406Sopenharmony_ci{ 98141cc406Sopenharmony_ci return kv_open_by_name (devicename, handle); 99141cc406Sopenharmony_ci} 100141cc406Sopenharmony_ci 101141cc406Sopenharmony_ci/* Close device */ 102141cc406Sopenharmony_civoid 103141cc406Sopenharmony_cisane_close (SANE_Handle handle) 104141cc406Sopenharmony_ci{ 105141cc406Sopenharmony_ci DBG (DBG_proc, "sane_close: enter\n"); 106141cc406Sopenharmony_ci kv_close ((PKV_DEV) handle); 107141cc406Sopenharmony_ci DBG (DBG_proc, "sane_close: leave\n"); 108141cc406Sopenharmony_ci} 109141cc406Sopenharmony_ci 110141cc406Sopenharmony_ci/* Get option descriptor */ 111141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 112141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 113141cc406Sopenharmony_ci{ 114141cc406Sopenharmony_ci return kv_get_option_descriptor ((PKV_DEV) handle, option); 115141cc406Sopenharmony_ci} 116141cc406Sopenharmony_ci 117141cc406Sopenharmony_ci/* Control option */ 118141cc406Sopenharmony_ciSANE_Status 119141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 120141cc406Sopenharmony_ci SANE_Action action, void *val, SANE_Int * info) 121141cc406Sopenharmony_ci{ 122141cc406Sopenharmony_ci return kv_control_option ((PKV_DEV) handle, option, action, val, info); 123141cc406Sopenharmony_ci} 124141cc406Sopenharmony_ci 125141cc406Sopenharmony_ci/* Get scan parameters */ 126141cc406Sopenharmony_ciSANE_Status 127141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 128141cc406Sopenharmony_ci{ 129141cc406Sopenharmony_ci PKV_DEV dev = (PKV_DEV) handle; 130141cc406Sopenharmony_ci 131141cc406Sopenharmony_ci int side = dev->current_side == SIDE_FRONT ? 0 : 1; 132141cc406Sopenharmony_ci 133141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_parameters: enter\n"); 134141cc406Sopenharmony_ci 135141cc406Sopenharmony_ci if (!(dev->scanning)) 136141cc406Sopenharmony_ci { 137141cc406Sopenharmony_ci /* Setup the parameters for the scan. (guessed value) */ 138141cc406Sopenharmony_ci int resolution = dev->val[OPT_RESOLUTION].w; 139141cc406Sopenharmony_ci int width, length, depth = kv_get_depth (kv_get_mode (dev));; 140141cc406Sopenharmony_ci 141141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_parameters: initial settings\n"); 142141cc406Sopenharmony_ci kv_calc_paper_size (dev, &width, &length); 143141cc406Sopenharmony_ci 144141cc406Sopenharmony_ci DBG (DBG_error, "Resolution = %d\n", resolution); 145141cc406Sopenharmony_ci DBG (DBG_error, "Paper width = %d, height = %d\n", width, length); 146141cc406Sopenharmony_ci 147141cc406Sopenharmony_ci /* Prepare the parameters for the caller. */ 148141cc406Sopenharmony_ci dev->params[0].format = kv_get_mode (dev) == SM_COLOR ? 149141cc406Sopenharmony_ci SANE_FRAME_RGB : SANE_FRAME_GRAY; 150141cc406Sopenharmony_ci 151141cc406Sopenharmony_ci dev->params[0].last_frame = SANE_TRUE; 152141cc406Sopenharmony_ci dev->params[0].pixels_per_line = ((width * resolution) / 1200) & (~0xf); 153141cc406Sopenharmony_ci 154141cc406Sopenharmony_ci dev->params[0].depth = depth > 8 ? 8 : depth; 155141cc406Sopenharmony_ci 156141cc406Sopenharmony_ci dev->params[0].bytes_per_line = 157141cc406Sopenharmony_ci (dev->params[0].pixels_per_line / 8) * depth; 158141cc406Sopenharmony_ci dev->params[0].lines = (length * resolution) / 1200; 159141cc406Sopenharmony_ci 160141cc406Sopenharmony_ci memcpy (&dev->params[1], &dev->params[0], sizeof (SANE_Parameters)); 161141cc406Sopenharmony_ci } 162141cc406Sopenharmony_ci 163141cc406Sopenharmony_ci /* Return the current values. */ 164141cc406Sopenharmony_ci if (params) 165141cc406Sopenharmony_ci *params = (dev->params[side]); 166141cc406Sopenharmony_ci 167141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_parameters: exit\n"); 168141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 169141cc406Sopenharmony_ci} 170141cc406Sopenharmony_ci 171141cc406Sopenharmony_ci/* Start scanning */ 172141cc406Sopenharmony_ciSANE_Status 173141cc406Sopenharmony_cisane_start (SANE_Handle handle) 174141cc406Sopenharmony_ci{ 175141cc406Sopenharmony_ci SANE_Status status; 176141cc406Sopenharmony_ci PKV_DEV dev = (PKV_DEV) handle; 177141cc406Sopenharmony_ci SANE_Bool dev_ready; 178141cc406Sopenharmony_ci KV_CMD_RESPONSE rs; 179141cc406Sopenharmony_ci 180141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: enter\n"); 181141cc406Sopenharmony_ci if (!dev->scanning) 182141cc406Sopenharmony_ci { 183141cc406Sopenharmony_ci /* open device */ 184141cc406Sopenharmony_ci if (!kv_already_open (dev)) 185141cc406Sopenharmony_ci { 186141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: need to open device\n"); 187141cc406Sopenharmony_ci status = kv_open (dev); 188141cc406Sopenharmony_ci if (status) 189141cc406Sopenharmony_ci { 190141cc406Sopenharmony_ci return status; 191141cc406Sopenharmony_ci } 192141cc406Sopenharmony_ci } 193141cc406Sopenharmony_ci /* Begin scan */ 194141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: begin scan\n"); 195141cc406Sopenharmony_ci 196141cc406Sopenharmony_ci /* Get necessary parameters */ 197141cc406Sopenharmony_ci sane_get_parameters (dev, NULL); 198141cc406Sopenharmony_ci 199141cc406Sopenharmony_ci dev->current_page = 0; 200141cc406Sopenharmony_ci dev->current_side = SIDE_FRONT; 201141cc406Sopenharmony_ci 202141cc406Sopenharmony_ci /* The scanner must be ready. */ 203141cc406Sopenharmony_ci status = CMD_test_unit_ready (dev, &dev_ready); 204141cc406Sopenharmony_ci if (status || !dev_ready) 205141cc406Sopenharmony_ci { 206141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 207141cc406Sopenharmony_ci } 208141cc406Sopenharmony_ci 209141cc406Sopenharmony_ci if (!strcmp (dev->val[OPT_MANUALFEED].s, "off")) 210141cc406Sopenharmony_ci { 211141cc406Sopenharmony_ci status = CMD_get_document_existanse (dev); 212141cc406Sopenharmony_ci if (status) 213141cc406Sopenharmony_ci { 214141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: exit with no more docs\n"); 215141cc406Sopenharmony_ci return status; 216141cc406Sopenharmony_ci } 217141cc406Sopenharmony_ci } 218141cc406Sopenharmony_ci 219141cc406Sopenharmony_ci /* Set window */ 220141cc406Sopenharmony_ci status = CMD_reset_window (dev); 221141cc406Sopenharmony_ci if (status) 222141cc406Sopenharmony_ci { 223141cc406Sopenharmony_ci return status; 224141cc406Sopenharmony_ci } 225141cc406Sopenharmony_ci 226141cc406Sopenharmony_ci status = CMD_set_window (dev, SIDE_FRONT, &rs); 227141cc406Sopenharmony_ci if (status) 228141cc406Sopenharmony_ci { 229141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: error setting window\n"); 230141cc406Sopenharmony_ci return status; 231141cc406Sopenharmony_ci } 232141cc406Sopenharmony_ci 233141cc406Sopenharmony_ci if (rs.status) 234141cc406Sopenharmony_ci { 235141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: error setting window\n"); 236141cc406Sopenharmony_ci DBG (DBG_proc, 237141cc406Sopenharmony_ci "sane_start: sense_key=0x%x, ASC=0x%x, ASCQ=0x%x\n", 238141cc406Sopenharmony_ci get_RS_sense_key (rs.sense), 239141cc406Sopenharmony_ci get_RS_ASC (rs.sense), get_RS_ASCQ (rs.sense)); 240141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 241141cc406Sopenharmony_ci } 242141cc406Sopenharmony_ci 243141cc406Sopenharmony_ci if (IS_DUPLEX (dev)) 244141cc406Sopenharmony_ci { 245141cc406Sopenharmony_ci status = CMD_set_window (dev, SIDE_BACK, &rs); 246141cc406Sopenharmony_ci 247141cc406Sopenharmony_ci if (status) 248141cc406Sopenharmony_ci { 249141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: error setting window\n"); 250141cc406Sopenharmony_ci return status; 251141cc406Sopenharmony_ci } 252141cc406Sopenharmony_ci if (rs.status) 253141cc406Sopenharmony_ci { 254141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: error setting window\n"); 255141cc406Sopenharmony_ci DBG (DBG_proc, 256141cc406Sopenharmony_ci "sane_start: sense_key=0x%x, " 257141cc406Sopenharmony_ci "ASC=0x%x, ASCQ=0x%x\n", 258141cc406Sopenharmony_ci get_RS_sense_key (rs.sense), 259141cc406Sopenharmony_ci get_RS_ASC (rs.sense), get_RS_ASCQ (rs.sense)); 260141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 261141cc406Sopenharmony_ci } 262141cc406Sopenharmony_ci } 263141cc406Sopenharmony_ci 264141cc406Sopenharmony_ci /* Scan */ 265141cc406Sopenharmony_ci status = CMD_scan (dev); 266141cc406Sopenharmony_ci if (status) 267141cc406Sopenharmony_ci { 268141cc406Sopenharmony_ci return status; 269141cc406Sopenharmony_ci } 270141cc406Sopenharmony_ci 271141cc406Sopenharmony_ci status = AllocateImageBuffer (dev); 272141cc406Sopenharmony_ci if (status) 273141cc406Sopenharmony_ci { 274141cc406Sopenharmony_ci return status; 275141cc406Sopenharmony_ci } 276141cc406Sopenharmony_ci dev->scanning = 1; 277141cc406Sopenharmony_ci } 278141cc406Sopenharmony_ci else 279141cc406Sopenharmony_ci { 280141cc406Sopenharmony_ci /* renew page */ 281141cc406Sopenharmony_ci if (IS_DUPLEX (dev)) 282141cc406Sopenharmony_ci { 283141cc406Sopenharmony_ci if (dev->current_side == SIDE_FRONT) 284141cc406Sopenharmony_ci { 285141cc406Sopenharmony_ci /* back image data already read, so just return */ 286141cc406Sopenharmony_ci dev->current_side = SIDE_BACK; 287141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: duplex back\n"); 288141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 289141cc406Sopenharmony_ci goto cleanup; 290141cc406Sopenharmony_ci } 291141cc406Sopenharmony_ci else 292141cc406Sopenharmony_ci { 293141cc406Sopenharmony_ci dev->current_side = SIDE_FRONT; 294141cc406Sopenharmony_ci dev->current_page++; 295141cc406Sopenharmony_ci } 296141cc406Sopenharmony_ci } 297141cc406Sopenharmony_ci else 298141cc406Sopenharmony_ci { 299141cc406Sopenharmony_ci dev->current_page++; 300141cc406Sopenharmony_ci } 301141cc406Sopenharmony_ci } 302141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: NOW SCANNING page\n"); 303141cc406Sopenharmony_ci 304141cc406Sopenharmony_ci /* Read image data */ 305141cc406Sopenharmony_ci status = ReadImageData (dev, dev->current_page); 306141cc406Sopenharmony_ci if (status) 307141cc406Sopenharmony_ci { 308141cc406Sopenharmony_ci dev->scanning = 0; 309141cc406Sopenharmony_ci return status; 310141cc406Sopenharmony_ci } 311141cc406Sopenharmony_ci 312141cc406Sopenharmony_ci /* Get picture element size */ 313141cc406Sopenharmony_ci { 314141cc406Sopenharmony_ci int width, height; 315141cc406Sopenharmony_ci status = CMD_read_pic_elements (dev, dev->current_page, 316141cc406Sopenharmony_ci SIDE_FRONT, &width, &height); 317141cc406Sopenharmony_ci if (status) 318141cc406Sopenharmony_ci return status; 319141cc406Sopenharmony_ci } 320141cc406Sopenharmony_ci 321141cc406Sopenharmony_ci if (IS_DUPLEX (dev)) 322141cc406Sopenharmony_ci { 323141cc406Sopenharmony_ci int width, height; 324141cc406Sopenharmony_ci status = CMD_read_pic_elements (dev, dev->current_page, 325141cc406Sopenharmony_ci SIDE_BACK, &width, &height); 326141cc406Sopenharmony_ci if (status) 327141cc406Sopenharmony_ci return status; 328141cc406Sopenharmony_ci } 329141cc406Sopenharmony_ci 330141cc406Sopenharmony_ci /* software based enhancement functions from sanei_magic */ 331141cc406Sopenharmony_ci /* these will modify the image, and adjust the params */ 332141cc406Sopenharmony_ci /* at this point, we are only looking at the front image */ 333141cc406Sopenharmony_ci /* of simplex or duplex data, back side has already exited */ 334141cc406Sopenharmony_ci /* so, we do both sides now, if required */ 335141cc406Sopenharmony_ci if (dev->val[OPT_SWDESKEW].w){ 336141cc406Sopenharmony_ci buffer_deskew(dev,SIDE_FRONT); 337141cc406Sopenharmony_ci } 338141cc406Sopenharmony_ci if (dev->val[OPT_SWCROP].w){ 339141cc406Sopenharmony_ci buffer_crop(dev,SIDE_FRONT); 340141cc406Sopenharmony_ci } 341141cc406Sopenharmony_ci if (dev->val[OPT_SWDESPECK].w){ 342141cc406Sopenharmony_ci buffer_despeck(dev,SIDE_FRONT); 343141cc406Sopenharmony_ci } 344141cc406Sopenharmony_ci if (dev->val[OPT_SWDEROTATE].w || dev->val[OPT_ROTATE].w){ 345141cc406Sopenharmony_ci buffer_rotate(dev,SIDE_FRONT); 346141cc406Sopenharmony_ci } 347141cc406Sopenharmony_ci 348141cc406Sopenharmony_ci if (IS_DUPLEX (dev)){ 349141cc406Sopenharmony_ci if (dev->val[OPT_SWDESKEW].w){ 350141cc406Sopenharmony_ci buffer_deskew(dev,SIDE_BACK); 351141cc406Sopenharmony_ci } 352141cc406Sopenharmony_ci if (dev->val[OPT_SWCROP].w){ 353141cc406Sopenharmony_ci buffer_crop(dev,SIDE_BACK); 354141cc406Sopenharmony_ci } 355141cc406Sopenharmony_ci if (dev->val[OPT_SWDESPECK].w){ 356141cc406Sopenharmony_ci buffer_despeck(dev,SIDE_BACK); 357141cc406Sopenharmony_ci } 358141cc406Sopenharmony_ci if (dev->val[OPT_SWDEROTATE].w || dev->val[OPT_ROTATE].w){ 359141cc406Sopenharmony_ci buffer_rotate(dev,SIDE_BACK); 360141cc406Sopenharmony_ci } 361141cc406Sopenharmony_ci } 362141cc406Sopenharmony_ci 363141cc406Sopenharmony_ci cleanup: 364141cc406Sopenharmony_ci 365141cc406Sopenharmony_ci /* check if we need to skip this page */ 366141cc406Sopenharmony_ci if (dev->val[OPT_SWSKIP].w && buffer_isblank(dev,dev->current_side)){ 367141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: blank page, recurse\n"); 368141cc406Sopenharmony_ci return sane_start(handle); 369141cc406Sopenharmony_ci } 370141cc406Sopenharmony_ci 371141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: exit\n"); 372141cc406Sopenharmony_ci return status; 373141cc406Sopenharmony_ci} 374141cc406Sopenharmony_ci 375141cc406Sopenharmony_ciSANE_Status 376141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, 377141cc406Sopenharmony_ci SANE_Int max_len, SANE_Int * len) 378141cc406Sopenharmony_ci{ 379141cc406Sopenharmony_ci PKV_DEV dev = (PKV_DEV) handle; 380141cc406Sopenharmony_ci int side = dev->current_side == SIDE_FRONT ? 0 : 1; 381141cc406Sopenharmony_ci 382141cc406Sopenharmony_ci int size = max_len; 383141cc406Sopenharmony_ci if (!dev->scanning) 384141cc406Sopenharmony_ci return SANE_STATUS_EOF; 385141cc406Sopenharmony_ci 386141cc406Sopenharmony_ci if (size > dev->img_size[side]) 387141cc406Sopenharmony_ci size = dev->img_size[side]; 388141cc406Sopenharmony_ci 389141cc406Sopenharmony_ci if (size == 0) 390141cc406Sopenharmony_ci { 391141cc406Sopenharmony_ci *len = size; 392141cc406Sopenharmony_ci return SANE_STATUS_EOF; 393141cc406Sopenharmony_ci } 394141cc406Sopenharmony_ci 395141cc406Sopenharmony_ci if (dev->val[OPT_INVERSE].w && 396141cc406Sopenharmony_ci (kv_get_mode (dev) == SM_BINARY || kv_get_mode (dev) == SM_DITHER)) 397141cc406Sopenharmony_ci { 398141cc406Sopenharmony_ci int i; 399141cc406Sopenharmony_ci unsigned char *p = dev->img_pt[side]; 400141cc406Sopenharmony_ci for (i = 0; i < size; i++) 401141cc406Sopenharmony_ci { 402141cc406Sopenharmony_ci buf[i] = ~p[i]; 403141cc406Sopenharmony_ci } 404141cc406Sopenharmony_ci } 405141cc406Sopenharmony_ci else 406141cc406Sopenharmony_ci { 407141cc406Sopenharmony_ci memcpy (buf, dev->img_pt[side], size); 408141cc406Sopenharmony_ci } 409141cc406Sopenharmony_ci 410141cc406Sopenharmony_ci /*hexdump(DBG_error, "img data", buf, 128); */ 411141cc406Sopenharmony_ci 412141cc406Sopenharmony_ci dev->img_pt[side] += size; 413141cc406Sopenharmony_ci dev->img_size[side] -= size; 414141cc406Sopenharmony_ci 415141cc406Sopenharmony_ci DBG (DBG_proc, "sane_read: %d bytes to read, " 416141cc406Sopenharmony_ci "%d bytes read, EOF=%s %d\n", 417141cc406Sopenharmony_ci max_len, size, dev->img_size[side] == 0 ? "True" : "False", side); 418141cc406Sopenharmony_ci 419141cc406Sopenharmony_ci if (len) 420141cc406Sopenharmony_ci { 421141cc406Sopenharmony_ci *len = size; 422141cc406Sopenharmony_ci } 423141cc406Sopenharmony_ci if (dev->img_size[side] == 0) 424141cc406Sopenharmony_ci { 425141cc406Sopenharmony_ci if (!strcmp (dev->val[OPT_FEEDER_MODE].s, "single")) 426141cc406Sopenharmony_ci if ((IS_DUPLEX (dev) && side) || !IS_DUPLEX (dev)) 427141cc406Sopenharmony_ci dev->scanning = 0; 428141cc406Sopenharmony_ci } 429141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 430141cc406Sopenharmony_ci} 431141cc406Sopenharmony_ci 432141cc406Sopenharmony_civoid 433141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 434141cc406Sopenharmony_ci{ 435141cc406Sopenharmony_ci PKV_DEV dev = (PKV_DEV) handle; 436141cc406Sopenharmony_ci DBG (DBG_proc, "sane_cancel: scan canceled.\n"); 437141cc406Sopenharmony_ci dev->scanning = 0; 438141cc406Sopenharmony_ci 439141cc406Sopenharmony_ci kv_close (dev); 440141cc406Sopenharmony_ci} 441141cc406Sopenharmony_ci 442141cc406Sopenharmony_ciSANE_Status 443141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle h, SANE_Bool m) 444141cc406Sopenharmony_ci{ 445141cc406Sopenharmony_ci (void) h; 446141cc406Sopenharmony_ci (void) m; 447141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 448141cc406Sopenharmony_ci} 449141cc406Sopenharmony_ci 450141cc406Sopenharmony_ciSANE_Status 451141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle h, SANE_Int * fd) 452141cc406Sopenharmony_ci{ 453141cc406Sopenharmony_ci (void) h; 454141cc406Sopenharmony_ci (void) fd; 455141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 456141cc406Sopenharmony_ci} 457