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