From owner-svn-src-head@FreeBSD.ORG Thu Jul 30 00:11:42 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0EF25106564A; Thu, 30 Jul 2009 00:11:42 +0000 (UTC) (envelope-from alfred@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id EF9908FC17; Thu, 30 Jul 2009 00:11:41 +0000 (UTC) (envelope-from alfred@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n6U0BfK2086177; Thu, 30 Jul 2009 00:11:41 GMT (envelope-from alfred@svn.freebsd.org) Received: (from alfred@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n6U0BffM086172; Thu, 30 Jul 2009 00:11:41 GMT (envelope-from alfred@svn.freebsd.org) Message-Id: <200907300011.n6U0BffM086172@svn.freebsd.org> From: Alfred Perlstein Date: Thu, 30 Jul 2009 00:11:41 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r195957 - head/lib/libusb X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 30 Jul 2009 00:11:42 -0000 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 #include #include -#include #include #include @@ -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 #include #include #include @@ -32,6 +32,9 @@ #include #include #include +#include +#include +#include #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 ***