Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 30 Jul 2009 00:11:41 +0000 (UTC)
From:      Alfred Perlstein <alfred@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r195957 - head/lib/libusb
Message-ID:  <200907300011.n6U0BffM086172@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: alfred
Date: Thu Jul 30 00:11:41 2009
New Revision: 195957
URL: http://svn.freebsd.org/changeset/base/195957

Log:
          LibUSB v1.0:
  
          - Significantly improve libusb10 support.
          - Many minor issues fixed.
          - P4 ID: 166189, 165853, 165991, 166052, 166069
  
  Submitted by:	hps
  Approved by:	re

Modified:
  head/lib/libusb/libusb.3
  head/lib/libusb/libusb.h
  head/lib/libusb/libusb10.c
  head/lib/libusb/libusb10.h
  head/lib/libusb/libusb10_desc.c
  head/lib/libusb/libusb10_io.c
  head/lib/libusb/libusb20.3
  head/lib/libusb/libusb20_compat01.c
  head/lib/libusb/libusb20_int.h

Modified: head/lib/libusb/libusb.3
==============================================================================
--- head/lib/libusb/libusb.3	Wed Jul 29 22:19:52 2009	(r195956)
+++ head/lib/libusb/libusb.3	Thu Jul 30 00:11:41 2009	(r195957)
@@ -294,7 +294,7 @@ LIBUSB_ERROR code on failure.
 .
 .Pp
 .Ft void
-.Fn libusb_free_config_descriptor "libusb_config_descriptor *config`"
+.Fn libusb_free_config_descriptor "libusb_config_descriptor *config"
 Free a configuration descriptor.
 .
 .Pp

Modified: head/lib/libusb/libusb.h
==============================================================================
--- head/lib/libusb/libusb.h	Wed Jul 29 22:19:52 2009	(r195956)
+++ head/lib/libusb/libusb.h	Thu Jul 30 00:11:41 2009	(r195957)
@@ -30,7 +30,6 @@
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/endian.h>
-#include <sys/queue.h>
 
 #include <stdint.h>
 #include <time.h>
@@ -181,95 +180,25 @@ enum libusb_debug_level {
 	LIBUSB_DEBUG_TRANSFER=2,
 };
 
-/* internal structures */
+/* libusb structures */
+
+struct libusb_context;
+struct libusb_device;
+struct libusb_transfer;
+struct libusb20_device;
 
-typedef struct libusb_pollfd {
+struct libusb_pollfd {
 	int	fd;
 	short	events;
-}	libusb_pollfd;
-
-struct usb_pollfd {
-	TAILQ_ENTRY(usb_pollfd) list;
-	struct libusb_pollfd pollfd;
-};
-
-struct usb_transfer {
-	TAILQ_ENTRY(usb_transfer) list;
-	int num_iso_packets;
-	struct timeval timeout;
-	int transferred;
-	uint8_t flags;
-};
-
-struct usb_ep_tr {
-	TAILQ_ENTRY(usb_ep_tr) list;
-	uint8_t addr;
-	uint8_t idx;
-	uint8_t flags;
-	void *os_priv;
 };
-/* libusb structures */
 
+typedef struct libusb_context libusb_context;
+typedef struct libusb_device libusb_device;
+typedef struct libusb20_device libusb_device_handle;
+typedef struct libusb_pollfd libusb_pollfd;
 typedef void (*libusb_pollfd_added_cb) (int fd, short events, void *user_data);
 typedef void (*libusb_pollfd_removed_cb) (int fd, void *user_data);
 
-typedef struct libusb_context {
-	int	debug;
-	int	debug_fixed;
-
-	int	ctrl_pipe[2];
-
-	TAILQ_HEAD(usb_devs_list, libusb_device) usb_devs;
-	pthread_mutex_t usb_devs_lock;
-
-	TAILQ_HEAD(open_devs_list, libusb_device_handle) open_devs;
-	pthread_mutex_t open_devs_lock;
-
-	TAILQ_HEAD(flying_transfers_list, usb_transfer) flying_transfers;
-	pthread_mutex_t flying_transfers_lock;
-
-	TAILQ_HEAD(pollfds_list, usb_pollfd) pollfds;
-	pthread_mutex_t pollfds_lock;
-
-	unsigned int pollfd_modify;
-	pthread_mutex_t pollfd_modify_lock;
-
-	libusb_pollfd_added_cb fd_added_cb;
-	libusb_pollfd_removed_cb fd_removed_cb;
-	void   *fd_cb_user_data;
-
-	pthread_mutex_t events_lock;
-	int	event_handler_active;
-
-	pthread_mutex_t event_waiters_lock;
-	pthread_cond_t event_waiters_cond;
-}	libusb_context;
-
-typedef struct libusb_device {
-	pthread_mutex_t lock;
-	int	refcnt;
-
-	struct libusb_context *ctx;
-
-	uint8_t	bus_number;
-	uint8_t	device_address;
-	uint8_t	num_configurations;
-
-	TAILQ_ENTRY(libusb_device) list;
-	unsigned long session_data;
-	void   *os_priv;
-}	libusb_device;
-
-typedef struct libusb_device_handle {
-	pthread_mutex_t lock;
-	unsigned long claimed_interfaces;
-
-	TAILQ_ENTRY(libusb_device_handle) list;
-	struct libusb_device *dev;
-	void   *os_priv;
-	TAILQ_HEAD(ep_list, usb_ep_tr) ep_list; 
-}	libusb_device_handle;
-
 typedef struct libusb_device_descriptor {
 	uint8_t	bLength;
 	uint8_t	bDescriptorType;
@@ -296,7 +225,7 @@ typedef struct libusb_endpoint_descripto
 	uint8_t	bInterval;
 	uint8_t	bRefresh;
 	uint8_t	bSynchAddress;
-	unsigned char *extra;
+	uint8_t *extra;
 	int	extra_length;
 }	libusb_endpoint_descriptor __aligned(sizeof(void *));
 
@@ -311,7 +240,7 @@ typedef struct libusb_interface_descript
 	uint8_t	bInterfaceProtocol;
 	uint8_t	iInterface;
 	struct libusb_endpoint_descriptor *endpoint;
-	unsigned char *extra;
+	uint8_t *extra;
 	int	extra_length;
 }	libusb_interface_descriptor __aligned(sizeof(void *));
 
@@ -330,7 +259,7 @@ typedef struct libusb_config_descriptor 
 	uint8_t	bmAttributes;
 	uint8_t	MaxPower;
 	struct libusb_interface *interface;
-	unsigned char *extra;
+	uint8_t *extra;
 	int	extra_length;
 }	libusb_config_descriptor __aligned(sizeof(void *));
 
@@ -348,22 +277,20 @@ typedef struct libusb_iso_packet_descrip
 	enum libusb_transfer_status status;
 }	libusb_iso_packet_descriptor __aligned(sizeof(void *));
 
-struct libusb_transfer;
-
 typedef void (*libusb_transfer_cb_fn) (struct libusb_transfer *transfer);
 
 typedef struct libusb_transfer {
 	libusb_device_handle *dev_handle;
 	uint8_t	flags;
 	unsigned int endpoint;
-	unsigned char type;
+	uint8_t type;
 	unsigned int timeout;
 	enum libusb_transfer_status status;
 	int	length;
 	int	actual_length;
 	libusb_transfer_cb_fn callback;
 	void   *user_data;
-	unsigned char *buffer;
+	uint8_t *buffer;
 	void *os_priv;
 	int	num_iso_packets;
 	struct libusb_iso_packet_descriptor iso_packet_desc[0];
@@ -381,8 +308,8 @@ ssize_t libusb_get_device_list(libusb_co
 void	libusb_free_device_list(libusb_device ** list, int unref_devices);
 uint8_t	libusb_get_bus_number(libusb_device * dev);
 uint8_t	libusb_get_device_address(libusb_device * dev);
-int	libusb_clear_halt(libusb_device_handle *devh, unsigned char endpoint);
-int	libusb_get_max_packet_size(libusb_device * dev, unsigned char endpoint);
+int	libusb_clear_halt(libusb_device_handle *devh, uint8_t endpoint);
+int	libusb_get_max_packet_size(libusb_device * dev, uint8_t endpoint);
 libusb_device *libusb_ref_device(libusb_device * dev);
 void	libusb_unref_device(libusb_device * dev);
 int	libusb_open(libusb_device * dev, libusb_device_handle ** devh);
@@ -393,6 +320,7 @@ int	libusb_get_configuration(libusb_devi
 int	libusb_set_configuration(libusb_device_handle * devh, int configuration);
 int	libusb_claim_interface(libusb_device_handle * devh, int interface_number);
 int	libusb_release_interface(libusb_device_handle * devh, int interface_number);
+int	libusb_reset_device(libusb_device_handle * dev);
 int 	libusb_kernel_driver_active(libusb_device_handle * devh, int interface);
 int 	libusb_detach_kernel_driver(libusb_device_handle * devh, int interface);
 int 	libusb_attach_kernel_driver(libusb_device_handle * devh, int interface);
@@ -405,15 +333,15 @@ int	libusb_get_active_config_descriptor(
 int	libusb_get_config_descriptor(libusb_device * dev, uint8_t config_index, struct libusb_config_descriptor **config);
 int	libusb_get_config_descriptor_by_value(libusb_device * dev, uint8_t bConfigurationValue, struct libusb_config_descriptor **config);
 void	libusb_free_config_descriptor(struct libusb_config_descriptor *config);
-int	libusb_get_string_descriptor_ascii(libusb_device_handle * dev, uint8_t desc_index, unsigned char *data, int length);
+int	libusb_get_string_descriptor_ascii(libusb_device_handle * dev, uint8_t desc_index, uint8_t *data, int length);
 
-/* Asynchronous device I/O*/
+/* Asynchronous device I/O */
 
 struct libusb_transfer *libusb_alloc_transfer(int iso_packets);
 void	libusb_free_transfer(struct libusb_transfer *transfer);
 int	libusb_submit_transfer(struct libusb_transfer *transfer);
 int	libusb_cancel_transfer(struct libusb_transfer *transfer);
-unsigned char *libusb_get_iso_packet_buffer_simple(struct libusb_transfer *transfer, unsigned int packet);
+uint8_t *libusb_get_iso_packet_buffer_simple(struct libusb_transfer *transfer, unsigned int packet);
 
 /* Polling and timing */
 
@@ -434,9 +362,9 @@ struct libusb_pollfd **libusb_get_pollfd
 
 /* Synchronous device I/O */
 
-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);
-int	libusb_bulk_transfer(struct libusb_device_handle *devh, unsigned char endpoint, unsigned char *data, int length, int *transferred, unsigned int timeout);
-int	libusb_interrupt_transfer(struct libusb_device_handle *devh, unsigned char endpoint, unsigned char *data, int length, int *transferred, unsigned int timeout);
+int	libusb_control_transfer(libusb_device_handle * devh, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint8_t *data, uint16_t wLength, unsigned int timeout);
+int	libusb_bulk_transfer(libusb_device_handle *devh, uint8_t endpoint, uint8_t *data, int length, int *transferred, unsigned int timeout);
+int	libusb_interrupt_transfer(libusb_device_handle *devh, uint8_t endpoint, uint8_t *data, int length, int *transferred, unsigned int timeout);
 
 #if 0
 {					/* indent fix */

Modified: head/lib/libusb/libusb10.c
==============================================================================
--- head/lib/libusb/libusb10.c	Wed Jul 29 22:19:52 2009	(r195956)
+++ head/lib/libusb/libusb10.c	Thu Jul 30 00:11:41 2009	(r195957)
@@ -1,6 +1,7 @@
 /* $FreeBSD$ */
 /*-
  * 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
@@ -24,7 +25,6 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/queue.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -32,6 +32,9 @@
 #include <pthread.h>
 #include <time.h>
 #include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/filio.h>
+#include <sys/queue.h>
 
 #include "libusb20.h"
 #include "libusb20_desc.h"
@@ -41,23 +44,34 @@
 
 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(struct libusb20_device *, uint8_t, uint8_t);
+static int libusb10_get_maxframe(struct libusb20_device *, libusb_transfer *);
+static int libusb10_get_buffsize(struct libusb20_device *, libusb_transfer *);
+static int libusb10_convert_error(uint8_t status);
+static void libusb10_complete_transfer(struct libusb20_transfer *, struct libusb_super_transfer *, int);
+static void libusb10_isoc_proxy(struct libusb20_transfer *);
+static void libusb10_bulk_intr_proxy(struct libusb20_transfer *);
+static void libusb10_ctrl_proxy(struct libusb20_transfer *);
+static void libusb10_submit_transfer_sub(struct libusb20_device *, uint8_t);
 
 /*  Library initialisation / deinitialisation */
 
 void
-libusb_set_debug(libusb_context * ctx, int level)
+libusb_set_debug(libusb_context *ctx, int level)
 {
-	GET_CONTEXT(ctx);
+	ctx = GET_CONTEXT(ctx);
 	if (ctx)
 		ctx->debug = level;
 }
 
 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));
@@ -72,39 +86,28 @@ libusb_init(libusb_context ** context)
 		if (ctx->debug != 0)
 			ctx->debug_fixed = 1;
 	}
+	TAILQ_INIT(&ctx->pollfds);
+	TAILQ_INIT(&ctx->tr_done);
 
-	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);
+	ctx->ctx_handler = NO_THREAD;
 
 	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);
 	}
+	/* set non-blocking mode on the control pipe to avoid deadlock */
+	ret = 1;
+	ioctl(ctx->ctrl_pipe[0], FIONBIO, &ret);
+	ret = 1;
+	ioctl(ctx->ctrl_pipe[1], FIONBIO, &ret);
 
-	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) {
@@ -115,18 +118,26 @@ libusb_init(libusb_context ** context)
 	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)
 {
-	GET_CONTEXT(ctx);
+	ctx = GET_CONTEXT(ctx);
+
+	if (ctx == NULL)
+		return;
 
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_exit enter");
-	usb_remove_pollfd(ctx, ctx->ctrl_pipe[0]);
+	/* 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) {
@@ -135,47 +146,48 @@ libusb_exit(libusb_context * ctx)
 	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;
 
-	GET_CONTEXT(ctx);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_list enter");
+	ctx = GET_CONTEXT(ctx);
+
+	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) {
@@ -183,23 +195,21 @@ libusb_get_device_list(libusb_context * 
 				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);
+
+		/* 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;
-
-		pthread_mutex_lock(&ctx->usb_devs_lock);
-		TAILQ_INSERT_HEAD(&ctx->usb_devs, dev, list);
-		pthread_mutex_unlock(&ctx->usb_devs_lock);
+		pdev->privLuData = dev;
 
 		(*list)[i] = libusb_ref_device(dev);
 		i++;
@@ -207,91 +217,65 @@ libusb_get_device_list(libusb_context * 
 	(*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 = NULL;
-	GET_CONTEXT(ctx);
-	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 = NULL;
-	GET_CONTEXT(ctx);
-	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 = NULL;
-	GET_CONTEXT(ctx);
-	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;
-
-	ctx = NULL;
-	GET_CONTEXT(ctx);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_max_packet_size enter");
+	int i;
+	int j;
+	int k;
+	int ret;
 
 	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;
@@ -303,485 +287,401 @@ libusb_get_max_packet_size(libusb_device
 
 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 = NULL;
-	GET_CONTEXT(ctx);
-	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 = NULL;
-	GET_CONTEXT(ctx);
-	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;
 
-	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 = 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;
 
-	GET_CONTEXT(ctx);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_width_vid_pid enter");
+	ctx = GET_CONTEXT(ctx);
+	if (ctx == NULL)
+		return (NULL);		/* be NULL safe */
 
-	devh = NULL;
+	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_width_vid_pid enter");
 
 	if ((i = libusb_get_device_list(ctx, &devs)) < 0)
 		return (NULL);
 
+	pdev = 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 ;
+			if (libusb_open(devs[j], &pdev) < 0)
+				pdev = NULL;
+			break;
 		}
 	}
 
 	libusb_free_device_list(devs, 1);
 	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_width_vid_pid leave");
-	return (devh);
+	return (pdev);
 }
 
 void
-libusb_close(libusb_device_handle * devh)
+libusb_close(struct libusb20_device *pdev)
 {
 	libusb_context *ctx;
-	struct libusb20_device *pdev;
-	struct usb_ep_tr *eptr;
-	unsigned char dummy = 1;
+	struct libusb_device *dev;
+	uint8_t dummy;
 	int err;
 
-	if (devh == NULL)
-		return ;
+	if (pdev == NULL)
+		return;			/* be NULL safe */
 
-	ctx = devh->dev->ctx;
-	pdev = devh->os_priv;
+	dev = libusb_get_device(pdev);
+	ctx = dev->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(struct libusb20_device *pdev)
 {
-	libusb_context *ctx;
-
-	ctx = NULL;
-	GET_CONTEXT(ctx);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device enter");
-
-	if (devh == NULL)
+	if (pdev == NULL)
 		return (NULL);
-
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device leave");
-	return (devh->dev);
+	return ((libusb_device *)pdev->privLuData);
 }
 
 int
-libusb_get_configuration(libusb_device_handle * devh, int *config)
+libusb_get_configuration(struct libusb20_device *pdev, int *config)
 {
-	libusb_context *ctx;
-
-	ctx = NULL;
-	GET_CONTEXT(ctx);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_configuration enter");
+	struct libusb20_config *pconf;
 
-	if (devh == NULL || config == NULL)
+	if (pdev == NULL || config == NULL)
 		return (LIBUSB_ERROR_INVALID_PARAM);
 
-	*config = libusb20_dev_get_config_index((struct libusb20_device *)
-	    devh->dev->os_priv);
+	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(struct libusb20_device *pdev, int configuration)
 {
-	struct libusb20_device *pdev;
-	libusb_context *ctx;
+	struct libusb20_config *pconf;
+	struct libusb_device *dev;
+	int err;
+	uint8_t i;
 
-	ctx = NULL;
-	GET_CONTEXT(ctx);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_configuration enter");
+	dev = libusb_get_device(pdev);
 
-	if (devh == NULL)
+	if (dev == NULL)
 		return (LIBUSB_ERROR_INVALID_PARAM);
 
-	pdev = (struct libusb20_device *)devh->dev->os_priv;
+	if (configuration < 1) {
+		/* unconfigure */
+		i = 255;
+	} else {
+		for (i = 0; i != 255; i++) {
+			uint8_t found;
+
+			pconf = libusb20_dev_alloc_config(pdev, i);
+			if (pconf == NULL)
+				return (LIBUSB_ERROR_INVALID_PARAM);
+			found = (pconf->desc.bConfigurationValue
+			    == configuration);
+			free(pconf);
 
-	libusb20_dev_set_config_index(pdev, configuration);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_configuration leave");
-	return (0);
+			if (found)
+				goto set_config;
+		}
+		return (LIBUSB_ERROR_INVALID_PARAM);
+	}
+
+set_config:
+
+	libusb10_cancel_all_transfer(dev);
+
+	libusb10_remove_pollfd(dev->ctx, &dev->dev_poll);
+
+	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);
+
+	return (err ? LIBUSB_ERROR_INVALID_PARAM : 0);
 }
 
 int
-libusb_claim_interface(libusb_device_handle * dev, int interface_number)
+libusb_claim_interface(struct libusb20_device *pdev, int interface_number)
 {
-	libusb_context *ctx;
-	int ret = 0;
-
-	ctx = NULL;
-	GET_CONTEXT(ctx);
-	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_claim_interface enter");
+	libusb_device *dev;
+	int err = 0;
 
+	dev = libusb_get_device(pdev);
 	if (dev == NULL)
 		return (LIBUSB_ERROR_INVALID_PARAM);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200907300011.n6U0BffM086172>