/*
* libusb example program to manipulate U.are.U 4000B fingerprint scanner.
- * Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
+ * Copyright © 2007 Daniel Drake <dsd@gentoo.org>
*
* Basic image capture program only, does not consider the powerup quirks or
* the fact that image encryption may be enabled. Not expected to work
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <errno.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
-#include <libusb/libusb.h>
+#include "libusb.h"
#define EP_INTR (1 | LIBUSB_ENDPOINT_IN)
#define EP_DATA (2 | LIBUSB_ENDPOINT_IN)
-#define CTRL_IN (LIBUSB_TYPE_VENDOR | LIBUSB_ENDPOINT_IN)
-#define CTRL_OUT (LIBUSB_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT)
+#define CTRL_IN (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN)
+#define CTRL_OUT (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT)
#define USB_RQ 0x04
#define INTR_LENGTH 64
};
static int next_state(void);
-static int submit_irq_urb(void);
-static int submit_img_urb(void);
enum {
STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON = 1,
};
static int state = 0;
-static struct libusb_dev_handle *devh = NULL;
+static struct libusb_device_handle *devh = NULL;
static unsigned char imgbuf[0x1b340];
static unsigned char irqbuf[INTR_LENGTH];
-static libusb_urb_handle *img_urbh = NULL;
-static libusb_urb_handle *irq_urbh = NULL;
+static struct libusb_transfer *img_transfer = NULL;
+static struct libusb_transfer *irq_transfer = NULL;
static int img_idx = 0;
static int do_exit = 0;
-static struct libusb_bulk_transfer imgtrf = {
- .endpoint = EP_DATA,
- .data = imgbuf,
- .length = sizeof(imgbuf),
-};
-
-static struct libusb_bulk_transfer irqtrf = {
- .endpoint = EP_INTR,
- .data = irqbuf,
- .length = sizeof(irqbuf),
-};
-
-static struct libusb_dev *find_dpfp_device(void)
+static int find_dpfp_device(void)
{
- struct libusb_dev *dev;
-
- libusb_find_devices();
-
- for (dev = libusb_get_devices(); dev; dev = libusb_dev_next(dev)) {
- struct libusb_dev_descriptor *desc = libusb_dev_get_descriptor(dev);
- if (desc->idVendor == 0x05ba && desc->idProduct == 0x000a)
- return dev;
- }
-
- return NULL;
+ devh = libusb_open_device_with_vid_pid(NULL, 0x05ba, 0x000a);
+ return devh ? 0 : -EIO;
}
static int print_f0_data(void)
{
unsigned char data[0x10];
- struct libusb_control_transfer transfer = {
- .requesttype = CTRL_IN,
- .request = USB_RQ,
- .value = 0xf0,
- .index = 0,
- .length = sizeof(data),
- .data = data,
- };
int r;
unsigned int i;
- r = libusb_control_transfer(devh, &transfer, 0);
+ r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0xf0, 0, data,
+ sizeof(data), 0);
if (r < 0) {
fprintf(stderr, "F0 error %d\n", r);
return r;
static int get_hwstat(unsigned char *status)
{
- struct libusb_control_transfer transfer = {
- .requesttype = CTRL_IN,
- .request = USB_RQ,
- .value = 0x07,
- .index = 0,
- .length = 1,
- .data = status,
- };
int r;
- r = libusb_control_transfer(devh, &transfer, 0);
+ r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0x07, 0, status, 1, 0);
if (r < 0) {
fprintf(stderr, "read hwstat error %d\n", r);
return r;
static int set_hwstat(unsigned char data)
{
int r;
- struct libusb_control_transfer transfer = {
- .requesttype = CTRL_OUT,
- .request = USB_RQ,
- .value = 0x07,
- .index = 0,
- .length = 1,
- .data = &data,
- };
printf("set hwstat to %02x\n", data);
-
- r = libusb_control_transfer(devh, &transfer, 0);
+ r = libusb_control_transfer(devh, CTRL_OUT, USB_RQ, 0x07, 0, &data, 1, 0);
if (r < 0) {
fprintf(stderr, "set hwstat error %d\n", r);
return r;
static int set_mode(unsigned char data)
{
int r;
- struct libusb_control_transfer transfer = {
- .requesttype = CTRL_OUT,
- .request = USB_RQ,
- .value = 0x4e,
- .index = 0,
- .length = 1,
- .data = &data,
- };
-
printf("set mode %02x\n", data);
- r = libusb_control_transfer(devh, &transfer, 0);
+ r = libusb_control_transfer(devh, CTRL_OUT, USB_RQ, 0x4e, 0, &data, 1, 0);
if (r < 0) {
fprintf(stderr, "set mode error %d\n", r);
return r;
return 0;
}
-static void cb_mode_changed(struct libusb_dev_handle *_devh,
- struct libusb_urb_handle *urbh, enum libusb_urb_cb_status status,
- struct libusb_ctrl_setup *setup, unsigned char *data, int actual_length,
- void *user_data)
+static void LIBUSB_CALL cb_mode_changed(struct libusb_transfer *transfer)
{
- if (status != FP_URB_COMPLETED) {
- fprintf(stderr, "mode change URB not completed!\n");
+ if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
+ fprintf(stderr, "mode change transfer not completed!\n");
do_exit = 2;
}
- printf("async cb_mode_changed\n");
+ printf("async cb_mode_changed length=%d actual_length=%d\n",
+ transfer->length, transfer->actual_length);
if (next_state() < 0)
do_exit = 2;
}
static int set_mode_async(unsigned char data)
{
- libusb_urb_handle *urbh;
- struct libusb_control_transfer transfer = {
- .requesttype = CTRL_OUT,
- .request = USB_RQ,
- .value = 0x4e,
- .index = 0,
- .length = 1,
- .data = &data,
- };
+ unsigned char *buf = (unsigned char*) malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
+ struct libusb_transfer *transfer;
- printf("async set mode %02x\n", data);
+ if (!buf)
+ return -ENOMEM;
- urbh = libusb_async_control_transfer(devh, &transfer, cb_mode_changed, NULL,
- 1000);
- if (!urbh) {
- fprintf(stderr, "set mode submit error\n");
- return -1;
+ transfer = libusb_alloc_transfer(0);
+ if (!transfer) {
+ free(buf);
+ return -ENOMEM;
}
- return 0;
+ printf("async set mode %02x\n", data);
+ libusb_fill_control_setup(buf, CTRL_OUT, USB_RQ, 0x4e, 0, 1);
+ buf[LIBUSB_CONTROL_SETUP_SIZE] = data;
+ libusb_fill_control_transfer(transfer, devh, buf, cb_mode_changed, NULL,
+ 1000);
+
+ transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK
+ | LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER;
+ return libusb_submit_transfer(transfer);
}
static int do_sync_intr(unsigned char *data)
{
- struct libusb_bulk_transfer transfer = {
- .endpoint = EP_INTR,
- .data = data,
- .length = INTR_LENGTH,
- };
int r;
int transferred;
- r = libusb_interrupt_transfer(devh, &transfer, &transferred, 1000);
+ r = libusb_interrupt_transfer(devh, EP_INTR, data, INTR_LENGTH,
+ &transferred, 1000);
if (r < 0) {
fprintf(stderr, "intr error %d\n", r);
return r;
}
static int sync_intr(unsigned char type)
-{
+{
int r;
unsigned char data[INTR_LENGTH];
FILE *fd;
char filename[64];
- sprintf(filename, "finger%d.pgm", img_idx++);
+ snprintf(filename, sizeof(filename), "finger%d.pgm", img_idx++);
fd = fopen(filename, "w");
if (!fd)
return -1;
fputs("P5 384 289 255 ", fd);
- fwrite(data + 64, 1, 384*289, fd);
+ (void) fwrite(data + 64, 1, 384*289, fd);
fclose(fd);
printf("saved image to %s\n", filename);
return 0;
printf("unrecognised state %d\n", state);
}
if (r < 0) {
- fprintf(stderr, "error detected changing state");
+ fprintf(stderr, "error detected changing state\n");
return r;
}
return 0;
}
-static void cb_irq(libusb_dev_handle *_devh, libusb_urb_handle *urbh,
- enum libusb_urb_cb_status status, unsigned char endpoint, int rqlength,
- unsigned char *data, int actual_length, void *user_data)
+static void LIBUSB_CALL cb_irq(struct libusb_transfer *transfer)
{
- unsigned char irqtype = data[0];
+ unsigned char irqtype = transfer->buffer[0];
- if (status != FP_URB_COMPLETED) {
- fprintf(stderr, "irq URB status %d?\n", status);
+ if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
+ fprintf(stderr, "irq transfer status %d?\n", transfer->status);
do_exit = 2;
+ libusb_free_transfer(transfer);
+ irq_transfer = NULL;
return;
}
}
break;
}
- if (submit_irq_urb() < 0)
+ if (libusb_submit_transfer(irq_transfer) < 0)
do_exit = 2;
}
-static void cb_img(libusb_dev_handle *_devh, libusb_urb_handle *urbh,
- enum libusb_urb_cb_status status, unsigned char endpoint, int rqlength,
- unsigned char *data, int actual_length, void *user_data)
+static void LIBUSB_CALL cb_img(struct libusb_transfer *transfer)
{
- if (status != FP_URB_COMPLETED) {
- fprintf(stderr, "img URB status %d?\n", status);
+ if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
+ fprintf(stderr, "img transfer status %d?\n", transfer->status);
do_exit = 2;
+ libusb_free_transfer(transfer);
+ img_transfer = NULL;
return;
}
do_exit = 2;
return;
}
- if (submit_img_urb() < 0)
+ if (libusb_submit_transfer(img_transfer) < 0)
do_exit = 2;
}
-static int submit_irq_urb(void)
-{
- libusb_urb_handle_free(irq_urbh);
- irq_urbh = libusb_async_interrupt_transfer(devh, &irqtrf, cb_irq, NULL, 0);
- return irq_urbh != NULL;
-}
-
-static int submit_img_urb(void)
-{
- libusb_urb_handle_free(img_urbh);
- img_urbh = libusb_async_bulk_transfer(devh, &imgtrf, cb_img, NULL, 0);
- return img_urbh != NULL;
-}
-
static int init_capture(void)
{
int r;
- r = submit_irq_urb();
+ r = libusb_submit_transfer(irq_transfer);
if (r < 0)
return r;
- r = submit_img_urb();
+ r = libusb_submit_transfer(img_transfer);
if (r < 0) {
- libusb_urb_handle_cancel_sync(devh, img_urbh);
+ libusb_cancel_transfer(irq_transfer);
+ while (irq_transfer)
+ if (libusb_handle_events(NULL) < 0)
+ break;
return r;
}
return 0;
}
+static int alloc_transfers(void)
+{
+ img_transfer = libusb_alloc_transfer(0);
+ if (!img_transfer)
+ return -ENOMEM;
+
+ irq_transfer = libusb_alloc_transfer(0);
+ if (!irq_transfer)
+ return -ENOMEM;
+
+ libusb_fill_bulk_transfer(img_transfer, devh, EP_DATA, imgbuf,
+ sizeof(imgbuf), cb_img, NULL, 0);
+ libusb_fill_interrupt_transfer(irq_transfer, devh, EP_INTR, irqbuf,
+ sizeof(irqbuf), cb_irq, NULL, 0);
+
+ return 0;
+}
+
static void sighandler(int signum)
{
- do_exit = 1;
+ (void)signum;
+
+ do_exit = 1;
}
int main(void)
{
- struct libusb_dev *dev;
struct sigaction sigact;
- int r = 1;
+ int r;
- r = libusb_init(0);
+ r = libusb_init(NULL);
if (r < 0) {
fprintf(stderr, "failed to initialise libusb\n");
exit(1);
}
- dev = find_dpfp_device();
- if (!dev) {
- fprintf(stderr, "No device found\n");
- goto out;
- }
- printf("found device\n");
-
- devh = libusb_open(dev);
- if (!devh) {
- fprintf(stderr, "Could not open device\n");
+ r = find_dpfp_device();
+ if (r < 0) {
+ fprintf(stderr, "Could not find/open device\n");
goto out;
}
- printf("opened device\n");
r = libusb_claim_interface(devh, 0);
if (r < 0) {
- fprintf(stderr, "usb_claim_interface error %d %s\n", r, strerror(-r));
+ fprintf(stderr, "usb_claim_interface error %d\n", r);
goto out;
}
printf("claimed interface\n");
/* async from here onwards */
+ r = alloc_transfers();
+ if (r < 0)
+ goto out_deinit;
+
r = init_capture();
if (r < 0)
goto out_deinit;
sigaction(SIGQUIT, &sigact, NULL);
while (!do_exit) {
- r = libusb_poll();
+ r = libusb_handle_events(NULL);
if (r < 0)
goto out_deinit;
}
printf("shutting down...\n");
- r = libusb_urb_handle_cancel_sync(devh, irq_urbh);
- if (r < 0)
- goto out_deinit;
+ if (irq_transfer) {
+ r = libusb_cancel_transfer(irq_transfer);
+ if (r < 0)
+ goto out_deinit;
+ }
+
+ if (img_transfer) {
+ r = libusb_cancel_transfer(img_transfer);
+ if (r < 0)
+ goto out_deinit;
+ }
+
+ while (irq_transfer || img_transfer)
+ if (libusb_handle_events(NULL) < 0)
+ break;
- r = libusb_urb_handle_cancel_sync(devh, img_urbh);
- if (r < 0)
- goto out_deinit;
-
if (do_exit == 1)
r = 0;
else
r = 1;
out_deinit:
- libusb_urb_handle_free(img_urbh);
- libusb_urb_handle_free(irq_urbh);
+ libusb_free_transfer(img_transfer);
+ libusb_free_transfer(irq_transfer);
set_mode(0);
set_hwstat(0x80);
out_release:
libusb_release_interface(devh, 0);
out:
libusb_close(devh);
- libusb_exit();
+ libusb_exit(NULL);
return r >= 0 ? r : -r;
}
-