2 * libusb example program to manipulate U.are.U 4000B fingerprint scanner.
3 * Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
5 * Basic image capture program only, does not consider the powerup quirks or
6 * the fact that image encryption may be enabled. Not expected to work
7 * flawlessly all of the time.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 #include <libusb/libusb.h>
31 #define EP_INTR (1 | LIBUSB_ENDPOINT_IN)
32 #define EP_DATA (2 | LIBUSB_ENDPOINT_IN)
33 #define CTRL_IN (LIBUSB_TYPE_VENDOR | LIBUSB_ENDPOINT_IN)
34 #define CTRL_OUT (LIBUSB_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT)
36 #define INTR_LENGTH 64
40 MODE_AWAIT_FINGER_ON = 0x10,
41 MODE_AWAIT_FINGER_OFF = 0x12,
47 static int next_state(void);
48 static int submit_irq_urb(void);
49 static int submit_img_urb(void);
52 STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON = 1,
53 STATE_AWAIT_IRQ_FINGER_DETECTED,
54 STATE_AWAIT_MODE_CHANGE_CAPTURE,
56 STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF,
57 STATE_AWAIT_IRQ_FINGER_REMOVED,
61 static struct libusb_dev_handle *devh = NULL;
62 static unsigned char imgbuf[0x1b340];
63 static unsigned char irqbuf[INTR_LENGTH];
64 static libusb_urb_handle *img_urbh = NULL;
65 static libusb_urb_handle *irq_urbh = NULL;
66 static int img_idx = 0;
67 static int do_exit = 0;
69 static struct libusb_bulk_transfer imgtrf = {
72 .length = sizeof(imgbuf),
75 static struct libusb_bulk_transfer irqtrf = {
78 .length = sizeof(irqbuf),
81 static struct libusb_dev *find_dpfp_device(void)
83 struct libusb_dev *dev;
85 libusb_find_devices();
87 for (dev = libusb_get_devices(); dev; dev = libusb_dev_next(dev)) {
88 struct libusb_dev_descriptor *desc = libusb_dev_get_descriptor(dev);
89 if (desc->idVendor == 0x05ba && desc->idProduct == 0x000a)
96 static int print_f0_data(void)
98 unsigned char data[0x10];
99 struct libusb_control_transfer transfer = {
100 .requesttype = CTRL_IN,
104 .length = sizeof(data),
110 r = libusb_control_transfer(devh, &transfer, 0);
112 fprintf(stderr, "F0 error %d\n", r);
115 if ((unsigned int) r < sizeof(data)) {
116 fprintf(stderr, "short read (%d)\n", r);
121 for (i = 0; i < sizeof(data); i++)
122 printf("%02x ", data[i]);
127 static int get_hwstat(unsigned char *status)
129 struct libusb_control_transfer transfer = {
130 .requesttype = CTRL_IN,
139 r = libusb_control_transfer(devh, &transfer, 0);
141 fprintf(stderr, "read hwstat error %d\n", r);
144 if ((unsigned int) r < 1) {
145 fprintf(stderr, "short read (%d)\n", r);
149 printf("hwstat reads %02x\n", *status);
153 static int set_hwstat(unsigned char data)
156 struct libusb_control_transfer transfer = {
157 .requesttype = CTRL_OUT,
165 printf("set hwstat to %02x\n", data);
167 r = libusb_control_transfer(devh, &transfer, 0);
169 fprintf(stderr, "set hwstat error %d\n", r);
172 if ((unsigned int) r < 1) {
173 fprintf(stderr, "short write (%d)", r);
180 static int set_mode(unsigned char data)
183 struct libusb_control_transfer transfer = {
184 .requesttype = CTRL_OUT,
192 printf("set mode %02x\n", data);
194 r = libusb_control_transfer(devh, &transfer, 0);
196 fprintf(stderr, "set mode error %d\n", r);
199 if ((unsigned int) r < 1) {
200 fprintf(stderr, "short write (%d)", r);
207 static void cb_mode_changed(struct libusb_dev_handle *_devh,
208 struct libusb_urb_handle *urbh, enum libusb_urb_cb_status status,
209 struct libusb_ctrl_setup *setup, unsigned char *data, int actual_length,
212 if (status != FP_URB_COMPLETED) {
213 fprintf(stderr, "mode change URB not completed!\n");
217 printf("async cb_mode_changed\n");
218 if (next_state() < 0)
222 static int set_mode_async(unsigned char data)
224 libusb_urb_handle *urbh;
225 struct libusb_control_transfer transfer = {
226 .requesttype = CTRL_OUT,
234 printf("async set mode %02x\n", data);
236 urbh = libusb_async_control_transfer(devh, &transfer, cb_mode_changed, NULL,
239 fprintf(stderr, "set mode submit error\n");
246 static int do_sync_intr(unsigned char *data)
248 struct libusb_bulk_transfer transfer = {
251 .length = INTR_LENGTH,
256 r = libusb_interrupt_transfer(devh, &transfer, &transferred, 1000);
258 fprintf(stderr, "intr error %d\n", r);
261 if (transferred < INTR_LENGTH) {
262 fprintf(stderr, "short read (%d)\n", r);
266 printf("recv interrupt %04x\n", *((uint16_t *) data));
270 static int sync_intr(unsigned char type)
273 unsigned char data[INTR_LENGTH];
276 r = do_sync_intr(data);
284 static int save_to_file(unsigned char *data)
289 sprintf(filename, "finger%d.pgm", img_idx++);
290 fd = fopen(filename, "w");
294 fputs("P5 384 289 255 ", fd);
295 fwrite(data + 64, 1, 384*289, fd);
297 printf("saved image to %s\n", filename);
301 static int next_state(void)
304 printf("old state: %d\n", state);
306 case STATE_AWAIT_IRQ_FINGER_REMOVED:
307 state = STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON;
308 r = set_mode_async(MODE_AWAIT_FINGER_ON);
310 case STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON:
311 state = STATE_AWAIT_IRQ_FINGER_DETECTED;
313 case STATE_AWAIT_IRQ_FINGER_DETECTED:
314 state = STATE_AWAIT_MODE_CHANGE_CAPTURE;
315 r = set_mode_async(MODE_CAPTURE);
317 case STATE_AWAIT_MODE_CHANGE_CAPTURE:
318 state = STATE_AWAIT_IMAGE;
320 case STATE_AWAIT_IMAGE:
321 state = STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF;
322 r = set_mode_async(MODE_AWAIT_FINGER_OFF);
324 case STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF:
325 state = STATE_AWAIT_IRQ_FINGER_REMOVED;
328 printf("unrecognised state %d\n", state);
331 fprintf(stderr, "error detected changing state");
335 printf("new state: %d\n", state);
339 static void cb_irq(libusb_dev_handle *_devh, libusb_urb_handle *urbh,
340 enum libusb_urb_cb_status status, unsigned char endpoint, int rqlength,
341 unsigned char *data, int actual_length, void *user_data)
343 unsigned char irqtype = data[0];
345 if (status != FP_URB_COMPLETED) {
346 fprintf(stderr, "irq URB status %d?\n", status);
351 printf("IRQ callback %02x\n", irqtype);
353 case STATE_AWAIT_IRQ_FINGER_DETECTED:
354 if (irqtype == 0x01) {
355 if (next_state() < 0) {
360 printf("finger-on-sensor detected in wrong state!\n");
363 case STATE_AWAIT_IRQ_FINGER_REMOVED:
364 if (irqtype == 0x02) {
365 if (next_state() < 0) {
370 printf("finger-on-sensor detected in wrong state!\n");
374 if (submit_irq_urb() < 0)
378 static void cb_img(libusb_dev_handle *_devh, libusb_urb_handle *urbh,
379 enum libusb_urb_cb_status status, unsigned char endpoint, int rqlength,
380 unsigned char *data, int actual_length, void *user_data)
382 if (status != FP_URB_COMPLETED) {
383 fprintf(stderr, "img URB status %d?\n", status);
388 printf("Image callback\n");
389 save_to_file(imgbuf);
390 if (next_state() < 0) {
394 if (submit_img_urb() < 0)
398 static int submit_irq_urb(void)
400 libusb_urb_handle_free(irq_urbh);
401 irq_urbh = libusb_async_interrupt_transfer(devh, &irqtrf, cb_irq, NULL, 0);
402 return irq_urbh != NULL;
405 static int submit_img_urb(void)
407 libusb_urb_handle_free(img_urbh);
408 img_urbh = libusb_async_bulk_transfer(devh, &imgtrf, cb_img, NULL, 0);
409 return img_urbh != NULL;
412 static int init_capture(void)
416 r = submit_irq_urb();
420 r = submit_img_urb();
422 libusb_urb_handle_cancel_sync(devh, img_urbh);
426 /* start state machine */
427 state = STATE_AWAIT_IRQ_FINGER_REMOVED;
431 static int do_init(void)
433 unsigned char status;
436 r = get_hwstat(&status);
440 if (!(status & 0x80)) {
441 r = set_hwstat(status | 0x80);
444 r = get_hwstat(&status);
450 r = set_hwstat(status);
454 r = get_hwstat(&status);
465 static void sighandler(int signum)
472 struct libusb_dev *dev;
473 struct sigaction sigact;
478 fprintf(stderr, "failed to initialise libusb\n");
482 dev = find_dpfp_device();
484 fprintf(stderr, "No device found\n");
487 printf("found device\n");
489 devh = libusb_open(dev);
491 fprintf(stderr, "Could not open device\n");
494 printf("opened device\n");
496 r = libusb_claim_interface(devh, 0);
498 fprintf(stderr, "usb_claim_interface error %d %s\n", r, strerror(-r));
501 printf("claimed interface\n");
511 /* async from here onwards */
517 sigact.sa_handler = sighandler;
518 sigemptyset(&sigact.sa_mask);
520 sigaction(SIGINT, &sigact, NULL);
521 sigaction(SIGTERM, &sigact, NULL);
522 sigaction(SIGQUIT, &sigact, NULL);
530 printf("shutting down...\n");
532 r = libusb_urb_handle_cancel_sync(devh, irq_urbh);
536 r = libusb_urb_handle_cancel_sync(devh, img_urbh);
546 libusb_urb_handle_free(img_urbh);
547 libusb_urb_handle_free(irq_urbh);
551 libusb_release_interface(devh, 0);
555 return r >= 0 ? r : -r;