Rework URB API naming
Now refer to everything as "transfers" as consistent with the USB spec libusb_transfer is now a kind of transfer handle. To reduce confusion with libusb_bulk_transfer and libusb_control_transfer, those have been renamed to libusb_{control,bulk}_transfer_request.
This commit is contained in:
parent
fd6fb3cc09
commit
d21ebe47ce
5 changed files with 264 additions and 251 deletions
5
TODO
5
TODO
|
@ -9,6 +9,7 @@ isochronous endpoint I/O
|
||||||
thread safety
|
thread safety
|
||||||
abstraction for cross-platform-ness
|
abstraction for cross-platform-ness
|
||||||
error codes
|
error codes
|
||||||
|
fixme review
|
||||||
|
|
||||||
for 1.1 or future
|
for 1.1 or future
|
||||||
==================
|
==================
|
||||||
|
@ -21,8 +22,8 @@ use poll() rather than select()?
|
||||||
|
|
||||||
struct libusb_(bulk|control)_transfer or parameters?
|
struct libusb_(bulk|control)_transfer or parameters?
|
||||||
devh in general
|
devh in general
|
||||||
urbh in general (should this be a transfer handle?)
|
separate transfer allocation and submission
|
||||||
config struct/function naming
|
config struct/function naming
|
||||||
typedef _cb or _cb_fn or _cb_t?
|
typedef _cb or _cb_fn or _cb_t?
|
||||||
typedef as-is or pointers? libusb_dev_t rather than libusb_dev *?
|
typedef as-is or pointers? libusb_dev_t rather than libusb_dev *?
|
||||||
FP_ urb status codes
|
remove "_transfer" from libusb_{control,bulk}_transfer_request?
|
||||||
|
|
|
@ -62,18 +62,18 @@ static int state = 0;
|
||||||
static struct libusb_dev_handle *devh = NULL;
|
static struct libusb_dev_handle *devh = NULL;
|
||||||
static unsigned char imgbuf[0x1b340];
|
static unsigned char imgbuf[0x1b340];
|
||||||
static unsigned char irqbuf[INTR_LENGTH];
|
static unsigned char irqbuf[INTR_LENGTH];
|
||||||
static libusb_urb_handle *img_urbh = NULL;
|
static libusb_transfer *img_urbh = NULL;
|
||||||
static libusb_urb_handle *irq_urbh = NULL;
|
static libusb_transfer *irq_urbh = NULL;
|
||||||
static int img_idx = 0;
|
static int img_idx = 0;
|
||||||
static int do_exit = 0;
|
static int do_exit = 0;
|
||||||
|
|
||||||
static struct libusb_bulk_transfer imgtrf = {
|
static struct libusb_bulk_transfer_request imgrq = {
|
||||||
.endpoint = EP_DATA,
|
.endpoint = EP_DATA,
|
||||||
.data = imgbuf,
|
.data = imgbuf,
|
||||||
.length = sizeof(imgbuf),
|
.length = sizeof(imgbuf),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct libusb_bulk_transfer irqtrf = {
|
static struct libusb_bulk_transfer_request intrrq = {
|
||||||
.endpoint = EP_INTR,
|
.endpoint = EP_INTR,
|
||||||
.data = irqbuf,
|
.data = irqbuf,
|
||||||
.length = sizeof(irqbuf),
|
.length = sizeof(irqbuf),
|
||||||
|
@ -88,7 +88,7 @@ static int find_dpfp_device(void)
|
||||||
static int print_f0_data(void)
|
static int print_f0_data(void)
|
||||||
{
|
{
|
||||||
unsigned char data[0x10];
|
unsigned char data[0x10];
|
||||||
struct libusb_control_transfer transfer = {
|
struct libusb_control_transfer_request rq = {
|
||||||
.requesttype = CTRL_IN,
|
.requesttype = CTRL_IN,
|
||||||
.request = USB_RQ,
|
.request = USB_RQ,
|
||||||
.value = 0xf0,
|
.value = 0xf0,
|
||||||
|
@ -99,7 +99,7 @@ static int print_f0_data(void)
|
||||||
int r;
|
int r;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
r = libusb_control_transfer(devh, &transfer, 0);
|
r = libusb_control_transfer(devh, &rq, 0);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
fprintf(stderr, "F0 error %d\n", r);
|
fprintf(stderr, "F0 error %d\n", r);
|
||||||
return r;
|
return r;
|
||||||
|
@ -118,7 +118,7 @@ static int print_f0_data(void)
|
||||||
|
|
||||||
static int get_hwstat(unsigned char *status)
|
static int get_hwstat(unsigned char *status)
|
||||||
{
|
{
|
||||||
struct libusb_control_transfer transfer = {
|
struct libusb_control_transfer_request rq = {
|
||||||
.requesttype = CTRL_IN,
|
.requesttype = CTRL_IN,
|
||||||
.request = USB_RQ,
|
.request = USB_RQ,
|
||||||
.value = 0x07,
|
.value = 0x07,
|
||||||
|
@ -128,7 +128,7 @@ static int get_hwstat(unsigned char *status)
|
||||||
};
|
};
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = libusb_control_transfer(devh, &transfer, 0);
|
r = libusb_control_transfer(devh, &rq, 0);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
fprintf(stderr, "read hwstat error %d\n", r);
|
fprintf(stderr, "read hwstat error %d\n", r);
|
||||||
return r;
|
return r;
|
||||||
|
@ -145,7 +145,7 @@ static int get_hwstat(unsigned char *status)
|
||||||
static int set_hwstat(unsigned char data)
|
static int set_hwstat(unsigned char data)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
struct libusb_control_transfer transfer = {
|
struct libusb_control_transfer_request rq = {
|
||||||
.requesttype = CTRL_OUT,
|
.requesttype = CTRL_OUT,
|
||||||
.request = USB_RQ,
|
.request = USB_RQ,
|
||||||
.value = 0x07,
|
.value = 0x07,
|
||||||
|
@ -156,7 +156,7 @@ static int set_hwstat(unsigned char data)
|
||||||
|
|
||||||
printf("set hwstat to %02x\n", data);
|
printf("set hwstat to %02x\n", data);
|
||||||
|
|
||||||
r = libusb_control_transfer(devh, &transfer, 0);
|
r = libusb_control_transfer(devh, &rq, 0);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
fprintf(stderr, "set hwstat error %d\n", r);
|
fprintf(stderr, "set hwstat error %d\n", r);
|
||||||
return r;
|
return r;
|
||||||
|
@ -172,7 +172,7 @@ static int set_hwstat(unsigned char data)
|
||||||
static int set_mode(unsigned char data)
|
static int set_mode(unsigned char data)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
struct libusb_control_transfer transfer = {
|
struct libusb_control_transfer_request rq = {
|
||||||
.requesttype = CTRL_OUT,
|
.requesttype = CTRL_OUT,
|
||||||
.request = USB_RQ,
|
.request = USB_RQ,
|
||||||
.value = 0x4e,
|
.value = 0x4e,
|
||||||
|
@ -183,7 +183,7 @@ static int set_mode(unsigned char data)
|
||||||
|
|
||||||
printf("set mode %02x\n", data);
|
printf("set mode %02x\n", data);
|
||||||
|
|
||||||
r = libusb_control_transfer(devh, &transfer, 0);
|
r = libusb_control_transfer(devh, &rq, 0);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
fprintf(stderr, "set mode error %d\n", r);
|
fprintf(stderr, "set mode error %d\n", r);
|
||||||
return r;
|
return r;
|
||||||
|
@ -197,11 +197,11 @@ static int set_mode(unsigned char data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cb_mode_changed(struct libusb_dev_handle *_devh,
|
static void cb_mode_changed(struct libusb_dev_handle *_devh,
|
||||||
struct libusb_urb_handle *urbh, enum libusb_urb_cb_status status,
|
struct libusb_transfer *urbh, enum libusb_transfer_status status,
|
||||||
struct libusb_ctrl_setup *setup, unsigned char *data, int actual_length,
|
struct libusb_control_setup *setup, unsigned char *data, int actual_length,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
if (status != FP_URB_COMPLETED) {
|
if (status != LIBUSB_TRANSFER_COMPLETED) {
|
||||||
fprintf(stderr, "mode change URB not completed!\n");
|
fprintf(stderr, "mode change URB not completed!\n");
|
||||||
do_exit = 2;
|
do_exit = 2;
|
||||||
}
|
}
|
||||||
|
@ -213,8 +213,8 @@ static void cb_mode_changed(struct libusb_dev_handle *_devh,
|
||||||
|
|
||||||
static int set_mode_async(unsigned char data)
|
static int set_mode_async(unsigned char data)
|
||||||
{
|
{
|
||||||
libusb_urb_handle *urbh;
|
libusb_transfer *urbh;
|
||||||
struct libusb_control_transfer transfer = {
|
struct libusb_control_transfer_request rq = {
|
||||||
.requesttype = CTRL_OUT,
|
.requesttype = CTRL_OUT,
|
||||||
.request = USB_RQ,
|
.request = USB_RQ,
|
||||||
.value = 0x4e,
|
.value = 0x4e,
|
||||||
|
@ -225,7 +225,7 @@ static int set_mode_async(unsigned char data)
|
||||||
|
|
||||||
printf("async set mode %02x\n", data);
|
printf("async set mode %02x\n", data);
|
||||||
|
|
||||||
urbh = libusb_async_control_transfer(devh, &transfer, cb_mode_changed, NULL,
|
urbh = libusb_async_control_transfer(devh, &rq, cb_mode_changed, NULL,
|
||||||
1000);
|
1000);
|
||||||
if (!urbh) {
|
if (!urbh) {
|
||||||
fprintf(stderr, "set mode submit error\n");
|
fprintf(stderr, "set mode submit error\n");
|
||||||
|
@ -237,7 +237,7 @@ static int set_mode_async(unsigned char data)
|
||||||
|
|
||||||
static int do_sync_intr(unsigned char *data)
|
static int do_sync_intr(unsigned char *data)
|
||||||
{
|
{
|
||||||
struct libusb_bulk_transfer transfer = {
|
struct libusb_bulk_transfer_request request = {
|
||||||
.endpoint = EP_INTR,
|
.endpoint = EP_INTR,
|
||||||
.data = data,
|
.data = data,
|
||||||
.length = INTR_LENGTH,
|
.length = INTR_LENGTH,
|
||||||
|
@ -245,7 +245,7 @@ static int do_sync_intr(unsigned char *data)
|
||||||
int r;
|
int r;
|
||||||
int transferred;
|
int transferred;
|
||||||
|
|
||||||
r = libusb_interrupt_transfer(devh, &transfer, &transferred, 1000);
|
r = libusb_interrupt_transfer(devh, &request, &transferred, 1000);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
fprintf(stderr, "intr error %d\n", r);
|
fprintf(stderr, "intr error %d\n", r);
|
||||||
return r;
|
return r;
|
||||||
|
@ -328,13 +328,13 @@ static int next_state(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cb_irq(libusb_dev_handle *_devh, libusb_urb_handle *urbh,
|
static void cb_irq(libusb_dev_handle *_devh, libusb_transfer *urbh,
|
||||||
enum libusb_urb_cb_status status, unsigned char endpoint, int rqlength,
|
enum libusb_transfer_status status, unsigned char endpoint, int rqlength,
|
||||||
unsigned char *data, int actual_length, void *user_data)
|
unsigned char *data, int actual_length, void *user_data)
|
||||||
{
|
{
|
||||||
unsigned char irqtype = data[0];
|
unsigned char irqtype = data[0];
|
||||||
|
|
||||||
if (status != FP_URB_COMPLETED) {
|
if (status != LIBUSB_TRANSFER_COMPLETED) {
|
||||||
fprintf(stderr, "irq URB status %d?\n", status);
|
fprintf(stderr, "irq URB status %d?\n", status);
|
||||||
do_exit = 2;
|
do_exit = 2;
|
||||||
return;
|
return;
|
||||||
|
@ -367,11 +367,11 @@ static void cb_irq(libusb_dev_handle *_devh, libusb_urb_handle *urbh,
|
||||||
do_exit = 2;
|
do_exit = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cb_img(libusb_dev_handle *_devh, libusb_urb_handle *urbh,
|
static void cb_img(libusb_dev_handle *_devh, libusb_transfer *urbh,
|
||||||
enum libusb_urb_cb_status status, unsigned char endpoint, int rqlength,
|
enum libusb_transfer_status status, unsigned char endpoint, int rqlength,
|
||||||
unsigned char *data, int actual_length, void *user_data)
|
unsigned char *data, int actual_length, void *user_data)
|
||||||
{
|
{
|
||||||
if (status != FP_URB_COMPLETED) {
|
if (status != LIBUSB_TRANSFER_COMPLETED) {
|
||||||
fprintf(stderr, "img URB status %d?\n", status);
|
fprintf(stderr, "img URB status %d?\n", status);
|
||||||
do_exit = 2;
|
do_exit = 2;
|
||||||
return;
|
return;
|
||||||
|
@ -389,15 +389,15 @@ static void cb_img(libusb_dev_handle *_devh, libusb_urb_handle *urbh,
|
||||||
|
|
||||||
static int submit_irq_urb(void)
|
static int submit_irq_urb(void)
|
||||||
{
|
{
|
||||||
libusb_urb_handle_free(irq_urbh);
|
libusb_transfer_free(irq_urbh);
|
||||||
irq_urbh = libusb_async_interrupt_transfer(devh, &irqtrf, cb_irq, NULL, 0);
|
irq_urbh = libusb_async_interrupt_transfer(devh, &intrrq, cb_irq, NULL, 0);
|
||||||
return irq_urbh != NULL;
|
return irq_urbh != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int submit_img_urb(void)
|
static int submit_img_urb(void)
|
||||||
{
|
{
|
||||||
libusb_urb_handle_free(img_urbh);
|
libusb_transfer_free(img_urbh);
|
||||||
img_urbh = libusb_async_bulk_transfer(devh, &imgtrf, cb_img, NULL, 0);
|
img_urbh = libusb_async_bulk_transfer(devh, &imgrq, cb_img, NULL, 0);
|
||||||
return img_urbh != NULL;
|
return img_urbh != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,7 +411,7 @@ static int init_capture(void)
|
||||||
|
|
||||||
r = submit_img_urb();
|
r = submit_img_urb();
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
libusb_urb_handle_cancel_sync(devh, img_urbh);
|
libusb_transfer_cancel_sync(devh, img_urbh);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,11 +512,11 @@ int main(void)
|
||||||
|
|
||||||
printf("shutting down...\n");
|
printf("shutting down...\n");
|
||||||
|
|
||||||
r = libusb_urb_handle_cancel_sync(devh, irq_urbh);
|
r = libusb_transfer_cancel_sync(devh, irq_urbh);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto out_deinit;
|
goto out_deinit;
|
||||||
|
|
||||||
r = libusb_urb_handle_cancel_sync(devh, img_urbh);
|
r = libusb_transfer_cancel_sync(devh, img_urbh);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto out_deinit;
|
goto out_deinit;
|
||||||
|
|
||||||
|
@ -526,8 +526,8 @@ int main(void)
|
||||||
r = 1;
|
r = 1;
|
||||||
|
|
||||||
out_deinit:
|
out_deinit:
|
||||||
libusb_urb_handle_free(img_urbh);
|
libusb_transfer_free(img_urbh);
|
||||||
libusb_urb_handle_free(irq_urbh);
|
libusb_transfer_free(irq_urbh);
|
||||||
set_mode(0);
|
set_mode(0);
|
||||||
set_hwstat(0x80);
|
set_hwstat(0x80);
|
||||||
out_release:
|
out_release:
|
||||||
|
|
362
libusb/io.c
362
libusb/io.c
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* I/O functions for libusb
|
* I/O functions for libusb
|
||||||
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
|
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
|
||||||
* Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
|
* Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
* URBs to timeout the soonest are placed at the beginning of the list, URBs
|
* URBs to timeout the soonest are placed at the beginning of the list, URBs
|
||||||
* that will time out later are placed after, and urbs with infinite timeout
|
* that will time out later are placed after, and urbs with infinite timeout
|
||||||
* are always placed at the very end. */
|
* are always placed at the very end. */
|
||||||
static struct list_head flying_urbs;
|
static struct list_head flying_transfers;
|
||||||
|
|
||||||
/* user callbacks for pollfd changes */
|
/* user callbacks for pollfd changes */
|
||||||
static libusb_pollfd_added_cb fd_added_cb = NULL;
|
static libusb_pollfd_added_cb fd_added_cb = NULL;
|
||||||
|
@ -44,12 +44,12 @@ static libusb_pollfd_removed_cb fd_removed_cb = NULL;
|
||||||
|
|
||||||
void usbi_io_init()
|
void usbi_io_init()
|
||||||
{
|
{
|
||||||
list_init(&flying_urbs);
|
list_init(&flying_transfers);
|
||||||
fd_added_cb = NULL;
|
fd_added_cb = NULL;
|
||||||
fd_removed_cb = NULL;
|
fd_removed_cb = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int calculate_timeout(struct libusb_urb_handle *urbh,
|
static int calculate_timeout(struct libusb_transfer *transfer,
|
||||||
unsigned int timeout)
|
unsigned int timeout)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
@ -72,54 +72,54 @@ static int calculate_timeout(struct libusb_urb_handle *urbh,
|
||||||
current_time.tv_sec++;
|
current_time.tv_sec++;
|
||||||
}
|
}
|
||||||
|
|
||||||
TIMESPEC_TO_TIMEVAL(&urbh->timeout, ¤t_time);
|
TIMESPEC_TO_TIMEVAL(&transfer->timeout, ¤t_time);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_to_flying_list(struct libusb_urb_handle *urbh)
|
static void add_to_flying_list(struct libusb_transfer *transfer)
|
||||||
{
|
{
|
||||||
struct libusb_urb_handle *cur;
|
struct libusb_transfer *cur;
|
||||||
struct timeval *timeout = &urbh->timeout;
|
struct timeval *timeout = &transfer->timeout;
|
||||||
|
|
||||||
/* if we have no other flying urbs, start the list with this one */
|
/* if we have no other flying transfers, start the list with this one */
|
||||||
if (list_empty(&flying_urbs)) {
|
if (list_empty(&flying_transfers)) {
|
||||||
list_add(&urbh->list, &flying_urbs);
|
list_add(&transfer->list, &flying_transfers);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we have infinite timeout, append to end of list */
|
/* if we have infinite timeout, append to end of list */
|
||||||
if (!timerisset(timeout)) {
|
if (!timerisset(timeout)) {
|
||||||
list_add_tail(&urbh->list, &flying_urbs);
|
list_add_tail(&transfer->list, &flying_transfers);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* otherwise, find appropriate place in list */
|
/* otherwise, find appropriate place in list */
|
||||||
list_for_each_entry(cur, &flying_urbs, list) {
|
list_for_each_entry(cur, &flying_transfers, list) {
|
||||||
/* find first timeout that occurs after the urbh in question */
|
/* find first timeout that occurs after the transfer in question */
|
||||||
struct timeval *cur_tv = &cur->timeout;
|
struct timeval *cur_tv = &cur->timeout;
|
||||||
|
|
||||||
if (!timerisset(cur_tv) || (cur_tv->tv_sec > timeout->tv_sec) ||
|
if (!timerisset(cur_tv) || (cur_tv->tv_sec > timeout->tv_sec) ||
|
||||||
(cur_tv->tv_sec == timeout->tv_sec &&
|
(cur_tv->tv_sec == timeout->tv_sec &&
|
||||||
cur_tv->tv_usec > timeout->tv_usec)) {
|
cur_tv->tv_usec > timeout->tv_usec)) {
|
||||||
list_add_tail(&urbh->list, &cur->list);
|
list_add_tail(&transfer->list, &cur->list);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* otherwise we need to be inserted at the end */
|
/* otherwise we need to be inserted at the end */
|
||||||
list_add_tail(&urbh->list, &flying_urbs);
|
list_add_tail(&transfer->list, &flying_transfers);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int submit_urb(struct libusb_dev_handle *devh,
|
static int submit_transfer(struct libusb_dev_handle *devh,
|
||||||
struct libusb_urb_handle *urbh)
|
struct libusb_transfer *transfer)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
struct usb_urb *urb = &urbh->urb;
|
struct usb_urb *urb = &transfer->urb;
|
||||||
int to_be_transferred = urbh->transfer_len - urbh->transferred;
|
int to_be_transferred = transfer->transfer_len - transfer->transferred;
|
||||||
|
|
||||||
urb->type = urbh->urb_type;
|
urb->type = transfer->urb_type;
|
||||||
urb->endpoint = urbh->endpoint;
|
urb->endpoint = transfer->endpoint;
|
||||||
urb->buffer = urbh->buffer + urbh->transferred;
|
urb->buffer = transfer->buffer + transfer->transferred;
|
||||||
urb->buffer_length = MIN(to_be_transferred, MAX_URB_BUFFER_LENGTH);
|
urb->buffer_length = MIN(to_be_transferred, MAX_URB_BUFFER_LENGTH);
|
||||||
|
|
||||||
/* FIXME: for requests that we have to split into multiple URBs, we should
|
/* FIXME: for requests that we have to split into multiple URBs, we should
|
||||||
|
@ -130,149 +130,153 @@ static int submit_urb(struct libusb_dev_handle *devh,
|
||||||
usbi_dbg("transferring %d from %d bytes", urb->buffer_length,
|
usbi_dbg("transferring %d from %d bytes", urb->buffer_length,
|
||||||
to_be_transferred);
|
to_be_transferred);
|
||||||
|
|
||||||
r = ioctl(devh->fd, IOCTL_USB_SUBMITURB, &urbh->urb);
|
r = ioctl(devh->fd, IOCTL_USB_SUBMITURB, &transfer->urb);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
usbi_err("submiturb failed error %d errno=%d", r, errno);
|
usbi_err("submiturb failed error %d errno=%d", r, errno);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_to_flying_list(urbh);
|
add_to_flying_list(transfer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORTED struct libusb_urb_handle *libusb_async_control_transfer(
|
API_EXPORTED struct libusb_transfer *libusb_async_control_transfer(
|
||||||
struct libusb_dev_handle *devh, struct libusb_control_transfer *transfer,
|
struct libusb_dev_handle *devh,
|
||||||
libusb_ctrl_cb_fn callback, void *user_data, unsigned int timeout)
|
struct libusb_control_transfer_request *request,
|
||||||
|
libusb_control_cb_fn callback, void *user_data, unsigned int timeout)
|
||||||
{
|
{
|
||||||
struct libusb_urb_handle *urbh = malloc(sizeof(*urbh));
|
struct libusb_transfer *transfer = malloc(sizeof(*transfer));
|
||||||
struct libusb_ctrl_setup *setup;
|
struct libusb_control_setup *setup;
|
||||||
unsigned char *urbdata;
|
unsigned char *urbdata;
|
||||||
int urbdata_length = sizeof(struct libusb_ctrl_setup) + transfer->length;
|
int urbdata_length = sizeof(struct libusb_control_setup) + request->length;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!urbh)
|
if (!transfer)
|
||||||
return NULL;
|
return NULL;
|
||||||
memset(urbh, 0, sizeof(*urbh));
|
memset(transfer, 0, sizeof(*transfer));
|
||||||
urbh->devh = devh;
|
transfer->devh = devh;
|
||||||
urbh->callback = callback;
|
transfer->callback = callback;
|
||||||
urbh->user_data = user_data;
|
transfer->user_data = user_data;
|
||||||
r = calculate_timeout(urbh, timeout);
|
r = calculate_timeout(transfer, timeout);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
free(urbh);
|
free(transfer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
urbdata = malloc(urbdata_length);
|
urbdata = malloc(urbdata_length);
|
||||||
if (!urbdata) {
|
if (!urbdata) {
|
||||||
free(urbh);
|
free(transfer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
usbi_dbg("RQT=%02x RQ=%02x VAL=%04x IDX=%04x length=%d",
|
usbi_dbg("RQT=%02x RQ=%02x VAL=%04x IDX=%04x length=%d",
|
||||||
transfer->requesttype, transfer->request, transfer->value,
|
request->requesttype, request->request, request->value,
|
||||||
transfer->index, transfer->length);
|
request->index, request->length);
|
||||||
|
|
||||||
setup = (struct libusb_ctrl_setup *) urbdata;
|
setup = (struct libusb_control_setup *) urbdata;
|
||||||
setup->bRequestType = transfer->requesttype;
|
setup->bRequestType = request->requesttype;
|
||||||
setup->bRequest = transfer->request;
|
setup->bRequest = request->request;
|
||||||
setup->wValue = cpu_to_le16(transfer->value);
|
setup->wValue = cpu_to_le16(request->value);
|
||||||
setup->wIndex = cpu_to_le16(transfer->index);
|
setup->wIndex = cpu_to_le16(request->index);
|
||||||
setup->wLength = cpu_to_le16(transfer->length);
|
setup->wLength = cpu_to_le16(request->length);
|
||||||
|
|
||||||
if ((transfer->requesttype & 0x80) == LIBUSB_ENDPOINT_OUT)
|
if ((request->requesttype & 0x80) == LIBUSB_ENDPOINT_OUT)
|
||||||
memcpy(urbdata + sizeof(struct libusb_ctrl_setup), transfer->data,
|
memcpy(urbdata + sizeof(struct libusb_control_setup), request->data,
|
||||||
transfer->length);
|
request->length);
|
||||||
|
|
||||||
urbh->urb_type = USB_URB_TYPE_CONTROL;
|
transfer->urb_type = USB_URB_TYPE_CONTROL;
|
||||||
urbh->buffer = urbdata;
|
transfer->buffer = urbdata;
|
||||||
urbh->transfer_len = urbdata_length;
|
transfer->transfer_len = urbdata_length;
|
||||||
|
|
||||||
r = submit_urb(devh, urbh);
|
r = submit_transfer(devh, transfer);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
free(urbh);
|
free(transfer);
|
||||||
free(urbdata);
|
free(urbdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return urbh;
|
return transfer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct libusb_urb_handle *submit_bulk_transfer(
|
static struct libusb_transfer *submit_bulk_transfer(
|
||||||
struct libusb_dev_handle *devh, struct libusb_bulk_transfer *transfer,
|
struct libusb_dev_handle *devh,
|
||||||
|
struct libusb_bulk_transfer_request *request,
|
||||||
libusb_bulk_cb_fn callback, void *user_data, unsigned int timeout,
|
libusb_bulk_cb_fn callback, void *user_data, unsigned int timeout,
|
||||||
unsigned char urbtype)
|
unsigned char urbtype)
|
||||||
{
|
{
|
||||||
struct libusb_urb_handle *urbh = malloc(sizeof(*urbh));
|
struct libusb_transfer *transfer = malloc(sizeof(*transfer));
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
usbi_dbg("length %d timeout %d", transfer->length, timeout);
|
usbi_dbg("length %d timeout %d", request->length, timeout);
|
||||||
|
|
||||||
if (!urbh)
|
if (!transfer)
|
||||||
return NULL;
|
return NULL;
|
||||||
memset(urbh, 0, sizeof(*urbh));
|
memset(transfer, 0, sizeof(*transfer));
|
||||||
r = calculate_timeout(urbh, timeout);
|
r = calculate_timeout(transfer, timeout);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
free(urbh);
|
free(transfer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
urbh->devh = devh;
|
transfer->devh = devh;
|
||||||
urbh->callback = callback;
|
transfer->callback = callback;
|
||||||
urbh->user_data = user_data;
|
transfer->user_data = user_data;
|
||||||
urbh->flags |= LIBUSB_URBH_DATA_BELONGS_TO_USER;
|
transfer->flags |= USBI_TRANSFER_DATA_BELONGS_TO_USER;
|
||||||
urbh->endpoint = transfer->endpoint;
|
transfer->endpoint = request->endpoint;
|
||||||
urbh->urb_type = urbtype;
|
transfer->urb_type = urbtype;
|
||||||
urbh->buffer = transfer->data;
|
transfer->buffer = request->data;
|
||||||
urbh->transfer_len = transfer->length;
|
transfer->transfer_len = request->length;
|
||||||
|
|
||||||
r = submit_urb(devh, urbh);
|
r = submit_transfer(devh, transfer);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
free(urbh);
|
free(transfer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return urbh;
|
return transfer;
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORTED struct libusb_urb_handle *libusb_async_bulk_transfer(
|
API_EXPORTED struct libusb_transfer *libusb_async_bulk_transfer(
|
||||||
struct libusb_dev_handle *devh, struct libusb_bulk_transfer *transfer,
|
struct libusb_dev_handle *devh,
|
||||||
|
struct libusb_bulk_transfer_request *request,
|
||||||
libusb_bulk_cb_fn callback, void *user_data, unsigned int timeout)
|
libusb_bulk_cb_fn callback, void *user_data, unsigned int timeout)
|
||||||
{
|
{
|
||||||
return submit_bulk_transfer(devh, transfer, callback, user_data, timeout,
|
return submit_bulk_transfer(devh, request, callback, user_data, timeout,
|
||||||
USB_URB_TYPE_BULK);
|
USB_URB_TYPE_BULK);
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORTED struct libusb_urb_handle *libusb_async_interrupt_transfer(
|
API_EXPORTED struct libusb_transfer *libusb_async_interrupt_transfer(
|
||||||
struct libusb_dev_handle *devh, struct libusb_bulk_transfer *transfer,
|
struct libusb_dev_handle *devh,
|
||||||
libusb_bulk_cb_fn callback, void *user_data, unsigned int timeout)
|
struct libusb_bulk_transfer_request *request, libusb_bulk_cb_fn callback,
|
||||||
|
void *user_data, unsigned int timeout)
|
||||||
{
|
{
|
||||||
return submit_bulk_transfer(devh, transfer, callback, user_data, timeout,
|
return submit_bulk_transfer(devh, request, callback, user_data, timeout,
|
||||||
USB_URB_TYPE_INTERRUPT);
|
USB_URB_TYPE_INTERRUPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORTED int libusb_urb_handle_cancel(struct libusb_dev_handle *devh,
|
API_EXPORTED int libusb_transfer_cancel(struct libusb_dev_handle *devh,
|
||||||
struct libusb_urb_handle *urbh)
|
struct libusb_transfer *transfer)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
usbi_dbg("");
|
usbi_dbg("");
|
||||||
r = ioctl(devh->fd, IOCTL_USB_DISCARDURB, &urbh->urb);
|
r = ioctl(devh->fd, IOCTL_USB_DISCARDURB, &transfer->urb);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
usbi_err("cancel urb failed error %d", r);
|
usbi_err("cancel transfer failed error %d", r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORTED int libusb_urb_handle_cancel_sync(struct libusb_dev_handle *devh,
|
API_EXPORTED int libusb_transfer_cancel_sync(struct libusb_dev_handle *devh,
|
||||||
struct libusb_urb_handle *urbh)
|
struct libusb_transfer *transfer)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
usbi_dbg("");
|
usbi_dbg("");
|
||||||
r = ioctl(devh->fd, IOCTL_USB_DISCARDURB, &urbh->urb);
|
r = ioctl(devh->fd, IOCTL_USB_DISCARDURB, &transfer->urb);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
usbi_err("cancel urb failed error %d", r);
|
usbi_err("cancel transfer failed error %d", r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
urbh->flags |= LIBUSB_URBH_SYNC_CANCELLED;
|
transfer->flags |= USBI_TRANSFER_SYNC_CANCELLED;
|
||||||
while (urbh->flags & LIBUSB_URBH_SYNC_CANCELLED) {
|
while (transfer->flags & USBI_TRANSFER_SYNC_CANCELLED) {
|
||||||
r = libusb_poll();
|
r = libusb_poll();
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
@ -282,57 +286,61 @@ API_EXPORTED int libusb_urb_handle_cancel_sync(struct libusb_dev_handle *devh,
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_transfer_completion(struct libusb_dev_handle *devh,
|
int handle_transfer_completion(struct libusb_dev_handle *devh,
|
||||||
struct libusb_urb_handle *urbh, enum libusb_urb_cb_status status)
|
struct libusb_transfer *transfer, enum libusb_transfer_status status)
|
||||||
{
|
{
|
||||||
struct usb_urb *urb = &urbh->urb;
|
struct usb_urb *urb = &transfer->urb;
|
||||||
|
|
||||||
if (status == FP_URB_SILENT_COMPLETION)
|
if (status == LIBUSB_TRANSFER_SILENT_COMPLETION)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (urb->type == USB_URB_TYPE_CONTROL) {
|
if (transfer->urb_type == USB_URB_TYPE_CONTROL) {
|
||||||
libusb_ctrl_cb_fn callback = urbh->callback;
|
libusb_control_cb_fn callback = transfer->callback;
|
||||||
if (callback)
|
if (callback)
|
||||||
callback(devh, urbh, status, urb->buffer,
|
callback(devh, transfer, status, urb->buffer,
|
||||||
urb->buffer + sizeof(struct libusb_ctrl_setup), urbh->transferred,
|
urb->buffer + sizeof(struct libusb_control_setup),
|
||||||
urbh->user_data);
|
transfer->transferred, transfer->user_data);
|
||||||
} else if (urb->type == USB_URB_TYPE_BULK ||
|
} else if (urb->type == USB_URB_TYPE_BULK ||
|
||||||
urb->type == USB_URB_TYPE_INTERRUPT) {
|
urb->type == USB_URB_TYPE_INTERRUPT) {
|
||||||
libusb_bulk_cb_fn callback = urbh->callback;
|
libusb_bulk_cb_fn callback = transfer->callback;
|
||||||
if (callback)
|
if (callback)
|
||||||
callback(devh, urbh, status, urbh->endpoint, urbh->transfer_len,
|
callback(devh, transfer, status, transfer->endpoint,
|
||||||
urbh->buffer, urbh->transferred, urbh->user_data);
|
transfer->transfer_len, transfer->buffer,
|
||||||
|
transfer->transferred, transfer->user_data);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_transfer_cancellation(struct libusb_dev_handle *devh,
|
static int handle_transfer_cancellation(struct libusb_dev_handle *devh,
|
||||||
struct libusb_urb_handle *urbh)
|
struct libusb_transfer *transfer)
|
||||||
{
|
{
|
||||||
/* if the URB is being cancelled synchronously, raise cancellation
|
/* if the URB is being cancelled synchronously, raise cancellation
|
||||||
* completion event by unsetting flag, and ensure that user callback does
|
* completion event by unsetting flag, and ensure that user callback does
|
||||||
* not get called.
|
* not get called.
|
||||||
*/
|
*/
|
||||||
if (urbh->flags & LIBUSB_URBH_SYNC_CANCELLED) {
|
if (transfer->flags & USBI_TRANSFER_SYNC_CANCELLED) {
|
||||||
urbh->flags &= ~LIBUSB_URBH_SYNC_CANCELLED;
|
transfer->flags &= ~USBI_TRANSFER_SYNC_CANCELLED;
|
||||||
usbi_dbg("detected sync. cancel");
|
usbi_dbg("detected sync. cancel");
|
||||||
return handle_transfer_completion(devh, urbh, FP_URB_SILENT_COMPLETION);
|
return handle_transfer_completion(devh, transfer,
|
||||||
|
LIBUSB_TRANSFER_SILENT_COMPLETION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if the URB was cancelled due to timeout, report timeout to the user */
|
/* if the URB was cancelled due to timeout, report timeout to the user */
|
||||||
if (urbh->flags & LIBUSB_URBH_TIMED_OUT) {
|
if (transfer->flags & USBI_TRANSFER_TIMED_OUT) {
|
||||||
usbi_dbg("detected timeout cancellation");
|
usbi_dbg("detected timeout cancellation");
|
||||||
return handle_transfer_completion(devh, urbh, FP_URB_TIMEOUT);
|
return handle_transfer_completion(devh, transfer,
|
||||||
|
LIBUSB_TRANSFER_TIMED_OUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* otherwise its a normal async cancel */
|
/* otherwise its a normal async cancel */
|
||||||
return handle_transfer_completion(devh, urbh, FP_URB_CANCELLED);
|
return handle_transfer_completion(devh, transfer,
|
||||||
|
LIBUSB_TRANSFER_CANCELLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int reap_for_devh(struct libusb_dev_handle *devh)
|
static int reap_for_devh(struct libusb_dev_handle *devh)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
struct usb_urb *urb;
|
struct usb_urb *urb;
|
||||||
struct libusb_urb_handle *urbh;
|
struct libusb_transfer *transfer;
|
||||||
int trf_requested;
|
int trf_requested;
|
||||||
|
|
||||||
r = ioctl(devh->fd, IOCTL_USB_REAPURBNDELAY, &urb);
|
r = ioctl(devh->fd, IOCTL_USB_REAPURBNDELAY, &urb);
|
||||||
|
@ -343,45 +351,47 @@ static int reap_for_devh(struct libusb_dev_handle *devh)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
urbh = container_of(urb, struct libusb_urb_handle, urb);
|
transfer = container_of(urb, struct libusb_transfer, urb);
|
||||||
|
|
||||||
usbi_dbg("urb type=%d status=%d transferred=%d", urb->type, urb->status,
|
usbi_dbg("urb type=%d status=%d transferred=%d", urb->type, urb->status,
|
||||||
urb->actual_length);
|
urb->actual_length);
|
||||||
list_del(&urbh->list);
|
list_del(&transfer->list);
|
||||||
|
|
||||||
if (urb->status == -2)
|
if (urb->status == -2)
|
||||||
return handle_transfer_cancellation(devh, urbh);
|
return handle_transfer_cancellation(devh, transfer);
|
||||||
/* FIXME: research what other status codes may exist */
|
/* FIXME: research what other status codes may exist */
|
||||||
if (urb->status != 0)
|
if (urb->status != 0)
|
||||||
usbi_warn("unrecognised urb status %d", urb->status);
|
usbi_warn("unrecognised urb status %d", urb->status);
|
||||||
|
|
||||||
/* determine how much data was asked for */
|
/* determine how much data was asked for */
|
||||||
trf_requested = MIN(urbh->transfer_len - urbh->transferred,
|
trf_requested = MIN(transfer->transfer_len - transfer->transferred,
|
||||||
MAX_URB_BUFFER_LENGTH);
|
MAX_URB_BUFFER_LENGTH);
|
||||||
|
|
||||||
urbh->transferred += urb->actual_length;
|
transfer->transferred += urb->actual_length;
|
||||||
|
|
||||||
/* if we were provided less data than requested, then our transfer is
|
/* if we were provided less data than requested, then our transfer is
|
||||||
* done */
|
* done */
|
||||||
if (urb->actual_length < trf_requested) {
|
if (urb->actual_length < trf_requested) {
|
||||||
usbi_dbg("less data than requested (%d/%d) --> all done",
|
usbi_dbg("less data than requested (%d/%d) --> all done",
|
||||||
urb->actual_length, trf_requested);
|
urb->actual_length, trf_requested);
|
||||||
return handle_transfer_completion(devh, urbh, FP_URB_COMPLETED);
|
return handle_transfer_completion(devh, transfer,
|
||||||
|
LIBUSB_TRANSFER_COMPLETED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we've transferred all data, we're done */
|
/* if we've transferred all data, we're done */
|
||||||
if (urbh->transferred == urbh->transfer_len) {
|
if (transfer->transferred == transfer->transfer_len) {
|
||||||
usbi_dbg("transfer complete --> all done");
|
usbi_dbg("transfer complete --> all done");
|
||||||
return handle_transfer_completion(devh, urbh, FP_URB_COMPLETED);
|
return handle_transfer_completion(devh, transfer,
|
||||||
|
LIBUSB_TRANSFER_COMPLETED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* otherwise, we have more data to transfer */
|
/* otherwise, we have more data to transfer */
|
||||||
usbi_dbg("more data to transfer...");
|
usbi_dbg("more data to transfer...");
|
||||||
memset(urb, 0, sizeof(*urb));
|
memset(urb, 0, sizeof(*urb));
|
||||||
return submit_urb(devh, urbh);
|
return submit_transfer(devh, transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_timeout(struct libusb_urb_handle *urbh)
|
static void handle_timeout(struct libusb_transfer *transfer)
|
||||||
{
|
{
|
||||||
/* handling timeouts is tricky, as we may race with the kernel: we may
|
/* handling timeouts is tricky, as we may race with the kernel: we may
|
||||||
* detect a timeout racing with the condition that the urb has actually
|
* detect a timeout racing with the condition that the urb has actually
|
||||||
|
@ -391,8 +401,8 @@ static void handle_timeout(struct libusb_urb_handle *urbh)
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
|
||||||
urbh->flags |= LIBUSB_URBH_TIMED_OUT;
|
transfer->flags |= USBI_TRANSFER_TIMED_OUT;
|
||||||
r = libusb_urb_handle_cancel(urbh->devh, urbh);
|
r = libusb_transfer_cancel(transfer->devh, transfer);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
usbi_warn("async cancel failed %d errno=%d", r, errno);
|
usbi_warn("async cancel failed %d errno=%d", r, errno);
|
||||||
}
|
}
|
||||||
|
@ -401,10 +411,10 @@ static int handle_timeouts(void)
|
||||||
{
|
{
|
||||||
struct timespec systime_ts;
|
struct timespec systime_ts;
|
||||||
struct timeval systime;
|
struct timeval systime;
|
||||||
struct libusb_urb_handle *urbh;
|
struct libusb_transfer *transfer;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (list_empty(&flying_urbs))
|
if (list_empty(&flying_transfers))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* get current time */
|
/* get current time */
|
||||||
|
@ -414,27 +424,27 @@ static int handle_timeouts(void)
|
||||||
|
|
||||||
TIMESPEC_TO_TIMEVAL(&systime, &systime_ts);
|
TIMESPEC_TO_TIMEVAL(&systime, &systime_ts);
|
||||||
|
|
||||||
/* iterate through flying urbs list, finding all urbs that have expired
|
/* iterate through flying transfers list, finding all transfers that
|
||||||
* timeouts */
|
* have expired timeouts */
|
||||||
list_for_each_entry(urbh, &flying_urbs, list) {
|
list_for_each_entry(transfer, &flying_transfers, list) {
|
||||||
struct timeval *cur_tv = &urbh->timeout;
|
struct timeval *cur_tv = &transfer->timeout;
|
||||||
|
|
||||||
/* if we've reached urbs of infinite timeout, we're all done */
|
/* if we've reached transfers of infinite timeout, we're all done */
|
||||||
if (!timerisset(cur_tv))
|
if (!timerisset(cur_tv))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* ignore timeouts we've already handled */
|
/* ignore timeouts we've already handled */
|
||||||
if (urbh->flags & LIBUSB_URBH_TIMED_OUT)
|
if (transfer->flags & USBI_TRANSFER_TIMED_OUT)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* if urb has non-expired timeout, nothing more to do */
|
/* if transfer has non-expired timeout, nothing more to do */
|
||||||
if ((cur_tv->tv_sec > systime.tv_sec) ||
|
if ((cur_tv->tv_sec > systime.tv_sec) ||
|
||||||
(cur_tv->tv_sec == systime.tv_sec &&
|
(cur_tv->tv_sec == systime.tv_sec &&
|
||||||
cur_tv->tv_usec > systime.tv_usec))
|
cur_tv->tv_usec > systime.tv_usec))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* otherwise, we've got an expired timeout to handle */
|
/* otherwise, we've got an expired timeout to handle */
|
||||||
handle_timeout(urbh);
|
handle_timeout(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -516,21 +526,21 @@ API_EXPORTED int libusb_poll(void)
|
||||||
|
|
||||||
API_EXPORTED int libusb_get_next_timeout(struct timeval *tv)
|
API_EXPORTED int libusb_get_next_timeout(struct timeval *tv)
|
||||||
{
|
{
|
||||||
struct libusb_urb_handle *urbh;
|
struct libusb_transfer *transfer;
|
||||||
struct timespec cur_ts;
|
struct timespec cur_ts;
|
||||||
struct timeval cur_tv;
|
struct timeval cur_tv;
|
||||||
struct timeval *next_timeout;
|
struct timeval *next_timeout;
|
||||||
int r;
|
int r;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
|
|
||||||
if (list_empty(&flying_urbs)) {
|
if (list_empty(&flying_transfers)) {
|
||||||
usbi_dbg("no URBs, no timeout!");
|
usbi_dbg("no URBs, no timeout!");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find next urb which hasn't already been processed as timed out */
|
/* find next transfer which hasn't already been processed as timed out */
|
||||||
list_for_each_entry(urbh, &flying_urbs, list) {
|
list_for_each_entry(transfer, &flying_transfers, list) {
|
||||||
if (!(urbh->flags & LIBUSB_URBH_TIMED_OUT)) {
|
if (!(transfer->flags & USBI_TRANSFER_TIMED_OUT)) {
|
||||||
found = 1;
|
found = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -541,9 +551,9 @@ API_EXPORTED int libusb_get_next_timeout(struct timeval *tv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
next_timeout = &urbh->timeout;
|
next_timeout = &transfer->timeout;
|
||||||
|
|
||||||
/* no timeout for next urb */
|
/* no timeout for next transfer */
|
||||||
if (!timerisset(next_timeout)) {
|
if (!timerisset(next_timeout)) {
|
||||||
usbi_dbg("no URBs with timeouts, no timeout!");
|
usbi_dbg("no URBs with timeouts, no timeout!");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -568,20 +578,20 @@ API_EXPORTED int libusb_get_next_timeout(struct timeval *tv)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sync_ctrl_handle {
|
struct sync_ctrl_handle {
|
||||||
enum libusb_urb_cb_status status;
|
enum libusb_transfer_status status;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
int actual_length;
|
int actual_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ctrl_transfer_cb(struct libusb_dev_handle *devh,
|
static void ctrl_transfer_cb(struct libusb_dev_handle *devh,
|
||||||
struct libusb_urb_handle *urbh, enum libusb_urb_cb_status status,
|
struct libusb_transfer *transfer, enum libusb_transfer_status status,
|
||||||
struct libusb_ctrl_setup *setup, unsigned char *data, int actual_length,
|
struct libusb_control_setup *setup, unsigned char *data, int actual_length,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct sync_ctrl_handle *ctrlh = (struct sync_ctrl_handle *) user_data;
|
struct sync_ctrl_handle *ctrlh = (struct sync_ctrl_handle *) user_data;
|
||||||
usbi_dbg("actual_length=%d", actual_length);
|
usbi_dbg("actual_length=%d", actual_length);
|
||||||
|
|
||||||
if (status == FP_URB_COMPLETED) {
|
if (status == LIBUSB_TRANSFER_COMPLETED) {
|
||||||
/* copy results into user-defined buffer */
|
/* copy results into user-defined buffer */
|
||||||
if (setup->bRequestType & LIBUSB_ENDPOINT_IN)
|
if (setup->bRequestType & LIBUSB_ENDPOINT_IN)
|
||||||
memcpy(ctrlh->data, data, actual_length);
|
memcpy(ctrlh->data, data, actual_length);
|
||||||
|
@ -589,37 +599,37 @@ static void ctrl_transfer_cb(struct libusb_dev_handle *devh,
|
||||||
|
|
||||||
ctrlh->status = status;
|
ctrlh->status = status;
|
||||||
ctrlh->actual_length = actual_length;
|
ctrlh->actual_length = actual_length;
|
||||||
/* caller frees urbh */
|
/* caller frees transfer */
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORTED int libusb_control_transfer(struct libusb_dev_handle *devh,
|
API_EXPORTED int libusb_control_transfer(struct libusb_dev_handle *devh,
|
||||||
struct libusb_control_transfer *transfer, unsigned int timeout)
|
struct libusb_control_transfer_request *request, unsigned int timeout)
|
||||||
{
|
{
|
||||||
struct libusb_urb_handle *urbh;
|
struct libusb_transfer *transfer;
|
||||||
struct sync_ctrl_handle ctrlh;
|
struct sync_ctrl_handle ctrlh;
|
||||||
|
|
||||||
memset(&ctrlh, 0, sizeof(ctrlh));
|
memset(&ctrlh, 0, sizeof(ctrlh));
|
||||||
ctrlh.data = transfer->data;
|
ctrlh.data = request->data;
|
||||||
|
|
||||||
urbh = libusb_async_control_transfer(devh, transfer, ctrl_transfer_cb,
|
transfer = libusb_async_control_transfer(devh, request, ctrl_transfer_cb,
|
||||||
&ctrlh, timeout);
|
&ctrlh, timeout);
|
||||||
if (!urbh)
|
if (!transfer)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
while (!ctrlh.status) {
|
while (!ctrlh.status) {
|
||||||
int r = libusb_poll();
|
int r = libusb_poll();
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
libusb_urb_handle_cancel_sync(devh, urbh);
|
libusb_transfer_cancel_sync(devh, transfer);
|
||||||
libusb_urb_handle_free(urbh);
|
libusb_transfer_free(transfer);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
libusb_urb_handle_free(urbh);
|
libusb_transfer_free(transfer);
|
||||||
switch (ctrlh.status) {
|
switch (ctrlh.status) {
|
||||||
case FP_URB_COMPLETED:
|
case LIBUSB_TRANSFER_COMPLETED:
|
||||||
return ctrlh.actual_length;
|
return ctrlh.actual_length;
|
||||||
case FP_URB_TIMEOUT:
|
case LIBUSB_TRANSFER_TIMED_OUT:
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
default:
|
default:
|
||||||
usbi_warn("unrecognised status code %d", ctrlh.status);
|
usbi_warn("unrecognised status code %d", ctrlh.status);
|
||||||
|
@ -628,12 +638,12 @@ API_EXPORTED int libusb_control_transfer(struct libusb_dev_handle *devh,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sync_bulk_handle {
|
struct sync_bulk_handle {
|
||||||
enum libusb_urb_cb_status status;
|
enum libusb_transfer_status status;
|
||||||
int actual_length;
|
int actual_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void bulk_transfer_cb(struct libusb_dev_handle *devh,
|
static void bulk_transfer_cb(struct libusb_dev_handle *devh,
|
||||||
struct libusb_urb_handle *urbh, enum libusb_urb_cb_status status,
|
struct libusb_transfer *transfer, enum libusb_transfer_status status,
|
||||||
unsigned char endpoint, int rqlength, unsigned char *data,
|
unsigned char endpoint, int rqlength, unsigned char *data,
|
||||||
int actual_length, void *user_data)
|
int actual_length, void *user_data)
|
||||||
{
|
{
|
||||||
|
@ -641,39 +651,39 @@ static void bulk_transfer_cb(struct libusb_dev_handle *devh,
|
||||||
usbi_dbg("");
|
usbi_dbg("");
|
||||||
bulkh->status = status;
|
bulkh->status = status;
|
||||||
bulkh->actual_length = actual_length;
|
bulkh->actual_length = actual_length;
|
||||||
/* caller frees urbh */
|
/* caller frees transfer */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_sync_bulk_transfer(struct libusb_dev_handle *devh,
|
static int do_sync_bulk_transfer(struct libusb_dev_handle *devh,
|
||||||
struct libusb_bulk_transfer *transfer, int *transferred,
|
struct libusb_bulk_transfer_request *request, int *transferred,
|
||||||
unsigned int timeout, unsigned char urbtype)
|
unsigned int timeout, unsigned char urbtype)
|
||||||
{
|
{
|
||||||
struct libusb_urb_handle *urbh;
|
struct libusb_transfer *transfer;
|
||||||
struct sync_bulk_handle bulkh;
|
struct sync_bulk_handle bulkh;
|
||||||
|
|
||||||
memset(&bulkh, 0, sizeof(bulkh));
|
memset(&bulkh, 0, sizeof(bulkh));
|
||||||
|
|
||||||
urbh = submit_bulk_transfer(devh, transfer, bulk_transfer_cb, &bulkh,
|
transfer = submit_bulk_transfer(devh, request, bulk_transfer_cb, &bulkh,
|
||||||
timeout, urbtype);
|
timeout, urbtype);
|
||||||
if (!urbh)
|
if (!transfer)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
while (!bulkh.status) {
|
while (!bulkh.status) {
|
||||||
int r = libusb_poll();
|
int r = libusb_poll();
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
libusb_urb_handle_cancel_sync(devh, urbh);
|
libusb_transfer_cancel_sync(devh, transfer);
|
||||||
libusb_urb_handle_free(urbh);
|
libusb_transfer_free(transfer);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*transferred = bulkh.actual_length;
|
*transferred = bulkh.actual_length;
|
||||||
libusb_urb_handle_free(urbh);
|
libusb_transfer_free(transfer);
|
||||||
|
|
||||||
switch (bulkh.status) {
|
switch (bulkh.status) {
|
||||||
case FP_URB_COMPLETED:
|
case LIBUSB_TRANSFER_COMPLETED:
|
||||||
return 0;
|
return 0;
|
||||||
case FP_URB_TIMEOUT:
|
case LIBUSB_TRANSFER_TIMED_OUT:
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
default:
|
default:
|
||||||
usbi_warn("unrecognised status code %d", bulkh.status);
|
usbi_warn("unrecognised status code %d", bulkh.status);
|
||||||
|
@ -682,29 +692,29 @@ static int do_sync_bulk_transfer(struct libusb_dev_handle *devh,
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORTED int libusb_interrupt_transfer(struct libusb_dev_handle *devh,
|
API_EXPORTED int libusb_interrupt_transfer(struct libusb_dev_handle *devh,
|
||||||
struct libusb_bulk_transfer *transfer, int *transferred,
|
struct libusb_bulk_transfer_request *request, int *transferred,
|
||||||
unsigned int timeout)
|
unsigned int timeout)
|
||||||
{
|
{
|
||||||
return do_sync_bulk_transfer(devh, transfer, transferred, timeout,
|
return do_sync_bulk_transfer(devh, request, transferred, timeout,
|
||||||
USB_URB_TYPE_INTERRUPT);
|
USB_URB_TYPE_INTERRUPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORTED int libusb_bulk_transfer(struct libusb_dev_handle *devh,
|
API_EXPORTED int libusb_bulk_transfer(struct libusb_dev_handle *devh,
|
||||||
struct libusb_bulk_transfer *transfer, int *transferred,
|
struct libusb_bulk_transfer_request *request, int *transferred,
|
||||||
unsigned int timeout)
|
unsigned int timeout)
|
||||||
{
|
{
|
||||||
return do_sync_bulk_transfer(devh, transfer, transferred, timeout,
|
return do_sync_bulk_transfer(devh, request, transferred, timeout,
|
||||||
USB_URB_TYPE_BULK);
|
USB_URB_TYPE_BULK);
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORTED void libusb_urb_handle_free(struct libusb_urb_handle *urbh)
|
API_EXPORTED void libusb_transfer_free(struct libusb_transfer *transfer)
|
||||||
{
|
{
|
||||||
if (!urbh)
|
if (!transfer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!(urbh->flags & LIBUSB_URBH_DATA_BELONGS_TO_USER))
|
if (!(transfer->flags & USBI_TRANSFER_DATA_BELONGS_TO_USER))
|
||||||
free(urbh->urb.buffer);
|
free(transfer->urb.buffer);
|
||||||
free(urbh);
|
free(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORTED void libusb_set_pollfd_notifiers(libusb_pollfd_added_cb added_cb,
|
API_EXPORTED void libusb_set_pollfd_notifiers(libusb_pollfd_added_cb added_cb,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Public libusb header file
|
* Public libusb header file
|
||||||
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
|
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
|
||||||
* Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
|
* Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
|
@ -170,7 +170,7 @@ struct libusb_config_descriptor {
|
||||||
|
|
||||||
/* off-the-wire structures */
|
/* off-the-wire structures */
|
||||||
|
|
||||||
struct libusb_ctrl_setup {
|
struct libusb_control_setup {
|
||||||
uint8_t bRequestType;
|
uint8_t bRequestType;
|
||||||
uint8_t bRequest;
|
uint8_t bRequest;
|
||||||
uint16_t wValue;
|
uint16_t wValue;
|
||||||
|
@ -186,17 +186,17 @@ typedef struct libusb_device libusb_device;
|
||||||
struct libusb_dev_handle;
|
struct libusb_dev_handle;
|
||||||
typedef struct libusb_dev_handle libusb_dev_handle;
|
typedef struct libusb_dev_handle libusb_dev_handle;
|
||||||
|
|
||||||
struct libusb_urb_handle;
|
struct libusb_transfer;
|
||||||
typedef struct libusb_urb_handle libusb_urb_handle;
|
typedef struct libusb_transfer libusb_transfer;
|
||||||
|
|
||||||
enum libusb_urb_cb_status {
|
enum libusb_transfer_status {
|
||||||
FP_URB_SILENT_COMPLETION = 0,
|
LIBUSB_TRANSFER_SILENT_COMPLETION = 0,
|
||||||
FP_URB_COMPLETED,
|
LIBUSB_TRANSFER_COMPLETED,
|
||||||
FP_URB_TIMEOUT,
|
LIBUSB_TRANSFER_TIMED_OUT,
|
||||||
FP_URB_CANCELLED,
|
LIBUSB_TRANSFER_CANCELLED,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct libusb_control_transfer {
|
struct libusb_control_transfer_request {
|
||||||
uint8_t requesttype;
|
uint8_t requesttype;
|
||||||
uint8_t request;
|
uint8_t request;
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
|
@ -205,19 +205,21 @@ struct libusb_control_transfer {
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*libusb_ctrl_cb_fn)(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
typedef void (*libusb_control_cb_fn)(libusb_dev_handle *devh,
|
||||||
enum libusb_urb_cb_status status, struct libusb_ctrl_setup *setup,
|
libusb_transfer *transfer, enum libusb_transfer_status status,
|
||||||
unsigned char *data, int actual_length, void *user_data);
|
struct libusb_control_setup *setup, unsigned char *data,
|
||||||
|
int actual_length, void *user_data);
|
||||||
|
|
||||||
struct libusb_bulk_transfer {
|
struct libusb_bulk_transfer_request {
|
||||||
unsigned char endpoint;
|
unsigned char endpoint;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
int length;
|
int length;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*libusb_bulk_cb_fn)(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
typedef void (*libusb_bulk_cb_fn)(libusb_dev_handle *devh,
|
||||||
enum libusb_urb_cb_status status, unsigned char endpoint,
|
libusb_transfer *transfer, enum libusb_transfer_status status,
|
||||||
int rqlength, unsigned char *data, int actual_length, void *user_data);
|
unsigned char endpoint, int rqlength, unsigned char *data,
|
||||||
|
int actual_length, void *user_data);
|
||||||
|
|
||||||
int libusb_init(void);
|
int libusb_init(void);
|
||||||
void libusb_exit(void);
|
void libusb_exit(void);
|
||||||
|
@ -240,30 +242,30 @@ libusb_dev_handle *libusb_open_device_with_vid_pid(uint16_t vendor_id,
|
||||||
|
|
||||||
/* async I/O */
|
/* async I/O */
|
||||||
|
|
||||||
libusb_urb_handle *libusb_async_control_transfer(libusb_dev_handle *devh,
|
libusb_transfer *libusb_async_control_transfer(libusb_dev_handle *devh,
|
||||||
struct libusb_control_transfer *transfer, libusb_ctrl_cb_fn callback,
|
struct libusb_control_transfer_request *request,
|
||||||
|
libusb_control_cb_fn callback, void *user_data, unsigned int timeout);
|
||||||
|
libusb_transfer *libusb_async_bulk_transfer(libusb_dev_handle *devh,
|
||||||
|
struct libusb_bulk_transfer_request *request, libusb_bulk_cb_fn callback,
|
||||||
void *user_data, unsigned int timeout);
|
void *user_data, unsigned int timeout);
|
||||||
libusb_urb_handle *libusb_async_bulk_transfer(libusb_dev_handle *devh,
|
libusb_transfer *libusb_async_interrupt_transfer(libusb_dev_handle *devh,
|
||||||
struct libusb_bulk_transfer *transfer, libusb_bulk_cb_fn callback,
|
struct libusb_bulk_transfer_request *request, libusb_bulk_cb_fn callback,
|
||||||
void *user_data, unsigned int timeout);
|
|
||||||
libusb_urb_handle *libusb_async_interrupt_transfer(libusb_dev_handle *devh,
|
|
||||||
struct libusb_bulk_transfer *transfer, libusb_bulk_cb_fn callback,
|
|
||||||
void *user_data, unsigned int timeout);
|
void *user_data, unsigned int timeout);
|
||||||
|
|
||||||
int libusb_urb_handle_cancel(libusb_dev_handle *devh, libusb_urb_handle *urbh);
|
int libusb_transfer_cancel(libusb_dev_handle *devh, libusb_transfer *transfer);
|
||||||
int libusb_urb_handle_cancel_sync(libusb_dev_handle *devh,
|
int libusb_transfer_cancel_sync(libusb_dev_handle *devh,
|
||||||
libusb_urb_handle *urbh);
|
libusb_transfer *transfer);
|
||||||
void libusb_urb_handle_free(libusb_urb_handle *urbh);
|
void libusb_transfer_free(libusb_transfer *transfer);
|
||||||
|
|
||||||
/* sync I/O */
|
/* sync I/O */
|
||||||
|
|
||||||
int libusb_control_transfer(libusb_dev_handle *devh,
|
int libusb_control_transfer(libusb_dev_handle *devh,
|
||||||
struct libusb_control_transfer *transfer, unsigned int timeout);
|
struct libusb_control_transfer_request *request, unsigned int timeout);
|
||||||
int libusb_bulk_transfer(libusb_dev_handle *devh,
|
int libusb_bulk_transfer(libusb_dev_handle *devh,
|
||||||
struct libusb_bulk_transfer *transfer, int *transferred,
|
struct libusb_bulk_transfer_request *request, int *transferred,
|
||||||
unsigned int timeout);
|
unsigned int timeout);
|
||||||
int libusb_interrupt_transfer(libusb_dev_handle *devh,
|
int libusb_interrupt_transfer(libusb_dev_handle *devh,
|
||||||
struct libusb_bulk_transfer *transfer, int *transferred,
|
struct libusb_bulk_transfer_request *request, int *transferred,
|
||||||
unsigned int timeout);
|
unsigned int timeout);
|
||||||
|
|
||||||
/* polling and timeouts */
|
/* polling and timeouts */
|
||||||
|
|
|
@ -157,16 +157,16 @@ struct libusb_dev_handle {
|
||||||
int fd;
|
int fd;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum libusb_urb_type {
|
enum libusb_transfer_type {
|
||||||
LIBUSB_URB_CONTROL,
|
LIBUSB_TRANSFER_CONTROL,
|
||||||
LIBUSB_URB_BULK,
|
LIBUSB_TRANSFER_BULK,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LIBUSB_URBH_DATA_BELONGS_TO_USER (1<<0)
|
#define USBI_TRANSFER_DATA_BELONGS_TO_USER (1<<0)
|
||||||
#define LIBUSB_URBH_SYNC_CANCELLED (1<<1)
|
#define USBI_TRANSFER_SYNC_CANCELLED (1<<1)
|
||||||
#define LIBUSB_URBH_TIMED_OUT (1<<2)
|
#define USBI_TRANSFER_TIMED_OUT (1<<2)
|
||||||
|
|
||||||
struct libusb_urb_handle {
|
struct libusb_transfer {
|
||||||
struct libusb_dev_handle *devh;
|
struct libusb_dev_handle *devh;
|
||||||
struct usb_urb urb;
|
struct usb_urb urb;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue