1/* 2 Copyright (C) 2008, Panasonic Russia Ltd. 3 Copyright (C) 2010, m. allan noah 4*/ 5/* 6 Panasonic KV-S20xx USB-SCSI scanners. 7*/ 8 9#define DEBUG_NOT_STATIC 10#define BUILD 2 11 12#include "../include/sane/config.h" 13 14#include <string.h> 15#include <unistd.h> 16 17#include "../include/sane/sanei_backend.h" 18#include "../include/sane/sanei_scsi.h" 19#include "../include/sane/sanei_usb.h" 20#include "../include/sane/saneopts.h" 21#include "../include/sane/sanei_config.h" 22#include "../include/lassert.h" 23 24#include "kvs20xx.h" 25#include "kvs20xx_cmd.h" 26 27struct known_device 28{ 29 const SANE_Int id; 30 const SANE_Device scanner; 31}; 32 33static const struct known_device known_devices[] = { 34 { 35 KV_S2025C, 36 { "", "MATSHITA", "KV-S2025C", "sheetfed scanner" }, 37 }, 38 { 39 KV_S2045C, 40 { "", "MATSHITA", "KV-S2045C", "sheetfed scanner" }, 41 }, 42 { 43 KV_S2026C, 44 { "", "MATSHITA", "KV-S2026C", "sheetfed scanner" }, 45 }, 46 { 47 KV_S2046C, 48 { "", "MATSHITA", "KV-S2046C", "sheetfed scanner" }, 49 }, 50 { 51 KV_S2028C, 52 { "", "MATSHITA", "KV-S2028C", "sheetfed scanner" }, 53 }, 54 { 55 KV_S2048C, 56 { "", "MATSHITA", "KV-S2048C", "sheetfed scanner" }, 57 }, 58}; 59 60SANE_Status 61sane_init (SANE_Int __sane_unused__ * version_code, 62 SANE_Auth_Callback __sane_unused__ authorize) 63{ 64 DBG_INIT (); 65 DBG (DBG_INFO, "This is panasonic kvs20xx driver\n"); 66 67 *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 68 69 /* Initialize USB */ 70 sanei_usb_init (); 71 72 return SANE_STATUS_GOOD; 73} 74 75/* 76 * List of available devices, allocated by sane_get_devices, released 77 * by sane_exit() 78 */ 79static SANE_Device **devlist = NULL; 80static unsigned curr_scan_dev = 0; 81 82void 83sane_exit (void) 84{ 85 if (devlist) 86 { 87 int i; 88 for (i = 0; devlist[i]; i++) 89 { 90 free ((void *) devlist[i]->name); 91 free ((void *) devlist[i]); 92 } 93 free ((void *) devlist); 94 devlist = NULL; 95 } 96} 97 98static SANE_Status 99attach (SANE_String_Const devname) 100{ 101 int i = 0; 102 if (devlist) 103 { 104 for (; devlist[i]; i++); 105 devlist = realloc (devlist, sizeof (SANE_Device *) * (i + 1)); 106 if (!devlist) 107 return SANE_STATUS_NO_MEM; 108 } 109 else 110 { 111 devlist = malloc (sizeof (SANE_Device *) * 2); 112 if (!devlist) 113 return SANE_STATUS_NO_MEM; 114 } 115 devlist[i] = malloc (sizeof (SANE_Device)); 116 if (!devlist[i]) 117 return SANE_STATUS_NO_MEM; 118 memcpy (devlist[i], &known_devices[curr_scan_dev].scanner, 119 sizeof (SANE_Device)); 120 devlist[i]->name = strdup (devname); 121 /* terminate device list with NULL entry: */ 122 devlist[i + 1] = 0; 123 DBG (DBG_INFO, "%s device attached\n", devname); 124 return SANE_STATUS_GOOD; 125} 126 127/* Get device list */ 128SANE_Status 129sane_get_devices (const SANE_Device *** device_list, 130 SANE_Bool __sane_unused__ local_only) 131{ 132 if (devlist) 133 { 134 int i; 135 for (i = 0; devlist[i]; i++) 136 { 137 free ((void *) devlist[i]->name); 138 free ((void *) devlist[i]); 139 } 140 free ((void *) devlist); 141 devlist = NULL; 142 } 143 144 for (curr_scan_dev = 0; 145 curr_scan_dev < sizeof (known_devices) / sizeof (known_devices[0]); 146 curr_scan_dev++) 147 { 148 sanei_usb_find_devices (PANASONIC_ID, 149 known_devices[curr_scan_dev].id, attach); 150 } 151 for (curr_scan_dev = 0; 152 curr_scan_dev < sizeof (known_devices) / sizeof (known_devices[0]); 153 curr_scan_dev++) 154 { 155 sanei_scsi_find_devices (known_devices[curr_scan_dev].scanner.vendor, 156 known_devices[curr_scan_dev].scanner.model, 157 NULL, -1, -1, -1, -1, attach); 158 } 159 if(device_list) 160 *device_list = (const SANE_Device **) devlist; 161 return SANE_STATUS_GOOD; 162} 163 164/* Open device, return the device handle */ 165SANE_Status 166sane_open (SANE_String_Const devname, SANE_Handle * handle) 167{ 168 unsigned i, j, id = 0; 169 struct scanner *s; 170 SANE_Int h, bus; 171 SANE_Status st; 172 if (!devlist) 173 { 174 st = sane_get_devices (NULL, 0); 175 if (st) 176 return st; 177 } 178 for (i = 0; devlist[i]; i++) 179 { 180 if (!strcmp (devlist[i]->name, devname)) 181 break; 182 } 183 if (!devlist[i]) 184 return SANE_STATUS_INVAL; 185 for (j = 0; j < sizeof (known_devices) / sizeof (known_devices[0]); j++) 186 { 187 if (!strcmp (devlist[i]->model, known_devices[j].scanner.model)) 188 { 189 id = known_devices[j].id; 190 break; 191 } 192 } 193 194 st = sanei_usb_open (devname, &h); 195 if (st == SANE_STATUS_ACCESS_DENIED) 196 return st; 197 if (st) 198 { 199 st = sanei_scsi_open (devname, &h, kvs20xx_sense_handler, NULL); 200 if (st) 201 { 202 return st; 203 } 204 bus = SCSI; 205 } 206 else 207 { 208 bus = USB; 209 st = sanei_usb_claim_interface (h, 0); 210 if (st) 211 { 212 sanei_usb_close (h); 213 return st; 214 } 215 } 216 217 s = malloc (sizeof (struct scanner)); 218 if (!s) 219 return SANE_STATUS_NO_MEM; 220 memset (s, 0, sizeof (struct scanner)); 221 s->buffer = malloc (MAX_READ_DATA_SIZE + BULK_HEADER_SIZE); 222 if (!s->buffer) 223 return SANE_STATUS_NO_MEM; 224 s->file = h; 225 s->bus = bus; 226 s->id = id; 227 kvs20xx_init_options (s); 228 *handle = s; 229 for (i = 0; i < 3; i++) 230 { 231 st = kvs20xx_test_unit_ready (s); 232 if (st) 233 { 234 if (s->bus == SCSI) 235 { 236 sanei_scsi_close (s->file); 237 st = sanei_scsi_open (devname, &h, kvs20xx_sense_handler, NULL); 238 if (st) 239 return st; 240 } 241 else 242 { 243 sanei_usb_release_interface (s->file, 0); 244 sanei_usb_close (s->file); 245 st = sanei_usb_open (devname, &h); 246 if (st) 247 return st; 248 st = sanei_usb_claim_interface (h, 0); 249 if (st) 250 { 251 sanei_usb_close (h); 252 return st; 253 } 254 } 255 s->file = h; 256 } 257 else 258 break; 259 } 260 if (i == 3) 261 return SANE_STATUS_DEVICE_BUSY; 262 263 st = kvs20xx_set_timeout (s, s->val[FEED_TIMEOUT].w); 264 if (st) 265 { 266 sane_close (s); 267 return st; 268 } 269 270 return SANE_STATUS_GOOD; 271} 272 273/* Close device */ 274void 275sane_close (SANE_Handle handle) 276{ 277 struct scanner *s = (struct scanner *) handle; 278 int i; 279 if (s->bus == USB) 280 { 281 sanei_usb_release_interface (s->file, 0); 282 sanei_usb_close (s->file); 283 } 284 else 285 sanei_scsi_close (s->file); 286 287 for (i = 1; i < NUM_OPTIONS; i++) 288 { 289 if (s->opt[i].type == SANE_TYPE_STRING && s->val[i].s) 290 free (s->val[i].s); 291 } 292 if (s->data) 293 free (s->data); 294 free (s->buffer); 295 free (s); 296 297} 298 299/* Get option descriptor */ 300const SANE_Option_Descriptor * 301sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 302{ 303 struct scanner *s = handle; 304 305 if ((unsigned) option >= NUM_OPTIONS || option < 0) 306 return NULL; 307 return s->opt + option; 308} 309 310static SANE_Status 311wait_document (struct scanner *s) 312{ 313 SANE_Status st; 314 int i; 315 if (!strcmp ("off", s->val[MANUALFEED].s)) 316 return kvs20xx_document_exist (s); 317 318 for (i = 0; i < s->val[FEED_TIMEOUT].w; i++) 319 { 320 st = kvs20xx_document_exist (s); 321 if (st != SANE_STATUS_NO_DOCS) 322 return st; 323 sleep (1); 324 } 325 return SANE_STATUS_NO_DOCS; 326} 327 328/* Start scanning */ 329SANE_Status 330sane_start (SANE_Handle handle) 331{ 332 struct scanner *s = (struct scanner *) handle; 333 SANE_Status st; 334 int duplex = s->val[DUPLEX].w; 335 336 if (!s->scanning) 337 { 338 unsigned dummy_length; 339 st = kvs20xx_test_unit_ready (s); 340 if (st) 341 return st; 342 343 st = wait_document (s); 344 if (st) 345 return st; 346 347 st = kvs20xx_reset_window (s); 348 if (st) 349 return st; 350 st = kvs20xx_set_window (s, SIDE_FRONT); 351 if (st) 352 return st; 353 if (duplex) 354 { 355 st = kvs20xx_set_window (s, SIDE_BACK); 356 if (st) 357 return st; 358 } 359 st = kvs20xx_scan (s); 360 if (st) 361 return st; 362 363 st = kvs20xx_read_picture_element (s, SIDE_FRONT, &s->params); 364 if (st) 365 return st; 366 if (duplex) 367 { 368 st = get_adjust_data (s, &dummy_length); 369 if (st) 370 return st; 371 } 372 else 373 { 374 dummy_length = 0; 375 } 376 s->scanning = 1; 377 s->page = 0; 378 s->read = 0; 379 s->side = SIDE_FRONT; 380 sane_get_parameters (s, NULL); 381 s->saved_dummy_size = s->dummy_size = dummy_length 382 ? (dummy_length * s->val[RESOLUTION].w / 1200 - 1) 383 * s->params.bytes_per_line : 0; 384 s->side_size = s->params.lines * s->params.bytes_per_line; 385 386 s->data = realloc (s->data, duplex ? s->side_size * 2 : s->side_size); 387 if (!s->data) 388 { 389 s->scanning = 0; 390 return SANE_STATUS_NO_MEM; 391 } 392 } 393 394 if (duplex) 395 { 396 unsigned side = SIDE_FRONT; 397 unsigned read, mx; 398 if (s->side == SIDE_FRONT && s->read == s->side_size - s->dummy_size) 399 { 400 s->side = SIDE_BACK; 401 s->read = s->dummy_size; 402 s->dummy_size = 0; 403 return SANE_STATUS_GOOD; 404 } 405 s->read = 0; 406 s->dummy_size = s->saved_dummy_size; 407 s->side = SIDE_FRONT; 408 st = kvs20xx_document_exist (s); 409 if (st) 410 return st; 411 for (mx = s->side_size * 2; !st; mx -= read, side ^= SIDE_BACK) 412 st = kvs20xx_read_image_data (s, s->page, side, 413 &s->data[s->side_size * 2 - mx], mx, 414 &read); 415 } 416 else 417 { 418 unsigned read, mx; 419 s->read = 0; 420 st = kvs20xx_document_exist (s); 421 if (st) 422 return st; 423 DBG (DBG_INFO, "start: %d\n", s->page); 424 425 for (mx = s->side_size; !st; mx -= read) 426 st = kvs20xx_read_image_data (s, s->page, SIDE_FRONT, 427 &s->data[s->side_size - mx], mx, &read); 428 } 429 if (st && st != SANE_STATUS_EOF) 430 { 431 s->scanning = 0; 432 return st; 433 } 434 s->page++; 435 return SANE_STATUS_GOOD; 436} 437 438inline static void 439memcpy24 (u8 * dest, u8 * src, unsigned size, unsigned ls) 440{ 441 unsigned i; 442 for (i = 0; i < size; i++) 443 { 444 dest[i * 3] = src[i]; 445 dest[i * 3 + 1] = src[i + ls]; 446 dest[i * 3 + 2] = src[i + 2 * ls]; 447 } 448} 449 450SANE_Status 451sane_read (SANE_Handle handle, SANE_Byte * buf, 452 SANE_Int max_len, SANE_Int * len) 453{ 454 struct scanner *s = (struct scanner *) handle; 455 int duplex = s->val[DUPLEX].w; 456 int color = !strcmp (s->val[MODE].s, SANE_VALUE_SCAN_MODE_COLOR); 457 int rest = s->side_size - s->read - s->dummy_size; 458 *len = 0; 459 460 if (!s->scanning || !rest) 461 { 462 if (strcmp (s->val[FEEDER_MODE].s, SANE_I18N ("continuous"))) 463 { 464 if (!duplex || s->side == SIDE_BACK) 465 s->scanning = 0; 466 } 467 return SANE_STATUS_EOF; 468 } 469 470 *len = max_len < rest ? max_len : rest; 471 if (duplex && (s->id == KV_S2025C 472 || s->id == KV_S2026C || s->id == KV_S2028C)) 473 { 474 if (color) 475 { 476 unsigned ls = s->params.bytes_per_line; 477 unsigned i, a = s->side == SIDE_FRONT ? 0 : ls / 3; 478 u8 *data; 479 *len = (*len / ls) * ls; 480 for (i = 0, data = s->data + s->read * 2 + a; 481 i < *len / ls; buf += ls, data += 2 * ls, i++) 482 memcpy24 (buf, data, ls / 3, ls * 2 / 3); 483 } 484 else 485 { 486 unsigned ls = s->params.bytes_per_line; 487 unsigned i = s->side == SIDE_FRONT ? 0 : ls; 488 unsigned head = ls - (s->read % ls); 489 unsigned tail = (*len - head) % ls; 490 unsigned lines = (*len - head) / ls; 491 u8 *data = s->data + (s->read / ls) * ls * 2 + i + s->read % ls; 492 assert (data <= s->data + s->side_size * 2); 493 memcpy (buf, data, head); 494 for (i = 0, buf += head, data += head + (head ? ls : 0); 495 i < lines; buf += ls, data += ls * 2, i++) 496 { 497 assert (data <= s->data + s->side_size * 2); 498 memcpy (buf, data, ls); 499 } 500 assert ((data <= s->data + s->side_size * 2) || !tail); 501 memcpy (buf, data, tail); 502 } 503 s->read += *len; 504 } 505 else 506 { 507 if (color) 508 { 509 unsigned i, ls = s->params.bytes_per_line; 510 u8 *data = s->data + s->read; 511 *len = (*len / ls) * ls; 512 for (i = 0; i < *len / ls; buf += ls, data += ls, i++) 513 memcpy24 (buf, data, ls / 3, ls / 3); 514 } 515 else 516 { 517 memcpy (buf, s->data + s->read, *len); 518 } 519 s->read += *len; 520 } 521 return SANE_STATUS_GOOD; 522} 523 524void 525sane_cancel (SANE_Handle handle) 526{ 527 struct scanner *s = (struct scanner *) handle; 528 s->scanning = 0; 529} 530 531SANE_Status 532sane_set_io_mode (SANE_Handle __sane_unused__ h, SANE_Bool __sane_unused__ m) 533{ 534 return SANE_STATUS_UNSUPPORTED; 535} 536 537SANE_Status 538sane_get_select_fd (SANE_Handle __sane_unused__ h, 539 SANE_Int __sane_unused__ * fd) 540{ 541 return SANE_STATUS_UNSUPPORTED; 542} 543