PERFORCE change 165790 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Tue Jul 7 20:41:12 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=165790
Change 165790 by hselasky at hselasky_laptop001 on 2009/07/07 20:40:23
LibUSB v1.0 improvements:
- fix some range checks
- checking for TAILQ_EMPTY() before TAILQ_FOREACH() is
Linuxism and not required for the BSD platform.
- libusb_control_transfer() can use already existing libusb20_dev_request_sync().
- fix some return values.
- more to come ...
Affected files ...
.. //depot/projects/usb/src/lib/libusb/libusb10_io.c#3 edit
Differences ...
==== //depot/projects/usb/src/lib/libusb/libusb10_io.c#3 (text+ko) ====
@@ -269,9 +269,7 @@
pthread_mutex_unlock(&ctx->pollfds_lock);
- timeout = (tv->tv_sec * 1000) + (tv->tv_usec / 1000);
- if (tv->tv_usec % 1000)
- timeout++;
+ timeout = (tv->tv_sec * 1000) + ((tv->tv_usec + 999) / 1000);
ret = poll(fds, nfds, timeout);
if (ret == 0)
@@ -471,7 +469,7 @@
ts.tv_sec = tv->tv_sec;
ts.tv_nsec = tv->tv_usec * 1000;
- if (ts.tv_nsec > 1000000000) {
+ if (ts.tv_nsec >= 1000000000) {
ts.tv_nsec -= 1000000000;
ts.tv_sec++;
}
@@ -577,11 +575,6 @@
found = 0;
pthread_mutex_lock(&ctx->flying_transfers_lock);
- if (TAILQ_EMPTY(&ctx->flying_transfers)) {
- pthread_mutex_unlock(&ctx->flying_transfers_lock);
- return (0);
- }
-
TAILQ_FOREACH(xfer, &ctx->flying_transfers, list) {
if (!(xfer->flags & USB_TIMED_OUT)) {
found = 1;
@@ -628,7 +621,7 @@
}
struct libusb_pollfd **
-libusb_get_pollfds(libusb_context * ctx)
+libusb_get_pollfds(libusb_context *ctx)
{
struct usb_pollfd *pollfd;
libusb_pollfd **ret;
@@ -660,106 +653,61 @@
/* Synchronous device I/O */
-static void ctrl_tr_cb(struct libusb_transfer *transfer)
-{
- libusb_context *ctx;
- int *complet;
-
- ctx = NULL;
- GET_CONTEXT(ctx);
- DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "CALLBACK ENTER");
-
- complet = transfer->user_data;
- *complet = 1;
-}
-
int
libusb_control_transfer(libusb_device_handle * devh,
uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
unsigned char *data, uint16_t wLength, unsigned int timeout)
{
- struct libusb_transfer *xfer;
- struct libusb_control_setup *ctr;
- libusb_context *ctx;
- unsigned char *buff;
- int complet;
- int ret;
+ struct LIBUSB20_CONTROL_SETUP_DECODED req;
+ int err;
+ uint16_t actlen;
- ctx = devh->dev->ctx;
- GET_CONTEXT(ctx);
- DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_control_transfer enter");
+ if (devh == NULL)
+ return (LIBUSB_ERROR_INVALID_PARAM);
- if (devh == NULL || data == NULL)
- return (LIBUSB_ERROR_NO_MEM);
+ if ((wLength != 0) && (data == NULL))
+ return (LIBUSB_ERROR_INVALID_PARAM);
- xfer = libusb_alloc_transfer(0);
- if (xfer == NULL)
- return (LIBUSB_ERROR_NO_MEM);
+ LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req);
- buff = malloc(sizeof(libusb_control_setup) + wLength);
- if (buff == NULL) {
- libusb_free_transfer(xfer);
- return (LIBUSB_ERROR_NO_MEM);
- }
+ req.bmRequestType = bmRequestType;
+ req.bRequest = bRequest;
+ req.wValue = wValue;
+ req.wIndex = wIndex;
+ req.wLength = wLength;
- ctr = (libusb_control_setup *)buff;
- ctr->bmRequestType = bmRequestType;
- ctr->bRequest = bRequest;
- ctr->wValue = wValue;
- ctr->wIndex = wIndex;
- ctr->wLength = wLength;
- if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT)
- memcpy(buff + sizeof(libusb_control_setup), data, wLength);
+ err = libusb20_dev_request_sync(devh->os_priv, &req, data,
+ &actlen, timeout, 0);
- xfer->dev_handle = devh;
- xfer->endpoint = 0;
- xfer->type = LIBUSB_TRANSFER_TYPE_CONTROL;
- xfer->timeout = timeout;
- xfer->buffer = buff;
- xfer->length = sizeof(libusb_control_setup) + wLength;
- xfer->user_data = &complet;
- xfer->callback = ctrl_tr_cb;
- xfer->flags = LIBUSB_TRANSFER_FREE_TRANSFER;
- complet = 0;
+ if (err == LIBUSB20_ERROR_PIPE)
+ return (LIBUSB_ERROR_PIPE);
+ else if (err == LIBUSB20_ERROR_TIMEOUT)
+ return (LIBUSB_ERROR_TIMEOUT);
+ else if (err)
+ return (LIBUSB_ERROR_NO_DEVICE);
- if ((ret = libusb_submit_transfer(xfer)) < 0) {
- libusb_free_transfer(xfer);
- return (ret);
- }
+ return (actlen);
+}
- while (complet == 0)
- if ((ret = libusb_handle_events(ctx)) < 0) {
- libusb_cancel_transfer(xfer);
- while (complet == 0)
- if (libusb_handle_events(ctx) < 0) {
- break;
- }
- libusb_free_transfer(xfer);
- return (ret);
- }
+static void
+do_transfer_cb(struct libusb_transfer *transfer)
+{
+ libusb_context *ctx;
+ int *pdone;
+
+ ctx = NULL;
+ GET_CONTEXT(ctx);
+ DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "sync I/O done");
- if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
- memcpy(data, buff + sizeof(libusb_control_setup), wLength);
-
- switch (xfer->status) {
- case LIBUSB_TRANSFER_COMPLETED:
- ret = xfer->actual_length;
- break;
- case LIBUSB_TRANSFER_TIMED_OUT:
- case LIBUSB_TRANSFER_STALL:
- case LIBUSB_TRANSFER_NO_DEVICE:
- ret = xfer->status;
- break;
- default:
- ret = LIBUSB_ERROR_OTHER;
- }
- libusb_free_transfer(xfer);
-
- DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_control_transfer leave");
- return (ret);
+ pdone = transfer->user_data;
+ *pdone = 1;
}
+/*
+ * TODO: Replace the following function. Allocating and freeing on a
+ * per-transfer basis is slow. --HPS
+ */
static int
do_transfer(struct libusb_device_handle *devh,
unsigned char endpoint, unsigned char *data, int length,
@@ -767,11 +715,14 @@
{
struct libusb_transfer *xfer;
libusb_context *ctx;
- int complet;
+ volatile int complet;
int ret;
- if (devh == NULL || data == NULL)
- return (LIBUSB_ERROR_NO_MEM);
+ if (devh == NULL)
+ return (LIBUSB_ERROR_INVALID_PARAM);
+
+ if ((length != 0) && (data == NULL))
+ return (LIBUSB_ERROR_INVALID_PARAM);
xfer = libusb_alloc_transfer(0);
if (xfer == NULL)
@@ -786,8 +737,8 @@
xfer->timeout = timeout;
xfer->buffer = data;
xfer->length = length;
- xfer->user_data = &complet;
- xfer->callback = ctrl_tr_cb;
+ xfer->user_data = (void *)&complet;
+ xfer->callback = do_transfer_cb;
complet = 0;
DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "SUBMIT_TRANSFER");
@@ -810,19 +761,28 @@
}
*transferred = xfer->actual_length;
+
DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "xfer->status %i", xfer->status);
+
switch (xfer->status) {
case LIBUSB_TRANSFER_COMPLETED:
- ret = xfer->actual_length;
+ ret = 0;
break;
case LIBUSB_TRANSFER_TIMED_OUT:
+ ret = LIBUSB_ERROR_TIMEOUT;
+ break;
case LIBUSB_TRANSFER_OVERFLOW:
+ ret = LIBUSB_ERROR_OVERFLOW;
+ break;
case LIBUSB_TRANSFER_STALL:
+ ret = LIBUSB_ERROR_PIPE;
+ break;
case LIBUSB_TRANSFER_NO_DEVICE:
- ret = xfer->status;
+ ret = LIBUSB_ERROR_NO_DEVICE;
break;
default:
ret = LIBUSB_ERROR_OTHER;
+ break;
}
libusb_free_transfer(xfer);
More information about the p4-projects
mailing list