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#include <sys/ioctl.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#include "kvs1025_usb.h" 35141cc406Sopenharmony_ci#include "kvs1025_cmds.h" 36141cc406Sopenharmony_ci 37141cc406Sopenharmony_ci#include "../include/sane/sanei_debug.h" 38141cc406Sopenharmony_ci 39141cc406Sopenharmony_ciextern PKV_DEV g_devices; /* Chain of devices */ 40141cc406Sopenharmony_ciextern const SANE_Device **g_devlist; 41141cc406Sopenharmony_ci 42141cc406Sopenharmony_ci/* static functions */ 43141cc406Sopenharmony_ci 44141cc406Sopenharmony_ci/* Attach USB scanner */ 45141cc406Sopenharmony_cistatic SANE_Status 46141cc406Sopenharmony_ciattach_scanner_usb (const char *device_name) 47141cc406Sopenharmony_ci{ 48141cc406Sopenharmony_ci PKV_DEV dev; 49141cc406Sopenharmony_ci SANE_Word vendor, product; 50141cc406Sopenharmony_ci 51141cc406Sopenharmony_ci DBG (DBG_error, "attaching USB scanner %s\n", device_name); 52141cc406Sopenharmony_ci 53141cc406Sopenharmony_ci sanei_usb_get_vendor_product_byname(device_name,&vendor,&product); 54141cc406Sopenharmony_ci 55141cc406Sopenharmony_ci dev = (PKV_DEV) malloc (sizeof (KV_DEV)); 56141cc406Sopenharmony_ci 57141cc406Sopenharmony_ci if (dev == NULL) 58141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 59141cc406Sopenharmony_ci 60141cc406Sopenharmony_ci memset (dev, 0, sizeof (KV_DEV)); 61141cc406Sopenharmony_ci 62141cc406Sopenharmony_ci dev->bus_mode = KV_USB_BUS; 63141cc406Sopenharmony_ci dev->usb_fd = -1; 64141cc406Sopenharmony_ci dev->scsi_fd = -1; 65141cc406Sopenharmony_ci strcpy (dev->device_name, device_name); 66141cc406Sopenharmony_ci 67141cc406Sopenharmony_ci dev->buffer0 = (unsigned char *) malloc (SCSI_BUFFER_SIZE + 12); 68141cc406Sopenharmony_ci dev->buffer = dev->buffer0 + 12; 69141cc406Sopenharmony_ci 70141cc406Sopenharmony_ci if (dev->buffer0 == NULL) 71141cc406Sopenharmony_ci { 72141cc406Sopenharmony_ci free (dev); 73141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 74141cc406Sopenharmony_ci } 75141cc406Sopenharmony_ci 76141cc406Sopenharmony_ci dev->scsi_type = 6; 77141cc406Sopenharmony_ci strcpy (dev->scsi_type_str, "ADF Scanner"); 78141cc406Sopenharmony_ci strcpy (dev->scsi_vendor, "Panasonic"); 79141cc406Sopenharmony_ci strcpy (dev->scsi_product, 80141cc406Sopenharmony_ci product == (int) KV_S1020C ? "KV-S1020C" : 81141cc406Sopenharmony_ci product == (int) KV_S1025C ? "KV-S1025C" : 82141cc406Sopenharmony_ci product == (int) KV_S1045C ? "KV-S1045C" : 83141cc406Sopenharmony_ci "KV-S10xxC"); 84141cc406Sopenharmony_ci strcpy (dev->scsi_version, "1.00"); 85141cc406Sopenharmony_ci 86141cc406Sopenharmony_ci /* Set SANE_Device */ 87141cc406Sopenharmony_ci dev->sane.name = dev->device_name; 88141cc406Sopenharmony_ci dev->sane.vendor = dev->scsi_vendor; 89141cc406Sopenharmony_ci dev->sane.model = dev->scsi_product; 90141cc406Sopenharmony_ci dev->sane.type = dev->scsi_type_str; 91141cc406Sopenharmony_ci 92141cc406Sopenharmony_ci /* Add into g_devices chain */ 93141cc406Sopenharmony_ci dev->next = g_devices; 94141cc406Sopenharmony_ci g_devices = dev; 95141cc406Sopenharmony_ci 96141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 97141cc406Sopenharmony_ci} 98141cc406Sopenharmony_ci 99141cc406Sopenharmony_ci/* Get all supported scanners, and store into g_devlist */ 100141cc406Sopenharmony_ciSANE_Status 101141cc406Sopenharmony_cikv_usb_enum_devices (void) 102141cc406Sopenharmony_ci{ 103141cc406Sopenharmony_ci int cnt = 0; 104141cc406Sopenharmony_ci int i; 105141cc406Sopenharmony_ci PKV_DEV pd; 106141cc406Sopenharmony_ci char usb_str[18]; 107141cc406Sopenharmony_ci 108141cc406Sopenharmony_ci DBG (DBG_proc, "kv_usb_enum_devices: enter\n"); 109141cc406Sopenharmony_ci 110141cc406Sopenharmony_ci sanei_usb_init(); 111141cc406Sopenharmony_ci 112141cc406Sopenharmony_ci sprintf(usb_str,"usb %#04x %#04x",VENDOR_ID,KV_S1020C); 113141cc406Sopenharmony_ci sanei_usb_attach_matching_devices(usb_str, attach_scanner_usb); 114141cc406Sopenharmony_ci 115141cc406Sopenharmony_ci sprintf(usb_str,"usb %#04x %#04x",VENDOR_ID,KV_S1025C); 116141cc406Sopenharmony_ci sanei_usb_attach_matching_devices(usb_str, attach_scanner_usb); 117141cc406Sopenharmony_ci 118141cc406Sopenharmony_ci sprintf(usb_str,"usb %#04x %#04x",VENDOR_ID,KV_S1045C); 119141cc406Sopenharmony_ci sanei_usb_attach_matching_devices(usb_str, attach_scanner_usb); 120141cc406Sopenharmony_ci 121141cc406Sopenharmony_ci for (pd = g_devices; pd; pd=pd->next) { 122141cc406Sopenharmony_ci cnt++; 123141cc406Sopenharmony_ci } 124141cc406Sopenharmony_ci 125141cc406Sopenharmony_ci g_devlist = 126141cc406Sopenharmony_ci (const SANE_Device **) malloc (sizeof (SANE_Device *) * (cnt + 1)); 127141cc406Sopenharmony_ci if (g_devlist == NULL) 128141cc406Sopenharmony_ci { 129141cc406Sopenharmony_ci DBG (DBG_proc, 130141cc406Sopenharmony_ci "kv_usb_enum_devices: leave on error " " --out of memory\n"); 131141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 132141cc406Sopenharmony_ci } 133141cc406Sopenharmony_ci 134141cc406Sopenharmony_ci pd = g_devices; 135141cc406Sopenharmony_ci for (i = 0; i < cnt; i++) 136141cc406Sopenharmony_ci { 137141cc406Sopenharmony_ci g_devlist[i] = (const SANE_Device *) &pd->sane; 138141cc406Sopenharmony_ci pd = pd->next; 139141cc406Sopenharmony_ci } 140141cc406Sopenharmony_ci g_devlist[cnt] = 0; 141141cc406Sopenharmony_ci 142141cc406Sopenharmony_ci DBG (DBG_proc, "kv_usb_enum_devices: leave with %d devices.\n", cnt); 143141cc406Sopenharmony_ci 144141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 145141cc406Sopenharmony_ci} 146141cc406Sopenharmony_ci 147141cc406Sopenharmony_ci/* Check if device is already open */ 148141cc406Sopenharmony_ciSANE_Bool 149141cc406Sopenharmony_cikv_usb_already_open (PKV_DEV dev) 150141cc406Sopenharmony_ci{ 151141cc406Sopenharmony_ci return (dev->usb_fd > -1); 152141cc406Sopenharmony_ci} 153141cc406Sopenharmony_ci 154141cc406Sopenharmony_ci/* Open an USB device */ 155141cc406Sopenharmony_ciSANE_Status 156141cc406Sopenharmony_cikv_usb_open (PKV_DEV dev) 157141cc406Sopenharmony_ci{ 158141cc406Sopenharmony_ci SANE_Status ret; 159141cc406Sopenharmony_ci 160141cc406Sopenharmony_ci DBG (DBG_proc, "kv_usb_open: enter\n"); 161141cc406Sopenharmony_ci if (kv_usb_already_open(dev)) 162141cc406Sopenharmony_ci { 163141cc406Sopenharmony_ci DBG (DBG_proc, "kv_usb_open: leave -- already open\n"); 164141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 165141cc406Sopenharmony_ci } 166141cc406Sopenharmony_ci 167141cc406Sopenharmony_ci ret = sanei_usb_open (dev->device_name, &(dev->usb_fd)); 168141cc406Sopenharmony_ci if (ret) 169141cc406Sopenharmony_ci { 170141cc406Sopenharmony_ci DBG (DBG_error, "kv_usb_open: leave -- cannot open device\n"); 171141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 172141cc406Sopenharmony_ci } 173141cc406Sopenharmony_ci 174141cc406Sopenharmony_ci sanei_usb_clear_halt (dev->usb_fd); 175141cc406Sopenharmony_ci 176141cc406Sopenharmony_ci DBG (DBG_proc, "kv_usb_open: leave\n"); 177141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 178141cc406Sopenharmony_ci} 179141cc406Sopenharmony_ci 180141cc406Sopenharmony_ci/* Close an USB device */ 181141cc406Sopenharmony_civoid 182141cc406Sopenharmony_cikv_usb_close (PKV_DEV dev) 183141cc406Sopenharmony_ci{ 184141cc406Sopenharmony_ci DBG (DBG_proc, "kv_usb_close: enter\n"); 185141cc406Sopenharmony_ci if (kv_usb_already_open(dev)) 186141cc406Sopenharmony_ci { 187141cc406Sopenharmony_ci sanei_usb_close(dev->usb_fd); 188141cc406Sopenharmony_ci dev->usb_fd = -1; 189141cc406Sopenharmony_ci } 190141cc406Sopenharmony_ci DBG (DBG_proc, "kv_usb_close: leave\n"); 191141cc406Sopenharmony_ci} 192141cc406Sopenharmony_ci 193141cc406Sopenharmony_ci/* Clean up the USB bus and release all resources allocated to devices */ 194141cc406Sopenharmony_civoid 195141cc406Sopenharmony_cikv_usb_cleanup (void) 196141cc406Sopenharmony_ci{ 197141cc406Sopenharmony_ci} 198141cc406Sopenharmony_ci 199141cc406Sopenharmony_ci/* Send command via USB, and get response data */ 200141cc406Sopenharmony_ciSANE_Status 201141cc406Sopenharmony_cikv_usb_escape (PKV_DEV dev, 202141cc406Sopenharmony_ci PKV_CMD_HEADER header, unsigned char *status_byte) 203141cc406Sopenharmony_ci{ 204141cc406Sopenharmony_ci int got_response = 0; 205141cc406Sopenharmony_ci size_t len; 206141cc406Sopenharmony_ci unsigned char cmd_buff[24]; 207141cc406Sopenharmony_ci memset (cmd_buff, 0, 24); 208141cc406Sopenharmony_ci cmd_buff[3] = 0x18; /* container length */ 209141cc406Sopenharmony_ci cmd_buff[5] = 1; /* container type: command block */ 210141cc406Sopenharmony_ci cmd_buff[6] = 0x90; /* code */ 211141cc406Sopenharmony_ci 212141cc406Sopenharmony_ci if (!kv_usb_already_open(dev)) 213141cc406Sopenharmony_ci { 214141cc406Sopenharmony_ci DBG (DBG_error, "kv_usb_escape: error, device not open.\n"); 215141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 216141cc406Sopenharmony_ci } 217141cc406Sopenharmony_ci memcpy (cmd_buff + 12, header->cdb, header->cdb_size); 218141cc406Sopenharmony_ci 219141cc406Sopenharmony_ci /* change timeout */ 220141cc406Sopenharmony_ci sanei_usb_set_timeout(KV_CMD_TIMEOUT); 221141cc406Sopenharmony_ci 222141cc406Sopenharmony_ci /* Send command */ 223141cc406Sopenharmony_ci len = 24; 224141cc406Sopenharmony_ci if (sanei_usb_write_bulk (dev->usb_fd, (SANE_Byte *) cmd_buff, &len)) 225141cc406Sopenharmony_ci { 226141cc406Sopenharmony_ci DBG (DBG_error, "usb_bulk_write: Error writing command.\n"); 227141cc406Sopenharmony_ci hexdump (DBG_error, "cmd block", cmd_buff, 24); 228141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 229141cc406Sopenharmony_ci } 230141cc406Sopenharmony_ci 231141cc406Sopenharmony_ci /* Send / Read data */ 232141cc406Sopenharmony_ci if (header->direction == KV_CMD_IN) 233141cc406Sopenharmony_ci { 234141cc406Sopenharmony_ci size_t size = header->data_size + 12; 235141cc406Sopenharmony_ci size_t size_read = size; 236141cc406Sopenharmony_ci unsigned char *data = ((unsigned char *) header->data) - 12; 237141cc406Sopenharmony_ci SANE_Status ret; 238141cc406Sopenharmony_ci 239141cc406Sopenharmony_ci ret = sanei_usb_read_bulk (dev->usb_fd, (SANE_Byte *) data, &size_read); 240141cc406Sopenharmony_ci 241141cc406Sopenharmony_ci /*empty read is ok?*/ 242141cc406Sopenharmony_ci if (ret == SANE_STATUS_EOF){ 243141cc406Sopenharmony_ci sanei_usb_clear_halt (dev->usb_fd); 244141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 245141cc406Sopenharmony_ci } 246141cc406Sopenharmony_ci 247141cc406Sopenharmony_ci if (ret) { 248141cc406Sopenharmony_ci sanei_usb_clear_halt (dev->usb_fd); 249141cc406Sopenharmony_ci DBG (DBG_error, "usb_bulk_read: Error reading data.\n"); 250141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 251141cc406Sopenharmony_ci } 252141cc406Sopenharmony_ci 253141cc406Sopenharmony_ci if (size_read != size) 254141cc406Sopenharmony_ci { 255141cc406Sopenharmony_ci DBG (DBG_shortread, "usb_bulk_read: Warning - short read\n"); 256141cc406Sopenharmony_ci DBG (DBG_shortread, "usb_bulk_read: bytes to read = %lu\n", (unsigned long)size); 257141cc406Sopenharmony_ci DBG (DBG_shortread, 258141cc406Sopenharmony_ci "usb_bulk_read: bytes actual read = %lu\n", (unsigned long)size_read); 259141cc406Sopenharmony_ci /*hexdump (DBG_shortread, "data", data, size_read); */ 260141cc406Sopenharmony_ci } 261141cc406Sopenharmony_ci } 262141cc406Sopenharmony_ci 263141cc406Sopenharmony_ci if (header->direction == KV_CMD_OUT) 264141cc406Sopenharmony_ci { 265141cc406Sopenharmony_ci size_t size = header->data_size + 12; 266141cc406Sopenharmony_ci size_t size_written = size; 267141cc406Sopenharmony_ci unsigned char *data = ((unsigned char *) header->data) - 12; 268141cc406Sopenharmony_ci SANE_Status ret; 269141cc406Sopenharmony_ci 270141cc406Sopenharmony_ci memset (data, 0, 12); 271141cc406Sopenharmony_ci Ito32 (size, data); 272141cc406Sopenharmony_ci data[5] = 0x02; /* container type: data block */ 273141cc406Sopenharmony_ci data[6] = 0xb0; /* code */ 274141cc406Sopenharmony_ci 275141cc406Sopenharmony_ci ret = sanei_usb_write_bulk (dev->usb_fd, (SANE_Byte *) data, &size_written); 276141cc406Sopenharmony_ci 277141cc406Sopenharmony_ci /*empty write is ok?*/ 278141cc406Sopenharmony_ci if (ret == SANE_STATUS_EOF){ 279141cc406Sopenharmony_ci sanei_usb_clear_halt (dev->usb_fd); 280141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 281141cc406Sopenharmony_ci } 282141cc406Sopenharmony_ci 283141cc406Sopenharmony_ci if (ret) { 284141cc406Sopenharmony_ci sanei_usb_clear_halt (dev->usb_fd); 285141cc406Sopenharmony_ci DBG (DBG_error, "usb_bulk_write: Error writing data.\n"); 286141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 287141cc406Sopenharmony_ci } 288141cc406Sopenharmony_ci 289141cc406Sopenharmony_ci if (size_written != size) 290141cc406Sopenharmony_ci { 291141cc406Sopenharmony_ci DBG (DBG_shortread, "usb_bulk_write: Warning - short written\n"); 292141cc406Sopenharmony_ci DBG (DBG_shortread, "usb_bulk_write: bytes to write = %lu\n", (unsigned long)size); 293141cc406Sopenharmony_ci DBG (DBG_shortread, 294141cc406Sopenharmony_ci "usb_bulk_write: bytes actual written = %lu\n", (unsigned long)size_written); 295141cc406Sopenharmony_ci hexdump (DBG_shortread, "data", data, size_written); 296141cc406Sopenharmony_ci } 297141cc406Sopenharmony_ci } 298141cc406Sopenharmony_ci 299141cc406Sopenharmony_ci /* Get response */ 300141cc406Sopenharmony_ci if (!got_response) 301141cc406Sopenharmony_ci { 302141cc406Sopenharmony_ci SANE_Status ret; 303141cc406Sopenharmony_ci size_t len = 16; 304141cc406Sopenharmony_ci 305141cc406Sopenharmony_ci ret = sanei_usb_read_bulk (dev->usb_fd, (SANE_Byte *) cmd_buff, &len); 306141cc406Sopenharmony_ci 307141cc406Sopenharmony_ci if (ret || len != 16) 308141cc406Sopenharmony_ci { 309141cc406Sopenharmony_ci DBG (DBG_error, "usb_bulk_read: Error reading response." 310141cc406Sopenharmony_ci " read %lu bytes\n", (unsigned long)len); 311141cc406Sopenharmony_ci sanei_usb_clear_halt (dev->usb_fd); 312141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 313141cc406Sopenharmony_ci } 314141cc406Sopenharmony_ci } 315141cc406Sopenharmony_ci 316141cc406Sopenharmony_ci if (cmd_buff[5] != 3) 317141cc406Sopenharmony_ci { 318141cc406Sopenharmony_ci DBG (DBG_error, "usb_bulk_read: Invalid response block.\n"); 319141cc406Sopenharmony_ci hexdump (DBG_error, "response", cmd_buff, 16); 320141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 321141cc406Sopenharmony_ci } 322141cc406Sopenharmony_ci 323141cc406Sopenharmony_ci *status_byte = cmd_buff[15] & 0x3E; 324141cc406Sopenharmony_ci 325141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 326141cc406Sopenharmony_ci} 327141cc406Sopenharmony_ci 328141cc406Sopenharmony_ci/* Send command via USB, and request sense on CHECK CONDITION status */ 329141cc406Sopenharmony_ciSANE_Status 330141cc406Sopenharmony_cikv_usb_send_command (PKV_DEV dev, 331141cc406Sopenharmony_ci PKV_CMD_HEADER header, PKV_CMD_RESPONSE response) 332141cc406Sopenharmony_ci{ 333141cc406Sopenharmony_ci unsigned char status = 0; 334141cc406Sopenharmony_ci SANE_Status s; 335141cc406Sopenharmony_ci memset (response, 0, sizeof (KV_CMD_RESPONSE)); 336141cc406Sopenharmony_ci response->status = KV_FAILED; 337141cc406Sopenharmony_ci 338141cc406Sopenharmony_ci s = kv_usb_escape (dev, header, &status); 339141cc406Sopenharmony_ci 340141cc406Sopenharmony_ci if (s) 341141cc406Sopenharmony_ci { 342141cc406Sopenharmony_ci status = 0x02; 343141cc406Sopenharmony_ci } 344141cc406Sopenharmony_ci 345141cc406Sopenharmony_ci if (status == 0x02) 346141cc406Sopenharmony_ci { /* check condition */ 347141cc406Sopenharmony_ci /* request sense */ 348141cc406Sopenharmony_ci KV_CMD_HEADER hdr; 349141cc406Sopenharmony_ci memset (&hdr, 0, sizeof (hdr)); 350141cc406Sopenharmony_ci hdr.direction = KV_CMD_IN; 351141cc406Sopenharmony_ci hdr.cdb[0] = SCSI_REQUEST_SENSE; 352141cc406Sopenharmony_ci hdr.cdb[4] = 0x12; 353141cc406Sopenharmony_ci hdr.cdb_size = 6; 354141cc406Sopenharmony_ci hdr.data_size = 0x12; 355141cc406Sopenharmony_ci hdr.data = &response->sense; 356141cc406Sopenharmony_ci 357141cc406Sopenharmony_ci if (kv_usb_escape (dev, &hdr, &status) != 0) 358141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 359141cc406Sopenharmony_ci 360141cc406Sopenharmony_ci hexdump (DBG_error, "sense data", (unsigned char *) &response->sense, 361141cc406Sopenharmony_ci 0x12); 362141cc406Sopenharmony_ci 363141cc406Sopenharmony_ci response->status = KV_CHK_CONDITION; 364141cc406Sopenharmony_ci } 365141cc406Sopenharmony_ci else 366141cc406Sopenharmony_ci { 367141cc406Sopenharmony_ci response->status = KV_SUCCESS; 368141cc406Sopenharmony_ci } 369141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 370141cc406Sopenharmony_ci} 371