/** release all claimed devices * loop on all opened devices and claim interface 0 * @param dn array of opened device number * @param expected number of devices to be claimed * @return 1 on success, else 0 */ static int test_release_all (SANE_Int * dn, int expected) { int released = 0; int i; SANE_Status status; device_list_type mock; released = 0; for (i = 0; i < expected; i++) { status = sanei_usb_release_interface (dn[i], devices[dn[i]].interface_nr); if (status != SANE_STATUS_GOOD) { printf ("ERROR: couldn't release interface 0 on device %d!\n", dn[i]); } else { released++; } } if (released != expected) { printf ("ERROR: expected %d released interfaces, got %d!\n", expected, released); return 0; } printf ("%d devices released...\n\n", released); /* try to release invalid device entry */ status = sanei_usb_release_interface (device_number, 0); if (status == SANE_STATUS_GOOD) { printf ("ERROR: could release interface 0 on invalid device!\n"); return 0; } /* create a mock device and make it missing by rescanning */ create_mock_device ("mock", &mock); store_device (mock); sanei_usb_scan_devices (); /* try to claim interface on missing device */ status = sanei_usb_release_interface (device_number - 1, 0); if (status == SANE_STATUS_GOOD) { printf ("ERROR: could release interface 0 on invalid device!\n"); return 0; } /* remove mock device */ device_number--; free (devices[device_number].devname); devices[device_number].devname = NULL; return 1; }
/* Close device */ void sane_close (SANE_Handle handle) { struct scanner *s = (struct scanner *) handle; unsigned i; hopper_down (s); if (s->bus == USB) { sanei_usb_release_interface (s->file, 0); sanei_usb_close (s->file); } else sanei_scsi_close (s->file); for (i = 1; i < NUM_OPTIONS; i++) { if (s->opt[i].type == SANE_TYPE_STRING && s->val[i].s) free (s->val[i].s); } for (i = 0; i < sizeof (s->buf) / sizeof (s->buf[0]); i++) buf_deinit (&s->buf[i]); free (s->buffer); free (s); }
static SANE_Status usb_send_command (struct scanner *s, struct cmd *c, struct response *r, void *buf) { SANE_Status st; struct bulk_header *h = (struct bulk_header *) buf; u8 resp[sizeof (*h) + STATUS_SIZE]; size_t sz = sizeof (*h) + MAX_CMD_SIZE; memset (h, 0, sz); h->length = cpu2be32 (sz); h->type = cpu2be16 (COMMAND_BLOCK); h->code = cpu2be16 (COMMAND_CODE); memcpy (h + 1, c->cmd, c->cmd_size); st = sanei_usb_write_bulk (s->file, (const SANE_Byte *) h, &sz); if (st) return st; if (sz != sizeof (*h) + MAX_CMD_SIZE) return SANE_STATUS_IO_ERROR; if (c->dir == CMD_IN) { sz = sizeof (*h) + c->data_size; st = sanei_usb_read_bulk (s->file, (SANE_Byte *) h, &sz); c->data = h + 1; c->data_size = sz - sizeof (*h); if (st || sz < sizeof (*h)) { st = sanei_usb_release_interface (s->file, 0); if (st) return st; st = sanei_usb_claim_interface (s->file, 0); if (st) return st; r->status = CHECK_CONDITION; return SANE_STATUS_GOOD; } } else if (c->dir == CMD_OUT) { sz = sizeof (*h) + c->data_size; memset (h, 0, sizeof (*h)); h->length = cpu2be32 (sizeof (*h) + c->data_size); h->type = cpu2be16 (DATA_BLOCK); h->code = cpu2be16 (DATA_CODE); memcpy (h + 1, c->data, c->data_size); st = sanei_usb_write_bulk (s->file, (const SANE_Byte *) h, &sz); if (st) return st; } sz = sizeof (resp); st = sanei_usb_read_bulk (s->file, resp, &sz); if (st || sz != sizeof (resp)) return SANE_STATUS_IO_ERROR; r->status = be2cpu32 (*((u32 *) (resp + sizeof (*h)))); return st; }
void sane_close (SANE_Handle h) { struct device_s *dev = (struct device_s *) h; /* Just in case if sane_cancel() is called * after starting a scan but not while a sane_read */ if (dev->status == STATUS_CANCELING) { do_cancel(dev); } sanei_usb_release_interface (dev->dn, 0); sanei_usb_close (dev->dn); }
/* Close device */ void sane_close (SANE_Handle handle) { struct scanner *s = (struct scanner *) handle; int i; if (s->bus == USB) { sanei_usb_release_interface (s->file, 0); sanei_usb_close (s->file); } else sanei_scsi_close (s->file); for (i = 1; i < NUM_OPTIONS; i++) { if (s->opt[i].type == SANE_TYPE_STRING && s->val[i].s) free (s->val[i].s); } if (s->data) free (s->data); free (s->buffer); free (s); }
/* Open device, return the device handle */ SANE_Status sane_open (SANE_String_Const devname, SANE_Handle * handle) { unsigned i, j, id = 0; struct scanner *s; SANE_Int h, bus; SANE_Status st = SANE_STATUS_GOOD; if (!devlist) { st = sane_get_devices (NULL, 0); if (st) return st; } for (i = 0; devlist[i]; i++) { if (!strcmp (devlist[i]->name, devname)) break; } if (!devlist[i]) return SANE_STATUS_INVAL; for (j = 0; j < sizeof (known_devices) / sizeof (known_devices[0]); j++) { if (!strcmp (devlist[i]->model, known_devices[j].scanner.model)) { id = known_devices[j].id; break; } } st = sanei_usb_open (devname, &h); if (st == SANE_STATUS_ACCESS_DENIED) return st; if (st) { st = sanei_scsi_open (devname, &h, kvs40xx_sense_handler, NULL); if (st) { return st; } bus = SCSI; } else { bus = USB; st = sanei_usb_claim_interface (h, 0); if (st) { sanei_usb_close (h); return st; } } s = malloc (sizeof (struct scanner)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (struct scanner)); s->buffer = malloc (MAX_READ_DATA_SIZE + BULK_HEADER_SIZE); if (!s->buffer) return SANE_STATUS_NO_MEM; s->file = h; s->bus = bus; s->id = id; strcpy (s->name, devname); *handle = s; for (i = 0; i < 3; i++) { st = kvs40xx_test_unit_ready (s); if (st) { if (s->bus == SCSI) { sanei_scsi_close (s->file); st = sanei_scsi_open (devname, &h, kvs40xx_sense_handler, NULL); if (st) return st; } else { sanei_usb_release_interface (s->file, 0); sanei_usb_close (s->file); st = sanei_usb_open (devname, &h); if (st) return st; st = sanei_usb_claim_interface (h, 0); if (st) { sanei_usb_close (h); return st; } } s->file = h; } else break; } if (i == 3) return SANE_STATUS_DEVICE_BUSY; if (id == KV_S4085C || id == KV_S4065C) { char str[16]; st = inquiry (s, str); if (st) goto err; if (id == KV_S4085C) s->id = !strcmp (str, "KV-S4085CL") ? KV_S4085CL : KV_S4085CW; else s->id = !strcmp (str, "KV-S4065CL") ? KV_S4065CL : KV_S4065CW; } kvs40xx_init_options (s); st = kvs40xx_set_timeout (s, s->val[FEED_TIMEOUT].w); if (st) goto err; return SANE_STATUS_GOOD; err: sane_close (s); return st; }