PERFORCE change 166052 for review

Hans Petter Selasky hselasky at FreeBSD.org
Mon Jul 13 21:53:15 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=166052

Change 166052 by hselasky at hselasky_laptop001 on 2009/07/13 21:52:33

	
	LibUSB v1.0 - first pass improving the v1.0 API
	and fixing several compliance issues. Reduce the
	number of locks to simplify the understanding of
	the library and chance of LOR's. Rework the USB
	transfer handling part so that we can queue
	multiple transfers and also that we get
	double buffering. Add extra checking when
	stopping a transfers. Make sure mutexes and
	condition variables gets destroyed to avoid
	resource leakage. Make sure internal structures
	like device handle and device are not exposed
	through libusb.h, because they might be subject
	to change.
	
	There will be a followup commit tomorrow getting
	the rest of the libUSB v1.0 code in line. Compiling
	libusb is currently broken unless the libusb10*.c files
	are removed from the Makefile, due to the ongoing work.

Affected files ...

.. //depot/projects/usb/src/lib/libusb/libusb10.c#7 edit
.. //depot/projects/usb/src/lib/libusb/libusb10.h#4 edit
.. //depot/projects/usb/src/lib/libusb/libusb20_compat01.c#6 edit
.. //depot/projects/usb/src/lib/libusb/libusb20_int.h#7 edit

Differences ...

==== //depot/projects/usb/src/lib/libusb/libusb10.c#7 (text+ko) ====

@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2009 Sylvestre Gallon. All rights reserved.
+ * Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -23,7 +24,6 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/queue.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -31,6 +31,7 @@
 #include <pthread.h>
 #include <time.h>
 #include <errno.h>
+#include <sys/queue.h>
 
 #include "libusb20.h"
 #include "libusb20_desc.h"
@@ -40,12 +41,22 @@
 
 static pthread_mutex_t default_context_lock = PTHREAD_MUTEX_INITIALIZER;
 struct libusb_context *usbi_default_context = NULL;
-pthread_mutex_t libusb20_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* Prototypes */
+
+static struct libusb20_transfer *libusb10_get_transfer(libusb_device_handle *devh, uint8_t endpoint, uint8_t index);
+static int libusb10_get_maxframe(struct libusb20_device *pdev, libusb_transfer *xfer);
+static int libusb10_get_buffsize(struct libusb20_device *pdev, libusb_transfer *xfer);
+static int libusb10_convert_error(uint8_t status);
+static void libusb10_isoc_proxy(struct libusb20_transfer *pxfer);
+static void libusb10_bulk_intr_proxy(struct libusb20_transfer *pxfer);
+static void libusb10_ctrl_proxy(struct libusb20_transfer *pxfer);
+static void libusb10_submit_transfer_sub(struct libusb_device_handle *devh, uint8_t endpoint);
 
 /*  Library initialisation / deinitialisation */
 
 void
-libusb_set_debug(libusb_context * ctx, int level)
+libusb_set_debug(libusb_context *ctx, int level)
 {
 	ctx = GET_CONTEXT(ctx);
 	if (ctx)
@@ -53,10 +64,10 @@
 }
 
 int
-libusb_init(libusb_context ** context)
+libusb_init(libusb_context **context)
 {
 	struct libusb_context *ctx;
-	char * debug;
+	char *debug;
 	int ret;
 
 	ctx = malloc(sizeof(*ctx));
@@ -71,39 +82,19 @@
 		if (ctx->debug != 0)
 			ctx->debug_fixed = 1;
 	}
+	TAILQ_INIT(&ctx->pollfds);
 
-	pthread_mutex_init(&ctx->usb_devs_lock, NULL);
-	pthread_mutex_init(&ctx->open_devs_lock, NULL);
-	TAILQ_INIT(&ctx->usb_devs);
-	TAILQ_INIT(&ctx->open_devs);
-
-	pthread_mutex_init(&ctx->flying_transfers_lock, NULL);
-	pthread_mutex_init(&ctx->pollfds_lock, NULL);
-	pthread_mutex_init(&ctx->pollfd_modify_lock, NULL);
-	pthread_mutex_init(&ctx->events_lock, NULL);
-	pthread_mutex_init(&ctx->event_waiters_lock, NULL);
-	pthread_cond_init(&ctx->event_waiters_cond, NULL);
+	pthread_mutex_init(&ctx->ctx_lock, NULL);
+	pthread_cond_init(&ctx->ctx_cond, NULL);
 
-	TAILQ_INIT(&ctx->flying_transfers);
-	TAILQ_INIT(&ctx->pollfds);
-
 	ret = pipe(ctx->ctrl_pipe);
 	if (ret < 0) {
-		usb_remove_pollfd(ctx, ctx->ctrl_pipe[0]);
-		close(ctx->ctrl_pipe[0]);
-		close(ctx->ctrl_pipe[1]);
+		pthread_mutex_destroy(&ctx->ctx_lock);
+		pthread_cond_destroy(&ctx->ctx_cond);
 		free(ctx);
 		return (LIBUSB_ERROR_OTHER);
 	}
-
-	ret = usb_add_pollfd(ctx, ctx->ctrl_pipe[0], POLLIN);
-	if (ret < 0) {
-		usb_remove_pollfd(ctx, ctx->ctrl_pipe[0]);
-		close(ctx->ctrl_pipe[0]);
-		close(ctx->ctrl_pipe[1]);
-		free(ctx);
-		return ret;
-	}
+	libusb10_add_pollfd(ctx, &ctx->ctx_poll, NULL, ctx->ctrl_pipe[0], POLLIN);
 
 	pthread_mutex_lock(&default_context_lock);
 	if (usbi_default_context == NULL) {
@@ -114,18 +105,26 @@
 	if (context)
 		*context = ctx;
 
+	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_init complete");
+
 	return (0);
 }
 
 void
-libusb_exit(libusb_context * ctx)
+libusb_exit(libusb_context *ctx)
 {
 	ctx = GET_CONTEXT(ctx);
 
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_exit enter");
-	usb_remove_pollfd(ctx, ctx->ctrl_pipe[0]);
+	if (ctx == NULL)
+		return;
+
+	/* XXX cleanup devices */
+
+	libusb10_remove_pollfd(ctx, &ctx->ctx_poll);
 	close(ctx->ctrl_pipe[0]);
 	close(ctx->ctrl_pipe[1]);
+	pthread_mutex_destroy(&ctx->ctx_lock);
+	pthread_cond_destroy(&ctx->ctx_cond);
 
 	pthread_mutex_lock(&default_context_lock);
 	if (ctx == usbi_default_context) {
@@ -134,47 +133,48 @@
 	pthread_mutex_unlock(&default_context_lock);
 
 	free(ctx);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_exit leave");
 }
 
 /* Device handling and initialisation. */
 
 ssize_t
-libusb_get_device_list(libusb_context * ctx, libusb_device *** list)
+libusb_get_device_list(libusb_context *ctx, libusb_device ***list)
 {
+	struct libusb20_backend *usb_backend;
 	struct libusb20_device *pdev;
-	struct LIBUSB20_DEVICE_DESC_DECODED *ddesc;
 	struct libusb_device *dev;
-	struct libusb20_backend *usb_backend;
 	int i;
 
 	ctx = GET_CONTEXT(ctx);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_list enter");
+
+	if (ctx == NULL)
+		return (LIBUSB_ERROR_INVALID_PARAM);
+
+	if (list == NULL)
+		return (LIBUSB_ERROR_INVALID_PARAM);
 
 	usb_backend = libusb20_be_alloc_default();
 	if (usb_backend == NULL)
-		return (-1);
+		return (LIBUSB_ERROR_NO_MEM);
 
+	/* figure out how many USB devices are present */
 	pdev = NULL;
 	i = 0;
 	while ((pdev = libusb20_be_device_foreach(usb_backend, pdev)))
 		i++;
 
-	if (list == NULL) {
-		libusb20_be_free(usb_backend);
-		return (LIBUSB_ERROR_INVALID_PARAM);
-	}
+	/* allocate device pointer list */
 	*list = malloc((i + 1) * sizeof(void *));
 	if (*list == NULL) {
 		libusb20_be_free(usb_backend);
 		return (LIBUSB_ERROR_NO_MEM);
 	}
+	/* create libusb v1.0 compliant devices */
 	i = 0;
 	while ((pdev = libusb20_be_device_foreach(usb_backend, NULL))) {
 		/* get device into libUSB v1.0 list */
 		libusb20_be_dequeue_device(usb_backend, pdev);
 
-		ddesc = libusb20_dev_get_device_desc(pdev);
 		dev = malloc(sizeof(*dev));
 		if (dev == NULL) {
 			while (i != 0) {
@@ -182,111 +182,88 @@
 				i--;
 			}
 			free(*list);
+			*list = NULL;
 			libusb20_be_free(usb_backend);
 			return (LIBUSB_ERROR_NO_MEM);
 		}
 		memset(dev, 0, sizeof(*dev));
 
-		pthread_mutex_init(&dev->lock, NULL);
+		/* init transfer queues */
+		TAILQ_INIT(&dev->tr_head);
+		TAILQ_INIT(&dev->tr_done);
+
+		/* set context we belong to */
 		dev->ctx = ctx;
-		dev->bus_number = pdev->bus_number;
-		dev->device_address = pdev->device_address;
-		dev->num_configurations = ddesc->bNumConfigurations;
 
 		/* link together the two structures */
 		dev->os_priv = pdev;
+		pdev->privLuData = dev;
 
-		pthread_mutex_lock(&ctx->usb_devs_lock);
-		TAILQ_INSERT_HEAD(&ctx->usb_devs, dev, list);
-		pthread_mutex_unlock(&ctx->usb_devs_lock);
-
 		(*list)[i] = libusb_ref_device(dev);
 		i++;
 	}
 	(*list)[i] = NULL;
 
 	libusb20_be_free(usb_backend);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_list leave");
 	return (i);
 }
 
-/*
- * In this function we cant free all the device contained into list because
- * open_with_pid_vid use some node of list after the free_device_list.
- */
 void
 libusb_free_device_list(libusb_device **list, int unref_devices)
 {
 	int i;
-	libusb_context *ctx;
 
-	ctx = GET_CONTEXT(NULL);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_free_device_list enter");
-
 	if (list == NULL)
-		return ;
+		return;			/* be NULL safe */
 
 	if (unref_devices) {
 		for (i = 0; list[i] != NULL; i++)
 			libusb_unref_device(list[i]);
 	}
 	free(list);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_free_device_list leave");
 }
 
 uint8_t
-libusb_get_bus_number(libusb_device * dev)
+libusb_get_bus_number(libusb_device *dev)
 {
-	libusb_context *ctx;
-
-	ctx = GET_CONTEXT(NULL);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_bus_number enter");
-
 	if (dev == NULL)
-		return (LIBUSB_ERROR_NO_DEVICE);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_bus_number leave");
-	return (dev->bus_number);
+		return (0);		/* should not happen */
+	return (libusb20_dev_get_bus_number(dev->os_priv));
 }
 
 uint8_t
-libusb_get_device_address(libusb_device * dev)
+libusb_get_device_address(libusb_device *dev)
 {
-	libusb_context *ctx;
-
-	ctx = GET_CONTEXT(NULL);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_address enter");
-
 	if (dev == NULL)
-		return (LIBUSB_ERROR_NO_DEVICE);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_address leave");
-	return (dev->device_address);
+		return (0);		/* should not happen */
+	return (libusb20_dev_get_address(dev->os_priv));
 }
 
 int
-libusb_get_max_packet_size(libusb_device *dev, unsigned char endpoint)
+libusb_get_max_packet_size(libusb_device *dev, uint8_t endpoint)
 {
 	struct libusb_config_descriptor *pdconf;
 	struct libusb_interface *pinf;
 	struct libusb_interface_descriptor *pdinf;
 	struct libusb_endpoint_descriptor *pdend;
-	libusb_context *ctx;
-	int i, j, k, ret;
+	int i;
+	int j;
+	int k;
+	int ret;
 
-	ctx = GET_CONTEXT(NULL);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_max_packet_size enter");
-
 	if (dev == NULL)
 		return (LIBUSB_ERROR_NO_DEVICE);
 
-	if (libusb_get_active_config_descriptor(dev, &pdconf) < 0) 
-		return (LIBUSB_ERROR_OTHER);
- 
+	ret = libusb_get_active_config_descriptor(dev, &pdconf);
+	if (ret < 0)
+		return (ret);
+
 	ret = LIBUSB_ERROR_NOT_FOUND;
-	for (i = 0 ; i < pdconf->bNumInterfaces ; i++) {
+	for (i = 0; i < pdconf->bNumInterfaces; i++) {
 		pinf = &pdconf->interface[i];
-		for (j = 0 ; j < pinf->num_altsetting ; j++) {
+		for (j = 0; j < pinf->num_altsetting; j++) {
 			pdinf = &pinf->altsetting[j];
-			for (k = 0 ; k < pdinf->bNumEndpoints ; k++) {
+			for (k = 0; k < pdinf->bNumEndpoints; k++) {
 				pdend = &pdinf->endpoint[k];
 				if (pdend->bEndpointAddress == endpoint) {
 					ret = pdend->wMaxPacketSize;
@@ -298,150 +275,111 @@
 
 out:
 	libusb_free_config_descriptor(pdconf);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_max_packet_size leave");
 	return (ret);
 }
 
 libusb_device *
-libusb_ref_device(libusb_device * dev)
+libusb_ref_device(libusb_device *dev)
 {
-	libusb_context *ctx;
-
-	ctx = GET_CONTEXT(NULL);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_ref_device enter");
-
 	if (dev == NULL)
-		return (NULL);
+		return (NULL);		/* be NULL safe */
 
-	pthread_mutex_lock(&dev->lock);
+	CTX_LOCK(dev->ctx);
 	dev->refcnt++;
-	pthread_mutex_unlock(&dev->lock);
+	CTX_UNLOCK(dev->ctx);
 
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_ref_device leave");
 	return (dev);
 }
 
 void
-libusb_unref_device(libusb_device * dev)
+libusb_unref_device(libusb_device *dev)
 {
-	libusb_context *ctx;
-
-	ctx = GET_CONTEXT(NULL);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unref_device enter");
-
 	if (dev == NULL)
-		return;
+		return;			/* be NULL safe */
 
-	pthread_mutex_lock(&dev->lock);
+	CTX_LOCK(dev->ctx);
 	dev->refcnt--;
-	pthread_mutex_unlock(&dev->lock);
+	CTX_UNLOCK(dev->ctx);
 
 	if (dev->refcnt == 0) {
-		pthread_mutex_lock(&dev->ctx->usb_devs_lock);
-		TAILQ_REMOVE(&ctx->usb_devs, dev, list);
-		pthread_mutex_unlock(&dev->ctx->usb_devs_lock);
-
 		libusb20_dev_free(dev->os_priv);
 		free(dev);
 	}
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unref_device leave");
 }
 
 int
-libusb_open(libusb_device * dev, libusb_device_handle **devh)
+libusb_open(libusb_device *dev, libusb_device_handle **devh)
 {
 	libusb_context *ctx = dev->ctx;
 	struct libusb20_device *pdev = dev->os_priv;
-	libusb_device_handle *hdl;
-	unsigned char dummy;
+	uint8_t dummy;
 	int err;
 
-	ctx = GET_CONTEXT(ctx);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open enter");
-
-	dummy = 1;
 	if (devh == NULL)
 		return (LIBUSB_ERROR_INVALID_PARAM);
 
-	hdl = malloc(sizeof(*hdl));
-	if (hdl == NULL)
-		return (LIBUSB_ERROR_NO_MEM);
+	/* set default device handle value */
+	*devh = NULL;
+
+	dev = libusb_ref_device(dev);
+	if (dev == NULL)
+		return (LIBUSB_ERROR_INVALID_PARAM);
 
 	err = libusb20_dev_open(pdev, 16 * 4 /* number of endpoints */ );
 	if (err) {
-		free(hdl);
+		libusb_unref_device(dev);
 		return (LIBUSB_ERROR_NO_MEM);
 	}
-	memset(hdl, 0, sizeof(*hdl));
-	pthread_mutex_init(&hdl->lock, NULL);
-
-	TAILQ_INIT(&hdl->ep_list);
-	hdl->dev = libusb_ref_device(dev);
-	hdl->claimed_interfaces = 0;
-	hdl->os_priv = dev->os_priv;
-	err = usb_add_pollfd(ctx, libusb20_dev_get_fd(pdev), POLLIN |
+	libusb10_add_pollfd(ctx, &dev->dev_poll, pdev, libusb20_dev_get_fd(pdev), POLLIN |
 	    POLLOUT | POLLRDNORM | POLLWRNORM);
-	if (err < 0) {
-		libusb_unref_device(dev);
-		free(hdl);
-		return (err);
-	}
 
-	pthread_mutex_lock(&ctx->open_devs_lock);
-	TAILQ_INSERT_HEAD(&ctx->open_devs, hdl, list);
-	pthread_mutex_unlock(&ctx->open_devs_lock);
-
-	*devh = hdl;
-
-	pthread_mutex_lock(&ctx->pollfd_modify_lock);
-	ctx->pollfd_modify++;
-	pthread_mutex_unlock(&ctx->pollfd_modify_lock);	
-
+	/* make sure our event loop detects the new device */
+	dummy = 0;
 	err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy));
-	if (err <= 0) {
-		pthread_mutex_lock(&ctx->pollfd_modify_lock);
-		ctx->pollfd_modify--;
-		pthread_mutex_unlock(&ctx->pollfd_modify_lock);
-		return 0;
+	if (err < sizeof(dummy)) {
+		/* ignore error, if any */
+		DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open write failed!");
 	}
+	*devh = (libusb_device_handle *)pdev;
 
-	libusb_lock_events(ctx);
-	read(ctx->ctrl_pipe[0], &dummy, sizeof(dummy));
-	pthread_mutex_lock(&ctx->pollfd_modify_lock);
-	ctx->pollfd_modify--;
-	pthread_mutex_unlock(&ctx->pollfd_modify_lock);
-	libusb_unlock_events(ctx);
-
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open leave");
 	return (0);
 }
 
 libusb_device_handle *
-libusb_open_device_with_vid_pid(libusb_context * ctx, uint16_t vendor_id,
+libusb_open_device_with_vid_pid(libusb_context *ctx, uint16_t vendor_id,
     uint16_t product_id)
 {
 	struct libusb_device **devs;
 	struct libusb_device_handle *devh;
 	struct libusb20_device *pdev;
 	struct LIBUSB20_DEVICE_DESC_DECODED *pdesc;
-	int i, j;
+	int i;
+	int j;
 
 	ctx = GET_CONTEXT(ctx);
+	if (ctx == NULL)
+		return (NULL);		/* be NULL safe */
+
 	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_width_vid_pid enter");
 
-	devh = NULL;
-
 	if ((i = libusb_get_device_list(ctx, &devs)) < 0)
 		return (NULL);
 
+	devh = NULL;
+
 	for (j = 0; j < i; j++) {
-		pdev = (struct libusb20_device *)devs[j]->os_priv;
+		pdev = devs[j]->os_priv;
 		pdesc = libusb20_dev_get_device_desc(pdev);
+		/*
+		 * NOTE: The USB library will automatically swap the
+		 * fields in the device descriptor to be of host
+		 * endian type!
+		 */
 		if (pdesc->idVendor == vendor_id &&
 		    pdesc->idProduct == product_id) {
 			if (libusb_open(devs[j], &devh) < 0)
 				devh = NULL;
-			break ;
+			break;
 		}
 	}
 
@@ -451,319 +389,306 @@
 }
 
 void
-libusb_close(libusb_device_handle * devh)
+libusb_close(libusb_device_handle *devh)
 {
 	libusb_context *ctx;
 	struct libusb20_device *pdev;
+	struct libusb_device *dev;
 	struct usb_ep_tr *eptr;
-	unsigned char dummy = 1;
+	uint8_t dummy;
 	int err;
 
 	if (devh == NULL)
-		return ;
+		return;			/* be NULL safe */
 
-	ctx = devh->dev->ctx;
-	pdev = devh->os_priv;
+	pdev = (struct libusb20_device *)devh;
+	dev = pdev->privLuData;
+	ctx = dev->ctx;
 
-	ctx = GET_CONTEXT(ctx);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_close enter");
+	libusb10_remove_pollfd(ctx, &dev->dev_poll);
 
-	pthread_mutex_lock(&ctx->pollfd_modify_lock);
-	ctx->pollfd_modify++;
-	pthread_mutex_unlock(&ctx->pollfd_modify_lock);
+	libusb20_dev_close(pdev);
+	libusb_unref_device(dev);
 
+	/* make sure our event loop detects the closed device */
+	dummy = 0;
 	err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy));
-	
-	if (err <= 0) {
-		pthread_mutex_lock(&ctx->open_devs_lock);
-		TAILQ_REMOVE(&ctx->open_devs, devh, list);
-		pthread_mutex_unlock(&ctx->open_devs_lock);
-
-		usb_remove_pollfd(ctx, libusb20_dev_get_fd(pdev));
-		libusb20_dev_close(pdev);
-		libusb_unref_device(devh->dev);
-		TAILQ_FOREACH(eptr, &devh->ep_list, list) {
-			TAILQ_REMOVE(&devh->ep_list, eptr, list);
-			libusb20_tr_close(((struct libusb20_transfer **)
-			    eptr->os_priv)[0]);
-			if (eptr->flags)
-				libusb20_tr_close(((struct libusb20_transfer **)
-			            eptr->os_priv)[1]);
-			free((struct libusb20_transfer **)eptr->os_priv);
-		}
-		free(devh);
-
-		pthread_mutex_lock(&ctx->pollfd_modify_lock);
-		ctx->pollfd_modify--;
-		pthread_mutex_unlock(&ctx->pollfd_modify_lock);
-		return ;
+	if (err < sizeof(dummy)) {
+		/* ignore error, if any */
+		DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_close write failed!");
 	}
-	libusb_lock_events(ctx);
-
-	read(ctx->ctrl_pipe[0], &dummy, sizeof(dummy));
-	pthread_mutex_lock(&ctx->open_devs_lock);
-	TAILQ_REMOVE(&ctx->open_devs, devh, list);
-	pthread_mutex_unlock(&ctx->open_devs_lock);
-
-	usb_remove_pollfd(ctx, libusb20_dev_get_fd(pdev));
-	libusb20_dev_close(pdev);
-	libusb_unref_device(devh->dev);
-	TAILQ_FOREACH(eptr, &devh->ep_list, list) {
-		TAILQ_REMOVE(&devh->ep_list, eptr, list);
-		libusb20_tr_close(((struct libusb20_transfer **)
-		    eptr->os_priv)[0]);
-		if (eptr->flags)
-			libusb20_tr_close(((struct libusb20_transfer **)
-			    eptr->os_priv)[1]);
-		free((struct libusb20_transfer **)eptr->os_priv);
-	}
-	free(devh);
-
-	pthread_mutex_lock(&ctx->pollfd_modify_lock);
-	ctx->pollfd_modify--;
-	pthread_mutex_unlock(&ctx->pollfd_modify_lock);
-
-	libusb_unlock_events(ctx);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_close leave");
 }
 
 libusb_device *
-libusb_get_device(libusb_device_handle * devh)
+libusb_get_device(libusb_device_handle *devh)
 {
-	libusb_context *ctx;
-
-	ctx = GET_CONTEXT(NULL);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device enter");
-
 	if (devh == NULL)
 		return (NULL);
-
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device leave");
-	return (devh->dev);
+	return ((libusb_device *)(((struct libusb20_device *)devh)->privLuData));
 }
 
 int
-libusb_get_configuration(libusb_device_handle * devh, int *config)
+libusb_get_configuration(libusb_device_handle *devh, int *config)
 {
-	libusb_context *ctx;
-
-	ctx = GET_CONTEXT(NULL);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_configuration enter");
+	struct libusb20_config *pconf;
+	struct libusb20_device *pdev;
+	int err;
 
 	if (devh == NULL || config == NULL)
 		return (LIBUSB_ERROR_INVALID_PARAM);
 
-	*config = libusb20_dev_get_config_index((struct libusb20_device *)
-	    devh->dev->os_priv);
+	pdev = (struct libusb20_device *)devh;
+
+	pconf = libusb20_dev_alloc_config(pdev, libusb20_dev_get_config_index(pdev));
+	if (pconf == NULL)
+		return (LIBUSB_ERROR_NO_MEM);
+
+	*config = pconf->desc.bConfigurationValue;
+
+	free(pconf);
 
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_configuration leave");
 	return (0);
 }
 
 int
-libusb_set_configuration(libusb_device_handle * devh, int configuration)
+libusb_set_configuration(libusb_device_handle *devh, int configuration)
 {
+	struct libusb20_config *pconf;
 	struct libusb20_device *pdev;
-	libusb_context *ctx;
+	struct libusb_device *dev;
+	int err;
+	uint8_t i;
+
+	dev = libusb_get_device(devh);
+
+	if (dev == NULL)
+		return (LIBUSB_ERROR_INVALID_PARAM);
+
+	pdev = (struct libusb20_device *)devh;
+
+	if (configuration < 1) {
+		/* unconfigure */
+		i = 255;
+	} else {
+		for (i = 0; i != 255; i++) {
+			uint8_t found;
 
-	ctx = GET_CONTEXT(NULL);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_configuration enter");
+			pconf = libusb20_dev_alloc_config(pdev, i);
+			if (pconf == NULL)
+				return (LIBUSB_ERROR_INVALID_PARAM);
+			found = (pconf->desc.bConfigurationValue
+			    == configuration);
+			free(pconf);
 
-	if (devh == NULL)
+			if (found)
+				goto set_config;
+		}
 		return (LIBUSB_ERROR_INVALID_PARAM);
+	}
 
-	pdev = (struct libusb20_device *)devh->dev->os_priv;
+set_config:
+
+	libusb10_remove_pollfd(dev->ctx, &dev->dev_poll);
+
+	usb_cancel_all_dev(dev);
+
+	err = libusb20_dev_set_config_index(pdev, i);
+
+	libusb10_add_pollfd(dev->ctx, &dev->dev_poll, pdev, libusb20_dev_get_fd(pdev), POLLIN |
+	    POLLOUT | POLLRDNORM | POLLWRNORM);
 
-	libusb20_dev_set_config_index(pdev, configuration);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_configuration leave");
-	return (0);
+	return (err ? LIBUSB_ERROR_INVALID_PARAM : 0);
 }
 
 int
-libusb_claim_interface(libusb_device_handle * dev, int interface_number)
+libusb_claim_interface(libusb_device_handle *devh, int interface_number)
 {
-	libusb_context *ctx;
-	int ret = 0;
+	libusb_device *dev;
+	int err = 0;
 
-	ctx = GET_CONTEXT(NULL);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_claim_interface enter");
-
+	dev = libusb_get_device(devh);
 	if (dev == NULL)
 		return (LIBUSB_ERROR_INVALID_PARAM);
 
-	if (interface_number >= sizeof(dev->claimed_interfaces) * 8)
+	if (interface_number < 0 || interface_number > 31)
 		return (LIBUSB_ERROR_INVALID_PARAM);
 
-	pthread_mutex_lock(&(dev->lock));
+	CTX_LOCK(dev->ctx);
 	if (dev->claimed_interfaces & (1 << interface_number))
-		ret = LIBUSB_ERROR_BUSY;
+		err = LIBUSB_ERROR_BUSY;
 
-	if (!ret)
+	if (!err)
 		dev->claimed_interfaces |= (1 << interface_number);
-	pthread_mutex_unlock(&(dev->lock));
-
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_claim_interface leave");
-	return (ret);
+	CTX_UNLOCK(dev->ctx);
+	return (err);
 }
 
 int
-libusb_release_interface(libusb_device_handle * dev, int interface_number)
+libusb_release_interface(libusb_device_handle *devh, int interface_number)
 {
-	libusb_context *ctx;
-	int ret;
+	libusb_device *dev;
+	int err = 0;
 
-	ctx = GET_CONTEXT(NULL);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_release_interface enter");
-
-	ret = 0;
+	dev = libusb_get_device(devh);
 	if (dev == NULL)
 		return (LIBUSB_ERROR_INVALID_PARAM);
 
-	if (interface_number >= sizeof(dev->claimed_interfaces) * 8)
+	if (interface_number < 0 || interface_number > 31)
 		return (LIBUSB_ERROR_INVALID_PARAM);
 
-	pthread_mutex_lock(&(dev->lock));
+	CTX_LOCK(dev->ctx);
 	if (!(dev->claimed_interfaces & (1 << interface_number)))
-		ret = LIBUSB_ERROR_NOT_FOUND;
+		err = LIBUSB_ERROR_NOT_FOUND;
 
-	if (!ret)
+	if (!err)
 		dev->claimed_interfaces &= ~(1 << interface_number);
-	pthread_mutex_unlock(&(dev->lock));
-
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_release_interface leave");
-	return (ret);
+	CTX_UNLOCK(dev->ctx);
+	return (err);
 }
 
 int
-libusb_set_interface_alt_setting(libusb_device_handle * dev,
+libusb_set_interface_alt_setting(libusb_device_handle *devh,
     int interface_number, int alternate_setting)
 {
-	libusb_context *ctx;
+	struct libusb20_device *pdev;
+	libusb_device *dev;
+	int err = 0;
 
-	ctx = GET_CONTEXT(NULL);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_interface_alt_setting enter");
-
+	dev = libusb_get_device(devh);
 	if (dev == NULL)
 		return (LIBUSB_ERROR_INVALID_PARAM);
 
-	if (interface_number >= sizeof(dev->claimed_interfaces) *8)
+	if (interface_number < 0 || interface_number > 31)
 		return (LIBUSB_ERROR_INVALID_PARAM);
 
-	pthread_mutex_lock(&dev->lock);
-	if (!(dev->claimed_interfaces & (1 << interface_number))) {
-		pthread_mutex_unlock(&dev->lock);
-		return (LIBUSB_ERROR_NOT_FOUND);
+	CTX_LOCK(dev->ctx);
+	if (!(dev->claimed_interfaces & (1 << interface_number)))
+		err = LIBUSB_ERROR_NOT_FOUND;
+	CTX_UNLOCK(dev->ctx);
+
+	if (err)
+		return (err);
+
+	libusb10_remove_pollfd(dev->ctx, &dev->dev_poll);
+
+	usb_cancel_all_dev(dev);
+
+	pdev = (struct libusb20_device *)devh;
+
+	err = libusb20_dev_set_alt_index(pdev,
+	    interface_number, alternate_setting);
+
+	libusb10_add_pollfd(dev->ctx, &dev->dev_poll,
+	    pdev, libusb20_dev_get_fd(pdev),
+	    POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM);
+
+	return (err ? LIBUSB_ERROR_OTHER : 0);
+}
+
+
+UNEXPORTED static struct libusb20_transfer *
+libusb10_get_transfer(libusb_device_handle *devh,
+    uint8_t endpoint, uint8_t index)
+{
+	index &= 1;			/* double buffering */
+
+	index |= (endpoint & LIBUSB20_ENDPOINT_ADDRESS_MASK) * 4;
+
+	if (endpoint & LIBUSB20_ENDPOINT_DIR_MASK) {
+		/* this is an IN endpoint */
+		index |= 2;
 	}
-	pthread_mutex_unlock(&dev->lock);
-
-	if (libusb20_dev_set_alt_index(dev->os_priv, interface_number,
-	    alternate_setting) != 0)
-		return (LIBUSB_ERROR_OTHER);
-	
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_interface_alt_setting leave");
-	return (0);
+	return (libusb20_tr_get_pointer((struct libusb20_device *)devh, index));
 }
 
 int
-libusb_clear_halt(libusb_device_handle * devh, unsigned char endpoint)
+libusb_clear_halt(libusb_device_handle *devh, uint8_t endpoint)
 {
 	struct libusb20_transfer *xfer;
 	struct libusb20_device *pdev;
-	libusb_context *ctx;
-	int ret; 
+	struct libusb_device *dev;
+	int err;
 
-	ctx = GET_CONTEXT(NULL);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_clear_halt enter");
-	
-	pdev = devh->os_priv;
-	xfer = libusb20_tr_get_pointer(pdev, 
-	    ((endpoint / 0x40) | (endpoint * 4)) % (16 * 4));
+	xfer = libusb10_get_transfer(devh, endpoint, 0);
 	if (xfer == NULL)
-		return (LIBUSB_ERROR_NO_MEM);
+		return (LIBUSB_ERROR_INVALID_PARAM);
+
+	dev = pdev->privLuData;
+
+	CTX_LOCK(dev->ctx);
+	err = libusb20_tr_open(xfer, 0, 0, endpoint);
+	CTX_UNLOCK(dev->ctx);
 
-	pthread_mutex_lock(&libusb20_lock);
-	ret = libusb20_tr_open(xfer, 0, 0, endpoint);
-	if (ret != 0 && ret != LIBUSB20_ERROR_BUSY) {
-		pthread_mutex_unlock(&libusb20_lock);
+	if (err != 0 && err != LIBUSB20_ERROR_BUSY)
 		return (LIBUSB_ERROR_OTHER);
-	}
 
 	libusb20_tr_clear_stall_sync(xfer);
-	if (ret == 0) /* check if we have open the device */
+
+	/* check if we opened the transfer */
+	if (err == 0) {
+		CTX_LOCK(dev->ctx);
 		libusb20_tr_close(xfer);
-	pthread_mutex_unlock(&libusb20_lock);
-
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_clear_halt leave");
-	return (0);
+		CTX_UNLOCK(dev->ctx);
+	}
+	return (0);			/* success */
 }
 
 int
-libusb_reset_device(libusb_device_handle * dev)
+libusb_reset_device(libusb_device_handle *devh)
 {
-	libusb_context *ctx;
+	struct libusb20_device *pdev;
+	libusb_device *dev;
+	int err;
 
-	ctx = GET_CONTEXT(NULL);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_reset_device enter");
-
+	dev = libusb_get_device(devh);
 	if (dev == NULL)
 		return (LIBUSB20_ERROR_INVALID_PARAM);
 
-	libusb20_dev_reset(dev->os_priv);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_reset_device leave");
-	return (0);
+	libusb10_remove_pollfd(dev->ctx, &dev->dev_poll);
+
+	usb_cancel_all_dev(dev);
+
+	err = libusb20_dev_reset((struct libusb20_device *)devh);
+
+	pdev = (struct libusb20_device *)devh;
+
+	libusb10_add_pollfd(dev->ctx, &dev->dev_poll,
+	    pdev, libusb20_dev_get_fd(pdev),
+	    POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM);
+
+	return (err ? LIBUSB_ERROR_OTHER : 0);
 }
 
 int
-libusb_kernel_driver_active(libusb_device_handle * devh, int interface)
+libusb_kernel_driver_active(libusb_device_handle *devh, int interface)
 {
-	libusb_context *ctx;
-

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list