1141cc406Sopenharmony_ci/* 2141cc406Sopenharmony_ci Copyright (C) 2008, Panasonic Russia Ltd. 3141cc406Sopenharmony_ci*/ 4141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 5141cc406Sopenharmony_ci Panasonic KV-S1020C / KV-S1025C USB scanners. 6141cc406Sopenharmony_ci*/ 7141cc406Sopenharmony_ci 8141cc406Sopenharmony_ci#define DEBUG_DECLARE_ONLY 9141cc406Sopenharmony_ci 10141cc406Sopenharmony_ci#include "../include/sane/config.h" 11141cc406Sopenharmony_ci 12141cc406Sopenharmony_ci#include <errno.h> 13141cc406Sopenharmony_ci#include <fcntl.h> 14141cc406Sopenharmony_ci#include <limits.h> 15141cc406Sopenharmony_ci#include <signal.h> 16141cc406Sopenharmony_ci#include <stdio.h> 17141cc406Sopenharmony_ci#include <stdlib.h> 18141cc406Sopenharmony_ci#include <string.h> 19141cc406Sopenharmony_ci#include <sys/types.h> 20141cc406Sopenharmony_ci#include <sys/wait.h> 21141cc406Sopenharmony_ci#include <unistd.h> 22141cc406Sopenharmony_ci 23141cc406Sopenharmony_ci#include "../include/sane/sane.h" 24141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 25141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 26141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h" 27141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 28141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 29141cc406Sopenharmony_ci#include "../include/lassert.h" 30141cc406Sopenharmony_ci#include "../include/sane/sanei_magic.h" 31141cc406Sopenharmony_ci 32141cc406Sopenharmony_ci#include "kvs1025.h" 33141cc406Sopenharmony_ci#include "kvs1025_low.h" 34141cc406Sopenharmony_ci#include "kvs1025_usb.h" 35141cc406Sopenharmony_ci 36141cc406Sopenharmony_ci#include "../include/sane/sanei_debug.h" 37141cc406Sopenharmony_ci 38141cc406Sopenharmony_ci/* Global storage */ 39141cc406Sopenharmony_ci 40141cc406Sopenharmony_ciPKV_DEV g_devices = NULL; /* Chain of devices */ 41141cc406Sopenharmony_ciconst SANE_Device **g_devlist = NULL; 42141cc406Sopenharmony_ci 43141cc406Sopenharmony_ci/* Static functions */ 44141cc406Sopenharmony_ci 45141cc406Sopenharmony_ci/* Free one device */ 46141cc406Sopenharmony_cistatic void 47141cc406Sopenharmony_cikv_free (KV_DEV ** pdev) 48141cc406Sopenharmony_ci{ 49141cc406Sopenharmony_ci KV_DEV *dev; 50141cc406Sopenharmony_ci 51141cc406Sopenharmony_ci dev = *pdev; 52141cc406Sopenharmony_ci 53141cc406Sopenharmony_ci if (dev == NULL) 54141cc406Sopenharmony_ci return; 55141cc406Sopenharmony_ci 56141cc406Sopenharmony_ci DBG (DBG_proc, "kv_free : enter\n"); 57141cc406Sopenharmony_ci 58141cc406Sopenharmony_ci kv_close (dev); 59141cc406Sopenharmony_ci 60141cc406Sopenharmony_ci DBG (DBG_proc, "kv_free : free image buffer 0 \n"); 61141cc406Sopenharmony_ci if (dev->img_buffers[0]) 62141cc406Sopenharmony_ci free (dev->img_buffers[0]); 63141cc406Sopenharmony_ci DBG (DBG_proc, "kv_free : free image buffer 1 \n"); 64141cc406Sopenharmony_ci if (dev->img_buffers[1]) 65141cc406Sopenharmony_ci free (dev->img_buffers[1]); 66141cc406Sopenharmony_ci DBG (DBG_proc, "kv_free : free scsi device name\n"); 67141cc406Sopenharmony_ci if (dev->scsi_device_name) 68141cc406Sopenharmony_ci free (dev->scsi_device_name); 69141cc406Sopenharmony_ci 70141cc406Sopenharmony_ci DBG (DBG_proc, "kv_free : free SCSI buffer\n"); 71141cc406Sopenharmony_ci if (dev->buffer0) 72141cc406Sopenharmony_ci free (dev->buffer0); 73141cc406Sopenharmony_ci 74141cc406Sopenharmony_ci DBG (DBG_proc, "kv_free : free dev \n"); 75141cc406Sopenharmony_ci free (dev); 76141cc406Sopenharmony_ci 77141cc406Sopenharmony_ci *pdev = NULL; 78141cc406Sopenharmony_ci 79141cc406Sopenharmony_ci DBG (DBG_proc, "kv_free : exit\n"); 80141cc406Sopenharmony_ci} 81141cc406Sopenharmony_ci 82141cc406Sopenharmony_ci/* Free all devices */ 83141cc406Sopenharmony_cistatic void 84141cc406Sopenharmony_cikv_free_devices (void) 85141cc406Sopenharmony_ci{ 86141cc406Sopenharmony_ci PKV_DEV dev; 87141cc406Sopenharmony_ci while (g_devices) 88141cc406Sopenharmony_ci { 89141cc406Sopenharmony_ci dev = g_devices; 90141cc406Sopenharmony_ci g_devices = dev->next; 91141cc406Sopenharmony_ci kv_free (&dev); 92141cc406Sopenharmony_ci } 93141cc406Sopenharmony_ci if (g_devlist) 94141cc406Sopenharmony_ci { 95141cc406Sopenharmony_ci free (g_devlist); 96141cc406Sopenharmony_ci g_devlist = NULL; 97141cc406Sopenharmony_ci } 98141cc406Sopenharmony_ci} 99141cc406Sopenharmony_ci 100141cc406Sopenharmony_ci/* Get all supported scanners, and store into g_scanners_supported */ 101141cc406Sopenharmony_ciSANE_Status 102141cc406Sopenharmony_cikv_enum_devices (void) 103141cc406Sopenharmony_ci{ 104141cc406Sopenharmony_ci SANE_Status status; 105141cc406Sopenharmony_ci kv_free_devices (); 106141cc406Sopenharmony_ci status = kv_usb_enum_devices (); 107141cc406Sopenharmony_ci if (status) 108141cc406Sopenharmony_ci { 109141cc406Sopenharmony_ci kv_free_devices (); 110141cc406Sopenharmony_ci } 111141cc406Sopenharmony_ci 112141cc406Sopenharmony_ci return status; 113141cc406Sopenharmony_ci} 114141cc406Sopenharmony_ci 115141cc406Sopenharmony_ci/* Return devices list to the front end */ 116141cc406Sopenharmony_civoid 117141cc406Sopenharmony_cikv_get_devices_list (const SANE_Device *** devices_list) 118141cc406Sopenharmony_ci{ 119141cc406Sopenharmony_ci *devices_list = g_devlist; 120141cc406Sopenharmony_ci} 121141cc406Sopenharmony_ci 122141cc406Sopenharmony_ci/* Close all open handles and clean up global storage */ 123141cc406Sopenharmony_civoid 124141cc406Sopenharmony_cikv_exit (void) 125141cc406Sopenharmony_ci{ 126141cc406Sopenharmony_ci kv_free_devices (); /* Free all devices */ 127141cc406Sopenharmony_ci kv_usb_cleanup (); /* Clean USB bus */ 128141cc406Sopenharmony_ci} 129141cc406Sopenharmony_ci 130141cc406Sopenharmony_ci/* Open device by name */ 131141cc406Sopenharmony_ciSANE_Status 132141cc406Sopenharmony_cikv_open_by_name (SANE_String_Const devicename, SANE_Handle * handle) 133141cc406Sopenharmony_ci{ 134141cc406Sopenharmony_ci 135141cc406Sopenharmony_ci PKV_DEV pd = g_devices; 136141cc406Sopenharmony_ci DBG (DBG_proc, "sane_open: enter (dev_name=%s)\n", devicename); 137141cc406Sopenharmony_ci while (pd) 138141cc406Sopenharmony_ci { 139141cc406Sopenharmony_ci if (strcmp (pd->sane.name, devicename) == 0) 140141cc406Sopenharmony_ci { 141141cc406Sopenharmony_ci if (kv_open (pd) == 0) 142141cc406Sopenharmony_ci { 143141cc406Sopenharmony_ci *handle = (SANE_Handle) pd; 144141cc406Sopenharmony_ci DBG (DBG_proc, "sane_open: leave\n"); 145141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 146141cc406Sopenharmony_ci } 147141cc406Sopenharmony_ci } 148141cc406Sopenharmony_ci pd = pd->next; 149141cc406Sopenharmony_ci } 150141cc406Sopenharmony_ci DBG (DBG_proc, "sane_open: leave -- no device found\n"); 151141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 152141cc406Sopenharmony_ci} 153141cc406Sopenharmony_ci 154141cc406Sopenharmony_ci/* Open a device */ 155141cc406Sopenharmony_ciSANE_Status 156141cc406Sopenharmony_cikv_open (PKV_DEV dev) 157141cc406Sopenharmony_ci{ 158141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_UNSUPPORTED; 159141cc406Sopenharmony_ci int i; 160141cc406Sopenharmony_ci#define RETRAY_NUM 3 161141cc406Sopenharmony_ci 162141cc406Sopenharmony_ci 163141cc406Sopenharmony_ci if (dev->bus_mode == KV_USB_BUS) 164141cc406Sopenharmony_ci { 165141cc406Sopenharmony_ci status = kv_usb_open (dev); 166141cc406Sopenharmony_ci } 167141cc406Sopenharmony_ci if (status) 168141cc406Sopenharmony_ci return status; 169141cc406Sopenharmony_ci for (i = 0; i < RETRAY_NUM; i++) 170141cc406Sopenharmony_ci { 171141cc406Sopenharmony_ci SANE_Bool dev_ready; 172141cc406Sopenharmony_ci status = CMD_test_unit_ready (dev, &dev_ready); 173141cc406Sopenharmony_ci if (!status && dev_ready) 174141cc406Sopenharmony_ci break; 175141cc406Sopenharmony_ci } 176141cc406Sopenharmony_ci 177141cc406Sopenharmony_ci if (status == 0) 178141cc406Sopenharmony_ci { 179141cc406Sopenharmony_ci /* Read device support info */ 180141cc406Sopenharmony_ci status = CMD_read_support_info (dev); 181141cc406Sopenharmony_ci 182141cc406Sopenharmony_ci if (status == 0) 183141cc406Sopenharmony_ci { 184141cc406Sopenharmony_ci /* Init options */ 185141cc406Sopenharmony_ci kv_init_options (dev); 186141cc406Sopenharmony_ci status = CMD_set_timeout (dev, dev->val[OPT_FEED_TIMEOUT].w); 187141cc406Sopenharmony_ci } 188141cc406Sopenharmony_ci } 189141cc406Sopenharmony_ci dev->scanning = 0; 190141cc406Sopenharmony_ci return status; 191141cc406Sopenharmony_ci} 192141cc406Sopenharmony_ci 193141cc406Sopenharmony_ci/* Check if device is already open */ 194141cc406Sopenharmony_ci 195141cc406Sopenharmony_ciSANE_Bool 196141cc406Sopenharmony_cikv_already_open (PKV_DEV dev) 197141cc406Sopenharmony_ci{ 198141cc406Sopenharmony_ci SANE_Bool status = 0; 199141cc406Sopenharmony_ci 200141cc406Sopenharmony_ci if (dev->bus_mode == KV_USB_BUS) 201141cc406Sopenharmony_ci { 202141cc406Sopenharmony_ci status = kv_usb_already_open (dev); 203141cc406Sopenharmony_ci } 204141cc406Sopenharmony_ci 205141cc406Sopenharmony_ci return status; 206141cc406Sopenharmony_ci} 207141cc406Sopenharmony_ci 208141cc406Sopenharmony_ci/* Close a device */ 209141cc406Sopenharmony_civoid 210141cc406Sopenharmony_cikv_close (PKV_DEV dev) 211141cc406Sopenharmony_ci{ 212141cc406Sopenharmony_ci if (dev->bus_mode == KV_USB_BUS) 213141cc406Sopenharmony_ci { 214141cc406Sopenharmony_ci kv_usb_close (dev); 215141cc406Sopenharmony_ci } 216141cc406Sopenharmony_ci dev->scanning = 0; 217141cc406Sopenharmony_ci} 218141cc406Sopenharmony_ci 219141cc406Sopenharmony_ci/* Send command to a device */ 220141cc406Sopenharmony_ciSANE_Status 221141cc406Sopenharmony_cikv_send_command (PKV_DEV dev, 222141cc406Sopenharmony_ci PKV_CMD_HEADER header, PKV_CMD_RESPONSE response) 223141cc406Sopenharmony_ci{ 224141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_UNSUPPORTED; 225141cc406Sopenharmony_ci if (dev->bus_mode == KV_USB_BUS) 226141cc406Sopenharmony_ci { 227141cc406Sopenharmony_ci if (!kv_usb_already_open(dev)) 228141cc406Sopenharmony_ci { 229141cc406Sopenharmony_ci DBG (DBG_error, "kv_send_command error: device not open.\n"); 230141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 231141cc406Sopenharmony_ci } 232141cc406Sopenharmony_ci 233141cc406Sopenharmony_ci status = kv_usb_send_command (dev, header, response); 234141cc406Sopenharmony_ci } 235141cc406Sopenharmony_ci 236141cc406Sopenharmony_ci return status; 237141cc406Sopenharmony_ci} 238141cc406Sopenharmony_ci 239141cc406Sopenharmony_ci/* Commands */ 240141cc406Sopenharmony_ci 241141cc406Sopenharmony_ciSANE_Status 242141cc406Sopenharmony_ciCMD_test_unit_ready (PKV_DEV dev, SANE_Bool * ready) 243141cc406Sopenharmony_ci{ 244141cc406Sopenharmony_ci SANE_Status status; 245141cc406Sopenharmony_ci KV_CMD_HEADER hdr; 246141cc406Sopenharmony_ci KV_CMD_RESPONSE rs; 247141cc406Sopenharmony_ci 248141cc406Sopenharmony_ci DBG (DBG_proc, "CMD_test_unit_ready\n"); 249141cc406Sopenharmony_ci 250141cc406Sopenharmony_ci memset (&hdr, 0, sizeof (hdr)); 251141cc406Sopenharmony_ci 252141cc406Sopenharmony_ci hdr.direction = KV_CMD_NONE; 253141cc406Sopenharmony_ci hdr.cdb[0] = SCSI_TEST_UNIT_READY; 254141cc406Sopenharmony_ci hdr.cdb_size = 6; 255141cc406Sopenharmony_ci 256141cc406Sopenharmony_ci status = kv_send_command (dev, &hdr, &rs); 257141cc406Sopenharmony_ci 258141cc406Sopenharmony_ci if (status == 0) 259141cc406Sopenharmony_ci { 260141cc406Sopenharmony_ci *ready = (rs.status == KV_SUCCESS ? 1 : 0); 261141cc406Sopenharmony_ci } 262141cc406Sopenharmony_ci 263141cc406Sopenharmony_ci return status; 264141cc406Sopenharmony_ci} 265141cc406Sopenharmony_ci 266141cc406Sopenharmony_ciSANE_Status 267141cc406Sopenharmony_ciCMD_set_timeout (PKV_DEV dev, SANE_Word timeout) 268141cc406Sopenharmony_ci{ 269141cc406Sopenharmony_ci SANE_Status status; 270141cc406Sopenharmony_ci KV_CMD_HEADER hdr; 271141cc406Sopenharmony_ci KV_CMD_RESPONSE rs; 272141cc406Sopenharmony_ci 273141cc406Sopenharmony_ci DBG (DBG_proc, "CMD_set_timeout\n"); 274141cc406Sopenharmony_ci 275141cc406Sopenharmony_ci memset (&hdr, 0, sizeof (hdr)); 276141cc406Sopenharmony_ci 277141cc406Sopenharmony_ci hdr.direction = KV_CMD_OUT; 278141cc406Sopenharmony_ci hdr.cdb[0] = SCSI_SET_TIMEOUT; 279141cc406Sopenharmony_ci hdr.cdb[2] = 0x8D; 280141cc406Sopenharmony_ci hdr.cdb[8] = 0x2; 281141cc406Sopenharmony_ci hdr.cdb_size = 10; 282141cc406Sopenharmony_ci hdr.data = dev->buffer; 283141cc406Sopenharmony_ci dev->buffer[0] = 0; 284141cc406Sopenharmony_ci dev->buffer[1] = (SANE_Byte) timeout; 285141cc406Sopenharmony_ci hdr.data_size = 2; 286141cc406Sopenharmony_ci 287141cc406Sopenharmony_ci status = kv_send_command (dev, &hdr, &rs); 288141cc406Sopenharmony_ci 289141cc406Sopenharmony_ci return status; 290141cc406Sopenharmony_ci} 291141cc406Sopenharmony_ci 292141cc406Sopenharmony_ciSANE_Status 293141cc406Sopenharmony_ciCMD_read_support_info (PKV_DEV dev) 294141cc406Sopenharmony_ci{ 295141cc406Sopenharmony_ci SANE_Status status; 296141cc406Sopenharmony_ci KV_CMD_HEADER hdr; 297141cc406Sopenharmony_ci KV_CMD_RESPONSE rs; 298141cc406Sopenharmony_ci 299141cc406Sopenharmony_ci DBG (DBG_proc, "CMD_read_support_info\n"); 300141cc406Sopenharmony_ci 301141cc406Sopenharmony_ci memset (&hdr, 0, sizeof (hdr)); 302141cc406Sopenharmony_ci 303141cc406Sopenharmony_ci hdr.direction = KV_CMD_IN; 304141cc406Sopenharmony_ci hdr.cdb_size = 10; 305141cc406Sopenharmony_ci hdr.cdb[0] = SCSI_READ_10; 306141cc406Sopenharmony_ci hdr.cdb[2] = 0x93; 307141cc406Sopenharmony_ci Ito24 (32, &hdr.cdb[6]); 308141cc406Sopenharmony_ci hdr.data = dev->buffer; 309141cc406Sopenharmony_ci hdr.data_size = 32; 310141cc406Sopenharmony_ci 311141cc406Sopenharmony_ci status = kv_send_command (dev, &hdr, &rs); 312141cc406Sopenharmony_ci 313141cc406Sopenharmony_ci DBG (DBG_error, "test.\n"); 314141cc406Sopenharmony_ci 315141cc406Sopenharmony_ci if (status == 0) 316141cc406Sopenharmony_ci { 317141cc406Sopenharmony_ci if (rs.status == 0) 318141cc406Sopenharmony_ci { 319141cc406Sopenharmony_ci int min_x_res, min_y_res, max_x_res, max_y_res; 320141cc406Sopenharmony_ci int step_x_res, step_y_res; 321141cc406Sopenharmony_ci 322141cc406Sopenharmony_ci dev->support_info.memory_size 323141cc406Sopenharmony_ci = (dev->buffer[2] << 8 | dev->buffer[3]); 324141cc406Sopenharmony_ci min_x_res = (dev->buffer[4] << 8) | dev->buffer[5]; 325141cc406Sopenharmony_ci min_y_res = (dev->buffer[6] << 8) | dev->buffer[7]; 326141cc406Sopenharmony_ci max_x_res = (dev->buffer[8] << 8) | dev->buffer[9]; 327141cc406Sopenharmony_ci max_y_res = (dev->buffer[10] << 8) | dev->buffer[11]; 328141cc406Sopenharmony_ci step_x_res = (dev->buffer[12] << 8) | dev->buffer[13]; 329141cc406Sopenharmony_ci step_y_res = (dev->buffer[14] << 8) | dev->buffer[15]; 330141cc406Sopenharmony_ci 331141cc406Sopenharmony_ci dev->support_info.min_resolution = 332141cc406Sopenharmony_ci min_x_res > min_y_res ? min_x_res : min_y_res; 333141cc406Sopenharmony_ci dev->support_info.max_resolution = 334141cc406Sopenharmony_ci max_x_res < max_y_res ? max_x_res : max_y_res; 335141cc406Sopenharmony_ci dev->support_info.step_resolution = 336141cc406Sopenharmony_ci step_x_res > step_y_res ? step_x_res : step_y_res; 337141cc406Sopenharmony_ci dev->support_info.support_duplex = 338141cc406Sopenharmony_ci ((dev->buffer[0] & 0x08) == 0) ? 1 : 0; 339141cc406Sopenharmony_ci dev->support_info.support_lamp = 340141cc406Sopenharmony_ci ((dev->buffer[23] & 0x80) != 0) ? 1 : 0; 341141cc406Sopenharmony_ci 342141cc406Sopenharmony_ci dev->support_info.max_x_range = KV_MAX_X_RANGE; 343141cc406Sopenharmony_ci dev->support_info.max_y_range = KV_MAX_Y_RANGE; 344141cc406Sopenharmony_ci 345141cc406Sopenharmony_ci dev->x_range.min = dev->y_range.min = 0; 346141cc406Sopenharmony_ci dev->x_range.max = SANE_FIX (dev->support_info.max_x_range); 347141cc406Sopenharmony_ci dev->y_range.max = SANE_FIX (dev->support_info.max_y_range); 348141cc406Sopenharmony_ci dev->x_range.quant = dev->y_range.quant = 0; 349141cc406Sopenharmony_ci 350141cc406Sopenharmony_ci DBG (DBG_error, 351141cc406Sopenharmony_ci "support_info.memory_size = %d (MB)\n", 352141cc406Sopenharmony_ci dev->support_info.memory_size); 353141cc406Sopenharmony_ci DBG (DBG_error, 354141cc406Sopenharmony_ci "support_info.min_resolution = %d (DPI)\n", 355141cc406Sopenharmony_ci dev->support_info.min_resolution); 356141cc406Sopenharmony_ci DBG (DBG_error, 357141cc406Sopenharmony_ci "support_info.max_resolution = %d (DPI)\n", 358141cc406Sopenharmony_ci dev->support_info.max_resolution); 359141cc406Sopenharmony_ci DBG (DBG_error, 360141cc406Sopenharmony_ci "support_info.step_resolution = %d (DPI)\n", 361141cc406Sopenharmony_ci dev->support_info.step_resolution); 362141cc406Sopenharmony_ci DBG (DBG_error, 363141cc406Sopenharmony_ci "support_info.support_duplex = %s\n", 364141cc406Sopenharmony_ci dev->support_info.support_duplex ? "TRUE" : "FALSE"); 365141cc406Sopenharmony_ci DBG (DBG_error, "support_info.support_lamp = %s\n", 366141cc406Sopenharmony_ci dev->support_info.support_lamp ? "TRUE" : "FALSE"); 367141cc406Sopenharmony_ci } 368141cc406Sopenharmony_ci else 369141cc406Sopenharmony_ci { 370141cc406Sopenharmony_ci DBG (DBG_error, "Error in CMD_get_support_info, " 371141cc406Sopenharmony_ci "sense_key=%d, ASC=%d, ASCQ=%d\n", 372141cc406Sopenharmony_ci get_RS_sense_key (rs.sense), 373141cc406Sopenharmony_ci get_RS_ASC (rs.sense), get_RS_ASCQ (rs.sense)); 374141cc406Sopenharmony_ci 375141cc406Sopenharmony_ci } 376141cc406Sopenharmony_ci } 377141cc406Sopenharmony_ci 378141cc406Sopenharmony_ci return status; 379141cc406Sopenharmony_ci} 380141cc406Sopenharmony_ci 381141cc406Sopenharmony_ciSANE_Status 382141cc406Sopenharmony_ciCMD_scan (PKV_DEV dev) 383141cc406Sopenharmony_ci{ 384141cc406Sopenharmony_ci SANE_Status status; 385141cc406Sopenharmony_ci KV_CMD_HEADER hdr; 386141cc406Sopenharmony_ci KV_CMD_RESPONSE rs; 387141cc406Sopenharmony_ci 388141cc406Sopenharmony_ci DBG (DBG_proc, "CMD_scan\n"); 389141cc406Sopenharmony_ci 390141cc406Sopenharmony_ci memset (&hdr, 0, sizeof (hdr)); 391141cc406Sopenharmony_ci 392141cc406Sopenharmony_ci hdr.direction = KV_CMD_NONE; 393141cc406Sopenharmony_ci hdr.cdb[0] = SCSI_SCAN; 394141cc406Sopenharmony_ci hdr.cdb_size = 6; 395141cc406Sopenharmony_ci 396141cc406Sopenharmony_ci status = kv_send_command (dev, &hdr, &rs); 397141cc406Sopenharmony_ci 398141cc406Sopenharmony_ci if (status == 0 && rs.status != 0) 399141cc406Sopenharmony_ci { 400141cc406Sopenharmony_ci DBG (DBG_error, 401141cc406Sopenharmony_ci "Error in CMD_scan, sense_key=%d, ASC=%d, ASCQ=%d\n", 402141cc406Sopenharmony_ci get_RS_sense_key (rs.sense), get_RS_ASC (rs.sense), 403141cc406Sopenharmony_ci get_RS_ASCQ (rs.sense)); 404141cc406Sopenharmony_ci } 405141cc406Sopenharmony_ci 406141cc406Sopenharmony_ci return status; 407141cc406Sopenharmony_ci} 408141cc406Sopenharmony_ci 409141cc406Sopenharmony_ciSANE_Status 410141cc406Sopenharmony_ciCMD_set_window (PKV_DEV dev, int side, PKV_CMD_RESPONSE rs) 411141cc406Sopenharmony_ci{ 412141cc406Sopenharmony_ci unsigned char *window; 413141cc406Sopenharmony_ci unsigned char *windowdata; 414141cc406Sopenharmony_ci int size = 74; 415141cc406Sopenharmony_ci KV_SCAN_MODE scan_mode; 416141cc406Sopenharmony_ci KV_CMD_HEADER hdr; 417141cc406Sopenharmony_ci 418141cc406Sopenharmony_ci DBG (DBG_proc, "CMD_set_window\n"); 419141cc406Sopenharmony_ci 420141cc406Sopenharmony_ci window = (unsigned char *) dev->buffer; 421141cc406Sopenharmony_ci windowdata = window + 8; 422141cc406Sopenharmony_ci 423141cc406Sopenharmony_ci memset (&hdr, 0, sizeof (hdr)); 424141cc406Sopenharmony_ci memset (window, 0, size); 425141cc406Sopenharmony_ci 426141cc406Sopenharmony_ci Ito16 (66, &window[6]); /* Window descriptor block length */ 427141cc406Sopenharmony_ci 428141cc406Sopenharmony_ci /* Set window data */ 429141cc406Sopenharmony_ci 430141cc406Sopenharmony_ci scan_mode = kv_get_mode (dev); 431141cc406Sopenharmony_ci 432141cc406Sopenharmony_ci kv_set_window_data (dev, scan_mode, side, windowdata); 433141cc406Sopenharmony_ci 434141cc406Sopenharmony_ci hdr.direction = KV_CMD_OUT; 435141cc406Sopenharmony_ci hdr.cdb_size = 10; 436141cc406Sopenharmony_ci hdr.cdb[0] = SCSI_SET_WINDOW; 437141cc406Sopenharmony_ci Ito24 (size, &hdr.cdb[6]); 438141cc406Sopenharmony_ci hdr.data = window; 439141cc406Sopenharmony_ci hdr.data_size = size; 440141cc406Sopenharmony_ci 441141cc406Sopenharmony_ci hexdump (DBG_error, "window", window, size); 442141cc406Sopenharmony_ci 443141cc406Sopenharmony_ci return kv_send_command (dev, &hdr, rs); 444141cc406Sopenharmony_ci} 445141cc406Sopenharmony_ci 446141cc406Sopenharmony_ciSANE_Status 447141cc406Sopenharmony_ciCMD_reset_window (PKV_DEV dev) 448141cc406Sopenharmony_ci{ 449141cc406Sopenharmony_ci KV_CMD_HEADER hdr; 450141cc406Sopenharmony_ci KV_CMD_RESPONSE rs; 451141cc406Sopenharmony_ci SANE_Status status; 452141cc406Sopenharmony_ci 453141cc406Sopenharmony_ci DBG (DBG_proc, "CMD_reset_window\n"); 454141cc406Sopenharmony_ci 455141cc406Sopenharmony_ci memset (&hdr, 0, sizeof (hdr)); 456141cc406Sopenharmony_ci 457141cc406Sopenharmony_ci hdr.direction = KV_CMD_NONE; 458141cc406Sopenharmony_ci hdr.cdb_size = 10; 459141cc406Sopenharmony_ci hdr.cdb[0] = SCSI_SET_WINDOW; 460141cc406Sopenharmony_ci 461141cc406Sopenharmony_ci status = kv_send_command (dev, &hdr, &rs); 462141cc406Sopenharmony_ci if (rs.status != 0) 463141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 464141cc406Sopenharmony_ci 465141cc406Sopenharmony_ci return status; 466141cc406Sopenharmony_ci} 467141cc406Sopenharmony_ci 468141cc406Sopenharmony_ciSANE_Status 469141cc406Sopenharmony_ciCMD_get_buff_status (PKV_DEV dev, int *front_size, int *back_size) 470141cc406Sopenharmony_ci{ 471141cc406Sopenharmony_ci KV_CMD_HEADER hdr; 472141cc406Sopenharmony_ci KV_CMD_RESPONSE rs; 473141cc406Sopenharmony_ci SANE_Status status; 474141cc406Sopenharmony_ci unsigned char *data = (unsigned char *) dev->buffer; 475141cc406Sopenharmony_ci int size = 12; 476141cc406Sopenharmony_ci memset (&hdr, 0, sizeof (hdr)); 477141cc406Sopenharmony_ci memset (data, 0, size); 478141cc406Sopenharmony_ci 479141cc406Sopenharmony_ci hdr.direction = KV_CMD_IN; 480141cc406Sopenharmony_ci hdr.cdb_size = 10; 481141cc406Sopenharmony_ci hdr.cdb[0] = SCSI_GET_BUFFER_STATUS; 482141cc406Sopenharmony_ci hdr.cdb[8] = size; 483141cc406Sopenharmony_ci hdr.data = data; 484141cc406Sopenharmony_ci hdr.data_size = size; 485141cc406Sopenharmony_ci 486141cc406Sopenharmony_ci status = kv_send_command (dev, &hdr, &rs); 487141cc406Sopenharmony_ci if (status == 0) 488141cc406Sopenharmony_ci { 489141cc406Sopenharmony_ci if (rs.status == KV_CHK_CONDITION) 490141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 491141cc406Sopenharmony_ci else 492141cc406Sopenharmony_ci { 493141cc406Sopenharmony_ci unsigned char *p = data + 4; 494141cc406Sopenharmony_ci if (p[0] == SIDE_FRONT) 495141cc406Sopenharmony_ci { 496141cc406Sopenharmony_ci *front_size = (p[5] << 16) | (p[6] << 8) | p[7]; 497141cc406Sopenharmony_ci } 498141cc406Sopenharmony_ci else 499141cc406Sopenharmony_ci { 500141cc406Sopenharmony_ci *back_size = (p[5] << 16) | (p[6] << 8) | p[7]; 501141cc406Sopenharmony_ci } 502141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 503141cc406Sopenharmony_ci } 504141cc406Sopenharmony_ci } 505141cc406Sopenharmony_ci return status; 506141cc406Sopenharmony_ci} 507141cc406Sopenharmony_ci 508141cc406Sopenharmony_ciSANE_Status 509141cc406Sopenharmony_ciCMD_wait_buff_status (PKV_DEV dev, int *front_size, int *back_size) 510141cc406Sopenharmony_ci{ 511141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 512141cc406Sopenharmony_ci int cnt = 0; 513141cc406Sopenharmony_ci *front_size = 0; 514141cc406Sopenharmony_ci *back_size = 0; 515141cc406Sopenharmony_ci 516141cc406Sopenharmony_ci DBG (DBG_proc, "CMD_wait_buff_status: enter feed %s\n", 517141cc406Sopenharmony_ci dev->val[OPT_MANUALFEED].s); 518141cc406Sopenharmony_ci 519141cc406Sopenharmony_ci do 520141cc406Sopenharmony_ci { 521141cc406Sopenharmony_ci DBG (DBG_proc, "CMD_wait_buff_status: tray #%d of %d\n", cnt, 522141cc406Sopenharmony_ci dev->val[OPT_FEED_TIMEOUT].w); 523141cc406Sopenharmony_ci status = CMD_get_buff_status (dev, front_size, back_size); 524141cc406Sopenharmony_ci sleep (1); 525141cc406Sopenharmony_ci } 526141cc406Sopenharmony_ci while (status == SANE_STATUS_GOOD && (*front_size == 0) 527141cc406Sopenharmony_ci && (*back_size == 0) && cnt++ < dev->val[OPT_FEED_TIMEOUT].w); 528141cc406Sopenharmony_ci 529141cc406Sopenharmony_ci if (cnt > dev->val[OPT_FEED_TIMEOUT].w) 530141cc406Sopenharmony_ci status = SANE_STATUS_NO_DOCS; 531141cc406Sopenharmony_ci 532141cc406Sopenharmony_ci if (status == 0) 533141cc406Sopenharmony_ci DBG (DBG_proc, "CMD_wait_buff_status: exit " 534141cc406Sopenharmony_ci "front_size %d, back_size %d\n", *front_size, *back_size); 535141cc406Sopenharmony_ci else 536141cc406Sopenharmony_ci DBG (DBG_proc, "CMD_wait_buff_status: exit with no docs\n"); 537141cc406Sopenharmony_ci return status; 538141cc406Sopenharmony_ci} 539141cc406Sopenharmony_ci 540141cc406Sopenharmony_ci 541141cc406Sopenharmony_ciSANE_Status 542141cc406Sopenharmony_ciCMD_read_pic_elements (PKV_DEV dev, int page, int side, 543141cc406Sopenharmony_ci int *width, int *height) 544141cc406Sopenharmony_ci{ 545141cc406Sopenharmony_ci SANE_Status status; 546141cc406Sopenharmony_ci KV_CMD_HEADER hdr; 547141cc406Sopenharmony_ci KV_CMD_RESPONSE rs; 548141cc406Sopenharmony_ci 549141cc406Sopenharmony_ci DBG (DBG_proc, "CMD_read_pic_elements\n"); 550141cc406Sopenharmony_ci 551141cc406Sopenharmony_ci memset (&hdr, 0, sizeof (hdr)); 552141cc406Sopenharmony_ci 553141cc406Sopenharmony_ci hdr.direction = KV_CMD_IN; 554141cc406Sopenharmony_ci hdr.cdb_size = 10; 555141cc406Sopenharmony_ci hdr.cdb[0] = SCSI_READ_10; 556141cc406Sopenharmony_ci hdr.cdb[2] = 0x80; 557141cc406Sopenharmony_ci hdr.cdb[4] = page; 558141cc406Sopenharmony_ci hdr.cdb[5] = side; 559141cc406Sopenharmony_ci Ito24 (16, &hdr.cdb[6]); 560141cc406Sopenharmony_ci hdr.data = dev->buffer; 561141cc406Sopenharmony_ci hdr.data_size = 16; 562141cc406Sopenharmony_ci 563141cc406Sopenharmony_ci status = kv_send_command (dev, &hdr, &rs); 564141cc406Sopenharmony_ci if (status == 0) 565141cc406Sopenharmony_ci { 566141cc406Sopenharmony_ci if (rs.status == 0) 567141cc406Sopenharmony_ci { 568141cc406Sopenharmony_ci int s = side == SIDE_FRONT ? 0 : 1; 569141cc406Sopenharmony_ci int depth = kv_get_depth (kv_get_mode (dev)); 570141cc406Sopenharmony_ci *width = B32TOI (dev->buffer); 571141cc406Sopenharmony_ci *height = B32TOI (&dev->buffer[4]); 572141cc406Sopenharmony_ci 573141cc406Sopenharmony_ci assert ((*width) % 8 == 0); 574141cc406Sopenharmony_ci 575141cc406Sopenharmony_ci DBG (DBG_proc, "CMD_read_pic_elements: " 576141cc406Sopenharmony_ci "Page %d, Side %s, W=%d, H=%d\n", 577141cc406Sopenharmony_ci page, side == SIDE_FRONT ? "F" : "B", *width, *height); 578141cc406Sopenharmony_ci 579141cc406Sopenharmony_ci dev->params[s].format = kv_get_mode (dev) == SM_COLOR ? 580141cc406Sopenharmony_ci SANE_FRAME_RGB : SANE_FRAME_GRAY; 581141cc406Sopenharmony_ci dev->params[s].last_frame = SANE_TRUE; 582141cc406Sopenharmony_ci dev->params[s].depth = depth > 8 ? 8 : depth; 583141cc406Sopenharmony_ci dev->params[s].lines = *height ? *height 584141cc406Sopenharmony_ci : dev->val[OPT_LANDSCAPE].w ? (*width * 3) / 4 : (*width * 4) / 3; 585141cc406Sopenharmony_ci dev->params[s].pixels_per_line = *width; 586141cc406Sopenharmony_ci dev->params[s].bytes_per_line = 587141cc406Sopenharmony_ci (dev->params[s].pixels_per_line / 8) * depth; 588141cc406Sopenharmony_ci } 589141cc406Sopenharmony_ci else 590141cc406Sopenharmony_ci { 591141cc406Sopenharmony_ci DBG (DBG_proc, "CMD_read_pic_elements: failed\n"); 592141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 593141cc406Sopenharmony_ci } 594141cc406Sopenharmony_ci } 595141cc406Sopenharmony_ci 596141cc406Sopenharmony_ci return status; 597141cc406Sopenharmony_ci} 598141cc406Sopenharmony_ci 599141cc406Sopenharmony_ciSANE_Status 600141cc406Sopenharmony_ciCMD_read_image (PKV_DEV dev, int page, int side, 601141cc406Sopenharmony_ci unsigned char *buffer, int *psize, KV_CMD_RESPONSE * rs) 602141cc406Sopenharmony_ci{ 603141cc406Sopenharmony_ci SANE_Status status; 604141cc406Sopenharmony_ci KV_CMD_HEADER hdr; 605141cc406Sopenharmony_ci int size = *psize; 606141cc406Sopenharmony_ci 607141cc406Sopenharmony_ci DBG (DBG_proc, "CMD_read_image\n"); 608141cc406Sopenharmony_ci 609141cc406Sopenharmony_ci memset (&hdr, 0, sizeof (hdr)); 610141cc406Sopenharmony_ci 611141cc406Sopenharmony_ci hdr.direction = KV_CMD_IN; 612141cc406Sopenharmony_ci hdr.cdb_size = 10; 613141cc406Sopenharmony_ci hdr.cdb[0] = SCSI_READ_10; 614141cc406Sopenharmony_ci hdr.cdb[4] = page; 615141cc406Sopenharmony_ci hdr.cdb[5] = side; 616141cc406Sopenharmony_ci Ito24 (size, &hdr.cdb[6]); 617141cc406Sopenharmony_ci hdr.data = buffer; 618141cc406Sopenharmony_ci hdr.data_size = size; 619141cc406Sopenharmony_ci 620141cc406Sopenharmony_ci *psize = 0; 621141cc406Sopenharmony_ci 622141cc406Sopenharmony_ci status = kv_send_command (dev, &hdr, rs); 623141cc406Sopenharmony_ci 624141cc406Sopenharmony_ci if (status) 625141cc406Sopenharmony_ci return status; 626141cc406Sopenharmony_ci 627141cc406Sopenharmony_ci *psize = size; 628141cc406Sopenharmony_ci 629141cc406Sopenharmony_ci if (rs->status == KV_CHK_CONDITION && get_RS_ILI (rs->sense)) 630141cc406Sopenharmony_ci { 631141cc406Sopenharmony_ci int delta = B32TOI (&rs->sense[3]); 632141cc406Sopenharmony_ci DBG (DBG_error, "size=%d, delta=0x%x (%d)\n", size, delta, delta); 633141cc406Sopenharmony_ci *psize = size - delta; 634141cc406Sopenharmony_ci } 635141cc406Sopenharmony_ci 636141cc406Sopenharmony_ci DBG (DBG_error, "CMD_read_image: bytes requested=%d, read=%d\n", 637141cc406Sopenharmony_ci size, *psize); 638141cc406Sopenharmony_ci DBG (DBG_error, "CMD_read_image: ILI=%d, EOM=%d\n", 639141cc406Sopenharmony_ci get_RS_ILI (rs->sense), get_RS_EOM (rs->sense)); 640141cc406Sopenharmony_ci 641141cc406Sopenharmony_ci return status; 642141cc406Sopenharmony_ci} 643141cc406Sopenharmony_ci 644141cc406Sopenharmony_ciSANE_Status 645141cc406Sopenharmony_ciCMD_get_document_existanse (PKV_DEV dev) 646141cc406Sopenharmony_ci{ 647141cc406Sopenharmony_ci SANE_Status status; 648141cc406Sopenharmony_ci KV_CMD_HEADER hdr; 649141cc406Sopenharmony_ci KV_CMD_RESPONSE rs; 650141cc406Sopenharmony_ci 651141cc406Sopenharmony_ci DBG (DBG_proc, "CMD_get_document_existanse\n"); 652141cc406Sopenharmony_ci 653141cc406Sopenharmony_ci memset (&hdr, 0, sizeof (hdr)); 654141cc406Sopenharmony_ci 655141cc406Sopenharmony_ci hdr.direction = KV_CMD_IN; 656141cc406Sopenharmony_ci hdr.cdb_size = 10; 657141cc406Sopenharmony_ci hdr.cdb[0] = SCSI_READ_10; 658141cc406Sopenharmony_ci hdr.cdb[2] = 0x81; 659141cc406Sopenharmony_ci Ito24 (6, &hdr.cdb[6]); 660141cc406Sopenharmony_ci hdr.data = dev->buffer; 661141cc406Sopenharmony_ci hdr.data_size = 6; 662141cc406Sopenharmony_ci 663141cc406Sopenharmony_ci status = kv_send_command (dev, &hdr, &rs); 664141cc406Sopenharmony_ci if (status) 665141cc406Sopenharmony_ci return status; 666141cc406Sopenharmony_ci if (rs.status) 667141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 668141cc406Sopenharmony_ci if ((dev->buffer[0] & 0x20) != 0) 669141cc406Sopenharmony_ci { 670141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 671141cc406Sopenharmony_ci } 672141cc406Sopenharmony_ci 673141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 674141cc406Sopenharmony_ci} 675141cc406Sopenharmony_ci 676141cc406Sopenharmony_ciSANE_Status 677141cc406Sopenharmony_ciCMD_wait_document_existanse (PKV_DEV dev) 678141cc406Sopenharmony_ci{ 679141cc406Sopenharmony_ci SANE_Status status; 680141cc406Sopenharmony_ci KV_CMD_HEADER hdr; 681141cc406Sopenharmony_ci KV_CMD_RESPONSE rs; 682141cc406Sopenharmony_ci int cnt; 683141cc406Sopenharmony_ci 684141cc406Sopenharmony_ci DBG (DBG_proc, "CMD_wait_document_existanse\n"); 685141cc406Sopenharmony_ci 686141cc406Sopenharmony_ci memset (&hdr, 0, sizeof (hdr)); 687141cc406Sopenharmony_ci 688141cc406Sopenharmony_ci hdr.direction = KV_CMD_IN; 689141cc406Sopenharmony_ci hdr.cdb_size = 10; 690141cc406Sopenharmony_ci hdr.cdb[0] = SCSI_READ_10; 691141cc406Sopenharmony_ci hdr.cdb[2] = 0x81; 692141cc406Sopenharmony_ci Ito24 (6, &hdr.cdb[6]); 693141cc406Sopenharmony_ci hdr.data = dev->buffer; 694141cc406Sopenharmony_ci hdr.data_size = 6; 695141cc406Sopenharmony_ci 696141cc406Sopenharmony_ci for (cnt = 0; cnt < dev->val[OPT_FEED_TIMEOUT].w; cnt++) 697141cc406Sopenharmony_ci { 698141cc406Sopenharmony_ci DBG (DBG_proc, "CMD_wait_document_existanse: tray #%d of %d\n", cnt, 699141cc406Sopenharmony_ci dev->val[OPT_FEED_TIMEOUT].w); 700141cc406Sopenharmony_ci status = kv_send_command (dev, &hdr, &rs); 701141cc406Sopenharmony_ci if (status) 702141cc406Sopenharmony_ci return status; 703141cc406Sopenharmony_ci if (rs.status) 704141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 705141cc406Sopenharmony_ci if ((dev->buffer[0] & 0x20) != 0) 706141cc406Sopenharmony_ci { 707141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 708141cc406Sopenharmony_ci } 709141cc406Sopenharmony_ci else if (strcmp (dev->val[OPT_MANUALFEED].s, "off") == 0) 710141cc406Sopenharmony_ci { 711141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 712141cc406Sopenharmony_ci } 713141cc406Sopenharmony_ci sleep (1); 714141cc406Sopenharmony_ci } 715141cc406Sopenharmony_ci 716141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 717141cc406Sopenharmony_ci} 718141cc406Sopenharmony_ci 719141cc406Sopenharmony_ciSANE_Status 720141cc406Sopenharmony_ciCMD_request_sense (PKV_DEV dev) 721141cc406Sopenharmony_ci{ 722141cc406Sopenharmony_ci KV_CMD_HEADER hdr; 723141cc406Sopenharmony_ci KV_CMD_RESPONSE rs; 724141cc406Sopenharmony_ci 725141cc406Sopenharmony_ci DBG (DBG_proc, "CMD_request_sense\n"); 726141cc406Sopenharmony_ci memset (&hdr, 0, sizeof (hdr)); 727141cc406Sopenharmony_ci hdr.direction = KV_CMD_IN; 728141cc406Sopenharmony_ci hdr.cdb[0] = SCSI_REQUEST_SENSE; 729141cc406Sopenharmony_ci hdr.cdb[4] = 0x12; 730141cc406Sopenharmony_ci hdr.cdb_size = 6; 731141cc406Sopenharmony_ci hdr.data_size = 0x12; 732141cc406Sopenharmony_ci hdr.data = dev->buffer; 733141cc406Sopenharmony_ci 734141cc406Sopenharmony_ci return kv_send_command (dev, &hdr, &rs); 735141cc406Sopenharmony_ci} 736141cc406Sopenharmony_ci 737141cc406Sopenharmony_ci/* Scan routines */ 738141cc406Sopenharmony_ci 739141cc406Sopenharmony_ci/* Allocate image buffer for one page (1 or 2 sides) */ 740141cc406Sopenharmony_ci 741141cc406Sopenharmony_ciSANE_Status 742141cc406Sopenharmony_ciAllocateImageBuffer (PKV_DEV dev) 743141cc406Sopenharmony_ci{ 744141cc406Sopenharmony_ci int *size = dev->bytes_to_read; 745141cc406Sopenharmony_ci int sides = IS_DUPLEX (dev) ? 2 : 1; 746141cc406Sopenharmony_ci int i; 747141cc406Sopenharmony_ci size[0] = dev->params[0].bytes_per_line * dev->params[0].lines; 748141cc406Sopenharmony_ci size[1] = dev->params[1].bytes_per_line * dev->params[1].lines; 749141cc406Sopenharmony_ci 750141cc406Sopenharmony_ci DBG (DBG_proc, "AllocateImageBuffer: enter\n"); 751141cc406Sopenharmony_ci 752141cc406Sopenharmony_ci for (i = 0; i < sides; i++) 753141cc406Sopenharmony_ci { 754141cc406Sopenharmony_ci SANE_Byte *p; 755141cc406Sopenharmony_ci DBG (DBG_proc, "AllocateImageBuffer: size(%c)=%d\n", 756141cc406Sopenharmony_ci i ? 'B' : 'F', size[i]); 757141cc406Sopenharmony_ci 758141cc406Sopenharmony_ci if (dev->img_buffers[i] == NULL) 759141cc406Sopenharmony_ci { 760141cc406Sopenharmony_ci p = (SANE_Byte *) malloc (size[i]); 761141cc406Sopenharmony_ci if (p == NULL) 762141cc406Sopenharmony_ci { 763141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 764141cc406Sopenharmony_ci } 765141cc406Sopenharmony_ci dev->img_buffers[i] = p; 766141cc406Sopenharmony_ci } 767141cc406Sopenharmony_ci else 768141cc406Sopenharmony_ci { 769141cc406Sopenharmony_ci p = (SANE_Byte *) realloc (dev->img_buffers[i], size[i]); 770141cc406Sopenharmony_ci if (p == NULL) 771141cc406Sopenharmony_ci { 772141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 773141cc406Sopenharmony_ci } 774141cc406Sopenharmony_ci else 775141cc406Sopenharmony_ci { 776141cc406Sopenharmony_ci dev->img_buffers[i] = p; 777141cc406Sopenharmony_ci } 778141cc406Sopenharmony_ci } 779141cc406Sopenharmony_ci } 780141cc406Sopenharmony_ci DBG (DBG_proc, "AllocateImageBuffer: exit\n"); 781141cc406Sopenharmony_ci 782141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 783141cc406Sopenharmony_ci} 784141cc406Sopenharmony_ci 785141cc406Sopenharmony_ci/* Read image data from scanner dev->img_buffers[0], 786141cc406Sopenharmony_ci for the simplex page */ 787141cc406Sopenharmony_ciSANE_Status 788141cc406Sopenharmony_ciReadImageDataSimplex (PKV_DEV dev, int page) 789141cc406Sopenharmony_ci{ 790141cc406Sopenharmony_ci int bytes_to_read = dev->bytes_to_read[0]; 791141cc406Sopenharmony_ci SANE_Byte *buffer = (SANE_Byte *) dev->buffer; 792141cc406Sopenharmony_ci int buff_size = SCSI_BUFFER_SIZE; 793141cc406Sopenharmony_ci SANE_Byte *pt = dev->img_buffers[0]; 794141cc406Sopenharmony_ci KV_CMD_RESPONSE rs; 795141cc406Sopenharmony_ci dev->img_size[0] = 0; 796141cc406Sopenharmony_ci dev->img_size[1] = 0; 797141cc406Sopenharmony_ci 798141cc406Sopenharmony_ci /* read loop */ 799141cc406Sopenharmony_ci do 800141cc406Sopenharmony_ci { 801141cc406Sopenharmony_ci int size = buff_size; 802141cc406Sopenharmony_ci SANE_Status status; 803141cc406Sopenharmony_ci DBG (DBG_error, "Bytes left = %d\n", bytes_to_read); 804141cc406Sopenharmony_ci status = CMD_read_image (dev, page, SIDE_FRONT, buffer, &size, &rs); 805141cc406Sopenharmony_ci if (status) 806141cc406Sopenharmony_ci { 807141cc406Sopenharmony_ci return status; 808141cc406Sopenharmony_ci } 809141cc406Sopenharmony_ci if (rs.status) 810141cc406Sopenharmony_ci { 811141cc406Sopenharmony_ci if (get_RS_sense_key (rs.sense)) 812141cc406Sopenharmony_ci { 813141cc406Sopenharmony_ci DBG (DBG_error, "Error reading image data, " 814141cc406Sopenharmony_ci "sense_key=%d, ASC=%d, ASCQ=%d", 815141cc406Sopenharmony_ci get_RS_sense_key (rs.sense), 816141cc406Sopenharmony_ci get_RS_ASC (rs.sense), get_RS_ASCQ (rs.sense)); 817141cc406Sopenharmony_ci 818141cc406Sopenharmony_ci if (get_RS_sense_key (rs.sense) == 3) 819141cc406Sopenharmony_ci { 820141cc406Sopenharmony_ci if (!get_RS_ASCQ (rs.sense)) 821141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 822141cc406Sopenharmony_ci return SANE_STATUS_JAMMED; 823141cc406Sopenharmony_ci } 824141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 825141cc406Sopenharmony_ci } 826141cc406Sopenharmony_ci 827141cc406Sopenharmony_ci } 828141cc406Sopenharmony_ci /* copy data to image buffer */ 829141cc406Sopenharmony_ci if (size > bytes_to_read) 830141cc406Sopenharmony_ci { 831141cc406Sopenharmony_ci size = bytes_to_read; 832141cc406Sopenharmony_ci } 833141cc406Sopenharmony_ci if (size > 0) 834141cc406Sopenharmony_ci { 835141cc406Sopenharmony_ci memcpy (pt, buffer, size); 836141cc406Sopenharmony_ci bytes_to_read -= size; 837141cc406Sopenharmony_ci pt += size; 838141cc406Sopenharmony_ci dev->img_size[0] += size; 839141cc406Sopenharmony_ci } 840141cc406Sopenharmony_ci } 841141cc406Sopenharmony_ci while (!get_RS_EOM (rs.sense)); 842141cc406Sopenharmony_ci 843141cc406Sopenharmony_ci assert (pt == dev->img_buffers[0] + dev->img_size[0]); 844141cc406Sopenharmony_ci DBG (DBG_error, "Image size = %d\n", dev->img_size[0]); 845141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 846141cc406Sopenharmony_ci} 847141cc406Sopenharmony_ci 848141cc406Sopenharmony_ci/* Read image data from scanner dev->img_buffers[0], 849141cc406Sopenharmony_ci for the duplex page */ 850141cc406Sopenharmony_ciSANE_Status 851141cc406Sopenharmony_ciReadImageDataDuplex (PKV_DEV dev, int page) 852141cc406Sopenharmony_ci{ 853141cc406Sopenharmony_ci int bytes_to_read[2]; 854141cc406Sopenharmony_ci SANE_Byte *buffer = (SANE_Byte *) dev->buffer; 855141cc406Sopenharmony_ci int buff_size[2]; 856141cc406Sopenharmony_ci SANE_Byte *pt[2]; 857141cc406Sopenharmony_ci KV_CMD_RESPONSE rs; 858141cc406Sopenharmony_ci int sides[2]; 859141cc406Sopenharmony_ci SANE_Bool eoms[2]; 860141cc406Sopenharmony_ci int current_side = 1; 861141cc406Sopenharmony_ci 862141cc406Sopenharmony_ci bytes_to_read[0] = dev->bytes_to_read[0]; 863141cc406Sopenharmony_ci bytes_to_read[1] = dev->bytes_to_read[1]; 864141cc406Sopenharmony_ci 865141cc406Sopenharmony_ci pt[0] = dev->img_buffers[0]; 866141cc406Sopenharmony_ci pt[1] = dev->img_buffers[1]; 867141cc406Sopenharmony_ci 868141cc406Sopenharmony_ci sides[0] = SIDE_FRONT; 869141cc406Sopenharmony_ci sides[1] = SIDE_BACK; 870141cc406Sopenharmony_ci eoms[0] = eoms[1] = 0; 871141cc406Sopenharmony_ci 872141cc406Sopenharmony_ci buff_size[0] = SCSI_BUFFER_SIZE; 873141cc406Sopenharmony_ci buff_size[1] = SCSI_BUFFER_SIZE; 874141cc406Sopenharmony_ci dev->img_size[0] = 0; 875141cc406Sopenharmony_ci dev->img_size[1] = 0; 876141cc406Sopenharmony_ci 877141cc406Sopenharmony_ci /* read loop */ 878141cc406Sopenharmony_ci do 879141cc406Sopenharmony_ci { 880141cc406Sopenharmony_ci int size = buff_size[current_side]; 881141cc406Sopenharmony_ci SANE_Status status; 882141cc406Sopenharmony_ci DBG (DBG_error, "Bytes left (F) = %d\n", bytes_to_read[0]); 883141cc406Sopenharmony_ci DBG (DBG_error, "Bytes left (B) = %d\n", bytes_to_read[1]); 884141cc406Sopenharmony_ci 885141cc406Sopenharmony_ci status = CMD_read_image (dev, page, sides[current_side], 886141cc406Sopenharmony_ci buffer, &size, &rs); 887141cc406Sopenharmony_ci if (status) 888141cc406Sopenharmony_ci { 889141cc406Sopenharmony_ci return status; 890141cc406Sopenharmony_ci } 891141cc406Sopenharmony_ci if (rs.status) 892141cc406Sopenharmony_ci { 893141cc406Sopenharmony_ci if (get_RS_sense_key (rs.sense)) 894141cc406Sopenharmony_ci { 895141cc406Sopenharmony_ci DBG (DBG_error, "Error reading image data, " 896141cc406Sopenharmony_ci "sense_key=%d, ASC=%d, ASCQ=%d", 897141cc406Sopenharmony_ci get_RS_sense_key (rs.sense), 898141cc406Sopenharmony_ci get_RS_ASC (rs.sense), get_RS_ASCQ (rs.sense)); 899141cc406Sopenharmony_ci 900141cc406Sopenharmony_ci if (get_RS_sense_key (rs.sense) == 3) 901141cc406Sopenharmony_ci { 902141cc406Sopenharmony_ci if (!get_RS_ASCQ (rs.sense)) 903141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 904141cc406Sopenharmony_ci return SANE_STATUS_JAMMED; 905141cc406Sopenharmony_ci } 906141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 907141cc406Sopenharmony_ci } 908141cc406Sopenharmony_ci } 909141cc406Sopenharmony_ci 910141cc406Sopenharmony_ci /* copy data to image buffer */ 911141cc406Sopenharmony_ci if (size > bytes_to_read[current_side]) 912141cc406Sopenharmony_ci { 913141cc406Sopenharmony_ci size = bytes_to_read[current_side]; 914141cc406Sopenharmony_ci } 915141cc406Sopenharmony_ci if (size > 0) 916141cc406Sopenharmony_ci { 917141cc406Sopenharmony_ci memcpy (pt[current_side], buffer, size); 918141cc406Sopenharmony_ci bytes_to_read[current_side] -= size; 919141cc406Sopenharmony_ci pt[current_side] += size; 920141cc406Sopenharmony_ci dev->img_size[current_side] += size; 921141cc406Sopenharmony_ci } 922141cc406Sopenharmony_ci if (rs.status) 923141cc406Sopenharmony_ci { 924141cc406Sopenharmony_ci if (get_RS_EOM (rs.sense)) 925141cc406Sopenharmony_ci { 926141cc406Sopenharmony_ci eoms[current_side] = 1; 927141cc406Sopenharmony_ci } 928141cc406Sopenharmony_ci if (get_RS_ILI (rs.sense)) 929141cc406Sopenharmony_ci { 930141cc406Sopenharmony_ci current_side++; 931141cc406Sopenharmony_ci current_side &= 1; 932141cc406Sopenharmony_ci } 933141cc406Sopenharmony_ci } 934141cc406Sopenharmony_ci } 935141cc406Sopenharmony_ci while (eoms[0] == 0 || eoms[1] == 0); 936141cc406Sopenharmony_ci 937141cc406Sopenharmony_ci DBG (DBG_error, "Image size (F) = %d\n", dev->img_size[0]); 938141cc406Sopenharmony_ci DBG (DBG_error, "Image size (B) = %d\n", dev->img_size[1]); 939141cc406Sopenharmony_ci 940141cc406Sopenharmony_ci assert (pt[0] == dev->img_buffers[0] + dev->img_size[0]); 941141cc406Sopenharmony_ci assert (pt[1] == dev->img_buffers[1] + dev->img_size[1]); 942141cc406Sopenharmony_ci 943141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 944141cc406Sopenharmony_ci} 945141cc406Sopenharmony_ci 946141cc406Sopenharmony_ci/* Read image data for one page */ 947141cc406Sopenharmony_ciSANE_Status 948141cc406Sopenharmony_ciReadImageData (PKV_DEV dev, int page) 949141cc406Sopenharmony_ci{ 950141cc406Sopenharmony_ci SANE_Status status; 951141cc406Sopenharmony_ci DBG (DBG_proc, "Reading image data for page %d\n", page); 952141cc406Sopenharmony_ci 953141cc406Sopenharmony_ci if (IS_DUPLEX (dev)) 954141cc406Sopenharmony_ci { 955141cc406Sopenharmony_ci DBG (DBG_proc, "ReadImageData: Duplex %d\n", page); 956141cc406Sopenharmony_ci status = ReadImageDataDuplex (dev, page); 957141cc406Sopenharmony_ci } 958141cc406Sopenharmony_ci else 959141cc406Sopenharmony_ci { 960141cc406Sopenharmony_ci DBG (DBG_proc, "ReadImageData: Simplex %d\n", page); 961141cc406Sopenharmony_ci status = ReadImageDataSimplex (dev, page); 962141cc406Sopenharmony_ci } 963141cc406Sopenharmony_ci dev->img_pt[0] = dev->img_buffers[0]; 964141cc406Sopenharmony_ci dev->img_pt[1] = dev->img_buffers[1]; 965141cc406Sopenharmony_ci 966141cc406Sopenharmony_ci DBG (DBG_proc, "Reading image data for page %d, finished\n", page); 967141cc406Sopenharmony_ci 968141cc406Sopenharmony_ci return status; 969141cc406Sopenharmony_ci} 970141cc406Sopenharmony_ci 971141cc406Sopenharmony_ci/* Look in image for likely upper and left paper edges, then rotate 972141cc406Sopenharmony_ci * image so that upper left corner of paper is upper left of image. 973141cc406Sopenharmony_ci * FIXME: should we do this before we binarize instead of after? */ 974141cc406Sopenharmony_ciSANE_Status 975141cc406Sopenharmony_cibuffer_deskew(PKV_DEV s, int side) 976141cc406Sopenharmony_ci{ 977141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 978141cc406Sopenharmony_ci int bg_color = 0xd6; 979141cc406Sopenharmony_ci int side_index = (side == SIDE_FRONT)?0:1; 980141cc406Sopenharmony_ci int resolution = s->val[OPT_RESOLUTION].w; 981141cc406Sopenharmony_ci 982141cc406Sopenharmony_ci DBG (10, "buffer_deskew: start\n"); 983141cc406Sopenharmony_ci 984141cc406Sopenharmony_ci /*only find skew on first image from a page, or if first image had error */ 985141cc406Sopenharmony_ci if(side == SIDE_FRONT || s->deskew_stat){ 986141cc406Sopenharmony_ci 987141cc406Sopenharmony_ci s->deskew_stat = sanei_magic_findSkew( 988141cc406Sopenharmony_ci &s->params[side_index],s->img_buffers[side_index], 989141cc406Sopenharmony_ci resolution,resolution, 990141cc406Sopenharmony_ci &s->deskew_vals[0],&s->deskew_vals[1],&s->deskew_slope); 991141cc406Sopenharmony_ci 992141cc406Sopenharmony_ci if(s->deskew_stat){ 993141cc406Sopenharmony_ci DBG (5, "buffer_despeck: bad findSkew, bailing\n"); 994141cc406Sopenharmony_ci goto cleanup; 995141cc406Sopenharmony_ci } 996141cc406Sopenharmony_ci } 997141cc406Sopenharmony_ci /* backside images can use a 'flipped' version of frontside data */ 998141cc406Sopenharmony_ci else{ 999141cc406Sopenharmony_ci s->deskew_slope *= -1; 1000141cc406Sopenharmony_ci s->deskew_vals[0] 1001141cc406Sopenharmony_ci = s->params[side_index].pixels_per_line - s->deskew_vals[0]; 1002141cc406Sopenharmony_ci } 1003141cc406Sopenharmony_ci 1004141cc406Sopenharmony_ci ret = sanei_magic_rotate(&s->params[side_index],s->img_buffers[side_index], 1005141cc406Sopenharmony_ci s->deskew_vals[0],s->deskew_vals[1],s->deskew_slope,bg_color); 1006141cc406Sopenharmony_ci 1007141cc406Sopenharmony_ci if(ret){ 1008141cc406Sopenharmony_ci DBG(5,"buffer_deskew: rotate error: %d",ret); 1009141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 1010141cc406Sopenharmony_ci goto cleanup; 1011141cc406Sopenharmony_ci } 1012141cc406Sopenharmony_ci 1013141cc406Sopenharmony_ci cleanup: 1014141cc406Sopenharmony_ci DBG (10, "buffer_deskew: finish\n"); 1015141cc406Sopenharmony_ci return ret; 1016141cc406Sopenharmony_ci} 1017141cc406Sopenharmony_ci 1018141cc406Sopenharmony_ci/* Look in image for likely left/right/bottom paper edges, then crop image. 1019141cc406Sopenharmony_ci * Does not attempt to rotate the image, that should be done first. 1020141cc406Sopenharmony_ci * FIXME: should we do this before we binarize instead of after? */ 1021141cc406Sopenharmony_ciSANE_Status 1022141cc406Sopenharmony_cibuffer_crop(PKV_DEV s, int side) 1023141cc406Sopenharmony_ci{ 1024141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 1025141cc406Sopenharmony_ci int side_index = (side == SIDE_FRONT)?0:1; 1026141cc406Sopenharmony_ci int resolution = s->val[OPT_RESOLUTION].w; 1027141cc406Sopenharmony_ci 1028141cc406Sopenharmony_ci DBG (10, "buffer_crop: start\n"); 1029141cc406Sopenharmony_ci 1030141cc406Sopenharmony_ci /*only find edges on first image from a page, or if first image had error */ 1031141cc406Sopenharmony_ci if(side == SIDE_FRONT || s->crop_stat){ 1032141cc406Sopenharmony_ci 1033141cc406Sopenharmony_ci s->crop_stat = sanei_magic_findEdges( 1034141cc406Sopenharmony_ci &s->params[side_index],s->img_buffers[side_index], 1035141cc406Sopenharmony_ci resolution,resolution, 1036141cc406Sopenharmony_ci &s->crop_vals[0],&s->crop_vals[1],&s->crop_vals[2],&s->crop_vals[3]); 1037141cc406Sopenharmony_ci 1038141cc406Sopenharmony_ci if(s->crop_stat){ 1039141cc406Sopenharmony_ci DBG (5, "buffer_crop: bad edges, bailing\n"); 1040141cc406Sopenharmony_ci goto cleanup; 1041141cc406Sopenharmony_ci } 1042141cc406Sopenharmony_ci 1043141cc406Sopenharmony_ci DBG (15, "buffer_crop: t:%d b:%d l:%d r:%d\n", 1044141cc406Sopenharmony_ci s->crop_vals[0],s->crop_vals[1],s->crop_vals[2],s->crop_vals[3]); 1045141cc406Sopenharmony_ci 1046141cc406Sopenharmony_ci /* we don't listen to the 'top' value, since the top is not padded */ 1047141cc406Sopenharmony_ci /*s->crop_vals[0] = 0;*/ 1048141cc406Sopenharmony_ci } 1049141cc406Sopenharmony_ci /* backside images can use a 'flipped' version of frontside data */ 1050141cc406Sopenharmony_ci else{ 1051141cc406Sopenharmony_ci int left = s->crop_vals[2]; 1052141cc406Sopenharmony_ci int right = s->crop_vals[3]; 1053141cc406Sopenharmony_ci 1054141cc406Sopenharmony_ci s->crop_vals[2] = s->params[side_index].pixels_per_line - right; 1055141cc406Sopenharmony_ci s->crop_vals[3] = s->params[side_index].pixels_per_line - left; 1056141cc406Sopenharmony_ci } 1057141cc406Sopenharmony_ci 1058141cc406Sopenharmony_ci /* now crop the image */ 1059141cc406Sopenharmony_ci ret = sanei_magic_crop(&s->params[side_index],s->img_buffers[side_index], 1060141cc406Sopenharmony_ci s->crop_vals[0],s->crop_vals[1],s->crop_vals[2],s->crop_vals[3]); 1061141cc406Sopenharmony_ci 1062141cc406Sopenharmony_ci if(ret){ 1063141cc406Sopenharmony_ci DBG (5, "buffer_crop: bad crop, bailing\n"); 1064141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 1065141cc406Sopenharmony_ci goto cleanup; 1066141cc406Sopenharmony_ci } 1067141cc406Sopenharmony_ci 1068141cc406Sopenharmony_ci /* update image size counter to new, smaller size */ 1069141cc406Sopenharmony_ci s->img_size[side_index] 1070141cc406Sopenharmony_ci = s->params[side_index].lines * s->params[side_index].bytes_per_line; 1071141cc406Sopenharmony_ci 1072141cc406Sopenharmony_ci cleanup: 1073141cc406Sopenharmony_ci DBG (10, "buffer_crop: finish\n"); 1074141cc406Sopenharmony_ci return ret; 1075141cc406Sopenharmony_ci} 1076141cc406Sopenharmony_ci 1077141cc406Sopenharmony_ci/* Look in image for disconnected 'spots' of the requested size. 1078141cc406Sopenharmony_ci * Replace the spots with the average color of the surrounding pixels. 1079141cc406Sopenharmony_ci * FIXME: should we do this before we binarize instead of after? */ 1080141cc406Sopenharmony_ciSANE_Status 1081141cc406Sopenharmony_cibuffer_despeck(PKV_DEV s, int side) 1082141cc406Sopenharmony_ci{ 1083141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 1084141cc406Sopenharmony_ci int side_index = (side == SIDE_FRONT)?0:1; 1085141cc406Sopenharmony_ci 1086141cc406Sopenharmony_ci DBG (10, "buffer_despeck: start\n"); 1087141cc406Sopenharmony_ci 1088141cc406Sopenharmony_ci ret = sanei_magic_despeck( 1089141cc406Sopenharmony_ci &s->params[side_index],s->img_buffers[side_index],s->val[OPT_SWDESPECK].w 1090141cc406Sopenharmony_ci ); 1091141cc406Sopenharmony_ci if(ret){ 1092141cc406Sopenharmony_ci DBG (5, "buffer_despeck: bad despeck, bailing\n"); 1093141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 1094141cc406Sopenharmony_ci goto cleanup; 1095141cc406Sopenharmony_ci } 1096141cc406Sopenharmony_ci 1097141cc406Sopenharmony_ci cleanup: 1098141cc406Sopenharmony_ci DBG (10, "buffer_despeck: finish\n"); 1099141cc406Sopenharmony_ci return ret; 1100141cc406Sopenharmony_ci} 1101141cc406Sopenharmony_ci 1102141cc406Sopenharmony_ci/* Look if image has too few dark pixels. 1103141cc406Sopenharmony_ci * FIXME: should we do this before we binarize instead of after? */ 1104141cc406Sopenharmony_ciint 1105141cc406Sopenharmony_cibuffer_isblank(PKV_DEV s, int side) 1106141cc406Sopenharmony_ci{ 1107141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 1108141cc406Sopenharmony_ci int side_index = (side == SIDE_FRONT)?0:1; 1109141cc406Sopenharmony_ci int status = 0; 1110141cc406Sopenharmony_ci 1111141cc406Sopenharmony_ci DBG (10, "buffer_isblank: start\n"); 1112141cc406Sopenharmony_ci 1113141cc406Sopenharmony_ci ret = sanei_magic_isBlank( 1114141cc406Sopenharmony_ci &s->params[side_index],s->img_buffers[side_index], 1115141cc406Sopenharmony_ci SANE_UNFIX(s->val[OPT_SWSKIP].w) 1116141cc406Sopenharmony_ci ); 1117141cc406Sopenharmony_ci 1118141cc406Sopenharmony_ci if(ret == SANE_STATUS_NO_DOCS){ 1119141cc406Sopenharmony_ci DBG (5, "buffer_isblank: blank!\n"); 1120141cc406Sopenharmony_ci status = 1; 1121141cc406Sopenharmony_ci } 1122141cc406Sopenharmony_ci else if(ret){ 1123141cc406Sopenharmony_ci DBG (5, "buffer_isblank: error %d\n",ret); 1124141cc406Sopenharmony_ci } 1125141cc406Sopenharmony_ci 1126141cc406Sopenharmony_ci DBG (10, "buffer_isblank: finished\n"); 1127141cc406Sopenharmony_ci return status; 1128141cc406Sopenharmony_ci} 1129141cc406Sopenharmony_ci 1130141cc406Sopenharmony_ci/* Look if image needs rotation 1131141cc406Sopenharmony_ci * FIXME: should we do this before we binarize instead of after? */ 1132141cc406Sopenharmony_ciSANE_Status 1133141cc406Sopenharmony_cibuffer_rotate(PKV_DEV s, int side) 1134141cc406Sopenharmony_ci{ 1135141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 1136141cc406Sopenharmony_ci int angle = 0; 1137141cc406Sopenharmony_ci int side_index = (side == SIDE_FRONT)?0:1; 1138141cc406Sopenharmony_ci int resolution = s->val[OPT_RESOLUTION].w; 1139141cc406Sopenharmony_ci 1140141cc406Sopenharmony_ci DBG (10, "buffer_rotate: start\n"); 1141141cc406Sopenharmony_ci 1142141cc406Sopenharmony_ci if(s->val[OPT_SWDEROTATE].w){ 1143141cc406Sopenharmony_ci ret = sanei_magic_findTurn( 1144141cc406Sopenharmony_ci &s->params[side_index],s->img_buffers[side_index], 1145141cc406Sopenharmony_ci resolution,resolution,&angle); 1146141cc406Sopenharmony_ci 1147141cc406Sopenharmony_ci if(ret){ 1148141cc406Sopenharmony_ci DBG (5, "buffer_rotate: error %d\n",ret); 1149141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 1150141cc406Sopenharmony_ci goto cleanup; 1151141cc406Sopenharmony_ci } 1152141cc406Sopenharmony_ci } 1153141cc406Sopenharmony_ci 1154141cc406Sopenharmony_ci angle += s->val[OPT_ROTATE].w; 1155141cc406Sopenharmony_ci 1156141cc406Sopenharmony_ci /*90 or 270 degree rotations are reversed on back side*/ 1157141cc406Sopenharmony_ci if(side == SIDE_BACK && s->val[OPT_ROTATE].w % 180){ 1158141cc406Sopenharmony_ci angle += 180; 1159141cc406Sopenharmony_ci } 1160141cc406Sopenharmony_ci 1161141cc406Sopenharmony_ci ret = sanei_magic_turn( 1162141cc406Sopenharmony_ci &s->params[side_index],s->img_buffers[side_index], 1163141cc406Sopenharmony_ci angle); 1164141cc406Sopenharmony_ci 1165141cc406Sopenharmony_ci if(ret){ 1166141cc406Sopenharmony_ci DBG (5, "buffer_rotate: error %d\n",ret); 1167141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 1168141cc406Sopenharmony_ci goto cleanup; 1169141cc406Sopenharmony_ci } 1170141cc406Sopenharmony_ci 1171141cc406Sopenharmony_ci /* update image size counter to new, smaller size */ 1172141cc406Sopenharmony_ci s->img_size[side_index] 1173141cc406Sopenharmony_ci = s->params[side_index].lines * s->params[side_index].bytes_per_line; 1174141cc406Sopenharmony_ci 1175141cc406Sopenharmony_ci cleanup: 1176141cc406Sopenharmony_ci DBG (10, "buffer_rotate: finished\n"); 1177141cc406Sopenharmony_ci return ret; 1178141cc406Sopenharmony_ci} 1179