Update for libusb API rework

This commit is contained in:
Daniel Drake 2008-03-10 11:35:58 +00:00
parent 81a5d6d966
commit 4e884807a7
9 changed files with 601 additions and 489 deletions

View file

@ -46,22 +46,19 @@ static void continue_write_regv(struct write_regv_data *wdata);
/* libusb bulk callback for regv write completion transfer. continues the
* transaction */
static void write_regv_trf_complete(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 write_regv_trf_complete(struct libusb_transfer *transfer)
{
struct write_regv_data *wdata = user_data;
struct write_regv_data *wdata = transfer->user_data;
g_free(data);
libusb_urb_handle_free(urbh);
if (status != FP_URB_COMPLETED)
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
wdata->callback(wdata->imgdev, -EIO, wdata->user_data);
else if (rqlength != actual_length)
else if (transfer->length != transfer->actual_length)
wdata->callback(wdata->imgdev, -EPROTO, wdata->user_data);
else
continue_write_regv(wdata);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
}
/* write from wdata->offset to upper_bound (inclusive) of wdata->regs */
@ -73,12 +70,13 @@ static int do_write_regv(struct write_regv_data *wdata, int upper_bound)
unsigned char *data = g_malloc(alloc_size);
unsigned int i;
size_t data_offset = 0;
struct libusb_urb_handle *urbh;
struct libusb_bulk_transfer msg = {
.endpoint = EP_OUT,
.data = data,
.length = alloc_size,
};
struct libusb_transfer *transfer = libusb_alloc_transfer();
int r;
if (!transfer) {
g_free(data);
return -ENOMEM;
}
for (i = offset; i < offset + num; i++) {
const struct aes_regwrite *regwrite = &wdata->regs[i];
@ -86,14 +84,15 @@ static int do_write_regv(struct write_regv_data *wdata, int upper_bound)
data[data_offset++] = regwrite->value;
}
urbh = libusb_async_bulk_transfer(wdata->imgdev->udev, &msg,
write_regv_trf_complete, wdata, BULK_TIMEOUT);
if (!urbh) {
libusb_fill_bulk_transfer(transfer, wdata->imgdev->udev, EP_OUT, data,
alloc_size, write_regv_trf_complete, wdata, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
return -EIO;
libusb_free_transfer(transfer);
}
return 0;
return r;
}
/* write the next batch of registers to be written, or if there are no more,

View file

@ -41,7 +41,7 @@ API_EXPORTED int fp_async_dev_open(struct fp_dscv_dev *ddev, fp_dev_open_cb cb,
{
struct fp_driver *drv = ddev->drv;
struct fp_dev *dev;
libusb_dev_handle *udevh;
libusb_device_handle *udevh;
int r;
fp_dbg("");

View file

@ -352,11 +352,11 @@ static void register_drivers(void)
}
}
static struct fp_driver *find_supporting_driver(libusb_dev *udev,
static struct fp_driver *find_supporting_driver(libusb_device *udev,
const struct usb_id **usb_id)
{
GSList *elem = registered_drivers;
struct libusb_dev_descriptor *dsc = libusb_dev_get_descriptor(udev);
struct libusb_device_descriptor *dsc = libusb_get_device_descriptor(udev);
do {
struct fp_driver *drv = elem->data;
@ -373,7 +373,7 @@ static struct fp_driver *find_supporting_driver(libusb_dev *udev,
return NULL;
}
static struct fp_dscv_dev *discover_dev(libusb_dev *udev)
static struct fp_dscv_dev *discover_dev(libusb_device *udev)
{
const struct usb_id *usb_id;
struct fp_driver *drv = find_supporting_driver(udev, &usb_id);
@ -409,20 +409,27 @@ API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
{
GSList *tmplist = NULL;
struct fp_dscv_dev **list;
struct libusb_dev *udev;
libusb_device *udev;
libusb_device **devs;
int dscv_count = 0;
int r;
int i = 0;
if (registered_drivers == NULL)
return NULL;
libusb_find_devices();
r = libusb_get_device_list(&devs);
if (r < 0) {
fp_err("couldn't enumerate USB devices, error %d", r);
return NULL;
}
/* Check each device against each driver, temporarily storing successfully
* discovered devices in a GSList.
*
* Quite inefficient but excusable as we'll only be dealing with small
* sets of drivers against small sets of USB devices */
for (udev = libusb_get_devices(); udev; udev = libusb_dev_next(udev)) {
while ((udev = devs[i++]) != NULL) {
struct fp_dscv_dev *ddev = discover_dev(udev);
if (!ddev)
continue;
@ -435,7 +442,7 @@ API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
list = g_malloc(sizeof(*list) * (dscv_count + 1));
if (dscv_count > 0) {
GSList *elem = tmplist;
int i = 0;
i = 0;
do {
list[i++] = elem->data;
} while ((elem = g_slist_next(elem)));

View file

@ -79,48 +79,53 @@ struct aes2501_read_regs {
void *user_data;
};
static void read_regs_data_cb(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 read_regs_data_cb(struct libusb_transfer *transfer)
{
struct aes2501_read_regs *rdata = user_data;
struct aes2501_read_regs *rdata = transfer->user_data;
unsigned char *retdata = NULL;
int r;
if (status != FP_URB_COMPLETED) {
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
r = -EIO;
} else if (rqlength != actual_length) {
} else if (transfer->length != transfer->actual_length) {
r = -EPROTO;
} else {
r = 0;
retdata = data;
retdata = transfer->buffer;
}
rdata->callback(rdata->dev, r, retdata, rdata->user_data);
libusb_urb_handle_free(urbh);
g_free(data);
g_free(rdata);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
}
static void read_regs_rq_cb(struct fp_img_dev *dev, int result, void *user_data)
{
struct aes2501_read_regs *rdata = user_data;
struct libusb_urb_handle *urbh;
struct libusb_bulk_transfer trf = {
.endpoint = EP_IN,
.length = 126,
};
struct libusb_transfer *transfer;
unsigned char *data;
int r;
g_free(rdata->regwrite);
if (result != 0)
goto err;
trf.data = g_malloc(trf.length);
urbh = libusb_async_bulk_transfer(dev->udev, &trf, read_regs_data_cb,
rdata, BULK_TIMEOUT);
if (!urbh) {
g_free(trf.data);
result = EIO;
transfer = libusb_alloc_transfer();
if (!transfer) {
result = -ENOMEM;
goto err;
}
data = g_malloc(126);
libusb_fill_bulk_transfer(transfer, dev->udev, EP_IN, data, 126,
read_regs_data_cb, rdata, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
result = -EIO;
goto err;
}
@ -179,40 +184,43 @@ static void generic_write_regv_cb(struct fp_img_dev *dev, int result,
}
/* check that read succeeded but ignore all data */
static void generic_ignore_data_cb(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 generic_ignore_data_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = user_data;
struct fpi_ssm *ssm = transfer->user_data;
libusb_urb_handle_free(urbh);
g_free(data);
if (status != FP_URB_COMPLETED)
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_aborted(ssm, -EIO);
else if (rqlength != actual_length)
else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_aborted(ssm, -EPROTO);
else
fpi_ssm_next_state(ssm);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
}
/* read the specified number of bytes from the IN endpoint but throw them
* away, then increment the SSM */
static void generic_read_ignore_data(struct fpi_ssm *ssm, size_t bytes)
{
struct libusb_urb_handle *urbh;
struct libusb_bulk_transfer trf = {
.endpoint = EP_IN,
.data = g_malloc(bytes),
.length = bytes,
};
struct libusb_transfer *transfer = libusb_alloc_transfer();
unsigned char *data;
int r;
urbh = libusb_async_bulk_transfer(ssm->dev->udev, &trf,
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
data = g_malloc(bytes);
libusb_fill_bulk_transfer(transfer, ssm->dev->udev, EP_IN, data, bytes,
generic_ignore_data_cb, ssm, BULK_TIMEOUT);
if (!urbh) {
g_free(trf.data);
fpi_ssm_mark_aborted(ssm, -EIO);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
}
}
@ -382,19 +390,17 @@ static const struct aes_regwrite finger_det_reqs[] = {
static void start_finger_detection(struct fp_img_dev *dev);
static void finger_det_data_cb(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 finger_det_data_cb(struct libusb_transfer *transfer)
{
struct fp_img_dev *dev = user_data;
struct fp_img_dev *dev = transfer->user_data;
unsigned char *data = transfer->buffer;
int i;
int sum = 0;
libusb_urb_handle_free(urbh);
if (status != FP_URB_COMPLETED) {
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_imgdev_session_error(dev, -EIO);
goto out;
} else if (rqlength != actual_length) {
} else if (transfer->length != transfer->actual_length) {
fpi_imgdev_session_error(dev, -EPROTO);
goto out;
}
@ -413,28 +419,36 @@ static void finger_det_data_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
out:
g_free(data);
libusb_free_transfer(transfer);
}
static void finger_det_reqs_cb(struct fp_img_dev *dev, int result,
void *user_data)
{
struct libusb_urb_handle *urbh;
struct libusb_bulk_transfer trf = {
.endpoint = EP_IN,
.length = 20,
};
struct libusb_transfer *transfer;
unsigned char *data;
int r;
if (result) {
fpi_imgdev_session_error(dev, result);
return;
}
trf.data = g_malloc(trf.length);
urbh = libusb_async_bulk_transfer(dev->udev, &trf, finger_det_data_cb,
dev, BULK_TIMEOUT);
if (!urbh) {
g_free(trf.data);
fpi_imgdev_session_error(dev, -EIO);
transfer = libusb_alloc_transfer();
if (!transfer) {
fpi_imgdev_session_error(dev, -ENOMEM);
return;
}
data = g_malloc(20);
libusb_fill_bulk_transfer(transfer, dev->udev, EP_IN, data, 20,
finger_det_data_cb, dev, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_imgdev_session_error(dev, r);
}
}
@ -527,23 +541,20 @@ enum capture_states {
CAPTURE_NUM_STATES,
};
static void capture_read_strip_cb(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 capture_read_strip_cb(struct libusb_transfer *transfer)
{
unsigned char *stripdata;
struct fpi_ssm *ssm = user_data;
struct fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = ssm->priv;
struct aes2501_dev *aesdev = dev->priv;
unsigned char *data = transfer->buffer;
int sum;
int threshold;
libusb_urb_handle_free(urbh);
if (status != FP_URB_COMPLETED) {
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
} else if (rqlength != actual_length) {
} else if (transfer->length != transfer->actual_length) {
fpi_ssm_mark_aborted(ssm, -EPROTO);
goto out;
}
@ -587,12 +598,14 @@ static void capture_read_strip_cb(libusb_dev_handle *devh,
out:
g_free(data);
libusb_free_transfer(transfer);
}
static void capture_run_state(struct fpi_ssm *ssm)
{
struct fp_img_dev *dev = ssm->priv;
struct aes2501_dev *aesdev = dev->priv;
int r;
switch (ssm->cur_state) {
case CAPTURE_WRITE_REQS_1:
@ -617,17 +630,23 @@ static void capture_run_state(struct fpi_ssm *ssm)
generic_write_regv_cb, ssm);
break;
case CAPTURE_READ_STRIP: ;
struct libusb_urb_handle *urbh;
struct libusb_bulk_transfer trf = {
.endpoint = EP_IN,
.data = g_malloc(1705),
.length = 1705,
};
urbh = libusb_async_bulk_transfer(dev->udev, &trf,
struct libusb_transfer *transfer = libusb_alloc_transfer();
unsigned char *data;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
data = g_malloc(1705);
libusb_fill_bulk_transfer(transfer, dev->udev, EP_IN, data, 1705,
capture_read_strip_cb, ssm, BULK_TIMEOUT);
if (!urbh) {
g_free(trf.data);
fpi_ssm_mark_aborted(ssm, -EIO);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
}
break;
};

View file

@ -35,7 +35,7 @@
#define SUBARRAY_LEN 768
struct aes4k_dev {
libusb_urb_handle *img_trf;
struct libusb_transfer *img_trf;
};
static const struct aes_regwrite init_reqs[] = {
@ -115,22 +115,20 @@ static const struct aes_regwrite init_reqs[] = {
static void do_capture(struct fp_img_dev *dev);
static void img_cb(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 img_cb(struct libusb_transfer *transfer)
{
struct fp_img_dev *dev = user_data;
struct fp_img_dev *dev = transfer->user_data;
struct aes4k_dev *aesdev = dev->priv;
unsigned char *ptr = data;
unsigned char *ptr = transfer->buffer;
struct fp_img *img;
int i;
if (status == FP_URB_CANCELLED) {
if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
goto err;
} else if (status != FP_URB_COMPLETED) {
} else if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_imgdev_session_error(dev, -EIO);
goto err;
} else if (rqlength != actual_length) {
} else if (transfer->length != transfer->actual_length) {
fpi_imgdev_session_error(dev, -EPROTO);
goto err;
}
@ -155,25 +153,33 @@ static void img_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
do_capture(dev);
err:
g_free(data);
g_free(transfer->buffer);
aesdev->img_trf = NULL;
libusb_urb_handle_free(urbh);
libusb_free_transfer(transfer);
}
static void do_capture(struct fp_img_dev *dev)
{
struct aes4k_dev *aesdev = dev->priv;
struct libusb_bulk_transfer trf = {
.endpoint = EP_IN,
.length = DATA_BUFLEN,
.data = g_malloc(DATA_BUFLEN),
};
unsigned char *data;
int r;
aesdev->img_trf = libusb_async_bulk_transfer(dev->udev, &trf, img_cb, dev,
0);
aesdev->img_trf = libusb_alloc_transfer();
if (!aesdev->img_trf) {
g_free(trf.data);
fpi_imgdev_session_error(dev, -EIO);
return;
}
data = g_malloc(DATA_BUFLEN);
libusb_fill_bulk_transfer(aesdev->img_trf, dev->udev, EP_IN, data,
DATA_BUFLEN, img_cb, dev, 0);
r = libusb_submit_transfer(aesdev->img_trf);
if (r < 0) {
g_free(data);
libusb_free_transfer(aesdev->img_trf);
aesdev->img_trf = NULL;
fpi_imgdev_session_error(dev, r);
}
}
@ -198,7 +204,7 @@ static void dev_deactivate(struct fp_img_dev *dev)
* from deactivation, otherwise app may legally exit before we've
* cleaned up */
if (aesdev->img_trf)
libusb_urb_handle_cancel(dev->udev, aesdev->img_trf);
libusb_cancel_transfer(aesdev->img_trf);
fpi_imgdev_deactivate_complete(dev);
}

View file

@ -133,10 +133,11 @@ static uint16_t udf_crc(unsigned char *buffer, size_t size)
#define CMD_SEQ_INCREMENT 0x10
static void fill_send_cmd_urb(struct libusb_bulk_transfer *msg,
static struct libusb_transfer *alloc_send_cmd_transfer(struct fp_dev *dev,
unsigned char seq_a, unsigned char seq_b, const unsigned char *data,
uint16_t len)
uint16_t len, libusb_transfer_cb_fn callback, void *user_data)
{
struct libusb_transfer *transfer = libusb_alloc_transfer();
uint16_t crc;
/* 9 bytes extra for: 4 byte 'Ciao', 1 byte A, 1 byte B | lenHI,
@ -144,15 +145,15 @@ static void fill_send_cmd_urb(struct libusb_bulk_transfer *msg,
size_t urblen = len + 9;
unsigned char *buf;
if (!transfer)
return NULL;
if (!data && len > 0) {
fp_err("len>0 but no data?");
return;
return NULL;
}
msg->endpoint = EP_OUT;
msg->length = urblen;
buf = g_malloc(urblen);
msg->data = buf;
/* Write header */
strncpy(buf, "Ciao", 4);
@ -169,17 +170,22 @@ static void fill_send_cmd_urb(struct libusb_bulk_transfer *msg,
crc = GUINT16_TO_BE(udf_crc(buf + 4, urblen - 6));
buf[urblen - 2] = crc >> 8;
buf[urblen - 1] = crc & 0xff;
libusb_fill_bulk_transfer(transfer, dev->udev, EP_OUT, buf, urblen,
callback, user_data, TIMEOUT);
return transfer;
}
static void fill_send_cmd28_urb(struct fp_dev *dev,
struct libusb_bulk_transfer *msg, unsigned char subcmd,
const unsigned char *data, uint16_t innerlen)
static struct libusb_transfer *alloc_send_cmd28_transfer(struct fp_dev *dev,
unsigned char subcmd, const unsigned char *data, uint16_t innerlen,
libusb_transfer_cb_fn callback, void *user_data)
{
uint16_t _innerlen = innerlen;
size_t len = innerlen + 6;
unsigned char *buf = g_malloc0(len);
struct upekts_dev *upekdev = dev->priv;
uint8_t seq = upekdev->seq + CMD_SEQ_INCREMENT;
struct libusb_transfer *ret;
fp_dbg("seq=%02x subcmd=%02x with %d bytes of data", seq, subcmd, innerlen);
@ -190,17 +196,19 @@ static void fill_send_cmd28_urb(struct fp_dev *dev,
buf[5] = subcmd;
memcpy(buf + 6, data, innerlen);
fill_send_cmd_urb(msg, 0, seq, buf, len);
ret = alloc_send_cmd_transfer(dev, 0, seq, buf, len, callback, user_data);
upekdev->seq = seq;
g_free(buf);
return ret;
}
static void fill_send_cmdresponse_urb(struct libusb_bulk_transfer *msg,
unsigned char seq, const unsigned char *data, uint8_t len)
static struct libusb_transfer *alloc_send_cmdresponse_transfer(
struct fp_dev *dev, unsigned char seq, const unsigned char *data,
uint8_t len, libusb_transfer_cb_fn callback, void *user_data)
{
fp_dbg("seq=%02x len=%d", seq, len);
fill_send_cmd_urb(msg, seq, 0, data, len);
return alloc_send_cmd_transfer(dev, seq, 0, data, len, callback, user_data);
}
enum read_msg_status {
@ -224,12 +232,12 @@ static int __read_msg_async(struct read_msg_data *udata);
#define READ_MSG_DATA_CB_ERR(udata) (udata)->callback((udata)->dev, \
READ_MSG_ERROR, 0, 0, NULL, 0, (udata)->user_data)
static void busy_ack_sent_cb(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 *_data)
static void busy_ack_sent_cb(struct libusb_transfer *transfer)
{
struct read_msg_data *udata = (struct read_msg_data *) _data;
if (status != FP_URB_COMPLETED || rqlength != actual_length) {
struct read_msg_data *udata = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED ||
transfer->length != transfer->actual_length) {
READ_MSG_DATA_CB_ERR(udata);
g_free(udata);
} else {
@ -239,22 +247,25 @@ static void busy_ack_sent_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
g_free(udata);
}
}
libusb_urb_handle_free(urbh);
libusb_free_transfer(transfer);
}
static int busy_ack_retry_read(struct read_msg_data *udata)
{
struct libusb_bulk_transfer msg;
libusb_urb_handle *urbh;
struct libusb_transfer *transfer;
int r;
fill_send_cmdresponse_urb(&msg, 0x09, NULL, 0);
urbh = libusb_async_bulk_transfer(udata->dev->udev, &msg, busy_ack_sent_cb,
udata, TIMEOUT);
if (!urbh) {
g_free(msg.data);
return -EIO;
transfer = alloc_send_cmdresponse_transfer(udata->dev, 0x09, NULL, 0,
busy_ack_sent_cb, udata);
if (!transfer)
return -ENOMEM;
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(transfer->buffer);
libusb_free_transfer(transfer);
}
return 0;
return r;
}
/* Returns 0 if message was handled, 1 if it was a device-busy message, and
@ -333,20 +344,19 @@ static int __handle_incoming_msg(struct read_msg_data *udata,
return 0;
}
static void read_msg_extend_cb(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 read_msg_extend_cb(struct libusb_transfer *transfer)
{
struct read_msg_data *udata = user_data;
unsigned char *buf = data - MSG_READ_BUF_SIZE;
struct read_msg_data *udata = transfer->user_data;
unsigned char *buf = transfer->buffer - MSG_READ_BUF_SIZE;
int handle_result = 0;
if (status != FP_URB_COMPLETED) {
fp_err("extended msg read failed, code %d", status);
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fp_err("extended msg read failed, code %d", transfer->status);
goto err;
}
if (actual_length < rqlength) {
fp_err("extended msg short read (%d/%d)", actual_length, rqlength);
if (transfer->actual_length < transfer->length) {
fp_err("extended msg short read (%d/%d)", transfer->actual_length,
transfer->length);
goto err;
}
@ -361,23 +371,22 @@ out:
if (handle_result != 1)
g_free(udata);
g_free(buf);
libusb_urb_handle_free(urbh);
libusb_free_transfer(transfer);
}
static void read_msg_cb(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 read_msg_cb(struct libusb_transfer *transfer)
{
struct read_msg_data *udata = user_data;
struct read_msg_data *udata = transfer->user_data;
unsigned char *data = transfer->buffer;
uint16_t len;
int handle_result = 0;
if (status != FP_URB_COMPLETED) {
fp_err("async msg read failed, code %d", status);
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fp_err("async msg read failed, code %d", transfer->status);
goto err;
}
if (actual_length < 9) {
fp_err("async msg read too short (%d)", actual_length);
if (transfer->actual_length < 9) {
fp_err("async msg read too short (%d)", transfer->actual_length);
goto err;
}
@ -387,11 +396,12 @@ static void read_msg_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
}
len = GUINT16_FROM_LE(((data[5] & 0xf) << 8) | data[6]);
if (actual_length != MSG_READ_BUF_SIZE && (len + 9) > actual_length) {
if (transfer->actual_length != MSG_READ_BUF_SIZE
&& (len + 9) > transfer->actual_length) {
/* Check that the length claimed inside the message is in line with
* the amount of data that was transferred over USB. */
fp_err("msg didn't include enough data, expected=%d recv=%d",
len + 9, actual_length);
len + 9, transfer->actual_length);
goto err;
}
@ -400,22 +410,26 @@ static void read_msg_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
* to read the remainder. This is handled below. */
if (len > MAX_DATA_IN_READ_BUF) {
int needed = len - MAX_DATA_IN_READ_BUF;
libusb_urb_handle *eurbh;
struct libusb_bulk_transfer extend_msg = {
.endpoint = EP_IN,
.length = needed,
};
struct libusb_transfer *etransfer = libusb_alloc_transfer();
int r;
if (!transfer)
goto err;
fp_dbg("didn't fit in buffer, need to extend by %d bytes", needed);
data = g_realloc((gpointer) data, MSG_READ_BUF_SIZE + needed);
extend_msg.data = data + MSG_READ_BUF_SIZE;
eurbh = libusb_async_bulk_transfer(udata->dev->udev, &extend_msg,
read_msg_extend_cb, udata, TIMEOUT);
if (!eurbh) {
libusb_fill_bulk_transfer(etransfer, udata->dev->udev, EP_IN,
data + MSG_READ_BUF_SIZE, needed, read_msg_extend_cb, udata,
TIMEOUT);
r = libusb_submit_transfer(etransfer);
if (r < 0) {
fp_err("extended read submission failed");
/* FIXME memory leak here? */
goto err;
}
libusb_urb_handle_free(urbh);
libusb_free_transfer(transfer);
return;
}
@ -427,7 +441,7 @@ static void read_msg_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
err:
READ_MSG_DATA_CB_ERR(udata);
out:
libusb_urb_handle_free(urbh);
libusb_free_transfer(transfer);
if (handle_result != 1)
g_free(udata);
g_free(data);
@ -436,18 +450,23 @@ out:
static int __read_msg_async(struct read_msg_data *udata)
{
unsigned char *buf = g_malloc(MSG_READ_BUF_SIZE);
struct libusb_bulk_transfer msg = {
.endpoint = EP_IN,
.data = buf,
.length = MSG_READ_BUF_SIZE,
};
libusb_urb_handle *urbh = libusb_async_bulk_transfer(udata->dev->udev, &msg,
read_msg_cb, udata, TIMEOUT);
if (!urbh) {
struct libusb_transfer *transfer = libusb_alloc_transfer();
int r;
if (!transfer) {
g_free(buf);
return -EIO;
return -ENOMEM;
}
return 0;
libusb_fill_bulk_transfer(transfer, udata->dev->udev, EP_IN, buf,
MSG_READ_BUF_SIZE, read_msg_cb, udata, TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(buf);
libusb_free_transfer(transfer);
}
return r;
}
static int read_msg_async(struct fp_dev *dev, read_msg_cb_fn callback,
@ -613,16 +632,16 @@ static void read_msg03_cb(struct fp_dev *dev, enum read_msg_status status,
initsm_read_msg_cmd_cb((struct fpi_ssm *) user_data, status, 3, seq);
}
static void ctrl400_cb(libusb_dev_handle *devh, 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 ctrl400_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = user_data;
if (status == FP_URB_COMPLETED)
struct fpi_ssm *ssm = transfer->user_data;
/* FIXME check length? */
if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_next_state(ssm);
else
fpi_ssm_mark_aborted(ssm, -1);
libusb_urb_handle_free(urbh);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
}
static void initsm_read_msg_handler(struct fpi_ssm *ssm,
@ -635,35 +654,40 @@ static void initsm_read_msg_handler(struct fpi_ssm *ssm,
}
}
static void initsm_send_msg_cb(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 initsm_send_msg_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = user_data;
if (status == FP_URB_COMPLETED && rqlength == actual_length) {
struct fpi_ssm *ssm = transfer->user_data;
if (transfer->status == LIBUSB_TRANSFER_COMPLETED
&& transfer->length == transfer->actual_length) {
fp_dbg("state %d completed", ssm->cur_state);
fpi_ssm_next_state(ssm);
} else {
fp_err("failed, state=%d rqlength=%d actual_length=%d", ssm->cur_state,
rqlength, actual_length);
transfer->length, transfer->actual_length);
fpi_ssm_mark_aborted(ssm, -1);
}
libusb_urb_handle_free(urbh);
libusb_free_transfer(transfer);
}
static void initsm_send_msg28_handler(struct fpi_ssm *ssm,
unsigned char subcmd, const unsigned char *data, uint16_t innerlen)
{
struct fp_dev *dev = ssm->dev;
struct libusb_urb_handle *urbh;
struct libusb_bulk_transfer trf;
struct libusb_transfer *transfer;
int r;
fill_send_cmd28_urb(dev, &trf, subcmd, data, innerlen);
urbh = libusb_async_bulk_transfer(dev->udev, &trf, initsm_send_msg_cb,
ssm, TIMEOUT);
if (!urbh) {
fp_err("urb submission failed in state %d", ssm->cur_state);
g_free(trf.data);
transfer = alloc_send_cmd28_transfer(dev, subcmd, data, innerlen,
initsm_send_msg_cb, ssm);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
r = libusb_submit_transfer(transfer);
if (r < 0) {
fp_err("urb submission failed error %d in state %d", r, ssm->cur_state);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, -EIO);
}
}
@ -672,38 +696,48 @@ static void initsm_run_state(struct fpi_ssm *ssm)
{
struct fp_dev *dev = ssm->dev;
struct upekts_dev *upekdev = dev->priv;
struct libusb_urb_handle *urbh;
struct libusb_transfer *transfer;
int r;
switch (ssm->cur_state) {
case WRITE_CTRL400: ;
unsigned char dummy = 0x10;
struct libusb_control_transfer ctrl400_trf = {
.requesttype = LIBUSB_TYPE_VENDOR | LIBUSB_RECIP_DEVICE,
.request = 0x0c,
.value = 0x0100,
.index = 0x0400,
.length = sizeof(dummy),
.data = &dummy,
};
unsigned char *data;
urbh = libusb_async_control_transfer(ssm->dev->udev, &ctrl400_trf,
transfer = libusb_alloc_transfer();
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
libusb_fill_control_setup(data,
LIBUSB_TYPE_VENDOR | LIBUSB_RECIP_DEVICE, 0x0c, 0x100, 0x0400, 1);
libusb_fill_control_transfer(transfer, ssm->dev->udev, data,
ctrl400_cb, ssm, TIMEOUT);
if (!urbh)
fpi_ssm_mark_aborted(ssm, -1);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
}
break;
case READ_MSG03:
initsm_read_msg_handler(ssm, read_msg03_cb);
break;
case SEND_RESP03: ;
struct libusb_bulk_transfer resp03_trf;
transfer = alloc_send_cmdresponse_transfer(dev, ++upekdev->seq,
init_resp03, sizeof(init_resp03), initsm_send_msg_cb, ssm);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
fill_send_cmdresponse_urb(&resp03_trf, ++upekdev->seq, init_resp03,
sizeof(init_resp03));
urbh = libusb_async_bulk_transfer(dev->udev, &resp03_trf,
initsm_send_msg_cb, ssm, TIMEOUT);
if (!urbh) {
g_free(resp03_trf.data);
fpi_ssm_mark_aborted(ssm, -EIO);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(transfer->buffer);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
}
break;
case READ_MSG05:
@ -756,18 +790,16 @@ enum deinitsm_states {
DEINITSM_NUM_STATES,
};
static void send_resp07_cb(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 send_resp07_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = user_data;
if (status != FP_URB_COMPLETED)
struct fpi_ssm *ssm = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_aborted(ssm, -EIO);
else if (rqlength != actual_length)
else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_aborted(ssm, -EPROTO);
else
fpi_ssm_next_state(ssm);
libusb_urb_handle_free(urbh);
libusb_free_transfer(transfer);
}
static void read_msg01_cb(struct fp_dev *dev, enum read_msg_status status,
@ -798,23 +830,29 @@ static void read_msg01_cb(struct fp_dev *dev, enum read_msg_status status,
static void deinitsm_state_handler(struct fpi_ssm *ssm)
{
struct fp_dev *dev = ssm->dev;
int r;
switch (ssm->cur_state) {
case SEND_RESP07: ;
struct libusb_bulk_transfer msg;
struct libusb_urb_handle *urbh;
struct libusb_transfer *transfer;
unsigned char dummy = 0;
fill_send_cmdresponse_urb(&msg, 0x07, &dummy, 1);
urbh = libusb_async_bulk_transfer(dev->udev, &msg, send_resp07_cb, ssm,
TIMEOUT);
if (!urbh) {
g_free(msg.data);
fpi_ssm_mark_aborted(ssm, -EIO);
transfer = alloc_send_cmdresponse_transfer(dev, 0x07, &dummy, 1,
send_resp07_cb, ssm);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(transfer->buffer);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
}
break;
case READ_MSG01: ;
int r = read_msg_async(dev, read_msg01_cb, ssm);
r = read_msg_async(dev, read_msg01_cb, ssm);
if (r < 0)
fpi_ssm_mark_aborted(ssm, r);
break;
@ -882,19 +920,16 @@ static void enroll_start_sm_cb_initsm(struct fpi_ssm *initsm)
}
/* called when enroll init URB has completed */
static void enroll_start_sm_cb_init(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 enroll_start_sm_cb_init(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = user_data;
if (status != FP_URB_COMPLETED)
struct fpi_ssm *ssm = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_aborted(ssm, -EIO);
else if (rqlength != actual_length)
else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_aborted(ssm, -EPROTO);
else
fpi_ssm_next_state(ssm);
libusb_urb_handle_free(urbh);
libusb_free_transfer(transfer);
}
static void enroll_start_sm_cb_msg28(struct fp_dev *dev,
@ -923,6 +958,7 @@ static void enroll_start_sm_cb_msg28(struct fp_dev *dev,
static void enroll_start_sm_run_state(struct fpi_ssm *ssm)
{
struct fp_dev *dev = ssm->dev;
int r;
switch (ssm->cur_state) {
case RUN_INITSM: ;
@ -931,14 +967,19 @@ static void enroll_start_sm_run_state(struct fpi_ssm *ssm)
fpi_ssm_start(initsm, enroll_start_sm_cb_initsm);
break;
case ENROLL_INIT: ;
struct libusb_bulk_transfer msg;
struct libusb_urb_handle *urbh;
fill_send_cmd28_urb(dev, &msg, 0x02, enroll_init, sizeof(enroll_init));
urbh = libusb_async_bulk_transfer(dev->udev, &msg,
enroll_start_sm_cb_init, ssm, TIMEOUT);
if (!urbh) {
g_free(msg.data);
fpi_ssm_mark_aborted(ssm, -EIO);
struct libusb_transfer *transfer;
transfer = alloc_send_cmd28_transfer(dev, 0x02, enroll_init,
sizeof(enroll_init), enroll_start_sm_cb_init, ssm);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(transfer->buffer);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
}
break;
case READ_ENROLL_MSG28: ;
@ -946,7 +987,7 @@ static void enroll_start_sm_run_state(struct fpi_ssm *ssm)
* to subcmd 0 after submitting subcmd 2? */
/* actually this is probably a poll response? does the above cmd
* include a 30 01 poll somewhere? */
int r = read_msg_async(dev, enroll_start_sm_cb_msg28, ssm);
r = read_msg_async(dev, enroll_start_sm_cb_msg28, ssm);
if (r < 0)
fpi_ssm_mark_aborted(ssm, r);
break;
@ -1069,35 +1110,37 @@ static void enroll_iterate_msg_cb(struct fp_dev *dev,
}
static void enroll_iterate_cmd_cb(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 enroll_iterate_cmd_cb(struct libusb_transfer *transfer)
{
struct fp_dev *dev = user_data;
struct fp_dev *dev = transfer->user_data;
if (status != FP_URB_COMPLETED) {
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_drvcb_enroll_stage_completed(dev, -EIO, NULL, NULL);
} else if (rqlength != actual_length) {
} else if (transfer->length != transfer->actual_length) {
fpi_drvcb_enroll_stage_completed(dev, -EPROTO, NULL, NULL);
} else {
int r = read_msg_async(dev, enroll_iterate_msg_cb, NULL);
if (r < 0)
fpi_drvcb_enroll_stage_completed(dev, r, NULL, NULL);
}
libusb_urb_handle_free(urbh);
libusb_free_transfer(transfer);
}
static void enroll_iterate(struct fp_dev *dev)
{
struct libusb_bulk_transfer msg;
struct libusb_urb_handle *urbh;
int r;
struct libusb_transfer *transfer = alloc_send_cmd28_transfer(dev, 0x00,
poll_data, sizeof(poll_data), enroll_iterate_cmd_cb, dev);
fill_send_cmd28_urb(dev, &msg, 0x00, poll_data, sizeof(poll_data));
urbh = libusb_async_bulk_transfer(dev->udev, &msg, enroll_iterate_cmd_cb,
dev, TIMEOUT);
if (!urbh) {
g_free(msg.data);
if (!transfer) {
fpi_drvcb_enroll_stage_completed(dev, -ENOMEM, NULL, NULL);
return;
}
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(transfer->buffer);
libusb_free_transfer(transfer);
fpi_drvcb_enroll_stage_completed(dev, -EIO, NULL, NULL);
}
}
@ -1176,23 +1219,22 @@ static void verify_start_sm_cb_initsm(struct fpi_ssm *initsm)
fpi_ssm_free(initsm);
}
static void verify_init_2803_cb(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 verify_init_2803_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = user_data;
if (status != FP_URB_COMPLETED)
struct fpi_ssm *ssm = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_aborted(ssm, -EIO);
else if (rqlength != actual_length)
else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_aborted(ssm, -EPROTO);
else
fpi_ssm_next_state(ssm);
libusb_urb_handle_free(urbh);
libusb_free_transfer(transfer);
}
static void verify_start_sm_run_state(struct fpi_ssm *ssm)
{
struct fp_dev *dev = ssm->dev;
int r;
switch (ssm->cur_state) {
case VERIFY_RUN_INITSM: ;
@ -1204,18 +1246,22 @@ static void verify_start_sm_run_state(struct fpi_ssm *ssm)
struct fp_print_data *print = dev->verify_data;
size_t data_len = sizeof(verify_hdr) + print->length;
unsigned char *data = g_malloc(data_len);
struct libusb_bulk_transfer msg;
struct libusb_urb_handle *urbh;
struct libusb_transfer *transfer;
memcpy(data, verify_hdr, sizeof(verify_hdr));
memcpy(data + sizeof(verify_hdr), print->data, print->length);
fill_send_cmd28_urb(dev, &msg, 0x03, data, data_len);
transfer = alloc_send_cmd28_transfer(dev, 0x03, data, data_len,
verify_init_2803_cb, ssm);
g_free(data);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
urbh = libusb_async_bulk_transfer(dev->udev, &msg,
verify_init_2803_cb, ssm, TIMEOUT);
if (!urbh) {
g_free(msg.data);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(transfer->buffer);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, -EIO);
}
break;
@ -1323,28 +1369,25 @@ static void verify_rd2800_cb(struct fp_dev *dev, enum read_msg_status msgstat,
fpi_drvcb_report_verify_result(dev, -EPROTO, NULL);
}
static void verify_wr2800_cb(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 verify_wr2800_cb(struct libusb_transfer *transfer)
{
struct fp_dev *dev = user_data;
struct fp_dev *dev = transfer->user_data;
if (status != FP_URB_COMPLETED) {
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_drvcb_report_verify_result(dev, -EIO, NULL);
} else if (rqlength != actual_length) {
} else if (transfer->length != transfer->actual_length) {
fpi_drvcb_report_verify_result(dev, -EIO, NULL);
} else {
int r = read_msg_async(dev, verify_rd2800_cb, NULL);
if (r < 0)
fpi_drvcb_report_verify_result(dev, r, NULL);
}
libusb_urb_handle_free(urbh);
libusb_free_transfer(transfer);
}
static void verify_iterate(struct fp_dev *dev)
{
struct upekts_dev *upekdev = dev->priv;
struct libusb_bulk_transfer msg;
if (upekdev->stop_verify) {
do_verify_stop(dev);
@ -1359,12 +1402,19 @@ static void verify_iterate(struct fp_dev *dev)
if (r < 0)
fpi_drvcb_report_verify_result(dev, r, NULL);
} else {
struct libusb_urb_handle *urbh;
fill_send_cmd28_urb(dev, &msg, 0x00, poll_data, sizeof(poll_data));
urbh = libusb_async_bulk_transfer(dev->udev, &msg, verify_wr2800_cb,
dev, TIMEOUT);
if (!urbh) {
g_free(msg.data);
int r;
struct libusb_transfer *transfer = alloc_send_cmd28_transfer(dev,
0x00, poll_data, sizeof(poll_data), verify_wr2800_cb, dev);
if (!transfer) {
fpi_drvcb_report_verify_result(dev, -ENOMEM, NULL);
return;
}
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(transfer->buffer);
libusb_free_transfer(transfer);
fpi_drvcb_report_verify_result(dev, -EIO, NULL);
}
}

View file

@ -122,8 +122,8 @@ struct uru4k_dev {
enum fp_imgdev_state activate_state;
unsigned char last_hwstat_rd;
libusb_urb_handle *irq_transfer;
libusb_urb_handle *img_transfer;
struct libusb_transfer *irq_transfer;
struct libusb_transfer *img_transfer;
irq_cb_fn irq_cb;
void *irq_cb_data;
@ -154,19 +154,18 @@ struct set_reg_data {
void *user_data;
};
static void set_reg_cb(libusb_dev_handle *devh, 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 set_reg_cb(struct libusb_transfer *transfer)
{
struct set_reg_data *srdata = user_data;
struct set_reg_data *srdata = transfer->user_data;
int r = 0;
if (status != FP_URB_COMPLETED)
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
r = -EIO;
else if (setup->wLength != actual_length)
else if (transfer->actual_length != 1)
r = -EPROTO;
libusb_urb_handle_free(urbh);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
srdata->callback(srdata->dev, r, srdata->user_data);
g_free(srdata);
}
@ -174,29 +173,32 @@ static void set_reg_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
static int set_reg(struct fp_img_dev *dev, unsigned char reg,
unsigned char value, set_reg_cb_fn callback, void *user_data)
{
struct set_reg_data *srdata = g_malloc(sizeof(*srdata));
struct libusb_urb_handle *urbh;
struct libusb_control_transfer trf = {
.requesttype = CTRL_OUT,
.request = USB_RQ,
.value = reg,
.index = 0,
.length = 1,
.data = &value,
};
struct set_reg_data *srdata;
struct libusb_transfer *transfer = libusb_alloc_transfer();
unsigned char *data;
int r;
if (!transfer)
return -ENOMEM;
srdata = g_malloc(sizeof(*srdata));
srdata->dev = dev;
srdata->callback = callback;
srdata->user_data = user_data;
trf.data[0] = value;
urbh = libusb_async_control_transfer(dev->udev, &trf, set_reg_cb, srdata,
CTRL_TIMEOUT);
if (!urbh) {
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
data[LIBUSB_CONTROL_SETUP_SIZE] = value;
libusb_fill_control_setup(data, CTRL_OUT, USB_RQ, reg, 0, 1);
libusb_fill_control_transfer(transfer, dev->udev, data, set_reg_cb,
srdata, CTRL_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(srdata);
return -EIO;
g_free(data);
libusb_free_transfer(transfer);
}
return 0;
return r;
}
/*
@ -233,59 +235,65 @@ struct c_r_data {
void *user_data;
};
static void response_cb(libusb_dev_handle *devh, 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 response_cb(struct libusb_transfer *transfer)
{
struct c_r_data *crdata = user_data;
struct c_r_data *crdata = transfer->user_data;
int r = 0;
if (status == FP_URB_COMPLETED)
if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
r = -EIO;
else if (actual_length != setup->wLength)
else if (transfer->actual_length != CR_LENGTH)
r = -EPROTO;
libusb_urb_handle_free(urbh);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
crdata->callback(crdata->dev, r, crdata->user_data);
}
static void challenge_cb(libusb_dev_handle *devh, 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 challenge_cb(struct libusb_transfer *transfer)
{
struct c_r_data *crdata = user_data;
struct c_r_data *crdata = transfer->user_data;
struct fp_img_dev *dev = crdata->dev;
struct uru4k_dev *urudev = dev->priv;
unsigned char respdata[CR_LENGTH];
struct libusb_transfer *resp_transfer;
unsigned char *respdata;
int r;
struct libusb_urb_handle *resp_urbh;
struct libusb_control_transfer trf_write_response = {
.requesttype = CTRL_OUT,
.request = USB_RQ,
.value = REG_RESPONSE,
.index = 0,
.data = respdata,
.length = sizeof(respdata),
};
if (status != FP_URB_COMPLETED) {
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
crdata->callback(crdata->dev, -EIO, crdata->user_data);
goto out;
} else if (setup->wLength != actual_length) {
} else if (transfer->actual_length != CR_LENGTH) {
crdata->callback(crdata->dev, -EPROTO, crdata->user_data);
goto out;
}
/* produce response from challenge */
AES_encrypt(data, respdata, &urudev->aeskey);
/* submit response */
resp_urbh = libusb_async_control_transfer(dev->udev, &trf_write_response,
response_cb, crdata, CTRL_TIMEOUT);
if (!resp_urbh)
crdata->callback(crdata->dev, -EIO, crdata->user_data);
resp_transfer = libusb_alloc_transfer();
if (!resp_transfer) {
crdata->callback(crdata->dev, -ENOMEM, crdata->user_data);
goto out;
}
respdata = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + CR_LENGTH);
libusb_fill_control_setup(respdata, CTRL_OUT, USB_RQ, REG_RESPONSE, 0,
CR_LENGTH);
libusb_fill_control_transfer(transfer, dev->udev, respdata, response_cb,
crdata, CTRL_TIMEOUT);
/* produce response from challenge */
AES_encrypt(libusb_control_transfer_get_data(transfer),
respdata + LIBUSB_CONTROL_SETUP_SIZE, &urudev->aeskey);
r = libusb_submit_transfer(resp_transfer);
if (r < 0) {
g_free(respdata);
libusb_free_transfer(resp_transfer);
crdata->callback(crdata->dev, r, crdata->user_data);
}
out:
libusb_urb_handle_free(urbh);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
}
/*
@ -296,28 +304,33 @@ out:
static int do_challenge_response(struct fp_img_dev *dev,
challenge_response_cb callback, void *user_data)
{
struct c_r_data *crdata = g_malloc(sizeof(*crdata));
struct libusb_urb_handle *urbh;
struct libusb_control_transfer trf_read_challenge = {
.requesttype = CTRL_IN,
.request = USB_RQ,
.value = REG_CHALLENGE,
.index = 0,
.length = CR_LENGTH,
};
struct libusb_transfer *transfer = libusb_alloc_transfer();;
struct c_r_data *crdata;
unsigned char *data;
int r;
fp_dbg("");
if (!transfer)
return -ENOMEM;
crdata = g_malloc(sizeof(*crdata));
crdata->dev = dev;
crdata->callback = callback;
crdata->user_data = user_data;
urbh = libusb_async_control_transfer(dev->udev, &trf_read_challenge,
challenge_cb, crdata, CTRL_TIMEOUT);
if (!urbh) {
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + CR_LENGTH);
libusb_fill_control_setup(data, CTRL_IN, USB_RQ, REG_CHALLENGE, 0,
CR_LENGTH);
libusb_fill_control_transfer(transfer, dev->udev, data, challenge_cb,
crdata, CTRL_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(crdata);
return -EIO;
g_free(data);
libusb_free_transfer(transfer);
}
return 0;
return r;
}
/***** INTERRUPT HANDLING *****/
@ -326,35 +339,33 @@ static int do_challenge_response(struct fp_img_dev *dev,
static int start_irq_handler(struct fp_img_dev *dev);
static void irq_handler(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 irq_handler(struct libusb_transfer *transfer)
{
struct fp_img_dev *dev = user_data;
struct fp_img_dev *dev = transfer->user_data;
struct uru4k_dev *urudev = dev->priv;
unsigned char *data = transfer->buffer;
uint16_t type;
int r = 0;
libusb_urb_handle_free(urbh);
if (status == FP_URB_CANCELLED) {
if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
fp_dbg("cancelled");
if (urudev->irqs_stopped_cb)
urudev->irqs_stopped_cb(dev);
urudev->irqs_stopped_cb = NULL;
goto out;
} else if (status != FP_URB_COMPLETED) {
} else if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
r = -EIO;
goto err;
} else if (actual_length != rqlength) {
fp_err("short interrupt read? %d", actual_length);
} else if (transfer->actual_length != transfer->length) {
fp_err("short interrupt read? %d", transfer->actual_length);
r = -EPROTO;
goto err;
}
type = GUINT16_FROM_BE(*((uint16_t *) data));
g_free(data);
fp_dbg("recv irq type %04x", type);
g_free(data);
libusb_free_transfer(transfer);
/* The 0800 interrupt seems to indicate imminent failure (0 bytes transfer)
* of the next scan. It still appears on occasion. */
@ -370,41 +381,47 @@ static void irq_handler(libusb_dev_handle *devh, libusb_urb_handle *urbh,
if (r == 0)
return;
transfer = NULL;
data = NULL;
err:
if (urudev->irq_cb)
urudev->irq_cb(dev, r, 0, urudev->irq_cb_data);
out:
g_free(data);
libusb_free_transfer(transfer);
urudev->irq_transfer = NULL;
}
static int start_irq_handler(struct fp_img_dev *dev)
{
struct uru4k_dev *urudev = dev->priv;
struct libusb_urb_handle *urbh;
struct libusb_bulk_transfer trf = {
.endpoint = EP_INTR,
.length = IRQ_LENGTH,
.data = g_malloc(IRQ_LENGTH),
};
struct libusb_transfer *transfer = libusb_alloc_transfer();
unsigned char *data;
int r;
urbh = libusb_async_interrupt_transfer(dev->udev, &trf, irq_handler, dev,
0);
urudev->irq_transfer = urbh;
if (!urbh) {
g_free(trf.data);
return -EIO;
if (!transfer)
return -ENOMEM;
data = g_malloc(IRQ_LENGTH);
libusb_fill_bulk_transfer(transfer, dev->udev, EP_INTR, data, IRQ_LENGTH,
irq_handler, dev, 0);
urudev->irq_transfer = transfer;
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
urudev->irq_transfer = NULL;
}
return 0;
return r;
}
static void stop_irq_handler(struct fp_img_dev *dev, irqs_stopped_cb_fn cb)
{
struct uru4k_dev *urudev = dev->priv;
struct libusb_urb_handle *urbh = urudev->irq_transfer;
if (urbh) {
libusb_urb_handle_cancel(dev->udev, urbh);
struct libusb_transfer *transfer = urudev->irq_transfer;
if (transfer) {
libusb_cancel_transfer(transfer);
urudev->irqs_stopped_cb = cb;
}
}
@ -413,46 +430,45 @@ static void stop_irq_handler(struct fp_img_dev *dev, irqs_stopped_cb_fn cb)
static int start_imaging_loop(struct fp_img_dev *dev);
static void image_cb(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 image_cb(struct libusb_transfer *transfer)
{
struct fp_img_dev *dev = user_data;
struct fp_img_dev *dev = transfer->user_data;
struct uru4k_dev *urudev = dev->priv;
int hdr_skip = CAPTURE_HDRLEN;
int image_size = DATABLK_EXPECT - CAPTURE_HDRLEN;
struct fp_img *img;
int r = 0;
libusb_urb_handle_free(urbh);
if (status == FP_URB_CANCELLED) {
if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
fp_dbg("cancelled");
urudev->img_transfer = NULL;
g_free(data);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
return;
} else if (status != FP_URB_COMPLETED) {
} else if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
r = -EIO;
goto out;
}
if (actual_length == image_size) {
if (transfer->actual_length == image_size) {
/* no header! this is rather odd, but it happens sometimes with my MS
* keyboard */
fp_dbg("got image with no header!");
hdr_skip = 0;
} else if (actual_length != DATABLK_EXPECT) {
fp_err("unexpected image capture size (%d)", actual_length);
} else if (transfer->actual_length != DATABLK_EXPECT) {
fp_err("unexpected image capture size (%d)", transfer->actual_length);
r = -EPROTO;
goto out;
}
img = fpi_img_new(image_size);
memcpy(img->data, data + hdr_skip, image_size);
memcpy(img->data, transfer->buffer + hdr_skip, image_size);
img->flags = FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED | FP_IMG_COLORS_INVERTED;
fpi_imgdev_image_captured(dev, img);
out:
g_free(data);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
if (r == 0)
r = start_imaging_loop(dev);
@ -463,29 +479,33 @@ out:
static int start_imaging_loop(struct fp_img_dev *dev)
{
struct uru4k_dev *urudev = dev->priv;
struct libusb_urb_handle *urbh;
struct libusb_bulk_transfer trf = {
.endpoint = EP_DATA,
.length = DATABLK_RQLEN,
.data = g_malloc(DATABLK_RQLEN),
};
struct libusb_transfer *transfer = libusb_alloc_transfer();
unsigned char *data;
int r;
urbh = libusb_async_bulk_transfer(dev->udev, &trf, image_cb, dev, 0);
urudev->img_transfer = urbh;
if (!urbh) {
g_free(trf.data);
return -EIO;
if (!transfer)
return -ENOMEM;
data = g_malloc(DATABLK_RQLEN);
libusb_fill_bulk_transfer(transfer, dev->udev, EP_DATA, data,
DATABLK_RQLEN, image_cb, dev, 0);
urudev->img_transfer = transfer;
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
}
return 0;
return r;
}
static void stop_imaging_loop(struct fp_img_dev *dev)
{
struct uru4k_dev *urudev = dev->priv;
libusb_urb_handle *urbh = urudev->img_transfer;
if (urbh)
libusb_urb_handle_cancel(dev->udev, urbh);
struct libusb_transfer *transfer = urudev->img_transfer;
if (transfer)
libusb_cancel_transfer(transfer);
/* FIXME: should probably wait for cancellation to complete */
}
@ -577,68 +597,72 @@ static void sm_set_hwstat(struct fpi_ssm *ssm, unsigned char value)
sm_set_reg(ssm, REG_HWSTAT, value);
}
static void sm_get_hwstat_cb(libusb_dev_handle *devh, 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 sm_get_hwstat_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = user_data;
struct fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = ssm->priv;
struct uru4k_dev *urudev = dev->priv;
if (status != FP_URB_COMPLETED) {
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_aborted(ssm, -EIO);
} else if (setup->wLength != actual_length) {
} else if (transfer->actual_length != 1) {
fpi_ssm_mark_aborted(ssm, -EPROTO);
} else {
urudev->last_hwstat_rd = *data;
urudev->last_hwstat_rd = libusb_control_transfer_get_data(transfer)[0];
fp_dbg("value %02x", urudev->last_hwstat_rd);
fpi_ssm_next_state(ssm);
}
libusb_urb_handle_free(urbh);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
}
static void sm_get_hwstat(struct fpi_ssm *ssm)
{
struct fp_img_dev *dev = ssm->priv;
struct libusb_urb_handle *urbh;
struct libusb_transfer *transfer = libusb_alloc_transfer();
unsigned char *data;
int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
/* The windows driver uses a request of 0x0c here. We use 0x04 to be
* consistent with every other command we know about. */
/* FIXME is the above comment still true? */
struct libusb_control_transfer trf = {
.requesttype = CTRL_IN,
.request = USB_RQ,
.value = REG_HWSTAT,
.index = 0,
.length = 1,
};
urbh = libusb_async_control_transfer(dev->udev, &trf, sm_get_hwstat_cb,
libusb_fill_control_setup(data, CTRL_IN, USB_RQ, REG_HWSTAT, 0, 1);
libusb_fill_control_transfer(transfer, dev->udev, data, sm_get_hwstat_cb,
ssm, CTRL_TIMEOUT);
if (!urbh)
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, -EIO);
}
}
static void sm_fix_fw_read_cb(libusb_dev_handle *devh, 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 sm_fix_fw_read_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = user_data;
struct fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = ssm->priv;
struct uru4k_dev *urudev = dev->priv;
unsigned char new;
unsigned char fwenc;
uint32_t enc_addr = FIRMWARE_START + urudev->profile->fw_enc_offset;
if (status != FP_URB_COMPLETED) {
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
} else if (actual_length != setup->wLength) {
} else if (transfer->actual_length != 1) {
fpi_ssm_mark_aborted(ssm, -EPROTO);
goto out;
}
fwenc = data[0];
fwenc = libusb_control_transfer_get_data(transfer)[0];
fp_dbg("firmware encryption byte at %x reads %02x", enc_addr, fwenc);
if (fwenc != 0x07 && fwenc != 0x17)
fp_dbg("strange encryption byte value, please report this");
@ -652,7 +676,8 @@ static void sm_fix_fw_read_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
}
out:
libusb_urb_handle_free(urbh);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
}
static void sm_fix_firmware(struct fpi_ssm *ssm)
@ -660,20 +685,26 @@ static void sm_fix_firmware(struct fpi_ssm *ssm)
struct fp_img_dev *dev = ssm->priv;
struct uru4k_dev *urudev = dev->priv;
uint32_t enc_addr = FIRMWARE_START + urudev->profile->fw_enc_offset;
struct libusb_transfer *transfer = libusb_alloc_transfer();
unsigned char *data;
int r;
struct libusb_urb_handle *urbh;
struct libusb_control_transfer trf_read_fw = {
.requesttype = 0xc0,
.request = 0x0c,
.value = enc_addr,
.index = 0,
.length = 1,
};
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
urbh = libusb_async_control_transfer(dev->udev, &trf_read_fw,
sm_fix_fw_read_cb, ssm, CTRL_TIMEOUT);
if (!urbh)
fpi_ssm_mark_aborted(ssm, -EIO);
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
libusb_fill_control_setup(data, 0xc0, 0x0c, enc_addr, 0, 1);
libusb_fill_control_transfer(transfer, dev->udev, data, sm_fix_fw_read_cb,
ssm, CTRL_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
}
}
/***** INITIALIZATION *****/
@ -1070,7 +1101,7 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r;
/* Find fingerprint interface */
config = libusb_dev_get_config(libusb_devh_get_dev(dev->udev));
config = libusb_get_config_descriptor(libusb_get_device(dev->udev));
for (i = 0; i < config->bNumInterfaces; i++) {
struct libusb_interface *cur_iface = &config->interface[i];

View file

@ -93,7 +93,7 @@ enum fp_dev_state {
struct fp_dev {
struct fp_driver *drv;
libusb_dev_handle *udev;
libusb_device_handle *udev;
uint32_t devtype;
void *priv;
@ -161,7 +161,7 @@ enum fp_imgdev_verify_state {
struct fp_img_dev {
struct fp_dev *dev;
libusb_dev_handle *udev;
libusb_device_handle *udev;
enum fp_imgdev_action action;
int action_state;
@ -249,7 +249,7 @@ void fpi_img_driver_setup(struct fp_img_driver *idriver);
container_of((drv), struct fp_img_driver, driver)
struct fp_dscv_dev {
libusb_dev *udev;
struct libusb_device *udev;
struct fp_driver *drv;
unsigned long driver_data;
uint32_t devtype;

View file

@ -180,7 +180,7 @@ API_EXPORTED int fp_enroll_finger_img(struct fp_dev *dev,
int stage = dev->__enroll_stage;
gboolean final = FALSE;
gboolean stopped = FALSE;
struct sync_enroll_data *edata;
struct sync_enroll_data *edata = NULL;
int r;
fp_dbg("");