svn commit: r195957 - head/lib/libusb
Alfred Perlstein
alfred at FreeBSD.org
Thu Jul 30 00:11:42 UTC 2009
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 ***
More information about the svn-src-head
mailing list