1bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev/* 2bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * libusb example program to manipulate U.are.U 4000B fingerprint scanner. 3bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * Copyright (C) 2007 Daniel Drake <dsd@gentoo.org> 4bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * 5bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * Basic image capture program only, does not consider the powerup quirks or 6bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * the fact that image encryption may be enabled. Not expected to work 7bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * flawlessly all of the time. 8bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * 9bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * This library is free software; you can redistribute it and/or 10bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * modify it under the terms of the GNU Lesser General Public 11bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * License as published by the Free Software Foundation; either 12bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * version 2.1 of the License, or (at your option) any later version. 13bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * 14bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * This library is distributed in the hope that it will be useful, 15bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * but WITHOUT ANY WARRANTY; without even the implied warranty of 16bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * Lesser General Public License for more details. 18bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * 19bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * You should have received a copy of the GNU Lesser General Public 20bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * License along with this library; if not, write to the Free Software 21bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev */ 23bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 24bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev#include <errno.h> 25bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev#include <signal.h> 26bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev#include <string.h> 27bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev#include <stdio.h> 28bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev#include <stdlib.h> 29bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 30bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev#include <libusb/libusb.h> 31bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 32bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev#define EP_INTR (1 | LIBUSB_ENDPOINT_IN) 33bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev#define EP_DATA (2 | LIBUSB_ENDPOINT_IN) 34bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev#define CTRL_IN (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN) 35bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev#define CTRL_OUT (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT) 36bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev#define USB_RQ 0x04 37bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev#define INTR_LENGTH 64 38bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 39bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevenum { 40bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev MODE_INIT = 0x00, 41bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev MODE_AWAIT_FINGER_ON = 0x10, 42bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev MODE_AWAIT_FINGER_OFF = 0x12, 43bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev MODE_CAPTURE = 0x20, 44bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev MODE_SHUT_UP = 0x30, 45bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev MODE_READY = 0x80, 46bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev}; 47bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 48bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic int next_state(void); 49bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 50bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevenum { 51bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON = 1, 52bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev STATE_AWAIT_IRQ_FINGER_DETECTED, 53bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev STATE_AWAIT_MODE_CHANGE_CAPTURE, 54bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev STATE_AWAIT_IMAGE, 55bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF, 56bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev STATE_AWAIT_IRQ_FINGER_REMOVED, 57bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev}; 58bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 59bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic int state = 0; 60bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic struct libusb_device_handle *devh = NULL; 61bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic unsigned char imgbuf[0x1b340]; 62bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic unsigned char irqbuf[INTR_LENGTH]; 63bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic struct libusb_transfer *img_transfer = NULL; 64bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic struct libusb_transfer *irq_transfer = NULL; 65bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic int img_idx = 0; 66bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic int do_exit = 0; 67bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 68bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic int find_dpfp_device(void) 69bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev{ 70bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev devh = libusb_open_device_with_vid_pid(NULL, 0x05ba, 0x000a); 71bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return devh ? 0 : -EIO; 72bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev} 73bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 74bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic int print_f0_data(void) 75bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev{ 76bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev unsigned char data[0x10]; 77bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev int r; 78bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev unsigned int i; 79bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 80bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0xf0, 0, data, 81bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev sizeof(data), 0); 82bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) { 83bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fprintf(stderr, "F0 error %d\n", r); 84bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return r; 85bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 86bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if ((unsigned int) r < sizeof(data)) { 87bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fprintf(stderr, "short read (%d)\n", r); 88bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return -1; 89bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 90bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 91bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("F0 data:"); 92bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev for (i = 0; i < sizeof(data); i++) 93bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("%02x ", data[i]); 94bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("\n"); 95bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return 0; 96bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev} 97bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 98bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic int get_hwstat(unsigned char *status) 99bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev{ 100bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev int r; 101bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 102bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0x07, 0, status, 1, 0); 103bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) { 104bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fprintf(stderr, "read hwstat error %d\n", r); 105bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return r; 106bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 107bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if ((unsigned int) r < 1) { 108bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fprintf(stderr, "short read (%d)\n", r); 109bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return -1; 110bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 111bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 112bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("hwstat reads %02x\n", *status); 113bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return 0; 114bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev} 115bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 116bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic int set_hwstat(unsigned char data) 117bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev{ 118bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev int r; 119bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 120bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("set hwstat to %02x\n", data); 121bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = libusb_control_transfer(devh, CTRL_OUT, USB_RQ, 0x07, 0, &data, 1, 0); 122bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) { 123bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fprintf(stderr, "set hwstat error %d\n", r); 124bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return r; 125bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 126bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if ((unsigned int) r < 1) { 127bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fprintf(stderr, "short write (%d)", r); 128bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return -1; 129bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 130bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 131bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return 0; 132bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev} 133bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 134bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic int set_mode(unsigned char data) 135bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev{ 136bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev int r; 137bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("set mode %02x\n", data); 138bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 139bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = libusb_control_transfer(devh, CTRL_OUT, USB_RQ, 0x4e, 0, &data, 1, 0); 140bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) { 141bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fprintf(stderr, "set mode error %d\n", r); 142bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return r; 143bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 144bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if ((unsigned int) r < 1) { 145bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fprintf(stderr, "short write (%d)", r); 146bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return -1; 147bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 148bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 149bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return 0; 150bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev} 151bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 152bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic void cb_mode_changed(struct libusb_transfer *transfer) 153bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev{ 154bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { 155bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fprintf(stderr, "mode change transfer not completed!\n"); 156bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev do_exit = 2; 157bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 158bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 159bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("async cb_mode_changed length=%d actual_length=%d\n", 160bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev transfer->length, transfer->actual_length); 161bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (next_state() < 0) 162bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev do_exit = 2; 163bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev} 164bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 165bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic int set_mode_async(unsigned char data) 166bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev{ 167bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev unsigned char *buf = malloc(LIBUSB_CONTROL_SETUP_SIZE + 1); 168bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev struct libusb_transfer *transfer; 169bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 170bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (!buf) 171bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return -ENOMEM; 172bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 173bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev transfer = libusb_alloc_transfer(0); 174bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (!transfer) { 175bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev free(buf); 176bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return -ENOMEM; 177bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 178bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 179bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("async set mode %02x\n", data); 180bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev libusb_fill_control_setup(buf, CTRL_OUT, USB_RQ, 0x4e, 0, 1); 181bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev buf[LIBUSB_CONTROL_SETUP_SIZE] = data; 182bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev libusb_fill_control_transfer(transfer, devh, buf, cb_mode_changed, NULL, 183bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 1000); 184bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 185bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK 186bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev | LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER; 187bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return libusb_submit_transfer(transfer); 188bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev} 189bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 190bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic int do_sync_intr(unsigned char *data) 191bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev{ 192bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev int r; 193bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev int transferred; 194bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 195bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = libusb_interrupt_transfer(devh, EP_INTR, data, INTR_LENGTH, 196bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev &transferred, 1000); 197bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) { 198bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fprintf(stderr, "intr error %d\n", r); 199bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return r; 200bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 201bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (transferred < INTR_LENGTH) { 202bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fprintf(stderr, "short read (%d)\n", r); 203bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return -1; 204bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 205bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 206bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("recv interrupt %04x\n", *((uint16_t *) data)); 207bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return 0; 208bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev} 209bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 210bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic int sync_intr(unsigned char type) 211bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev{ 212bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev int r; 213bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev unsigned char data[INTR_LENGTH]; 214bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 215bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev while (1) { 216bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = do_sync_intr(data); 217bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) 218bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return r; 219bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (data[0] == type) 220bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return 0; 221bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 222bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev} 223bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 224bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic int save_to_file(unsigned char *data) 225bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev{ 226bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev FILE *fd; 227bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev char filename[64]; 228bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 229bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev sprintf(filename, "finger%d.pgm", img_idx++); 230bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fd = fopen(filename, "w"); 231bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (!fd) 232bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return -1; 233bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 234bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fputs("P5 384 289 255 ", fd); 235bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fwrite(data + 64, 1, 384*289, fd); 236bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fclose(fd); 237bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("saved image to %s\n", filename); 238bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return 0; 239bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev} 240bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 241bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic int next_state(void) 242bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev{ 243bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev int r = 0; 244bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("old state: %d\n", state); 245bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev switch (state) { 246bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev case STATE_AWAIT_IRQ_FINGER_REMOVED: 247bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev state = STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON; 248bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = set_mode_async(MODE_AWAIT_FINGER_ON); 249bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev break; 250bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev case STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON: 251bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev state = STATE_AWAIT_IRQ_FINGER_DETECTED; 252bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev break; 253bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev case STATE_AWAIT_IRQ_FINGER_DETECTED: 254bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev state = STATE_AWAIT_MODE_CHANGE_CAPTURE; 255bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = set_mode_async(MODE_CAPTURE); 256bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev break; 257bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev case STATE_AWAIT_MODE_CHANGE_CAPTURE: 258bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev state = STATE_AWAIT_IMAGE; 259bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev break; 260bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev case STATE_AWAIT_IMAGE: 261bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev state = STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF; 262bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = set_mode_async(MODE_AWAIT_FINGER_OFF); 263bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev break; 264bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev case STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF: 265bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev state = STATE_AWAIT_IRQ_FINGER_REMOVED; 266bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev break; 267bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev default: 268bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("unrecognised state %d\n", state); 269bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 270bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) { 271bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fprintf(stderr, "error detected changing state\n"); 272bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return r; 273bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 274bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 275bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("new state: %d\n", state); 276bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return 0; 277bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev} 278bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 279bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic void cb_irq(struct libusb_transfer *transfer) 280bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev{ 281bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev unsigned char irqtype = transfer->buffer[0]; 282bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 283bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { 284bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fprintf(stderr, "irq transfer status %d?\n", transfer->status); 285bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev do_exit = 2; 286bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev libusb_free_transfer(transfer); 287bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev irq_transfer = NULL; 288bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return; 289bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 290bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 291bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("IRQ callback %02x\n", irqtype); 292bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev switch (state) { 293bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev case STATE_AWAIT_IRQ_FINGER_DETECTED: 294bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (irqtype == 0x01) { 295bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (next_state() < 0) { 296bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev do_exit = 2; 297bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return; 298bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 299bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } else { 300bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("finger-on-sensor detected in wrong state!\n"); 301bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 302bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev break; 303bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev case STATE_AWAIT_IRQ_FINGER_REMOVED: 304bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (irqtype == 0x02) { 305bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (next_state() < 0) { 306bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev do_exit = 2; 307bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return; 308bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 309bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } else { 310bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("finger-on-sensor detected in wrong state!\n"); 311bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 312bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev break; 313bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 314bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (libusb_submit_transfer(irq_transfer) < 0) 315bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev do_exit = 2; 316bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev} 317bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 318bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic void cb_img(struct libusb_transfer *transfer) 319bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev{ 320bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { 321bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fprintf(stderr, "img transfer status %d?\n", transfer->status); 322bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev do_exit = 2; 323bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev libusb_free_transfer(transfer); 324bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev img_transfer = NULL; 325bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return; 326bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 327bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 328bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("Image callback\n"); 329bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev save_to_file(imgbuf); 330bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (next_state() < 0) { 331bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev do_exit = 2; 332bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return; 333bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 334bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (libusb_submit_transfer(img_transfer) < 0) 335bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev do_exit = 2; 336bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev} 337bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 338bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic int init_capture(void) 339bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev{ 340bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev int r; 341bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 342bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = libusb_submit_transfer(irq_transfer); 343bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) 344bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return r; 345bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 346bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = libusb_submit_transfer(img_transfer); 347bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) { 348bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev libusb_cancel_transfer(irq_transfer); 349bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev while (irq_transfer) 350bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (libusb_handle_events(NULL) < 0) 351bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev break; 352bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return r; 353bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 354bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 355bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev /* start state machine */ 356bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev state = STATE_AWAIT_IRQ_FINGER_REMOVED; 357bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return next_state(); 358bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev} 359bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 360bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic int do_init(void) 361bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev{ 362bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev unsigned char status; 363bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev int r; 364bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 365bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = get_hwstat(&status); 366bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) 367bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return r; 368bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 369bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (!(status & 0x80)) { 370bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = set_hwstat(status | 0x80); 371bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) 372bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return r; 373bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = get_hwstat(&status); 374bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) 375bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return r; 376bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 377bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 378bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev status &= ~0x80; 379bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = set_hwstat(status); 380bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) 381bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return r; 382bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 383bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = get_hwstat(&status); 384bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) 385bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return r; 386bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 387bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = sync_intr(0x56); 388bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) 389bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return r; 390bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 391bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return 0; 392bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev} 393bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 394bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic int alloc_transfers(void) 395bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev{ 396bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev img_transfer = libusb_alloc_transfer(0); 397bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (!img_transfer) 398bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return -ENOMEM; 399bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 400bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev irq_transfer = libusb_alloc_transfer(0); 401bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (!irq_transfer) 402bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return -ENOMEM; 403bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 404bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev libusb_fill_bulk_transfer(img_transfer, devh, EP_DATA, imgbuf, 405bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev sizeof(imgbuf), cb_img, NULL, 0); 406bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev libusb_fill_interrupt_transfer(irq_transfer, devh, EP_INTR, irqbuf, 407bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev sizeof(irqbuf), cb_irq, NULL, 0); 408bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 409bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return 0; 410bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev} 411bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 412bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevstatic void sighandler(int signum) 413bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev{ 414bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev do_exit = 1; 415bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev} 416bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 417bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevint main(void) 418bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev{ 419bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev struct sigaction sigact; 420bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev int r = 1; 421bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 422bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = libusb_init(NULL); 423bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) { 424bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fprintf(stderr, "failed to initialise libusb\n"); 425bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev exit(1); 426bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 427bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 428bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = find_dpfp_device(); 429bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) { 430bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fprintf(stderr, "Could not find/open device\n"); 431bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev goto out; 432bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 433bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 434bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = libusb_claim_interface(devh, 0); 435bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) { 436bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev fprintf(stderr, "usb_claim_interface error %d\n", r); 437bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev goto out; 438bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 439bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("claimed interface\n"); 440bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 441bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = print_f0_data(); 442bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) 443bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev goto out_release; 444bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 445bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = do_init(); 446bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) 447bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev goto out_deinit; 448bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 449bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev /* async from here onwards */ 450bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 451bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = alloc_transfers(); 452bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) 453bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev goto out_deinit; 454bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 455bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = init_capture(); 456bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) 457bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev goto out_deinit; 458bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 459bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev sigact.sa_handler = sighandler; 460bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev sigemptyset(&sigact.sa_mask); 461bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev sigact.sa_flags = 0; 462bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev sigaction(SIGINT, &sigact, NULL); 463bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev sigaction(SIGTERM, &sigact, NULL); 464bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev sigaction(SIGQUIT, &sigact, NULL); 465bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 466bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev while (!do_exit) { 467bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = libusb_handle_events(NULL); 468bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) 469bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev goto out_deinit; 470bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 471bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 472bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev printf("shutting down...\n"); 473bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 474bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (irq_transfer) { 475bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = libusb_cancel_transfer(irq_transfer); 476bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) 477bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev goto out_deinit; 478bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 479bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 480bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (img_transfer) { 481bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = libusb_cancel_transfer(img_transfer); 482bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (r < 0) 483bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev goto out_deinit; 484bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev } 485bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 486bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev while (irq_transfer || img_transfer) 487bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (libusb_handle_events(NULL) < 0) 488bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev break; 489bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 490bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev if (do_exit == 1) 491bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = 0; 492bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev else 493bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev r = 1; 494bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 495bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevout_deinit: 496bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev libusb_free_transfer(img_transfer); 497bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev libusb_free_transfer(irq_transfer); 498bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev set_mode(0); 499bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev set_hwstat(0x80); 500bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevout_release: 501bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev libusb_release_interface(devh, 0); 502bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishevout: 503bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev libusb_close(devh); 504bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev libusb_exit(NULL); 505bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev return r >= 0 ? r : -r; 506bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev} 507bda86ae8203fd360c4e87c310498da1e1e4c53a7Yavor Goulishev 508