From 4e884807a793091e3410ea0ba10e3e314e21818f Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Mon, 10 Mar 2008 11:35:58 +0000 Subject: [PATCH] Update for libusb API rework --- libfprint/aeslib.c | 41 ++-- libfprint/async.c | 2 +- libfprint/core.c | 33 +-- libfprint/drivers/aes2501.c | 171 ++++++++------- libfprint/drivers/aes4000.c | 46 ++-- libfprint/drivers/upekts.c | 426 ++++++++++++++++++++---------------- libfprint/drivers/uru4000.c | 363 ++++++++++++++++-------------- libfprint/fp_internal.h | 6 +- libfprint/sync.c | 2 +- 9 files changed, 601 insertions(+), 489 deletions(-) diff --git a/libfprint/aeslib.c b/libfprint/aeslib.c index 4c797c3..579cd12 100644 --- a/libfprint/aeslib.c +++ b/libfprint/aeslib.c @@ -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, diff --git a/libfprint/async.c b/libfprint/async.c index 00d9727..5d0bd10 100644 --- a/libfprint/async.c +++ b/libfprint/async.c @@ -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(""); diff --git a/libfprint/core.c b/libfprint/core.c index f16c6ca..0be4569 100644 --- a/libfprint/core.c +++ b/libfprint/core.c @@ -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,33 +409,40 @@ 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)) { - struct fp_dscv_dev *ddev = discover_dev(udev); - if (!ddev) - continue; - tmplist = g_slist_prepend(tmplist, (gpointer) ddev); - dscv_count++; - } + while ((udev = devs[i++]) != NULL) { + struct fp_dscv_dev *ddev = discover_dev(udev); + if (!ddev) + continue; + tmplist = g_slist_prepend(tmplist, (gpointer) ddev); + dscv_count++; + } /* Convert our temporary GSList into a standard NULL-terminated pointer * array. */ 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))); diff --git a/libfprint/drivers/aes2501.c b/libfprint/drivers/aes2501.c index f0ea95d..3e3bae6 100644 --- a/libfprint/drivers/aes2501.c +++ b/libfprint/drivers/aes2501.c @@ -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; }; diff --git a/libfprint/drivers/aes4000.c b/libfprint/drivers/aes4000.c index ff3b3c2..8c2ec0e 100644 --- a/libfprint/drivers/aes4000.c +++ b/libfprint/drivers/aes4000.c @@ -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); } diff --git a/libfprint/drivers/upekts.c b/libfprint/drivers/upekts.c index 214d4fd..e0e7d1a 100644 --- a/libfprint/drivers/upekts.c +++ b/libfprint/drivers/upekts.c @@ -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); } } diff --git a/libfprint/drivers/uru4000.c b/libfprint/drivers/uru4000.c index c2e5761..48e2b67 100644 --- a/libfprint/drivers/uru4000.c +++ b/libfprint/drivers/uru4000.c @@ -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; + } + + 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); - 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); + 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]; diff --git a/libfprint/fp_internal.h b/libfprint/fp_internal.h index c391e37..5b1c289 100644 --- a/libfprint/fp_internal.h +++ b/libfprint/fp_internal.h @@ -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; diff --git a/libfprint/sync.c b/libfprint/sync.c index 61557eb..d636edd 100644 --- a/libfprint/sync.c +++ b/libfprint/sync.c @@ -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("");