From ab8f71c03f8334df7b88a725a730d2020f2e9f80 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Thu, 6 Nov 2014 00:50:01 +0000 Subject: [PATCH 001/222] Windows: Fix cygwin64 build * Issue reported by Thejus --- libusb/os/windows_usb.h | 5 ++--- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libusb/os/windows_usb.h b/libusb/os/windows_usb.h index 413adfc49..a36419e26 100644 --- a/libusb/os/windows_usb.h +++ b/libusb/os/windows_usb.h @@ -47,9 +47,8 @@ #if defined(__CYGWIN__ ) #define _stricmp stricmp -// cygwin produces a warning unless these prototypes are defined -extern int _snprintf(char *buffer, size_t count, const char *format, ...); -extern char *_strdup(const char *strSource); +#define _snprintf snprintf +#define _strdup strdup // _beginthreadex is MSVCRT => unavailable for cygwin. Fallback to using CreateThread #define _beginthreadex(a, b, c, d, e, f) CreateThread(a, b, (LPTHREAD_START_ROUTINE)c, d, e, f) #endif diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 5cc4a5206..1318c5ebf 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 10920 +#define LIBUSB_NANO 10921 From ada59db186aa95215158129db8cd42e079daff07 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Thu, 13 Nov 2014 22:03:30 +0000 Subject: [PATCH 002/222] Windows: Silence VS2013 code analysis warnings * Also update Windows version report for Windows 10 --- examples/xusb.c | 3 ++- libusb/os/threads_windows.c | 3 ++- libusb/os/windows_usb.c | 4 ++-- libusb/os/windows_usb.h | 10 ++++++---- libusb/version_nano.h | 2 +- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/examples/xusb.c b/examples/xusb.c index f7549ca15..0fdb19d44 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -1098,7 +1098,8 @@ int main(int argc, char** argv) // but since we can't call on libusb_set_debug() before libusb_init(), we use the env variable method old_dbg_str = getenv("LIBUSB_DEBUG"); if (debug_mode) { - putenv("LIBUSB_DEBUG=4"); // LIBUSB_LOG_LEVEL_DEBUG + if (putenv("LIBUSB_DEBUG=4") != 0) // LIBUSB_LOG_LEVEL_DEBUG + printf("Unable to set debug level"); } version = libusb_get_version(); diff --git a/libusb/os/threads_windows.c b/libusb/os/threads_windows.c index 8d34ed50d..700bad614 100644 --- a/libusb/os/threads_windows.c +++ b/libusb/os/threads_windows.c @@ -186,7 +186,8 @@ int usbi_cond_timedwait(usbi_cond_t *cond, // GetSystemTimeAsFileTime() is not available on CE SYSTEMTIME st; GetSystemTime(&st); - SystemTimeToFileTime(&st, &filetime); + if (!SystemTimeToFileTime(&st, &filetime)) + return 0; rtime.LowPart = filetime.dwLowDateTime; rtime.HighPart = filetime.dwHighDateTime; rtime.QuadPart -= epoch_time; diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c index 59f748019..20ca448cd 100644 --- a/libusb/os/windows_usb.c +++ b/libusb/os/windows_usb.c @@ -890,13 +890,13 @@ static void get_windows_version(void) break; case 0x63: w = (ws?"8.1":"2012_R2"); break; - case 0x64: w = (ws?"8.2":"2012_R3"); + case 0x64: w = (ws?"10":"2015"); break; default: if (windows_version < 0x50) windows_version = WINDOWS_UNSUPPORTED; else - w = "9 or later"; + w = "11 or later"; break; } } diff --git a/libusb/os/windows_usb.h b/libusb/os/windows_usb.h index a36419e26..817a4697f 100644 --- a/libusb/os/windows_usb.h +++ b/libusb/os/windows_usb.h @@ -26,10 +26,12 @@ #if defined(_MSC_VER) // disable /W4 MSVC warnings that are benign -#pragma warning(disable:4127) // conditional expression is constant -#pragma warning(disable:4100) // unreferenced formal parameter -#pragma warning(disable:4214) // bit field types other than int -#pragma warning(disable:4201) // nameless struct/union +#pragma warning(disable:4100) // unreferenced formal parameter +#pragma warning(disable:4127) // conditional expression is constant +#pragma warning(disable:4201) // nameless struct/union +#pragma warning(disable:4214) // bit field types other than int +#pragma warning(disable:4996) // deprecated API calls +#pragma warning(disable:28159) // more deprecated API calls #endif // Missing from MSVC6 setupapi.h diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 1318c5ebf..958de462a 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 10921 +#define LIBUSB_NANO 10922 From d37635afb2e845210c80c0765dccad98933e72d0 Mon Sep 17 00:00:00 2001 From: Simon Newton Date: Mon, 24 Nov 2014 20:09:57 -0800 Subject: [PATCH 003/222] misc: Fix grammar in a comment # Closes #41 --- libusb/core.c | 3 ++- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index c24ab775a..a39a17315 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1417,7 +1417,8 @@ int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev, * * \param dev a device handle * \param configuration the bConfigurationValue of the configuration you - * wish to activate, or -1 if you wish to put the device in unconfigured state + * wish to activate, or -1 if you wish to put the device in an unconfigured + * state * \returns 0 on success * \returns LIBUSB_ERROR_NOT_FOUND if the requested configuration does not exist * \returns LIBUSB_ERROR_BUSY if interfaces are currently claimed diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 958de462a..0c23ca630 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 10922 +#define LIBUSB_NANO 10923 From 63cd7d193cfd78712bfc0a74cb35cf76dc55f55d Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Tue, 16 Dec 2014 19:19:50 +0000 Subject: [PATCH 004/222] Windows: fix 2 bugs in windows_handle_events() * Var found was not reset to false before list_for_each_entry() * ctx->open_devs_lock was not released on error. * Issues reported by Yongjian Xu --- libusb/os/windows_usb.c | 4 +++- libusb/version_nano.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c index 20ca448cd..0ce0dfcb0 100644 --- a/libusb/os/windows_usb.c +++ b/libusb/os/windows_usb.c @@ -2252,7 +2252,7 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, { struct windows_transfer_priv* transfer_priv = NULL; POLL_NFDS_TYPE i = 0; - bool found = false; + bool found; struct usbi_transfer *transfer; DWORD io_size, io_result; @@ -2270,6 +2270,7 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, // Because a Windows OVERLAPPED is used for poll emulation, // a pollable fd is created and stored with each transfer usbi_mutex_lock(&ctx->flying_transfers_lock); + found = false; list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { transfer_priv = usbi_transfer_get_os_priv(transfer); if (transfer_priv->pollable_fd.fd == fds[i].fd) { @@ -2297,6 +2298,7 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, // newly allocated wfd that took the place of the one from the transfer. windows_handle_callback(transfer, io_result, io_size); } else { + usbi_mutex_unlock(&ctx->open_devs_lock); usbi_err(ctx, "could not find a matching transfer for fd %x", fds[i]); return LIBUSB_ERROR_NOT_FOUND; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 0c23ca630..5a8011243 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 10923 +#define LIBUSB_NANO 10924 From 8c4f86b9f54d50833f7ee30b56f0e5cfdab494ee Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Mon, 15 Dec 2014 11:46:41 +0100 Subject: [PATCH 005/222] API: Add an Application Programming Interface page This page lists the all the public functions, structures and enums provided by libusb. The HTML page is generated by Doxygen. --- libusb/core.c | 149 ++++++++++++++++++++++++++++++++++++++++++ libusb/version_nano.h | 2 +- 2 files changed, 150 insertions(+), 1 deletion(-) diff --git a/libusb/core.c b/libusb/core.c index a39a17315..c992747de 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -94,6 +94,10 @@ struct list_head active_contexts_list; * Specification which is available for free download. You can probably * find less verbose introductions by searching the web. * + * \section API Application Programming Interface (API) + * + * See the \ref api page for a complete list of the libusb functions. + * * \section features Library features * * - All transfer types supported (control/bulk/interrupt/isochronous) @@ -325,6 +329,151 @@ if (cfg != desired) * can infer the context from those objects. */ + /** + * \page api Application Programming Interface + * + * This is the complete list of libusb functions, structures and + * enumerations in alphabetical order. + * + * \section Functions + * - libusb_alloc_streams() + * - libusb_alloc_transfer() + * - libusb_attach_kernel_driver() + * - libusb_bulk_transfer() + * - libusb_cancel_transfer() + * - libusb_claim_interface() + * - libusb_clear_halt() + * - libusb_close() + * - libusb_control_transfer() + * - libusb_control_transfer_get_data() + * - libusb_control_transfer_get_setup() + * - libusb_cpu_to_le16() + * - libusb_detach_kernel_driver() + * - libusb_error_name() + * - libusb_event_handler_active() + * - libusb_event_handling_ok() + * - libusb_exit() + * - libusb_fill_bulk_stream_transfer() + * - libusb_fill_bulk_transfer() + * - libusb_fill_control_setup() + * - libusb_fill_control_transfer() + * - libusb_fill_interrupt_transfer() + * - libusb_fill_iso_transfer() + * - libusb_free_bos_descriptor() + * - libusb_free_config_descriptor() + * - libusb_free_container_id_descriptor() + * - libusb_free_device_list() + * - libusb_free_ss_endpoint_companion_descriptor() + * - libusb_free_ss_usb_device_capability_descriptor() + * - libusb_free_streams() + * - libusb_free_transfer() + * - libusb_free_usb_2_0_extension_descriptor() + * - libusb_get_active_config_descriptor() + * - libusb_get_bos_descriptor() + * - libusb_get_bus_number() + * - libusb_get_config_descriptor() + * - libusb_get_config_descriptor_by_value() + * - libusb_get_configuration() + * - libusb_get_container_id_descriptor() + * - libusb_get_descriptor() + * - libusb_get_device() + * - libusb_get_device_address() + * - libusb_get_device_descriptor() + * - libusb_get_device_list() + * - libusb_get_device_speed() + * - libusb_get_iso_packet_buffer() + * - libusb_get_iso_packet_buffer_simple() + * - libusb_get_max_iso_packet_size() + * - libusb_get_max_packet_size() + * - libusb_get_next_timeout() + * - libusb_get_parent() + * - libusb_get_port_number() + * - libusb_get_port_numbers() + * - libusb_get_ss_endpoint_companion_descriptor() + * - libusb_get_ss_usb_device_capability_descriptor() + * - libusb_get_string_descriptor() + * - libusb_get_string_descriptor_ascii() + * - libusb_get_usb_2_0_extension_descriptor() + * - libusb_get_version() + * - libusb_handle_events() + * - libusb_handle_events_completed() + * - libusb_handle_events_locked() + * - libusb_handle_events_timeout() + * - libusb_handle_events_timeout_completed() + * - libusb_has_capability() + * - libusb_hotplug_deregister_callback() + * - libusb_hotplug_register_callback() + * - libusb_init() + * - libusb_interrupt_transfer() + * - libusb_kernel_driver_active() + * - libusb_lock_events() + * - libusb_lock_event_waiters() + * - libusb_open() + * - libusb_open_device_with_vid_pid() + * - libusb_pollfds_handle_timeouts() + * - libusb_ref_device() + * - libusb_release_interface() + * - libusb_reset_device() + * - libusb_set_auto_detach_kernel_driver() + * - libusb_set_configuration() + * - libusb_set_debug() + * - libusb_set_interface_alt_setting() + * - libusb_set_iso_packet_lengths() + * - libusb_setlocale() + * - libusb_set_pollfd_notifiers() + * - libusb_strerror() + * - libusb_submit_transfer() + * - libusb_transfer_get_stream_id() + * - libusb_transfer_set_stream_id() + * - libusb_try_lock_events() + * - libusb_unlock_events() + * - libusb_unlock_event_waiters() + * - libusb_unref_device() + * - libusb_wait_for_event() + * + * \section Structures + * - libusb_bos_descriptor + * - libusb_bos_dev_capability_descriptor + * - libusb_config_descriptor + * - libusb_container_id_descriptor + * - \ref libusb_context + * - libusb_control_setup + * - \ref libusb_device + * - libusb_device_descriptor + * - \ref libusb_device_handle + * - libusb_endpoint_descriptor + * - libusb_interface + * - libusb_interface_descriptor + * - libusb_iso_packet_descriptor + * - libusb_pollfd + * - libusb_ss_endpoint_companion_descriptor + * - libusb_ss_usb_device_capability_descriptor + * - libusb_transfer + * - libusb_usb_2_0_extension_descriptor + * - libusb_version + * + * \section Enums + * - \ref libusb_bos_type + * - \ref libusb_capability + * - \ref libusb_class_code + * - \ref libusb_descriptor_type + * - \ref libusb_endpoint_direction + * - \ref libusb_error + * - \ref libusb_iso_sync_type + * - \ref libusb_iso_usage_type + * - \ref libusb_log_level + * - \ref libusb_request_recipient + * - \ref libusb_request_type + * - \ref libusb_speed + * - \ref libusb_ss_usb_device_capability_attributes + * - \ref libusb_standard_request + * - \ref libusb_supported_speed + * - \ref libusb_transfer_flags + * - \ref libusb_transfer_status + * - \ref libusb_transfer_type + * - \ref libusb_usb_2_0_extension_attributes + */ + /** * @defgroup lib Library initialization/deinitialization * This page details how to initialize and deinitialize libusb. Initialization diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 5a8011243..5f534d05d 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 10924 +#define LIBUSB_NANO 10926 From e82c9b2b46828ef590a66ab5a8aa629ddfacbfe2 Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Tue, 16 Dec 2014 21:17:16 +0100 Subject: [PATCH 006/222] API: remove unused libusb_hotplug_callback struct The structure libusb_hotplug_callback was declared (but not defined) and never used in the public API. --- libusb/libusb.h | 1 - libusb/version_nano.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libusb/libusb.h b/libusb/libusb.h index 79b255fa2..9285b1d83 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -900,7 +900,6 @@ struct libusb_control_setup { struct libusb_context; struct libusb_device; struct libusb_device_handle; -struct libusb_hotplug_callback; /** \ingroup lib * Structure providing the version of the libusb runtime diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 5f534d05d..f038975d2 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 10926 +#define LIBUSB_NANO 10927 From de6130dc0d09d1416ca7f5bc6af80c04b2e2f840 Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Tue, 16 Dec 2014 21:47:44 +0100 Subject: [PATCH 007/222] Doxygen: fix a duplicate label libusb/hotplug.c:46: warning: multiple use of section label 'intro' while adding section, (first occurrence: libusb/core.c, line 79) Use label "hotplug_intro" instead of "intro" --- libusb/hotplug.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/hotplug.c b/libusb/hotplug.c index eba8f98b5..9ecb2c74e 100644 --- a/libusb/hotplug.c +++ b/libusb/hotplug.c @@ -43,7 +43,7 @@ * * \page hotplug Device hotplug event notification * - * \section intro Introduction + * \section hotplug_intro Introduction * * Version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102, has added support * for hotplug events on some platforms (you should test if your platform diff --git a/libusb/version_nano.h b/libusb/version_nano.h index f038975d2..ec29ede58 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 10927 +#define LIBUSB_NANO 10928 From 7e725e556a1a17f256878517c345e702f4a5858b Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Tue, 16 Dec 2014 21:50:19 +0100 Subject: [PATCH 008/222] Doxygen: fix a duplicate label libusb/io.c:46: warning: multiple use of section label 'intro' while adding section, (first occurrence: libusb/core.c, line 79) Use label "io_intro" instead of "intro" --- libusb/io.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/io.c b/libusb/io.c index 2bc122ca9..9cf38f886 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -43,7 +43,7 @@ /** * \page io Synchronous and asynchronous device I/O * - * \section intro Introduction + * \section io_intro Introduction * * If you're using libusb in your application, you're probably wanting to * perform I/O with devices - you want to perform USB data transfers. diff --git a/libusb/version_nano.h b/libusb/version_nano.h index ec29ede58..5a60da37a 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 10928 +#define LIBUSB_NANO 10929 From 7924c1fc67e72e238f24f8fae63d44006de19e85 Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Tue, 16 Dec 2014 21:55:37 +0100 Subject: [PATCH 009/222] Doxygen: upgrade doxygen.cfg.in file Warning: Tag `XML_SCHEMA' at line 942 of file `doxygen.cfg' has become obsolete. To avoid this warning please remove this line from your configuration file or upgrade it using "doxygen -u" Warning: Tag `XML_DTD' at line 948 of file `doxygen.cfg' has become obsolete. To avoid this warning please remove this line from your configuration file or upgrade it using "doxygen -u" I upgrade the doxygen.cfg.in using: "doxygen -u doxygen.cfg.in" The configuration file changed from Doxyfile 1.5.3 to Doxyfile 1.8.8 --- doc/doxygen.cfg.in | 2524 +++++++++++++++++++++++++++++------------ libusb/version_nano.h | 2 +- 2 files changed, 1786 insertions(+), 740 deletions(-) diff --git a/doc/doxygen.cfg.in b/doc/doxygen.cfg.in index bb5e0c0ab..d26ae3338 100644 --- a/doc/doxygen.cfg.in +++ b/doc/doxygen.cfg.in @@ -1,35 +1,42 @@ -# Doxyfile 1.5.3 +# Doxyfile 1.8.8 # This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project +# doxygen (www.doxygen.org) for a project. # -# All text after a hash (#) is considered a comment and will be ignored +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. # The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- -# This tag specifies the encoding used for all characters in the config file that -# follow. The default is UTF-8 which is also the encoding used for all text before -# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into -# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of -# possible encodings. +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. PROJECT_NAME = -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. PROJECT_NUMBER = @@ -39,1250 +46,2289 @@ PROJECT_NUMBER = PROJECT_BRIEF = "A cross-platform user library to access USB devices" -# With the PROJECT_LOGO tag one can specify an logo or icon that is included -# in the documentation. The maximum height of the logo should not exceed 55 -# pixels and the maximum width should not exceed 200 pixels. Doxygen will -# copy the logo to the output directory. +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. PROJECT_LOGO = libusb.png -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. -OUTPUT_DIRECTORY = +OUTPUT_DIRECTORY = -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. CREATE_SUBDIRS = NO -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, -# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, -# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, -# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. OUTPUT_LANGUAGE = English -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. +# The default value is: YES. REPEAT_BRIEF = YES -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. -ABBREVIATE_BRIEF = +ABBREVIATE_BRIEF = -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief # description. +# The default value is: NO. ALWAYS_DETAILED_SEC = NO -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. +# The default value is: NO. INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. FULL_PATH_NAMES = NO -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. -STRIP_FROM_PATH = +STRIP_FROM_PATH = -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. -STRIP_FROM_INC_PATH = +STRIP_FROM_INC_PATH = -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. SHORT_NAMES = NO -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. JAVADOC_AUTOBRIEF = YES -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. QT_AUTOBRIEF = NO -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. INHERIT_DOCS = YES -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. SEPARATE_MEMBER_PAGES = NO -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. -ALIASES = +ALIASES = -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = YES -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for Java. -# For instance, namespaces will be presented as packages, qualified scopes -# will look different, etc. +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to -# include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. +# The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. +# The default value is: NO. CPP_CLI_SUPPORT = NO -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. +# The default value is: NO. DISTRIBUTE_GROUP_DOC = NO -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. SUBGROUPING = YES +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. EXTRACT_ALL = NO -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. EXTRACT_PRIVATE = NO -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. EXTRACT_STATIC = YES -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. EXTRACT_LOCAL_CLASSES = YES -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. EXTRACT_LOCAL_METHODS = NO -# If this flag is set to YES, the members of anonymous namespaces will be extracted -# and appear in the documentation as a namespace called 'anonymous_namespace{file}', -# where file will be replaced with the base name of the file that contains the anonymous -# namespace. By default anonymous namespace are hidden. +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. EXTRACT_ANON_NSPACES = NO -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_MEMBERS = NO -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_CLASSES = NO -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. HIDE_IN_BODY_DOCS = NO -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. +# The default value is: system dependent. CASE_SENSE_NAMES = YES -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. HIDE_SCOPE_NAMES = NO -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. SHOW_INCLUDE_FILES = YES -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. INLINE_INFO = YES -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. SORT_MEMBER_DOCS = NO -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. SORT_BRIEF_DOCS = NO -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. SORT_BY_SCOPE_NAME = NO -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. GENERATE_TODOLIST = YES -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. GENERATE_TESTLIST = YES -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. GENERATE_BUGLIST = YES -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. GENERATE_DEPRECATEDLIST= YES -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. -ENABLED_SECTIONS = +ENABLED_SECTIONS = -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. SHOW_USED_FILES = YES -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from the -# version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. -FILE_VERSION_FILTER = +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = #--------------------------------------------------------------------------- -# configuration options related to warning and progress messages +# Configuration options related to warning and progress messages #--------------------------------------------------------------------------- -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. QUIET = YES -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. WARNINGS = YES -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. WARN_IF_UNDOCUMENTED = YES -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. WARN_IF_DOC_ERROR = YES -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. WARN_NO_PARAMDOC = NO -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). -WARN_LOGFILE = +WARN_LOGFILE = #--------------------------------------------------------------------------- -# configuration options related to the input files +# Configuration options related to the input files #--------------------------------------------------------------------------- -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. INPUT = @top_srcdir@/libusb -# This tag can be used to specify the character encoding of the source files that -# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default -# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. -# See http://www.gnu.org/software/libiconv for the list of possible encodings. +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. INPUT_ENCODING = UTF-8 -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. -FILE_PATTERNS = +FILE_PATTERNS = -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. RECURSIVE = NO -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. -EXCLUDE = @top_srcdir@/libusb/libusbi.h @top_srcdir@/libusb/hotplug.h +EXCLUDE = @top_srcdir@/libusb/libusbi.h \ + @top_srcdir@/libusb/hotplug.h -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded # from the input. +# The default value is: NO. EXCLUDE_SYMLINKS = NO -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the output. -# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, -# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* -EXCLUDE_SYMBOLS = +EXCLUDE_SYMBOLS = -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). -EXAMPLE_PATH = +EXAMPLE_PATH = -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. -EXAMPLE_PATTERNS = +EXAMPLE_PATTERNS = -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. EXAMPLE_RECURSIVE = NO -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). -IMAGE_PATH = +IMAGE_PATH = -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. If FILTER_PATTERNS is specified, this tag will be -# ignored. +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. -INPUT_FILTER = +INPUT_FILTER = -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. -FILTER_PATTERNS = +FILTER_PATTERNS = -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. FILTER_SOURCE_FILES = NO +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + #--------------------------------------------------------------------------- -# configuration options related to source browsing +# Configuration options related to source browsing #--------------------------------------------------------------------------- -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH -# then you must also enable this option. If you don't then doxygen will produce -# a warning and turn it on anyway +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. SOURCE_BROWSER = NO -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. INLINE_SOURCES = NO -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. STRIP_CODE_COMMENTS = YES -# If the REFERENCED_BY_RELATION tag is set to YES (the default) -# then for each documented function all documented -# functions referencing it will be listed. +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. REFERENCED_BY_RELATION = NO -# If the REFERENCES_RELATION tag is set to YES (the default) -# then for each documented function all documented entities -# called/used by that function will be listed. +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. REFERENCES_RELATION = NO -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. Otherwise they will link to the documentstion. +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. REFERENCES_LINK_SOURCE = YES -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index +# Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. ALPHABETICAL_INDEX = YES -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. -IGNORE_PREFIX = +IGNORE_PREFIX = #--------------------------------------------------------------------------- -# configuration options related to the HTML output +# Configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. GENERATE_HTML = YES -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a # standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra stylesheet files is of importance (e.g. the last +# stylesheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = +HTML_DYNAMIC_SECTIONS = YES -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) -# of the generated HTML documentation. +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = YES - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be # written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. -CHM_FILE = +CHM_FILE = -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. -HHC_LOCATION = +HHC_LOCATION = -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. -ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO -# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be -# generated containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, -# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are -# probably better off using the HTML help feature. +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. -GENERATE_TREEVIEW = NO +ENUM_VALUES_PER_LINE = 4 -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , / @@ -408,7 +408,7 @@ > - + @@ -155,7 +155,7 @@ - + diff --git a/msvc/libusb_dll_2010.vcxproj.filters b/msvc/libusb_dll_2010.vcxproj.filters index 7a4578c5b..c77654bdd 100644 --- a/msvc/libusb_dll_2010.vcxproj.filters +++ b/msvc/libusb_dll_2010.vcxproj.filters @@ -38,7 +38,7 @@ Source Files - + Source Files @@ -61,7 +61,7 @@ Header Files - + Header Files diff --git a/msvc/libusb_dll_2012.vcxproj b/msvc/libusb_dll_2012.vcxproj index adcad4ad0..65e1a3416 100644 --- a/msvc/libusb_dll_2012.vcxproj +++ b/msvc/libusb_dll_2012.vcxproj @@ -150,7 +150,7 @@ - + @@ -161,7 +161,7 @@ - + diff --git a/msvc/libusb_dll_2012.vcxproj.filters b/msvc/libusb_dll_2012.vcxproj.filters index ccada704b..6120953fe 100644 --- a/msvc/libusb_dll_2012.vcxproj.filters +++ b/msvc/libusb_dll_2012.vcxproj.filters @@ -35,7 +35,7 @@ Source Files - + Source Files @@ -58,7 +58,7 @@ Header Files - + Header Files diff --git a/msvc/libusb_dll_2013.vcxproj b/msvc/libusb_dll_2013.vcxproj index d2ee6755b..6f79468d6 100644 --- a/msvc/libusb_dll_2013.vcxproj +++ b/msvc/libusb_dll_2013.vcxproj @@ -151,7 +151,7 @@ - + @@ -163,7 +163,7 @@ - + diff --git a/msvc/libusb_dll_2015.vcxproj b/msvc/libusb_dll_2015.vcxproj index 85d9823c0..44ea2507e 100644 --- a/msvc/libusb_dll_2015.vcxproj +++ b/msvc/libusb_dll_2015.vcxproj @@ -151,7 +151,7 @@ - + @@ -163,7 +163,7 @@ - + diff --git a/msvc/libusb_sources b/msvc/libusb_sources index f9718cfe8..a0387d91e 100644 --- a/msvc/libusb_sources +++ b/msvc/libusb_sources @@ -34,6 +34,6 @@ SOURCES=..\core.c \ ..\hotplug.c \ threads_windows.c \ poll_windows.c \ - windows_usb.c \ + windows_winusb.c \ windows_nt_common.c \ ..\libusb-1.0.rc diff --git a/msvc/libusb_static.dsp b/msvc/libusb_static.dsp index afdbbeddb..7eddf7988 100644 --- a/msvc/libusb_static.dsp +++ b/msvc/libusb_static.dsp @@ -119,7 +119,7 @@ SOURCE=..\libusb\os\threads_windows.c # End Source File # Begin Source File -SOURCE=..\libusb\os\windows_usb.c +SOURCE=..\libusb\os\windows_winusb.c # End Source File # End Group # Begin Group "Header Files" @@ -163,7 +163,7 @@ SOURCE=..\libusb\os\threads_windows.h # End Source File # Begin Source File -SOURCE=..\libusb\os\windows_usb.h +SOURCE=..\libusb\os\windows_winusb.h # End Source File # Begin Source File diff --git a/msvc/libusb_static_2005.vcproj b/msvc/libusb_static_2005.vcproj index f7b8e4590..5ba681934 100644 --- a/msvc/libusb_static_2005.vcproj +++ b/msvc/libusb_static_2005.vcproj @@ -314,7 +314,7 @@ > @@ -348,7 +348,7 @@ > - + @@ -147,7 +147,7 @@ - + diff --git a/msvc/libusb_static_2010.vcxproj.filters b/msvc/libusb_static_2010.vcxproj.filters index 5cd806065..cce80014c 100644 --- a/msvc/libusb_static_2010.vcxproj.filters +++ b/msvc/libusb_static_2010.vcxproj.filters @@ -32,7 +32,7 @@ Source Files - + Source Files @@ -55,7 +55,7 @@ Header Files - + Header Files diff --git a/msvc/libusb_static_2012.vcxproj b/msvc/libusb_static_2012.vcxproj index 88605ba24..5cce2b860 100644 --- a/msvc/libusb_static_2012.vcxproj +++ b/msvc/libusb_static_2012.vcxproj @@ -140,7 +140,7 @@ - + @@ -151,7 +151,7 @@ - + diff --git a/msvc/libusb_static_2012.vcxproj.filters b/msvc/libusb_static_2012.vcxproj.filters index 5cd806065..cce80014c 100644 --- a/msvc/libusb_static_2012.vcxproj.filters +++ b/msvc/libusb_static_2012.vcxproj.filters @@ -32,7 +32,7 @@ Source Files - + Source Files @@ -55,7 +55,7 @@ Header Files - + Header Files diff --git a/msvc/libusb_static_2013.vcxproj b/msvc/libusb_static_2013.vcxproj index f980ae3c7..4ea706f12 100644 --- a/msvc/libusb_static_2013.vcxproj +++ b/msvc/libusb_static_2013.vcxproj @@ -141,7 +141,7 @@ - + @@ -153,7 +153,7 @@ - + diff --git a/msvc/libusb_static_2015.vcxproj b/msvc/libusb_static_2015.vcxproj index b50cdf272..510ef5cca 100644 --- a/msvc/libusb_static_2015.vcxproj +++ b/msvc/libusb_static_2015.vcxproj @@ -145,7 +145,7 @@ - + @@ -157,7 +157,7 @@ - + From 8823c17024c59984c2dcf5870e27ab3a023428b9 Mon Sep 17 00:00:00 2001 From: Dmitry Fleytman Date: Wed, 20 Jan 2016 17:05:54 +0200 Subject: [PATCH 110/222] usbdk: Introduce usbdk backend Signed-off-by: Pavel Gurvich Signed-off-by: Dmitry Fleytman Signed-off-by: Chris Dickens --- libusb/core.c | 6 + libusb/libusbi.h | 1 + libusb/os/windows_usbdk.c | 952 +++++++++++++++++++++++++++++++++++++ libusb/os/windows_usbdk.h | 126 +++++ libusb/os/windows_winusb.c | 4 + libusb/version_nano.h | 2 +- 6 files changed, 1090 insertions(+), 1 deletion(-) create mode 100644 libusb/os/windows_usbdk.c create mode 100644 libusb/os/windows_usbdk.h diff --git a/libusb/core.c b/libusb/core.c index 067cd4924..90491e6cb 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -53,7 +53,13 @@ const struct usbi_os_backend * const usbi_backend = &openbsd_backend; #elif defined(OS_NETBSD) const struct usbi_os_backend * const usbi_backend = &netbsd_backend; #elif defined(OS_WINDOWS) + +#if defined(USE_USBDK) +const struct usbi_os_backend * const usbi_backend = &usbdk_backend; +#else const struct usbi_os_backend * const usbi_backend = &windows_backend; +#endif + #elif defined(OS_WINCE) const struct usbi_os_backend * const usbi_backend = &wince_backend; #elif defined(OS_HAIKU) diff --git a/libusb/libusbi.h b/libusb/libusbi.h index d69d61342..2d229da39 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -1118,6 +1118,7 @@ extern const struct usbi_os_backend darwin_backend; extern const struct usbi_os_backend openbsd_backend; extern const struct usbi_os_backend netbsd_backend; extern const struct usbi_os_backend windows_backend; +extern const struct usbi_os_backend usbdk_backend; extern const struct usbi_os_backend wince_backend; extern const struct usbi_os_backend haiku_usb_raw_backend; diff --git a/libusb/os/windows_usbdk.c b/libusb/os/windows_usbdk.c new file mode 100644 index 000000000..3336d9a58 --- /dev/null +++ b/libusb/os/windows_usbdk.c @@ -0,0 +1,952 @@ +/* + * windows UsbDk backend for libusb 1.0 + * Copyright © 2014 Red Hat, Inc. + + * Authors: + * Dmitry Fleytman + * Pavel Gurvich + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#if defined(USE_USBDK) + +#include +#include +#include + +#include "libusbi.h" +#include "windows_common.h" +#include "windows_nt_common.h" + +#define ULONG64 uint64_t +#define PVOID64 uint64_t + +typedef CONST WCHAR *PCWCHAR; +#define wcsncpy_s wcsncpy + +#include "windows_usbdk.h" + +#if !defined(STATUS_SUCCESS) +typedef LONG NTSTATUS; +#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) +#endif + +#if !defined(STATUS_CANCELLED) +#define STATUS_CANCELLED ((NTSTATUS)0xC0000120L) +#endif + +#if !defined(STATUS_REQUEST_CANCELED) +#define STATUS_REQUEST_CANCELED ((NTSTATUS)0xC0000703L) +#endif + +#if !defined(USBD_SUCCESS) +typedef int32_t USBD_STATUS; +#define USBD_SUCCESS(Status) ((USBD_STATUS) (Status) >= 0) +#define USBD_PENDING(Status) ((ULONG) (Status) >> 30 == 1) +#define USBD_ERROR(Status) ((USBD_STATUS) (Status) < 0) +#define USBD_STATUS_STALL_PID ((USBD_STATUS) 0xc0000004) +#define USBD_STATUS_ENDPOINT_HALTED ((USBD_STATUS) 0xc0000030) +#define USBD_STATUS_BAD_START_FRAME ((USBD_STATUS) 0xc0000a00) +#define USBD_STATUS_TIMEOUT ((USBD_STATUS) 0xc0006000) +#define USBD_STATUS_CANCELED ((USBD_STATUS) 0xc0010000) +#endif + +static int concurrent_usage = -1; +static int init_succeeded = 0; + +struct usbdk_device_priv { + USB_DK_DEVICE_INFO info; + PUSB_CONFIGURATION_DESCRIPTOR *config_descriptors; + HANDLE redirector_handle; + uint8_t active_configuration; +}; + +struct usbdk_device_handle_priv { + //This field is to solve compilation error on VS2013: + //error C2016: C requires that a struct or union has at least one member + int dummy; +}; + +struct usbdk_transfer_priv { + USB_DK_TRANSFER_REQUEST request; + struct winfd pollable_fd; + PULONG64 IsochronousPacketsArray; + PUSB_DK_ISO_TRANSFER_RESULT IsochronousResultsArray; +}; + +static inline struct usbdk_device_priv *_usbdk_device_priv(struct libusb_device *dev) +{ + return (struct usbdk_device_priv*) dev->os_priv; +} + +static inline struct usbdk_transfer_priv *_usbdk_transfer_priv(struct usbi_transfer *itransfer) +{ + return (struct usbdk_transfer_priv*) usbi_transfer_get_os_priv(itransfer); +} + +static struct { + HMODULE module; + + USBDK_GET_DEVICES_LIST GetDevicesList; + USBDK_RELEASE_DEVICES_LIST ReleaseDevicesList; + USBDK_START_REDIRECT StartRedirect; + USBDK_STOP_REDIRECT StopRedirect; + USBDK_GET_CONFIGURATION_DESCRIPTOR GetConfigurationDescriptor; + USBDK_RELEASE_CONFIGURATION_DESCRIPTOR ReleaseConfigurationDescriptor; + USBDK_READ_PIPE ReadPipe; + USBDK_WRITE_PIPE WritePipe; + USBDK_ABORT_PIPE AbortPipe; + USBDK_RESET_PIPE ResetPipe; + USBDK_SET_ALTSETTING SetAltsetting; + USBDK_RESET_DEVICE ResetDevice; + USBDK_GET_REDIRECTOR_SYSTEM_HANDLE GetRedirectorSystemHandle; +} usbdk_helper; + +static FARPROC get_usbdk_proc_addr(struct libusb_context *ctx, LPCSTR api_name) +{ + FARPROC api_ptr = GetProcAddress(usbdk_helper.module, api_name); + if (api_ptr == NULL) { + DWORD err = GetLastError(); + usbi_err(ctx, "UsbDkHelper API %s not found, error %d", api_name, err); + } + + return api_ptr; +} + +static void unload_usbdk_helper_dll(void) +{ + FreeLibrary(usbdk_helper.module); +} + +static int load_usbdk_helper_dll(struct libusb_context *ctx) +{ + usbdk_helper.module = LoadLibraryA("UsbDkHelper"); + if (usbdk_helper.module == NULL) { + DWORD err = GetLastError(); + usbi_err(ctx, "Failed to load UsbDkHelper.dll, error %d", err); + return LIBUSB_ERROR_NOT_FOUND; + } + + usbdk_helper.GetDevicesList = (USBDK_GET_DEVICES_LIST) get_usbdk_proc_addr(ctx, "UsbDk_GetDevicesList"); + if (usbdk_helper.GetDevicesList == NULL) { + goto error_unload; + } + + usbdk_helper.ReleaseDevicesList = (USBDK_RELEASE_DEVICES_LIST) get_usbdk_proc_addr(ctx, "UsbDk_ReleaseDevicesList"); + if (usbdk_helper.ReleaseDevicesList == NULL) { + goto error_unload; + } + + usbdk_helper.StartRedirect = (USBDK_START_REDIRECT) get_usbdk_proc_addr(ctx, "UsbDk_StartRedirect"); + if (usbdk_helper.StartRedirect == NULL) { + goto error_unload; + } + + usbdk_helper.StopRedirect = (USBDK_STOP_REDIRECT) get_usbdk_proc_addr(ctx, "UsbDk_StopRedirect"); + if (usbdk_helper.StopRedirect == NULL) { + goto error_unload; + } + + usbdk_helper.GetConfigurationDescriptor = (USBDK_GET_CONFIGURATION_DESCRIPTOR) get_usbdk_proc_addr(ctx, "UsbDk_GetConfigurationDescriptor"); + if (usbdk_helper.GetConfigurationDescriptor == NULL) { + goto error_unload; + } + + usbdk_helper.ReleaseConfigurationDescriptor = (USBDK_RELEASE_CONFIGURATION_DESCRIPTOR) get_usbdk_proc_addr(ctx, "UsbDk_ReleaseConfigurationDescriptor"); + if (usbdk_helper.ReleaseConfigurationDescriptor == NULL) { + goto error_unload; + } + + usbdk_helper.ReadPipe = (USBDK_READ_PIPE) get_usbdk_proc_addr(ctx, "UsbDk_ReadPipe"); + if (usbdk_helper.ReadPipe == NULL) { + goto error_unload; + } + + usbdk_helper.WritePipe = (USBDK_WRITE_PIPE) get_usbdk_proc_addr(ctx, "UsbDk_WritePipe"); + if (usbdk_helper.WritePipe == NULL) { + goto error_unload; + } + + usbdk_helper.AbortPipe = (USBDK_ABORT_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_AbortPipe"); + if (usbdk_helper.AbortPipe == NULL) { + goto error_unload; + } + + usbdk_helper.ResetPipe = (USBDK_RESET_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_ResetPipe"); + if (usbdk_helper.ResetPipe == NULL) { + goto error_unload; + } + + usbdk_helper.SetAltsetting = (USBDK_SET_ALTSETTING)get_usbdk_proc_addr(ctx, "UsbDk_SetAltsetting"); + if (usbdk_helper.SetAltsetting == NULL) { + goto error_unload; + } + + usbdk_helper.ResetDevice = (USBDK_RESET_DEVICE)get_usbdk_proc_addr(ctx, "UsbDk_ResetDevice"); + if (usbdk_helper.ResetDevice == NULL) { + goto error_unload; + } + + usbdk_helper.GetRedirectorSystemHandle = (USBDK_GET_REDIRECTOR_SYSTEM_HANDLE)get_usbdk_proc_addr(ctx, "UsbDk_GetRedirectorSystemHandle"); + if (usbdk_helper.GetRedirectorSystemHandle == NULL) { + goto error_unload; + } + + return LIBUSB_SUCCESS; + +error_unload: + FreeLibrary(usbdk_helper.module); + return LIBUSB_ERROR_NOT_FOUND; +} + +static int usbdk_init(struct libusb_context *ctx) +{ + int r; + + if ((++concurrent_usage == 0) || !init_succeeded) { + r = load_usbdk_helper_dll(ctx); + if (r) { + return r; + } + + init_polling(); + + r = windows_common_init(ctx); + if (r) { + goto error_roll_back; + } + + init_succeeded = 1; + } + + return LIBUSB_SUCCESS; + +error_roll_back: + windows_common_exit(); + unload_usbdk_helper_dll(); + return r; +} + +static int usbdk_get_session_id_for_device(struct libusb_context *ctx, + PUSB_DK_DEVICE_ID id, + unsigned long* session_id) +{ + char dev_identity[ARRAYSIZE(id->DeviceID) + ARRAYSIZE(id->InstanceID)]; + + if (sprintf(dev_identity, "%S%S", id->DeviceID, id->InstanceID) == -1) { + usbi_warn(ctx, "cannot form device identity", id->DeviceID); + return LIBUSB_ERROR_NOT_SUPPORTED; + } + + *session_id = htab_hash(dev_identity); + + return LIBUSB_SUCCESS; +} + +static void usbdk_release_config_descriptors(struct usbdk_device_priv* p, uint8_t count) +{ + uint8_t i; + for (i = 0; i < count; i++) { + usbdk_helper.ReleaseConfigurationDescriptor(p->config_descriptors[i]); + } + free(p->config_descriptors); + p->config_descriptors = NULL; +} + +static int usbdk_cache_config_descriptors(struct libusb_context *ctx, + struct usbdk_device_priv* p, + PUSB_DK_DEVICE_INFO info) +{ + uint8_t i; + USB_DK_CONFIG_DESCRIPTOR_REQUEST Request; + Request.ID = info->ID; + + p->config_descriptors = calloc(info->DeviceDescriptor.bNumConfigurations, + sizeof(PUSB_CONFIGURATION_DESCRIPTOR)); + if (p->config_descriptors == NULL) { + usbi_err(ctx, "failed to allocate configuration descriptors holder"); + return LIBUSB_ERROR_NO_MEM; + } + + for (i = 0; i < info->DeviceDescriptor.bNumConfigurations; i++) { + ULONG Length; + + Request.Index = i; + if (!usbdk_helper.GetConfigurationDescriptor(&Request, + &p->config_descriptors[i], + &Length)) { + usbi_err(ctx, "failed to retrieve configuration descriptors"); + usbdk_release_config_descriptors(p, i); + return LIBUSB_ERROR_OTHER; + } + } + + return LIBUSB_SUCCESS; +} + +static inline int usbdk_device_priv_init(struct libusb_context *ctx, libusb_device* dev, PUSB_DK_DEVICE_INFO info) +{ + struct usbdk_device_priv* p = _usbdk_device_priv(dev); + p->info = *info; + p->active_configuration = 0; + return usbdk_cache_config_descriptors(ctx, p, info); +} + +static void usbdk_device_init(libusb_device* dev, PUSB_DK_DEVICE_INFO info) +{ + dev->bus_number = (uint8_t) info->FilterID; + dev->port_number = (uint8_t) info->Port; + dev->parent_dev = NULL; + + //Addresses in libusb are 1-based + dev->device_address = (uint8_t) info->Port + 1; + + dev->num_configurations = info->DeviceDescriptor.bNumConfigurations; + dev->device_descriptor = info->DeviceDescriptor; + + switch (info->Speed) + { + case LowSpeed: + dev->speed = LIBUSB_SPEED_LOW; + break; + case FullSpeed: + dev->speed = LIBUSB_SPEED_FULL; + break; + case HighSpeed: + dev->speed = LIBUSB_SPEED_HIGH; + break; + case SuperSpeed: + dev->speed = LIBUSB_SPEED_SUPER; + break; + case NoSpeed: + default: + dev->speed = LIBUSB_SPEED_UNKNOWN; + break; + } +} + +static int usbdk_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs) +{ + int r = LIBUSB_SUCCESS; + ULONG i; + + struct discovered_devs *discdevs = NULL; + ULONG dev_number; + PUSB_DK_DEVICE_INFO devices; + + if(!usbdk_helper.GetDevicesList(&devices, &dev_number)) { + return LIBUSB_ERROR_OTHER; + } + + for (i = 0; i < dev_number; ++i) { + unsigned long session_id; + struct libusb_device *dev = NULL; + + if (usbdk_get_session_id_for_device(ctx, &devices[i].ID, &session_id)) { + continue; + } + + dev = usbi_get_device_by_session_id(ctx, session_id); + if (dev == NULL) { + dev = usbi_alloc_device(ctx, session_id); + if (dev == NULL) { + usbi_err(ctx, "failed to allocate a new device structure"); + continue; + } + + usbdk_device_init(dev, &devices[i]); + if (usbdk_device_priv_init(ctx, dev, &devices[i]) != LIBUSB_SUCCESS) { + libusb_unref_device(dev); + continue; + } + } + + discdevs = discovered_devs_append(*_discdevs, dev); + + libusb_unref_device(dev); + + if (!discdevs) + { + usbi_err(ctx, "cannot append new device to list"); + r = LIBUSB_ERROR_NO_MEM; + goto func_exit; + } + *_discdevs = discdevs; + } + +func_exit: + usbdk_helper.ReleaseDevicesList(devices); + return r; +} + +static void usbdk_exit(void) +{ + if ((--concurrent_usage < 0) && init_succeeded) { + windows_common_exit(); + exit_polling(); + unload_usbdk_helper_dll(); + init_succeeded = 0; + } +} + +static int usbdk_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian) +{ + struct usbdk_device_priv *priv = _usbdk_device_priv(dev); + + memcpy(buffer, &priv->info.DeviceDescriptor, DEVICE_DESC_LENGTH); + *host_endian = 0; + + return LIBUSB_SUCCESS; +} + +static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) +{ + struct usbdk_device_priv *priv = _usbdk_device_priv(dev); + PUSB_CONFIGURATION_DESCRIPTOR config_header; + size_t size; + + if (config_index >= dev->num_configurations) + return LIBUSB_ERROR_INVALID_PARAM; + + config_header = (PUSB_CONFIGURATION_DESCRIPTOR) priv->config_descriptors[config_index]; + + size = min(config_header->wTotalLength, len); + memcpy(buffer, config_header, size); + *host_endian = 0; + + return (int)size; +} + +static inline int usbdk_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian) +{ + return usbdk_get_config_descriptor(dev, _usbdk_device_priv(dev)->active_configuration, + buffer, len, host_endian); +} + +static int usbdk_open(struct libusb_device_handle *dev_handle) +{ + struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); + + priv->redirector_handle = usbdk_helper.StartRedirect(&priv->info.ID); + if (priv->redirector_handle == INVALID_HANDLE_VALUE) + { + usbi_err(DEVICE_CTX(dev_handle->dev), "Redirector startup failed"); + return LIBUSB_ERROR_OTHER; + } + + return LIBUSB_SUCCESS; +} + +static void usbdk_close(struct libusb_device_handle *dev_handle) +{ + struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); + + if (!usbdk_helper.StopRedirect(priv->redirector_handle)) + { + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + usbi_err(ctx, "Redirector shutdown failed"); + } +} + +static int usbdk_get_configuration(struct libusb_device_handle *dev_handle, int *config) +{ + *config = _usbdk_device_priv(dev_handle->dev)->active_configuration; + return LIBUSB_SUCCESS; +} + +static int usbdk_set_configuration(struct libusb_device_handle *dev_handle, int config) +{ + UNREFERENCED_PARAMETER(dev_handle); + UNREFERENCED_PARAMETER(config); + return LIBUSB_SUCCESS; +} + +static int usbdk_claim_interface(struct libusb_device_handle *dev_handle, int iface) +{ + UNREFERENCED_PARAMETER(dev_handle); + UNREFERENCED_PARAMETER(iface); + return LIBUSB_SUCCESS; +} + +static int usbdk_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) +{ + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); + + if (!usbdk_helper.SetAltsetting(priv->redirector_handle, iface, altsetting)) { + usbi_err(ctx, "SetAltsetting failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } + + return LIBUSB_SUCCESS; +} + +static int usbdk_release_interface(struct libusb_device_handle *dev_handle, int iface) +{ + UNREFERENCED_PARAMETER(dev_handle); + UNREFERENCED_PARAMETER(iface); + return LIBUSB_SUCCESS; +} + +static int usbdk_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) +{ + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); + + if (!usbdk_helper.ResetPipe(priv->redirector_handle, endpoint)) { + usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } + + return LIBUSB_SUCCESS; +} + +static int usbdk_reset_device(struct libusb_device_handle *dev_handle) +{ + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); + + if (!usbdk_helper.ResetDevice(priv->redirector_handle)) { + usbi_err(ctx, "ResetDevice failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } + + return LIBUSB_SUCCESS; +} + +static int usbdk_kernel_driver_active(struct libusb_device_handle *dev_handle, int iface) +{ + UNREFERENCED_PARAMETER(dev_handle); + UNREFERENCED_PARAMETER(iface); + return LIBUSB_ERROR_NOT_SUPPORTED; +} + +static int usbdk_attach_kernel_driver(struct libusb_device_handle *dev_handle, int iface) +{ + UNREFERENCED_PARAMETER(dev_handle); + UNREFERENCED_PARAMETER(iface); + return LIBUSB_ERROR_NOT_SUPPORTED; +} + +static int usbdk_detach_kernel_driver(struct libusb_device_handle *dev_handle, int iface) +{ + UNREFERENCED_PARAMETER(dev_handle); + UNREFERENCED_PARAMETER(iface); + return LIBUSB_ERROR_NOT_SUPPORTED; +} + +static void usbdk_destroy_device(struct libusb_device *dev) +{ + struct usbdk_device_priv* p = _usbdk_device_priv(dev); + + if (p->config_descriptors != NULL) + { + usbdk_release_config_descriptors(p, p->info.DeviceDescriptor.bNumConfigurations); + } +} + +void windows_clear_transfer_priv(struct usbi_transfer *itransfer) +{ + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + usbi_free_fd(&transfer_priv->pollable_fd); + + if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS){ + safe_free(transfer_priv->IsochronousPacketsArray); + safe_free(transfer_priv->IsochronousResultsArray); + } +} + +static int usbdk_do_control_transfer(struct usbi_transfer *itransfer) +{ + ULONG Length; + TransferResult transResult; + + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + + HANDLE sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); + + struct winfd wfd = usbi_create_fd(sysHandle, RW_READ, NULL, NULL); + // Always use the handle returned from usbi_create_fd (wfd.handle) + if (wfd.fd < 0) { + return LIBUSB_ERROR_NO_MEM; + } + + transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; + transfer_priv->request.BufferLength = transfer->length; + transfer_priv->request.TransferType = ControlTransferType; + transfer_priv->pollable_fd = INVALID_WINFD; + Length = (ULONG)transfer->length; + + if (IS_XFERIN(transfer)) { + transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + } + else { + transResult = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + } + + + switch (transResult) + { + case TransferSuccess: + wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; + wfd.overlapped->InternalHigh = (DWORD)Length; + break; + case TransferSuccessAsync: + break; + case TransferFailure: + { + usbi_err(ctx, "ControlTransfer failed: %s", windows_error_str(0)); + usbi_free_fd(&wfd); + return LIBUSB_ERROR_IO; + } + } + + // Use priv_transfer to store data needed for async polling + transfer_priv->pollable_fd = wfd; + usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN); + return LIBUSB_SUCCESS; +} + +static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winfd wfd; + TransferResult transferRes; + HANDLE sysHandle; + + transfer_priv->request.Buffer = (PVOID64) (uintptr_t) transfer->buffer; + transfer_priv->request.BufferLength = transfer->length; + transfer_priv->request.EndpointAddress = transfer->endpoint; + + switch (transfer->type) + { + case LIBUSB_TRANSFER_TYPE_BULK: + transfer_priv->request.TransferType = BulkTransferType; + break; + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + transfer_priv->request.TransferType = IntertuptTransferType; + break; + default: + usbi_err(ctx, "Wrong transfer type (%d) in usbdk_do_bulk_transfer. %s", transfer->type, windows_error_str(0)); + return LIBUSB_ERROR_INVALID_PARAM; + } + + transfer_priv->pollable_fd = INVALID_WINFD; + + sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); + + wfd = usbi_create_fd(sysHandle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL); + // Always use the handle returned from usbi_create_fd (wfd.handle) + if (wfd.fd < 0) { + return LIBUSB_ERROR_NO_MEM; + } + + if (IS_XFERIN(transfer)) { + transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + } + else { + transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + } + + switch (transferRes) + { + case TransferSuccess: + wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; + break; + case TransferSuccessAsync: + break; + case TransferFailure: + { + usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); + usbi_free_fd(&wfd); + return LIBUSB_ERROR_IO; + } + } + + transfer_priv->pollable_fd = wfd; + usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, (short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT)); + return LIBUSB_SUCCESS; +} + +static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winfd wfd; + TransferResult transferRes; + int i; + HANDLE sysHandle; + + transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; + transfer_priv->request.BufferLength = transfer->length; + transfer_priv->request.EndpointAddress = transfer->endpoint; + transfer_priv->request.TransferType = IsochronousTransferType; + transfer_priv->request.IsochronousPacketsArraySize = transfer->num_iso_packets; + transfer_priv->IsochronousPacketsArray = malloc(transfer->num_iso_packets * sizeof(ULONG64)); + transfer_priv->request.IsochronousPacketsArray = (PVOID64)(uintptr_t)transfer_priv->IsochronousPacketsArray; + if (!transfer_priv->IsochronousPacketsArray){ + usbi_err(ctx, "Allocation of IsochronousPacketsArray is failed, %s", windows_error_str(0)); + return LIBUSB_ERROR_IO; + } + + transfer_priv->IsochronousResultsArray = malloc(transfer->num_iso_packets * sizeof(USB_DK_ISO_TRANSFER_RESULT)); + transfer_priv->request.Result.IsochronousResultsArray = (PVOID64)(uintptr_t)transfer_priv->IsochronousResultsArray; + if (!transfer_priv->IsochronousResultsArray){ + usbi_err(ctx, "Allocation of isochronousResultsArray is failed, %s", windows_error_str(0)); + free(transfer_priv->IsochronousPacketsArray); + return LIBUSB_ERROR_IO; + } + + for (i = 0; i < transfer->num_iso_packets; i++){ + transfer_priv->IsochronousPacketsArray[i] = transfer->iso_packet_desc[i].length; + } + + transfer_priv->pollable_fd = INVALID_WINFD; + + sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); + + wfd = usbi_create_fd(sysHandle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL); + // Always use the handle returned from usbi_create_fd (wfd.handle) + if (wfd.fd < 0) { + free(transfer_priv->IsochronousPacketsArray); + free(transfer_priv->IsochronousResultsArray); + return LIBUSB_ERROR_NO_MEM; + } + + if (IS_XFERIN(transfer)) { + transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + } + else { + transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + } + + switch (transferRes){ + case TransferSuccess: + wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; + break; + case TransferSuccessAsync: + break; + case TransferFailure: + { + usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); + usbi_free_fd(&wfd); + free(transfer_priv->IsochronousPacketsArray); + free(transfer_priv->IsochronousResultsArray); + return LIBUSB_ERROR_IO; + } + } + + transfer_priv->pollable_fd = wfd; + usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, (short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT)); + + return LIBUSB_SUCCESS; +} + +static int usbdk_submit_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + return usbdk_do_control_transfer(itransfer); + + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + if (IS_XFEROUT(transfer) && transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) { + //TODO: Check whether we can support this in UsbDk + return LIBUSB_ERROR_NOT_SUPPORTED; + } else { + return usbdk_do_bulk_transfer(itransfer); + } + + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + return usbdk_do_iso_transfer(itransfer); + default: + usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); + return LIBUSB_ERROR_INVALID_PARAM; + } +} + +static int usbdk_abort_transfers(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); + + if (!usbdk_helper.AbortPipe(priv->redirector_handle, transfer->endpoint)) { + usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } + + return LIBUSB_SUCCESS; +} + +static int usbdk_cancel_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + // Control transfers cancelled by IoCancelXXX() API + // No special treatment needed + return LIBUSB_SUCCESS; + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + return usbdk_abort_transfers(itransfer); + default: + usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); + return LIBUSB_ERROR_INVALID_PARAM; + } +} + +int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size) +{ + itransfer->transferred += io_size; + return LIBUSB_TRANSFER_COMPLETED; +} + +struct winfd *windows_get_fd(struct usbi_transfer *transfer) +{ + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer); + return &transfer_priv->pollable_fd; +} + +static DWORD usbdk_translate_usbd_status(USBD_STATUS UsbdStatus) +{ + if (USBD_SUCCESS(UsbdStatus)) + { + return NO_ERROR; + } + + switch (UsbdStatus) + { + case USBD_STATUS_STALL_PID: + case USBD_STATUS_ENDPOINT_HALTED: + case USBD_STATUS_BAD_START_FRAME: + return ERROR_GEN_FAILURE; + case USBD_STATUS_TIMEOUT: + return ERROR_SEM_TIMEOUT; + case USBD_STATUS_CANCELED: + return ERROR_OPERATION_ABORTED; + default: + return ERROR_FUNCTION_FAILED; + } +} + +void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size) +{ + if (HasOverlappedIoCompletedSync(pollable_fd->overlapped) || // Handle async requests that completed synchronously first + GetOverlappedResult(pollable_fd->handle, pollable_fd->overlapped, io_size, false)) { // Regular async overlapped + struct libusb_transfer *ltransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer); + + if (ltransfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS){ + int i; + for (i = 0; i < transfer_priv->request.IsochronousPacketsArraySize; i++) { + struct libusb_iso_packet_descriptor *lib_desc = <ransfer->iso_packet_desc[i]; + + switch (transfer_priv->IsochronousResultsArray[i].TransferResult){ + case STATUS_SUCCESS: + case STATUS_CANCELLED: + case STATUS_REQUEST_CANCELED: + lib_desc->status = LIBUSB_TRANSFER_COMPLETED; // == ERROR_SUCCESS + break; + default: + lib_desc->status = LIBUSB_TRANSFER_ERROR; // ERROR_UNKNOWN_EXCEPTION; + break; + } + + lib_desc->actual_length = (unsigned int) transfer_priv->IsochronousResultsArray[i].ActualLength; + } + } + + *io_size = (DWORD) transfer_priv->request.Result.GenResult.BytesTransferred; + *io_result = usbdk_translate_usbd_status((USBD_STATUS) transfer_priv->request.Result.GenResult.UsbdStatus); + } + else { + *io_result = GetLastError(); + } +} + +static int usbdk_clock_gettime(int clk_id, struct timespec *tp) +{ + return windows_clock_gettime(clk_id, tp); +} + +const struct usbi_os_backend usbdk_backend = { + "Windows", + USBI_CAP_HAS_HID_ACCESS, + usbdk_init, + usbdk_exit, + + usbdk_get_device_list, + NULL, + usbdk_open, + usbdk_close, + + usbdk_get_device_descriptor, + usbdk_get_active_config_descriptor, + usbdk_get_config_descriptor, + NULL, + + usbdk_get_configuration, + usbdk_set_configuration, + usbdk_claim_interface, + usbdk_release_interface, + + usbdk_set_interface_altsetting, + usbdk_clear_halt, + usbdk_reset_device, + + NULL, + NULL, + + usbdk_kernel_driver_active, + usbdk_detach_kernel_driver, + usbdk_attach_kernel_driver, + + usbdk_destroy_device, + + usbdk_submit_transfer, + usbdk_cancel_transfer, + windows_clear_transfer_priv, + + windows_handle_events, + NULL, + + usbdk_clock_gettime, +#if defined(USBI_TIMERFD_AVAILABLE) + NULL, +#endif + sizeof(struct usbdk_device_priv), + sizeof(struct usbdk_device_handle_priv), + sizeof(struct usbdk_transfer_priv), +}; + +#endif /* USE_USBDK */ diff --git a/libusb/os/windows_usbdk.h b/libusb/os/windows_usbdk.h new file mode 100644 index 000000000..6b7173525 --- /dev/null +++ b/libusb/os/windows_usbdk.h @@ -0,0 +1,126 @@ +/* +* windows UsbDk backend for libusb 1.0 +* Copyright © 2014 Red Hat, Inc. + +* Authors: +* Dmitry Fleytman +* Pavel Gurvich +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +typedef struct tag_USB_DK_DEVICE_ID +{ + WCHAR DeviceID[MAX_DEVICE_ID_LEN]; + WCHAR InstanceID[MAX_DEVICE_ID_LEN]; +} USB_DK_DEVICE_ID, *PUSB_DK_DEVICE_ID; + +static inline +void UsbDkFillIDStruct(USB_DK_DEVICE_ID *ID, PCWCHAR DeviceID, PCWCHAR InstanceID) +{ + wcsncpy_s(ID->DeviceID, DeviceID, MAX_DEVICE_ID_LEN); + wcsncpy_s(ID->InstanceID, InstanceID, MAX_DEVICE_ID_LEN); +} + +typedef struct tag_USB_DK_DEVICE_INFO +{ + USB_DK_DEVICE_ID ID; + ULONG64 FilterID; + ULONG64 Port; + ULONG64 Speed; + USB_DEVICE_DESCRIPTOR DeviceDescriptor; +} USB_DK_DEVICE_INFO, *PUSB_DK_DEVICE_INFO; + +typedef struct tag_USB_DK_CONFIG_DESCRIPTOR_REQUEST +{ + USB_DK_DEVICE_ID ID; + ULONG64 Index; +} USB_DK_CONFIG_DESCRIPTOR_REQUEST, *PUSB_DK_CONFIG_DESCRIPTOR_REQUEST; + +typedef struct tag_USB_DK_ISO_TRANSFER_RESULT +{ + ULONG64 ActualLength; + ULONG64 TransferResult; +} USB_DK_ISO_TRANSFER_RESULT, *PUSB_DK_ISO_TRANSFER_RESULT; + +typedef struct tag_USB_DK_GEN_TRANSFER_RESULT +{ + ULONG64 BytesTransferred; + ULONG64 UsbdStatus; // USBD_STATUS code +} USB_DK_GEN_TRANSFER_RESULT, *PUSB_DK_GEN_TRANSFER_RESULT; + +typedef struct tag_USB_DK_TRANSFER_RESULT +{ + USB_DK_GEN_TRANSFER_RESULT GenResult; + PVOID64 IsochronousResultsArray; // array of USB_DK_ISO_TRANSFER_RESULT +} USB_DK_TRANSFER_RESULT, *PUSB_DK_TRANSFER_RESULT; + +typedef struct tag_USB_DK_TRANSFER_REQUEST +{ + ULONG64 EndpointAddress; + PVOID64 Buffer; + ULONG64 BufferLength; + ULONG64 TransferType; + ULONG64 IsochronousPacketsArraySize; + PVOID64 IsochronousPacketsArray; + + USB_DK_TRANSFER_RESULT Result; +} USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST; + +typedef enum +{ + TransferFailure = 0, + TransferSuccess, + TransferSuccessAsync +} TransferResult; + +typedef enum +{ + NoSpeed = 0, + LowSpeed, + FullSpeed, + HighSpeed, + SuperSpeed +} USB_DK_DEVICE_SPEED; + +typedef enum +{ + ControlTransferType, + BulkTransferType, + IntertuptTransferType, + IsochronousTransferType +} USB_DK_TRANSFER_TYPE; + +typedef BOOL (__cdecl *USBDK_GET_DEVICES_LIST) (PUSB_DK_DEVICE_INFO *, PULONG); +typedef void (__cdecl *USBDK_RELEASE_DEVICES_LIST) (PUSB_DK_DEVICE_INFO); + +typedef HANDLE (__cdecl *USBDK_START_REDIRECT) (PUSB_DK_DEVICE_ID); +typedef BOOL (__cdecl *USBDK_STOP_REDIRECT) (HANDLE); + +typedef BOOL (__cdecl *USBDK_GET_CONFIGURATION_DESCRIPTOR) (PUSB_DK_CONFIG_DESCRIPTOR_REQUEST Request, + PUSB_CONFIGURATION_DESCRIPTOR *Descriptor, + PULONG Length); +typedef void (__cdecl *USBDK_RELEASE_CONFIGURATION_DESCRIPTOR) (PUSB_CONFIGURATION_DESCRIPTOR Descriptor); + +typedef TransferResult (__cdecl *USBDK_WRITE_PIPE) (HANDLE DeviceHandle, PUSB_DK_TRANSFER_REQUEST Request, LPOVERLAPPED lpOverlapped); +typedef TransferResult (__cdecl *USBDK_READ_PIPE) (HANDLE DeviceHandle, PUSB_DK_TRANSFER_REQUEST Request, LPOVERLAPPED lpOverlapped); +typedef BOOL (__cdecl *USBDK_ABORT_PIPE) (HANDLE DeviceHandle, ULONG64 PipeAddress); +typedef BOOL (__cdecl *USBDK_RESET_PIPE) (HANDLE DeviceHandle, ULONG64 PipeAddress); +typedef BOOL (__cdecl *USBDK_SET_ALTSETTING) (HANDLE DeviceHandle, ULONG64 InterfaceIdx, ULONG64 AltSettingIdx); +typedef BOOL (__cdecl *USBDK_RESET_DEVICE) (HANDLE DeviceHandle); + +typedef HANDLE (__cdecl *USBDK_GET_REDIRECTOR_SYSTEM_HANDLE) (HANDLE DeviceHandle); diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 34ce46135..ef4009628 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -24,6 +24,8 @@ #include +#if !defined(USE_USBDK) + #include #include #include @@ -4138,3 +4140,5 @@ static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itran return priv->usb_interface[transfer_priv->interface_number].apib-> copy_transfer_data(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer, io_size); } + +#endif /* !USE_USBDK */ diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 36ec18ed7..dc96b181b 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11029 +#define LIBUSB_NANO 11030 From 24c528934236fd167adc162695a5bdbd60bf7842 Mon Sep 17 00:00:00 2001 From: Dmitry Fleytman Date: Wed, 20 Jan 2016 17:05:55 +0200 Subject: [PATCH 111/222] build: Integrate usbdk backend Signed-off-by: Dmitry Fleytman Signed-off-by: Chris Dickens --- configure.ac | 9 ++ libusb/Makefile.am | 10 +- libusb/version_nano.h | 2 +- msvc/ddk_build.cmd | 9 ++ msvc/libusb_2013.sln | 20 +++ msvc/libusb_2015.sln | 20 +++ msvc/libusb_sources | 7 +- msvc/libusb_usbdk_dll_2013.vcxproj | 178 ++++++++++++++++++++++++++ msvc/libusb_usbdk_dll_2015.vcxproj | 178 ++++++++++++++++++++++++++ msvc/libusb_usbdk_static_2013.vcxproj | 162 +++++++++++++++++++++++ msvc/libusb_usbdk_static_2015.vcxproj | 162 +++++++++++++++++++++++ 11 files changed, 753 insertions(+), 4 deletions(-) create mode 100644 msvc/libusb_usbdk_dll_2013.vcxproj create mode 100644 msvc/libusb_usbdk_dll_2015.vcxproj create mode 100644 msvc/libusb_usbdk_static_2013.vcxproj create mode 100644 msvc/libusb_usbdk_static_2015.vcxproj diff --git a/configure.ac b/configure.ac index 244cd41c0..ec71e6225 100644 --- a/configure.ac +++ b/configure.ac @@ -172,6 +172,14 @@ windows) LTLDFLAGS="${LTLDFLAGS} -avoid-version -Wl,--add-stdcall-alias" AC_DEFINE([POLL_NFDS_TYPE],[unsigned int],[type of second poll() argument]) AC_DEFINE([WINVER], 0x0501, [Oldest Windows version supported]) + + AC_ARG_ENABLE([usbdk], + [AC_HELP_STRING([--enable-usbdk], [use UsbDk Windows backend [default=no]])], + [], [enable_usbdk="no"]) + if test "x$enable_usbdk" = "xyes" ; then + AC_DEFINE(USE_USBDK, 1, [Use UsbDk Windows backend]) + fi + AC_SUBST(USE_USBDK) ;; haiku) AC_DEFINE(OS_HAIKU, 1, [Haiku backend]) @@ -193,6 +201,7 @@ AM_CONDITIONAL(OS_HAIKU, test "x$backend" = xhaiku) AM_CONDITIONAL(THREADS_POSIX, test "x$threads" = xposix) AM_CONDITIONAL(CREATE_IMPORT_LIB, test "x$create_import_lib" = "xyes") AM_CONDITIONAL(USE_UDEV, test "x$enable_udev" = xyes) +AM_CONDITIONAL(USE_USBDK, test "x$enable_usbdk" = xyes) if test "$threads" = posix; then AC_DEFINE(THREADS_POSIX, 1, [Use POSIX Threads]) fi diff --git a/libusb/Makefile.am b/libusb/Makefile.am index 4990ada51..971c5b202 100644 --- a/libusb/Makefile.am +++ b/libusb/Makefile.am @@ -17,6 +17,7 @@ COMMON_WINDOWS_SRC = os/windows_nt_common.h \ os/windows_common.h \ libusb-1.0.rc libusb-1.0.def WINDOWS_USB_SRC = os/windows_winusb.h os/windows_winusb.c $(COMMON_WINDOWS_SRC) +WINDOWS_USBDK_SRC = os/windows_usbdk.h os/windows_usbdk.c $(COMMON_WINDOWS_SRC) WINCE_USB_SRC = os/wince_usb.h os/wince_usb.c HAIKU_USB_SRC = os/haiku_usb.h os/haiku_usb_backend.cpp \ os/haiku_usb_raw.h os/haiku_usb_raw.cpp os/haiku_pollfs.cpp @@ -25,8 +26,8 @@ EXTRA_DIST = $(POSIX_POLL_SRC) $(POSIX_THREADS_SRC) \ $(WINDOWS_POLL_SRC) $(WINDOWS_THREADS_SRC) \ $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) \ $(OPENBSD_USB_SRC) $(NETBSD_USB_SRC) \ - $(WINDOWS_USB_SRC) $(WINCE_USB_SRC) \ - $(HAIKU_USB_SRC) \ + $(WINDOWS_USB_SRC) $(WINDOWS_USBDK_SRC) \ + $(WINCE_USB_SRC) $(HAIKU_USB_SRC) \ os/linux_udev.c os/linux_netlink.c if OS_LINUX @@ -59,7 +60,12 @@ libusb_1_0_la_LIBADD = libusb_haiku.la endif if OS_WINDOWS + +if USE_USBDK +OS_SRC = $(WINDOWS_USBDK_SRC) +else OS_SRC = $(WINDOWS_USB_SRC) +endif .rc.lo: $(AM_V_GEN)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(RCFLAGS) -i $< -o $@ diff --git a/libusb/version_nano.h b/libusb/version_nano.h index dc96b181b..88d988d9f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11030 +#define LIBUSB_NANO 11031 diff --git a/msvc/ddk_build.cmd b/msvc/ddk_build.cmd index aadab502e..c0b905abd 100644 --- a/msvc/ddk_build.cmd +++ b/msvc/ddk_build.cmd @@ -3,20 +3,29 @@ ::# you can pass the following arguments (case insensitive): ::# - "DLL" to build a DLL instead of a static library ::# - "/MT" to build a static library compatible with MSVC's /MT option (LIBCMT vs MSVCRT) +::# - "USBDK" to build with UsbDk backend if Test%BUILD_ALT_DIR%==Test goto usage ::# process commandline parameters set TARGET=LIBRARY set STATIC_LIBC= +set WITH_USBDK= set version=1.0 set PWD=%~dp0 set BUILD_CMD=build -bcwgZ -M2 +:more_args + if "%1" == "" goto no_more_args ::# /I for case insensitive if /I Test%1==TestDLL set TARGET=DYNLINK if /I Test%1==Test/MT set STATIC_LIBC=1 +if /I Test%1==TestUSBDK set WITH_USBDK=1 + +shift +goto more_args + :no_more_args cd ..\libusb\os diff --git a/msvc/libusb_2013.sln b/msvc/libusb_2013.sln index 9d04d2c51..fb05ded21 100644 --- a/msvc/libusb_2013.sln +++ b/msvc/libusb_2013.sln @@ -21,6 +21,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stress", "stress_2013.vcxpr EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hotplugtest", "hotplugtest_2013.vcxproj", "{99D2AC64-DC66-4422-91CE-6715C403C9E5}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-usbdk-1.0 (dll)", "libusb_usbdk_dll_2013.vcxproj", "{F53A5974-2319-48EB-A67B-27933AEDF14A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-usbdk-1.0 (static)", "libusb_usbdk_static_2013.vcxproj", "{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -93,6 +97,22 @@ Global {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|Win32.Build.0 = Release|Win32 {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|x64.ActiveCfg = Release|x64 {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|x64.Build.0 = Release|x64 + {F53A5974-2319-48EB-A67B-27933AEDF14A}.Debug|Win32.ActiveCfg = Debug|Win32 + {F53A5974-2319-48EB-A67B-27933AEDF14A}.Debug|Win32.Build.0 = Debug|Win32 + {F53A5974-2319-48EB-A67B-27933AEDF14A}.Debug|x64.ActiveCfg = Debug|x64 + {F53A5974-2319-48EB-A67B-27933AEDF14A}.Debug|x64.Build.0 = Debug|x64 + {F53A5974-2319-48EB-A67B-27933AEDF14A}.Release|Win32.ActiveCfg = Release|Win32 + {F53A5974-2319-48EB-A67B-27933AEDF14A}.Release|Win32.Build.0 = Release|Win32 + {F53A5974-2319-48EB-A67B-27933AEDF14A}.Release|x64.ActiveCfg = Release|x64 + {F53A5974-2319-48EB-A67B-27933AEDF14A}.Release|x64.Build.0 = Release|x64 + {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Debug|Win32.ActiveCfg = Debug|Win32 + {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Debug|Win32.Build.0 = Debug|Win32 + {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Debug|x64.ActiveCfg = Debug|x64 + {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Debug|x64.Build.0 = Debug|x64 + {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Release|Win32.ActiveCfg = Release|Win32 + {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Release|Win32.Build.0 = Release|Win32 + {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Release|x64.ActiveCfg = Release|x64 + {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/msvc/libusb_2015.sln b/msvc/libusb_2015.sln index da6706fff..c6bd0effe 100644 --- a/msvc/libusb_2015.sln +++ b/msvc/libusb_2015.sln @@ -21,6 +21,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stress", "stress_2015.vcxpr EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hotplugtest", "hotplugtest_2015.vcxproj", "{99D2AC64-DC66-4422-91CE-6715C403C9E5}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-usbdk-1.0 (dll)", "libusb_usbdk_dll_2015.vcxproj", "{F53A5974-2319-48EB-A67B-27933AEDF14A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-usbdk-1.0 (static)", "libusb_usbdk_static_2015.vcxproj", "{0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -93,6 +97,22 @@ Global {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|Win32.Build.0 = Release|Win32 {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|x64.ActiveCfg = Release|x64 {99D2AC64-DC66-4422-91CE-6715C403C9E5}.Release|x64.Build.0 = Release|x64 + {F53A5974-2319-48EB-A67B-27933AEDF14A}.Debug|Win32.ActiveCfg = Debug|Win32 + {F53A5974-2319-48EB-A67B-27933AEDF14A}.Debug|Win32.Build.0 = Debug|Win32 + {F53A5974-2319-48EB-A67B-27933AEDF14A}.Debug|x64.ActiveCfg = Debug|x64 + {F53A5974-2319-48EB-A67B-27933AEDF14A}.Debug|x64.Build.0 = Debug|x64 + {F53A5974-2319-48EB-A67B-27933AEDF14A}.Release|Win32.ActiveCfg = Release|Win32 + {F53A5974-2319-48EB-A67B-27933AEDF14A}.Release|Win32.Build.0 = Release|Win32 + {F53A5974-2319-48EB-A67B-27933AEDF14A}.Release|x64.ActiveCfg = Release|x64 + {F53A5974-2319-48EB-A67B-27933AEDF14A}.Release|x64.Build.0 = Release|x64 + {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Debug|Win32.ActiveCfg = Debug|Win32 + {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Debug|Win32.Build.0 = Debug|Win32 + {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Debug|x64.ActiveCfg = Debug|x64 + {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Debug|x64.Build.0 = Debug|x64 + {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Release|Win32.ActiveCfg = Release|Win32 + {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Release|Win32.Build.0 = Release|Win32 + {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Release|x64.ActiveCfg = Release|x64 + {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/msvc/libusb_sources b/msvc/libusb_sources index a0387d91e..591d7f613 100644 --- a/msvc/libusb_sources +++ b/msvc/libusb_sources @@ -12,8 +12,12 @@ USE_LIBCMT=1 USE_MSVCRT=1 !ENDIF +!IFDEF WITH_USBDK +BACKEND_DEFINES="/DUSE_USBDK" +!ENDIF + INCLUDES=..;..\..\msvc;$(DDK_INC_PATH) -C_DEFINES= $(C_DEFINES) $(LIBUSB_DEFINES) /DDDKBUILD +C_DEFINES= $(C_DEFINES) $(LIBUSB_DEFINES) $(BACKEND_DEFINES) /DDDKBUILD # http://jpassing.com/2009/10/21/ltcg-issues-with-the-win7amd64-environment-of-wdk-7600/ # prevents the following error when using the 64 bit static lib with Visual Studio 2010: @@ -35,5 +39,6 @@ SOURCES=..\core.c \ threads_windows.c \ poll_windows.c \ windows_winusb.c \ + windows_usbdk.c \ windows_nt_common.c \ ..\libusb-1.0.rc diff --git a/msvc/libusb_usbdk_dll_2013.vcxproj b/msvc/libusb_usbdk_dll_2013.vcxproj new file mode 100644 index 000000000..5fb1635dc --- /dev/null +++ b/msvc/libusb_usbdk_dll_2013.vcxproj @@ -0,0 +1,178 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + libusb-usbdk-1.0 (dll) + {F53A5974-2319-48EB-A67B-27933AEDF14A} + libusbdll + + + + DynamicLibrary + Unicode + true + v120 + + + DynamicLibrary + Unicode + v120 + + + DynamicLibrary + Unicode + true + v120 + + + DynamicLibrary + Unicode + v120 + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ + $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\ + $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ + $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\ + $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ + $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\ + $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ + $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\ + libusb-usbdk-1.0 + libusb-usbdk-1.0 + libusb-usbdk-1.0 + libusb-usbdk-1.0 + + + + Disabled + .;..\libusb;%(AdditionalIncludeDirectories) + _WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level4 + ProgramDatabase + + + $(OutDir)libusb-usbdk-1.0.dll + ..\libusb\libusb-1.0.def + libusb-1.0.rc;%(EmbedManagedResourceFile) + true + + + + + X64 + + + Disabled + .;..\libusb;%(AdditionalIncludeDirectories) + _WIN32;_WIN64;_DEBUG;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level4 + ProgramDatabase + + + $(OutDir)libusb-usbdk-1.0.dll + ..\libusb\libusb-1.0.def + libusb-1.0.rc;%(EmbedManagedResourceFile) + true + + + + + .;..\libusb;%(AdditionalIncludeDirectories) + _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) + MultiThreadedDLL + Level4 + + + $(OutDir)libusb-usbdk-1.0.dll + ..\libusb\libusb-1.0.def + libusb-1.0.rc;%(EmbedManagedResourceFile) + + + + + X64 + + + .;..\libusb;%(AdditionalIncludeDirectories) + _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) + MultiThreadedDLL + Level4 + + + $(OutDir)libusb-usbdk-1.0.dll + ..\libusb\libusb-1.0.def + libusb-1.0.rc;%(EmbedManagedResourceFile) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/libusb_usbdk_dll_2015.vcxproj b/msvc/libusb_usbdk_dll_2015.vcxproj new file mode 100644 index 000000000..ff3c64ba6 --- /dev/null +++ b/msvc/libusb_usbdk_dll_2015.vcxproj @@ -0,0 +1,178 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + libusb-usbdk-1.0 (dll) + {F53A5974-2319-48EB-A67B-27933AEDF14A} + libusbdll + + + + DynamicLibrary + Unicode + true + v140 + + + DynamicLibrary + Unicode + v140 + + + DynamicLibrary + Unicode + true + v140 + + + DynamicLibrary + Unicode + v140 + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ + $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\ + $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ + $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\ + $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ + $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\ + $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ + $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\ + libusb-usbdk-1.0 + libusb-usbdk-1.0 + libusb-usbdk-1.0 + libusb-usbdk-1.0 + + + + Disabled + .;..\libusb;%(AdditionalIncludeDirectories) + _WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level4 + ProgramDatabase + + + $(OutDir)libusb-usbdk-1.0.dll + ..\libusb\libusb-1.0.def + libusb-1.0.rc;%(EmbedManagedResourceFile) + true + + + + + X64 + + + Disabled + .;..\libusb;%(AdditionalIncludeDirectories) + _WIN32;_WIN64;_DEBUG;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level4 + ProgramDatabase + + + $(OutDir)libusb-usbdk-1.0.dll + ..\libusb\libusb-1.0.def + libusb-1.0.rc;%(EmbedManagedResourceFile) + true + + + + + .;..\libusb;%(AdditionalIncludeDirectories) + _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) + MultiThreadedDLL + Level4 + + + $(OutDir)libusb-usbdk-1.0.dll + ..\libusb\libusb-1.0.def + libusb-1.0.rc;%(EmbedManagedResourceFile) + + + + + X64 + + + .;..\libusb;%(AdditionalIncludeDirectories) + _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) + MultiThreadedDLL + Level4 + + + $(OutDir)libusb-usbdk-1.0.dll + ..\libusb\libusb-1.0.def + libusb-1.0.rc;%(EmbedManagedResourceFile) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/libusb_usbdk_static_2013.vcxproj b/msvc/libusb_usbdk_static_2013.vcxproj new file mode 100644 index 000000000..1447dbbcc --- /dev/null +++ b/msvc/libusb_usbdk_static_2013.vcxproj @@ -0,0 +1,162 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + libusb-usbdk-1.0 (static) + {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED} + libusb + + + + StaticLibrary + Unicode + true + v120 + + + StaticLibrary + Unicode + v120 + + + StaticLibrary + Unicode + true + v120 + + + StaticLibrary + Unicode + v120 + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ + $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\ + $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ + $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\ + $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ + $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\ + $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ + $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\ + libusb-usbdk-1.0 + libusb-usbdk-1.0 + libusb-usbdk-1.0 + libusb-usbdk-1.0 + + + + Disabled + .;..\libusb;%(AdditionalIncludeDirectories) + _WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) + MultiThreadedDebug + Level4 + ProgramDatabase + + + $(OutDir)libusb-usbdk-1.0.lib + + + + + X64 + + + Disabled + .;..\libusb;%(AdditionalIncludeDirectories) + _WIN32;_WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) + MultiThreadedDebug + Level4 + ProgramDatabase + + + $(OutDir)libusb-usbdk-1.0.lib + + + + + .;..\libusb;%(AdditionalIncludeDirectories) + _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) + MultiThreaded + Level4 + + + $(OutDir)libusb-usbdk-1.0.lib + + + + + X64 + + + .;..\libusb;%(AdditionalIncludeDirectories) + _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) + MultiThreaded + Level4 + + + $(OutDir)libusb-usbdk-1.0.lib + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/libusb_usbdk_static_2015.vcxproj b/msvc/libusb_usbdk_static_2015.vcxproj new file mode 100644 index 000000000..1d5df29dd --- /dev/null +++ b/msvc/libusb_usbdk_static_2015.vcxproj @@ -0,0 +1,162 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + libusb-usbdk-1.0 (static) + {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED} + libusb + + + + StaticLibrary + Unicode + true + v140 + + + StaticLibrary + Unicode + v140 + + + StaticLibrary + Unicode + true + v140 + + + StaticLibrary + Unicode + v140 + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ + $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\ + $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ + $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\ + $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ + $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\ + $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ + $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\ + libusb-usbdk-1.0 + libusb-usbdk-1.0 + libusb-usbdk-1.0 + libusb-usbdk-1.0 + + + + Disabled + .;..\libusb;%(AdditionalIncludeDirectories) + _WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) + MultiThreadedDebug + Level4 + ProgramDatabase + + + $(OutDir)libusb-usbdk-1.0.lib + + + + + X64 + + + Disabled + .;..\libusb;%(AdditionalIncludeDirectories) + _WIN32;_WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) + MultiThreadedDebug + Level4 + ProgramDatabase + + + $(OutDir)libusb-usbdk-1.0.lib + + + + + .;..\libusb;%(AdditionalIncludeDirectories) + _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) + MultiThreaded + Level4 + + + $(OutDir)libusb-usbdk-1.0.lib + + + + + X64 + + + .;..\libusb;%(AdditionalIncludeDirectories) + _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) + MultiThreaded + Level4 + + + $(OutDir)libusb-usbdk-1.0.lib + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 48bfef6c1d1d2275dc1999a8b7b55954983d809c Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Sat, 23 Jan 2016 23:08:09 -0800 Subject: [PATCH 112/222] Misc: Minor makefile cleanup Signed-off-by: Chris Dickens --- libusb/Makefile.am | 16 +++++++--------- libusb/version_nano.h | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libusb/Makefile.am b/libusb/Makefile.am index 971c5b202..15042d3d7 100644 --- a/libusb/Makefile.am +++ b/libusb/Makefile.am @@ -12,12 +12,10 @@ LINUX_USBFS_SRC = os/linux_usbfs.h os/linux_usbfs.c DARWIN_USB_SRC = os/darwin_usb.h os/darwin_usb.c OPENBSD_USB_SRC = os/openbsd_usb.c NETBSD_USB_SRC = os/netbsd_usb.c -COMMON_WINDOWS_SRC = os/windows_nt_common.h \ - os/windows_nt_common.c \ - os/windows_common.h \ - libusb-1.0.rc libusb-1.0.def -WINDOWS_USB_SRC = os/windows_winusb.h os/windows_winusb.c $(COMMON_WINDOWS_SRC) -WINDOWS_USBDK_SRC = os/windows_usbdk.h os/windows_usbdk.c $(COMMON_WINDOWS_SRC) +WINDOWS_COMMON_SRC = os/windows_nt_common.h os/windows_nt_common.c \ + os/windows_common.h libusb-1.0.rc libusb-1.0.def +WINDOWS_USB_SRC = os/windows_winusb.h os/windows_winusb.c +WINDOWS_USBDK_SRC = os/windows_usbdk.h os/windows_usbdk.c WINCE_USB_SRC = os/wince_usb.h os/wince_usb.c HAIKU_USB_SRC = os/haiku_usb.h os/haiku_usb_backend.cpp \ os/haiku_usb_raw.h os/haiku_usb_raw.cpp os/haiku_pollfs.cpp @@ -26,7 +24,7 @@ EXTRA_DIST = $(POSIX_POLL_SRC) $(POSIX_THREADS_SRC) \ $(WINDOWS_POLL_SRC) $(WINDOWS_THREADS_SRC) \ $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) \ $(OPENBSD_USB_SRC) $(NETBSD_USB_SRC) \ - $(WINDOWS_USB_SRC) $(WINDOWS_USBDK_SRC) \ + $(WINDOWS_COMMON_SRC) $(WINDOWS_USB_SRC) $(WINDOWS_USBDK_SRC) \ $(WINCE_USB_SRC) $(HAIKU_USB_SRC) \ os/linux_udev.c os/linux_netlink.c @@ -62,9 +60,9 @@ endif if OS_WINDOWS if USE_USBDK -OS_SRC = $(WINDOWS_USBDK_SRC) +OS_SRC = $(WINDOWS_USBDK_SRC) $(WINDOWS_COMMON_SRC) else -OS_SRC = $(WINDOWS_USB_SRC) +OS_SRC = $(WINDOWS_USB_SRC) $(WINDOWS_COMMON_SRC) endif .rc.lo: diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 88d988d9f..330e4563f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11031 +#define LIBUSB_NANO 11032 From a3ec36d3ecc268d2f8b9f1f9800cd438c57cab56 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Tue, 26 Jan 2016 23:40:33 -0800 Subject: [PATCH 113/222] Windows: Source file cleanup This commit addresses a few different issues: 1) Whitespace made consistent with the rest of the library source 2) Formatting of function and variable declarations made consistent with the rest of the library source 3) Functions and variables made static where possible 4) Definitions in header files moved if not used publicly Signed-off-by: Chris Dickens --- libusb/os/windows_common.h | 4 +- libusb/os/windows_nt_common.c | 739 +++++++++---------- libusb/os/windows_nt_common.h | 4 +- libusb/os/windows_usbdk.c | 1299 ++++++++++++++++----------------- libusb/os/windows_usbdk.h | 174 +++-- libusb/os/windows_winusb.c | 1272 +++++++++++++++++--------------- libusb/os/windows_winusb.h | 505 ++++++------- libusb/version_nano.h | 2 +- 8 files changed, 2009 insertions(+), 1990 deletions(-) diff --git a/libusb/os/windows_common.h b/libusb/os/windows_common.h index 466f31d98..45c59af44 100644 --- a/libusb/os/windows_common.h +++ b/libusb/os/windows_common.h @@ -58,9 +58,7 @@ #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) #endif -#define ERR_BUFFER_SIZE 256 -#define TIMER_REQUEST_RETRY_MS 100 -#define MAX_TIMER_SEMAPHORES 128 +#define ERR_BUFFER_SIZE 256 /* diff --git a/libusb/os/windows_nt_common.c b/libusb/os/windows_nt_common.c index d99e3b8aa..897286561 100644 --- a/libusb/os/windows_nt_common.c +++ b/libusb/os/windows_nt_common.c @@ -23,10 +23,10 @@ */ #include -#include + #include #include - +#include #include "libusbi.h" #include "windows_common.h" @@ -36,91 +36,96 @@ const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime // Global variables for clock_gettime mechanism -uint64_t hires_ticks_to_ps; -uint64_t hires_frequency; +static uint64_t hires_ticks_to_ps; +static uint64_t hires_frequency; -#define WM_TIMER_REQUEST (WM_USER + 1) -#define WM_TIMER_EXIT (WM_USER + 2) +#define TIMER_REQUEST_RETRY_MS 100 +#define WM_TIMER_REQUEST (WM_USER + 1) +#define WM_TIMER_EXIT (WM_USER + 2) // used for monotonic clock_gettime() struct timer_request { - struct timespec *tp; - HANDLE event; + struct timespec *tp; + HANDLE event; }; // Timer thread -HANDLE timer_thread = NULL; -DWORD timer_thread_id = 0; +static HANDLE timer_thread = NULL; +static DWORD timer_thread_id = 0; /* User32 dependencies */ DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, GetMessageA, (LPMSG, HWND, UINT, UINT)); DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, PeekMessageA, (LPMSG, HWND, UINT, UINT, UINT)); DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, PostThreadMessageA, (DWORD, UINT, WPARAM, LPARAM)); -static unsigned __stdcall windows_clock_gettime_threaded(void* param); +static unsigned __stdcall windows_clock_gettime_threaded(void *param); /* * Converts a windows error to human readable string * uses retval as errorcode, or, if 0, use GetLastError() */ #if defined(ENABLE_LOGGING) -char *windows_error_str(uint32_t retval) +const char *windows_error_str(DWORD retval) { - static char err_string[ERR_BUFFER_SIZE]; - - DWORD size; - ssize_t i; - uint32_t error_code, format_error; - - error_code = retval ? retval : GetLastError(); - - safe_sprintf(err_string, ERR_BUFFER_SIZE, "[%u] ", error_code); - - // Translate codes returned by SetupAPI. The ones we are dealing with are either - // in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes. - // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx - switch (error_code & 0xE0000000) { - case 0: - error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified - break; - case 0xE0000000: - error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF); - break; - default: - break; - } - - size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &err_string[safe_strlen(err_string)], - ERR_BUFFER_SIZE - (DWORD)safe_strlen(err_string), NULL); - if (size == 0) { - format_error = GetLastError(); - if (format_error) - safe_sprintf(err_string, ERR_BUFFER_SIZE, - "Windows error code %u (FormatMessage error code %u)", error_code, format_error); - else - safe_sprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", error_code); - } - else { - // Remove CR/LF terminators - for (i = safe_strlen(err_string) - 1; (i >= 0) && ((err_string[i] == 0x0A) || (err_string[i] == 0x0D)); i--) { - err_string[i] = 0; - } - } - return err_string; + static char err_string[ERR_BUFFER_SIZE]; + + DWORD error_code, format_error; + DWORD size; + ssize_t i; + + error_code = retval ? retval : GetLastError(); + + safe_sprintf(err_string, ERR_BUFFER_SIZE, "[%u] ", error_code); + + // Translate codes returned by SetupAPI. The ones we are dealing with are either + // in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes. + // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx + switch (error_code & 0xE0000000) { + case 0: + error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified + break; + case 0xE0000000: + error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF); + break; + default: + break; + } + + size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &err_string[safe_strlen(err_string)], + ERR_BUFFER_SIZE - (DWORD)safe_strlen(err_string), NULL); + if (size == 0) { + format_error = GetLastError(); + if (format_error) + safe_sprintf(err_string, ERR_BUFFER_SIZE, + "Windows error code %u (FormatMessage error code %u)", error_code, format_error); + else + safe_sprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", error_code); + } + else { + // Remove CR/LF terminators + for (i = safe_strlen(err_string) - 1; (i >= 0) && ((err_string[i] == 0x0A) || (err_string[i] == 0x0D)); i--) + err_string[i] = 0; + } + + return err_string; } #endif /* Hash table functions - modified From glibc 2.3.2: [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986 [Knuth] The Art of Computer Programming, part 3 (6.4) */ + +#define HTAB_SIZE 1021 + typedef struct htab_entry { unsigned long used; char* str; } htab_entry; -htab_entry* htab_table = NULL; -usbi_mutex_t htab_write_mutex = NULL; -unsigned long htab_size, htab_filled; + +static htab_entry *htab_table = NULL; +static usbi_mutex_t htab_write_mutex = NULL; +static unsigned long htab_size, htab_filled; /* For the used double hash method the table size has to be a prime. To correct the user given table size we need a prime test. This trivial @@ -141,7 +146,7 @@ static int isprime(unsigned long number) We allocate one element more as the found prime number says. This is done for more effective indexing as explained in the comment for the hash function. */ -int htab_create(struct libusb_context *ctx, unsigned long nel) +static bool htab_create(struct libusb_context *ctx, unsigned long nel) { if (htab_table != NULL) { usbi_err(ctx, "hash table already allocated"); @@ -152,7 +157,7 @@ int htab_create(struct libusb_context *ctx, unsigned long nel) // Change nel to the first prime number not smaller as nel. nel |= 1; - while(!isprime(nel)) + while (!isprime(nel)) nel += 2; htab_size = nel; @@ -160,47 +165,47 @@ int htab_create(struct libusb_context *ctx, unsigned long nel) htab_filled = 0; // allocate memory and zero out. - htab_table = (htab_entry*) calloc(htab_size + 1, sizeof(htab_entry)); + htab_table = calloc(htab_size + 1, sizeof(htab_entry)); if (htab_table == NULL) { usbi_err(ctx, "could not allocate space for hash table"); - return 0; + return false; } - return 1; + return true; } /* After using the hash table it has to be destroyed. */ -void htab_destroy(void) +static void htab_destroy(void) { - size_t i; - if (htab_table == NULL) { + unsigned long i; + + if (htab_table == NULL) return; - } - for (i=0; itp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency); - request->tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) / 1000) * hires_ticks_to_ps); - if (!SetEvent(request->event)) { - usbi_err(NULL, "SetEvent failed for timer request: %s", windows_error_str(0)); - } - break; - - case WM_TIMER_EXIT: - usbi_dbg("timer thread quitting"); - return 0; - } - - } + struct timer_request *request; + LARGE_INTEGER hires_counter; + MSG msg; + + // The following call will create this thread's message queue + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644946.aspx + pPeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); + + // Signal windows_init_clock() that we're ready to service requests + if (!SetEvent((HANDLE)param)) + usbi_dbg("SetEvent failed for timer init event: %s", windows_error_str(0)); + param = NULL; + + // Main loop - wait for requests + while (1) { + if (pGetMessageA(&msg, NULL, WM_TIMER_REQUEST, WM_TIMER_EXIT) == -1) { + usbi_err(NULL, "GetMessage failed for timer thread: %s", windows_error_str(0)); + return 1; + } + + switch (msg.message) { + case WM_TIMER_REQUEST: + // Requests to this thread are for hires always + // Microsoft says that this function always succeeds on XP and later + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904.aspx + request = (struct timer_request *)msg.lParam; + QueryPerformanceCounter(&hires_counter); + request->tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency); + request->tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) / 1000) * hires_ticks_to_ps); + if (!SetEvent(request->event)) + usbi_err(NULL, "SetEvent failed for timer request: %s", windows_error_str(0)); + break; + case WM_TIMER_EXIT: + usbi_dbg("timer thread quitting"); + return 0; + } + } } int windows_clock_gettime(int clk_id, struct timespec *tp) { - struct timer_request request; - FILETIME filetime; - ULARGE_INTEGER rtime; - DWORD r; - switch (clk_id) { - case USBI_CLOCK_MONOTONIC: - if (timer_thread) { - request.tp = tp; - request.event = CreateEvent(NULL, FALSE, FALSE, NULL); - if (request.event == NULL) { - return LIBUSB_ERROR_NO_MEM; - } - - if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_REQUEST, 0, (LPARAM)&request)) { - usbi_err(NULL, "PostThreadMessage failed for timer thread: %s", windows_error_str(0)); - CloseHandle(request.event); - return LIBUSB_ERROR_OTHER; - } - - do { - r = WaitForSingleObject(request.event, TIMER_REQUEST_RETRY_MS); - if (r == WAIT_TIMEOUT) { - usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?"); - } - else if (r == WAIT_FAILED) { - usbi_err(NULL, "WaitForSingleObject failed: %s", windows_error_str(0)); - } - } while (r == WAIT_TIMEOUT); - CloseHandle(request.event); - - if (r == WAIT_OBJECT_0) { - return LIBUSB_SUCCESS; - } else { - return LIBUSB_ERROR_OTHER; - } - } - // Fall through and return real-time if monotonic was not detected @ timer init - case USBI_CLOCK_REALTIME: - // We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx - // with a predef epoch_time to have an epoch that starts at 1970.01.01 00:00 - // Note however that our resolution is bounded by the Windows system time - // functions and is at best of the order of 1 ms (or, usually, worse) - GetSystemTimeAsFileTime(&filetime); - rtime.LowPart = filetime.dwLowDateTime; - rtime.HighPart = filetime.dwHighDateTime; - rtime.QuadPart -= epoch_time; - tp->tv_sec = (long)(rtime.QuadPart / 10000000); - tp->tv_nsec = (long)((rtime.QuadPart % 10000000) * 100); - return LIBUSB_SUCCESS; - default: - return LIBUSB_ERROR_INVALID_PARAM; - } + struct timer_request request; + FILETIME filetime; + ULARGE_INTEGER rtime; + DWORD r; + + switch (clk_id) { + case USBI_CLOCK_MONOTONIC: + if (timer_thread) { + request.tp = tp; + request.event = CreateEvent(NULL, FALSE, FALSE, NULL); + if (request.event == NULL) + return LIBUSB_ERROR_NO_MEM; + + if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_REQUEST, 0, (LPARAM)&request)) { + usbi_err(NULL, "PostThreadMessage failed for timer thread: %s", windows_error_str(0)); + CloseHandle(request.event); + return LIBUSB_ERROR_OTHER; + } + + do { + r = WaitForSingleObject(request.event, TIMER_REQUEST_RETRY_MS); + if (r == WAIT_TIMEOUT) + usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?"); + else if (r == WAIT_FAILED) + usbi_err(NULL, "WaitForSingleObject failed: %s", windows_error_str(0)); + } while (r == WAIT_TIMEOUT); + CloseHandle(request.event); + + if (r == WAIT_OBJECT_0) + return LIBUSB_SUCCESS; + else + return LIBUSB_ERROR_OTHER; + } + // Fall through and return real-time if monotonic was not detected @ timer init + case USBI_CLOCK_REALTIME: + // We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx + // with a predef epoch_time to have an epoch that starts at 1970.01.01 00:00 + // Note however that our resolution is bounded by the Windows system time + // functions and is at best of the order of 1 ms (or, usually, worse) + GetSystemTimeAsFileTime(&filetime); + rtime.LowPart = filetime.dwLowDateTime; + rtime.HighPart = filetime.dwHighDateTime; + rtime.QuadPart -= epoch_time; + tp->tv_sec = (long)(rtime.QuadPart / 10000000); + tp->tv_nsec = (long)((rtime.QuadPart % 10000000) * 100); + return LIBUSB_SUCCESS; + default: + return LIBUSB_ERROR_INVALID_PARAM; + } } static void windows_transfer_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size) { - int status, istatus; - - usbi_dbg("handling I/O completion with errcode %u, size %u", io_result, io_size); - - switch (io_result) { - case NO_ERROR: - status = windows_copy_transfer_data(itransfer, io_size); - break; - case ERROR_GEN_FAILURE: - usbi_dbg("detected endpoint stall"); - status = LIBUSB_TRANSFER_STALL; - break; - case ERROR_SEM_TIMEOUT: - usbi_dbg("detected semaphore timeout"); - status = LIBUSB_TRANSFER_TIMED_OUT; - break; - case ERROR_OPERATION_ABORTED: - istatus = windows_copy_transfer_data(itransfer, io_size); - if (istatus != LIBUSB_TRANSFER_COMPLETED) { - usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus); - } - if (itransfer->flags & USBI_TRANSFER_TIMED_OUT) { - usbi_dbg("detected timeout"); - status = LIBUSB_TRANSFER_TIMED_OUT; - } - else { - usbi_dbg("detected operation aborted"); - status = LIBUSB_TRANSFER_CANCELLED; - } - break; - default: - usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %u: %s", io_result, windows_error_str(io_result)); - status = LIBUSB_TRANSFER_ERROR; - break; - } - windows_clear_transfer_priv(itransfer); // Cancel polling - usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); + int status, istatus; + + usbi_dbg("handling I/O completion with errcode %u, size %u", io_result, io_size); + + switch (io_result) { + case NO_ERROR: + status = windows_copy_transfer_data(itransfer, io_size); + break; + case ERROR_GEN_FAILURE: + usbi_dbg("detected endpoint stall"); + status = LIBUSB_TRANSFER_STALL; + break; + case ERROR_SEM_TIMEOUT: + usbi_dbg("detected semaphore timeout"); + status = LIBUSB_TRANSFER_TIMED_OUT; + break; + case ERROR_OPERATION_ABORTED: + istatus = windows_copy_transfer_data(itransfer, io_size); + if (istatus != LIBUSB_TRANSFER_COMPLETED) + usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus); + if (itransfer->flags & USBI_TRANSFER_TIMED_OUT) { + usbi_dbg("detected timeout"); + status = LIBUSB_TRANSFER_TIMED_OUT; + } + else { + usbi_dbg("detected operation aborted"); + status = LIBUSB_TRANSFER_CANCELLED; + } + break; + default: + usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %u: %s", io_result, windows_error_str(io_result)); + status = LIBUSB_TRANSFER_ERROR; + break; + } + windows_clear_transfer_priv(itransfer); // Cancel polling + usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); } void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - windows_transfer_callback(itransfer, io_result, io_size); - break; - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - usbi_warn(ITRANSFER_CTX(itransfer), "bulk stream transfers are not yet supported on this platform"); - break; - default: - usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); - } + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + windows_transfer_callback(itransfer, io_result, io_size); + break; + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + usbi_warn(ITRANSFER_CTX(itransfer), "bulk stream transfers are not yet supported on this platform"); + break; + default: + usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); + } } int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) { - POLL_NFDS_TYPE i = 0; - bool found = false; - struct usbi_transfer *transfer; - struct winfd *pollable_fd = NULL; - DWORD io_size, io_result; - - usbi_mutex_lock(&ctx->open_devs_lock); - for (i = 0; i < nfds && num_ready > 0; i++) { - - usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); - - if (!fds[i].revents) { - continue; - } - - num_ready--; - - // Because a Windows OVERLAPPED is used for poll emulation, - // a pollable fd is created and stored with each transfer - usbi_mutex_lock(&ctx->flying_transfers_lock); - found = false; - list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { - pollable_fd = windows_get_fd(transfer); - if (pollable_fd->fd == fds[i].fd) { - found = true; - break; - } - } - usbi_mutex_unlock(&ctx->flying_transfers_lock); - - if (found) { - windows_get_overlapped_result(transfer, pollable_fd, &io_result, &io_size); - - usbi_remove_pollfd(ctx, pollable_fd->fd); - // let handle_callback free the event using the transfer wfd - // If you don't use the transfer wfd, you run a risk of trying to free a - // newly allocated wfd that took the place of the one from the transfer. - windows_handle_callback(transfer, io_result, io_size); - } else { - usbi_mutex_unlock(&ctx->open_devs_lock); - usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]); - return LIBUSB_ERROR_NOT_FOUND; - } - } - - usbi_mutex_unlock(&ctx->open_devs_lock); - return LIBUSB_SUCCESS; + POLL_NFDS_TYPE i = 0; + bool found = false; + struct usbi_transfer *transfer; + struct winfd *pollable_fd = NULL; + DWORD io_size, io_result; + + usbi_mutex_lock(&ctx->open_devs_lock); + for (i = 0; i < nfds && num_ready > 0; i++) { + + usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); + + if (!fds[i].revents) + continue; + + num_ready--; + + // Because a Windows OVERLAPPED is used for poll emulation, + // a pollable fd is created and stored with each transfer + usbi_mutex_lock(&ctx->flying_transfers_lock); + found = false; + list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { + pollable_fd = windows_get_fd(transfer); + if (pollable_fd->fd == fds[i].fd) { + found = true; + break; + } + } + usbi_mutex_unlock(&ctx->flying_transfers_lock); + + if (found) { + windows_get_overlapped_result(transfer, pollable_fd, &io_result, &io_size); + + usbi_remove_pollfd(ctx, pollable_fd->fd); + // let handle_callback free the event using the transfer wfd + // If you don't use the transfer wfd, you run a risk of trying to free a + // newly allocated wfd that took the place of the one from the transfer. + windows_handle_callback(transfer, io_result, io_size); + } else { + usbi_mutex_unlock(&ctx->open_devs_lock); + usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]); + return LIBUSB_ERROR_NOT_FOUND; + } + } + usbi_mutex_unlock(&ctx->open_devs_lock); + + return LIBUSB_SUCCESS; } int windows_common_init(struct libusb_context *ctx) { - static const unsigned long HTAB_SIZE = 1021; - - if (!windows_init_clock(ctx)){ - goto error_roll_back; - } + if (!windows_init_clock(ctx)) + goto error_roll_back; - if (!htab_create(ctx, HTAB_SIZE)) { - goto error_roll_back; - } + if (!htab_create(ctx, HTAB_SIZE)) + goto error_roll_back; - return LIBUSB_SUCCESS; + return LIBUSB_SUCCESS; error_roll_back: - windows_common_exit(); - - return LIBUSB_ERROR_NO_MEM; + windows_common_exit(); + return LIBUSB_ERROR_NO_MEM; } void windows_common_exit(void) { - htab_destroy(); - windows_destroy_clock(); + htab_destroy(); + windows_destroy_clock(); } diff --git a/libusb/os/windows_nt_common.h b/libusb/os/windows_nt_common.h index ac907ce12..ceb547bf6 100644 --- a/libusb/os/windows_nt_common.h +++ b/libusb/os/windows_nt_common.h @@ -42,7 +42,7 @@ typedef struct libusb_device_descriptor USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESC int windows_common_init(struct libusb_context *ctx); void windows_common_exit(void); -unsigned long htab_hash(char* str); +unsigned long htab_hash(const char *str); int windows_clock_gettime(int clk_id, struct timespec *tp); void windows_clear_transfer_priv(struct usbi_transfer *itransfer); @@ -54,5 +54,5 @@ void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready); #if defined(ENABLE_LOGGING) -char *windows_error_str(uint32_t retval); +const char *windows_error_str(DWORD retval); #endif diff --git a/libusb/os/windows_usbdk.c b/libusb/os/windows_usbdk.c index 3336d9a58..f2bea9338 100644 --- a/libusb/os/windows_usbdk.c +++ b/libusb/os/windows_usbdk.c @@ -43,910 +43,861 @@ typedef CONST WCHAR *PCWCHAR; #if !defined(STATUS_SUCCESS) typedef LONG NTSTATUS; -#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) +#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) #endif #if !defined(STATUS_CANCELLED) -#define STATUS_CANCELLED ((NTSTATUS)0xC0000120L) +#define STATUS_CANCELLED ((NTSTATUS)0xC0000120L) #endif #if !defined(STATUS_REQUEST_CANCELED) -#define STATUS_REQUEST_CANCELED ((NTSTATUS)0xC0000703L) +#define STATUS_REQUEST_CANCELED ((NTSTATUS)0xC0000703L) #endif #if !defined(USBD_SUCCESS) typedef int32_t USBD_STATUS; -#define USBD_SUCCESS(Status) ((USBD_STATUS) (Status) >= 0) -#define USBD_PENDING(Status) ((ULONG) (Status) >> 30 == 1) -#define USBD_ERROR(Status) ((USBD_STATUS) (Status) < 0) -#define USBD_STATUS_STALL_PID ((USBD_STATUS) 0xc0000004) -#define USBD_STATUS_ENDPOINT_HALTED ((USBD_STATUS) 0xc0000030) -#define USBD_STATUS_BAD_START_FRAME ((USBD_STATUS) 0xc0000a00) -#define USBD_STATUS_TIMEOUT ((USBD_STATUS) 0xc0006000) -#define USBD_STATUS_CANCELED ((USBD_STATUS) 0xc0010000) +#define USBD_SUCCESS(Status) ((USBD_STATUS) (Status) >= 0) +#define USBD_PENDING(Status) ((ULONG) (Status) >> 30 == 1) +#define USBD_ERROR(Status) ((USBD_STATUS) (Status) < 0) +#define USBD_STATUS_STALL_PID ((USBD_STATUS) 0xc0000004) +#define USBD_STATUS_ENDPOINT_HALTED ((USBD_STATUS) 0xc0000030) +#define USBD_STATUS_BAD_START_FRAME ((USBD_STATUS) 0xc0000a00) +#define USBD_STATUS_TIMEOUT ((USBD_STATUS) 0xc0006000) +#define USBD_STATUS_CANCELED ((USBD_STATUS) 0xc0010000) #endif static int concurrent_usage = -1; static int init_succeeded = 0; struct usbdk_device_priv { - USB_DK_DEVICE_INFO info; - PUSB_CONFIGURATION_DESCRIPTOR *config_descriptors; - HANDLE redirector_handle; - uint8_t active_configuration; + USB_DK_DEVICE_INFO info; + PUSB_CONFIGURATION_DESCRIPTOR *config_descriptors; + HANDLE redirector_handle; + uint8_t active_configuration; }; struct usbdk_device_handle_priv { - //This field is to solve compilation error on VS2013: - //error C2016: C requires that a struct or union has at least one member - int dummy; + //This field is to solve compilation error on VS2013: + //error C2016: C requires that a struct or union has at least one member + int dummy; }; struct usbdk_transfer_priv { - USB_DK_TRANSFER_REQUEST request; - struct winfd pollable_fd; - PULONG64 IsochronousPacketsArray; - PUSB_DK_ISO_TRANSFER_RESULT IsochronousResultsArray; + USB_DK_TRANSFER_REQUEST request; + struct winfd pollable_fd; + PULONG64 IsochronousPacketsArray; + PUSB_DK_ISO_TRANSFER_RESULT IsochronousResultsArray; }; static inline struct usbdk_device_priv *_usbdk_device_priv(struct libusb_device *dev) { - return (struct usbdk_device_priv*) dev->os_priv; + return (struct usbdk_device_priv *)dev->os_priv; } static inline struct usbdk_transfer_priv *_usbdk_transfer_priv(struct usbi_transfer *itransfer) { - return (struct usbdk_transfer_priv*) usbi_transfer_get_os_priv(itransfer); + return (struct usbdk_transfer_priv *)usbi_transfer_get_os_priv(itransfer); } static struct { - HMODULE module; - - USBDK_GET_DEVICES_LIST GetDevicesList; - USBDK_RELEASE_DEVICES_LIST ReleaseDevicesList; - USBDK_START_REDIRECT StartRedirect; - USBDK_STOP_REDIRECT StopRedirect; - USBDK_GET_CONFIGURATION_DESCRIPTOR GetConfigurationDescriptor; - USBDK_RELEASE_CONFIGURATION_DESCRIPTOR ReleaseConfigurationDescriptor; - USBDK_READ_PIPE ReadPipe; - USBDK_WRITE_PIPE WritePipe; - USBDK_ABORT_PIPE AbortPipe; - USBDK_RESET_PIPE ResetPipe; - USBDK_SET_ALTSETTING SetAltsetting; - USBDK_RESET_DEVICE ResetDevice; - USBDK_GET_REDIRECTOR_SYSTEM_HANDLE GetRedirectorSystemHandle; + HMODULE module; + + USBDK_GET_DEVICES_LIST GetDevicesList; + USBDK_RELEASE_DEVICES_LIST ReleaseDevicesList; + USBDK_START_REDIRECT StartRedirect; + USBDK_STOP_REDIRECT StopRedirect; + USBDK_GET_CONFIGURATION_DESCRIPTOR GetConfigurationDescriptor; + USBDK_RELEASE_CONFIGURATION_DESCRIPTOR ReleaseConfigurationDescriptor; + USBDK_READ_PIPE ReadPipe; + USBDK_WRITE_PIPE WritePipe; + USBDK_ABORT_PIPE AbortPipe; + USBDK_RESET_PIPE ResetPipe; + USBDK_SET_ALTSETTING SetAltsetting; + USBDK_RESET_DEVICE ResetDevice; + USBDK_GET_REDIRECTOR_SYSTEM_HANDLE GetRedirectorSystemHandle; } usbdk_helper; static FARPROC get_usbdk_proc_addr(struct libusb_context *ctx, LPCSTR api_name) { - FARPROC api_ptr = GetProcAddress(usbdk_helper.module, api_name); - if (api_ptr == NULL) { - DWORD err = GetLastError(); - usbi_err(ctx, "UsbDkHelper API %s not found, error %d", api_name, err); - } + FARPROC api_ptr = GetProcAddress(usbdk_helper.module, api_name); - return api_ptr; + if (api_ptr == NULL) { + DWORD err = GetLastError(); + usbi_err(ctx, "UsbDkHelper API %s not found, error %d", api_name, err); + } + + return api_ptr; } static void unload_usbdk_helper_dll(void) { - FreeLibrary(usbdk_helper.module); + FreeLibrary(usbdk_helper.module); } static int load_usbdk_helper_dll(struct libusb_context *ctx) { - usbdk_helper.module = LoadLibraryA("UsbDkHelper"); - if (usbdk_helper.module == NULL) { - DWORD err = GetLastError(); - usbi_err(ctx, "Failed to load UsbDkHelper.dll, error %d", err); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbdk_helper.GetDevicesList = (USBDK_GET_DEVICES_LIST) get_usbdk_proc_addr(ctx, "UsbDk_GetDevicesList"); - if (usbdk_helper.GetDevicesList == NULL) { - goto error_unload; - } - - usbdk_helper.ReleaseDevicesList = (USBDK_RELEASE_DEVICES_LIST) get_usbdk_proc_addr(ctx, "UsbDk_ReleaseDevicesList"); - if (usbdk_helper.ReleaseDevicesList == NULL) { - goto error_unload; - } - - usbdk_helper.StartRedirect = (USBDK_START_REDIRECT) get_usbdk_proc_addr(ctx, "UsbDk_StartRedirect"); - if (usbdk_helper.StartRedirect == NULL) { - goto error_unload; - } - - usbdk_helper.StopRedirect = (USBDK_STOP_REDIRECT) get_usbdk_proc_addr(ctx, "UsbDk_StopRedirect"); - if (usbdk_helper.StopRedirect == NULL) { - goto error_unload; - } - - usbdk_helper.GetConfigurationDescriptor = (USBDK_GET_CONFIGURATION_DESCRIPTOR) get_usbdk_proc_addr(ctx, "UsbDk_GetConfigurationDescriptor"); - if (usbdk_helper.GetConfigurationDescriptor == NULL) { - goto error_unload; - } - - usbdk_helper.ReleaseConfigurationDescriptor = (USBDK_RELEASE_CONFIGURATION_DESCRIPTOR) get_usbdk_proc_addr(ctx, "UsbDk_ReleaseConfigurationDescriptor"); - if (usbdk_helper.ReleaseConfigurationDescriptor == NULL) { - goto error_unload; - } - - usbdk_helper.ReadPipe = (USBDK_READ_PIPE) get_usbdk_proc_addr(ctx, "UsbDk_ReadPipe"); - if (usbdk_helper.ReadPipe == NULL) { - goto error_unload; - } - - usbdk_helper.WritePipe = (USBDK_WRITE_PIPE) get_usbdk_proc_addr(ctx, "UsbDk_WritePipe"); - if (usbdk_helper.WritePipe == NULL) { - goto error_unload; - } - - usbdk_helper.AbortPipe = (USBDK_ABORT_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_AbortPipe"); - if (usbdk_helper.AbortPipe == NULL) { - goto error_unload; - } - - usbdk_helper.ResetPipe = (USBDK_RESET_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_ResetPipe"); - if (usbdk_helper.ResetPipe == NULL) { - goto error_unload; - } - - usbdk_helper.SetAltsetting = (USBDK_SET_ALTSETTING)get_usbdk_proc_addr(ctx, "UsbDk_SetAltsetting"); - if (usbdk_helper.SetAltsetting == NULL) { - goto error_unload; - } - - usbdk_helper.ResetDevice = (USBDK_RESET_DEVICE)get_usbdk_proc_addr(ctx, "UsbDk_ResetDevice"); - if (usbdk_helper.ResetDevice == NULL) { - goto error_unload; - } - - usbdk_helper.GetRedirectorSystemHandle = (USBDK_GET_REDIRECTOR_SYSTEM_HANDLE)get_usbdk_proc_addr(ctx, "UsbDk_GetRedirectorSystemHandle"); - if (usbdk_helper.GetRedirectorSystemHandle == NULL) { - goto error_unload; - } - - return LIBUSB_SUCCESS; + usbdk_helper.module = LoadLibraryA("UsbDkHelper"); + if (usbdk_helper.module == NULL) { + DWORD err = GetLastError(); + usbi_err(ctx, "Failed to load UsbDkHelper.dll, error %d", err); + return LIBUSB_ERROR_NOT_FOUND; + } + + usbdk_helper.GetDevicesList = (USBDK_GET_DEVICES_LIST)get_usbdk_proc_addr(ctx, "UsbDk_GetDevicesList"); + if (usbdk_helper.GetDevicesList == NULL) + goto error_unload; + + usbdk_helper.ReleaseDevicesList = (USBDK_RELEASE_DEVICES_LIST)get_usbdk_proc_addr(ctx, "UsbDk_ReleaseDevicesList"); + if (usbdk_helper.ReleaseDevicesList == NULL) + goto error_unload; + + usbdk_helper.StartRedirect = (USBDK_START_REDIRECT)get_usbdk_proc_addr(ctx, "UsbDk_StartRedirect"); + if (usbdk_helper.StartRedirect == NULL) + goto error_unload; + + usbdk_helper.StopRedirect = (USBDK_STOP_REDIRECT)get_usbdk_proc_addr(ctx, "UsbDk_StopRedirect"); + if (usbdk_helper.StopRedirect == NULL) + goto error_unload; + + usbdk_helper.GetConfigurationDescriptor = (USBDK_GET_CONFIGURATION_DESCRIPTOR)get_usbdk_proc_addr(ctx, "UsbDk_GetConfigurationDescriptor"); + if (usbdk_helper.GetConfigurationDescriptor == NULL) + goto error_unload; + + usbdk_helper.ReleaseConfigurationDescriptor = (USBDK_RELEASE_CONFIGURATION_DESCRIPTOR)get_usbdk_proc_addr(ctx, "UsbDk_ReleaseConfigurationDescriptor"); + if (usbdk_helper.ReleaseConfigurationDescriptor == NULL) + goto error_unload; + + usbdk_helper.ReadPipe = (USBDK_READ_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_ReadPipe"); + if (usbdk_helper.ReadPipe == NULL) + goto error_unload; + + usbdk_helper.WritePipe = (USBDK_WRITE_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_WritePipe"); + if (usbdk_helper.WritePipe == NULL) + goto error_unload; + + usbdk_helper.AbortPipe = (USBDK_ABORT_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_AbortPipe"); + if (usbdk_helper.AbortPipe == NULL) + goto error_unload; + + usbdk_helper.ResetPipe = (USBDK_RESET_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_ResetPipe"); + if (usbdk_helper.ResetPipe == NULL) + goto error_unload; + + usbdk_helper.SetAltsetting = (USBDK_SET_ALTSETTING)get_usbdk_proc_addr(ctx, "UsbDk_SetAltsetting"); + if (usbdk_helper.SetAltsetting == NULL) + goto error_unload; + + usbdk_helper.ResetDevice = (USBDK_RESET_DEVICE)get_usbdk_proc_addr(ctx, "UsbDk_ResetDevice"); + if (usbdk_helper.ResetDevice == NULL) + goto error_unload; + + usbdk_helper.GetRedirectorSystemHandle = (USBDK_GET_REDIRECTOR_SYSTEM_HANDLE)get_usbdk_proc_addr(ctx, "UsbDk_GetRedirectorSystemHandle"); + if (usbdk_helper.GetRedirectorSystemHandle == NULL) + goto error_unload; + + return LIBUSB_SUCCESS; error_unload: - FreeLibrary(usbdk_helper.module); - return LIBUSB_ERROR_NOT_FOUND; + FreeLibrary(usbdk_helper.module); + return LIBUSB_ERROR_NOT_FOUND; } static int usbdk_init(struct libusb_context *ctx) { - int r; + int r; - if ((++concurrent_usage == 0) || !init_succeeded) { - r = load_usbdk_helper_dll(ctx); - if (r) { - return r; - } + if ((++concurrent_usage == 0) || !init_succeeded) { + r = load_usbdk_helper_dll(ctx); + if (r) + return r; - init_polling(); + init_polling(); - r = windows_common_init(ctx); - if (r) { - goto error_roll_back; - } + r = windows_common_init(ctx); + if (r) + goto error_roll_back; - init_succeeded = 1; - } + init_succeeded = 1; + } - return LIBUSB_SUCCESS; + return LIBUSB_SUCCESS; error_roll_back: - windows_common_exit(); - unload_usbdk_helper_dll(); - return r; + windows_common_exit(); + unload_usbdk_helper_dll(); + return r; } static int usbdk_get_session_id_for_device(struct libusb_context *ctx, - PUSB_DK_DEVICE_ID id, - unsigned long* session_id) + PUSB_DK_DEVICE_ID id, unsigned long *session_id) { - char dev_identity[ARRAYSIZE(id->DeviceID) + ARRAYSIZE(id->InstanceID)]; + char dev_identity[ARRAYSIZE(id->DeviceID) + ARRAYSIZE(id->InstanceID)]; - if (sprintf(dev_identity, "%S%S", id->DeviceID, id->InstanceID) == -1) { - usbi_warn(ctx, "cannot form device identity", id->DeviceID); - return LIBUSB_ERROR_NOT_SUPPORTED; - } + if (sprintf(dev_identity, "%S%S", id->DeviceID, id->InstanceID) == -1) { + usbi_warn(ctx, "cannot form device identity", id->DeviceID); + return LIBUSB_ERROR_NOT_SUPPORTED; + } - *session_id = htab_hash(dev_identity); + *session_id = htab_hash(dev_identity); - return LIBUSB_SUCCESS; + return LIBUSB_SUCCESS; } -static void usbdk_release_config_descriptors(struct usbdk_device_priv* p, uint8_t count) +static void usbdk_release_config_descriptors(struct usbdk_device_priv *p, uint8_t count) { - uint8_t i; - for (i = 0; i < count; i++) { - usbdk_helper.ReleaseConfigurationDescriptor(p->config_descriptors[i]); - } - free(p->config_descriptors); - p->config_descriptors = NULL; + uint8_t i; + + for (i = 0; i < count; i++) + usbdk_helper.ReleaseConfigurationDescriptor(p->config_descriptors[i]); + + free(p->config_descriptors); + p->config_descriptors = NULL; } static int usbdk_cache_config_descriptors(struct libusb_context *ctx, - struct usbdk_device_priv* p, - PUSB_DK_DEVICE_INFO info) -{ - uint8_t i; - USB_DK_CONFIG_DESCRIPTOR_REQUEST Request; - Request.ID = info->ID; - - p->config_descriptors = calloc(info->DeviceDescriptor.bNumConfigurations, - sizeof(PUSB_CONFIGURATION_DESCRIPTOR)); - if (p->config_descriptors == NULL) { - usbi_err(ctx, "failed to allocate configuration descriptors holder"); - return LIBUSB_ERROR_NO_MEM; - } - - for (i = 0; i < info->DeviceDescriptor.bNumConfigurations; i++) { - ULONG Length; - - Request.Index = i; - if (!usbdk_helper.GetConfigurationDescriptor(&Request, - &p->config_descriptors[i], - &Length)) { - usbi_err(ctx, "failed to retrieve configuration descriptors"); - usbdk_release_config_descriptors(p, i); - return LIBUSB_ERROR_OTHER; - } - } - - return LIBUSB_SUCCESS; -} - -static inline int usbdk_device_priv_init(struct libusb_context *ctx, libusb_device* dev, PUSB_DK_DEVICE_INFO info) -{ - struct usbdk_device_priv* p = _usbdk_device_priv(dev); - p->info = *info; - p->active_configuration = 0; - return usbdk_cache_config_descriptors(ctx, p, info); -} - -static void usbdk_device_init(libusb_device* dev, PUSB_DK_DEVICE_INFO info) -{ - dev->bus_number = (uint8_t) info->FilterID; - dev->port_number = (uint8_t) info->Port; - dev->parent_dev = NULL; - - //Addresses in libusb are 1-based - dev->device_address = (uint8_t) info->Port + 1; - - dev->num_configurations = info->DeviceDescriptor.bNumConfigurations; - dev->device_descriptor = info->DeviceDescriptor; - - switch (info->Speed) - { - case LowSpeed: - dev->speed = LIBUSB_SPEED_LOW; - break; - case FullSpeed: - dev->speed = LIBUSB_SPEED_FULL; - break; - case HighSpeed: - dev->speed = LIBUSB_SPEED_HIGH; - break; - case SuperSpeed: - dev->speed = LIBUSB_SPEED_SUPER; - break; - case NoSpeed: - default: - dev->speed = LIBUSB_SPEED_UNKNOWN; - break; - } + struct usbdk_device_priv *p, PUSB_DK_DEVICE_INFO info) +{ + uint8_t i; + USB_DK_CONFIG_DESCRIPTOR_REQUEST Request; + Request.ID = info->ID; + + p->config_descriptors = calloc(info->DeviceDescriptor.bNumConfigurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR)); + if (p->config_descriptors == NULL) { + usbi_err(ctx, "failed to allocate configuration descriptors holder"); + return LIBUSB_ERROR_NO_MEM; + } + + for (i = 0; i < info->DeviceDescriptor.bNumConfigurations; i++) { + ULONG Length; + + Request.Index = i; + if (!usbdk_helper.GetConfigurationDescriptor(&Request, &p->config_descriptors[i], &Length)) { + usbi_err(ctx, "failed to retrieve configuration descriptors"); + usbdk_release_config_descriptors(p, i); + return LIBUSB_ERROR_OTHER; + } + } + + return LIBUSB_SUCCESS; +} + +static inline int usbdk_device_priv_init(struct libusb_context *ctx, struct libusb_device *dev, PUSB_DK_DEVICE_INFO info) +{ + struct usbdk_device_priv *p = _usbdk_device_priv(dev); + + p->info = *info; + p->active_configuration = 0; + + return usbdk_cache_config_descriptors(ctx, p, info); +} + +static void usbdk_device_init(libusb_device *dev, PUSB_DK_DEVICE_INFO info) +{ + dev->bus_number = (uint8_t)info->FilterID; + dev->port_number = (uint8_t)info->Port; + dev->parent_dev = NULL; + + //Addresses in libusb are 1-based + dev->device_address = (uint8_t)(info->Port + 1); + + dev->num_configurations = info->DeviceDescriptor.bNumConfigurations; + dev->device_descriptor = info->DeviceDescriptor; + + switch (info->Speed) { + case LowSpeed: + dev->speed = LIBUSB_SPEED_LOW; + break; + case FullSpeed: + dev->speed = LIBUSB_SPEED_FULL; + break; + case HighSpeed: + dev->speed = LIBUSB_SPEED_HIGH; + break; + case SuperSpeed: + dev->speed = LIBUSB_SPEED_SUPER; + break; + case NoSpeed: + default: + dev->speed = LIBUSB_SPEED_UNKNOWN; + break; + } } static int usbdk_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs) { - int r = LIBUSB_SUCCESS; - ULONG i; - - struct discovered_devs *discdevs = NULL; - ULONG dev_number; - PUSB_DK_DEVICE_INFO devices; - - if(!usbdk_helper.GetDevicesList(&devices, &dev_number)) { - return LIBUSB_ERROR_OTHER; - } - - for (i = 0; i < dev_number; ++i) { - unsigned long session_id; - struct libusb_device *dev = NULL; - - if (usbdk_get_session_id_for_device(ctx, &devices[i].ID, &session_id)) { - continue; - } - - dev = usbi_get_device_by_session_id(ctx, session_id); - if (dev == NULL) { - dev = usbi_alloc_device(ctx, session_id); - if (dev == NULL) { - usbi_err(ctx, "failed to allocate a new device structure"); - continue; - } - - usbdk_device_init(dev, &devices[i]); - if (usbdk_device_priv_init(ctx, dev, &devices[i]) != LIBUSB_SUCCESS) { - libusb_unref_device(dev); - continue; - } - } - - discdevs = discovered_devs_append(*_discdevs, dev); - - libusb_unref_device(dev); - - if (!discdevs) - { - usbi_err(ctx, "cannot append new device to list"); - r = LIBUSB_ERROR_NO_MEM; - goto func_exit; - } - *_discdevs = discdevs; - } + int r = LIBUSB_SUCCESS; + ULONG i; + struct discovered_devs *discdevs = NULL; + ULONG dev_number; + PUSB_DK_DEVICE_INFO devices; + + if(!usbdk_helper.GetDevicesList(&devices, &dev_number)) + return LIBUSB_ERROR_OTHER; + + for (i = 0; i < dev_number; i++) { + unsigned long session_id; + struct libusb_device *dev = NULL; + + if (usbdk_get_session_id_for_device(ctx, &devices[i].ID, &session_id)) + continue; + + dev = usbi_get_device_by_session_id(ctx, session_id); + if (dev == NULL) { + dev = usbi_alloc_device(ctx, session_id); + if (dev == NULL) { + usbi_err(ctx, "failed to allocate a new device structure"); + continue; + } + + usbdk_device_init(dev, &devices[i]); + if (usbdk_device_priv_init(ctx, dev, &devices[i]) != LIBUSB_SUCCESS) { + libusb_unref_device(dev); + continue; + } + } + + discdevs = discovered_devs_append(*_discdevs, dev); + libusb_unref_device(dev); + if (!discdevs) { + usbi_err(ctx, "cannot append new device to list"); + r = LIBUSB_ERROR_NO_MEM; + goto func_exit; + } + + *_discdevs = discdevs; + } func_exit: - usbdk_helper.ReleaseDevicesList(devices); - return r; + usbdk_helper.ReleaseDevicesList(devices); + return r; } static void usbdk_exit(void) { - if ((--concurrent_usage < 0) && init_succeeded) { - windows_common_exit(); - exit_polling(); - unload_usbdk_helper_dll(); - init_succeeded = 0; - } + if ((--concurrent_usage < 0) && init_succeeded) { + windows_common_exit(); + exit_polling(); + unload_usbdk_helper_dll(); + init_succeeded = 0; + } } static int usbdk_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian) { - struct usbdk_device_priv *priv = _usbdk_device_priv(dev); + struct usbdk_device_priv *priv = _usbdk_device_priv(dev); - memcpy(buffer, &priv->info.DeviceDescriptor, DEVICE_DESC_LENGTH); - *host_endian = 0; + memcpy(buffer, &priv->info.DeviceDescriptor, DEVICE_DESC_LENGTH); + *host_endian = 0; - return LIBUSB_SUCCESS; + return LIBUSB_SUCCESS; } static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) { - struct usbdk_device_priv *priv = _usbdk_device_priv(dev); - PUSB_CONFIGURATION_DESCRIPTOR config_header; - size_t size; + struct usbdk_device_priv *priv = _usbdk_device_priv(dev); + PUSB_CONFIGURATION_DESCRIPTOR config_header; + size_t size; - if (config_index >= dev->num_configurations) - return LIBUSB_ERROR_INVALID_PARAM; + if (config_index >= dev->num_configurations) + return LIBUSB_ERROR_INVALID_PARAM; - config_header = (PUSB_CONFIGURATION_DESCRIPTOR) priv->config_descriptors[config_index]; + config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptors[config_index]; - size = min(config_header->wTotalLength, len); - memcpy(buffer, config_header, size); - *host_endian = 0; + size = min(config_header->wTotalLength, len); + memcpy(buffer, config_header, size); + *host_endian = 0; - return (int)size; + return (int)size; } static inline int usbdk_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian) { - return usbdk_get_config_descriptor(dev, _usbdk_device_priv(dev)->active_configuration, - buffer, len, host_endian); + return usbdk_get_config_descriptor(dev, _usbdk_device_priv(dev)->active_configuration, + buffer, len, host_endian); } static int usbdk_open(struct libusb_device_handle *dev_handle) { - struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); + struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); - priv->redirector_handle = usbdk_helper.StartRedirect(&priv->info.ID); - if (priv->redirector_handle == INVALID_HANDLE_VALUE) - { - usbi_err(DEVICE_CTX(dev_handle->dev), "Redirector startup failed"); - return LIBUSB_ERROR_OTHER; - } + priv->redirector_handle = usbdk_helper.StartRedirect(&priv->info.ID); + if (priv->redirector_handle == INVALID_HANDLE_VALUE) { + usbi_err(DEVICE_CTX(dev_handle->dev), "Redirector startup failed"); + return LIBUSB_ERROR_OTHER; + } - return LIBUSB_SUCCESS; + return LIBUSB_SUCCESS; } static void usbdk_close(struct libusb_device_handle *dev_handle) { - struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); + struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); - if (!usbdk_helper.StopRedirect(priv->redirector_handle)) - { - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - usbi_err(ctx, "Redirector shutdown failed"); - } + if (!usbdk_helper.StopRedirect(priv->redirector_handle)) { + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + usbi_err(ctx, "Redirector shutdown failed"); + } } static int usbdk_get_configuration(struct libusb_device_handle *dev_handle, int *config) { - *config = _usbdk_device_priv(dev_handle->dev)->active_configuration; - return LIBUSB_SUCCESS; + *config = _usbdk_device_priv(dev_handle->dev)->active_configuration; + + return LIBUSB_SUCCESS; } static int usbdk_set_configuration(struct libusb_device_handle *dev_handle, int config) { - UNREFERENCED_PARAMETER(dev_handle); - UNREFERENCED_PARAMETER(config); - return LIBUSB_SUCCESS; + UNUSED(dev_handle); + UNUSED(config); + return LIBUSB_SUCCESS; } static int usbdk_claim_interface(struct libusb_device_handle *dev_handle, int iface) { - UNREFERENCED_PARAMETER(dev_handle); - UNREFERENCED_PARAMETER(iface); - return LIBUSB_SUCCESS; + UNUSED(dev_handle); + UNUSED(iface); + return LIBUSB_SUCCESS; } static int usbdk_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) { - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); - if (!usbdk_helper.SetAltsetting(priv->redirector_handle, iface, altsetting)) { - usbi_err(ctx, "SetAltsetting failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } + if (!usbdk_helper.SetAltsetting(priv->redirector_handle, iface, altsetting)) { + usbi_err(ctx, "SetAltsetting failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } - return LIBUSB_SUCCESS; + return LIBUSB_SUCCESS; } static int usbdk_release_interface(struct libusb_device_handle *dev_handle, int iface) { - UNREFERENCED_PARAMETER(dev_handle); - UNREFERENCED_PARAMETER(iface); - return LIBUSB_SUCCESS; + UNUSED(dev_handle); + UNUSED(iface); + return LIBUSB_SUCCESS; } static int usbdk_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) { - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); - if (!usbdk_helper.ResetPipe(priv->redirector_handle, endpoint)) { - usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } + if (!usbdk_helper.ResetPipe(priv->redirector_handle, endpoint)) { + usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } - return LIBUSB_SUCCESS; + return LIBUSB_SUCCESS; } static int usbdk_reset_device(struct libusb_device_handle *dev_handle) { - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); - if (!usbdk_helper.ResetDevice(priv->redirector_handle)) { - usbi_err(ctx, "ResetDevice failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } + if (!usbdk_helper.ResetDevice(priv->redirector_handle)) { + usbi_err(ctx, "ResetDevice failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } - return LIBUSB_SUCCESS; + return LIBUSB_SUCCESS; } static int usbdk_kernel_driver_active(struct libusb_device_handle *dev_handle, int iface) { - UNREFERENCED_PARAMETER(dev_handle); - UNREFERENCED_PARAMETER(iface); - return LIBUSB_ERROR_NOT_SUPPORTED; + UNUSED(dev_handle); + UNUSED(iface); + return LIBUSB_ERROR_NOT_SUPPORTED; } static int usbdk_attach_kernel_driver(struct libusb_device_handle *dev_handle, int iface) { - UNREFERENCED_PARAMETER(dev_handle); - UNREFERENCED_PARAMETER(iface); - return LIBUSB_ERROR_NOT_SUPPORTED; + UNUSED(dev_handle); + UNUSED(iface); + return LIBUSB_ERROR_NOT_SUPPORTED; } static int usbdk_detach_kernel_driver(struct libusb_device_handle *dev_handle, int iface) { - UNREFERENCED_PARAMETER(dev_handle); - UNREFERENCED_PARAMETER(iface); - return LIBUSB_ERROR_NOT_SUPPORTED; + UNUSED(dev_handle); + UNUSED(iface); + return LIBUSB_ERROR_NOT_SUPPORTED; } static void usbdk_destroy_device(struct libusb_device *dev) { - struct usbdk_device_priv* p = _usbdk_device_priv(dev); + struct usbdk_device_priv* p = _usbdk_device_priv(dev); - if (p->config_descriptors != NULL) - { - usbdk_release_config_descriptors(p, p->info.DeviceDescriptor.bNumConfigurations); - } + if (p->config_descriptors != NULL) + usbdk_release_config_descriptors(p, p->info.DeviceDescriptor.bNumConfigurations); } void windows_clear_transfer_priv(struct usbi_transfer *itransfer) { - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - usbi_free_fd(&transfer_priv->pollable_fd); + usbi_free_fd(&transfer_priv->pollable_fd); - if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS){ - safe_free(transfer_priv->IsochronousPacketsArray); - safe_free(transfer_priv->IsochronousResultsArray); - } + if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { + safe_free(transfer_priv->IsochronousPacketsArray); + safe_free(transfer_priv->IsochronousResultsArray); + } } static int usbdk_do_control_transfer(struct usbi_transfer *itransfer) { - ULONG Length; - TransferResult transResult; - - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - - HANDLE sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); - - struct winfd wfd = usbi_create_fd(sysHandle, RW_READ, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) { - return LIBUSB_ERROR_NO_MEM; - } - - transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; - transfer_priv->request.BufferLength = transfer->length; - transfer_priv->request.TransferType = ControlTransferType; - transfer_priv->pollable_fd = INVALID_WINFD; - Length = (ULONG)transfer->length; - - if (IS_XFERIN(transfer)) { - transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); - } - else { - transResult = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); - } - - - switch (transResult) - { - case TransferSuccess: - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - wfd.overlapped->InternalHigh = (DWORD)Length; - break; - case TransferSuccessAsync: - break; - case TransferFailure: - { - usbi_err(ctx, "ControlTransfer failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); - return LIBUSB_ERROR_IO; - } - } - - // Use priv_transfer to store data needed for async polling - transfer_priv->pollable_fd = wfd; - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN); - return LIBUSB_SUCCESS; + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + ULONG Length; + TransferResult transResult; + HANDLE sysHandle; + + sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); + + struct winfd wfd = usbi_create_fd(sysHandle, RW_READ, NULL, NULL); + // Always use the handle returned from usbi_create_fd (wfd.handle) + if (wfd.fd < 0) + return LIBUSB_ERROR_NO_MEM; + + transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; + transfer_priv->request.BufferLength = transfer->length; + transfer_priv->request.TransferType = ControlTransferType; + transfer_priv->pollable_fd = INVALID_WINFD; + Length = (ULONG)transfer->length; + + if (IS_XFERIN(transfer)) + transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + else + transResult = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + + switch (transResult) { + case TransferSuccess: + wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; + wfd.overlapped->InternalHigh = (DWORD)Length; + break; + case TransferSuccessAsync: + break; + case TransferFailure: + usbi_err(ctx, "ControlTransfer failed: %s", windows_error_str(0)); + usbi_free_fd(&wfd); + return LIBUSB_ERROR_IO; + } + + // Use priv_transfer to store data needed for async polling + transfer_priv->pollable_fd = wfd; + usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN); + + return LIBUSB_SUCCESS; } static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winfd wfd; - TransferResult transferRes; - HANDLE sysHandle; - - transfer_priv->request.Buffer = (PVOID64) (uintptr_t) transfer->buffer; - transfer_priv->request.BufferLength = transfer->length; - transfer_priv->request.EndpointAddress = transfer->endpoint; - - switch (transfer->type) - { - case LIBUSB_TRANSFER_TYPE_BULK: - transfer_priv->request.TransferType = BulkTransferType; - break; - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - transfer_priv->request.TransferType = IntertuptTransferType; - break; - default: - usbi_err(ctx, "Wrong transfer type (%d) in usbdk_do_bulk_transfer. %s", transfer->type, windows_error_str(0)); - return LIBUSB_ERROR_INVALID_PARAM; - } - - transfer_priv->pollable_fd = INVALID_WINFD; - - sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); - - wfd = usbi_create_fd(sysHandle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) { - return LIBUSB_ERROR_NO_MEM; - } - - if (IS_XFERIN(transfer)) { - transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); - } - else { - transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); - } - - switch (transferRes) - { - case TransferSuccess: - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - break; - case TransferSuccessAsync: - break; - case TransferFailure: - { - usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); - return LIBUSB_ERROR_IO; - } - } - - transfer_priv->pollable_fd = wfd; - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, (short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT)); - return LIBUSB_SUCCESS; + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winfd wfd; + TransferResult transferRes; + HANDLE sysHandle; + + transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; + transfer_priv->request.BufferLength = transfer->length; + transfer_priv->request.EndpointAddress = transfer->endpoint; + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_BULK: + transfer_priv->request.TransferType = BulkTransferType; + break; + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + transfer_priv->request.TransferType = IntertuptTransferType; + break; + default: + usbi_err(ctx, "Wrong transfer type (%d) in usbdk_do_bulk_transfer. %s", transfer->type, windows_error_str(0)); + return LIBUSB_ERROR_INVALID_PARAM; + } + + transfer_priv->pollable_fd = INVALID_WINFD; + + sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); + + wfd = usbi_create_fd(sysHandle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL); + // Always use the handle returned from usbi_create_fd (wfd.handle) + if (wfd.fd < 0) + return LIBUSB_ERROR_NO_MEM; + + if (IS_XFERIN(transfer)) + transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + else + transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + + switch (transferRes) { + case TransferSuccess: + wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; + break; + case TransferSuccessAsync: + break; + case TransferFailure: + usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); + usbi_free_fd(&wfd); + return LIBUSB_ERROR_IO; + } + + transfer_priv->pollable_fd = wfd; + usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, IS_XFERIN(transfer) ? POLLIN : POLLOUT); + + return LIBUSB_SUCCESS; } static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winfd wfd; - TransferResult transferRes; - int i; - HANDLE sysHandle; - - transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; - transfer_priv->request.BufferLength = transfer->length; - transfer_priv->request.EndpointAddress = transfer->endpoint; - transfer_priv->request.TransferType = IsochronousTransferType; - transfer_priv->request.IsochronousPacketsArraySize = transfer->num_iso_packets; - transfer_priv->IsochronousPacketsArray = malloc(transfer->num_iso_packets * sizeof(ULONG64)); - transfer_priv->request.IsochronousPacketsArray = (PVOID64)(uintptr_t)transfer_priv->IsochronousPacketsArray; - if (!transfer_priv->IsochronousPacketsArray){ - usbi_err(ctx, "Allocation of IsochronousPacketsArray is failed, %s", windows_error_str(0)); - return LIBUSB_ERROR_IO; - } - - transfer_priv->IsochronousResultsArray = malloc(transfer->num_iso_packets * sizeof(USB_DK_ISO_TRANSFER_RESULT)); - transfer_priv->request.Result.IsochronousResultsArray = (PVOID64)(uintptr_t)transfer_priv->IsochronousResultsArray; - if (!transfer_priv->IsochronousResultsArray){ - usbi_err(ctx, "Allocation of isochronousResultsArray is failed, %s", windows_error_str(0)); - free(transfer_priv->IsochronousPacketsArray); - return LIBUSB_ERROR_IO; - } - - for (i = 0; i < transfer->num_iso_packets; i++){ - transfer_priv->IsochronousPacketsArray[i] = transfer->iso_packet_desc[i].length; - } - - transfer_priv->pollable_fd = INVALID_WINFD; - - sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); - - wfd = usbi_create_fd(sysHandle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) { - free(transfer_priv->IsochronousPacketsArray); - free(transfer_priv->IsochronousResultsArray); - return LIBUSB_ERROR_NO_MEM; - } - - if (IS_XFERIN(transfer)) { - transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); - } - else { - transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); - } - - switch (transferRes){ - case TransferSuccess: - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - break; - case TransferSuccessAsync: - break; - case TransferFailure: - { - usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); - free(transfer_priv->IsochronousPacketsArray); - free(transfer_priv->IsochronousResultsArray); - return LIBUSB_ERROR_IO; - } - } - - transfer_priv->pollable_fd = wfd; - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, (short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT)); - - return LIBUSB_SUCCESS; + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winfd wfd; + TransferResult transferRes; + int i; + HANDLE sysHandle; + + transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; + transfer_priv->request.BufferLength = transfer->length; + transfer_priv->request.EndpointAddress = transfer->endpoint; + transfer_priv->request.TransferType = IsochronousTransferType; + transfer_priv->request.IsochronousPacketsArraySize = transfer->num_iso_packets; + transfer_priv->IsochronousPacketsArray = malloc(transfer->num_iso_packets * sizeof(ULONG64)); + transfer_priv->request.IsochronousPacketsArray = (PVOID64)(uintptr_t)transfer_priv->IsochronousPacketsArray; + if (!transfer_priv->IsochronousPacketsArray) { + usbi_err(ctx, "Allocation of IsochronousPacketsArray is failed, %s", windows_error_str(0)); + return LIBUSB_ERROR_IO; + } + + transfer_priv->IsochronousResultsArray = malloc(transfer->num_iso_packets * sizeof(USB_DK_ISO_TRANSFER_RESULT)); + transfer_priv->request.Result.IsochronousResultsArray = (PVOID64)(uintptr_t)transfer_priv->IsochronousResultsArray; + if (!transfer_priv->IsochronousResultsArray) { + usbi_err(ctx, "Allocation of isochronousResultsArray is failed, %s", windows_error_str(0)); + free(transfer_priv->IsochronousPacketsArray); + return LIBUSB_ERROR_IO; + } + + for (i = 0; i < transfer->num_iso_packets; i++) + transfer_priv->IsochronousPacketsArray[i] = transfer->iso_packet_desc[i].length; + + transfer_priv->pollable_fd = INVALID_WINFD; + + sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); + + wfd = usbi_create_fd(sysHandle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL); + // Always use the handle returned from usbi_create_fd (wfd.handle) + if (wfd.fd < 0) { + free(transfer_priv->IsochronousPacketsArray); + free(transfer_priv->IsochronousResultsArray); + return LIBUSB_ERROR_NO_MEM; + } + + if (IS_XFERIN(transfer)) + transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + else + transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + + switch (transferRes) { + case TransferSuccess: + wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; + break; + case TransferSuccessAsync: + break; + case TransferFailure: + usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); + usbi_free_fd(&wfd); + free(transfer_priv->IsochronousPacketsArray); + free(transfer_priv->IsochronousResultsArray); + return LIBUSB_ERROR_IO; + } + + transfer_priv->pollable_fd = wfd; + usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, IS_XFERIN(transfer) ? POLLIN : POLLOUT); + + return LIBUSB_SUCCESS; } static int usbdk_submit_transfer(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - return usbdk_do_control_transfer(itransfer); - - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - if (IS_XFEROUT(transfer) && transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) { - //TODO: Check whether we can support this in UsbDk - return LIBUSB_ERROR_NOT_SUPPORTED; - } else { - return usbdk_do_bulk_transfer(itransfer); - } - - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return usbdk_do_iso_transfer(itransfer); - default: - usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + return usbdk_do_control_transfer(itransfer); + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)) + return LIBUSB_ERROR_NOT_SUPPORTED; //TODO: Check whether we can support this in UsbDk + else + return usbdk_do_bulk_transfer(itransfer); + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + return usbdk_do_iso_transfer(itransfer); + default: + usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); + return LIBUSB_ERROR_INVALID_PARAM; + } } static int usbdk_abort_transfers(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); - if (!usbdk_helper.AbortPipe(priv->redirector_handle, transfer->endpoint)) { - usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } + if (!usbdk_helper.AbortPipe(priv->redirector_handle, transfer->endpoint)) { + usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } - return LIBUSB_SUCCESS; + return LIBUSB_SUCCESS; } static int usbdk_cancel_transfer(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - // Control transfers cancelled by IoCancelXXX() API - // No special treatment needed - return LIBUSB_SUCCESS; - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return usbdk_abort_transfers(itransfer); - default: - usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + // Control transfers cancelled by IoCancelXXX() API + // No special treatment needed + return LIBUSB_SUCCESS; + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + return usbdk_abort_transfers(itransfer); + default: + usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); + return LIBUSB_ERROR_INVALID_PARAM; + } } int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size) { - itransfer->transferred += io_size; - return LIBUSB_TRANSFER_COMPLETED; + itransfer->transferred += io_size; + return LIBUSB_TRANSFER_COMPLETED; } struct winfd *windows_get_fd(struct usbi_transfer *transfer) { - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer); - return &transfer_priv->pollable_fd; + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer); + return &transfer_priv->pollable_fd; } static DWORD usbdk_translate_usbd_status(USBD_STATUS UsbdStatus) { - if (USBD_SUCCESS(UsbdStatus)) - { - return NO_ERROR; - } - - switch (UsbdStatus) - { - case USBD_STATUS_STALL_PID: - case USBD_STATUS_ENDPOINT_HALTED: - case USBD_STATUS_BAD_START_FRAME: - return ERROR_GEN_FAILURE; - case USBD_STATUS_TIMEOUT: - return ERROR_SEM_TIMEOUT; - case USBD_STATUS_CANCELED: - return ERROR_OPERATION_ABORTED; - default: - return ERROR_FUNCTION_FAILED; - } + if (USBD_SUCCESS(UsbdStatus)) + return NO_ERROR; + + switch (UsbdStatus) { + case USBD_STATUS_STALL_PID: + case USBD_STATUS_ENDPOINT_HALTED: + case USBD_STATUS_BAD_START_FRAME: + return ERROR_GEN_FAILURE; + case USBD_STATUS_TIMEOUT: + return ERROR_SEM_TIMEOUT; + case USBD_STATUS_CANCELED: + return ERROR_OPERATION_ABORTED; + default: + return ERROR_FUNCTION_FAILED; + } } void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size) { - if (HasOverlappedIoCompletedSync(pollable_fd->overlapped) || // Handle async requests that completed synchronously first - GetOverlappedResult(pollable_fd->handle, pollable_fd->overlapped, io_size, false)) { // Regular async overlapped - struct libusb_transfer *ltransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer); - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer); - - if (ltransfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS){ - int i; - for (i = 0; i < transfer_priv->request.IsochronousPacketsArraySize; i++) { - struct libusb_iso_packet_descriptor *lib_desc = <ransfer->iso_packet_desc[i]; - - switch (transfer_priv->IsochronousResultsArray[i].TransferResult){ - case STATUS_SUCCESS: - case STATUS_CANCELLED: - case STATUS_REQUEST_CANCELED: - lib_desc->status = LIBUSB_TRANSFER_COMPLETED; // == ERROR_SUCCESS - break; - default: - lib_desc->status = LIBUSB_TRANSFER_ERROR; // ERROR_UNKNOWN_EXCEPTION; - break; - } - - lib_desc->actual_length = (unsigned int) transfer_priv->IsochronousResultsArray[i].ActualLength; - } - } - - *io_size = (DWORD) transfer_priv->request.Result.GenResult.BytesTransferred; - *io_result = usbdk_translate_usbd_status((USBD_STATUS) transfer_priv->request.Result.GenResult.UsbdStatus); - } - else { - *io_result = GetLastError(); - } + if (HasOverlappedIoCompletedSync(pollable_fd->overlapped) // Handle async requests that completed synchronously first + || GetOverlappedResult(pollable_fd->handle, pollable_fd->overlapped, io_size, false)) { // Regular async overlapped + struct libusb_transfer *ltransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer); + + if (ltransfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { + int i; + for (i = 0; i < transfer_priv->request.IsochronousPacketsArraySize; i++) { + struct libusb_iso_packet_descriptor *lib_desc = <ransfer->iso_packet_desc[i]; + + switch (transfer_priv->IsochronousResultsArray[i].TransferResult) { + case STATUS_SUCCESS: + case STATUS_CANCELLED: + case STATUS_REQUEST_CANCELED: + lib_desc->status = LIBUSB_TRANSFER_COMPLETED; // == ERROR_SUCCESS + break; + default: + lib_desc->status = LIBUSB_TRANSFER_ERROR; // ERROR_UNKNOWN_EXCEPTION; + break; + } + + lib_desc->actual_length = (unsigned int)transfer_priv->IsochronousResultsArray[i].ActualLength; + } + } + + *io_size = (DWORD) transfer_priv->request.Result.GenResult.BytesTransferred; + *io_result = usbdk_translate_usbd_status((USBD_STATUS) transfer_priv->request.Result.GenResult.UsbdStatus); + } + else { + *io_result = GetLastError(); + } } static int usbdk_clock_gettime(int clk_id, struct timespec *tp) { - return windows_clock_gettime(clk_id, tp); + return windows_clock_gettime(clk_id, tp); } const struct usbi_os_backend usbdk_backend = { - "Windows", - USBI_CAP_HAS_HID_ACCESS, - usbdk_init, - usbdk_exit, + "Windows", + USBI_CAP_HAS_HID_ACCESS, + usbdk_init, + usbdk_exit, - usbdk_get_device_list, - NULL, - usbdk_open, - usbdk_close, + usbdk_get_device_list, + NULL, + usbdk_open, + usbdk_close, - usbdk_get_device_descriptor, - usbdk_get_active_config_descriptor, - usbdk_get_config_descriptor, - NULL, + usbdk_get_device_descriptor, + usbdk_get_active_config_descriptor, + usbdk_get_config_descriptor, + NULL, - usbdk_get_configuration, - usbdk_set_configuration, - usbdk_claim_interface, - usbdk_release_interface, + usbdk_get_configuration, + usbdk_set_configuration, + usbdk_claim_interface, + usbdk_release_interface, - usbdk_set_interface_altsetting, - usbdk_clear_halt, - usbdk_reset_device, + usbdk_set_interface_altsetting, + usbdk_clear_halt, + usbdk_reset_device, - NULL, - NULL, + NULL, + NULL, - usbdk_kernel_driver_active, - usbdk_detach_kernel_driver, - usbdk_attach_kernel_driver, + usbdk_kernel_driver_active, + usbdk_detach_kernel_driver, + usbdk_attach_kernel_driver, - usbdk_destroy_device, + usbdk_destroy_device, - usbdk_submit_transfer, - usbdk_cancel_transfer, - windows_clear_transfer_priv, + usbdk_submit_transfer, + usbdk_cancel_transfer, + windows_clear_transfer_priv, - windows_handle_events, - NULL, + windows_handle_events, + NULL, - usbdk_clock_gettime, + usbdk_clock_gettime, #if defined(USBI_TIMERFD_AVAILABLE) - NULL, + NULL, #endif - sizeof(struct usbdk_device_priv), - sizeof(struct usbdk_device_handle_priv), - sizeof(struct usbdk_transfer_priv), + sizeof(struct usbdk_device_priv), + sizeof(struct usbdk_device_handle_priv), + sizeof(struct usbdk_transfer_priv), }; #endif /* USE_USBDK */ diff --git a/libusb/os/windows_usbdk.h b/libusb/os/windows_usbdk.h index 6b7173525..04a9787f2 100644 --- a/libusb/os/windows_usbdk.h +++ b/libusb/os/windows_usbdk.h @@ -23,104 +23,124 @@ #pragma once -typedef struct tag_USB_DK_DEVICE_ID -{ - WCHAR DeviceID[MAX_DEVICE_ID_LEN]; - WCHAR InstanceID[MAX_DEVICE_ID_LEN]; +typedef struct tag_USB_DK_DEVICE_ID { + WCHAR DeviceID[MAX_DEVICE_ID_LEN]; + WCHAR InstanceID[MAX_DEVICE_ID_LEN]; } USB_DK_DEVICE_ID, *PUSB_DK_DEVICE_ID; -static inline -void UsbDkFillIDStruct(USB_DK_DEVICE_ID *ID, PCWCHAR DeviceID, PCWCHAR InstanceID) +static inline void UsbDkFillIDStruct(USB_DK_DEVICE_ID *ID, PCWCHAR DeviceID, PCWCHAR InstanceID) { - wcsncpy_s(ID->DeviceID, DeviceID, MAX_DEVICE_ID_LEN); - wcsncpy_s(ID->InstanceID, InstanceID, MAX_DEVICE_ID_LEN); + wcsncpy_s(ID->DeviceID, DeviceID, MAX_DEVICE_ID_LEN); + wcsncpy_s(ID->InstanceID, InstanceID, MAX_DEVICE_ID_LEN); } -typedef struct tag_USB_DK_DEVICE_INFO -{ - USB_DK_DEVICE_ID ID; - ULONG64 FilterID; - ULONG64 Port; - ULONG64 Speed; - USB_DEVICE_DESCRIPTOR DeviceDescriptor; +typedef struct tag_USB_DK_DEVICE_INFO { + USB_DK_DEVICE_ID ID; + ULONG64 FilterID; + ULONG64 Port; + ULONG64 Speed; + USB_DEVICE_DESCRIPTOR DeviceDescriptor; } USB_DK_DEVICE_INFO, *PUSB_DK_DEVICE_INFO; -typedef struct tag_USB_DK_CONFIG_DESCRIPTOR_REQUEST -{ - USB_DK_DEVICE_ID ID; - ULONG64 Index; +typedef struct tag_USB_DK_CONFIG_DESCRIPTOR_REQUEST { + USB_DK_DEVICE_ID ID; + ULONG64 Index; } USB_DK_CONFIG_DESCRIPTOR_REQUEST, *PUSB_DK_CONFIG_DESCRIPTOR_REQUEST; -typedef struct tag_USB_DK_ISO_TRANSFER_RESULT -{ - ULONG64 ActualLength; - ULONG64 TransferResult; +typedef struct tag_USB_DK_ISO_TRANSFER_RESULT { + ULONG64 ActualLength; + ULONG64 TransferResult; } USB_DK_ISO_TRANSFER_RESULT, *PUSB_DK_ISO_TRANSFER_RESULT; -typedef struct tag_USB_DK_GEN_TRANSFER_RESULT -{ - ULONG64 BytesTransferred; - ULONG64 UsbdStatus; // USBD_STATUS code +typedef struct tag_USB_DK_GEN_TRANSFER_RESULT { + ULONG64 BytesTransferred; + ULONG64 UsbdStatus; // USBD_STATUS code } USB_DK_GEN_TRANSFER_RESULT, *PUSB_DK_GEN_TRANSFER_RESULT; -typedef struct tag_USB_DK_TRANSFER_RESULT -{ - USB_DK_GEN_TRANSFER_RESULT GenResult; - PVOID64 IsochronousResultsArray; // array of USB_DK_ISO_TRANSFER_RESULT +typedef struct tag_USB_DK_TRANSFER_RESULT { + USB_DK_GEN_TRANSFER_RESULT GenResult; + PVOID64 IsochronousResultsArray; // array of USB_DK_ISO_TRANSFER_RESULT } USB_DK_TRANSFER_RESULT, *PUSB_DK_TRANSFER_RESULT; -typedef struct tag_USB_DK_TRANSFER_REQUEST -{ - ULONG64 EndpointAddress; - PVOID64 Buffer; - ULONG64 BufferLength; - ULONG64 TransferType; - ULONG64 IsochronousPacketsArraySize; - PVOID64 IsochronousPacketsArray; +typedef struct tag_USB_DK_TRANSFER_REQUEST { + ULONG64 EndpointAddress; + PVOID64 Buffer; + ULONG64 BufferLength; + ULONG64 TransferType; + ULONG64 IsochronousPacketsArraySize; + PVOID64 IsochronousPacketsArray; - USB_DK_TRANSFER_RESULT Result; + USB_DK_TRANSFER_RESULT Result; } USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST; -typedef enum -{ - TransferFailure = 0, - TransferSuccess, - TransferSuccessAsync +typedef enum { + TransferFailure = 0, + TransferSuccess, + TransferSuccessAsync } TransferResult; -typedef enum -{ - NoSpeed = 0, - LowSpeed, - FullSpeed, - HighSpeed, - SuperSpeed +typedef enum { + NoSpeed = 0, + LowSpeed, + FullSpeed, + HighSpeed, + SuperSpeed } USB_DK_DEVICE_SPEED; -typedef enum -{ - ControlTransferType, - BulkTransferType, - IntertuptTransferType, - IsochronousTransferType +typedef enum { + ControlTransferType, + BulkTransferType, + IntertuptTransferType, + IsochronousTransferType } USB_DK_TRANSFER_TYPE; -typedef BOOL (__cdecl *USBDK_GET_DEVICES_LIST) (PUSB_DK_DEVICE_INFO *, PULONG); -typedef void (__cdecl *USBDK_RELEASE_DEVICES_LIST) (PUSB_DK_DEVICE_INFO); - -typedef HANDLE (__cdecl *USBDK_START_REDIRECT) (PUSB_DK_DEVICE_ID); -typedef BOOL (__cdecl *USBDK_STOP_REDIRECT) (HANDLE); - -typedef BOOL (__cdecl *USBDK_GET_CONFIGURATION_DESCRIPTOR) (PUSB_DK_CONFIG_DESCRIPTOR_REQUEST Request, - PUSB_CONFIGURATION_DESCRIPTOR *Descriptor, - PULONG Length); -typedef void (__cdecl *USBDK_RELEASE_CONFIGURATION_DESCRIPTOR) (PUSB_CONFIGURATION_DESCRIPTOR Descriptor); - -typedef TransferResult (__cdecl *USBDK_WRITE_PIPE) (HANDLE DeviceHandle, PUSB_DK_TRANSFER_REQUEST Request, LPOVERLAPPED lpOverlapped); -typedef TransferResult (__cdecl *USBDK_READ_PIPE) (HANDLE DeviceHandle, PUSB_DK_TRANSFER_REQUEST Request, LPOVERLAPPED lpOverlapped); -typedef BOOL (__cdecl *USBDK_ABORT_PIPE) (HANDLE DeviceHandle, ULONG64 PipeAddress); -typedef BOOL (__cdecl *USBDK_RESET_PIPE) (HANDLE DeviceHandle, ULONG64 PipeAddress); -typedef BOOL (__cdecl *USBDK_SET_ALTSETTING) (HANDLE DeviceHandle, ULONG64 InterfaceIdx, ULONG64 AltSettingIdx); -typedef BOOL (__cdecl *USBDK_RESET_DEVICE) (HANDLE DeviceHandle); - -typedef HANDLE (__cdecl *USBDK_GET_REDIRECTOR_SYSTEM_HANDLE) (HANDLE DeviceHandle); +typedef BOOL (__cdecl *USBDK_GET_DEVICES_LIST)( + PUSB_DK_DEVICE_INFO *DeviceInfo, + PULONG DeviceNumber +); +typedef void (__cdecl *USBDK_RELEASE_DEVICES_LIST)( + PUSB_DK_DEVICE_INFO DeviceInfo +); +typedef HANDLE (__cdecl *USBDK_START_REDIRECT)( + PUSB_DK_DEVICE_ID DeviceId +); +typedef BOOL (__cdecl *USBDK_STOP_REDIRECT)( + HANDLE DeviceHandle +); +typedef BOOL (__cdecl *USBDK_GET_CONFIGURATION_DESCRIPTOR)( + PUSB_DK_CONFIG_DESCRIPTOR_REQUEST Request, + PUSB_CONFIGURATION_DESCRIPTOR *Descriptor, + PULONG Length +); +typedef void (__cdecl *USBDK_RELEASE_CONFIGURATION_DESCRIPTOR)( + PUSB_CONFIGURATION_DESCRIPTOR Descriptor +); +typedef TransferResult (__cdecl *USBDK_WRITE_PIPE)( + HANDLE DeviceHandle, + PUSB_DK_TRANSFER_REQUEST Request, + LPOVERLAPPED lpOverlapped +); +typedef TransferResult (__cdecl *USBDK_READ_PIPE)( + HANDLE DeviceHandle, + PUSB_DK_TRANSFER_REQUEST Request, + LPOVERLAPPED lpOverlapped +); +typedef BOOL (__cdecl *USBDK_ABORT_PIPE)( + HANDLE DeviceHandle, + ULONG64 PipeAddress +); +typedef BOOL (__cdecl *USBDK_RESET_PIPE)( + HANDLE DeviceHandle, + ULONG64 PipeAddress +); +typedef BOOL (__cdecl *USBDK_SET_ALTSETTING)( + HANDLE DeviceHandle, + ULONG64 InterfaceIdx, + ULONG64 AltSettingIdx +); +typedef BOOL (__cdecl *USBDK_RESET_DEVICE)( + HANDLE DeviceHandle +); +typedef HANDLE (__cdecl *USBDK_GET_REDIRECTOR_SYSTEM_HANDLE)( + HANDLE DeviceHandle +); diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index ef4009628..0488e8e2e 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -41,9 +41,20 @@ #include "poll_windows.h" #include "windows_winusb.h" +#define HANDLE_VALID(h) (((h) != 0) && ((h) != INVALID_HANDLE_VALUE)) + // The 2 macros below are used in conjunction with safe loops. -#define LOOP_CHECK(fcall) { r=fcall; if (r != LIBUSB_SUCCESS) continue; } -#define LOOP_BREAK(err) { r=err; continue; } +#define LOOP_CHECK(fcall) \ + { \ + r = fcall; \ + if (r != LIBUSB_SUCCESS) \ + continue; \ + } +#define LOOP_BREAK(err) \ + { \ + r = err; \ + continue; \ + } // Helper prototypes static int windows_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian); @@ -99,37 +110,50 @@ static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itran // Global variables -uint64_t hires_frequency, hires_ticks_to_ps; int windows_version = WINDOWS_UNDEFINED; static char windows_version_str[128] = "Windows Undefined"; // Concurrency static int concurrent_usage = -1; -usbi_mutex_t autoclaim_lock; +static usbi_mutex_t autoclaim_lock; // API globals -#define CHECK_WINUSBX_AVAILABLE(sub_api) do { if (sub_api == SUB_API_NOTSET) sub_api = priv->sub_api; \ - if (!WinUSBX[sub_api].initialized) return LIBUSB_ERROR_ACCESS; } while(0) -static struct winusb_interface WinUSBX[SUB_API_MAX]; -const char* sub_api_name[SUB_API_MAX] = WINUSBX_DRV_NAMES; -bool api_hid_available = false; -#define CHECK_HID_AVAILABLE do { if (!api_hid_available) return LIBUSB_ERROR_ACCESS; } while (0) +#define CHECK_WINUSBX_AVAILABLE(sub_api) \ + do { \ + if (sub_api == SUB_API_NOTSET) \ + sub_api = priv->sub_api; \ + if (!WinUSBX[sub_api].initialized) \ + return LIBUSB_ERROR_ACCESS; \ + } while(0) -static inline BOOLEAN guid_eq(const GUID *guid1, const GUID *guid2) { - if ((guid1 != NULL) && (guid2 != NULL)) { +static struct winusb_interface WinUSBX[SUB_API_MAX]; +static const char *sub_api_name[SUB_API_MAX] = WINUSBX_DRV_NAMES; +static bool api_hid_available = false; +#define CHECK_HID_AVAILABLE \ + do { \ + if (!api_hid_available) \ + return LIBUSB_ERROR_ACCESS; \ + } while (0) + +static inline BOOLEAN guid_eq(const GUID *guid1, const GUID *guid2) +{ + if ((guid1 != NULL) && (guid2 != NULL)) return (memcmp(guid1, guid2, sizeof(GUID)) == 0); - } + return false; } #if defined(ENABLE_LOGGING) -static char* guid_to_string(const GUID* guid) +static char *guid_to_string(const GUID *guid) { static char guid_string[MAX_GUID_STRING_LENGTH]; - if (guid == NULL) return NULL; + if (guid == NULL) + return NULL; + sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", (unsigned int)guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); + return guid_string; } #endif @@ -138,38 +162,39 @@ static char* guid_to_string(const GUID* guid) * Sanitize Microsoft's paths: convert to uppercase, add prefix and fix backslashes. * Return an allocated sanitized string or NULL on error. */ -static char* sanitize_path(const char* path) +static char *sanitize_path(const char *path) { const char root_prefix[] = "\\\\.\\"; size_t j, size, root_size; - char* ret_path = NULL; + char *ret_path = NULL; size_t add_root = 0; if (path == NULL) return NULL; - size = safe_strlen(path)+1; - root_size = sizeof(root_prefix)-1; + size = safe_strlen(path) + 1; + root_size = sizeof(root_prefix) - 1; // Microsoft indiscriminately uses '\\?\', '\\.\', '##?#" or "##.#" for root prefixes. - if (!((size > 3) && (((path[0] == '\\') && (path[1] == '\\') && (path[3] == '\\')) || - ((path[0] == '#') && (path[1] == '#') && (path[3] == '#'))))) { + if (!((size > 3) && (((path[0] == '\\') && (path[1] == '\\') && (path[3] == '\\')) + || ((path[0] == '#') && (path[1] == '#') && (path[3] == '#'))))) { add_root = root_size; size += add_root; } - if ((ret_path = (char*) calloc(size, 1)) == NULL) + ret_path = calloc(1, size); + if (ret_path == NULL) return NULL; safe_strcpy(&ret_path[add_root], size-add_root, path); // Ensure consistency with root prefix - for (j=0; jcbSize = sizeof(SP_DEVINFO_DATA); if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) { + if (GetLastError() != ERROR_NO_MORE_ITEMS) usbi_err(ctx, "Could not obtain device info data for index %u: %s", _index, windows_error_str(0)); - } + pSetupDiDestroyDeviceInfoList(*dev_info); *dev_info = INVALID_HANDLE_VALUE; return false; @@ -251,23 +275,22 @@ static bool get_devinfo_data(struct libusb_context *ctx, * incremented index starting at zero) until all interfaces have been returned. */ static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details(struct libusb_context *ctx, - HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID* guid, unsigned _index) + HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID *guid, unsigned _index) { SP_DEVICE_INTERFACE_DATA dev_interface_data; SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL; DWORD size; - if (_index <= 0) { + if (_index <= 0) *dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); - } if (dev_info_data != NULL) { dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) { + if (GetLastError() != ERROR_NO_MORE_ITEMS) usbi_err(ctx, "Could not obtain device info data for index %u: %s", _index, windows_error_str(0)); - } + pSetupDiDestroyDeviceInfoList(*dev_info); *dev_info = INVALID_HANDLE_VALUE; return NULL; @@ -276,10 +299,10 @@ static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details(struct libusb_co dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, guid, _index, &dev_interface_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) { + if (GetLastError() != ERROR_NO_MORE_ITEMS) usbi_err(ctx, "Could not obtain interface data for index %u: %s", _index, windows_error_str(0)); - } + pSetupDiDestroyDeviceInfoList(*dev_info); *dev_info = INVALID_HANDLE_VALUE; return NULL; @@ -298,7 +321,8 @@ static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details(struct libusb_co goto err_exit; } - if ((dev_interface_details = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) calloc(size, 1)) == NULL) { + dev_interface_details = calloc(1, size); + if (dev_interface_details == NULL) { usbi_err(ctx, "could not allocate interface data for index %u.", _index); goto err_exit; } @@ -320,35 +344,39 @@ static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details(struct libusb_co /* For libusb0 filter */ static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details_filter(struct libusb_context *ctx, - HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID* guid, unsigned _index, char* filter_path){ + HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID *guid, unsigned _index, char *filter_path) +{ SP_DEVICE_INTERFACE_DATA dev_interface_data; SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL; DWORD size; - if (_index <= 0) { + + if (_index <= 0) *dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); - } + if (dev_info_data != NULL) { dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) { + if (GetLastError() != ERROR_NO_MORE_ITEMS) usbi_err(ctx, "Could not obtain device info data for index %u: %s", _index, windows_error_str(0)); - } + pSetupDiDestroyDeviceInfoList(*dev_info); *dev_info = INVALID_HANDLE_VALUE; return NULL; } } + dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, guid, _index, &dev_interface_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) { + if (GetLastError() != ERROR_NO_MORE_ITEMS) usbi_err(ctx, "Could not obtain interface data for index %u: %s", _index, windows_error_str(0)); - } + pSetupDiDestroyDeviceInfoList(*dev_info); *dev_info = INVALID_HANDLE_VALUE; return NULL; } + // Read interface data (dummy + actual) to access the device path if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, NULL, 0, &size, NULL)) { // The dummy call should fail with ERROR_INSUFFICIENT_BUFFER @@ -361,26 +389,29 @@ static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details_filter(struct li usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong."); goto err_exit; } - if ((dev_interface_details = malloc(size)) == NULL) { + + dev_interface_details = calloc(1, size); + if (dev_interface_details == NULL) { usbi_err(ctx, "could not allocate interface data for index %u.", _index); goto err_exit; } + dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); - if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, - dev_interface_details, size, &size, NULL)) { + if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, dev_interface_details, size, &size, NULL)) usbi_err(ctx, "could not access interface data (actual) for index %u: %s", _index, windows_error_str(0)); - } + // [trobinso] lookup the libusb0 symbolic index. if (dev_interface_details) { - HKEY hkey_device_interface=pSetupDiOpenDeviceInterfaceRegKey(*dev_info,&dev_interface_data,0,KEY_READ); + HKEY hkey_device_interface = pSetupDiOpenDeviceInterfaceRegKey(*dev_info, &dev_interface_data, 0, KEY_READ); if (hkey_device_interface != INVALID_HANDLE_VALUE) { - DWORD libusb0_symboliclink_index=0; - DWORD value_length=sizeof(DWORD); - DWORD value_type=0; + DWORD libusb0_symboliclink_index = 0; + DWORD value_length = sizeof(DWORD); + DWORD value_type = 0; LONG status; + status = pRegQueryValueExW(hkey_device_interface, L"LUsb0", NULL, &value_type, - (LPBYTE) &libusb0_symboliclink_index, &value_length); + (LPBYTE)&libusb0_symboliclink_index, &value_length); if (status == ERROR_SUCCESS) { if (libusb0_symboliclink_index < 256) { // libusb0.sys is connected to this device instance. @@ -394,11 +425,14 @@ static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details_filter(struct li pRegCloseKey(hkey_device_interface); } } + return dev_interface_details; + err_exit: pSetupDiDestroyDeviceInfoList(*dev_info); *dev_info = INVALID_HANDLE_VALUE; - return NULL;} + return NULL; +} /* * Returns the session ID of a device's nth level ancestor @@ -408,25 +442,27 @@ static unsigned long get_ancestor_session_id(DWORD devinst, unsigned level) { DWORD parent_devinst; unsigned long session_id = 0; - char* sanitized_path = NULL; + char *sanitized_path = NULL; char path[MAX_PATH_LENGTH]; unsigned i; - if (level < 1) return 0; - for (i = 0; iusb_interface[iface].endpoint = (uint8_t*) malloc(if_desc->bNumEndpoints); + priv->usb_interface[iface].endpoint = malloc(if_desc->bNumEndpoints); if (priv->usb_interface[iface].endpoint == NULL) { libusb_free_config_descriptor(conf_desc); return LIBUSB_ERROR_NO_MEM; } priv->usb_interface[iface].nb_endpoints = if_desc->bNumEndpoints; - for (i=0; ibNumEndpoints; i++) { + for (i = 0; i < if_desc->bNumEndpoints; i++) { priv->usb_interface[iface].endpoint[i] = if_desc->endpoint[i].bEndpointAddress; usbi_dbg("(re)assigned endpoint %02X to interface %d", priv->usb_interface[iface].endpoint[i], iface); } @@ -503,19 +539,24 @@ static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int // Lookup for a match in the list of API driver names // return -1 if not found, driver match number otherwise -static int get_sub_api(char* driver, int api){ +static int get_sub_api(char *driver, int api) +{ int i; const char sep_str[2] = {LIST_SEPARATOR, 0}; char *tok, *tmp_str; size_t len = safe_strlen(driver); - if (len == 0) return SUB_API_NOTSET; - tmp_str = (char*) calloc(len+1, 1); - if (tmp_str == NULL) return SUB_API_NOTSET; - memcpy(tmp_str, driver, len+1); + if (len == 0) + return SUB_API_NOTSET; + + tmp_str = calloc(1, len + 1); + if (tmp_str == NULL) + return SUB_API_NOTSET; + + memcpy(tmp_str, driver, len + 1); tok = strtok(tmp_str, sep_str); while (tok != NULL) { - for (i=0; iusb_interface[current_interface].apib->id == api_type) - && (libusb_claim_interface(transfer->dev_handle, current_interface) == LIBUSB_SUCCESS) ) { + if ((priv->usb_interface[current_interface].apib->id == api_type) + && (libusb_claim_interface(transfer->dev_handle, current_interface) == LIBUSB_SUCCESS)) { usbi_dbg("auto-claimed interface %d for control request", current_interface); - if (handle_priv->autoclaim_count[current_interface] != 0) { + if (handle_priv->autoclaim_count[current_interface] != 0) usbi_warn(ctx, "program assertion failed - autoclaim_count was nonzero"); - } handle_priv->autoclaim_count[current_interface]++; break; } @@ -569,23 +609,21 @@ static int auto_claim(struct libusb_transfer *transfer, int *interface_number, i } else { // If we have a valid interface that was autoclaimed, we must increment // its autoclaim count so that we can prevent an early release. - if (handle_priv->autoclaim_count[current_interface] != 0) { + if (handle_priv->autoclaim_count[current_interface] != 0) handle_priv->autoclaim_count[current_interface]++; - } } usbi_mutex_unlock(&autoclaim_lock); *interface_number = current_interface; return r; - } static void auto_release(struct usbi_transfer *itransfer) { - struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer); + struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); libusb_device_handle *dev_handle = transfer->dev_handle; - struct windows_device_handle_priv* handle_priv = _device_handle_priv(dev_handle); + struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); int r; usbi_mutex_lock(&autoclaim_lock); @@ -593,12 +631,11 @@ static void auto_release(struct usbi_transfer *itransfer) handle_priv->autoclaim_count[transfer_priv->interface_number]--; if (handle_priv->autoclaim_count[transfer_priv->interface_number] == 0) { r = libusb_release_interface(dev_handle, transfer_priv->interface_number); - if (r == LIBUSB_SUCCESS) { + if (r == LIBUSB_SUCCESS) usbi_dbg("auto-released interface %d", transfer_priv->interface_number); - } else { + else usbi_dbg("failed to auto-release interface %d (%s)", transfer_priv->interface_number, libusb_error_name((enum libusb_error)r)); - } } } usbi_mutex_unlock(&autoclaim_lock); @@ -608,24 +645,25 @@ static void auto_release(struct usbi_transfer *itransfer) static BOOL is_x64(void) { BOOL ret = FALSE; + // Detect if we're running a 32 or 64 bit system if (sizeof(uintptr_t) < 8) { DLL_LOAD_PREFIXED(Kernel32.dll, p, IsWow64Process, FALSE); - if (pIsWow64Process != NULL) { + if (pIsWow64Process != NULL) (*pIsWow64Process)(GetCurrentProcess(), &ret); - } } else { ret = TRUE; } + return ret; } static void get_windows_version(void) { OSVERSIONINFOEXA vi, vi2; - const char* w = 0; - const char* w64 = "32 bit"; - char* vptr; + const char *w = 0; + const char *w64 = "32 bit"; + char *vptr; size_t vlen; unsigned major, minor; ULONGLONG major_equal, minor_equal; @@ -641,7 +679,6 @@ static void get_windows_version(void) } if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) { - if (vi.dwMajorVersion > 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion >= 2)) { // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx @@ -649,19 +686,24 @@ static void get_windows_version(void) major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); for (major = vi.dwMajorVersion; major <= 9; major++) { memset(&vi2, 0, sizeof(vi2)); - vi2.dwOSVersionInfoSize = sizeof(vi2); vi2.dwMajorVersion = major; + vi2.dwOSVersionInfoSize = sizeof(vi2); + vi2.dwMajorVersion = major; if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal)) continue; + if (vi.dwMajorVersion < major) { - vi.dwMajorVersion = major; vi.dwMinorVersion = 0; + vi.dwMajorVersion = major; + vi.dwMinorVersion = 0; } minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL); for (minor = vi.dwMinorVersion; minor <= 9; minor++) { - memset(&vi2, 0, sizeof(vi2)); vi2.dwOSVersionInfoSize = sizeof(vi2); + memset(&vi2, 0, sizeof(vi2)); + vi2.dwOSVersionInfoSize = sizeof(vi2); vi2.dwMinorVersion = minor; if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal)) continue; + vi.dwMinorVersion = minor; break; } @@ -674,22 +716,14 @@ static void get_windows_version(void) ws = (vi.wProductType <= VER_NT_WORKSTATION); windows_version = vi.dwMajorVersion << 4 | vi.dwMinorVersion; switch (windows_version) { - case 0x50: w = "2000"; - break; - case 0x51: w = "XP"; - break; - case 0x52: w = ("2003"); - break; - case 0x60: w = (ws?"Vista":"2008"); - break; - case 0x61: w = (ws?"7":"2008_R2"); - break; - case 0x62: w = (ws?"8":"2012"); - break; - case 0x63: w = (ws?"8.1":"2012_R2"); - break; - case 0x64: w = (ws?"10":"2015"); - break; + case 0x50: w = "2000"; break; + case 0x51: w = "XP"; break; + case 0x52: w = ("2003"); break; + case 0x60: w = (ws ? "Vista" : "2008"); break; + case 0x61: w = (ws ? "7" : "2008_R2"); break; + case 0x62: w = (ws ? "8" : "2012"); break; + case 0x63: w = (ws ? "8.1": "2012_R2"); break; + case 0x64: w = (ws ? "10": "2015"); break; default: if (windows_version < 0x50) windows_version = WINDOWS_UNSUPPORTED; @@ -706,7 +740,7 @@ static void get_windows_version(void) vptr = &windows_version_str[sizeof("Windows ") - 1]; vlen = sizeof(windows_version_str) - sizeof("Windows ") - 1; if (!w) - safe_sprintf(vptr, vlen, "%s %u.%u %s", (vi.dwPlatformId==VER_PLATFORM_WIN32_NT?"NT":"??"), + safe_sprintf(vptr, vlen, "%s %u.%u %s", (vi.dwPlatformId == VER_PLATFORM_WIN32_NT ? "NT" : "??"), (unsigned int)vi.dwMajorVersion, (unsigned int)vi.dwMinorVersion, w64); else if (vi.wServicePackMinor) safe_sprintf(vptr, vlen, "%s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, w64); @@ -727,7 +761,7 @@ static int windows_init(struct libusb_context *ctx) { int i, r = LIBUSB_ERROR_OTHER; HANDLE semaphore; - char sem_name[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID) + char sem_name[11 + 1 + 8]; // strlen(libusb_init)+'\0'+(32-bit hex PID) sprintf(sem_name, "libusb_init%08X", (unsigned int)GetCurrentProcessId()); semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name); @@ -746,7 +780,7 @@ static int windows_init(struct libusb_context *ctx) // NB: concurrent usage supposes that init calls are equally balanced with // exit calls. If init is called more than exit, we will not exit properly - if ( ++concurrent_usage == 0 ) { // First init? + if (++concurrent_usage == 0) { // First init? get_windows_version(); usbi_dbg(windows_version_str); if (windows_version == WINDOWS_UNSUPPORTED) { @@ -768,14 +802,12 @@ static int windows_init(struct libusb_context *ctx) } // Initialize the low level APIs (we don't care about errors at this stage) - for (i=0; iparent_dev); if (sscanf(parent_priv->path, "\\\\.\\PCI#VEN_%04x&DEV_%04x%*s", &vid, &pid) == 2) { priv->dev_descriptor.idVendor = (uint16_t)vid; priv->dev_descriptor.idProduct = (uint16_t)pid; } else { usbi_warn(ctx, "could not infer VID/PID of HCD hub from '%s'", parent_priv->path); - priv->dev_descriptor.idVendor = 0x1d6b; // Linux Foundation root hub + priv->dev_descriptor.idVendor = 0x1d6b; // Linux Foundation root hub priv->dev_descriptor.idProduct = 1; } + return LIBUSB_SUCCESS; } /* * fetch and cache all the config descriptors through I/O */ -static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle, char* device_id) +static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle, char *device_id) { DWORD size, ret_size; struct libusb_context *ctx = DEVICE_CTX(dev); @@ -839,21 +873,21 @@ static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle int r; uint8_t i; - USB_CONFIGURATION_DESCRIPTOR_SHORT cd_buf_short; // dummy request - PUSB_DESCRIPTOR_REQUEST cd_buf_actual = NULL; // actual request + USB_CONFIGURATION_DESCRIPTOR_SHORT cd_buf_short; // dummy request + PUSB_DESCRIPTOR_REQUEST cd_buf_actual = NULL; // actual request PUSB_CONFIGURATION_DESCRIPTOR cd_data = NULL; if (dev->num_configurations == 0) return LIBUSB_ERROR_INVALID_PARAM; - priv->config_descriptor = (unsigned char**) calloc(dev->num_configurations, sizeof(unsigned char*)); + priv->config_descriptor = calloc(dev->num_configurations, sizeof(unsigned char *)); if (priv->config_descriptor == NULL) return LIBUSB_ERROR_NO_MEM; - for (i=0; inum_configurations; i++) + + for (i = 0; i < dev->num_configurations; i++) priv->config_descriptor[i] = NULL; - for (i=0, r=LIBUSB_SUCCESS; ; i++) - { + for (i = 0, r = LIBUSB_SUCCESS; ; i++) { // safe loop: release all dynamic resources safe_free(cd_buf_actual); @@ -886,11 +920,11 @@ static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle } size = sizeof(USB_DESCRIPTOR_REQUEST) + cd_buf_short.data.wTotalLength; - if ((cd_buf_actual = (PUSB_DESCRIPTOR_REQUEST) calloc(1, size)) == NULL) { + cd_buf_actual = calloc(1, size); + if (cd_buf_actual == NULL) { usbi_err(ctx, "could not allocate configuration descriptor buffer for '%s'.", device_id); LOOP_BREAK(LIBUSB_ERROR_NO_MEM); } - memset(cd_buf_actual, 0, size); // Actual call cd_buf_actual->ConnectionIndex = (ULONG)priv->port; @@ -906,7 +940,7 @@ static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle LOOP_BREAK(LIBUSB_ERROR_IO); } - cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR*)cd_buf_actual+sizeof(USB_DESCRIPTOR_REQUEST)); + cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR *)cd_buf_actual + sizeof(USB_DESCRIPTOR_REQUEST)); if ((size != ret_size) || (cd_data->wTotalLength != cd_buf_short.data.wTotalLength)) { usbi_err(ctx, "unexpected configuration descriptor size (actual) for '%s'.", device_id); @@ -922,7 +956,7 @@ static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle i, cd_data->bConfigurationValue, cd_data->wTotalLength); // Cache the descriptor - priv->config_descriptor[i] = (unsigned char*) malloc(cd_data->wTotalLength); + priv->config_descriptor[i] = malloc(cd_data->wTotalLength); if (priv->config_descriptor[i] == NULL) LOOP_BREAK(LIBUSB_ERROR_NO_MEM); memcpy(priv->config_descriptor[i], cd_data, cd_data->wTotalLength); @@ -933,8 +967,8 @@ static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle /* * Populate a libusb device structure */ -static int init_device(struct libusb_device* dev, struct libusb_device* parent_dev, - uint8_t port_number, char* device_id, DWORD devinst) +static int init_device(struct libusb_device *dev, struct libusb_device *parent_dev, + uint8_t port_number, char *device_id, DWORD devinst) { HANDLE handle; DWORD size; @@ -942,13 +976,13 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2; struct windows_device_priv *priv, *parent_priv; struct libusb_context *ctx; - struct libusb_device* tmp_dev; + struct libusb_device *tmp_dev; unsigned long tmp_id; unsigned i; - if ((dev == NULL) || (parent_dev == NULL)) { + if ((dev == NULL) || (parent_dev == NULL)) return LIBUSB_ERROR_NOT_FOUND; - } + ctx = DEVICE_CTX(dev); priv = _device_priv(dev); parent_priv = _device_priv(parent_dev); @@ -960,24 +994,31 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d // It is possible for the parent hub not to have been initialized yet // If that's the case, lookup the ancestors to set the bus number if (parent_dev->bus_number == 0) { - for (i=2; ; i++) { + for (i = 2; ; i++) { tmp_id = get_ancestor_session_id(devinst, i); - if (tmp_id == 0) break; + if (tmp_id == 0) + break; + tmp_dev = usbi_get_device_by_session_id(ctx, tmp_id); - if (tmp_dev == NULL) continue; + if (tmp_dev == NULL) + continue; + if (tmp_dev->bus_number != 0) { usbi_dbg("got bus number from ancestor #%u", i); parent_dev->bus_number = tmp_dev->bus_number; libusb_unref_device(tmp_dev); break; } + libusb_unref_device(tmp_dev); } } + if (parent_dev->bus_number == 0) { usbi_err(ctx, "program assertion failed: unable to find ancestor bus number for '%s'", device_id); return LIBUSB_ERROR_NOT_FOUND; } + dev->bus_number = parent_dev->bus_number; priv->port = port_number; dev->port_number = port_number; @@ -986,17 +1027,18 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d dev->parent_dev = parent_dev; // If the device address is already set, we can stop here - if (dev->device_address != 0) { + if (dev->device_address != 0) return LIBUSB_SUCCESS; - } + memset(&conn_info, 0, sizeof(conn_info)); - if (priv->depth != 0) { // Not a HCD hub + if (priv->depth != 0) { // Not a HCD hub handle = CreateFileA(parent_priv->path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (handle == INVALID_HANDLE_VALUE) { usbi_warn(ctx, "could not open hub %s: %s", parent_priv->path, windows_error_str(0)); return LIBUSB_ERROR_ACCESS; } + size = sizeof(conn_info); conn_info.ConnectionIndex = (ULONG)port_number; // coverity[tainted_data_argument] @@ -1007,15 +1049,18 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d safe_closehandle(handle); return LIBUSB_ERROR_NO_DEVICE; } + if (conn_info.ConnectionStatus == NoDeviceConnected) { usbi_err(ctx, "device '%s' is no longer connected!", device_id); safe_closehandle(handle); return LIBUSB_ERROR_NO_DEVICE; } + memcpy(&priv->dev_descriptor, &(conn_info.DeviceDescriptor), sizeof(USB_DEVICE_DESCRIPTOR)); dev->num_configurations = priv->dev_descriptor.bNumConfigurations; priv->active_config = conn_info.CurrentConfigurationValue; usbi_dbg("found %u configurations (active conf: %u)", dev->num_configurations, priv->active_config); + // If we can't read the config descriptors, just set the number of confs to zero if (cache_config_descriptors(dev, handle, device_id) != LIBUSB_SUCCESS) { dev->num_configurations = 0; @@ -1040,13 +1085,13 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d safe_closehandle(handle); - if (conn_info.DeviceAddress > UINT8_MAX) { + if (conn_info.DeviceAddress > UINT8_MAX) usbi_err(ctx, "program assertion failed: device address overflow"); - } + dev->device_address = (uint8_t)conn_info.DeviceAddress + 1; - if (dev->device_address == 1) { + if (dev->device_address == 1) usbi_err(ctx, "program assertion failed: device address collision with root hub"); - } + switch (conn_info.Speed) { case 0: dev->speed = LIBUSB_SPEED_LOW; break; case 1: dev->speed = LIBUSB_SPEED_FULL; break; @@ -1057,7 +1102,7 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d break; } } else { - dev->device_address = 1; // root hubs are set to use device number 1 + dev->device_address = 1; // root hubs are set to use device number 1 force_hcd_device_descriptor(dev); } @@ -1085,38 +1130,37 @@ static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info, *api = USB_API_UNSUPPORTED; *sub_api = SUB_API_NOTSET; + // Check the service & filter names to know the API we should use - for (k=0; k<3; k++) { + for (k = 0; k < 3; k++) { if (pSetupDiGetDeviceRegistryPropertyA(*dev_info, dev_info_data, lookup[k].reg_prop, - ®_type, (BYTE*)lookup[k].list, MAX_KEY_LENGTH, &size)) { + ®_type, (BYTE *)lookup[k].list, MAX_KEY_LENGTH, &size)) { // Turn the REG_SZ SPDRP_SERVICE into REG_MULTI_SZ - if (lookup[k].reg_prop == SPDRP_SERVICE) { - // our buffers are MAX_KEY_LENGTH+1 so we can overflow if needed - lookup[k].list[safe_strlen(lookup[k].list)+1] = 0; - } + if (lookup[k].reg_prop == SPDRP_SERVICE) + // our buffers are MAX_KEY_LENGTH + 1 so we can overflow if needed + lookup[k].list[safe_strlen(lookup[k].list) + 1] = 0; + // MULTI_SZ is a pain to work with. Turn it into something much more manageable // NB: none of the driver names we check against contain LIST_SEPARATOR, // (currently ';'), so even if an unsuported one does, it's not an issue - for (l=0; (lookup[k].list[l] != 0) || (lookup[k].list[l+1] != 0); l++) { - if (lookup[k].list[l] == 0) { + for (l = 0; (lookup[k].list[l] != 0) || (lookup[k].list[l + 1] != 0); l++) { + if (lookup[k].list[l] == 0) lookup[k].list[l] = LIST_SEPARATOR; - } } usbi_dbg("%s(s): %s", lookup[k].designation, lookup[k].list); } else { - if (GetLastError() != ERROR_INVALID_DATA) { + if (GetLastError() != ERROR_INVALID_DATA) usbi_dbg("could not access %s: %s", lookup[k].designation, windows_error_str(0)); - } lookup[k].list[0] = 0; } } - for (i=1; i= 0) { - usbi_dbg("matched %s name against %s", - lookup[k].designation, (i!=USB_API_WINUSBX)?usb_api_backend[i].designation:sub_api_name[j]); + usbi_dbg("matched %s name against %s", lookup[k].designation, + (i != USB_API_WINUSBX) ? usb_api_backend[i].designation : sub_api_name[j]); *api = i; *sub_api = j; return; @@ -1125,8 +1169,8 @@ static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info, } } -static int set_composite_interface(struct libusb_context* ctx, struct libusb_device* dev, - char* dev_interface_path, char* device_id, int api, int sub_api) +static int set_composite_interface(struct libusb_context *ctx, struct libusb_device *dev, + char *dev_interface_path, char *device_id, int api, int sub_api) { unsigned i; struct windows_device_priv *priv = _device_priv(dev); @@ -1141,19 +1185,18 @@ static int set_composite_interface(struct libusb_context* ctx, struct libusb_dev // devices will have only MI_00 & MI_03 for instance), we retrieve the actual // interface number from the path's MI value interface_number = 0; - for (i=0; device_id[i] != 0; ) { - if ( (device_id[i++] == 'M') && (device_id[i++] == 'I') - && (device_id[i++] == '_') ) { - interface_number = (device_id[i++] - '0')*10; + for (i = 0; device_id[i] != 0; ) { + if ((device_id[i++] == 'M') && (device_id[i++] == 'I') + && (device_id[i++] == '_')) { + interface_number = (device_id[i++] - '0') * 10; interface_number += device_id[i] - '0'; break; } } - if (device_id[i] == 0) { + if (device_id[i] == 0) usbi_warn(ctx, "failure to read interface number for %s. Using default value %d", device_id, interface_number); - } if (priv->usb_interface[interface_number].path != NULL) { if (api == USB_API_HID) { @@ -1171,7 +1214,7 @@ static int set_composite_interface(struct libusb_context* ctx, struct libusb_dev priv->usb_interface[interface_number].apib = &usb_api_backend[api]; priv->usb_interface[interface_number].sub_api = sub_api; if ((api == USB_API_HID) && (priv->hid == NULL)) { - priv->hid = (struct hid_device_priv*) calloc(1, sizeof(struct hid_device_priv)); + priv->hid = calloc(1, sizeof(struct hid_device_priv)); if (priv->hid == NULL) return LIBUSB_ERROR_NO_MEM; } @@ -1179,8 +1222,8 @@ static int set_composite_interface(struct libusb_context* ctx, struct libusb_dev return LIBUSB_SUCCESS; } -static int set_hid_interface(struct libusb_context* ctx, struct libusb_device* dev, - char* dev_interface_path) +static int set_hid_interface(struct libusb_context *ctx, struct libusb_device *dev, + char *dev_interface_path) { int i; struct windows_device_priv *priv = _device_priv(dev); @@ -1188,12 +1231,12 @@ static int set_hid_interface(struct libusb_context* ctx, struct libusb_device* d if (priv->hid == NULL) { usbi_err(ctx, "program assertion failed: parent is not HID"); return LIBUSB_ERROR_NO_DEVICE; - } - if (priv->hid->nb_interfaces == USB_MAXINTERFACES) { + } else if (priv->hid->nb_interfaces == USB_MAXINTERFACES) { usbi_err(ctx, "program assertion failed: max USB interfaces reached for HID device"); return LIBUSB_ERROR_NO_DEVICE; } - for (i=0; ihid->nb_interfaces; i++) { + + for (i = 0; i < priv->hid->nb_interfaces; i++) { if (safe_strcmp(priv->usb_interface[i].path, dev_interface_path) == 0) { usbi_dbg("interface[%d] already set to %s", i, dev_interface_path); return LIBUSB_SUCCESS; @@ -1214,12 +1257,12 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered { struct discovered_devs *discdevs; HDEVINFO dev_info = { 0 }; - const char* usb_class[] = {"USB", "NUSB3", "IUSB3"}; + const char *usb_class[] = {"USB", "NUSB3", "IUSB3"}; SP_DEVINFO_DATA dev_info_data = { 0 }; SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL; GUID hid_guid; #define MAX_ENUM_GUIDS 64 - const GUID* guid[MAX_ENUM_GUIDS]; + const GUID *guid[MAX_ENUM_GUIDS]; #define HCD_PASS 0 #define HUB_PASS 1 #define GEN_PASS 2 @@ -1233,16 +1276,16 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered char strbuf[MAX_PATH_LENGTH]; struct libusb_device *dev, *parent_dev; struct windows_device_priv *priv, *parent_priv; - char* dev_interface_path = NULL; - char* dev_id_path = NULL; + char *dev_interface_path = NULL; + char *dev_id_path = NULL; unsigned long session_id; DWORD size, reg_type, port_nr, install_state; HKEY key; WCHAR guid_string_w[MAX_GUID_STRING_LENGTH]; - GUID* if_guid; + GUID *if_guid; LONG s; // Keep a list of newly allocated devs to unref - libusb_device** unref_list; + libusb_device **unref_list; unsigned int unref_size = 64; unsigned int unref_cur = 0; @@ -1261,19 +1304,18 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered guid[DEV_PASS] = &GUID_DEVINTERFACE_USB_DEVICE; HidD_GetHidGuid(&hid_guid); guid[HID_PASS] = &hid_guid; - nb_guids = HID_PASS+1; + nb_guids = HID_PASS + 1; - unref_list = (libusb_device**) calloc(unref_size, sizeof(libusb_device*)); - if (unref_list == NULL) { + unref_list = calloc(unref_size, sizeof(libusb_device *)); + if (unref_list == NULL) return LIBUSB_ERROR_NO_MEM; - } for (pass = 0; ((pass < nb_guids) && (r == LIBUSB_SUCCESS)); pass++) { //#define ENUM_DEBUG #ifdef ENUM_DEBUG const char *passname[] = { "HCD", "HUB", "GEN", "DEV", "HID", "EXT" }; - usbi_dbg("#### PROCESSING %ss %s", passname[(pass<=HID_PASS)?pass:HID_PASS+1], - (pass!=GEN_PASS)?guid_to_string(guid[pass]):""); + usbi_dbg("#### PROCESSING %ss %s", passname[(pass <= HID_PASS) ? pass : (HID_PASS + 1)], + (pass != GEN_PASS) ? guid_to_string(guid[pass]) : ""); #endif for (i = 0; ; i++) { // safe loop: free up any (unprotected) dynamic resource @@ -1285,24 +1327,24 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered dev = parent_dev = NULL; // Safe loop: end of loop conditions - if (r != LIBUSB_SUCCESS) { + if (r != LIBUSB_SUCCESS) break; - } + if ((pass == HCD_PASS) && (i == UINT8_MAX)) { usbi_warn(ctx, "program assertion failed - found more than %d buses, skipping the rest.", UINT8_MAX); break; } + if (pass != GEN_PASS) { // Except for GEN, all passes deal with device interfaces dev_interface_details = get_interface_details(ctx, &dev_info, &dev_info_data, guid[pass], i); - if (dev_interface_details == NULL) { + if (dev_interface_details == NULL) break; - } else { - dev_interface_path = sanitize_path(dev_interface_details->DevicePath); - if (dev_interface_path == NULL) { - usbi_warn(ctx, "could not sanitize device interface path for '%s'", dev_interface_details->DevicePath); - continue; - } + + dev_interface_path = sanitize_path(dev_interface_details->DevicePath); + if (dev_interface_path == NULL) { + usbi_warn(ctx, "could not sanitize device interface path for '%s'", dev_interface_details->DevicePath); + continue; } } else { // Workaround for a Nec/Renesas USB 3.0 driver bug where root hubs are @@ -1324,6 +1366,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered (unsigned int)dev_info_data.DevInst); continue; } + dev_id_path = sanitize_path(path); if (dev_id_path == NULL) { usbi_warn(ctx, "could not sanitize device id path for devinst %X, skipping", @@ -1337,9 +1380,8 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered // The SPDRP_ADDRESS for USB devices is the device port number on the hub port_nr = 0; if ((pass >= HUB_PASS) && (pass <= GEN_PASS)) { - if ( (!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_ADDRESS, - ®_type, (BYTE*)&port_nr, 4, &size)) - || (size != 4) ) { + if ((!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_ADDRESS, + ®_type, (BYTE *)&port_nr, 4, &size)) || (size != 4)) { usbi_warn(ctx, "could not retrieve port number for device '%s', skipping: %s", dev_id_path, windows_error_str(0)); continue; @@ -1356,7 +1398,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered // We use the GEN pass to detect driverless devices... size = sizeof(strbuf); if (!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_DRIVER, - ®_type, (BYTE*)strbuf, size, &size)) { + ®_type, (BYTE *)strbuf, size, &size)) { usbi_info(ctx, "The following device has no driver: '%s'", dev_id_path); usbi_info(ctx, "libusb will not be able to access it."); } @@ -1365,7 +1407,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered if (key != INVALID_HANDLE_VALUE) { size = sizeof(guid_string_w); s = pRegQueryValueExW(key, L"DeviceInterfaceGUIDs", NULL, ®_type, - (BYTE*)guid_string_w, &size); + (BYTE *)guid_string_w, &size); pRegCloseKey(key); if (s == ERROR_SUCCESS) { if (nb_guids >= MAX_ENUM_GUIDS) { @@ -1373,7 +1415,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered usbi_err(ctx, "program assertion failed: too many GUIDs"); LOOP_BREAK(LIBUSB_ERROR_OVERFLOW); } - if_guid = (GUID*) calloc(1, sizeof(GUID)); + if_guid = calloc(1, sizeof(GUID)); if (if_guid == NULL) { usbi_err(ctx, "could not calloc for if_guid: not enough memory"); LOOP_BREAK(LIBUSB_ERROR_NO_MEM); @@ -1389,9 +1431,8 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered break; default: // Get the API type (after checking that the driver installation is OK) - if ( (!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_INSTALL_STATE, - ®_type, (BYTE*)&install_state, 4, &size)) - || (size != 4) ){ + if ((!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_INSTALL_STATE, + ®_type, (BYTE *)&install_state, 4, &size)) || (size != 4)) { usbi_warn(ctx, "could not detect installation state of driver for '%s': %s", dev_id_path, windows_error_str(0)); } else if (install_state != 0) { @@ -1414,21 +1455,24 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered parent_dev = NULL; for (ancestor = 1; parent_dev == NULL; ancestor++) { session_id = get_ancestor_session_id(dev_info_data.DevInst, ancestor); - if (session_id == 0) { + if (session_id == 0) break; - } + parent_dev = usbi_get_device_by_session_id(ctx, session_id); } + if (parent_dev == NULL) { usbi_dbg("unlisted ancestor for '%s' (non USB HID, newly connected, etc.) - ignoring", dev_id_path); continue; } + parent_priv = _device_priv(parent_dev); // virtual USB devices are also listed during GEN - don't process these yet - if ( (pass == GEN_PASS) && (parent_priv->apib->id != USB_API_HUB) ) { + if ((pass == GEN_PASS) && (parent_priv->apib->id != USB_API_HUB)) { libusb_unref_device(parent_dev); continue; } + break; } @@ -1444,20 +1488,23 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered " - ignoring", dev_id_path); continue; } + usbi_dbg("allocating new device for session [%lX]", session_id); - if ((dev = usbi_alloc_device(ctx, session_id)) == NULL) { + dev = usbi_alloc_device(ctx, session_id); + if (dev == NULL) LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - } + windows_device_priv_init(dev); } else { usbi_dbg("found existing device for session [%lX] (%u.%u)", session_id, dev->bus_number, dev->device_address); } + // Keep track of devices that need unref unref_list[unref_cur++] = dev; if (unref_cur >= unref_size) { unref_size += 64; - unref_list = usbi_reallocf(unref_list, unref_size*sizeof(libusb_device*)); + unref_list = usbi_reallocf(unref_list, unref_size * sizeof(libusb_device *)); if (unref_list == NULL) { usbi_err(ctx, "could not realloc list for unref - aborting."); LOOP_BREAK(LIBUSB_ERROR_NO_MEM); @@ -1469,13 +1516,14 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered // Setup device switch (pass) { case HCD_PASS: - dev->bus_number = (uint8_t)(i + 1); // bus 0 is reserved for disconnected + dev->bus_number = (uint8_t)(i + 1); // bus 0 is reserved for disconnected dev->device_address = 0; dev->num_configurations = 0; priv->apib = &usb_api_backend[USB_API_HUB]; priv->sub_api = SUB_API_NOTSET; - priv->depth = UINT8_MAX; // Overflow to 0 for HCD Hubs - priv->path = dev_interface_path; dev_interface_path = NULL; + priv->depth = UINT8_MAX; // Overflow to 0 for HCD Hubs + priv->path = dev_interface_path; + dev_interface_path = NULL; break; case HUB_PASS: case DEV_PASS: @@ -1483,7 +1531,8 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered if (priv->path != NULL) break; // Take care of API initialization - priv->path = dev_interface_path; dev_interface_path = NULL; + priv->path = dev_interface_path; + dev_interface_path = NULL; priv->apib = &usb_api_backend[api]; priv->sub_api = sub_api; switch(api) { @@ -1492,24 +1541,23 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered break; case USB_API_HID: priv->hid = calloc(1, sizeof(struct hid_device_priv)); - if (priv->hid == NULL) { + if (priv->hid == NULL) LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - } + priv->hid->nb_interfaces = 0; break; default: // For other devices, the first interface is the same as the device - priv->usb_interface[0].path = (char*) calloc(safe_strlen(priv->path)+1, 1); - if (priv->usb_interface[0].path != NULL) { - safe_strcpy(priv->usb_interface[0].path, safe_strlen(priv->path)+1, priv->path); - } else { + priv->usb_interface[0].path = calloc(1, safe_strlen(priv->path)); + if (priv->usb_interface[0].path != NULL) + safe_strcpy(priv->usb_interface[0].path, safe_strlen(priv->path) + 1, priv->path); + else usbi_warn(ctx, "could not duplicate interface path '%s'", priv->path); - } // The following is needed if we want API calls to work for both simple // and composite devices. - for(j=0; jusb_interface[j].apib = &usb_api_backend[api]; - } + break; } break; @@ -1518,9 +1566,9 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered if (r == LIBUSB_SUCCESS) { // Append device to the list of discovered devices discdevs = discovered_devs_append(*_discdevs, dev); - if (!discdevs) { + if (!discdevs) LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - } + *_discdevs = discdevs; } else if (r == LIBUSB_ERROR_NO_DEVICE) { // This can occur if the device was disconnected but Windows hasn't @@ -1528,11 +1576,13 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered r = LIBUSB_SUCCESS; } break; - default: // HID_PASS and later + default: // HID_PASS and later if (parent_priv->apib->id == USB_API_HID) { usbi_dbg("setting HID interface for [%lX]:", parent_dev->session_data); r = set_hid_interface(ctx, parent_dev, dev_interface_path); - if (r != LIBUSB_SUCCESS) LOOP_BREAK(r); + if (r != LIBUSB_SUCCESS) + LOOP_BREAK(r); + dev_interface_path = NULL; } else if (parent_priv->apib->id == USB_API_COMPOSITE) { usbi_dbg("setting composite interface for [%lX]:", parent_dev->session_data); @@ -1555,15 +1605,13 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered } // Free any additional GUIDs - for (pass = HID_PASS+1; pass < nb_guids; pass++) { + for (pass = HID_PASS + 1; pass < nb_guids; pass++) safe_free(guid[pass]); - } // Unref newly allocated devs if (unref_list != NULL) { - for (i=0; i any concurent wait stalls until the semaphore release @@ -1593,16 +1640,15 @@ static void windows_exit(void) } // Only works if exits and inits are balanced exactly - if (--concurrent_usage < 0) { // Last exit - for (i=0; idev_descriptor), DEVICE_DESC_LENGTH); + memcpy(buffer, &priv->dev_descriptor, DEVICE_DESC_LENGTH); *host_endian = 0; return LIBUSB_SUCCESS; @@ -1703,9 +1749,9 @@ static int windows_set_configuration(struct libusb_device_handle *dev_handle, in LIBUSB_REQUEST_SET_CONFIGURATION, (uint16_t)config, 0, NULL, 0, 1000); - if (r == LIBUSB_SUCCESS) { + if (r == LIBUSB_SUCCESS) priv->active_config = (uint8_t)config; - } + return r; } @@ -1715,13 +1761,12 @@ static int windows_claim_interface(struct libusb_device_handle *dev_handle, int struct windows_device_priv *priv = _device_priv(dev_handle->dev); safe_free(priv->usb_interface[iface].endpoint); - priv->usb_interface[iface].nb_endpoints= 0; + priv->usb_interface[iface].nb_endpoints = 0; r = priv->apib->claim_interface(SUB_API_NOTSET, dev_handle, iface); - if (r == LIBUSB_SUCCESS) { + if (r == LIBUSB_SUCCESS) r = windows_assign_endpoints(dev_handle, iface, 0); - } return r; } @@ -1732,13 +1777,12 @@ static int windows_set_interface_altsetting(struct libusb_device_handle *dev_han struct windows_device_priv *priv = _device_priv(dev_handle->dev); safe_free(priv->usb_interface[iface].endpoint); - priv->usb_interface[iface].nb_endpoints= 0; + priv->usb_interface[iface].nb_endpoints = 0; r = priv->apib->set_interface_altsetting(SUB_API_NOTSET, dev_handle, iface, altsetting); - if (r == LIBUSB_SUCCESS) { + if (r == LIBUSB_SUCCESS) r = windows_assign_endpoints(dev_handle, iface, altsetting); - } return r; } @@ -1785,7 +1829,7 @@ static void windows_destroy_device(struct libusb_device *dev) void windows_clear_transfer_priv(struct usbi_transfer *itransfer) { - struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer); + struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); usbi_free_fd(&transfer_priv->pollable_fd); safe_free(transfer_priv->hid_buffer); @@ -1797,14 +1841,13 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer); + struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); int r; r = priv->apib->submit_bulk_transfer(SUB_API_NOTSET, itransfer); - if (r != LIBUSB_SUCCESS) { + if (r != LIBUSB_SUCCESS) return r; - } usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, (short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT)); @@ -1816,14 +1859,13 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer); + struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); int r; r = priv->apib->submit_iso_transfer(SUB_API_NOTSET, itransfer); - if (r != LIBUSB_SUCCESS) { + if (r != LIBUSB_SUCCESS) return r; - } usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, (short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT)); @@ -1835,19 +1877,17 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer); + struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); int r; r = priv->apib->submit_control_transfer(SUB_API_NOTSET, itransfer); - if (r != LIBUSB_SUCCESS) { + if (r != LIBUSB_SUCCESS) return r; - } usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN); return LIBUSB_SUCCESS; - } static int windows_submit_transfer(struct usbi_transfer *itransfer) @@ -1859,8 +1899,7 @@ static int windows_submit_transfer(struct usbi_transfer *itransfer) return submit_control_transfer(itransfer); case LIBUSB_TRANSFER_TYPE_BULK: case LIBUSB_TRANSFER_TYPE_INTERRUPT: - if (IS_XFEROUT(transfer) && - transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) + if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)) return LIBUSB_ERROR_NOT_SUPPORTED; return submit_bulk_transfer(itransfer); case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: @@ -1926,9 +1965,9 @@ void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd if (HasOverlappedIoCompletedSync(pollable_fd->overlapped)) { *io_result = NO_ERROR; *io_size = (DWORD)pollable_fd->overlapped->InternalHigh; - // Regular async overlapped } else if (GetOverlappedResult(pollable_fd->handle, pollable_fd->overlapped, io_size, false)) { + // Regular async overlapped *io_result = NO_ERROR; } else { @@ -1991,62 +2030,96 @@ const struct usbi_os_backend windows_backend = { /* * USB API backends */ -static int unsupported_init(int sub_api, struct libusb_context *ctx) { +static int unsupported_init(int sub_api, struct libusb_context *ctx) +{ return LIBUSB_SUCCESS; } -static int unsupported_exit(int sub_api) { + +static int unsupported_exit(int sub_api) +{ return LIBUSB_SUCCESS; } -static int unsupported_open(int sub_api, struct libusb_device_handle *dev_handle) { + +static int unsupported_open(int sub_api, struct libusb_device_handle *dev_handle) +{ PRINT_UNSUPPORTED_API(open); } -static void unsupported_close(int sub_api, struct libusb_device_handle *dev_handle) { + +static void unsupported_close(int sub_api, struct libusb_device_handle *dev_handle) +{ usbi_dbg("unsupported API call for 'close'"); } -static int unsupported_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface) { + +static int unsupported_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface) +{ PRINT_UNSUPPORTED_API(configure_endpoints); } -static int unsupported_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) { + +static int unsupported_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) +{ PRINT_UNSUPPORTED_API(claim_interface); } -static int unsupported_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) { + +static int unsupported_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) +{ PRINT_UNSUPPORTED_API(set_interface_altsetting); } -static int unsupported_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) { + +static int unsupported_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) +{ PRINT_UNSUPPORTED_API(release_interface); } -static int unsupported_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) { + +static int unsupported_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) +{ PRINT_UNSUPPORTED_API(clear_halt); } -static int unsupported_reset_device(int sub_api, struct libusb_device_handle *dev_handle) { + +static int unsupported_reset_device(int sub_api, struct libusb_device_handle *dev_handle) +{ PRINT_UNSUPPORTED_API(reset_device); } -static int unsupported_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) { + +static int unsupported_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) +{ PRINT_UNSUPPORTED_API(submit_bulk_transfer); } -static int unsupported_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) { + +static int unsupported_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) +{ PRINT_UNSUPPORTED_API(submit_iso_transfer); } -static int unsupported_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) { + +static int unsupported_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) +{ PRINT_UNSUPPORTED_API(submit_control_transfer); } -static int unsupported_abort_control(int sub_api, struct usbi_transfer *itransfer) { + +static int unsupported_abort_control(int sub_api, struct usbi_transfer *itransfer) +{ PRINT_UNSUPPORTED_API(abort_control); } -static int unsupported_abort_transfers(int sub_api, struct usbi_transfer *itransfer) { + +static int unsupported_abort_transfers(int sub_api, struct usbi_transfer *itransfer) +{ PRINT_UNSUPPORTED_API(abort_transfers); } -static int unsupported_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) { + +static int unsupported_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) +{ PRINT_UNSUPPORTED_API(copy_transfer_data); } -static int common_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface) { + +static int common_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface) +{ return LIBUSB_SUCCESS; } + // These names must be uppercase -const char* hub_driver_names[] = {"USBHUB", "USBHUB3", "USB3HUB", "NUSB3HUB", "RUSB3HUB", "FLXHCIH", "TIHUB3", "ETRONHUB3", "VIAHUB3", "ASMTHUB3", "IUSB3HUB", "VUSB3HUB", "AMDHUB30", "VHHUB"}; -const char* composite_driver_names[] = {"USBCCGP"}; -const char* winusbx_driver_names[] = WINUSBX_DRV_NAMES; -const char* hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"}; +static const char *hub_driver_names[] = {"USBHUB", "USBHUB3", "USB3HUB", "NUSB3HUB", "RUSB3HUB", "FLXHCIH", "TIHUB3", "ETRONHUB3", "VIAHUB3", "ASMTHUB3", "IUSB3HUB", "VUSB3HUB", "AMDHUB30", "VHHUB"}; +static const char *composite_driver_names[] = {"USBCCGP"}; +static const char *winusbx_driver_names[] = WINUSBX_DRV_NAMES; +static const char *hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"}; const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { { USB_API_UNSUPPORTED, @@ -2069,7 +2142,8 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { unsupported_abort_control, unsupported_abort_transfers, unsupported_copy_transfer_data, - }, { + }, + { USB_API_HUB, "HUB API", hub_driver_names, @@ -2090,7 +2164,8 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { unsupported_abort_control, unsupported_abort_transfers, unsupported_copy_transfer_data, - }, { + }, + { USB_API_COMPOSITE, "Composite API", composite_driver_names, @@ -2111,7 +2186,8 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { composite_abort_control, composite_abort_transfers, composite_copy_transfer_data, - }, { + }, + { USB_API_WINUSBX, "WinUSB-like APIs", winusbx_driver_names, @@ -2132,7 +2208,8 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { winusbx_abort_control, winusbx_abort_transfers, winusbx_copy_transfer_data, - }, { + }, + { USB_API_HID, "HID API", hid_driver_names, @@ -2160,48 +2237,55 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { /* * WinUSB-like (WinUSB, libusb0/libusbK through libusbk DLL) API functions */ -#define WinUSBX_Set(fn) do { if (native_winusb) WinUSBX[i].fn = (WinUsb_##fn##_t) GetProcAddress(h, "WinUsb_" #fn); \ - else pLibK_GetProcAddress((PVOID*)&WinUSBX[i].fn, i, KUSB_FNID_##fn); } while (0) +#define WinUSBX_Set(fn) \ + do { \ + if (native_winusb) \ + WinUSBX[i].fn = (WinUsb_##fn##_t) GetProcAddress(h, "WinUsb_" #fn); \ + else \ + pLibK_GetProcAddress((PVOID *)&WinUSBX[i].fn, i, KUSB_FNID_##fn); \ + } while (0) static int winusbx_init(int sub_api, struct libusb_context *ctx) { - HMODULE h = NULL; - bool native_winusb = false; + HMODULE h; + bool native_winusb; int i; KLIB_VERSION LibK_Version; LibK_GetProcAddress_t pLibK_GetProcAddress = NULL; - LibK_GetVersion_t pLibK_GetVersion = NULL; + LibK_GetVersion_t pLibK_GetVersion; h = GetModuleHandleA("libusbK"); - if (h == NULL) { + if (h == NULL) h = LoadLibraryA("libusbK"); - } + if (h == NULL) { usbi_info(ctx, "libusbK DLL is not available, will use native WinUSB"); h = GetModuleHandleA("WinUSB"); - if (h == NULL) { + if (h == NULL) h = LoadLibraryA("WinUSB"); - } if (h == NULL) { + + if (h == NULL) { usbi_warn(ctx, "WinUSB DLL is not available either, " "you will not be able to access devices outside of enumeration"); return LIBUSB_ERROR_NOT_FOUND; } } else { usbi_dbg("using libusbK DLL for universal access"); - pLibK_GetVersion = (LibK_GetVersion_t) GetProcAddress(h, "LibK_GetVersion"); + pLibK_GetVersion = (LibK_GetVersion_t)GetProcAddress(h, "LibK_GetVersion"); if (pLibK_GetVersion != NULL) { pLibK_GetVersion(&LibK_Version); usbi_dbg("libusbK version: %d.%d.%d.%d", LibK_Version.Major, LibK_Version.Minor, LibK_Version.Micro, LibK_Version.Nano); } - pLibK_GetProcAddress = (LibK_GetProcAddress_t) GetProcAddress(h, "LibK_GetProcAddress"); + pLibK_GetProcAddress = (LibK_GetProcAddress_t)GetProcAddress(h, "LibK_GetProcAddress"); if (pLibK_GetProcAddress == NULL) { usbi_err(ctx, "LibK_GetProcAddress() not found in libusbK DLL"); return LIBUSB_ERROR_NOT_FOUND; } } + native_winusb = (pLibK_GetProcAddress == NULL); - for (i=SUB_API_LIBUSBK; iusb_interface[i].path != NULL) - && (priv->usb_interface[i].apib->id == USB_API_WINUSBX) ) { + if ((priv->usb_interface[i].path != NULL) + && (priv->usb_interface[i].apib->id == USB_API_WINUSBX)) { file_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (file_handle == INVALID_HANDLE_VALUE) { usbi_err(ctx, "could not open device %s (interface %d): %s", priv->usb_interface[i].path, i, windows_error_str(0)); switch(GetLastError()) { - case ERROR_FILE_NOT_FOUND: // The device was disconnected + case ERROR_FILE_NOT_FOUND: // The device was disconnected return LIBUSB_ERROR_NO_DEVICE; case ERROR_ACCESS_DENIED: return LIBUSB_ERROR_ACCESS; @@ -2288,6 +2373,7 @@ static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle) if (sub_api == SUB_API_NOTSET) sub_api = priv->sub_api; + if (!WinUSBX[sub_api].initialized) return; @@ -2297,13 +2383,12 @@ static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle) for (i = 0; i < USB_MAXINTERFACES; i++) { if (priv->usb_interface[i].apib->id == USB_API_WINUSBX) { handle = handle_priv->interface_handle[i].api_handle; - if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) { + if (HANDLE_VALID(handle)) WinUSBX[sub_api].Free(handle); - } + handle = handle_priv->interface_handle[i].dev_handle; - if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) { + if (HANDLE_VALID(handle)) CloseHandle(handle); - } } } } @@ -2312,18 +2397,16 @@ static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle) // then free and close interface 0 last for (i = 1; i < USB_MAXINTERFACES; i++) { handle = handle_priv->interface_handle[i].api_handle; - if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) { + if (HANDLE_VALID(handle)) WinUSBX[sub_api].Free(handle); - } } handle = handle_priv->interface_handle[0].api_handle; - if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) { + if (HANDLE_VALID(handle)) WinUSBX[sub_api].Free(handle); - } + handle = handle_priv->interface_handle[0].dev_handle; - if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) { + if (HANDLE_VALID(handle)) CloseHandle(handle); - } } } @@ -2341,35 +2424,34 @@ static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle // With handle and enpoints set (in parent), we can setup the default pipe properties // see http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DVC-T705_DDC08.pptx - for (i=-1; iusb_interface[iface].nb_endpoints; i++) { - endpoint_address =(i==-1)?0:priv->usb_interface[iface].endpoint[i]; + for (i = -1; i < priv->usb_interface[iface].nb_endpoints; i++) { + endpoint_address = (i == -1) ? 0 : priv->usb_interface[iface].endpoint[i]; if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - PIPE_TRANSFER_TIMEOUT, sizeof(ULONG), &timeout)) { + PIPE_TRANSFER_TIMEOUT, sizeof(ULONG), &timeout)) usbi_dbg("failed to set PIPE_TRANSFER_TIMEOUT for control endpoint %02X", endpoint_address); - } - if ((i == -1) || (sub_api == SUB_API_LIBUSB0)) { - continue; // Other policies don't apply to control endpoint or libusb0 - } + + if ((i == -1) || (sub_api == SUB_API_LIBUSB0)) + continue; // Other policies don't apply to control endpoint or libusb0 + policy = false; if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy)) { + SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy)) usbi_dbg("failed to disable SHORT_PACKET_TERMINATE for endpoint %02X", endpoint_address); - } + if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - IGNORE_SHORT_PACKETS, sizeof(UCHAR), &policy)) { + IGNORE_SHORT_PACKETS, sizeof(UCHAR), &policy)) usbi_dbg("failed to disable IGNORE_SHORT_PACKETS for endpoint %02X", endpoint_address); - } + policy = true; /* ALLOW_PARTIAL_READS must be enabled due to likely libusbK bug. See: https://sourceforge.net/mailarchive/message.php?msg_id=29736015 */ if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - ALLOW_PARTIAL_READS, sizeof(UCHAR), &policy)) { + ALLOW_PARTIAL_READS, sizeof(UCHAR), &policy)) usbi_dbg("failed to enable ALLOW_PARTIAL_READS for endpoint %02X", endpoint_address); - } + if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - AUTO_CLEAR_STALL, sizeof(UCHAR), &policy)) { + AUTO_CLEAR_STALL, sizeof(UCHAR), &policy)) usbi_dbg("failed to enable AUTO_CLEAR_STALL for endpoint %02X", endpoint_address); - } } return LIBUSB_SUCCESS; @@ -2381,15 +2463,15 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); struct windows_device_priv *priv = _device_priv(dev_handle->dev); bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE); - HANDLE file_handle, winusb_handle; - DWORD err; - int i; SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL; HDEVINFO dev_info = INVALID_HANDLE_VALUE; SP_DEVINFO_DATA dev_info_data; - char* dev_path_no_guid = NULL; + char *dev_path_no_guid = NULL; char filter_path[] = "\\\\.\\libusb0-0000"; bool found_filter = false; + HANDLE file_handle, winusb_handle; + DWORD err; + int i; CHECK_WINUSBX_AVAILABLE(sub_api); @@ -2398,9 +2480,8 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev if ((is_using_usbccgp) || (iface == 0)) { // composite device (independent interfaces) or interface 0 file_handle = handle_priv->interface_handle[iface].dev_handle; - if ((file_handle == 0) || (file_handle == INVALID_HANDLE_VALUE)) { + if (!HANDLE_VALID(file_handle)) return LIBUSB_ERROR_NOT_FOUND; - } if (!WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; @@ -2417,9 +2498,9 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev safe_free(dev_interface_details); safe_free(dev_path_no_guid); dev_interface_details = get_interface_details_filter(ctx, &dev_info, &dev_info_data, &GUID_DEVINTERFACE_LIBUSB0_FILTER, i, filter_path); - if ((found_filter) || (dev_interface_details == NULL)) { + if ((found_filter) || (dev_interface_details == NULL)) break; - } + // ignore GUID part dev_path_no_guid = sanitize_path(strtok(dev_interface_details->DevicePath, "{")); if (safe_strncmp(dev_path_no_guid, priv->usb_interface[iface].path, safe_strlen(dev_path_no_guid)) == 0) { @@ -2448,7 +2529,7 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev winusb_handle = handle_priv->interface_handle[0].api_handle; // It is a requirement for multiple interface devices on Windows that, to you // must first claim the first interface before you claim the others - if ((winusb_handle == 0) || (winusb_handle == INVALID_HANDLE_VALUE)) { + if (!HANDLE_VALID(winusb_handle)) { file_handle = handle_priv->interface_handle[0].dev_handle; if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { handle_priv->interface_handle[0].api_handle = winusb_handle; @@ -2458,7 +2539,7 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev return LIBUSB_ERROR_ACCESS; } } - if (!WinUSBX[sub_api].GetAssociatedInterface(winusb_handle, (UCHAR)(iface-1), + if (!WinUSBX[sub_api].GetAssociatedInterface(winusb_handle, (UCHAR)(iface - 1), &handle_priv->interface_handle[iface].api_handle)) { handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; switch(GetLastError()) { @@ -2489,9 +2570,8 @@ static int winusbx_release_interface(int sub_api, struct libusb_device_handle *d CHECK_WINUSBX_AVAILABLE(sub_api); winusb_handle = handle_priv->interface_handle[iface].api_handle; - if ((winusb_handle == 0) || (winusb_handle == INVALID_HANDLE_VALUE)) { + if (!HANDLE_VALID(winusb_handle)) return LIBUSB_ERROR_NOT_FOUND; - } WinUSBX[sub_api].Free(winusb_handle); handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; @@ -2513,15 +2593,13 @@ static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_ return -1; } - for (i=0; iinterface_handle[i].dev_handle != 0) - && (handle_priv->interface_handle[i].dev_handle != INVALID_HANDLE_VALUE) - && (handle_priv->interface_handle[i].api_handle != 0) - && (handle_priv->interface_handle[i].api_handle != INVALID_HANDLE_VALUE) - && (priv->usb_interface[i].apib->id == api_id) ) { + for (i = 0; i < USB_MAXINTERFACES; i++) { + if (HANDLE_VALID(handle_priv->interface_handle[i].dev_handle) + && HANDLE_VALID(handle_priv->interface_handle[i].api_handle) + && (priv->usb_interface[i].apib->id == api_id)) return i; - } } + return -1; } @@ -2532,19 +2610,18 @@ static int interface_by_endpoint(struct windows_device_priv *priv, struct windows_device_handle_priv *handle_priv, uint8_t endpoint_address) { int i, j; - for (i=0; iinterface_handle[i].api_handle == INVALID_HANDLE_VALUE) - continue; - if (handle_priv->interface_handle[i].api_handle == 0) + + for (i = 0; i < USB_MAXINTERFACES; i++) { + if (!HANDLE_VALID(handle_priv->interface_handle[i].api_handle)) continue; if (priv->usb_interface[i].endpoint == NULL) continue; - for (j=0; jusb_interface[i].nb_endpoints; j++) { - if (priv->usb_interface[i].endpoint[j] == endpoint_address) { + for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) { + if (priv->usb_interface[i].endpoint[j] == endpoint_address) return i; - } } } + return -1; } @@ -2553,10 +2630,9 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer); - struct windows_device_handle_priv *handle_priv = _device_handle_priv( - transfer->dev_handle); - WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *) transfer->buffer; + struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer; ULONG size; HANDLE winusb_handle; int current_interface; @@ -2572,9 +2648,8 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it current_interface = get_valid_interface(transfer->dev_handle, USB_API_WINUSBX); if (current_interface < 0) { - if (auto_claim(transfer, ¤t_interface, USB_API_WINUSBX) != LIBUSB_SUCCESS) { + if (auto_claim(transfer, ¤t_interface, USB_API_WINUSBX) != LIBUSB_SUCCESS) return LIBUSB_ERROR_NOT_FOUND; - } } usbi_dbg("will use interface %d", current_interface); @@ -2582,13 +2657,12 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it wfd = usbi_create_fd(winusb_handle, RW_READ, NULL, NULL); // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) { + if (wfd.fd < 0) return LIBUSB_ERROR_NO_MEM; - } // Sending of set configuration control requests from WinUSB creates issues - if ( ((setup->request_type & (0x03 << 5)) == LIBUSB_REQUEST_TYPE_STANDARD) - && (setup->request == LIBUSB_REQUEST_SET_CONFIGURATION) ) { + if (((setup->request_type & (0x03 << 5)) == LIBUSB_REQUEST_TYPE_STANDARD) + && (setup->request == LIBUSB_REQUEST_SET_CONFIGURATION)) { if (setup->value != priv->active_config) { usbi_warn(ctx, "cannot set configuration other than the default one"); usbi_free_fd(&wfd); @@ -2598,7 +2672,7 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it wfd.overlapped->InternalHigh = 0; } else { if (!WinUSBX[sub_api].ControlTransfer(wfd.handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, wfd.overlapped)) { - if(GetLastError() != ERROR_IO_PENDING) { + if (GetLastError() != ERROR_IO_PENDING) { usbi_warn(ctx, "ControlTransfer failed: %s", windows_error_str(0)); usbi_free_fd(&wfd); return LIBUSB_ERROR_IO; @@ -2625,12 +2699,11 @@ static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_ha CHECK_WINUSBX_AVAILABLE(sub_api); - if (altsetting > 255) { + if (altsetting > 255) return LIBUSB_ERROR_INVALID_PARAM; - } winusb_handle = handle_priv->interface_handle[iface].api_handle; - if ((winusb_handle == 0) || (winusb_handle == INVALID_HANDLE_VALUE)) { + if (!HANDLE_VALID(winusb_handle)) { usbi_err(ctx, "interface must be claimed first"); return LIBUSB_ERROR_NOT_FOUND; } @@ -2647,7 +2720,7 @@ static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itran { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer); + struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); HANDLE winusb_handle; @@ -2671,9 +2744,8 @@ static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itran wfd = usbi_create_fd(winusb_handle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL); // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) { + if (wfd.fd < 0) return LIBUSB_ERROR_NO_MEM; - } if (IS_XFERIN(transfer)) { usbi_dbg("reading %d bytes", transfer->length); @@ -2682,8 +2754,9 @@ static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itran usbi_dbg("writing %d bytes", transfer->length); ret = WinUSBX[sub_api].WritePipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped); } + if (!ret) { - if(GetLastError() != ERROR_IO_PENDING) { + if (GetLastError() != ERROR_IO_PENDING) { usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); usbi_free_fd(&wfd); return LIBUSB_ERROR_IO; @@ -2743,7 +2816,7 @@ static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer) struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer); + struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); HANDLE winusb_handle; int current_interface; @@ -2788,33 +2861,31 @@ static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_ha CHECK_WINUSBX_AVAILABLE(sub_api); // Reset any available pipe (except control) - for (i=0; iinterface_handle[i].api_handle; - for (wfd = handle_to_winfd(winusb_handle); wfd.fd > 0;) - { + for (wfd = handle_to_winfd(winusb_handle); wfd.fd > 0; ) { // Cancel any pollable I/O usbi_remove_pollfd(ctx, wfd.fd); usbi_free_fd(&wfd); wfd = handle_to_winfd(winusb_handle); } - if ( (winusb_handle != 0) && (winusb_handle != INVALID_HANDLE_VALUE)) { - for (j=0; jusb_interface[i].nb_endpoints; j++) { + if (HANDLE_VALID(winusb_handle)) { + for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) { usbi_dbg("resetting ep %02X", priv->usb_interface[i].endpoint[j]); - if (!WinUSBX[sub_api].AbortPipe(winusb_handle, priv->usb_interface[i].endpoint[j])) { + if (!WinUSBX[sub_api].AbortPipe(winusb_handle, priv->usb_interface[i].endpoint[j])) usbi_err(ctx, "AbortPipe (pipe address %02X) failed: %s", priv->usb_interface[i].endpoint[j], windows_error_str(0)); - } + // FlushPipe seems to fail on OUT pipes if (IS_EPIN(priv->usb_interface[i].endpoint[j]) - && (!WinUSBX[sub_api].FlushPipe(winusb_handle, priv->usb_interface[i].endpoint[j])) ) { + && (!WinUSBX[sub_api].FlushPipe(winusb_handle, priv->usb_interface[i].endpoint[j]))) usbi_err(ctx, "FlushPipe (pipe address %02X) failed: %s", priv->usb_interface[i].endpoint[j], windows_error_str(0)); - } - if (!WinUSBX[sub_api].ResetPipe(winusb_handle, priv->usb_interface[i].endpoint[j])) { + + if (!WinUSBX[sub_api].ResetPipe(winusb_handle, priv->usb_interface[i].endpoint[j])) usbi_err(ctx, "ResetPipe (pipe address %02X) failed: %s", priv->usb_interface[i].endpoint[j], windows_error_str(0)); - } } } } @@ -2822,10 +2893,10 @@ static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_ha // libusbK & libusb0 have the ability to issue an actual device reset if (WinUSBX[sub_api].ResetDevice != NULL) { winusb_handle = handle_priv->interface_handle[0].api_handle; - if ( (winusb_handle != 0) && (winusb_handle != INVALID_HANDLE_VALUE)) { + if (HANDLE_VALID(winusb_handle)) WinUSBX[sub_api].ResetDevice(winusb_handle); - } } + return LIBUSB_SUCCESS; } @@ -2840,19 +2911,20 @@ static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransf * Note that functions that complete data transfer synchronously must return * LIBUSB_COMPLETED instead of LIBUSB_SUCCESS */ -static int _hid_get_hid_descriptor(struct hid_device_priv* dev, void *data, size_t *size); -static int _hid_get_report_descriptor(struct hid_device_priv* dev, void *data, size_t *size); +static int _hid_get_hid_descriptor(struct hid_device_priv *dev, void *data, size_t *size); +static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, size_t *size); static int _hid_wcslen(WCHAR *str) { int i = 0; - while (str[i] && (str[i] != 0x409)) { + + while (str[i] && (str[i] != 0x409)) i++; - } + return i; } -static int _hid_get_device_descriptor(struct hid_device_priv* dev, void *data, size_t *size) +static int _hid_get_device_descriptor(struct hid_device_priv *dev, void *data, size_t *size) { struct libusb_device_descriptor d; @@ -2874,10 +2946,11 @@ static int _hid_get_device_descriptor(struct hid_device_priv* dev, void *data, s if (*size > LIBUSB_DT_DEVICE_SIZE) *size = LIBUSB_DT_DEVICE_SIZE; memcpy(data, &d, *size); + return LIBUSB_COMPLETED; } -static int _hid_get_config_descriptor(struct hid_device_priv* dev, void *data, size_t *size) +static int _hid_get_config_descriptor(struct hid_device_priv *dev, void *data, size_t *size) { char num_endpoints = 0; size_t config_total_len = 0; @@ -2896,7 +2969,6 @@ static int _hid_get_config_descriptor(struct hid_device_priv* dev, void *data, s config_total_len = LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE + LIBUSB_DT_HID_SIZE + num_endpoints * LIBUSB_DT_ENDPOINT_SIZE; - cd = (struct libusb_config_descriptor *)tmp; id = (struct libusb_interface_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE); hd = (struct libusb_hid_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE @@ -2907,7 +2979,7 @@ static int _hid_get_config_descriptor(struct hid_device_priv* dev, void *data, s cd->bLength = LIBUSB_DT_CONFIG_SIZE; cd->bDescriptorType = LIBUSB_DT_CONFIG; - cd->wTotalLength = (uint16_t) config_total_len; + cd->wTotalLength = (uint16_t)config_total_len; cd->bNumInterfaces = 1; cd->bConfigurationValue = 1; cd->iConfiguration = 0; @@ -2934,7 +3006,7 @@ static int _hid_get_config_descriptor(struct hid_device_priv* dev, void *data, s ed->bmAttributes = 3; ed->wMaxPacketSize = dev->input_report_size - 1; ed->bInterval = 10; - ed = (struct libusb_endpoint_descriptor *)((char*)ed + LIBUSB_DT_ENDPOINT_SIZE); + ed = (struct libusb_endpoint_descriptor *)((char *)ed + LIBUSB_DT_ENDPOINT_SIZE); } if (dev->output_report_size) { @@ -2949,57 +3021,54 @@ static int _hid_get_config_descriptor(struct hid_device_priv* dev, void *data, s if (*size > config_total_len) *size = config_total_len; memcpy(data, tmp, *size); + return LIBUSB_COMPLETED; } -static int _hid_get_string_descriptor(struct hid_device_priv* dev, int _index, - void *data, size_t *size) +static int _hid_get_string_descriptor(struct hid_device_priv *dev, int _index, + void *data, size_t *size) { void *tmp = NULL; size_t tmp_size = 0; int i; /* language ID, EN-US */ - char string_langid[] = { - 0x09, - 0x04 - }; + char string_langid[] = {0x09, 0x04}; - if ((*size < 2) || (*size > 255)) { + if ((*size < 2) || (*size > 255)) return LIBUSB_ERROR_OVERFLOW; - } if (_index == 0) { tmp = string_langid; - tmp_size = sizeof(string_langid)+2; + tmp_size = sizeof(string_langid) + 2; } else { - for (i=0; i<3; i++) { + for (i = 0; i < 3; i++) { if (_index == (dev->string_index[i])) { tmp = dev->string[i]; - tmp_size = (_hid_wcslen(dev->string[i])+1) * sizeof(WCHAR); + tmp_size = (_hid_wcslen(dev->string[i]) + 1) * sizeof(WCHAR); break; } } - if (i == 3) { // not found + + if (i == 3) // not found return LIBUSB_ERROR_INVALID_PARAM; - } } - if(!tmp_size) { + if (!tmp_size) return LIBUSB_ERROR_INVALID_PARAM; - } - if (tmp_size < *size) { + if (tmp_size < *size) *size = tmp_size; - } + // 2 byte header - ((uint8_t*)data)[0] = (uint8_t)*size; - ((uint8_t*)data)[1] = LIBUSB_DT_STRING; - memcpy((uint8_t*)data+2, tmp, *size-2); + ((uint8_t *)data)[0] = (uint8_t)*size; + ((uint8_t *)data)[1] = LIBUSB_DT_STRING; + memcpy((uint8_t *)data + 2, tmp, *size - 2); + return LIBUSB_COMPLETED; } -static int _hid_get_hid_descriptor(struct hid_device_priv* dev, void *data, size_t *size) +static int _hid_get_hid_descriptor(struct hid_device_priv *dev, void *data, size_t *size) { struct libusb_hid_descriptor d; uint8_t tmp[MAX_HID_DESCRIPTOR_SIZE]; @@ -3018,10 +3087,11 @@ static int _hid_get_hid_descriptor(struct hid_device_priv* dev, void *data, size if (*size > LIBUSB_DT_HID_SIZE) *size = LIBUSB_DT_HID_SIZE; memcpy(data, &d, *size); + return LIBUSB_COMPLETED; } -static int _hid_get_report_descriptor(struct hid_device_priv* dev, void *data, size_t *size) +static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, size_t *size) { uint8_t d[MAX_HID_DESCRIPTOR_SIZE]; size_t i = 0; @@ -3084,11 +3154,12 @@ static int _hid_get_report_descriptor(struct hid_device_priv* dev, void *data, s if (*size > i) *size = i; memcpy(data, d, *size); + return LIBUSB_COMPLETED; } -static int _hid_get_descriptor(struct hid_device_priv* dev, HANDLE hid_handle, int recipient, - int type, int _index, void *data, size_t *size) +static int _hid_get_descriptor(struct hid_device_priv *dev, HANDLE hid_handle, int recipient, + int type, int _index, void *data, size_t *size) { switch(type) { case LIBUSB_DT_DEVICE: @@ -3118,21 +3189,20 @@ static int _hid_get_descriptor(struct hid_device_priv* dev, HANDLE hid_handle, i return LIBUSB_COMPLETED; return LIBUSB_ERROR_OTHER; } + usbi_dbg("unsupported"); return LIBUSB_ERROR_NOT_SUPPORTED; } -static int _hid_get_report(struct hid_device_priv* dev, HANDLE hid_handle, int id, void *data, - struct windows_transfer_priv *tp, size_t *size, OVERLAPPED* overlapped, - int report_type) +static int _hid_get_report(struct hid_device_priv *dev, HANDLE hid_handle, int id, void *data, + struct windows_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type) { uint8_t *buf; DWORD ioctl_code, read_size, expected_size = (DWORD)*size; int r = LIBUSB_SUCCESS; - if (tp->hid_buffer != NULL) { + if (tp->hid_buffer != NULL) usbi_dbg("program assertion failed: hid_buffer is not NULL"); - } if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) { usbi_dbg("invalid size (%u)", *size); @@ -3140,31 +3210,31 @@ static int _hid_get_report(struct hid_device_priv* dev, HANDLE hid_handle, int i } switch (report_type) { - case HID_REPORT_TYPE_INPUT: - ioctl_code = IOCTL_HID_GET_INPUT_REPORT; - break; - case HID_REPORT_TYPE_FEATURE: - ioctl_code = IOCTL_HID_GET_FEATURE; - break; - default: - usbi_dbg("unknown HID report type %d", report_type); - return LIBUSB_ERROR_INVALID_PARAM; + case HID_REPORT_TYPE_INPUT: + ioctl_code = IOCTL_HID_GET_INPUT_REPORT; + break; + case HID_REPORT_TYPE_FEATURE: + ioctl_code = IOCTL_HID_GET_FEATURE; + break; + default: + usbi_dbg("unknown HID report type %d", report_type); + return LIBUSB_ERROR_INVALID_PARAM; } // Add a trailing byte to detect overflows - buf = (uint8_t*)calloc(expected_size+1, 1); - if (buf == NULL) { + buf = calloc(1, expected_size + 1); + if (buf == NULL) return LIBUSB_ERROR_NO_MEM; - } - buf[0] = (uint8_t)id; // Must be set always + + buf[0] = (uint8_t)id; // Must be set always usbi_dbg("report ID: 0x%02X", buf[0]); tp->hid_expected_size = expected_size; read_size = expected_size; // NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0) - if (!DeviceIoControl(hid_handle, ioctl_code, buf, expected_size+1, - buf, expected_size+1, &read_size, overlapped)) { + if (!DeviceIoControl(hid_handle, ioctl_code, buf, expected_size + 1, + buf, expected_size + 1, &read_size, overlapped)) { if (GetLastError() != ERROR_IO_PENDING) { usbi_dbg("Failed to Read HID Report: %s", windows_error_str(0)); safe_free(buf); @@ -3172,7 +3242,7 @@ static int _hid_get_report(struct hid_device_priv* dev, HANDLE hid_handle, int i } // Asynchronous wait tp->hid_buffer = buf; - tp->hid_dest = (uint8_t*)data; // copy dest, as not necessarily the start of the transfer buffer + tp->hid_dest = data; // copy dest, as not necessarily the start of the transfer buffer return LIBUSB_SUCCESS; } @@ -3181,9 +3251,9 @@ static int _hid_get_report(struct hid_device_priv* dev, HANDLE hid_handle, int i usbi_warn(NULL, "program assertion failed - read completed synchronously, but no data was read"); *size = 0; } else { - if (buf[0] != id) { + if (buf[0] != id) usbi_warn(NULL, "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id); - } + if ((size_t)read_size > expected_size) { r = LIBUSB_ERROR_OVERFLOW; usbi_dbg("OVERFLOW!"); @@ -3192,27 +3262,24 @@ static int _hid_get_report(struct hid_device_priv* dev, HANDLE hid_handle, int i } *size = MIN((size_t)read_size, *size); - if (id == 0) { - // Discard report ID - memcpy(data, buf+1, *size); - } else { + if (id == 0) + memcpy(data, buf + 1, *size); // Discard report ID + else memcpy(data, buf, *size); - } } + safe_free(buf); return r; } -static int _hid_set_report(struct hid_device_priv* dev, HANDLE hid_handle, int id, void *data, - struct windows_transfer_priv *tp, size_t *size, OVERLAPPED* overlapped, - int report_type) +static int _hid_set_report(struct hid_device_priv *dev, HANDLE hid_handle, int id, void *data, + struct windows_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type) { uint8_t *buf = NULL; - DWORD ioctl_code, write_size= (DWORD)*size; + DWORD ioctl_code, write_size = (DWORD)*size; - if (tp->hid_buffer != NULL) { + if (tp->hid_buffer != NULL) usbi_dbg("program assertion failed: hid_buffer is not NULL"); - } if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) { usbi_dbg("invalid size (%u)", *size); @@ -3220,27 +3287,27 @@ static int _hid_set_report(struct hid_device_priv* dev, HANDLE hid_handle, int i } switch (report_type) { - case HID_REPORT_TYPE_OUTPUT: - ioctl_code = IOCTL_HID_SET_OUTPUT_REPORT; - break; - case HID_REPORT_TYPE_FEATURE: - ioctl_code = IOCTL_HID_SET_FEATURE; - break; - default: - usbi_dbg("unknown HID report type %d", report_type); - return LIBUSB_ERROR_INVALID_PARAM; + case HID_REPORT_TYPE_OUTPUT: + ioctl_code = IOCTL_HID_SET_OUTPUT_REPORT; + break; + case HID_REPORT_TYPE_FEATURE: + ioctl_code = IOCTL_HID_SET_FEATURE; + break; + default: + usbi_dbg("unknown HID report type %d", report_type); + return LIBUSB_ERROR_INVALID_PARAM; } usbi_dbg("report ID: 0x%02X", id); // When report IDs are not used (i.e. when id == 0), we must add // a null report ID. Otherwise, we just use original data buffer - if (id == 0) { + if (id == 0) write_size++; - } - buf = (uint8_t*) malloc(write_size); - if (buf == NULL) { + + buf = malloc(write_size); + if (buf == NULL) return LIBUSB_ERROR_NO_MEM; - } + if (id == 0) { buf[0] = 0; memcpy(buf + 1, data, *size); @@ -3248,9 +3315,8 @@ static int _hid_set_report(struct hid_device_priv* dev, HANDLE hid_handle, int i // This seems like a waste, but if we don't duplicate the // data, we'll get issues when freeing hid_buffer memcpy(buf, data, *size); - if (buf[0] != id) { + if (buf[0] != id) usbi_warn(NULL, "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id); - } } // NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0) @@ -3268,22 +3334,22 @@ static int _hid_set_report(struct hid_device_priv* dev, HANDLE hid_handle, int i // Transfer completed synchronously *size = write_size; - if (write_size == 0) { + if (write_size == 0) usbi_dbg("program assertion failed - write completed synchronously, but no data was written"); - } + safe_free(buf); return LIBUSB_COMPLETED; } -static int _hid_class_request(struct hid_device_priv* dev, HANDLE hid_handle, int request_type, - int request, int value, int _index, void *data, struct windows_transfer_priv *tp, - size_t *size, OVERLAPPED* overlapped) +static int _hid_class_request(struct hid_device_priv *dev, HANDLE hid_handle, int request_type, + int request, int value, int _index, void *data, struct windows_transfer_priv *tp, + size_t *size, OVERLAPPED *overlapped) { int report_type = (value >> 8) & 0xFF; int report_id = value & 0xFF; - if ( (LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_INTERFACE) - && (LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_DEVICE) ) + if ((LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_INTERFACE) + && (LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_DEVICE)) return LIBUSB_ERROR_INVALID_PARAM; if (LIBUSB_REQ_OUT(request_type) && request == HID_REQ_SET_REPORT) @@ -3335,28 +3401,27 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); struct windows_device_priv *priv = _device_priv(dev_handle->dev); struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - HIDD_ATTRIBUTES hid_attributes; PHIDP_PREPARSED_DATA preparsed_data = NULL; HIDP_CAPS capabilities; HIDP_VALUE_CAPS *value_caps; - HANDLE hid_handle = INVALID_HANDLE_VALUE; int i, j; // report IDs handling ULONG size[3]; - const char* type[3] = {"input", "output", "feature"}; - int nb_ids[2]; // zero and nonzero report IDs + const char *type[3] = {"input", "output", "feature"}; + int nb_ids[2]; // zero and nonzero report IDs CHECK_HID_AVAILABLE; + if (priv->hid == NULL) { usbi_err(ctx, "program assertion failed - private HID structure is unitialized"); return LIBUSB_ERROR_NOT_FOUND; } for (i = 0; i < USB_MAXINTERFACES; i++) { - if ( (priv->usb_interface[i].path != NULL) - && (priv->usb_interface[i].apib->id == USB_API_HID) ) { + if ((priv->usb_interface[i].path != NULL) + && (priv->usb_interface[i].apib->id == USB_API_HID)) { hid_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); /* @@ -3373,7 +3438,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) if (hid_handle == INVALID_HANDLE_VALUE) { usbi_err(ctx, "could not open device %s (interface %d): %s", priv->path, i, windows_error_str(0)); switch(GetLastError()) { - case ERROR_FILE_NOT_FOUND: // The device was disconnected + case ERROR_FILE_NOT_FOUND: // The device was disconnected return LIBUSB_ERROR_NO_DEVICE; case ERROR_ACCESS_DENIED: return LIBUSB_ERROR_ACCESS; @@ -3398,8 +3463,8 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) priv->hid->pid = hid_attributes.ProductID; // Set the maximum available input buffer size - for (i=32; HidD_SetNumInputBuffers(hid_handle, i); i*=2); - usbi_dbg("set maximum input buffer size to %d", i/2); + for (i = 32; HidD_SetNumInputBuffers(hid_handle, i); i *= 2); + usbi_dbg("set maximum input buffer size to %d", i / 2); // Get the maximum input and output report size if (!HidD_GetPreparsedData(hid_handle, &preparsed_data) || !preparsed_data) { @@ -3415,29 +3480,27 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) size[0] = capabilities.NumberInputValueCaps; size[1] = capabilities.NumberOutputValueCaps; size[2] = capabilities.NumberFeatureValueCaps; - for (j=HidP_Input; j<=HidP_Feature; j++) { + for (j = HidP_Input; j <= HidP_Feature; j++) { usbi_dbg("%u HID %s report value(s) found", (unsigned int)size[j], type[j]); priv->hid->uses_report_ids[j] = false; if (size[j] > 0) { - value_caps = (HIDP_VALUE_CAPS*) calloc(size[j], sizeof(HIDP_VALUE_CAPS)); - if ( (value_caps != NULL) - && (HidP_GetValueCaps((HIDP_REPORT_TYPE)j, value_caps, &size[j], preparsed_data) == HIDP_STATUS_SUCCESS) - && (size[j] >= 1) ) { + value_caps = calloc(size[j], sizeof(HIDP_VALUE_CAPS)); + if ((value_caps != NULL) + && (HidP_GetValueCaps((HIDP_REPORT_TYPE)j, value_caps, &size[j], preparsed_data) == HIDP_STATUS_SUCCESS) + && (size[j] >= 1)) { nb_ids[0] = 0; nb_ids[1] = 0; - for (i=0; i<(int)size[j]; i++) { + for (i = 0; i < (int)size[j]; i++) { usbi_dbg(" Report ID: 0x%02X", value_caps[i].ReportID); - if (value_caps[i].ReportID != 0) { + if (value_caps[i].ReportID != 0) nb_ids[1]++; - } else { + else nb_ids[0]++; - } } if (nb_ids[1] != 0) { - if (nb_ids[0] != 0) { + if (nb_ids[0] != 0) usbi_warn(ctx, "program assertion failed: zero and nonzero report IDs used for %s", type[j]); - } priv->hid->uses_report_ids[j] = true; } } else { @@ -3454,31 +3517,26 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) // Fetch string descriptors priv->hid->string_index[0] = priv->dev_descriptor.iManufacturer; - if (priv->hid->string_index[0] != 0) { - HidD_GetManufacturerString(hid_handle, priv->hid->string[0], - sizeof(priv->hid->string[0])); - } else { + if (priv->hid->string_index[0] != 0) + HidD_GetManufacturerString(hid_handle, priv->hid->string[0], sizeof(priv->hid->string[0])); + else priv->hid->string[0][0] = 0; - } + priv->hid->string_index[1] = priv->dev_descriptor.iProduct; - if (priv->hid->string_index[1] != 0) { - HidD_GetProductString(hid_handle, priv->hid->string[1], - sizeof(priv->hid->string[1])); - } else { + if (priv->hid->string_index[1] != 0) + HidD_GetProductString(hid_handle, priv->hid->string[1], sizeof(priv->hid->string[1])); + else priv->hid->string[1][0] = 0; - } + priv->hid->string_index[2] = priv->dev_descriptor.iSerialNumber; - if (priv->hid->string_index[2] != 0) { - HidD_GetSerialNumberString(hid_handle, priv->hid->string[2], - sizeof(priv->hid->string[2])); - } else { + if (priv->hid->string_index[2] != 0) + HidD_GetSerialNumberString(hid_handle, priv->hid->string[2], sizeof(priv->hid->string[2])); + else priv->hid->string[2][0] = 0; - } } while(0); - if (preparsed_data) { + if (preparsed_data) HidD_FreePreparsedData(preparsed_data); - } return LIBUSB_SUCCESS; } @@ -3496,9 +3554,8 @@ static void hid_close(int sub_api, struct libusb_device_handle *dev_handle) for (i = 0; i < USB_MAXINTERFACES; i++) { if (priv->usb_interface[i].apib->id == USB_API_HID) { file_handle = handle_priv->interface_handle[i].api_handle; - if ( (file_handle != 0) && (file_handle != INVALID_HANDLE_VALUE)) { + if (HANDLE_VALID(file_handle)) CloseHandle(file_handle); - } } } } @@ -3511,14 +3568,13 @@ static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_han CHECK_HID_AVAILABLE; // NB: Disconnection detection is not possible in this function - if (priv->usb_interface[iface].path == NULL) { - return LIBUSB_ERROR_NOT_FOUND; // invalid iface - } + if (priv->usb_interface[iface].path == NULL) + return LIBUSB_ERROR_NOT_FOUND; // invalid iface // We use dev_handle as a flag for interface claimed - if (handle_priv->interface_handle[iface].dev_handle == INTERFACE_CLAIMED) { - return LIBUSB_ERROR_BUSY; // already claimed - } + if (handle_priv->interface_handle[iface].dev_handle == INTERFACE_CLAIMED) + return LIBUSB_ERROR_BUSY; // already claimed + handle_priv->interface_handle[iface].dev_handle = INTERFACE_CLAIMED; @@ -3535,13 +3591,11 @@ static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_h CHECK_HID_AVAILABLE; - if (priv->usb_interface[iface].path == NULL) { - return LIBUSB_ERROR_NOT_FOUND; // invalid iface - } + if (priv->usb_interface[iface].path == NULL) + return LIBUSB_ERROR_NOT_FOUND; // invalid iface - if (handle_priv->interface_handle[iface].dev_handle != INTERFACE_CLAIMED) { - return LIBUSB_ERROR_NOT_FOUND; // invalid iface - } + if (handle_priv->interface_handle[iface].dev_handle != INTERFACE_CLAIMED) + return LIBUSB_ERROR_NOT_FOUND; // invalid iface handle_priv->interface_handle[iface].dev_handle = INVALID_HANDLE_VALUE; @@ -3554,9 +3608,8 @@ static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle CHECK_HID_AVAILABLE; - if (altsetting > 255) { + if (altsetting > 255) return LIBUSB_ERROR_INVALID_PARAM; - } if (altsetting != 0) { usbi_err(ctx, "set interface altsetting not supported for altsetting >0"); @@ -3569,11 +3622,11 @@ static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer); + struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *) transfer->buffer; + WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer; HANDLE hid_handle; struct winfd wfd; int current_interface, config; @@ -3587,24 +3640,21 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans transfer_priv->hid_dest = NULL; size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; - if (size > MAX_CTRL_BUFFER_LENGTH) { + if (size > MAX_CTRL_BUFFER_LENGTH) return LIBUSB_ERROR_INVALID_PARAM; - } current_interface = get_valid_interface(transfer->dev_handle, USB_API_HID); if (current_interface < 0) { - if (auto_claim(transfer, ¤t_interface, USB_API_HID) != LIBUSB_SUCCESS) { + if (auto_claim(transfer, ¤t_interface, USB_API_HID) != LIBUSB_SUCCESS) return LIBUSB_ERROR_NOT_FOUND; - } } usbi_dbg("will use interface %d", current_interface); hid_handle = handle_priv->interface_handle[current_interface].api_handle; // Always use the handle returned from usbi_create_fd (wfd.handle) wfd = usbi_create_fd(hid_handle, RW_READ, NULL, NULL); - if (wfd.fd < 0) { + if (wfd.fd < 0) return LIBUSB_ERROR_NOT_FOUND; - } switch(LIBUSB_REQ_TYPE(setup->request_type)) { case LIBUSB_REQUEST_TYPE_STANDARD: @@ -3617,7 +3667,7 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans r = windows_get_configuration(transfer->dev_handle, &config); if (r == LIBUSB_SUCCESS) { size = 1; - ((uint8_t*)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = (uint8_t)config; + ((uint8_t *)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = (uint8_t)config; r = LIBUSB_COMPLETED; } break; @@ -3631,14 +3681,13 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans break; case LIBUSB_REQUEST_GET_INTERFACE: size = 1; - ((uint8_t*)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = 0; + ((uint8_t *)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = 0; r = LIBUSB_COMPLETED; break; case LIBUSB_REQUEST_SET_INTERFACE: r = hid_set_interface_altsetting(0, transfer->dev_handle, setup->index, setup->value); - if (r == LIBUSB_SUCCESS) { + if (r == LIBUSB_SUCCESS) r = LIBUSB_COMPLETED; - } break; default: usbi_warn(ctx, "unsupported HID control request"); @@ -3647,7 +3696,7 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans } break; case LIBUSB_REQUEST_TYPE_CLASS: - r =_hid_class_request(priv->hid, wfd.handle, setup->request_type, setup->request, setup->value, + r = _hid_class_request(priv->hid, wfd.handle, setup->request_type, setup->request, setup->value, setup->index, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, transfer_priv, &size, wfd.overlapped); break; @@ -3677,9 +3726,10 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans return r; } -static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) { +static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) +{ struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer); + struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); @@ -3709,38 +3759,38 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer wfd = usbi_create_fd(hid_handle, direction_in?RW_READ:RW_WRITE, NULL, NULL); // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) { + if (wfd.fd < 0) return LIBUSB_ERROR_NO_MEM; - } // If report IDs are not in use, an extra prefix byte must be added - if ( ((direction_in) && (!priv->hid->uses_report_ids[0])) - || ((!direction_in) && (!priv->hid->uses_report_ids[1])) ) { - length = transfer->length+1; - } else { + if (((direction_in) && (!priv->hid->uses_report_ids[0])) + || ((!direction_in) && (!priv->hid->uses_report_ids[1]))) + length = transfer->length + 1; + else length = transfer->length; - } + // Add a trailing byte to detect overflows on input - transfer_priv->hid_buffer = (uint8_t*)calloc(length+1, 1); - if (transfer_priv->hid_buffer == NULL) { + transfer_priv->hid_buffer = calloc(1, length + 1); + if (transfer_priv->hid_buffer == NULL) return LIBUSB_ERROR_NO_MEM; - } + transfer_priv->hid_expected_size = length; if (direction_in) { transfer_priv->hid_dest = transfer->buffer; usbi_dbg("reading %d bytes (report ID: 0x00)", length); - ret = ReadFile(wfd.handle, transfer_priv->hid_buffer, length+1, &size, wfd.overlapped); + ret = ReadFile(wfd.handle, transfer_priv->hid_buffer, length + 1, &size, wfd.overlapped); } else { - if (!priv->hid->uses_report_ids[1]) { - memcpy(transfer_priv->hid_buffer+1, transfer->buffer, transfer->length); - } else { + if (!priv->hid->uses_report_ids[1]) + memcpy(transfer_priv->hid_buffer + 1, transfer->buffer, transfer->length); + else // We could actually do without the calloc and memcpy in this case memcpy(transfer_priv->hid_buffer, transfer->buffer, transfer->length); - } + usbi_dbg("writing %d bytes (report ID: 0x%02X)", length, transfer_priv->hid_buffer[0]); ret = WriteFile(wfd.handle, transfer_priv->hid_buffer, length, &size, wfd.overlapped); } + if (!ret) { if (GetLastError() != ERROR_IO_PENDING) { usbi_err(ctx, "HID transfer failed: %s", windows_error_str(0)); @@ -3751,9 +3801,9 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer } else { // Only write operations that completed synchronously need to free up // hid_buffer. For reads, copy_transfer_data() handles that process. - if (!direction_in) { + if (!direction_in) safe_free(transfer_priv->hid_buffer); - } + if (size == 0) { usbi_err(ctx, "program assertion failed - no data was transferred"); size = 1; @@ -3775,7 +3825,7 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer); + struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); HANDLE hid_handle; int current_interface; @@ -3800,10 +3850,10 @@ static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle // Flushing the queues on all interfaces is the best we can achieve for (current_interface = 0; current_interface < USB_MAXINTERFACES; current_interface++) { hid_handle = handle_priv->interface_handle[current_interface].api_handle; - if ((hid_handle != 0) && (hid_handle != INVALID_HANDLE_VALUE)) { + if (HANDLE_VALID(hid_handle)) HidD_FlushQueue(hid_handle); - } } + return LIBUSB_SUCCESS; } @@ -3838,7 +3888,8 @@ static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, } // This extra function is only needed for HID -static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) { +static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) +{ struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); @@ -3847,7 +3898,7 @@ static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, if (transfer_priv->hid_buffer != NULL) { // If we have a valid hid_buffer, it means the transfer was async - if (transfer_priv->hid_dest != NULL) { // Data readout + if (transfer_priv->hid_dest != NULL) { // Data readout if (corrected_size > 0) { // First, check for overflow if (corrected_size > transfer_priv->hid_expected_size) { @@ -3859,7 +3910,7 @@ static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, if (transfer_priv->hid_buffer[0] == 0) { // Discard the 1 byte report ID prefix corrected_size--; - memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer+1, corrected_size); + memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer + 1, corrected_size); } else { memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer, corrected_size); } @@ -3869,6 +3920,7 @@ static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, // For write, we just need to free the hid buffer safe_free(transfer_priv->hid_buffer); } + itransfer->transferred += corrected_size; return r; } @@ -3892,10 +3944,10 @@ static int composite_open(int sub_api, struct libusb_device_handle *dev_handle) struct windows_device_priv *priv = _device_priv(dev_handle->dev); int r = LIBUSB_ERROR_NOT_FOUND; uint8_t i; - // SUB_API_MAX+1 as the SUB_API_MAX pos is used to indicate availability of HID - bool available[SUB_API_MAX+1] = {0}; + // SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID + bool available[SUB_API_MAX + 1] = { 0 }; - for (i=0; iusb_interface[i].apib->id) { case USB_API_WINUSBX: if (priv->usb_interface[i].sub_api != SUB_API_NOTSET) @@ -3909,17 +3961,17 @@ static int composite_open(int sub_api, struct libusb_device_handle *dev_handle) } } - for (i=0; idev); uint8_t i; - // SUB_API_MAX+1 as the SUB_API_MAX pos is used to indicate availability of HID - bool available[SUB_API_MAX+1] = {0}; + // SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID + bool available[SUB_API_MAX + 1] = { 0 }; - for (i=0; iusb_interface[i].apib->id) { case USB_API_WINUSBX: if (priv->usb_interface[i].sub_api != SUB_API_NOTSET) @@ -3944,19 +3996,19 @@ static void composite_close(int sub_api, struct libusb_device_handle *dev_handle } } - for (i=0; idev); + return priv->usb_interface[iface].apib-> claim_interface(priv->usb_interface[iface].sub_api, dev_handle, iface); } @@ -3964,6 +4016,7 @@ static int composite_claim_interface(int sub_api, struct libusb_device_handle *d static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) { struct windows_device_priv *priv = _device_priv(dev_handle->dev); + return priv->usb_interface[iface].apib-> set_interface_altsetting(priv->usb_interface[iface].sub_api, dev_handle, iface, altsetting); } @@ -3971,6 +4024,7 @@ static int composite_set_interface_altsetting(int sub_api, struct libusb_device_ static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) { struct windows_device_priv *priv = _device_priv(dev_handle->dev); + return priv->usb_interface[iface].apib-> release_interface(priv->usb_interface[iface].sub_api, dev_handle, iface); } @@ -3981,7 +4035,7 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer * struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); struct libusb_config_descriptor *conf_desc; - WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *) transfer->buffer; + WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer; int iface, pass, r; // Interface shouldn't matter for control, but it does in practice, with Windows' @@ -3992,7 +4046,7 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer * iface = setup->index & 0xFF; break; case LIBUSB_RECIPIENT_ENDPOINT: - r = libusb_get_config_descriptor(transfer->dev_handle->dev, (uint8_t)(priv->active_config-1), &conf_desc); + r = libusb_get_config_descriptor(transfer->dev_handle->dev, (uint8_t)(priv->active_config - 1), &conf_desc); if (r == LIBUSB_SUCCESS) { iface = get_interface_by_endpoint(conf_desc, (setup->index & 0xFF)); libusb_free_config_descriptor(conf_desc); @@ -4009,9 +4063,8 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer * usbi_dbg("attempting control transfer targeted to interface %d", iface); if (priv->usb_interface[iface].path != NULL) { r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer); - if (r == LIBUSB_SUCCESS) { + if (r == LIBUSB_SUCCESS) return r; - } } } @@ -4027,9 +4080,8 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer * usbi_dbg("using interface %d", iface); r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer); // If not supported on this API, it may be supported on another, so don't give up yet!! - if (r == LIBUSB_ERROR_NOT_SUPPORTED) { + if (r == LIBUSB_ERROR_NOT_SUPPORTED) continue; - } return r; } } @@ -4053,7 +4105,8 @@ static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itr } return priv->usb_interface[current_interface].apib-> - submit_bulk_transfer(priv->usb_interface[current_interface].sub_api, itransfer);} + submit_bulk_transfer(priv->usb_interface[current_interface].sub_api, itransfer); +} static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); @@ -4069,7 +4122,8 @@ static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itra } return priv->usb_interface[current_interface].apib-> - submit_iso_transfer(priv->usb_interface[current_interface].sub_api, itransfer);} + submit_iso_transfer(priv->usb_interface[current_interface].sub_api, itransfer); +} static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) { @@ -4085,7 +4139,8 @@ static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_ha } return priv->usb_interface[current_interface].apib-> - clear_halt(priv->usb_interface[current_interface].sub_api, dev_handle, endpoint);} + clear_halt(priv->usb_interface[current_interface].sub_api, dev_handle, endpoint); +} static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer) { @@ -4094,7 +4149,8 @@ static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer) struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); return priv->usb_interface[transfer_priv->interface_number].apib-> - abort_control(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer);} + abort_control(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer); +} static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer) { @@ -4103,7 +4159,8 @@ static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfe struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); return priv->usb_interface[transfer_priv->interface_number].apib-> - abort_transfers(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer);} + abort_transfers(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer); +} static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle) { @@ -4111,23 +4168,24 @@ static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_ int r; uint8_t i; bool available[SUB_API_MAX]; - for (i = 0; iusb_interface[i].apib->id == USB_API_WINUSBX) - && (priv->usb_interface[i].sub_api != SUB_API_NOTSET) ) { + + for (i = 0; i < USB_MAXINTERFACES; i++) { + if ((priv->usb_interface[i].apib->id == USB_API_WINUSBX) + && (priv->usb_interface[i].sub_api != SUB_API_NOTSET)) available[priv->usb_interface[i].sub_api] = true; - } } - for (i=0; ios_priv; } -static inline void windows_device_priv_init(libusb_device* dev) { - struct windows_device_priv* p = _device_priv(dev); +static inline void windows_device_priv_init(struct libusb_device *dev) +{ + struct windows_device_priv *p = _device_priv(dev); int i; + p->depth = 0; p->port = 0; p->parent_dev = NULL; @@ -247,8 +251,8 @@ static inline void windows_device_priv_init(libusb_device* dev) { p->hid = NULL; p->active_config = 0; p->config_descriptor = NULL; - memset(&(p->dev_descriptor), 0, sizeof(USB_DEVICE_DESCRIPTOR)); - for (i=0; idev_descriptor, 0, sizeof(USB_DEVICE_DESCRIPTOR)); + for (i = 0; i < USB_MAXINTERFACES; i++) { p->usb_interface[i].path = NULL; p->usb_interface[i].apib = &usb_api_backend[USB_API_UNSUPPORTED]; p->usb_interface[i].sub_api = SUB_API_NOTSET; @@ -258,17 +262,19 @@ static inline void windows_device_priv_init(libusb_device* dev) { } } -static inline void windows_device_priv_release(libusb_device* dev) { - struct windows_device_priv* p = _device_priv(dev); +static inline void windows_device_priv_release(struct libusb_device *dev) +{ + struct windows_device_priv *p = _device_priv(dev); int i; + safe_free(p->path); if ((dev->num_configurations > 0) && (p->config_descriptor != NULL)) { - for (i=0; i < dev->num_configurations; i++) + for (i = 0; i < dev->num_configurations; i++) safe_free(p->config_descriptor[i]); } safe_free(p->config_descriptor); safe_free(p->hid); - for (i=0; iusb_interface[i].path); safe_free(p->usb_interface[i].endpoint); } @@ -288,7 +294,7 @@ struct windows_device_handle_priv { static inline struct windows_device_handle_priv *_device_handle_priv( struct libusb_device_handle *handle) { - return (struct windows_device_handle_priv *) handle->os_priv; + return (struct windows_device_handle_priv *)handle->os_priv; } // used for async polling functions @@ -302,9 +308,9 @@ struct windows_transfer_priv { // used to match a device driver (including filter drivers) against a supported API struct driver_lookup { - char list[MAX_KEY_LENGTH+1];// REG_MULTI_SZ list of services (driver) names - const DWORD reg_prop; // SPDRP registry key to use to retrieve list - const char* designation; // internal designation (for debug output) + char list[MAX_KEY_LENGTH + 1]; // REG_MULTI_SZ list of services (driver) names + const DWORD reg_prop; // SPDRP registry key to use to retrieve list + const char* designation; // internal designation (for debug output) }; /* OLE32 dependency */ @@ -336,57 +342,57 @@ typedef DEVNODE *PDEVNODE, *PDEVINST; typedef DWORD RETURN_TYPE; typedef RETURN_TYPE CONFIGRET; -#define CR_SUCCESS 0x00000000 -#define CR_NO_SUCH_DEVNODE 0x0000000D - -#define USB_DEVICE_DESCRIPTOR_TYPE LIBUSB_DT_DEVICE -#define USB_CONFIGURATION_DESCRIPTOR_TYPE LIBUSB_DT_CONFIG -#define USB_STRING_DESCRIPTOR_TYPE LIBUSB_DT_STRING -#define USB_INTERFACE_DESCRIPTOR_TYPE LIBUSB_DT_INTERFACE -#define USB_ENDPOINT_DESCRIPTOR_TYPE LIBUSB_DT_ENDPOINT - -#define USB_REQUEST_GET_STATUS LIBUSB_REQUEST_GET_STATUS -#define USB_REQUEST_CLEAR_FEATURE LIBUSB_REQUEST_CLEAR_FEATURE -#define USB_REQUEST_SET_FEATURE LIBUSB_REQUEST_SET_FEATURE -#define USB_REQUEST_SET_ADDRESS LIBUSB_REQUEST_SET_ADDRESS -#define USB_REQUEST_GET_DESCRIPTOR LIBUSB_REQUEST_GET_DESCRIPTOR -#define USB_REQUEST_SET_DESCRIPTOR LIBUSB_REQUEST_SET_DESCRIPTOR -#define USB_REQUEST_GET_CONFIGURATION LIBUSB_REQUEST_GET_CONFIGURATION -#define USB_REQUEST_SET_CONFIGURATION LIBUSB_REQUEST_SET_CONFIGURATION -#define USB_REQUEST_GET_INTERFACE LIBUSB_REQUEST_GET_INTERFACE -#define USB_REQUEST_SET_INTERFACE LIBUSB_REQUEST_SET_INTERFACE -#define USB_REQUEST_SYNC_FRAME LIBUSB_REQUEST_SYNCH_FRAME - -#define USB_GET_NODE_INFORMATION 258 -#define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 260 -#define USB_GET_NODE_CONNECTION_NAME 261 -#define USB_GET_HUB_CAPABILITIES 271 +#define CR_SUCCESS 0x00000000 +#define CR_NO_SUCH_DEVNODE 0x0000000D + +#define USB_DEVICE_DESCRIPTOR_TYPE LIBUSB_DT_DEVICE +#define USB_CONFIGURATION_DESCRIPTOR_TYPE LIBUSB_DT_CONFIG +#define USB_STRING_DESCRIPTOR_TYPE LIBUSB_DT_STRING +#define USB_INTERFACE_DESCRIPTOR_TYPE LIBUSB_DT_INTERFACE +#define USB_ENDPOINT_DESCRIPTOR_TYPE LIBUSB_DT_ENDPOINT + +#define USB_REQUEST_GET_STATUS LIBUSB_REQUEST_GET_STATUS +#define USB_REQUEST_CLEAR_FEATURE LIBUSB_REQUEST_CLEAR_FEATURE +#define USB_REQUEST_SET_FEATURE LIBUSB_REQUEST_SET_FEATURE +#define USB_REQUEST_SET_ADDRESS LIBUSB_REQUEST_SET_ADDRESS +#define USB_REQUEST_GET_DESCRIPTOR LIBUSB_REQUEST_GET_DESCRIPTOR +#define USB_REQUEST_SET_DESCRIPTOR LIBUSB_REQUEST_SET_DESCRIPTOR +#define USB_REQUEST_GET_CONFIGURATION LIBUSB_REQUEST_GET_CONFIGURATION +#define USB_REQUEST_SET_CONFIGURATION LIBUSB_REQUEST_SET_CONFIGURATION +#define USB_REQUEST_GET_INTERFACE LIBUSB_REQUEST_GET_INTERFACE +#define USB_REQUEST_SET_INTERFACE LIBUSB_REQUEST_SET_INTERFACE +#define USB_REQUEST_SYNC_FRAME LIBUSB_REQUEST_SYNCH_FRAME + +#define USB_GET_NODE_INFORMATION 258 +#define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 260 +#define USB_GET_NODE_CONNECTION_NAME 261 +#define USB_GET_HUB_CAPABILITIES 271 #if !defined(USB_GET_NODE_CONNECTION_INFORMATION_EX) -#define USB_GET_NODE_CONNECTION_INFORMATION_EX 274 +#define USB_GET_NODE_CONNECTION_INFORMATION_EX 274 #endif #if !defined(USB_GET_HUB_CAPABILITIES_EX) -#define USB_GET_HUB_CAPABILITIES_EX 276 +#define USB_GET_HUB_CAPABILITIES_EX 276 #endif #if !defined(USB_GET_NODE_CONNECTION_INFORMATION_EX_V2) -#define USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 279 +#define USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 279 #endif #ifndef METHOD_BUFFERED -#define METHOD_BUFFERED 0 +#define METHOD_BUFFERED 0 #endif #ifndef FILE_ANY_ACCESS -#define FILE_ANY_ACCESS 0x00000000 +#define FILE_ANY_ACCESS 0x00000000 #endif #ifndef FILE_DEVICE_UNKNOWN -#define FILE_DEVICE_UNKNOWN 0x00000022 +#define FILE_DEVICE_UNKNOWN 0x00000022 #endif #ifndef FILE_DEVICE_USB -#define FILE_DEVICE_USB FILE_DEVICE_UNKNOWN +#define FILE_DEVICE_USB FILE_DEVICE_UNKNOWN #endif #ifndef CTL_CODE -#define CTL_CODE(DeviceType, Function, Method, Access)( \ - ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) +#define CTL_CODE(DeviceType, Function, Method, Access) \ + (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) #endif typedef enum USB_CONNECTION_STATUS { @@ -413,45 +419,45 @@ DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Sibling, (PDEVINST, DEVINST, ULONG)); DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Device_IDA, (DEVINST, PCHAR, ULONG, ULONG)); #define IOCTL_USB_GET_HUB_CAPABILITIES_EX \ - CTL_CODE( FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES_EX, METHOD_BUFFERED, FILE_ANY_ACCESS) + CTL_CODE( FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES_EX, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_USB_GET_HUB_CAPABILITIES \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES, METHOD_BUFFERED, FILE_ANY_ACCESS) + CTL_CODE(FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, METHOD_BUFFERED, FILE_ANY_ACCESS) + CTL_CODE(FILE_DEVICE_USB, USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_USB_GET_ROOT_HUB_NAME \ - CTL_CODE(FILE_DEVICE_USB, HCD_GET_ROOT_HUB_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS) + CTL_CODE(FILE_DEVICE_USB, HCD_GET_ROOT_HUB_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_USB_GET_NODE_INFORMATION \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_INFORMATION, METHOD_BUFFERED, FILE_ANY_ACCESS) + CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_INFORMATION, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX, METHOD_BUFFERED, FILE_ANY_ACCESS) + CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, METHOD_BUFFERED, FILE_ANY_ACCESS) + CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_ATTRIBUTES, METHOD_BUFFERED, FILE_ANY_ACCESS) + CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_ATTRIBUTES, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_USB_GET_NODE_CONNECTION_NAME \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS) + CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS) // Most of the structures below need to be packed #pragma pack(push, 1) typedef struct USB_INTERFACE_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bInterfaceNumber; - UCHAR bAlternateSetting; - UCHAR bNumEndpoints; - UCHAR bInterfaceClass; - UCHAR bInterfaceSubClass; - UCHAR bInterfaceProtocol; - UCHAR iInterface; + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bInterfaceNumber; + UCHAR bAlternateSetting; + UCHAR bNumEndpoints; + UCHAR bInterfaceClass; + UCHAR bInterfaceSubClass; + UCHAR bInterfaceProtocol; + UCHAR iInterface; } USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR; typedef struct USB_CONFIGURATION_DESCRIPTOR_SHORT { @@ -469,39 +475,39 @@ typedef struct USB_CONFIGURATION_DESCRIPTOR_SHORT { } USB_CONFIGURATION_DESCRIPTOR_SHORT; typedef struct USB_ENDPOINT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bEndpointAddress; - UCHAR bmAttributes; - USHORT wMaxPacketSize; - UCHAR bInterval; + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bEndpointAddress; + UCHAR bmAttributes; + USHORT wMaxPacketSize; + UCHAR bInterval; } USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR; typedef struct USB_DESCRIPTOR_REQUEST { - ULONG ConnectionIndex; + ULONG ConnectionIndex; struct { - UCHAR bmRequest; - UCHAR bRequest; - USHORT wValue; - USHORT wIndex; - USHORT wLength; + UCHAR bmRequest; + UCHAR bRequest; + USHORT wValue; + USHORT wIndex; + USHORT wLength; } SetupPacket; -// UCHAR Data[0]; +// UCHAR Data[0]; } USB_DESCRIPTOR_REQUEST, *PUSB_DESCRIPTOR_REQUEST; typedef struct USB_HUB_DESCRIPTOR { - UCHAR bDescriptorLength; - UCHAR bDescriptorType; - UCHAR bNumberOfPorts; - USHORT wHubCharacteristics; - UCHAR bPowerOnToPowerGood; - UCHAR bHubControlCurrent; - UCHAR bRemoveAndPowerMask[64]; + UCHAR bDescriptorLength; + UCHAR bDescriptorType; + UCHAR bNumberOfPorts; + USHORT wHubCharacteristics; + UCHAR bPowerOnToPowerGood; + UCHAR bHubControlCurrent; + UCHAR bRemoveAndPowerMask[64]; } USB_HUB_DESCRIPTOR, *PUSB_HUB_DESCRIPTOR; typedef struct USB_ROOT_HUB_NAME { - ULONG ActualLength; - WCHAR RootHubName[1]; + ULONG ActualLength; + WCHAR RootHubName[1]; } USB_ROOT_HUB_NAME, *PUSB_ROOT_HUB_NAME; typedef struct USB_ROOT_HUB_NAME_FIXED { @@ -510,9 +516,9 @@ typedef struct USB_ROOT_HUB_NAME_FIXED { } USB_ROOT_HUB_NAME_FIXED; typedef struct USB_NODE_CONNECTION_NAME { - ULONG ConnectionIndex; - ULONG ActualLength; - WCHAR NodeName[1]; + ULONG ConnectionIndex; + ULONG ActualLength; + WCHAR NodeName[1]; } USB_NODE_CONNECTION_NAME, *PUSB_NODE_CONNECTION_NAME; typedef struct USB_NODE_CONNECTION_NAME_FIXED { @@ -529,41 +535,41 @@ typedef struct USB_HUB_NAME_FIXED { } USB_HUB_NAME_FIXED; typedef struct USB_HUB_INFORMATION { - USB_HUB_DESCRIPTOR HubDescriptor; - BOOLEAN HubIsBusPowered; + USB_HUB_DESCRIPTOR HubDescriptor; + BOOLEAN HubIsBusPowered; } USB_HUB_INFORMATION, *PUSB_HUB_INFORMATION; typedef struct USB_MI_PARENT_INFORMATION { - ULONG NumberOfInterfaces; + ULONG NumberOfInterfaces; } USB_MI_PARENT_INFORMATION, *PUSB_MI_PARENT_INFORMATION; typedef struct USB_NODE_INFORMATION { - USB_HUB_NODE NodeType; + USB_HUB_NODE NodeType; union { - USB_HUB_INFORMATION HubInformation; - USB_MI_PARENT_INFORMATION MiParentInformation; + USB_HUB_INFORMATION HubInformation; + USB_MI_PARENT_INFORMATION MiParentInformation; } u; } USB_NODE_INFORMATION, *PUSB_NODE_INFORMATION; typedef struct USB_PIPE_INFO { - USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; - ULONG ScheduleOffset; + USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; + ULONG ScheduleOffset; } USB_PIPE_INFO, *PUSB_PIPE_INFO; typedef struct USB_NODE_CONNECTION_INFORMATION_EX { - ULONG ConnectionIndex; - USB_DEVICE_DESCRIPTOR DeviceDescriptor; - UCHAR CurrentConfigurationValue; - UCHAR Speed; - BOOLEAN DeviceIsHub; - USHORT DeviceAddress; - ULONG NumberOfOpenPipes; - USB_CONNECTION_STATUS ConnectionStatus; -// USB_PIPE_INFO PipeList[0]; + ULONG ConnectionIndex; + USB_DEVICE_DESCRIPTOR DeviceDescriptor; + UCHAR CurrentConfigurationValue; + UCHAR Speed; + BOOLEAN DeviceIsHub; + USHORT DeviceAddress; + ULONG NumberOfOpenPipes; + USB_CONNECTION_STATUS ConnectionStatus; +// USB_PIPE_INFO PipeList[0]; } USB_NODE_CONNECTION_INFORMATION_EX, *PUSB_NODE_CONNECTION_INFORMATION_EX; typedef union _USB_PROTOCOLS { - ULONG ul; + ULONG ul; struct { ULONG Usb110:1; ULONG Usb200:1; @@ -599,7 +605,7 @@ typedef struct USB_HUB_CAP_FLAGS { } USB_HUB_CAP_FLAGS, *PUSB_HUB_CAP_FLAGS; typedef struct USB_HUB_CAPABILITIES { - ULONG HubIs2xCapable : 1; + ULONG HubIs2xCapable:1; } USB_HUB_CAPABILITIES, *PUSB_HUB_CAPABILITIES; typedef struct USB_HUB_CAPABILITIES_EX { @@ -610,20 +616,20 @@ typedef struct USB_HUB_CAPABILITIES_EX { /* winusb.dll interface */ -#define SHORT_PACKET_TERMINATE 0x01 -#define AUTO_CLEAR_STALL 0x02 -#define PIPE_TRANSFER_TIMEOUT 0x03 -#define IGNORE_SHORT_PACKETS 0x04 -#define ALLOW_PARTIAL_READS 0x05 -#define AUTO_FLUSH 0x06 -#define RAW_IO 0x07 -#define MAXIMUM_TRANSFER_SIZE 0x08 -#define AUTO_SUSPEND 0x81 -#define SUSPEND_DELAY 0x83 -#define DEVICE_SPEED 0x01 -#define LowSpeed 0x01 -#define FullSpeed 0x02 -#define HighSpeed 0x03 +#define SHORT_PACKET_TERMINATE 0x01 +#define AUTO_CLEAR_STALL 0x02 +#define PIPE_TRANSFER_TIMEOUT 0x03 +#define IGNORE_SHORT_PACKETS 0x04 +#define ALLOW_PARTIAL_READS 0x05 +#define AUTO_FLUSH 0x06 +#define RAW_IO 0x07 +#define MAXIMUM_TRANSFER_SIZE 0x08 +#define AUTO_SUSPEND 0x81 +#define SUSPEND_DELAY 0x83 +#define DEVICE_SPEED 0x01 +#define LowSpeed 0x01 +#define FullSpeed 0x02 +#define HighSpeed 0x03 typedef enum USBD_PIPE_TYPE { UsbdPipeTypeControl, @@ -633,19 +639,19 @@ typedef enum USBD_PIPE_TYPE { } USBD_PIPE_TYPE; typedef struct { - USBD_PIPE_TYPE PipeType; - UCHAR PipeId; - USHORT MaximumPacketSize; - UCHAR Interval; + USBD_PIPE_TYPE PipeType; + UCHAR PipeId; + USHORT MaximumPacketSize; + UCHAR Interval; } WINUSB_PIPE_INFORMATION, *PWINUSB_PIPE_INFORMATION; #pragma pack(1) typedef struct { - UCHAR request_type; - UCHAR request; - USHORT value; - USHORT index; - USHORT length; + UCHAR request_type; + UCHAR request; + USHORT value; + USHORT index; + USHORT length; } WINUSB_SETUP_PACKET, *PWINUSB_SETUP_PACKET; #pragma pack() @@ -770,8 +776,7 @@ typedef BOOL (WINAPI *WinUsb_ResetDevice_t)( ); /* /!\ These must match the ones from the official libusbk.h */ -typedef enum _KUSB_FNID -{ +typedef enum _KUSB_FNID { KUSB_FNID_Init, KUSB_FNID_Free, KUSB_FNID_ClaimInterface, @@ -818,7 +823,7 @@ typedef struct _KLIB_VERSION { typedef KLIB_VERSION* PKLIB_VERSION; typedef BOOL (WINAPI *LibK_GetProcAddress_t)( - PVOID* ProcAddress, + PVOID *ProcAddress, ULONG DriverID, ULONG FunctionID ); @@ -854,8 +859,8 @@ struct winusb_interface { /* hid.dll interface */ -#define HIDP_STATUS_SUCCESS 0x110000 -typedef void* PHIDP_PREPARSED_DATA; +#define HIDP_STATUS_SUCCESS 0x110000 +typedef void * PHIDP_PREPARSED_DATA; #pragma pack(1) typedef struct { @@ -868,64 +873,64 @@ typedef struct { typedef USHORT USAGE; typedef struct { - USAGE Usage; - USAGE UsagePage; - USHORT InputReportByteLength; - USHORT OutputReportByteLength; - USHORT FeatureReportByteLength; - USHORT Reserved[17]; - USHORT NumberLinkCollectionNodes; - USHORT NumberInputButtonCaps; - USHORT NumberInputValueCaps; - USHORT NumberInputDataIndices; - USHORT NumberOutputButtonCaps; - USHORT NumberOutputValueCaps; - USHORT NumberOutputDataIndices; - USHORT NumberFeatureButtonCaps; - USHORT NumberFeatureValueCaps; - USHORT NumberFeatureDataIndices; + USAGE Usage; + USAGE UsagePage; + USHORT InputReportByteLength; + USHORT OutputReportByteLength; + USHORT FeatureReportByteLength; + USHORT Reserved[17]; + USHORT NumberLinkCollectionNodes; + USHORT NumberInputButtonCaps; + USHORT NumberInputValueCaps; + USHORT NumberInputDataIndices; + USHORT NumberOutputButtonCaps; + USHORT NumberOutputValueCaps; + USHORT NumberOutputDataIndices; + USHORT NumberFeatureButtonCaps; + USHORT NumberFeatureValueCaps; + USHORT NumberFeatureDataIndices; } HIDP_CAPS, *PHIDP_CAPS; typedef enum _HIDP_REPORT_TYPE { - HidP_Input, - HidP_Output, - HidP_Feature + HidP_Input, + HidP_Output, + HidP_Feature } HIDP_REPORT_TYPE; typedef struct _HIDP_VALUE_CAPS { - USAGE UsagePage; - UCHAR ReportID; - BOOLEAN IsAlias; - USHORT BitField; - USHORT LinkCollection; - USAGE LinkUsage; - USAGE LinkUsagePage; - BOOLEAN IsRange; - BOOLEAN IsStringRange; - BOOLEAN IsDesignatorRange; - BOOLEAN IsAbsolute; - BOOLEAN HasNull; - UCHAR Reserved; - USHORT BitSize; - USHORT ReportCount; - USHORT Reserved2[5]; - ULONG UnitsExp; - ULONG Units; - LONG LogicalMin, LogicalMax; - LONG PhysicalMin, PhysicalMax; + USAGE UsagePage; + UCHAR ReportID; + BOOLEAN IsAlias; + USHORT BitField; + USHORT LinkCollection; + USAGE LinkUsage; + USAGE LinkUsagePage; + BOOLEAN IsRange; + BOOLEAN IsStringRange; + BOOLEAN IsDesignatorRange; + BOOLEAN IsAbsolute; + BOOLEAN HasNull; + UCHAR Reserved; + USHORT BitSize; + USHORT ReportCount; + USHORT Reserved2[5]; + ULONG UnitsExp; + ULONG Units; + LONG LogicalMin, LogicalMax; + LONG PhysicalMin, PhysicalMax; union { - struct { - USAGE UsageMin, UsageMax; - USHORT StringMin, StringMax; - USHORT DesignatorMin, DesignatorMax; - USHORT DataIndexMin, DataIndexMax; - } Range; - struct { - USAGE Usage, Reserved1; - USHORT StringIndex, Reserved2; - USHORT DesignatorIndex, Reserved3; - USHORT DataIndex, Reserved4; - } NotRange; + struct { + USAGE UsageMin, UsageMax; + USHORT StringMin, StringMax; + USHORT DesignatorMin, DesignatorMax; + USHORT DataIndexMin, DataIndexMax; + } Range; + struct { + USAGE Usage, Reserved1; + USHORT StringIndex, Reserved2; + USHORT DesignatorIndex, Reserved3; + USHORT DataIndex, Reserved4; + } NotRange; } u; } HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 330e4563f..4945a8da1 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11032 +#define LIBUSB_NANO 11033 From 4a0446f51bb28b8f7440be5290941b85ac23a7ff Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Wed, 27 Jan 2016 00:15:11 -0800 Subject: [PATCH 114/222] Misc: Fix up Visual Studio project files This commit sorts the source and header files by name (for easier human parsing), adds windows_nt_common.c to the 2010 and 2012 projects, and removes some CPP defines that should not be present in the libusb_static_2015.vcxproj file. Signed-off-by: Chris Dickens --- libusb/version_nano.h | 2 +- msvc/libusb_dll_2010.vcxproj | 6 +++++- msvc/libusb_dll_2012.vcxproj | 9 ++++++--- msvc/libusb_dll_2013.vcxproj | 11 ++++++----- msvc/libusb_dll_2015.vcxproj | 11 ++++++----- msvc/libusb_static_2010.vcxproj | 8 +++++--- msvc/libusb_static_2012.vcxproj | 10 ++++++---- msvc/libusb_static_2013.vcxproj | 12 ++++++------ msvc/libusb_static_2015.vcxproj | 16 ++++++++-------- msvc/libusb_usbdk_dll_2013.vcxproj | 16 ++++++++-------- msvc/libusb_usbdk_dll_2015.vcxproj | 16 ++++++++-------- msvc/libusb_usbdk_static_2013.vcxproj | 14 +++++++------- msvc/libusb_usbdk_static_2015.vcxproj | 14 +++++++------- 13 files changed, 79 insertions(+), 66 deletions(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 4945a8da1..bce5595e2 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11033 +#define LIBUSB_NANO 11034 diff --git a/msvc/libusb_dll_2010.vcxproj b/msvc/libusb_dll_2010.vcxproj index 9e5629ea6..3a3781139 100644 --- a/msvc/libusb_dll_2010.vcxproj +++ b/msvc/libusb_dll_2010.vcxproj @@ -146,6 +146,7 @@ + @@ -155,8 +156,11 @@ - + + + + diff --git a/msvc/libusb_dll_2012.vcxproj b/msvc/libusb_dll_2012.vcxproj index 65e1a3416..92a8baff6 100644 --- a/msvc/libusb_dll_2012.vcxproj +++ b/msvc/libusb_dll_2012.vcxproj @@ -150,17 +150,20 @@ + - - - + + + + + diff --git a/msvc/libusb_dll_2013.vcxproj b/msvc/libusb_dll_2013.vcxproj index 6f79468d6..6a4ce16f0 100644 --- a/msvc/libusb_dll_2013.vcxproj +++ b/msvc/libusb_dll_2013.vcxproj @@ -147,22 +147,23 @@ - + - - - - + + + + + diff --git a/msvc/libusb_dll_2015.vcxproj b/msvc/libusb_dll_2015.vcxproj index 44ea2507e..0c1730aa8 100644 --- a/msvc/libusb_dll_2015.vcxproj +++ b/msvc/libusb_dll_2015.vcxproj @@ -147,22 +147,23 @@ - + - - - - + + + + + diff --git a/msvc/libusb_static_2010.vcxproj b/msvc/libusb_static_2010.vcxproj index c4c49ad54..78233c3c9 100644 --- a/msvc/libusb_static_2010.vcxproj +++ b/msvc/libusb_static_2010.vcxproj @@ -136,19 +136,21 @@ + - - - + + + + diff --git a/msvc/libusb_static_2012.vcxproj b/msvc/libusb_static_2012.vcxproj index 5cce2b860..7df832d8c 100644 --- a/msvc/libusb_static_2012.vcxproj +++ b/msvc/libusb_static_2012.vcxproj @@ -140,19 +140,21 @@ + - - - + - + + + + diff --git a/msvc/libusb_static_2013.vcxproj b/msvc/libusb_static_2013.vcxproj index 4ea706f12..fa3caacbc 100644 --- a/msvc/libusb_static_2013.vcxproj +++ b/msvc/libusb_static_2013.vcxproj @@ -137,24 +137,24 @@ - + - - - - + - + + + + diff --git a/msvc/libusb_static_2015.vcxproj b/msvc/libusb_static_2015.vcxproj index 510ef5cca..b9c585074 100644 --- a/msvc/libusb_static_2015.vcxproj +++ b/msvc/libusb_static_2015.vcxproj @@ -81,7 +81,7 @@ Disabled .;..\libusb;%(AdditionalIncludeDirectories) - ENUM_DEBUG;ENABLE_DEBUG_LOGGING;_WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + _WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreadedDebug Level4 ProgramDatabase @@ -98,7 +98,7 @@ Disabled .;..\libusb;%(AdditionalIncludeDirectories) - ENUM_DEBUG;ENABLE_DEBUG_LOGGING;_WIN32;_WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + _WIN32;_WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreadedDebug Level4 ProgramDatabase @@ -141,24 +141,24 @@ - + - - - - + - + + + + diff --git a/msvc/libusb_usbdk_dll_2013.vcxproj b/msvc/libusb_usbdk_dll_2013.vcxproj index 5fb1635dc..6d9018f2c 100644 --- a/msvc/libusb_usbdk_dll_2013.vcxproj +++ b/msvc/libusb_usbdk_dll_2013.vcxproj @@ -147,24 +147,24 @@ - - + + - - - - - - + + + + + + diff --git a/msvc/libusb_usbdk_dll_2015.vcxproj b/msvc/libusb_usbdk_dll_2015.vcxproj index ff3c64ba6..a19c17e4b 100644 --- a/msvc/libusb_usbdk_dll_2015.vcxproj +++ b/msvc/libusb_usbdk_dll_2015.vcxproj @@ -147,24 +147,24 @@ - - + + - - - - - - + + + + + + diff --git a/msvc/libusb_usbdk_static_2013.vcxproj b/msvc/libusb_usbdk_static_2013.vcxproj index 1447dbbcc..5cc42d480 100644 --- a/msvc/libusb_usbdk_static_2013.vcxproj +++ b/msvc/libusb_usbdk_static_2013.vcxproj @@ -137,24 +137,24 @@ - - + + - - - - - + + + + + diff --git a/msvc/libusb_usbdk_static_2015.vcxproj b/msvc/libusb_usbdk_static_2015.vcxproj index 1d5df29dd..eec20eeff 100644 --- a/msvc/libusb_usbdk_static_2015.vcxproj +++ b/msvc/libusb_usbdk_static_2015.vcxproj @@ -137,24 +137,24 @@ - - + + - - - - - + + + + + From d76a40118af35558fd65c3a030793a671bab95b0 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Wed, 27 Jan 2016 00:25:25 -0800 Subject: [PATCH 115/222] Windows (usbdk): Remove unnecessary/unused structure Signed-off-by: Chris Dickens --- libusb/os/windows_usbdk.c | 8 +------- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/libusb/os/windows_usbdk.c b/libusb/os/windows_usbdk.c index f2bea9338..1d5bddffb 100644 --- a/libusb/os/windows_usbdk.c +++ b/libusb/os/windows_usbdk.c @@ -76,12 +76,6 @@ struct usbdk_device_priv { uint8_t active_configuration; }; -struct usbdk_device_handle_priv { - //This field is to solve compilation error on VS2013: - //error C2016: C requires that a struct or union has at least one member - int dummy; -}; - struct usbdk_transfer_priv { USB_DK_TRANSFER_REQUEST request; struct winfd pollable_fd; @@ -896,7 +890,7 @@ const struct usbi_os_backend usbdk_backend = { NULL, #endif sizeof(struct usbdk_device_priv), - sizeof(struct usbdk_device_handle_priv), + 0, sizeof(struct usbdk_transfer_priv), }; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index bce5595e2..03fcfd49f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11034 +#define LIBUSB_NANO 11035 From cdfe236931ef3fd06adac0fdf6df49baa39ff35e Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Wed, 27 Jan 2016 00:27:27 -0800 Subject: [PATCH 116/222] Windows (usbdk): Remove unnecessary bookkeeping The core library will not call the backend's exit() function if the init() function does not succeed, so keeping track of whether init() successfully completed is redundant. Signed-off-by: Chris Dickens --- libusb/os/windows_usbdk.c | 8 ++------ libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/libusb/os/windows_usbdk.c b/libusb/os/windows_usbdk.c index 1d5bddffb..c4cb183c6 100644 --- a/libusb/os/windows_usbdk.c +++ b/libusb/os/windows_usbdk.c @@ -67,7 +67,6 @@ typedef int32_t USBD_STATUS; #endif static int concurrent_usage = -1; -static int init_succeeded = 0; struct usbdk_device_priv { USB_DK_DEVICE_INFO info; @@ -200,7 +199,7 @@ static int usbdk_init(struct libusb_context *ctx) { int r; - if ((++concurrent_usage == 0) || !init_succeeded) { + if (++concurrent_usage == 0) { r = load_usbdk_helper_dll(ctx); if (r) return r; @@ -210,8 +209,6 @@ static int usbdk_init(struct libusb_context *ctx) r = windows_common_init(ctx); if (r) goto error_roll_back; - - init_succeeded = 1; } return LIBUSB_SUCCESS; @@ -368,11 +365,10 @@ static int usbdk_get_device_list(struct libusb_context *ctx, struct discovered_d static void usbdk_exit(void) { - if ((--concurrent_usage < 0) && init_succeeded) { + if (--concurrent_usage < 0) { windows_common_exit(); exit_polling(); unload_usbdk_helper_dll(); - init_succeeded = 0; } } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 03fcfd49f..e5b4908ed 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11035 +#define LIBUSB_NANO 11036 From 7de6c0f28186824ec04a33703ec079ed451c437d Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Wed, 27 Jan 2016 00:33:42 -0800 Subject: [PATCH 117/222] Windows: Fix compilation warnings when logging is disabled Signed-off-by: Chris Dickens --- libusb/os/windows_usbdk.c | 6 ++---- libusb/os/windows_winusb.c | 6 ++++-- libusb/version_nano.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libusb/os/windows_usbdk.c b/libusb/os/windows_usbdk.c index c4cb183c6..9abb83e77 100644 --- a/libusb/os/windows_usbdk.c +++ b/libusb/os/windows_usbdk.c @@ -115,8 +115,7 @@ static FARPROC get_usbdk_proc_addr(struct libusb_context *ctx, LPCSTR api_name) FARPROC api_ptr = GetProcAddress(usbdk_helper.module, api_name); if (api_ptr == NULL) { - DWORD err = GetLastError(); - usbi_err(ctx, "UsbDkHelper API %s not found, error %d", api_name, err); + usbi_err(ctx, "UsbDkHelper API %s not found, error %d", api_name, GetLastError()); } return api_ptr; @@ -131,8 +130,7 @@ static int load_usbdk_helper_dll(struct libusb_context *ctx) { usbdk_helper.module = LoadLibraryA("UsbDkHelper"); if (usbdk_helper.module == NULL) { - DWORD err = GetLastError(); - usbi_err(ctx, "Failed to load UsbDkHelper.dll, error %d", err); + usbi_err(ctx, "Failed to load UsbDkHelper.dll, error %d", GetLastError()); return LIBUSB_ERROR_NOT_FOUND; } diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 0488e8e2e..c6afb14be 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -1312,7 +1312,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered for (pass = 0; ((pass < nb_guids) && (r == LIBUSB_SUCCESS)); pass++) { //#define ENUM_DEBUG -#ifdef ENUM_DEBUG +#if defined(ENABLE_LOGGING) && defined(ENUM_DEBUG) const char *passname[] = { "HCD", "HUB", "GEN", "DEV", "HID", "EXT" }; usbi_dbg("#### PROCESSING %ss %s", passname[(pass <= HID_PASS) ? pass : (HID_PASS + 1)], (pass != GEN_PASS) ? guid_to_string(guid[pass]) : ""); @@ -3409,8 +3409,10 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) int i, j; // report IDs handling ULONG size[3]; - const char *type[3] = {"input", "output", "feature"}; int nb_ids[2]; // zero and nonzero report IDs +#if defined(ENABLE_LOGGING) + const char *type[3] = {"input", "output", "feature"}; +#endif CHECK_HID_AVAILABLE; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index e5b4908ed..dfcc7c565 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11036 +#define LIBUSB_NANO 11037 From fc721ede3e901fd8f25d2cc904a924384cd23d5f Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Wed, 27 Jan 2016 01:00:55 -0800 Subject: [PATCH 118/222] Windows: Replace open-coded string alloc + copy with _strdup() Signed-off-by: Chris Dickens --- libusb/os/windows_nt_common.c | 3 +-- libusb/os/windows_winusb.c | 9 +++------ libusb/version_nano.h | 2 +- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/libusb/os/windows_nt_common.c b/libusb/os/windows_nt_common.c index 897286561..9a4f854ae 100644 --- a/libusb/os/windows_nt_common.c +++ b/libusb/os/windows_nt_common.c @@ -267,13 +267,12 @@ unsigned long htab_hash(const char *str) // string (same hash, different string) at the same time is extremely low safe_free(htab_table[idx].str); htab_table[idx].used = hval; - htab_table[idx].str = malloc(safe_strlen(str) + 1); + htab_table[idx].str = _strdup(str); if (htab_table[idx].str == NULL) { usbi_err(NULL, "could not duplicate string for hash table"); usbi_mutex_unlock(&htab_write_mutex); return 0; } - memcpy(htab_table[idx].str, str, safe_strlen(str) + 1); ++htab_filled; usbi_mutex_unlock(&htab_write_mutex); diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index c6afb14be..8670be771 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -549,11 +549,10 @@ static int get_sub_api(char *driver, int api) if (len == 0) return SUB_API_NOTSET; - tmp_str = calloc(1, len + 1); + tmp_str = _strdup(driver); if (tmp_str == NULL) return SUB_API_NOTSET; - memcpy(tmp_str, driver, len + 1); tok = strtok(tmp_str, sep_str); while (tok != NULL) { for (i = 0; i < usb_api_backend[api].nb_driver_names; i++) { @@ -1548,10 +1547,8 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered break; default: // For other devices, the first interface is the same as the device - priv->usb_interface[0].path = calloc(1, safe_strlen(priv->path)); - if (priv->usb_interface[0].path != NULL) - safe_strcpy(priv->usb_interface[0].path, safe_strlen(priv->path) + 1, priv->path); - else + priv->usb_interface[0].path = _strdup(priv->path); + if (priv->usb_interface[0].path == NULL) usbi_warn(ctx, "could not duplicate interface path '%s'", priv->path); // The following is needed if we want API calls to work for both simple // and composite devices. diff --git a/libusb/version_nano.h b/libusb/version_nano.h index dfcc7c565..ca4d099c4 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11037 +#define LIBUSB_NANO 11038 From d73aafe5c12d8ab41553daece8f3131107a2d62f Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Wed, 27 Jan 2016 01:25:49 -0800 Subject: [PATCH 119/222] Windows: Minor improvements to windows_nt_common.c 1) Possible memory leak is avoided if htab_create() is called while a hash table is already allocated 2) Error handling is simplified in windows_handle_events() Signed-off-by: Chris Dickens --- libusb/os/windows_nt_common.c | 8 +++++--- libusb/version_nano.h | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libusb/os/windows_nt_common.c b/libusb/os/windows_nt_common.c index 9a4f854ae..30796ac02 100644 --- a/libusb/os/windows_nt_common.c +++ b/libusb/os/windows_nt_common.c @@ -150,6 +150,7 @@ static bool htab_create(struct libusb_context *ctx, unsigned long nel) { if (htab_table != NULL) { usbi_err(ctx, "hash table already allocated"); + return true; } // Create a mutex @@ -537,6 +538,7 @@ int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_N struct usbi_transfer *transfer; struct winfd *pollable_fd = NULL; DWORD io_size, io_result; + int r = LIBUSB_SUCCESS; usbi_mutex_lock(&ctx->open_devs_lock); for (i = 0; i < nfds && num_ready > 0; i++) { @@ -570,14 +572,14 @@ int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_N // newly allocated wfd that took the place of the one from the transfer. windows_handle_callback(transfer, io_result, io_size); } else { - usbi_mutex_unlock(&ctx->open_devs_lock); usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]); - return LIBUSB_ERROR_NOT_FOUND; + r = LIBUSB_ERROR_NOT_FOUND; + break; } } usbi_mutex_unlock(&ctx->open_devs_lock); - return LIBUSB_SUCCESS; + return r; } int windows_common_init(struct libusb_context *ctx) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index ca4d099c4..105925ca0 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11038 +#define LIBUSB_NANO 11039 From 4dfa6d6493ea52b81f4ebccfa5a1214746f58b6c Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Wed, 27 Jan 2016 19:24:13 +0000 Subject: [PATCH 120/222] Windows: Fix DDK compilation --- libusb/os/windows_usbdk.c | 3 ++- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libusb/os/windows_usbdk.c b/libusb/os/windows_usbdk.c index 9abb83e77..2bf3d8094 100644 --- a/libusb/os/windows_usbdk.c +++ b/libusb/os/windows_usbdk.c @@ -542,13 +542,14 @@ static int usbdk_do_control_transfer(struct usbi_transfer *itransfer) struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winfd wfd; ULONG Length; TransferResult transResult; HANDLE sysHandle; sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); - struct winfd wfd = usbi_create_fd(sysHandle, RW_READ, NULL, NULL); + wfd = usbi_create_fd(sysHandle, RW_READ, NULL, NULL); // Always use the handle returned from usbi_create_fd (wfd.handle) if (wfd.fd < 0) return LIBUSB_ERROR_NO_MEM; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 105925ca0..14860a873 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11039 +#define LIBUSB_NANO 11040 From c8f71151464141bf515353e5c2aff9e56bc15657 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Wed, 27 Jan 2016 11:46:01 -0800 Subject: [PATCH 121/222] Windows: Ensure proper cleanup when backend init() functions fail Signed-off-by: Chris Dickens --- libusb/os/windows_usbdk.c | 30 ++++++++++++++++++++---------- libusb/os/windows_winusb.c | 12 ++++++++---- libusb/version_nano.h | 2 +- 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/libusb/os/windows_usbdk.c b/libusb/os/windows_usbdk.c index 2bf3d8094..da12edaa7 100644 --- a/libusb/os/windows_usbdk.c +++ b/libusb/os/windows_usbdk.c @@ -114,16 +114,18 @@ static FARPROC get_usbdk_proc_addr(struct libusb_context *ctx, LPCSTR api_name) { FARPROC api_ptr = GetProcAddress(usbdk_helper.module, api_name); - if (api_ptr == NULL) { + if (api_ptr == NULL) usbi_err(ctx, "UsbDkHelper API %s not found, error %d", api_name, GetLastError()); - } return api_ptr; } static void unload_usbdk_helper_dll(void) { - FreeLibrary(usbdk_helper.module); + if (usbdk_helper.module != NULL) { + FreeLibrary(usbdk_helper.module); + usbdk_helper.module = NULL; + } } static int load_usbdk_helper_dll(struct libusb_context *ctx) @@ -190,6 +192,7 @@ static int load_usbdk_helper_dll(struct libusb_context *ctx) error_unload: FreeLibrary(usbdk_helper.module); + usbdk_helper.module = NULL; return LIBUSB_ERROR_NOT_FOUND; } @@ -197,23 +200,30 @@ static int usbdk_init(struct libusb_context *ctx) { int r; - if (++concurrent_usage == 0) { + if (++concurrent_usage == 0) { // First init? r = load_usbdk_helper_dll(ctx); if (r) - return r; + goto init_exit; init_polling(); r = windows_common_init(ctx); if (r) - goto error_roll_back; + goto init_exit; } + // At this stage, either we went through full init successfully, or didn't need to + r = LIBUSB_SUCCESS; - return LIBUSB_SUCCESS; +init_exit: + if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? + exit_polling(); + windows_common_exit(); + unload_usbdk_helper_dll(); + } + + if (r != LIBUSB_SUCCESS) + --concurrent_usage; // Not expected to call libusb_exit if we failed. -error_roll_back: - windows_common_exit(); - unload_usbdk_helper_dll(); return r; } diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 8670be771..5bf35a27d 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -760,9 +760,9 @@ static int windows_init(struct libusb_context *ctx) { int i, r = LIBUSB_ERROR_OTHER; HANDLE semaphore; - char sem_name[11 + 1 + 8]; // strlen(libusb_init)+'\0'+(32-bit hex PID) + char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' - sprintf(sem_name, "libusb_init%08X", (unsigned int)GetCurrentProcessId()); + sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name); if (semaphore == NULL) { usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0)); @@ -782,6 +782,7 @@ static int windows_init(struct libusb_context *ctx) if (++concurrent_usage == 0) { // First init? get_windows_version(); usbi_dbg(windows_version_str); + if (windows_version == WINDOWS_UNSUPPORTED) { usbi_err(ctx, "This version of Windows is NOT supported"); r = LIBUSB_ERROR_NOT_SUPPORTED; @@ -813,6 +814,9 @@ static int windows_init(struct libusb_context *ctx) init_exit: // Holds semaphore here. if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? + for (i = 0; i < USB_API_MAX; i++) + usb_api_backend[i].exit(SUBAPI_NOT_SET); + exit_polling(); windows_common_exit(); usbi_mutex_destroy(&autoclaim_lock); } @@ -1622,9 +1626,9 @@ static void windows_exit(void) { int i; HANDLE semaphore; - char sem_name[11 + 1 + 8]; // strlen(libusb_init)+'\0'+(32-bit hex PID) + char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' - sprintf(sem_name, "libusb_init%08X", (unsigned int)GetCurrentProcessId()); + sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name); if (semaphore == NULL) return; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 14860a873..91cf0727d 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11040 +#define LIBUSB_NANO 11041 From f2773136a063bc717a71d93384be1f42ef3468b0 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Thu, 28 Jan 2016 00:15:59 -0800 Subject: [PATCH 122/222] WinCE: Miscellaneous changes 1) Make some variables static that are not used outside wince_usb.c 2) Minor stylistic changes to match the rest of the library source Signed-off-by: Chris Dickens --- libusb/os/wince_usb.c | 195 +++++++++++++++++++++++------------------- libusb/version_nano.h | 2 +- 2 files changed, 109 insertions(+), 88 deletions(-) diff --git a/libusb/os/wince_usb.c b/libusb/os/wince_usb.c index cb8d4a75a..df5405158 100644 --- a/libusb/os/wince_usb.c +++ b/libusb/os/wince_usb.c @@ -31,29 +31,29 @@ #include "wince_usb.h" // Global variables -uint64_t hires_frequency, hires_ticks_to_ps; -const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime +const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime int windows_version = WINDOWS_CE; +static uint64_t hires_frequency, hires_ticks_to_ps; +static HANDLE driver_handle = INVALID_HANDLE_VALUE; static int concurrent_usage = -1; -HANDLE driver_handle = INVALID_HANDLE_VALUE; /* * Converts a windows error to human readable string * uses retval as errorcode, or, if 0, use GetLastError() */ #if defined(ENABLE_LOGGING) -static char* windows_error_str(uint32_t retval) +static const char *windows_error_str(DWORD retval) { static TCHAR wErr_string[ERR_BUFFER_SIZE]; static char err_string[ERR_BUFFER_SIZE]; + DWORD error_code, format_error; DWORD size; size_t i; - uint32_t error_code, format_error; - error_code = retval?retval:GetLastError(); + error_code = retval ? retval : GetLastError(); - safe_stprintf(wErr_string, ERR_BUFFER_SIZE, _T("[%u] "), error_code); + safe_stprintf(wErr_string, ERR_BUFFER_SIZE, _T("[%u] "), (unsigned int)error_code); size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &wErr_string[safe_tcslen(wErr_string)], @@ -62,50 +62,50 @@ static char* windows_error_str(uint32_t retval) format_error = GetLastError(); if (format_error) safe_stprintf(wErr_string, ERR_BUFFER_SIZE, - _T("Windows error code %u (FormatMessage error code %u)"), error_code, format_error); + _T("Windows error code %u (FormatMessage error code %u)"), + (unsigned int)error_code, (unsigned int)format_error); else - safe_stprintf(wErr_string, ERR_BUFFER_SIZE, _T("Unknown error code %u"), error_code); + safe_stprintf(wErr_string, ERR_BUFFER_SIZE, _T("Unknown error code %u"), (unsigned int)error_code); } else { // Remove CR/LF terminators - for (i=safe_tcslen(wErr_string)-1; ((wErr_string[i]==0x0A) || (wErr_string[i]==0x0D)); i--) { + for (i = safe_tcslen(wErr_string) - 1; ((wErr_string[i] == 0x0A) || (wErr_string[i] == 0x0D)); i--) wErr_string[i] = 0; - } } + if (WideCharToMultiByte(CP_ACP, 0, wErr_string, -1, err_string, ERR_BUFFER_SIZE, NULL, NULL) < 0) - { strcpy(err_string, "Unable to convert error string"); - } + return err_string; } #endif static struct wince_device_priv *_device_priv(struct libusb_device *dev) { - return (struct wince_device_priv *) dev->os_priv; + return (struct wince_device_priv *)dev->os_priv; } // ceusbkwrapper to libusb error code mapping -static int translate_driver_error(int error) +static int translate_driver_error(DWORD error) { switch (error) { - case ERROR_INVALID_PARAMETER: - return LIBUSB_ERROR_INVALID_PARAM; - case ERROR_CALL_NOT_IMPLEMENTED: - case ERROR_NOT_SUPPORTED: - return LIBUSB_ERROR_NOT_SUPPORTED; - case ERROR_NOT_ENOUGH_MEMORY: - return LIBUSB_ERROR_NO_MEM; - case ERROR_INVALID_HANDLE: - return LIBUSB_ERROR_NO_DEVICE; - case ERROR_BUSY: - return LIBUSB_ERROR_BUSY; - - // Error codes that are either unexpected, or have - // no suitable LIBUSB_ERROR equivalent. - case ERROR_CANCELLED: - case ERROR_INTERNAL_ERROR: - default: - return LIBUSB_ERROR_OTHER; + case ERROR_INVALID_PARAMETER: + return LIBUSB_ERROR_INVALID_PARAM; + case ERROR_CALL_NOT_IMPLEMENTED: + case ERROR_NOT_SUPPORTED: + return LIBUSB_ERROR_NOT_SUPPORTED; + case ERROR_NOT_ENOUGH_MEMORY: + return LIBUSB_ERROR_NO_MEM; + case ERROR_INVALID_HANDLE: + return LIBUSB_ERROR_NO_DEVICE; + case ERROR_BUSY: + return LIBUSB_ERROR_BUSY; + + // Error codes that are either unexpected, or have + // no suitable LIBUSB_ERROR equivalent. + case ERROR_CANCELLED: + case ERROR_INTERNAL_ERROR: + default: + return LIBUSB_ERROR_OTHER; } } @@ -147,9 +147,9 @@ static int init_device( dev->device_address = dev_addr; priv->dev = drv_dev; - if (!UkwGetDeviceDescriptor(priv->dev, &(priv->desc))) { + if (!UkwGetDeviceDescriptor(priv->dev, &(priv->desc))) r = translate_driver_error(GetLastError()); - } + return r; } @@ -159,9 +159,9 @@ static int wince_init(struct libusb_context *ctx) int r = LIBUSB_ERROR_OTHER; HANDLE semaphore; LARGE_INTEGER li_frequency; - TCHAR sem_name[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID) + TCHAR sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' - _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)GetCurrentProcessId()&0xFFFFFFFF); + _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); semaphore = CreateSemaphore(NULL, 1, 1, sem_name); if (semaphore == NULL) { usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0)); @@ -232,13 +232,12 @@ static int wince_init(struct libusb_context *ctx) static void wince_exit(void) { HANDLE semaphore; - TCHAR sem_name[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID) + TCHAR sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' - _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)GetCurrentProcessId()&0xFFFFFFFF); + _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); semaphore = CreateSemaphore(NULL, 1, 1, sem_name); - if (semaphore == NULL) { + if (semaphore == NULL) return; - } // A successful wait brings our semaphore count to 0 (unsignaled) // => any concurent wait stalls until the semaphore release @@ -266,7 +265,7 @@ static int wince_get_device_list( struct discovered_devs **discdevs) { UKW_DEVICE devices[MAX_DEVICE_COUNT]; - struct discovered_devs * new_devices = *discdevs; + struct discovered_devs *new_devices = *discdevs; DWORD count = 0, i; struct libusb_device *dev = NULL; unsigned char bus_addr, dev_addr; @@ -281,7 +280,8 @@ static int wince_get_device_list( usbi_err(ctx, "could not get devices: %s", windows_error_str(0)); return libusbErr; } - for(i = 0; i < count; ++i) { + + for (i = 0; i < count; ++i) { release_list_offset = i; success = UkwGetDeviceAddress(devices[i], &bus_addr, &dev_addr, &session_id); if (!success) { @@ -289,6 +289,7 @@ static int wince_get_device_list( usbi_err(ctx, "could not get device address for %u: %s", (unsigned int)i, windows_error_str(0)); goto err_out; } + dev = usbi_get_device_by_session_id(ctx, session_id); if (dev) { usbi_dbg("using existing device for %u/%u (session %lu)", @@ -305,20 +306,25 @@ static int wince_get_device_list( r = LIBUSB_ERROR_NO_MEM; goto err_out; } + r = init_device(dev, devices[i], bus_addr, dev_addr); if (r < 0) goto err_out; + r = usbi_sanitize_device(dev); if (r < 0) goto err_out; } + new_devices = discovered_devs_append(new_devices, dev); if (!discdevs) { r = LIBUSB_ERROR_NO_MEM; goto err_out; } + safe_unref_device(dev); } + *discdevs = new_devices; return r; err_out: @@ -360,10 +366,11 @@ static int wince_get_active_config_descriptor( { struct wince_device_priv *priv = _device_priv(device); DWORD actualSize = len; + *host_endian = 0; - if (!UkwGetConfigDescriptor(priv->dev, UKW_ACTIVE_CONFIGURATION, buffer, len, &actualSize)) { + if (!UkwGetConfigDescriptor(priv->dev, UKW_ACTIVE_CONFIGURATION, buffer, len, &actualSize)) return translate_driver_error(GetLastError()); - } + return actualSize; } @@ -374,10 +381,11 @@ static int wince_get_config_descriptor( { struct wince_device_priv *priv = _device_priv(device); DWORD actualSize = len; + *host_endian = 0; - if (!UkwGetConfigDescriptor(priv->dev, config_index, buffer, len, &actualSize)) { + if (!UkwGetConfigDescriptor(priv->dev, config_index, buffer, len, &actualSize)) return translate_driver_error(GetLastError()); - } + return actualSize; } @@ -387,9 +395,10 @@ static int wince_get_configuration( { struct wince_device_priv *priv = _device_priv(handle->dev); UCHAR cv = 0; - if (!UkwGetConfig(priv->dev, &cv)) { + + if (!UkwGetConfig(priv->dev, &cv)) return translate_driver_error(GetLastError()); - } + (*config) = cv; return LIBUSB_SUCCESS; } @@ -403,9 +412,9 @@ static int wince_set_configuration( // This should correspond to the "unconfigured state" required by // libusb when the specified configuration is -1. UCHAR cv = (config < 0) ? 0 : config; - if (!UkwSetConfig(priv->dev, cv)) { + if (!UkwSetConfig(priv->dev, cv)) return translate_driver_error(GetLastError()); - } + return LIBUSB_SUCCESS; } @@ -414,9 +423,10 @@ static int wince_claim_interface( int interface_number) { struct wince_device_priv *priv = _device_priv(handle->dev); - if (!UkwClaimInterface(priv->dev, interface_number)) { + + if (!UkwClaimInterface(priv->dev, interface_number)) return translate_driver_error(GetLastError()); - } + return LIBUSB_SUCCESS; } @@ -425,12 +435,13 @@ static int wince_release_interface( int interface_number) { struct wince_device_priv *priv = _device_priv(handle->dev); - if (!UkwSetInterfaceAlternateSetting(priv->dev, interface_number, 0)) { + + if (!UkwSetInterfaceAlternateSetting(priv->dev, interface_number, 0)) return translate_driver_error(GetLastError()); - } - if (!UkwReleaseInterface(priv->dev, interface_number)) { + + if (!UkwReleaseInterface(priv->dev, interface_number)) return translate_driver_error(GetLastError()); - } + return LIBUSB_SUCCESS; } @@ -439,9 +450,10 @@ static int wince_set_interface_altsetting( int interface_number, int altsetting) { struct wince_device_priv *priv = _device_priv(handle->dev); - if (!UkwSetInterfaceAlternateSetting(priv->dev, interface_number, altsetting)) { + + if (!UkwSetInterfaceAlternateSetting(priv->dev, interface_number, altsetting)) return translate_driver_error(GetLastError()); - } + return LIBUSB_SUCCESS; } @@ -450,12 +462,13 @@ static int wince_clear_halt( unsigned char endpoint) { struct wince_device_priv *priv = _device_priv(handle->dev); - if (!UkwClearHaltHost(priv->dev, endpoint)) { + + if (!UkwClearHaltHost(priv->dev, endpoint)) return translate_driver_error(GetLastError()); - } - if (!UkwClearHaltDevice(priv->dev, endpoint)) { + + if (!UkwClearHaltDevice(priv->dev, endpoint)) return translate_driver_error(GetLastError()); - } + return LIBUSB_SUCCESS; } @@ -463,9 +476,10 @@ static int wince_reset_device( struct libusb_device_handle *handle) { struct wince_device_priv *priv = _device_priv(handle->dev); - if (!UkwResetDevice(priv->dev)) { + + if (!UkwResetDevice(priv->dev)) return translate_driver_error(GetLastError()); - } + return LIBUSB_SUCCESS; } @@ -475,9 +489,10 @@ static int wince_kernel_driver_active( { struct wince_device_priv *priv = _device_priv(handle->dev); BOOL result = FALSE; - if (!UkwKernelDriverActive(priv->dev, interface_number, &result)) { + + if (!UkwKernelDriverActive(priv->dev, interface_number, &result)) return translate_driver_error(GetLastError()); - } + return result ? 1 : 0; } @@ -486,9 +501,10 @@ static int wince_detach_kernel_driver( int interface_number) { struct wince_device_priv *priv = _device_priv(handle->dev); - if (!UkwDetachKernelDriver(priv->dev, interface_number)) { + + if (!UkwDetachKernelDriver(priv->dev, interface_number)) return translate_driver_error(GetLastError()); - } + return LIBUSB_SUCCESS; } @@ -497,22 +513,25 @@ static int wince_attach_kernel_driver( int interface_number) { struct wince_device_priv *priv = _device_priv(handle->dev); - if (!UkwAttachKernelDriver(priv->dev, interface_number)) { + + if (!UkwAttachKernelDriver(priv->dev, interface_number)) return translate_driver_error(GetLastError()); - } + return LIBUSB_SUCCESS; } static void wince_destroy_device(struct libusb_device *dev) { struct wince_device_priv *priv = _device_priv(dev); + UkwReleaseDeviceList(driver_handle, &priv->dev, 1); } static void wince_clear_transfer_priv(struct usbi_transfer *itransfer) { - struct wince_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer); + struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); struct winfd wfd = fd_to_winfd(transfer_priv->pollable_fd.fd); + // No need to cancel transfer as it is either complete or abandoned wfd.itransfer = NULL; CloseHandle(wfd.handle); @@ -523,11 +542,11 @@ static int wince_cancel_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev); - struct wince_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer); + struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - if (!UkwCancelTransfer(priv->dev, transfer_priv->pollable_fd.overlapped, UKW_TF_NO_WAIT)) { + if (!UkwCancelTransfer(priv->dev, transfer_priv->pollable_fd.overlapped, UKW_TF_NO_WAIT)) return translate_driver_error(GetLastError()); - } + return LIBUSB_SUCCESS; } @@ -535,7 +554,7 @@ static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct wince_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer); + struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev); BOOL direction_in, ret; struct winfd wfd; @@ -577,6 +596,7 @@ static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer ret = UkwIssueBulkTransfer(priv->dev, flags, transfer->endpoint, transfer->buffer, transfer->length, &transfer->actual_length, wfd.overlapped); } + if (!ret) { int libusbErr = translate_driver_error(GetLastError()); usbi_err(ctx, "UkwIssue%sTransfer failed: error %u", @@ -702,12 +722,12 @@ static void wince_transfer_callback( status = LIBUSB_TRANSFER_ERROR; break; } + wince_clear_transfer_priv(itransfer); - if (status == LIBUSB_TRANSFER_CANCELLED) { + if (status == LIBUSB_TRANSFER_CANCELLED) usbi_handle_transfer_cancellation(itransfer); - } else { + else usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); - } } static void wince_handle_callback( @@ -739,15 +759,15 @@ static int wince_handle_events( BOOL found = FALSE; struct usbi_transfer *transfer; DWORD io_size, io_result; + int r = LIBUSB_SUCCESS; usbi_mutex_lock(&ctx->open_devs_lock); for (i = 0; i < nfds && num_ready > 0; i++) { usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); - if (!fds[i].revents) { + if (!fds[i].revents) continue; - } num_ready--; @@ -773,17 +793,17 @@ static int wince_handle_events( wince_handle_callback(transfer, io_result, io_size); } else if (found) { usbi_err(ctx, "matching transfer for fd %d has not completed", fds[i]); - usbi_mutex_unlock(&ctx->open_devs_lock); - return LIBUSB_ERROR_OTHER; + r = LIBUSB_ERROR_OTHER; + break; } else { usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]); - usbi_mutex_unlock(&ctx->open_devs_lock); - return LIBUSB_ERROR_NOT_FOUND; + r = LIBUSB_ERROR_NOT_FOUND; + break; } } - usbi_mutex_unlock(&ctx->open_devs_lock); - return LIBUSB_SUCCESS; + + return r; } /* @@ -795,6 +815,7 @@ static int wince_clock_gettime(int clk_id, struct timespec *tp) ULARGE_INTEGER rtime; FILETIME filetime; SYSTEMTIME st; + switch(clk_id) { case USBI_CLOCK_MONOTONIC: if (hires_frequency != 0 && QueryPerformanceCounter(&hires_counter)) { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 91cf0727d..b75c7f966 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11041 +#define LIBUSB_NANO 11042 From f94184c4f84857da8f015ea07803b550e8994161 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Thu, 28 Jan 2016 00:20:00 -0800 Subject: [PATCH 123/222] WinCE: Remove unnecessary/unused structure Signed-off-by: Chris Dickens --- libusb/os/wince_usb.c | 2 +- libusb/os/wince_usb.h | 6 ------ libusb/version_nano.h | 2 +- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/libusb/os/wince_usb.c b/libusb/os/wince_usb.c index df5405158..96cad675c 100644 --- a/libusb/os/wince_usb.c +++ b/libusb/os/wince_usb.c @@ -885,6 +885,6 @@ const struct usbi_os_backend wince_backend = { wince_clock_gettime, sizeof(struct wince_device_priv), - sizeof(struct wince_device_handle_priv), + 0, sizeof(struct wince_transfer_priv), }; diff --git a/libusb/os/wince_usb.h b/libusb/os/wince_usb.h index bc61b5c10..b3403dbde 100644 --- a/libusb/os/wince_usb.h +++ b/libusb/os/wince_usb.h @@ -118,12 +118,6 @@ struct wince_device_priv { UKW_DEVICE_DESCRIPTOR desc; }; -struct wince_device_handle_priv { - // This member isn't used, but only exists to avoid an empty structure - // for private data for the device handle. - int reserved; -}; - struct wince_transfer_priv { struct winfd pollable_fd; uint8_t interface_number; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index b75c7f966..49bc3237d 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11042 +#define LIBUSB_NANO 11043 From 452e7bd68383c43b75e6b12791f5721fbaea4697 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Thu, 28 Jan 2016 00:22:09 -0800 Subject: [PATCH 124/222] Windows: Fix some minor issues in windows_nt_common.c 1) Address a few more stylistic discrepancies 2) Add appropriate type casts for printf functions Signed-off-by: Chris Dickens --- libusb/os/windows_nt_common.c | 16 ++++++++-------- libusb/version_nano.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libusb/os/windows_nt_common.c b/libusb/os/windows_nt_common.c index 30796ac02..55b681898 100644 --- a/libusb/os/windows_nt_common.c +++ b/libusb/os/windows_nt_common.c @@ -33,7 +33,7 @@ #include "windows_nt_common.h" // Global variables -const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime +const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime // Global variables for clock_gettime mechanism static uint64_t hires_ticks_to_ps; @@ -75,14 +75,14 @@ const char *windows_error_str(DWORD retval) error_code = retval ? retval : GetLastError(); - safe_sprintf(err_string, ERR_BUFFER_SIZE, "[%u] ", error_code); + safe_sprintf(err_string, ERR_BUFFER_SIZE, "[%u] ", (unsigned int)error_code); // Translate codes returned by SetupAPI. The ones we are dealing with are either // in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes. // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx switch (error_code & 0xE0000000) { case 0: - error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified + error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified break; case 0xE0000000: error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF); @@ -98,9 +98,10 @@ const char *windows_error_str(DWORD retval) format_error = GetLastError(); if (format_error) safe_sprintf(err_string, ERR_BUFFER_SIZE, - "Windows error code %u (FormatMessage error code %u)", error_code, format_error); + "Windows error code %u (FormatMessage error code %u)", + (unsigned int)error_code, (unsigned int)format_error); else - safe_sprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", error_code); + safe_sprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", (unsigned int)error_code); } else { // Remove CR/LF terminators @@ -120,7 +121,7 @@ const char *windows_error_str(DWORD retval) typedef struct htab_entry { unsigned long used; - char* str; + char *str; } htab_entry; static htab_entry *htab_table = NULL; @@ -248,8 +249,7 @@ unsigned long htab_hash(const char *str) // If entry is found use it. if ((htab_table[idx].used == hval) && (safe_strcmp(str, htab_table[idx].str) == 0)) return idx; - } - while (htab_table[idx].used); + } while (htab_table[idx].used); } // Not found => New entry diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 49bc3237d..a3f68ad90 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11043 +#define LIBUSB_NANO 11044 From 57cfbb444e03179a4e4eafba18416209f0db1d1c Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Thu, 28 Jan 2016 00:29:58 -0800 Subject: [PATCH 125/222] Windows/WinCE: Improve the run-time dynamic linking scheme Prior to this commit, the Windows and WinCE backends had a specific shortcoming when loading DLLs, that being that once loaded they were never unloaded. This commit improves this by providing a means to unload the DLLs during cleanup. Note that the use of GetModuleHandle() has been removed in favor of the exclusive use of LoadLibrary(). This was done to ensure that a reference count is taken against the loaded DLL, which guards against some other part of the application unloading the DLL that libusb is currently using. Signed-off-by: Chris Dickens --- libusb/os/wince_usb.c | 59 ++++++++++-------- libusb/os/wince_usb.h | 45 +++++++------- libusb/os/windows_common.h | 95 +++++++++++++++++----------- libusb/os/windows_nt_common.c | 20 ++++-- libusb/os/windows_winusb.c | 112 ++++++++++++++++++++++------------ libusb/os/windows_winusb.h | 73 ++++++++++++---------- libusb/version_nano.h | 2 +- 7 files changed, 246 insertions(+), 160 deletions(-) diff --git a/libusb/os/wince_usb.c b/libusb/os/wince_usb.c index 96cad675c..fc95e9c7d 100644 --- a/libusb/os/wince_usb.c +++ b/libusb/os/wince_usb.c @@ -109,33 +109,40 @@ static int translate_driver_error(DWORD error) } } -static int init_dllimports() -{ - DLL_LOAD(ceusbkwrapper.dll, UkwOpenDriver, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwGetDeviceList, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwReleaseDeviceList, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwGetDeviceAddress, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwGetDeviceDescriptor, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwGetConfigDescriptor, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwCloseDriver, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwCancelTransfer, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwIssueControlTransfer, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwClaimInterface, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwReleaseInterface, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwSetInterfaceAlternateSetting, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwClearHaltHost, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwClearHaltDevice, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwGetConfig, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwSetConfig, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwResetDevice, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwKernelDriverActive, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwAttachKernelDriver, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwDetachKernelDriver, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwIssueBulkTransfer, TRUE); - DLL_LOAD(ceusbkwrapper.dll, UkwIsPipeHalted, TRUE); +static int init_dllimports(void) +{ + DLL_GET_HANDLE(ceusbkwrapper); + DLL_LOAD_FUNC(ceusbkwrapper, UkwOpenDriver, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwGetDeviceList, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwReleaseDeviceList, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwGetDeviceAddress, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwGetDeviceDescriptor, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwGetConfigDescriptor, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwCloseDriver, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwCancelTransfer, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwIssueControlTransfer, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwClaimInterface, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwReleaseInterface, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwSetInterfaceAlternateSetting, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwClearHaltHost, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwClearHaltDevice, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwGetConfig, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwSetConfig, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwResetDevice, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwKernelDriverActive, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwAttachKernelDriver, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwDetachKernelDriver, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwIssueBulkTransfer, TRUE); + DLL_LOAD_FUNC(ceusbkwrapper, UkwIsPipeHalted, TRUE); + return LIBUSB_SUCCESS; } +static void exit_dllimports(void) +{ + DLL_FREE_HANDLE(ceusbkwrapper); +} + static int init_device( struct libusb_device *dev, UKW_DEVICE drv_dev, unsigned char bus_addr, unsigned char dev_addr) @@ -215,6 +222,9 @@ static int wince_init(struct libusb_context *ctx) init_exit: // Holds semaphore here. if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? + exit_dllimports(); + exit_polling(); + if (driver_handle != INVALID_HANDLE_VALUE) { UkwCloseDriver(driver_handle); driver_handle = INVALID_HANDLE_VALUE; @@ -248,6 +258,7 @@ static void wince_exit(void) // Only works if exits and inits are balanced exactly if (--concurrent_usage < 0) { // Last exit + exit_dllimports(); exit_polling(); if (driver_handle != INVALID_HANDLE_VALUE) { diff --git a/libusb/os/wince_usb.h b/libusb/os/wince_usb.h index b3403dbde..edcb9fcc4 100644 --- a/libusb/os/wince_usb.h +++ b/libusb/os/wince_usb.h @@ -87,28 +87,29 @@ typedef struct { * to specify the currently active configuration for the device. */ #define UKW_ACTIVE_CONFIGURATION -1 -DLL_DECLARE(WINAPI, HANDLE, UkwOpenDriver, ()); -DLL_DECLARE(WINAPI, BOOL, UkwGetDeviceList, (HANDLE, LPUKW_DEVICE, DWORD, LPDWORD)); -DLL_DECLARE(WINAPI, void, UkwReleaseDeviceList, (HANDLE, LPUKW_DEVICE, DWORD)); -DLL_DECLARE(WINAPI, BOOL, UkwGetDeviceAddress, (UKW_DEVICE, unsigned char*, unsigned char*, unsigned long*)); -DLL_DECLARE(WINAPI, BOOL, UkwGetDeviceDescriptor, (UKW_DEVICE, LPUKW_DEVICE_DESCRIPTOR)); -DLL_DECLARE(WINAPI, BOOL, UkwGetConfigDescriptor, (UKW_DEVICE, DWORD, LPVOID, DWORD, LPDWORD)); -DLL_DECLARE(WINAPI, void, UkwCloseDriver, (HANDLE)); -DLL_DECLARE(WINAPI, BOOL, UkwCancelTransfer, (UKW_DEVICE, LPOVERLAPPED, DWORD)); -DLL_DECLARE(WINAPI, BOOL, UkwIssueControlTransfer, (UKW_DEVICE, DWORD, LPUKW_CONTROL_HEADER, LPVOID, DWORD, LPDWORD, LPOVERLAPPED)); -DLL_DECLARE(WINAPI, BOOL, UkwClaimInterface, (UKW_DEVICE, DWORD)); -DLL_DECLARE(WINAPI, BOOL, UkwReleaseInterface, (UKW_DEVICE, DWORD)); -DLL_DECLARE(WINAPI, BOOL, UkwSetInterfaceAlternateSetting, (UKW_DEVICE, DWORD, DWORD)); -DLL_DECLARE(WINAPI, BOOL, UkwClearHaltHost, (UKW_DEVICE, UCHAR)); -DLL_DECLARE(WINAPI, BOOL, UkwClearHaltDevice, (UKW_DEVICE, UCHAR)); -DLL_DECLARE(WINAPI, BOOL, UkwGetConfig, (UKW_DEVICE, PUCHAR)); -DLL_DECLARE(WINAPI, BOOL, UkwSetConfig, (UKW_DEVICE, UCHAR)); -DLL_DECLARE(WINAPI, BOOL, UkwResetDevice, (UKW_DEVICE)); -DLL_DECLARE(WINAPI, BOOL, UkwKernelDriverActive, (UKW_DEVICE, DWORD, PBOOL)); -DLL_DECLARE(WINAPI, BOOL, UkwAttachKernelDriver, (UKW_DEVICE, DWORD)); -DLL_DECLARE(WINAPI, BOOL, UkwDetachKernelDriver, (UKW_DEVICE, DWORD)); -DLL_DECLARE(WINAPI, BOOL, UkwIssueBulkTransfer, (UKW_DEVICE, DWORD, UCHAR, LPVOID, DWORD, LPDWORD, LPOVERLAPPED)); -DLL_DECLARE(WINAPI, BOOL, UkwIsPipeHalted, (UKW_DEVICE, UCHAR, LPBOOL)); +DLL_DECLARE_HANDLE(ceusbkwrapper); +DLL_DECLARE_FUNC(WINAPI, HANDLE, UkwOpenDriver, ()); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetDeviceList, (HANDLE, LPUKW_DEVICE, DWORD, LPDWORD)); +DLL_DECLARE_FUNC(WINAPI, void, UkwReleaseDeviceList, (HANDLE, LPUKW_DEVICE, DWORD)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetDeviceAddress, (UKW_DEVICE, unsigned char*, unsigned char*, unsigned long*)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetDeviceDescriptor, (UKW_DEVICE, LPUKW_DEVICE_DESCRIPTOR)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetConfigDescriptor, (UKW_DEVICE, DWORD, LPVOID, DWORD, LPDWORD)); +DLL_DECLARE_FUNC(WINAPI, void, UkwCloseDriver, (HANDLE)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwCancelTransfer, (UKW_DEVICE, LPOVERLAPPED, DWORD)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwIssueControlTransfer, (UKW_DEVICE, DWORD, LPUKW_CONTROL_HEADER, LPVOID, DWORD, LPDWORD, LPOVERLAPPED)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwClaimInterface, (UKW_DEVICE, DWORD)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwReleaseInterface, (UKW_DEVICE, DWORD)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwSetInterfaceAlternateSetting, (UKW_DEVICE, DWORD, DWORD)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwClearHaltHost, (UKW_DEVICE, UCHAR)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwClearHaltDevice, (UKW_DEVICE, UCHAR)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetConfig, (UKW_DEVICE, PUCHAR)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwSetConfig, (UKW_DEVICE, UCHAR)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwResetDevice, (UKW_DEVICE)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwKernelDriverActive, (UKW_DEVICE, DWORD, PBOOL)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwAttachKernelDriver, (UKW_DEVICE, DWORD)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwDetachKernelDriver, (UKW_DEVICE, DWORD)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwIssueBulkTransfer, (UKW_DEVICE, DWORD, UCHAR, LPVOID, DWORD, LPDWORD, LPOVERLAPPED)); +DLL_DECLARE_FUNC(WINAPI, BOOL, UkwIsPipeHalted, (UKW_DEVICE, UCHAR, LPBOOL)); // Used to determine if an endpoint status really is halted on a failed transfer. #define STATUS_HALT_FLAG 0x1 diff --git a/libusb/os/windows_common.h b/libusb/os/windows_common.h index 45c59af44..0149e11bf 100644 --- a/libusb/os/windows_common.h +++ b/libusb/os/windows_common.h @@ -62,45 +62,70 @@ /* - * API macros - from libusb-win32 1.x + * API macros - leveraged from libusb-win32 1.x */ -#define DLL_DECLARE_PREFIXNAME(api, ret, prefixname, name, args) \ - typedef ret (api * __dll_##name##_t)args; \ - static __dll_##name##_t prefixname = NULL - #ifndef _WIN32_WCE -#define DLL_STRINGIFY(dll) #dll -#define DLL_GET_MODULE_HANDLE(dll) GetModuleHandleA(DLL_STRINGIFY(dll)) -#define DLL_LOAD_LIBRARY(dll) LoadLibraryA(DLL_STRINGIFY(dll)) +#define DLL_STRINGIFY(s) #s +#define DLL_LOAD_LIBRARY(name) LoadLibraryA(DLL_STRINGIFY(name)) #else -#define DLL_STRINGIFY(dll) L#dll -#define DLL_GET_MODULE_HANDLE(dll) GetModuleHandle(DLL_STRINGIFY(dll)) -#define DLL_LOAD_LIBRARY(dll) LoadLibrary(DLL_STRINGIFY(dll)) +#define DLL_STRINGIFY(s) L#s +#define DLL_LOAD_LIBRARY(name) LoadLibrary(DLL_STRINGIFY(name)) #endif -#define DLL_LOAD_PREFIXNAME(dll, prefixname, name, ret_on_failure) \ - do { \ - HMODULE h = DLL_GET_MODULE_HANDLE(dll); \ - if (!h) \ - h = DLL_LOAD_LIBRARY(dll); \ - if (!h) { \ - if (ret_on_failure) { return LIBUSB_ERROR_NOT_FOUND; } \ - else { break; } \ - } \ - prefixname = (__dll_##name##_t)GetProcAddress(h, \ - DLL_STRINGIFY(name)); \ - if (prefixname) break; \ - prefixname = (__dll_##name##_t)GetProcAddress(h, \ - DLL_STRINGIFY(name) DLL_STRINGIFY(A)); \ - if (prefixname) break; \ - prefixname = (__dll_##name##_t)GetProcAddress(h, \ - DLL_STRINGIFY(name) DLL_STRINGIFY(W)); \ - if (prefixname) break; \ - if(ret_on_failure) \ - return LIBUSB_ERROR_NOT_FOUND; \ +/* + * Macros for handling DLL themselves + */ +#define DLL_DECLARE_HANDLE(name) \ + static HMODULE __dll_##name##_handle = NULL + +#define DLL_GET_HANDLE(name) \ + do { \ + __dll_##name##_handle = DLL_LOAD_LIBRARY(name); \ + if (!__dll_##name##_handle) \ + return LIBUSB_ERROR_OTHER; \ + } while (0) + +#define DLL_FREE_HANDLE(name) \ + do { \ + if (__dll_##name##_handle) { \ + FreeLibrary(__dll_##name##_handle); \ + __dll_##name##_handle = NULL; \ + } \ + } while(0) + + +/* + * Macros for handling functions within a DLL + */ +#define DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefixname, name, args) \ + typedef ret (api * __dll_##name##_func_t)args; \ + static __dll_##name##_func_t prefixname = NULL + +#define DLL_DECLARE_FUNC(api, ret, name, args) \ + DLL_DECLARE_FUNC_PREFIXNAME(api, ret, name, name, args) +#define DLL_DECLARE_FUNC_PREFIXED(api, ret, prefix, name, args) \ + DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefix##name, name, args) + +#define DLL_LOAD_FUNC_PREFIXNAME(dll, prefixname, name, ret_on_failure) \ + do { \ + HMODULE h = __dll_##dll##_handle; \ + prefixname = (__dll_##name##_func_t)GetProcAddress(h, \ + DLL_STRINGIFY(name)); \ + if (prefixname) \ + break; \ + prefixname = (__dll_##name##_func_t)GetProcAddress(h, \ + DLL_STRINGIFY(name) DLL_STRINGIFY(A)); \ + if (prefixname) \ + break; \ + prefixname = (__dll_##name##_func_t)GetProcAddress(h, \ + DLL_STRINGIFY(name) DLL_STRINGIFY(W)); \ + if (prefixname) \ + break; \ + if (ret_on_failure) \ + return LIBUSB_ERROR_NOT_FOUND; \ } while(0) -#define DLL_DECLARE(api, ret, name, args) DLL_DECLARE_PREFIXNAME(api, ret, name, name, args) -#define DLL_LOAD(dll, name, ret_on_failure) DLL_LOAD_PREFIXNAME(dll, name, name, ret_on_failure) -#define DLL_DECLARE_PREFIXED(api, ret, prefix, name, args) DLL_DECLARE_PREFIXNAME(api, ret, prefix##name, name, args) -#define DLL_LOAD_PREFIXED(dll, prefix, name, ret_on_failure) DLL_LOAD_PREFIXNAME(dll, prefix##name, name, ret_on_failure) +#define DLL_LOAD_FUNC(dll, name, ret_on_failure) \ + DLL_LOAD_FUNC_PREFIXNAME(dll, name, name, ret_on_failure) +#define DLL_LOAD_FUNC_PREFIXED(dll, prefix, name, ret_on_failure) \ + DLL_LOAD_FUNC_PREFIXNAME(dll, prefix##name, name, ret_on_failure) diff --git a/libusb/os/windows_nt_common.c b/libusb/os/windows_nt_common.c index 55b681898..650e2fa66 100644 --- a/libusb/os/windows_nt_common.c +++ b/libusb/os/windows_nt_common.c @@ -54,9 +54,10 @@ static HANDLE timer_thread = NULL; static DWORD timer_thread_id = 0; /* User32 dependencies */ -DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, GetMessageA, (LPMSG, HWND, UINT, UINT)); -DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, PeekMessageA, (LPMSG, HWND, UINT, UINT, UINT)); -DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, PostThreadMessageA, (DWORD, UINT, WPARAM, LPARAM)); +DLL_DECLARE_HANDLE(User32); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, GetMessageA, (LPMSG, HWND, UINT, UINT)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, PeekMessageA, (LPMSG, HWND, UINT, UINT, UINT)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, PostThreadMessageA, (DWORD, UINT, WPARAM, LPARAM)); static unsigned __stdcall windows_clock_gettime_threaded(void *param); @@ -282,13 +283,19 @@ unsigned long htab_hash(const char *str) static int windows_init_dlls(void) { - DLL_LOAD_PREFIXED(User32.dll, p, GetMessageA, TRUE); - DLL_LOAD_PREFIXED(User32.dll, p, PeekMessageA, TRUE); - DLL_LOAD_PREFIXED(User32.dll, p, PostThreadMessageA, TRUE); + DLL_GET_HANDLE(User32); + DLL_LOAD_FUNC_PREFIXED(User32, p, GetMessageA, TRUE); + DLL_LOAD_FUNC_PREFIXED(User32, p, PeekMessageA, TRUE); + DLL_LOAD_FUNC_PREFIXED(User32, p, PostThreadMessageA, TRUE); return LIBUSB_SUCCESS; } +static void windows_exit_dlls(void) +{ + DLL_FREE_HANDLE(User32); +} + static bool windows_init_clock(struct libusb_context *ctx) { DWORD_PTR affinity, dummy; @@ -601,4 +608,5 @@ void windows_common_exit(void) { htab_destroy(); windows_destroy_clock(); + windows_exit_dlls(); } diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 5bf35a27d..f790736ea 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -124,8 +124,10 @@ static usbi_mutex_t autoclaim_lock; return LIBUSB_ERROR_ACCESS; \ } while(0) +static HMODULE WinUSBX_handle = NULL; static struct winusb_interface WinUSBX[SUB_API_MAX]; static const char *sub_api_name[SUB_API_MAX] = WINUSBX_DRV_NAMES; + static bool api_hid_available = false; #define CHECK_HID_AVAILABLE \ do { \ @@ -207,25 +209,45 @@ static char *sanitize_path(const char *path) */ static int init_dlls(void) { - DLL_LOAD(Cfgmgr32.dll, CM_Get_Parent, TRUE); - DLL_LOAD(Cfgmgr32.dll, CM_Get_Child, TRUE); - DLL_LOAD(Cfgmgr32.dll, CM_Get_Sibling, TRUE); - DLL_LOAD(Cfgmgr32.dll, CM_Get_Device_IDA, TRUE); + DLL_GET_HANDLE(Cfgmgr32); + DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Parent, TRUE); + DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Child, TRUE); + DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Sibling, TRUE); + DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Device_IDA, TRUE); + // Prefixed to avoid conflict with header files - DLL_LOAD_PREFIXED(OLE32.dll, p, CLSIDFromString, TRUE); - DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiGetClassDevsA, TRUE); - DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiEnumDeviceInfo, TRUE); - DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiEnumDeviceInterfaces, TRUE); - DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiGetDeviceInterfaceDetailA, TRUE); - DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiDestroyDeviceInfoList, TRUE); - DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiOpenDevRegKey, TRUE); - DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiGetDeviceRegistryPropertyA, TRUE); - DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiOpenDeviceInterfaceRegKey, TRUE); - DLL_LOAD_PREFIXED(AdvAPI32.dll, p, RegQueryValueExW, TRUE); - DLL_LOAD_PREFIXED(AdvAPI32.dll, p, RegCloseKey, TRUE); + DLL_GET_HANDLE(AdvAPI32); + DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExW, TRUE); + DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegCloseKey, TRUE); + + DLL_GET_HANDLE(Kernel32); + DLL_LOAD_FUNC_PREFIXED(Kernel32, p, IsWow64Process, FALSE); + + DLL_GET_HANDLE(OLE32); + DLL_LOAD_FUNC_PREFIXED(OLE32, p, CLSIDFromString, TRUE); + + DLL_GET_HANDLE(SetupAPI); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetClassDevsA, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInfo, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInterfaces, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInterfaceDetailA, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiDestroyDeviceInfoList, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDevRegKey, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceRegistryPropertyA, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDeviceInterfaceRegKey, TRUE); + return LIBUSB_SUCCESS; } +static void exit_dlls(void) +{ + DLL_FREE_HANDLE(Cfgmgr32); + DLL_FREE_HANDLE(AdvAPI32); + DLL_FREE_HANDLE(Kernel32); + DLL_FREE_HANDLE(OLE32); + DLL_FREE_HANDLE(SetupAPI); +} + /* * enumerate interfaces for the whole USB class * @@ -647,9 +669,8 @@ static BOOL is_x64(void) // Detect if we're running a 32 or 64 bit system if (sizeof(uintptr_t) < 8) { - DLL_LOAD_PREFIXED(Kernel32.dll, p, IsWow64Process, FALSE); if (pIsWow64Process != NULL) - (*pIsWow64Process)(GetCurrentProcess(), &ret); + pIsWow64Process(GetCurrentProcess(), &ret); } else { ret = TRUE; } @@ -816,6 +837,7 @@ static int windows_init(struct libusb_context *ctx) if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? for (i = 0; i < USB_API_MAX; i++) usb_api_backend[i].exit(SUBAPI_NOT_SET); + exit_dlls(); exit_polling(); windows_common_exit(); usbi_mutex_destroy(&autoclaim_lock); @@ -1644,6 +1666,7 @@ static void windows_exit(void) if (--concurrent_usage < 0) { // Last exit for (i = 0; i < USB_API_MAX; i++) usb_api_backend[i].exit(SUB_API_NOTSET); + exit_dlls(); exit_polling(); windows_common_exit(); usbi_mutex_destroy(&autoclaim_lock); @@ -2241,7 +2264,7 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { #define WinUSBX_Set(fn) \ do { \ if (native_winusb) \ - WinUSBX[i].fn = (WinUsb_##fn##_t) GetProcAddress(h, "WinUsb_" #fn); \ + WinUSBX[i].fn = (WinUsb_##fn##_t)GetProcAddress(h, "WinUsb_" #fn); \ else \ pLibK_GetProcAddress((PVOID *)&WinUSBX[i].fn, i, KUSB_FNID_##fn); \ } while (0) @@ -2255,15 +2278,11 @@ static int winusbx_init(int sub_api, struct libusb_context *ctx) LibK_GetProcAddress_t pLibK_GetProcAddress = NULL; LibK_GetVersion_t pLibK_GetVersion; - h = GetModuleHandleA("libusbK"); - if (h == NULL) - h = LoadLibraryA("libusbK"); + h = LoadLibraryA("libusbK"); if (h == NULL) { usbi_info(ctx, "libusbK DLL is not available, will use native WinUSB"); - h = GetModuleHandleA("WinUSB"); - if (h == NULL) - h = LoadLibraryA("WinUSB"); + h = LoadLibraryA("WinUSB"); if (h == NULL) { usbi_warn(ctx, "WinUSB DLL is not available either, " @@ -2281,6 +2300,7 @@ static int winusbx_init(int sub_api, struct libusb_context *ctx) pLibK_GetProcAddress = (LibK_GetProcAddress_t)GetProcAddress(h, "LibK_GetProcAddress"); if (pLibK_GetProcAddress == NULL) { usbi_err(ctx, "LibK_GetProcAddress() not found in libusbK DLL"); + FreeLibrary(h); return LIBUSB_ERROR_NOT_FOUND; } } @@ -2319,11 +2339,20 @@ static int winusbx_init(int sub_api, struct libusb_context *ctx) } } + WinUSBX_handle = h; return LIBUSB_SUCCESS; } static int winusbx_exit(int sub_api) { + if (WinUSBX_handle != NULL) { + FreeLibrary(WinUSBX_handle); + WinUSBX_handle = NULL; + + /* Reset the WinUSBX API structures */ + memset(&WinUSBX, 0, sizeof(WinUSBX)); + } + return LIBUSB_SUCCESS; } @@ -3368,22 +3397,23 @@ static int _hid_class_request(struct hid_device_priv *dev, HANDLE hid_handle, in */ static int hid_init(int sub_api, struct libusb_context *ctx) { - DLL_LOAD(hid.dll, HidD_GetAttributes, TRUE); - DLL_LOAD(hid.dll, HidD_GetHidGuid, TRUE); - DLL_LOAD(hid.dll, HidD_GetPreparsedData, TRUE); - DLL_LOAD(hid.dll, HidD_FreePreparsedData, TRUE); - DLL_LOAD(hid.dll, HidD_GetManufacturerString, TRUE); - DLL_LOAD(hid.dll, HidD_GetProductString, TRUE); - DLL_LOAD(hid.dll, HidD_GetSerialNumberString, TRUE); - DLL_LOAD(hid.dll, HidP_GetCaps, TRUE); - DLL_LOAD(hid.dll, HidD_SetNumInputBuffers, TRUE); - DLL_LOAD(hid.dll, HidD_SetFeature, TRUE); - DLL_LOAD(hid.dll, HidD_GetFeature, TRUE); - DLL_LOAD(hid.dll, HidD_GetPhysicalDescriptor, TRUE); - DLL_LOAD(hid.dll, HidD_GetInputReport, FALSE); - DLL_LOAD(hid.dll, HidD_SetOutputReport, FALSE); - DLL_LOAD(hid.dll, HidD_FlushQueue, TRUE); - DLL_LOAD(hid.dll, HidP_GetValueCaps, TRUE); + DLL_GET_HANDLE(hid); + DLL_LOAD_FUNC(hid, HidD_GetAttributes, TRUE); + DLL_LOAD_FUNC(hid, HidD_GetHidGuid, TRUE); + DLL_LOAD_FUNC(hid, HidD_GetPreparsedData, TRUE); + DLL_LOAD_FUNC(hid, HidD_FreePreparsedData, TRUE); + DLL_LOAD_FUNC(hid, HidD_GetManufacturerString, TRUE); + DLL_LOAD_FUNC(hid, HidD_GetProductString, TRUE); + DLL_LOAD_FUNC(hid, HidD_GetSerialNumberString, TRUE); + DLL_LOAD_FUNC(hid, HidP_GetCaps, TRUE); + DLL_LOAD_FUNC(hid, HidD_SetNumInputBuffers, TRUE); + DLL_LOAD_FUNC(hid, HidD_SetFeature, TRUE); + DLL_LOAD_FUNC(hid, HidD_GetFeature, TRUE); + DLL_LOAD_FUNC(hid, HidD_GetPhysicalDescriptor, TRUE); + DLL_LOAD_FUNC(hid, HidD_GetInputReport, FALSE); + DLL_LOAD_FUNC(hid, HidD_SetOutputReport, FALSE); + DLL_LOAD_FUNC(hid, HidD_FlushQueue, TRUE); + DLL_LOAD_FUNC(hid, HidP_GetValueCaps, TRUE); api_hid_available = true; return LIBUSB_SUCCESS; @@ -3391,6 +3421,8 @@ static int hid_init(int sub_api, struct libusb_context *ctx) static int hid_exit(int sub_api) { + DLL_FREE_HANDLE(hid); + return LIBUSB_SUCCESS; } diff --git a/libusb/os/windows_winusb.h b/libusb/os/windows_winusb.h index 8f53c4a6a..047f2e269 100644 --- a/libusb/os/windows_winusb.h +++ b/libusb/os/windows_winusb.h @@ -314,25 +314,32 @@ struct driver_lookup { }; /* OLE32 dependency */ -DLL_DECLARE_PREFIXED(WINAPI, HRESULT, p, CLSIDFromString, (LPCOLESTR, LPCLSID)); +DLL_DECLARE_HANDLE(OLE32); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, HRESULT, p, CLSIDFromString, (LPCOLESTR, LPCLSID)); +/* Kernel32 dependencies */ +DLL_DECLARE_HANDLE(Kernel32); /* This call is only available from XP SP2 */ -DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, IsWow64Process, (HANDLE, PBOOL)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, IsWow64Process, (HANDLE, PBOOL)); /* SetupAPI dependencies */ -DLL_DECLARE_PREFIXED(WINAPI, HDEVINFO, p, SetupDiGetClassDevsA, (const GUID*, PCSTR, HWND, DWORD)); -DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInfo, (HDEVINFO, DWORD, PSP_DEVINFO_DATA)); -DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInterfaces, (HDEVINFO, PSP_DEVINFO_DATA, +DLL_DECLARE_HANDLE(SetupAPI); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, HDEVINFO, p, SetupDiGetClassDevsA, (const GUID*, PCSTR, HWND, DWORD)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInfo, (HDEVINFO, DWORD, PSP_DEVINFO_DATA)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInterfaces, (HDEVINFO, PSP_DEVINFO_DATA, const GUID*, DWORD, PSP_DEVICE_INTERFACE_DATA)); -DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInterfaceDetailA, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInterfaceDetailA, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA)); -DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO)); -DLL_DECLARE_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDevRegKey, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM)); -DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO, +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDevRegKey, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD)); -DLL_DECLARE_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDeviceInterfaceRegKey, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, DWORD)); -DLL_DECLARE_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD)); -DLL_DECLARE_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDeviceInterfaceRegKey, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, DWORD)); + +/* AdvAPI32 dependencies */ +DLL_DECLARE_HANDLE(AdvAPI32); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY)); /* * Windows DDK API definitions. Most of it copied from MinGW's includes @@ -413,10 +420,11 @@ typedef enum USB_HUB_NODE { } USB_HUB_NODE; /* Cfgmgr32.dll interface */ -DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG)); -DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG)); -DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Sibling, (PDEVINST, DEVINST, ULONG)); -DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Device_IDA, (DEVINST, PCHAR, ULONG, ULONG)); +DLL_DECLARE_HANDLE(Cfgmgr32); +DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG)); +DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG)); +DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Sibling, (PDEVINST, DEVINST, ULONG)); +DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Device_IDA, (DEVINST, PCHAR, ULONG, ULONG)); #define IOCTL_USB_GET_HUB_CAPABILITIES_EX \ CTL_CODE( FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES_EX, METHOD_BUFFERED, FILE_ANY_ACCESS) @@ -934,19 +942,20 @@ typedef struct _HIDP_VALUE_CAPS { } u; } HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS; -DLL_DECLARE(WINAPI, BOOL, HidD_GetAttributes, (HANDLE, PHIDD_ATTRIBUTES)); -DLL_DECLARE(WINAPI, VOID, HidD_GetHidGuid, (LPGUID)); -DLL_DECLARE(WINAPI, BOOL, HidD_GetPreparsedData, (HANDLE, PHIDP_PREPARSED_DATA *)); -DLL_DECLARE(WINAPI, BOOL, HidD_FreePreparsedData, (PHIDP_PREPARSED_DATA)); -DLL_DECLARE(WINAPI, BOOL, HidD_GetManufacturerString, (HANDLE, PVOID, ULONG)); -DLL_DECLARE(WINAPI, BOOL, HidD_GetProductString, (HANDLE, PVOID, ULONG)); -DLL_DECLARE(WINAPI, BOOL, HidD_GetSerialNumberString, (HANDLE, PVOID, ULONG)); -DLL_DECLARE(WINAPI, LONG, HidP_GetCaps, (PHIDP_PREPARSED_DATA, PHIDP_CAPS)); -DLL_DECLARE(WINAPI, BOOL, HidD_SetNumInputBuffers, (HANDLE, ULONG)); -DLL_DECLARE(WINAPI, BOOL, HidD_SetFeature, (HANDLE, PVOID, ULONG)); -DLL_DECLARE(WINAPI, BOOL, HidD_GetFeature, (HANDLE, PVOID, ULONG)); -DLL_DECLARE(WINAPI, BOOL, HidD_GetPhysicalDescriptor, (HANDLE, PVOID, ULONG)); -DLL_DECLARE(WINAPI, BOOL, HidD_GetInputReport, (HANDLE, PVOID, ULONG)); -DLL_DECLARE(WINAPI, BOOL, HidD_SetOutputReport, (HANDLE, PVOID, ULONG)); -DLL_DECLARE(WINAPI, BOOL, HidD_FlushQueue, (HANDLE)); -DLL_DECLARE(WINAPI, BOOL, HidP_GetValueCaps, (HIDP_REPORT_TYPE, PHIDP_VALUE_CAPS, PULONG, PHIDP_PREPARSED_DATA)); +DLL_DECLARE_HANDLE(hid); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetAttributes, (HANDLE, PHIDD_ATTRIBUTES)); +DLL_DECLARE_FUNC(WINAPI, VOID, HidD_GetHidGuid, (LPGUID)); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetPreparsedData, (HANDLE, PHIDP_PREPARSED_DATA *)); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_FreePreparsedData, (PHIDP_PREPARSED_DATA)); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetManufacturerString, (HANDLE, PVOID, ULONG)); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetProductString, (HANDLE, PVOID, ULONG)); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetSerialNumberString, (HANDLE, PVOID, ULONG)); +DLL_DECLARE_FUNC(WINAPI, LONG, HidP_GetCaps, (PHIDP_PREPARSED_DATA, PHIDP_CAPS)); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetNumInputBuffers, (HANDLE, ULONG)); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetFeature, (HANDLE, PVOID, ULONG)); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetFeature, (HANDLE, PVOID, ULONG)); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetPhysicalDescriptor, (HANDLE, PVOID, ULONG)); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetInputReport, (HANDLE, PVOID, ULONG)); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetOutputReport, (HANDLE, PVOID, ULONG)); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_FlushQueue, (HANDLE)); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidP_GetValueCaps, (HIDP_REPORT_TYPE, PHIDP_VALUE_CAPS, PULONG, PHIDP_PREPARSED_DATA)); \ No newline at end of file diff --git a/libusb/version_nano.h b/libusb/version_nano.h index a3f68ad90..b50520477 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11044 +#define LIBUSB_NANO 11045 From c37f8f4b143a41cf16302b7cdba2dbfbb01b9eef Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Thu, 28 Jan 2016 00:41:02 -0800 Subject: [PATCH 126/222] Misc: Minor stylistic improvements to libusbi.h Signed-off-by: Chris Dickens --- libusb/libusbi.h | 109 ++++++++++++++++++++++-------------------- libusb/version_nano.h | 2 +- 2 files changed, 58 insertions(+), 53 deletions(-) diff --git a/libusb/libusbi.h b/libusb/libusbi.h index 2d229da39..9ffee409d 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -52,14 +52,14 @@ extern "C" { #endif -#define DEVICE_DESC_LENGTH 18 +#define DEVICE_DESC_LENGTH 18 #define USB_MAXENDPOINTS 32 #define USB_MAXINTERFACES 32 #define USB_MAXCONFIG 8 /* Backend specific capabilities */ -#define USBI_CAP_HAS_HID_ACCESS 0x00010000 +#define USBI_CAP_HAS_HID_ACCESS 0x00010000 #define USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER 0x00020000 /* Maximum number of bytes in a log line */ @@ -68,10 +68,10 @@ extern "C" { #define USBI_LOG_LINE_END "\n" /* The following is used to silence warnings for unused variables */ -#define UNUSED(var) do { (void)(var); } while(0) +#define UNUSED(var) do { (void)(var); } while(0) #if !defined(ARRAYSIZE) -#define ARRAYSIZE(array) (sizeof(array)/sizeof(array[0])) +#define ARRAYSIZE(array) (sizeof(array) / sizeof(array[0])) #endif struct list_head { @@ -96,14 +96,14 @@ struct list_head { * type - the type of the first parameter */ #define list_for_each_entry(pos, head, member, type) \ - for (pos = list_entry((head)->next, type, member); \ - &pos->member != (head); \ + for (pos = list_entry((head)->next, type, member); \ + &pos->member != (head); \ pos = list_entry(pos->member.next, type, member)) -#define list_for_each_entry_safe(pos, n, head, member, type) \ - for (pos = list_entry((head)->next, type, member), \ - n = list_entry(pos->member.next, type, member); \ - &pos->member != (head); \ +#define list_for_each_entry_safe(pos, n, head, member, type) \ + for (pos = list_entry((head)->next, type, member), \ + n = list_entry(pos->member.next, type, member); \ + &pos->member != (head); \ pos = n, n = list_entry(n->member.next, type, member)) #define list_empty(entry) ((entry)->next == (entry)) @@ -147,9 +147,9 @@ static inline void *usbi_reallocf(void *ptr, size_t size) return ret; } -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *mptr = (ptr); \ - (type *)( (char *)mptr - offsetof(type,member) );}) +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *mptr = (ptr); \ + (type *)( (char *)mptr - offsetof(type,member) );}) #ifndef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) @@ -168,11 +168,11 @@ static inline void *usbi_reallocf(void *ptr, size_t size) /* Some platforms don't have this define */ #ifndef TIMESPEC_TO_TIMEVAL -#define TIMESPEC_TO_TIMEVAL(tv, ts) \ - do { \ - (tv)->tv_sec = (TIMEVAL_TV_SEC_TYPE) (ts)->tv_sec; \ - (tv)->tv_usec = (ts)->tv_nsec / 1000; \ - } while (0) +#define TIMESPEC_TO_TIMEVAL(tv, ts) \ + do { \ + (tv)->tv_sec = (TIMEVAL_TV_SEC_TYPE) (ts)->tv_sec; \ + (tv)->tv_usec = (ts)->tv_nsec / 1000; \ + } while (0) #endif void usbi_log(struct libusb_context *ctx, enum libusb_log_level level, @@ -198,49 +198,54 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, #else /* !defined(_MSC_VER) || _MSC_VER >= 1400 */ #ifdef ENABLE_LOGGING -#define LOG_BODY(ctxt, level) \ -{ \ - va_list args; \ - va_start (args, format); \ - usbi_log_v(ctxt, level, "", format, args); \ - va_end(args); \ +#define LOG_BODY(ctxt, level) \ +{ \ + va_list args; \ + va_start(args, format); \ + usbi_log_v(ctxt, level, "", format, args); \ + va_end(args); \ } #else -#define LOG_BODY(ctxt, level) do { (void)(ctxt); } while(0) +#define LOG_BODY(ctxt, level) \ +{ \ + (void)(ctxt); \ +} #endif -static inline void usbi_info(struct libusb_context *ctx, const char *format, - ...) - LOG_BODY(ctx,LIBUSB_LOG_LEVEL_INFO) -static inline void usbi_warn(struct libusb_context *ctx, const char *format, - ...) - LOG_BODY(ctx,LIBUSB_LOG_LEVEL_WARNING) -static inline void usbi_err( struct libusb_context *ctx, const char *format, - ...) - LOG_BODY(ctx,LIBUSB_LOG_LEVEL_ERROR) +static inline void usbi_info(struct libusb_context *ctx, const char *format, ...) + LOG_BODY(ctx, LIBUSB_LOG_LEVEL_INFO) +static inline void usbi_warn(struct libusb_context *ctx, const char *format, ...) + LOG_BODY(ctx, LIBUSB_LOG_LEVEL_WARNING) +static inline void usbi_err(struct libusb_context *ctx, const char *format, ...) + LOG_BODY(ctx, LIBUSB_LOG_LEVEL_ERROR) static inline void usbi_dbg(const char *format, ...) - LOG_BODY(NULL,LIBUSB_LOG_LEVEL_DEBUG) + LOG_BODY(NULL, LIBUSB_LOG_LEVEL_DEBUG) #endif /* !defined(_MSC_VER) || _MSC_VER >= 1400 */ -#define USBI_GET_CONTEXT(ctx) if (!(ctx)) (ctx) = usbi_default_context -#define DEVICE_CTX(dev) ((dev)->ctx) -#define HANDLE_CTX(handle) (DEVICE_CTX((handle)->dev)) -#define TRANSFER_CTX(transfer) (HANDLE_CTX((transfer)->dev_handle)) +#define USBI_GET_CONTEXT(ctx) \ + do { \ + if (!(ctx)) \ + (ctx) = usbi_default_context; \ + } while(0) + +#define DEVICE_CTX(dev) ((dev)->ctx) +#define HANDLE_CTX(handle) (DEVICE_CTX((handle)->dev)) +#define TRANSFER_CTX(transfer) (HANDLE_CTX((transfer)->dev_handle)) #define ITRANSFER_CTX(transfer) \ (TRANSFER_CTX(USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer))) -#define IS_EPIN(ep) (0 != ((ep) & LIBUSB_ENDPOINT_IN)) -#define IS_EPOUT(ep) (!IS_EPIN(ep)) -#define IS_XFERIN(xfer) (0 != ((xfer)->endpoint & LIBUSB_ENDPOINT_IN)) -#define IS_XFEROUT(xfer) (!IS_XFERIN(xfer)) +#define IS_EPIN(ep) (0 != ((ep) & LIBUSB_ENDPOINT_IN)) +#define IS_EPOUT(ep) (!IS_EPIN(ep)) +#define IS_XFERIN(xfer) (0 != ((xfer)->endpoint & LIBUSB_ENDPOINT_IN)) +#define IS_XFEROUT(xfer) (!IS_XFERIN(xfer)) /* Internal abstraction for thread synchronization */ #if defined(THREADS_POSIX) #include "os/threads_posix.h" #elif defined(OS_WINDOWS) || defined(OS_WINCE) -#include +#include "os/threads_windows.h" #endif extern struct libusb_context *usbi_default_context; @@ -403,8 +408,8 @@ struct libusb_device_handle { }; enum { - USBI_CLOCK_MONOTONIC, - USBI_CLOCK_REALTIME + USBI_CLOCK_MONOTONIC, + USBI_CLOCK_REALTIME }; /* in-memory transfer layout: @@ -469,11 +474,11 @@ enum usbi_transfer_flags { USBI_TRANSFER_TIMEOUT_HANDLED = 1 << 7, }; -#define USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \ - ((struct libusb_transfer *)(((unsigned char *)(transfer)) \ +#define USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \ + ((struct libusb_transfer *)(((unsigned char *)(transfer)) \ + sizeof(struct usbi_transfer))) -#define LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer) \ - ((struct usbi_transfer *)(((unsigned char *)(transfer)) \ +#define LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer) \ + ((struct usbi_transfer *)(((unsigned char *)(transfer)) \ - sizeof(struct usbi_transfer))) static inline void *usbi_transfer_get_os_priv(struct usbi_transfer *transfer) @@ -488,8 +493,8 @@ static inline void *usbi_transfer_get_os_priv(struct usbi_transfer *transfer) /* All standard descriptors have these 2 fields in common */ struct usb_descriptor_header { - uint8_t bLength; - uint8_t bDescriptorType; + uint8_t bLength; + uint8_t bDescriptorType; }; /* shared data and functions */ diff --git a/libusb/version_nano.h b/libusb/version_nano.h index b50520477..d0add8408 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11045 +#define LIBUSB_NANO 11046 From a57f0ec1d92dc58b4872814eec1ee30152cfab29 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Thu, 28 Jan 2016 00:43:15 -0800 Subject: [PATCH 127/222] Windows (winusb): Fix build break introduced in c8f71151 due to typo Signed-off-by: Chris Dickens --- libusb/os/windows_winusb.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index f790736ea..fec6ebe36 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -836,7 +836,7 @@ static int windows_init(struct libusb_context *ctx) init_exit: // Holds semaphore here. if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? for (i = 0; i < USB_API_MAX; i++) - usb_api_backend[i].exit(SUBAPI_NOT_SET); + usb_api_backend[i].exit(SUB_API_NOTSET); exit_dlls(); exit_polling(); windows_common_exit(); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index d0add8408..ff9977abe 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11046 +#define LIBUSB_NANO 11047 From 33f51ea92fba4b69159924b565da53f6b57e8830 Mon Sep 17 00:00:00 2001 From: KIMURA Masaru Date: Thu, 28 Jan 2016 16:25:37 +0900 Subject: [PATCH 128/222] Windows: Move definitions for Cygwin. Closes #145 Signed-off-by: Chris Dickens --- libusb/os/windows_common.h | 8 ++++++++ libusb/os/windows_winusb.h | 8 -------- libusb/version_nano.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libusb/os/windows_common.h b/libusb/os/windows_common.h index 0149e11bf..17a192372 100644 --- a/libusb/os/windows_common.h +++ b/libusb/os/windows_common.h @@ -37,6 +37,14 @@ #define false FALSE #endif +#if defined(__CYGWIN__ ) +#define _stricmp strcasecmp +#define _snprintf snprintf +#define _strdup strdup +// _beginthreadex is MSVCRT => unavailable for cygwin. Fallback to using CreateThread +#define _beginthreadex(a, b, c, d, e, f) CreateThread(a, b, (LPTHREAD_START_ROUTINE)c, d, e, (LPDWORD)f) +#endif + #define safe_free(p) do {if (p != NULL) {free((void*)p); p = NULL;}} while(0) #define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0) #define safe_min(a, b) MIN((size_t)(a), (size_t)(b)) diff --git a/libusb/os/windows_winusb.h b/libusb/os/windows_winusb.h index 047f2e269..d544a7f9e 100644 --- a/libusb/os/windows_winusb.h +++ b/libusb/os/windows_winusb.h @@ -48,14 +48,6 @@ #define FACILITY_SETUPAPI 15 #endif -#if defined(__CYGWIN__ ) -#define _stricmp strcasecmp -#define _snprintf snprintf -#define _strdup strdup -// _beginthreadex is MSVCRT => unavailable for cygwin. Fallback to using CreateThread -#define _beginthreadex(a, b, c, d, e, f) CreateThread(a, b, (LPTHREAD_START_ROUTINE)c, d, e, (LPDWORD)f) -#endif - #define MAX_CTRL_BUFFER_LENGTH 4096 #define MAX_USB_DEVICES 256 #define MAX_USB_STRING_LENGTH 128 diff --git a/libusb/version_nano.h b/libusb/version_nano.h index ff9977abe..b5eb18691 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11047 +#define LIBUSB_NANO 11048 From 448584afd1b012210e8e9038f888597588450d7a Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Sat, 30 Jan 2016 00:52:28 -0800 Subject: [PATCH 129/222] Windows: Fix style issues in threading code Also moves private structure definition outside of header file. Signed-off-by: Chris Dickens --- libusb/os/threads_windows.c | 264 +++++++++++++++++++++++------------- libusb/os/threads_windows.h | 53 +++----- libusb/version_nano.h | 2 +- 3 files changed, 189 insertions(+), 130 deletions(-) diff --git a/libusb/os/threads_windows.c b/libusb/os/threads_windows.c index e3fd910fb..933807e0c 100644 --- a/libusb/os/threads_windows.c +++ b/libusb/os/threads_windows.c @@ -22,134 +22,183 @@ #include #include -#include #include "libusbi.h" extern const uint64_t epoch_time; -int usbi_mutex_init(usbi_mutex_t *mutex, - const usbi_mutexattr_t *attr) { - UNUSED(attr); - if(! mutex) return ((errno=EINVAL)); - *mutex = CreateMutex(NULL, FALSE, NULL); - if(!*mutex) return ((errno=ENOMEM)); +struct usbi_cond_perthread { + struct list_head list; + DWORD tid; + HANDLE event; +}; + +int usbi_mutex_static_lock(usbi_mutex_static_t *mutex) +{ + if (!mutex) + return EINVAL; + while (InterlockedExchange(mutex, 1) == 1) + SleepEx(0, TRUE); return 0; } -int usbi_mutex_destroy(usbi_mutex_t *mutex) { - // It is not clear if CloseHandle failure is due to failure to unlock. - // If so, this should be errno=EBUSY. - if(!mutex || !CloseHandle(*mutex)) return ((errno=EINVAL)); - *mutex = NULL; +int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) +{ + if (!mutex) + return EINVAL; + InterlockedExchange(mutex, 0); return 0; } -int usbi_mutex_trylock(usbi_mutex_t *mutex) { - DWORD result; - if(!mutex) return ((errno=EINVAL)); - result = WaitForSingleObject(*mutex, 0); - if(result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) - return 0; // acquired (ToDo: check that abandoned is ok) - if(result == WAIT_TIMEOUT) - return ((errno=EBUSY)); - return ((errno=EINVAL)); // don't know how this would happen - // so don't know proper errno + +int usbi_mutex_init(usbi_mutex_t *mutex, const usbi_mutexattr_t *attr) +{ + UNUSED(attr); + if (!mutex) + return EINVAL; + *mutex = CreateMutex(NULL, FALSE, NULL); + if (!*mutex) + return ENOMEM; + return 0; } -int usbi_mutex_lock(usbi_mutex_t *mutex) { + +int usbi_mutex_lock(usbi_mutex_t *mutex) +{ DWORD result; - if(!mutex) return ((errno=EINVAL)); + + if (!mutex) + return EINVAL; result = WaitForSingleObject(*mutex, INFINITE); - if(result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) + if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) return 0; // acquired (ToDo: check that abandoned is ok) - return ((errno=EINVAL)); // don't know how this would happen - // so don't know proper errno + else + return EINVAL; // don't know how this would happen + // so don't know proper errno } -int usbi_mutex_unlock(usbi_mutex_t *mutex) { - if(!mutex) return ((errno=EINVAL)); - if(!ReleaseMutex(*mutex)) return ((errno=EPERM )); - return 0; + +int usbi_mutex_unlock(usbi_mutex_t *mutex) +{ + if (!mutex) + return EINVAL; + if (ReleaseMutex(*mutex)) + return 0; + else + return EPERM; } -int usbi_mutex_static_lock(usbi_mutex_static_t *mutex) { - if(!mutex) return ((errno=EINVAL)); - while (InterlockedExchange((LONG *)mutex, 1) == 1) { - SleepEx(0, TRUE); - } - return 0; +int usbi_mutex_trylock(usbi_mutex_t *mutex) +{ + DWORD result; + + if (!mutex) + return EINVAL; + result = WaitForSingleObject(*mutex, 0); + if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) + return 0; // acquired (ToDo: check that abandoned is ok) + else if (result == WAIT_TIMEOUT) + return EBUSY; + else + return EINVAL; // don't know how this would happen + // so don't know proper error } -int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) { - if(!mutex) return ((errno=EINVAL)); - *mutex = 0; + +int usbi_mutex_destroy(usbi_mutex_t *mutex) +{ + // It is not clear if CloseHandle failure is due to failure to unlock. + // If so, this should be errno=EBUSY. + if (!mutex || !CloseHandle(*mutex)) + return EINVAL; + *mutex = NULL; return 0; } -int usbi_cond_init(usbi_cond_t *cond, - const usbi_condattr_t *attr) { +int usbi_cond_init(usbi_cond_t *cond, const usbi_condattr_t *attr) +{ UNUSED(attr); - if(!cond) return ((errno=EINVAL)); - list_init(&cond->waiters ); + if (!cond) + return EINVAL; + list_init(&cond->waiters); list_init(&cond->not_waiting); return 0; } -int usbi_cond_destroy(usbi_cond_t *cond) { + +int usbi_cond_destroy(usbi_cond_t *cond) +{ // This assumes no one is using this anymore. The check MAY NOT BE safe. - struct usbi_cond_perthread *pos, *next_pos = NULL; - if(!cond) return ((errno=EINVAL)); - if(!list_empty(&cond->waiters)) return ((errno=EBUSY )); // (!see above!) + struct usbi_cond_perthread *pos, *next_pos; + + if(!cond) + return EINVAL; + if (!list_empty(&cond->waiters)) + return EBUSY; // (!see above!) list_for_each_entry_safe(pos, next_pos, &cond->not_waiting, list, struct usbi_cond_perthread) { CloseHandle(pos->event); list_del(&pos->list); free(pos); } - return 0; } -int usbi_cond_broadcast(usbi_cond_t *cond) { +int usbi_cond_broadcast(usbi_cond_t *cond) +{ // Assumes mutex is locked; this is not in keeping with POSIX spec, but // libusb does this anyway, so we simplify by not adding more sync // primitives to the CV definition! int fail = 0; struct usbi_cond_perthread *pos; - if(!cond) return ((errno=EINVAL)); + + if (!cond) + return EINVAL; list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread) { - if(!SetEvent(pos->event)) + if (!SetEvent(pos->event)) fail = 1; } // The wait function will remove its respective item from the list. - return fail ? ((errno=EINVAL)) : 0; + return fail ? EINVAL : 0; } -int usbi_cond_signal(usbi_cond_t *cond) { + +int usbi_cond_signal(usbi_cond_t *cond) +{ // Assumes mutex is locked; this is not in keeping with POSIX spec, but // libusb does this anyway, so we simplify by not adding more sync // primitives to the CV definition! struct usbi_cond_perthread *pos; - if(!cond) return ((errno=EINVAL)); - if(list_empty(&cond->waiters)) return 0; // no one to wakeup. - pos = list_entry(&cond->waiters.next, struct usbi_cond_perthread, list); + + if (!cond) + return EINVAL; + if (list_empty(&cond->waiters)) + return 0; // no one to wakeup. + pos = list_first_entry(&cond->waiters, struct usbi_cond_perthread, list); // The wait function will remove its respective item from the list. - return SetEvent(pos->event) ? 0 : ((errno=EINVAL)); + if (SetEvent(pos->event)) + return 0; + else + return EINVAL; } + __inline static int usbi_cond_intwait(usbi_cond_t *cond, - usbi_mutex_t *mutex, - DWORD timeout_ms) { + usbi_mutex_t *mutex, DWORD timeout_ms) +{ struct usbi_cond_perthread *pos; - int found = 0, r; - DWORD r2,tid = GetCurrentThreadId(); - if(!cond || !mutex) return ((errno=EINVAL)); + int r, found = 0; + DWORD r2, tid = GetCurrentThreadId(); + + if (!cond || !mutex) + return EINVAL; list_for_each_entry(pos, &cond->not_waiting, list, struct usbi_cond_perthread) { if(tid == pos->tid) { found = 1; break; } } - if(!found) { - pos = (struct usbi_cond_perthread*) calloc(1, sizeof(struct usbi_cond_perthread)); - if(!pos) return ((errno=ENOMEM)); // This errno is not POSIX-allowed. + + if (!found) { + pos = calloc(1, sizeof(struct usbi_cond_perthread)); + if (!pos) + return ENOMEM; // This errno is not POSIX-allowed. pos->tid = tid; pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset. - if(!pos->event) { + if (!pos->event) { free(pos); - return ((errno=ENOMEM)); + return ENOMEM; } list_add(&pos->list, &cond->not_waiting); } @@ -158,25 +207,33 @@ __inline static int usbi_cond_intwait(usbi_cond_t *cond, list_add(&pos->list, &cond->waiters); r = usbi_mutex_unlock(mutex); - if(r) return r; + if (r) + return r; + r2 = WaitForSingleObject(pos->event, timeout_ms); - r = usbi_mutex_lock(mutex); - if(r) return r; + r = usbi_mutex_lock(mutex); + if (r) + return r; list_del(&pos->list); list_add(&pos->list, &cond->not_waiting); - if(r2 == WAIT_TIMEOUT) return ((errno=ETIMEDOUT)); - - return 0; + if (r2 == WAIT_OBJECT_0) + return 0; + else if (r2 == WAIT_TIMEOUT) + return ETIMEDOUT; + else + return EINVAL; } // N.B.: usbi_cond_*wait() can also return ENOMEM, even though pthread_cond_*wait cannot! -int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) { +int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) +{ return usbi_cond_intwait(cond, mutex, INFINITE); } + int usbi_cond_timedwait(usbi_cond_t *cond, - usbi_mutex_t *mutex, - const struct timespec *abstime) { + usbi_mutex_t *mutex, const struct timespec *abstime) +{ FILETIME filetime; ULARGE_INTEGER rtime; struct timeval targ_time, cur_time, delta_time; @@ -192,45 +249,58 @@ int usbi_cond_timedwait(usbi_cond_t *cond, rtime.HighPart = filetime.dwHighDateTime; rtime.QuadPart -= epoch_time; cur_time_ns.tv_sec = (long)(rtime.QuadPart / 10000000); - cur_time_ns.tv_nsec = (long)((rtime.QuadPart % 10000000)*100); + cur_time_ns.tv_nsec = (long)((rtime.QuadPart % 10000000) * 100); TIMESPEC_TO_TIMEVAL(&cur_time, &cur_time_ns); TIMESPEC_TO_TIMEVAL(&targ_time, abstime); timersub(&targ_time, &cur_time, &delta_time); - if(delta_time.tv_sec < 0) // abstime already passed? + if (delta_time.tv_sec < 0) { + // abstime already passed? millis = 0; - else { - millis = delta_time.tv_usec/1000; - millis += delta_time.tv_sec *1000; - if (delta_time.tv_usec % 1000) // round up to next millisecond - millis++; + } else { + millis = delta_time.tv_usec / 1000; + millis += delta_time.tv_sec * 1000; + if (delta_time.tv_usec % 1000) + millis++; // round up to next millisecond } return usbi_cond_intwait(cond, mutex, millis); } -int usbi_tls_key_create(usbi_tls_key_t *key, void (*destructor)(void *)) { +int usbi_tls_key_create(usbi_tls_key_t *key, void (*destructor)(void *)) +{ UNUSED(destructor); - if(!key) return ((errno=EINVAL)); + if (!key) + return EINVAL; *key = TlsAlloc(); - if (*key == TLS_OUT_OF_INDEXES) return ((errno=ENOMEM)); - return 0; + if (*key == TLS_OUT_OF_INDEXES) + return ENOMEM; + else + return 0; } -void *usbi_tls_key_get(usbi_tls_key_t key) { +void *usbi_tls_key_get(usbi_tls_key_t key) +{ return TlsGetValue(key); } -int usbi_tls_key_set(usbi_tls_key_t key, const void *value) { - if (!TlsSetValue(key, (LPVOID)value)) return ((errno=EINVAL)); - return 0; +int usbi_tls_key_set(usbi_tls_key_t key, const void *value) +{ + if (TlsSetValue(key, (LPVOID)value)) + return 0; + else + return EINVAL; } -int usbi_tls_key_delete(usbi_tls_key_t key) { - if (!TlsFree(key)) return ((errno=EINVAL)); - return 0; +int usbi_tls_key_delete(usbi_tls_key_t key) +{ + if (TlsFree(key)) + return 0; + else + return EINVAL; } -int usbi_get_tid(void) { - return GetCurrentThreadId(); +int usbi_get_tid(void) +{ + return (int)GetCurrentThreadId(); } diff --git a/libusb/os/threads_windows.h b/libusb/os/threads_windows.h index 6a35d9da6..39dddc866 100644 --- a/libusb/os/threads_windows.h +++ b/libusb/os/threads_windows.h @@ -21,32 +21,25 @@ #ifndef LIBUSB_THREADS_WINDOWS_H #define LIBUSB_THREADS_WINDOWS_H -#define usbi_mutex_static_t volatile LONG -#define USBI_MUTEX_INITIALIZER 0 +#define usbi_mutex_static_t volatile LONG +#define USBI_MUTEX_INITIALIZER 0 -#define usbi_mutex_t HANDLE +#define usbi_mutex_t HANDLE -struct usbi_cond_perthread { - struct list_head list; - DWORD tid; - HANDLE event; -}; -struct usbi_cond_t_ { +typedef struct usbi_cond { // Every time a thread touches the CV, it winds up in one of these lists. - // It stays there until the CV is destroyed, even if the thread - // terminates. + // It stays there until the CV is destroyed, even if the thread terminates. struct list_head waiters; struct list_head not_waiting; -}; -typedef struct usbi_cond_t_ usbi_cond_t; +} usbi_cond_t; // We *were* getting timespec from pthread.h: #if (!defined(HAVE_STRUCT_TIMESPEC) && !defined(_TIMESPEC_DEFINED)) #define HAVE_STRUCT_TIMESPEC 1 #define _TIMESPEC_DEFINED 1 struct timespec { - long tv_sec; - long tv_nsec; + long tv_sec; + long tv_nsec; }; #endif /* HAVE_STRUCT_TIMESPEC | _TIMESPEC_DEFINED */ @@ -55,38 +48,34 @@ struct timespec { # define ETIMEDOUT 10060 /* This is the value in winsock.h. */ #endif -#define usbi_mutexattr_t void -#define usbi_condattr_t void -#define usbi_tls_key_t DWORD - -// all Windows mutexes are recursive -#define usbi_mutex_init_recursive(mutex, attr) usbi_mutex_init((mutex), (attr)) +#define usbi_mutexattr_t void +#define usbi_condattr_t void +#define usbi_tls_key_t DWORD int usbi_mutex_static_lock(usbi_mutex_static_t *mutex); int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex); - -int usbi_mutex_init(usbi_mutex_t *mutex, - const usbi_mutexattr_t *attr); +int usbi_mutex_init(usbi_mutex_t *mutex, const usbi_mutexattr_t *attr); int usbi_mutex_lock(usbi_mutex_t *mutex); int usbi_mutex_unlock(usbi_mutex_t *mutex); int usbi_mutex_trylock(usbi_mutex_t *mutex); int usbi_mutex_destroy(usbi_mutex_t *mutex); -int usbi_cond_init(usbi_cond_t *cond, - const usbi_condattr_t *attr); -int usbi_cond_destroy(usbi_cond_t *cond); +int usbi_cond_init(usbi_cond_t *cond, const usbi_condattr_t *attr); int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex); int usbi_cond_timedwait(usbi_cond_t *cond, - usbi_mutex_t *mutex, - const struct timespec *abstime); + usbi_mutex_t *mutex, const struct timespec *abstime); int usbi_cond_broadcast(usbi_cond_t *cond); int usbi_cond_signal(usbi_cond_t *cond); +int usbi_cond_destroy(usbi_cond_t *cond); -int usbi_tls_key_create(usbi_tls_key_t *key, void (*destructor)(void *)); +int usbi_tls_key_create(usbi_tls_key_t *key, void (*destructor)(void *)); void *usbi_tls_key_get(usbi_tls_key_t key); -int usbi_tls_key_set(usbi_tls_key_t key, const void *value); -int usbi_tls_key_delete(usbi_tls_key_t key); +int usbi_tls_key_set(usbi_tls_key_t key, const void *value); +int usbi_tls_key_delete(usbi_tls_key_t key); + +// all Windows mutexes are recursive +#define usbi_mutex_init_recursive(mutex, attr) usbi_mutex_init((mutex), (attr)) int usbi_get_tid(void); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index b5eb18691..9ea07cdf5 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11048 +#define LIBUSB_NANO 11049 From 3f4df898b7b7998d5c1353c2d03c7258c17f0489 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Thu, 28 Jan 2016 14:15:29 -0800 Subject: [PATCH 130/222] linux_netlink: Remove unnecessary header includes and conditionals We always require and do not need . Signed-off-by: Chris Dickens --- configure.ac | 6 ++---- libusb/os/linux_netlink.c | 11 ----------- libusb/version_nano.h | 2 +- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index ec71e6225..4e35bf677 100644 --- a/configure.ac +++ b/configure.ac @@ -113,14 +113,12 @@ linux) AC_CHECK_LIB([udev], [udev_new], [], [AC_ERROR(["udev support requested but libudev not installed"])]) AC_DEFINE(USE_UDEV, 1, [Use udev for device enumeration/hotplug]) else - AC_CHECK_HEADERS([asm/types.h sys/socket.h], [], []) - AC_CHECK_HEADERS([linux/netlink.h linux/filter.h], [], [AC_ERROR(["Linux netlink headers not found"])], [ + AC_CHECK_HEADERS([asm/types.h], [], []) + AC_CHECK_HEADERS([sys/socket.h linux/netlink.h], [], [AC_ERROR(["Linux netlink headers not found"])], [ #ifdef HAVE_ASM_TYPES_H #include #endif -#ifdef HAVE_SYS_SOCKET_H #include -#endif ]) fi AC_SUBST(USE_UDEV) diff --git a/libusb/os/linux_netlink.c b/libusb/os/linux_netlink.c index 5976e9144..5ad1e6220 100644 --- a/libusb/os/linux_netlink.c +++ b/libusb/os/linux_netlink.c @@ -36,19 +36,8 @@ #include #endif -#ifdef HAVE_SYS_SOCKET_H #include -#endif - -#include - -#ifdef HAVE_LINUX_NETLINK_H #include -#endif - -#ifdef HAVE_LINUX_FILTER_H -#include -#endif #include "libusbi.h" #include "linux_usbfs.h" diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 9ea07cdf5..b7a0eb17f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11049 +#define LIBUSB_NANO 11050 From ffb5926a30c07be8775c0df046672b427756cf85 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Thu, 28 Jan 2016 14:24:09 -0800 Subject: [PATCH 131/222] linux_netlink: Add useful debug messages and clean up error handling Also addresses some minor whitespace and stylistic issues. Signed-off-by: Chris Dickens --- libusb/os/linux_netlink.c | 168 ++++++++++++++++++++------------------ libusb/version_nano.h | 2 +- 2 files changed, 91 insertions(+), 79 deletions(-) diff --git a/libusb/os/linux_netlink.c b/libusb/os/linux_netlink.c index 5ad1e6220..501a94dbe 100644 --- a/libusb/os/linux_netlink.c +++ b/libusb/os/linux_netlink.c @@ -22,14 +22,14 @@ #include -#include -#include +#include #include #include #include #include #include #include +#include #include #ifdef HAVE_ASM_TYPES_H @@ -50,7 +50,7 @@ static pthread_t libusb_linux_event_thread; static void *linux_netlink_event_thread_main(void *arg); -static struct sockaddr_nl snl = { .nl_family=AF_NETLINK, .nl_groups=KERNEL }; +static struct sockaddr_nl snl = { .nl_family = AF_NETLINK, .nl_groups = KERNEL }; static int set_fd_cloexec_nb(int fd) { @@ -58,22 +58,30 @@ static int set_fd_cloexec_nb(int fd) #if defined(FD_CLOEXEC) flags = fcntl(fd, F_GETFD); - if (0 > flags) { + if (flags == -1) { + usbi_err(NULL, "failed to get netlink fd flags (%d)", errno); return -1; } if (!(flags & FD_CLOEXEC)) { - fcntl(fd, F_SETFD, flags | FD_CLOEXEC); + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { + usbi_err(NULL, "failed to set netlink fd flags (%d)", errno); + return -1; + } } #endif flags = fcntl(fd, F_GETFL); - if (0 > flags) { + if (flags == -1) { + usbi_err(NULL, "failed to get netlink fd status flags (%d)", errno); return -1; } if (!(flags & O_NONBLOCK)) { - fcntl(fd, F_SETFL, flags | O_NONBLOCK); + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { + usbi_err(NULL, "failed to set netlink fd status flags (%d)", errno); + return -1; + } } return 0; @@ -84,8 +92,6 @@ int linux_netlink_start_event_monitor(void) int socktype = SOCK_RAW; int ret; - snl.nl_groups = KERNEL; - #if defined(SOCK_CLOEXEC) socktype |= SOCK_CLOEXEC; #endif @@ -94,25 +100,24 @@ int linux_netlink_start_event_monitor(void) #endif linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT); - if (-1 == linux_netlink_socket && EINVAL == errno) { + if (linux_netlink_socket == -1 && errno == EINVAL) { + usbi_dbg("failed to create netlink socket of type %d, attempting SOCK_RAW", socktype); linux_netlink_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT); } - if (-1 == linux_netlink_socket) { - return LIBUSB_ERROR_OTHER; + if (linux_netlink_socket == -1) { + usbi_err(NULL, "failed to create netlink socket (%d)", errno); + goto err; } - ret = set_fd_cloexec_nb (linux_netlink_socket); - if (0 != ret) { - close (linux_netlink_socket); - linux_netlink_socket = -1; - return LIBUSB_ERROR_OTHER; - } + ret = set_fd_cloexec_nb(linux_netlink_socket); + if (ret == -1) + goto err_close_socket; - ret = bind(linux_netlink_socket, (struct sockaddr *) &snl, sizeof(snl)); - if (0 != ret) { - close(linux_netlink_socket); - return LIBUSB_ERROR_OTHER; + ret = bind(linux_netlink_socket, (struct sockaddr *)&snl, sizeof(snl)); + if (ret == -1) { + usbi_err(NULL, "failed to bind netlink socket (%d)", errno); + goto err_close_socket; } /* TODO -- add authentication */ @@ -120,38 +125,43 @@ int linux_netlink_start_event_monitor(void) ret = usbi_pipe(netlink_control_pipe); if (ret) { - usbi_err(NULL, "could not create netlink control pipe"); - close(linux_netlink_socket); - return LIBUSB_ERROR_OTHER; + usbi_err(NULL, "failed to create netlink control pipe"); + goto err_close_socket; } ret = pthread_create(&libusb_linux_event_thread, NULL, linux_netlink_event_thread_main, NULL); - if (0 != ret) { - close(netlink_control_pipe[0]); - close(netlink_control_pipe[1]); - close(linux_netlink_socket); - return LIBUSB_ERROR_OTHER; + if (ret != 0) { + usbi_err(NULL, "failed to create netlink event thread (%d)", ret); + goto err_close_pipe; } return LIBUSB_SUCCESS; + +err_close_pipe: + close(netlink_control_pipe[0]); + close(netlink_control_pipe[1]); + netlink_control_pipe[0] = -1; + netlink_control_pipe[1] = -1; +err_close_socket: + close(linux_netlink_socket); + linux_netlink_socket = -1; +err: + return LIBUSB_ERROR_OTHER; } int linux_netlink_stop_event_monitor(void) { - int r; char dummy = 1; + ssize_t r; - if (-1 == linux_netlink_socket) { - /* already closed. nothing to do */ - return LIBUSB_SUCCESS; - } + assert(linux_netlink_socket != -1); /* Write some dummy data to the control pipe and * wait for the thread to exit */ r = usbi_write(netlink_control_pipe[1], &dummy, sizeof(dummy)); - if (r <= 0) { + if (r <= 0) usbi_warn(NULL, "netlink control pipe signal failed"); - } + pthread_join(libusb_linux_event_thread, NULL); close(linux_netlink_socket); @@ -166,14 +176,14 @@ int linux_netlink_stop_event_monitor(void) return LIBUSB_SUCCESS; } -static const char *netlink_message_parse (const char *buffer, size_t len, const char *key) +static const char *netlink_message_parse(const char *buffer, size_t len, const char *key) { size_t keylen = strlen(key); size_t offset; - for (offset = 0 ; offset < len && '\0' != buffer[offset] ; offset += strlen(buffer + offset) + 1) { - if (0 == strncmp(buffer + offset, key, keylen) && - '=' == buffer[offset + keylen]) { + for (offset = 0; offset < len && buffer[offset] != '\0'; offset += strlen(buffer + offset) + 1) { + if (strncmp(buffer + offset, key, keylen) == 0 && + buffer[offset + keylen] == '=') { return buffer + offset + keylen + 1; } } @@ -182,8 +192,9 @@ static const char *netlink_message_parse (const char *buffer, size_t len, const } /* parse parts of netlink message common to both libudev and the kernel */ -static int linux_netlink_parse(char *buffer, size_t len, int *detached, const char **sys_name, - uint8_t *busnum, uint8_t *devaddr) { +static int linux_netlink_parse(const char *buffer, size_t len, int *detached, + const char **sys_name, uint8_t *busnum, uint8_t *devaddr) +{ const char *tmp; int i; @@ -194,57 +205,56 @@ static int linux_netlink_parse(char *buffer, size_t len, int *detached, const ch *busnum = 0; *devaddr = 0; - tmp = netlink_message_parse((const char *) buffer, len, "ACTION"); - if (tmp == NULL) + tmp = netlink_message_parse(buffer, len, "ACTION"); + if (!tmp) { return -1; - if (0 == strcmp(tmp, "remove")) { + } else if (strcmp(tmp, "remove") == 0) { *detached = 1; - } else if (0 != strcmp(tmp, "add")) { + } else if (strcmp(tmp, "add") != 0) { usbi_dbg("unknown device action %s", tmp); return -1; } /* check that this is a usb message */ tmp = netlink_message_parse(buffer, len, "SUBSYSTEM"); - if (NULL == tmp || 0 != strcmp(tmp, "usb")) { + if (!tmp || strcmp(tmp, "usb") != 0) { /* not usb. ignore */ return -1; } /* check that this is an actual usb device */ tmp = netlink_message_parse(buffer, len, "DEVTYPE"); - if (NULL == tmp || 0 != strcmp(tmp, "usb_device")) { + if (!tmp || strcmp(tmp, "usb_device") != 0) { /* not usb. ignore */ return -1; } tmp = netlink_message_parse(buffer, len, "BUSNUM"); - if (NULL == tmp) { + if (!tmp) { /* no bus number. try "DEVICE" */ tmp = netlink_message_parse(buffer, len, "DEVICE"); - if (NULL == tmp) { + if (!tmp) { /* not usb. ignore */ return -1; } - + /* Parse a device path such as /dev/bus/usb/003/004 */ - char *pLastSlash = (char*)strrchr(tmp,'/'); - if(NULL == pLastSlash) { + const char *pLastSlash = strrchr(tmp, '/'); + if (!pLastSlash) return -1; - } - *devaddr = strtoul(pLastSlash + 1, NULL, 10); + *busnum = (uint8_t)(strtoul(pLastSlash - 3, NULL, 10) & 0xff); if (errno) { errno = 0; return -1; } - - *busnum = strtoul(pLastSlash - 3, NULL, 10); + + *devaddr = (uint8_t)(strtoul(pLastSlash + 1, NULL, 10) & 0xff); if (errno) { errno = 0; return -1; } - + return 0; } @@ -255,9 +265,8 @@ static int linux_netlink_parse(char *buffer, size_t len, int *detached, const ch } tmp = netlink_message_parse(buffer, len, "DEVNUM"); - if (NULL == tmp) { + if (!tmp) return -1; - } *devaddr = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff); if (errno) { @@ -266,12 +275,11 @@ static int linux_netlink_parse(char *buffer, size_t len, int *detached, const ch } tmp = netlink_message_parse(buffer, len, "DEVPATH"); - if (NULL == tmp) { + if (!tmp) return -1; - } - for (i = strlen(tmp) - 1 ; i ; --i) { - if ('/' ==tmp[i]) { + for (i = strlen(tmp) - 1; i; --i) { + if (tmp[i] == '/') { *sys_name = tmp + i + 1; break; } @@ -283,14 +291,16 @@ static int linux_netlink_parse(char *buffer, size_t len, int *detached, const ch static int linux_netlink_read_message(void) { - unsigned char buffer[1024]; - struct iovec iov = {.iov_base = buffer, .iov_len = sizeof(buffer)}; - struct msghdr meh = { .msg_iov=&iov, .msg_iovlen=1, - .msg_name=&snl, .msg_namelen=sizeof(snl) }; + char buffer[1024]; const char *sys_name = NULL; uint8_t busnum, devaddr; int detached, r; - size_t len; + ssize_t len; + struct iovec iov = { .iov_base = buffer, .iov_len = sizeof(buffer) }; + struct msghdr meh = { + .msg_iov = &iov, .msg_iovlen = 1, + .msg_name = &snl, .msg_namelen = sizeof(snl) + }; /* read netlink message */ memset(buffer, 0, sizeof(buffer)); @@ -303,8 +313,7 @@ static int linux_netlink_read_message(void) /* TODO -- authenticate this message is from the kernel or udevd */ - r = linux_netlink_parse(buffer, len, &detached, &sys_name, - &busnum, &devaddr); + r = linux_netlink_parse(buffer, (size_t)len, &detached, &sys_name, &busnum, &devaddr); if (r) return r; @@ -323,7 +332,7 @@ static int linux_netlink_read_message(void) static void *linux_netlink_event_thread_main(void *arg) { char dummy; - int r; + ssize_t r; struct pollfd fds[] = { { .fd = netlink_control_pipe[0], .events = POLLIN }, @@ -333,22 +342,25 @@ static void *linux_netlink_event_thread_main(void *arg) UNUSED(arg); + usbi_dbg("netlink event thread entering"); + while (poll(fds, 2, -1) >= 0) { if (fds[0].revents & POLLIN) { /* activity on control pipe, read the byte and exit */ r = usbi_read(netlink_control_pipe[0], &dummy, sizeof(dummy)); - if (r <= 0) { + if (r <= 0) usbi_warn(NULL, "netlink control pipe read failed"); - } break; } if (fds[1].revents & POLLIN) { - usbi_mutex_static_lock(&linux_hotplug_lock); - linux_netlink_read_message(); - usbi_mutex_static_unlock(&linux_hotplug_lock); + usbi_mutex_static_lock(&linux_hotplug_lock); + linux_netlink_read_message(); + usbi_mutex_static_unlock(&linux_hotplug_lock); } } + usbi_dbg("netlink event thread exiting"); + return NULL; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index b7a0eb17f..f05564843 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11050 +#define LIBUSB_NANO 11051 From ec272992ea53547db791fe4ae2189c72f960b42a Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Thu, 28 Jan 2016 14:29:42 -0800 Subject: [PATCH 132/222] linux_netlink: Add message authentication and clean up parsing This commit adds credentials checking to ensure that we only process messages received from the kernel. In addition, the parsing logic was cleaned up and slightly optimized. Signed-off-by: Chris Dickens --- libusb/os/linux_netlink.c | 128 ++++++++++++++++++++++---------------- libusb/version_nano.h | 2 +- 2 files changed, 77 insertions(+), 53 deletions(-) diff --git a/libusb/os/linux_netlink.c b/libusb/os/linux_netlink.c index 501a94dbe..60cf3ad1b 100644 --- a/libusb/os/linux_netlink.c +++ b/libusb/os/linux_netlink.c @@ -4,6 +4,7 @@ * Copyright (C) 2007-2009 Daniel Drake * Copyright (c) 2001 Johannes Erdfelt * Copyright (c) 2013 Nathan Hjelm + * Copyright (c) 2016 Chris Dickens * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -42,7 +43,7 @@ #include "libusbi.h" #include "linux_usbfs.h" -#define KERNEL 1 +#define NL_GROUP_KERNEL 1 static int linux_netlink_socket = -1; static int netlink_control_pipe[2] = { -1, -1 }; @@ -50,8 +51,6 @@ static pthread_t libusb_linux_event_thread; static void *linux_netlink_event_thread_main(void *arg); -static struct sockaddr_nl snl = { .nl_family = AF_NETLINK, .nl_groups = KERNEL }; - static int set_fd_cloexec_nb(int fd) { int flags; @@ -89,7 +88,9 @@ static int set_fd_cloexec_nb(int fd) int linux_netlink_start_event_monitor(void) { + struct sockaddr_nl sa_nl = { .nl_family = AF_NETLINK, .nl_groups = NL_GROUP_KERNEL }; int socktype = SOCK_RAW; + int opt = 1; int ret; #if defined(SOCK_CLOEXEC) @@ -114,14 +115,17 @@ int linux_netlink_start_event_monitor(void) if (ret == -1) goto err_close_socket; - ret = bind(linux_netlink_socket, (struct sockaddr *)&snl, sizeof(snl)); + ret = bind(linux_netlink_socket, (struct sockaddr *)&sa_nl, sizeof(sa_nl)); if (ret == -1) { usbi_err(NULL, "failed to bind netlink socket (%d)", errno); goto err_close_socket; } - /* TODO -- add authentication */ - /* setsockopt(linux_netlink_socket, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); */ + ret = setsockopt(linux_netlink_socket, SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt)); + if (ret == -1) { + usbi_err(NULL, "failed to set netlink socket SO_PASSCRED option (%d)", errno); + goto err_close_socket; + } ret = usbi_pipe(netlink_control_pipe); if (ret) { @@ -178,14 +182,13 @@ int linux_netlink_stop_event_monitor(void) static const char *netlink_message_parse(const char *buffer, size_t len, const char *key) { + const char *end = buffer + len; size_t keylen = strlen(key); - size_t offset; - for (offset = 0; offset < len && buffer[offset] != '\0'; offset += strlen(buffer + offset) + 1) { - if (strncmp(buffer + offset, key, keylen) == 0 && - buffer[offset + keylen] == '=') { - return buffer + offset + keylen + 1; - } + while (buffer < end && *buffer) { + if (strncmp(buffer, key, keylen) == 0 && buffer[keylen] == '=') + return buffer + keylen + 1; + buffer += strlen(buffer) + 1; } return NULL; @@ -195,8 +198,7 @@ static const char *netlink_message_parse(const char *buffer, size_t len, const c static int linux_netlink_parse(const char *buffer, size_t len, int *detached, const char **sys_name, uint8_t *busnum, uint8_t *devaddr) { - const char *tmp; - int i; + const char *tmp, *slash; errno = 0; @@ -230,7 +232,23 @@ static int linux_netlink_parse(const char *buffer, size_t len, int *detached, } tmp = netlink_message_parse(buffer, len, "BUSNUM"); - if (!tmp) { + if (tmp) { + *busnum = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff); + if (errno) { + errno = 0; + return -1; + } + + tmp = netlink_message_parse(buffer, len, "DEVNUM"); + if (NULL == tmp) + return -1; + + *devaddr = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff); + if (errno) { + errno = 0; + return -1; + } + } else { /* no bus number. try "DEVICE" */ tmp = netlink_message_parse(buffer, len, "DEVICE"); if (!tmp) { @@ -239,17 +257,17 @@ static int linux_netlink_parse(const char *buffer, size_t len, int *detached, } /* Parse a device path such as /dev/bus/usb/003/004 */ - const char *pLastSlash = strrchr(tmp, '/'); - if (!pLastSlash) + slash = strrchr(tmp, '/'); + if (!slash) return -1; - *busnum = (uint8_t)(strtoul(pLastSlash - 3, NULL, 10) & 0xff); + *busnum = (uint8_t)(strtoul(slash - 3, NULL, 10) & 0xff); if (errno) { errno = 0; return -1; } - *devaddr = (uint8_t)(strtoul(pLastSlash + 1, NULL, 10) & 0xff); + *devaddr = (uint8_t)(strtoul(slash + 1, NULL, 10) & 0xff); if (errno) { errno = 0; return -1; @@ -258,32 +276,13 @@ static int linux_netlink_parse(const char *buffer, size_t len, int *detached, return 0; } - *busnum = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff); - if (errno) { - errno = 0; - return -1; - } - - tmp = netlink_message_parse(buffer, len, "DEVNUM"); - if (!tmp) - return -1; - - *devaddr = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff); - if (errno) { - errno = 0; - return -1; - } - tmp = netlink_message_parse(buffer, len, "DEVPATH"); if (!tmp) return -1; - for (i = strlen(tmp) - 1; i; --i) { - if (tmp[i] == '/') { - *sys_name = tmp + i + 1; - break; - } - } + slash = strrchr(tmp, '/'); + if (slash) + *sys_name = slash + 1; /* found a usb device */ return 0; @@ -291,29 +290,54 @@ static int linux_netlink_parse(const char *buffer, size_t len, int *detached, static int linux_netlink_read_message(void) { - char buffer[1024]; + char cred_buffer[CMSG_SPACE(sizeof(struct ucred))]; + char msg_buffer[2048]; const char *sys_name = NULL; uint8_t busnum, devaddr; int detached, r; ssize_t len; - struct iovec iov = { .iov_base = buffer, .iov_len = sizeof(buffer) }; - struct msghdr meh = { + struct cmsghdr *cmsg; + struct ucred *cred; + struct sockaddr_nl sa_nl; + struct iovec iov = { .iov_base = msg_buffer, .iov_len = sizeof(msg_buffer) }; + struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, - .msg_name = &snl, .msg_namelen = sizeof(snl) + .msg_control = cred_buffer, .msg_controllen = sizeof(cred_buffer), + .msg_name = &sa_nl, .msg_namelen = sizeof(sa_nl) }; /* read netlink message */ - memset(buffer, 0, sizeof(buffer)); - len = recvmsg(linux_netlink_socket, &meh, 0); - if (len < 32) { - if (errno != EAGAIN) - usbi_dbg("error receiving message from netlink"); + len = recvmsg(linux_netlink_socket, &msg, 0); + if (len == -1) { + if (errno != EAGAIN && errno != EINTR) + usbi_err(NULL, "error receiving message from netlink (%d)", errno); + return -1; + } + + if (len < 32 || (msg.msg_flags & MSG_TRUNC)) { + usbi_err(NULL, "invalid netlink message length"); + return -1; + } + + if (sa_nl.nl_groups != NL_GROUP_KERNEL || sa_nl.nl_pid != 0) { + usbi_dbg("ignoring netlink message from unknown group/PID (%u/%u)", + (unsigned int)sa_nl.nl_groups, (unsigned int)sa_nl.nl_pid); return -1; } - /* TODO -- authenticate this message is from the kernel or udevd */ + cmsg = CMSG_FIRSTHDR(&msg); + if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) { + usbi_dbg("ignoring netlink message with no sender credentials"); + return -1; + } + + cred = (struct ucred *)CMSG_DATA(cmsg); + if (cred->uid != 0) { + usbi_dbg("ignoring netlink message with non-zero sender UID %u", (unsigned int)cred->uid); + return -1; + } - r = linux_netlink_parse(buffer, (size_t)len, &detached, &sys_name, &busnum, &devaddr); + r = linux_netlink_parse(msg_buffer, (size_t)len, &detached, &sys_name, &busnum, &devaddr); if (r) return r; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index f05564843..61e27eab9 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11051 +#define LIBUSB_NANO 11052 From 8e3d41e5818c68eb9ea95e0066c44f29b3f5943a Mon Sep 17 00:00:00 2001 From: Evan Hunter Date: Fri, 8 Jan 2016 13:53:42 +0000 Subject: [PATCH 133/222] windows: Fix compilation for MSYS2 Closes #140 Signed-off-by: Chris Dickens --- configure.ac | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 4e35bf677..9f3e639d6 100644 --- a/configure.ac +++ b/configure.ac @@ -78,7 +78,7 @@ case $host in backend="netbsd" threads="posix" ;; -*-mingw*) +*-mingw* | *msys*) AC_MSG_RESULT([Windows]) backend="windows" threads="windows" diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 61e27eab9..3b9aefc21 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11052 +#define LIBUSB_NANO 11053 From 60e875dc90c48df5101fefc4ef7c76516bbcc6e4 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Tue, 23 Feb 2016 23:45:51 -0800 Subject: [PATCH 134/222] sync: Allow transferred argument to be optional in bulk APIs Closes #139 Signed-off-by: Chris Dickens --- libusb/sync.c | 12 +++++++++--- libusb/version_nano.h | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/libusb/sync.c b/libusb/sync.c index 0d1acd850..668909c88 100644 --- a/libusb/sync.c +++ b/libusb/sync.c @@ -188,7 +188,9 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, sync_transfer_wait_for_completion(transfer); - *transferred = transfer->actual_length; + if (transferred) + *transferred = transfer->actual_length; + switch (transfer->status) { case LIBUSB_TRANSFER_COMPLETED: r = 0; @@ -245,7 +247,9 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, * \param length for bulk writes, the number of bytes from data to be sent. for * bulk reads, the maximum number of bytes to receive into the data buffer. * \param transferred output location for the number of bytes actually - * transferred. + * transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105), + * it is legal to pass a NULL pointer if you do not wish to receive this + * information. * \param timeout timeout (in millseconds) that this function should wait * before giving up due to no response being received. For an unlimited * timeout, use value 0. @@ -296,7 +300,9 @@ int API_EXPORTED libusb_bulk_transfer(struct libusb_device_handle *dev_handle, * \param length for bulk writes, the number of bytes from data to be sent. for * bulk reads, the maximum number of bytes to receive into the data buffer. * \param transferred output location for the number of bytes actually - * transferred. + * transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105), + * it is legal to pass a NULL pointer if you do not wish to receive this + * information. * \param timeout timeout (in millseconds) that this function should wait * before giving up due to no response being received. For an unlimited * timeout, use value 0. diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 3b9aefc21..9bb57fa66 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11053 +#define LIBUSB_NANO 11054 From 8a0c14372f98d56529556f18126a42fda2ab0137 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Wed, 24 Feb 2016 00:23:49 -0800 Subject: [PATCH 135/222] Misc: Make API parameter names consistent and sensible Prior to this commit, API functions taking a libusb_device_handle argument had the parameter named dev, handle, or dev_handle. This commit changes the name of all libusb_device_handle parameters to dev_handle in both the documentation and actual code. Closes #132 Signed-off-by: Chris Dickens --- libusb/core.c | 174 +++++++++++++++++++++--------------------- libusb/descriptor.c | 24 +++--- libusb/hotplug.c | 31 ++++---- libusb/io.c | 24 +++--- libusb/libusb.h | 50 ++++++------ libusb/libusbi.h | 32 ++++---- libusb/version_nano.h | 2 +- 7 files changed, 168 insertions(+), 169 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 90491e6cb..4d6d37717 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1216,7 +1216,7 @@ int usbi_clear_event(struct libusb_context *ctx) * This is a non-blocking function; no requests are sent over the bus. * * \param dev the device to open - * \param handle output location for the returned device handle pointer. Only + * \param dev_handle output location for the returned device handle pointer. Only * populated when the return code is 0. * \returns 0 on success * \returns LIBUSB_ERROR_NO_MEM on memory allocation failure @@ -1225,10 +1225,10 @@ int usbi_clear_event(struct libusb_context *ctx) * \returns another LIBUSB_ERROR code on other failure */ int API_EXPORTED libusb_open(libusb_device *dev, - libusb_device_handle **handle) + libusb_device_handle **dev_handle) { struct libusb_context *ctx = DEVICE_CTX(dev); - struct libusb_device_handle *_handle; + struct libusb_device_handle *_dev_handle; size_t priv_size = usbi_backend->device_handle_priv_size; int r; usbi_dbg("open %d.%d", dev->bus_number, dev->device_address); @@ -1237,34 +1237,34 @@ int API_EXPORTED libusb_open(libusb_device *dev, return LIBUSB_ERROR_NO_DEVICE; } - _handle = malloc(sizeof(*_handle) + priv_size); - if (!_handle) + _dev_handle = malloc(sizeof(*_dev_handle) + priv_size); + if (!_dev_handle) return LIBUSB_ERROR_NO_MEM; - r = usbi_mutex_init(&_handle->lock, NULL); + r = usbi_mutex_init(&_dev_handle->lock, NULL); if (r) { - free(_handle); + free(_dev_handle); return LIBUSB_ERROR_OTHER; } - _handle->dev = libusb_ref_device(dev); - _handle->auto_detach_kernel_driver = 0; - _handle->claimed_interfaces = 0; - memset(&_handle->os_priv, 0, priv_size); + _dev_handle->dev = libusb_ref_device(dev); + _dev_handle->auto_detach_kernel_driver = 0; + _dev_handle->claimed_interfaces = 0; + memset(&_dev_handle->os_priv, 0, priv_size); - r = usbi_backend->open(_handle); + r = usbi_backend->open(_dev_handle); if (r < 0) { usbi_dbg("open %d.%d returns %d", dev->bus_number, dev->device_address, r); libusb_unref_device(dev); - usbi_mutex_destroy(&_handle->lock); - free(_handle); + usbi_mutex_destroy(&_dev_handle->lock); + free(_dev_handle); return r; } usbi_mutex_lock(&ctx->open_devs_lock); - list_add(&_handle->list, &ctx->open_devs); + list_add(&_dev_handle->list, &ctx->open_devs); usbi_mutex_unlock(&ctx->open_devs_lock); - *handle = _handle; + *dev_handle = _dev_handle; return 0; } @@ -1283,8 +1283,8 @@ int API_EXPORTED libusb_open(libusb_device *dev, * \param ctx the context to operate on, or NULL for the default context * \param vendor_id the idVendor value to search for * \param product_id the idProduct value to search for - * \returns a handle for the first found device, or NULL on error or if the - * device could not be found. */ + * \returns a device handle for the first found device, or NULL on error + * or if the device could not be found. */ DEFAULT_VISIBILITY libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid( libusb_context *ctx, uint16_t vendor_id, uint16_t product_id) @@ -1292,7 +1292,7 @@ libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid( struct libusb_device **devs; struct libusb_device *found = NULL; struct libusb_device *dev; - struct libusb_device_handle *handle = NULL; + struct libusb_device_handle *dev_handle = NULL; size_t i = 0; int r; @@ -1311,14 +1311,14 @@ libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid( } if (found) { - r = libusb_open(found, &handle); + r = libusb_open(found, &dev_handle); if (r < 0) - handle = NULL; + dev_handle = NULL; } out: libusb_free_device_list(devs, 1); - return handle; + return dev_handle; } static void do_close(struct libusb_context *ctx, @@ -1388,7 +1388,7 @@ static void do_close(struct libusb_context *ctx, * * This is a non-blocking function; no requests are sent over the bus. * - * \param dev_handle the handle to close + * \param dev_handle the device handle to close */ void API_EXPORTED libusb_close(libusb_device_handle *dev_handle) { @@ -1436,7 +1436,7 @@ void API_EXPORTED libusb_close(libusb_device_handle *dev_handle) } /** \ingroup dev - * Get the underlying device for a handle. This function does not modify + * Get the underlying device for a device handle. This function does not modify * the reference count of the returned device, so do not feel compelled to * unreference it when you are done. * \param dev_handle a device handle @@ -1461,29 +1461,29 @@ libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle) * This function will return a value of 0 in the config output * parameter if the device is in unconfigured state. * - * \param dev a device handle + * \param dev_handle a device handle * \param config output location for the bConfigurationValue of the active * configuration (only valid for return code 0) * \returns 0 on success * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * \returns another LIBUSB_ERROR code on other failure */ -int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev, +int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev_handle, int *config) { int r = LIBUSB_ERROR_NOT_SUPPORTED; usbi_dbg(""); if (usbi_backend->get_configuration) - r = usbi_backend->get_configuration(dev, config); + r = usbi_backend->get_configuration(dev_handle, config); if (r == LIBUSB_ERROR_NOT_SUPPORTED) { uint8_t tmp = 0; usbi_dbg("falling back to control message"); - r = libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN, + r = libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_CONFIGURATION, 0, 0, &tmp, 1, 1000); if (r == 0) { - usbi_err(HANDLE_CTX(dev), "zero bytes returned in ctrl transfer?"); + usbi_err(HANDLE_CTX(dev_handle), "zero bytes returned in ctrl transfer?"); r = LIBUSB_ERROR_IO; } else if (r == 1) { r = 0; @@ -1535,7 +1535,7 @@ int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev, * * This is a blocking function. * - * \param dev a device handle + * \param dev_handle a device handle * \param configuration the bConfigurationValue of the configuration you * wish to activate, or -1 if you wish to put the device in an unconfigured * state @@ -1546,11 +1546,11 @@ int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev, * \returns another LIBUSB_ERROR code on other failure * \see libusb_set_auto_detach_kernel_driver() */ -int API_EXPORTED libusb_set_configuration(libusb_device_handle *dev, +int API_EXPORTED libusb_set_configuration(libusb_device_handle *dev_handle, int configuration) { usbi_dbg("configuration %d", configuration); - return usbi_backend->set_configuration(dev, configuration); + return usbi_backend->set_configuration(dev_handle, configuration); } /** \ingroup dev @@ -1570,7 +1570,7 @@ int API_EXPORTED libusb_set_configuration(libusb_device_handle *dev, * * This is a non-blocking function. * - * \param dev a device handle + * \param dev_handle a device handle * \param interface_number the bInterfaceNumber of the interface you * wish to claim * \returns 0 on success @@ -1581,7 +1581,7 @@ int API_EXPORTED libusb_set_configuration(libusb_device_handle *dev, * \returns a LIBUSB_ERROR code on other failure * \see libusb_set_auto_detach_kernel_driver() */ -int API_EXPORTED libusb_claim_interface(libusb_device_handle *dev, +int API_EXPORTED libusb_claim_interface(libusb_device_handle *dev_handle, int interface_number) { int r = 0; @@ -1590,19 +1590,19 @@ int API_EXPORTED libusb_claim_interface(libusb_device_handle *dev, if (interface_number >= USB_MAXINTERFACES) return LIBUSB_ERROR_INVALID_PARAM; - if (!dev->dev->attached) + if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; - usbi_mutex_lock(&dev->lock); - if (dev->claimed_interfaces & (1 << interface_number)) + usbi_mutex_lock(&dev_handle->lock); + if (dev_handle->claimed_interfaces & (1 << interface_number)) goto out; - r = usbi_backend->claim_interface(dev, interface_number); + r = usbi_backend->claim_interface(dev_handle, interface_number); if (r == 0) - dev->claimed_interfaces |= 1 << interface_number; + dev_handle->claimed_interfaces |= 1 << interface_number; out: - usbi_mutex_unlock(&dev->lock); + usbi_mutex_unlock(&dev_handle->lock); return r; } @@ -1616,7 +1616,7 @@ int API_EXPORTED libusb_claim_interface(libusb_device_handle *dev, * If auto_detach_kernel_driver is set to 1 for dev, the kernel * driver will be re-attached after releasing the interface. * - * \param dev a device handle + * \param dev_handle a device handle * \param interface_number the bInterfaceNumber of the * previously-claimed interface * \returns 0 on success @@ -1625,7 +1625,7 @@ int API_EXPORTED libusb_claim_interface(libusb_device_handle *dev, * \returns another LIBUSB_ERROR code on other failure * \see libusb_set_auto_detach_kernel_driver() */ -int API_EXPORTED libusb_release_interface(libusb_device_handle *dev, +int API_EXPORTED libusb_release_interface(libusb_device_handle *dev_handle, int interface_number) { int r; @@ -1634,18 +1634,18 @@ int API_EXPORTED libusb_release_interface(libusb_device_handle *dev, if (interface_number >= USB_MAXINTERFACES) return LIBUSB_ERROR_INVALID_PARAM; - usbi_mutex_lock(&dev->lock); - if (!(dev->claimed_interfaces & (1 << interface_number))) { + usbi_mutex_lock(&dev_handle->lock); + if (!(dev_handle->claimed_interfaces & (1 << interface_number))) { r = LIBUSB_ERROR_NOT_FOUND; goto out; } - r = usbi_backend->release_interface(dev, interface_number); + r = usbi_backend->release_interface(dev_handle, interface_number); if (r == 0) - dev->claimed_interfaces &= ~(1 << interface_number); + dev_handle->claimed_interfaces &= ~(1 << interface_number); out: - usbi_mutex_unlock(&dev->lock); + usbi_mutex_unlock(&dev_handle->lock); return r; } @@ -1659,7 +1659,7 @@ int API_EXPORTED libusb_release_interface(libusb_device_handle *dev, * * This is a blocking function. * - * \param dev a device handle + * \param dev_handle a device handle * \param interface_number the bInterfaceNumber of the * previously-claimed interface * \param alternate_setting the bAlternateSetting of the alternate @@ -1670,7 +1670,7 @@ int API_EXPORTED libusb_release_interface(libusb_device_handle *dev, * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * \returns another LIBUSB_ERROR code on other failure */ -int API_EXPORTED libusb_set_interface_alt_setting(libusb_device_handle *dev, +int API_EXPORTED libusb_set_interface_alt_setting(libusb_device_handle *dev_handle, int interface_number, int alternate_setting) { usbi_dbg("interface %d altsetting %d", @@ -1678,19 +1678,19 @@ int API_EXPORTED libusb_set_interface_alt_setting(libusb_device_handle *dev, if (interface_number >= USB_MAXINTERFACES) return LIBUSB_ERROR_INVALID_PARAM; - usbi_mutex_lock(&dev->lock); - if (!dev->dev->attached) { - usbi_mutex_unlock(&dev->lock); + usbi_mutex_lock(&dev_handle->lock); + if (!dev_handle->dev->attached) { + usbi_mutex_unlock(&dev_handle->lock); return LIBUSB_ERROR_NO_DEVICE; } - if (!(dev->claimed_interfaces & (1 << interface_number))) { - usbi_mutex_unlock(&dev->lock); + if (!(dev_handle->claimed_interfaces & (1 << interface_number))) { + usbi_mutex_unlock(&dev_handle->lock); return LIBUSB_ERROR_NOT_FOUND; } - usbi_mutex_unlock(&dev->lock); + usbi_mutex_unlock(&dev_handle->lock); - return usbi_backend->set_interface_altsetting(dev, interface_number, + return usbi_backend->set_interface_altsetting(dev_handle, interface_number, alternate_setting); } @@ -1703,21 +1703,21 @@ int API_EXPORTED libusb_set_interface_alt_setting(libusb_device_handle *dev, * * This is a blocking function. * - * \param dev a device handle + * \param dev_handle a device handle * \param endpoint the endpoint to clear halt status * \returns 0 on success * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * \returns another LIBUSB_ERROR code on other failure */ -int API_EXPORTED libusb_clear_halt(libusb_device_handle *dev, +int API_EXPORTED libusb_clear_halt(libusb_device_handle *dev_handle, unsigned char endpoint) { usbi_dbg("endpoint %x", endpoint); - if (!dev->dev->attached) + if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; - return usbi_backend->clear_halt(dev, endpoint); + return usbi_backend->clear_halt(dev_handle, endpoint); } /** \ingroup dev @@ -1733,19 +1733,19 @@ int API_EXPORTED libusb_clear_halt(libusb_device_handle *dev, * * This is a blocking function which usually incurs a noticeable delay. * - * \param dev a handle of the device to reset + * \param dev_handle a handle of the device to reset * \returns 0 on success * \returns LIBUSB_ERROR_NOT_FOUND if re-enumeration is required, or if the * device has been disconnected * \returns another LIBUSB_ERROR code on other failure */ -int API_EXPORTED libusb_reset_device(libusb_device_handle *dev) +int API_EXPORTED libusb_reset_device(libusb_device_handle *dev_handle) { usbi_dbg(""); - if (!dev->dev->attached) + if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; - return usbi_backend->reset_device(dev); + return usbi_backend->reset_device(dev_handle); } /** \ingroup asyncio @@ -1763,22 +1763,22 @@ int API_EXPORTED libusb_reset_device(libusb_device_handle *dev) * * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 * - * \param dev a device handle + * \param dev_handle a device handle * \param num_streams number of streams to try to allocate * \param endpoints array of endpoints to allocate streams on * \param num_endpoints length of the endpoints array * \returns number of streams allocated, or a LIBUSB_ERROR code on failure */ -int API_EXPORTED libusb_alloc_streams(libusb_device_handle *dev, +int API_EXPORTED libusb_alloc_streams(libusb_device_handle *dev_handle, uint32_t num_streams, unsigned char *endpoints, int num_endpoints) { usbi_dbg("streams %u eps %d", (unsigned) num_streams, num_endpoints); - if (!dev->dev->attached) + if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; if (usbi_backend->alloc_streams) - return usbi_backend->alloc_streams(dev, num_streams, endpoints, + return usbi_backend->alloc_streams(dev_handle, num_streams, endpoints, num_endpoints); else return LIBUSB_ERROR_NOT_SUPPORTED; @@ -1791,21 +1791,21 @@ int API_EXPORTED libusb_alloc_streams(libusb_device_handle *dev, * * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 * - * \param dev a device handle + * \param dev_handle a device handle * \param endpoints array of endpoints to free streams on * \param num_endpoints length of the endpoints array * \returns LIBUSB_SUCCESS, or a LIBUSB_ERROR code on failure */ -int API_EXPORTED libusb_free_streams(libusb_device_handle *dev, +int API_EXPORTED libusb_free_streams(libusb_device_handle *dev_handle, unsigned char *endpoints, int num_endpoints) { usbi_dbg("eps %d", num_endpoints); - if (!dev->dev->attached) + if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; if (usbi_backend->free_streams) - return usbi_backend->free_streams(dev, endpoints, + return usbi_backend->free_streams(dev_handle, endpoints, num_endpoints); else return LIBUSB_ERROR_NOT_SUPPORTED; @@ -1818,7 +1818,7 @@ int API_EXPORTED libusb_free_streams(libusb_device_handle *dev, * * This functionality is not available on Windows. * - * \param dev a device handle + * \param dev_handle a device handle * \param interface_number the interface to check * \returns 0 if no kernel driver is active * \returns 1 if a kernel driver is active @@ -1828,16 +1828,16 @@ int API_EXPORTED libusb_free_streams(libusb_device_handle *dev, * \returns another LIBUSB_ERROR code on other failure * \see libusb_detach_kernel_driver() */ -int API_EXPORTED libusb_kernel_driver_active(libusb_device_handle *dev, +int API_EXPORTED libusb_kernel_driver_active(libusb_device_handle *dev_handle, int interface_number) { usbi_dbg("interface %d", interface_number); - if (!dev->dev->attached) + if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; if (usbi_backend->kernel_driver_active) - return usbi_backend->kernel_driver_active(dev, interface_number); + return usbi_backend->kernel_driver_active(dev_handle, interface_number); else return LIBUSB_ERROR_NOT_SUPPORTED; } @@ -1852,7 +1852,7 @@ int API_EXPORTED libusb_kernel_driver_active(libusb_device_handle *dev, * driver, if this driver is already attached to the device, this call will * not detach it and return LIBUSB_ERROR_NOT_FOUND. * - * \param dev a device handle + * \param dev_handle a device handle * \param interface_number the interface to detach the driver from * \returns 0 on success * \returns LIBUSB_ERROR_NOT_FOUND if no kernel driver was active @@ -1863,16 +1863,16 @@ int API_EXPORTED libusb_kernel_driver_active(libusb_device_handle *dev, * \returns another LIBUSB_ERROR code on other failure * \see libusb_kernel_driver_active() */ -int API_EXPORTED libusb_detach_kernel_driver(libusb_device_handle *dev, +int API_EXPORTED libusb_detach_kernel_driver(libusb_device_handle *dev_handle, int interface_number) { usbi_dbg("interface %d", interface_number); - if (!dev->dev->attached) + if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; if (usbi_backend->detach_kernel_driver) - return usbi_backend->detach_kernel_driver(dev, interface_number); + return usbi_backend->detach_kernel_driver(dev_handle, interface_number); else return LIBUSB_ERROR_NOT_SUPPORTED; } @@ -1884,7 +1884,7 @@ int API_EXPORTED libusb_detach_kernel_driver(libusb_device_handle *dev, * * This functionality is not available on Darwin or Windows. * - * \param dev a device handle + * \param dev_handle a device handle * \param interface_number the interface to attach the driver from * \returns 0 on success * \returns LIBUSB_ERROR_NOT_FOUND if no kernel driver was active @@ -1897,16 +1897,16 @@ int API_EXPORTED libusb_detach_kernel_driver(libusb_device_handle *dev, * \returns another LIBUSB_ERROR code on other failure * \see libusb_kernel_driver_active() */ -int API_EXPORTED libusb_attach_kernel_driver(libusb_device_handle *dev, +int API_EXPORTED libusb_attach_kernel_driver(libusb_device_handle *dev_handle, int interface_number) { usbi_dbg("interface %d", interface_number); - if (!dev->dev->attached) + if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; if (usbi_backend->attach_kernel_driver) - return usbi_backend->attach_kernel_driver(dev, interface_number); + return usbi_backend->attach_kernel_driver(dev_handle, interface_number); else return LIBUSB_ERROR_NOT_SUPPORTED; } @@ -1923,7 +1923,7 @@ int API_EXPORTED libusb_attach_kernel_driver(libusb_device_handle *dev, * this function will return LIBUSB_ERROR_NOT_SUPPORTED, and libusb will * continue as if this function was never called. * - * \param dev a device handle + * \param dev_handle a device handle * \param enable whether to enable or disable auto kernel driver detachment * * \returns LIBUSB_SUCCESS on success @@ -1934,12 +1934,12 @@ int API_EXPORTED libusb_attach_kernel_driver(libusb_device_handle *dev, * \see libusb_set_configuration() */ int API_EXPORTED libusb_set_auto_detach_kernel_driver( - libusb_device_handle *dev, int enable) + libusb_device_handle *dev_handle, int enable) { if (!(usbi_backend->caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER)) return LIBUSB_ERROR_NOT_SUPPORTED; - dev->auto_detach_kernel_driver = enable; + dev_handle->auto_detach_kernel_driver = enable; return LIBUSB_SUCCESS; } diff --git a/libusb/descriptor.c b/libusb/descriptor.c index defcacb1f..402c91da0 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -888,14 +888,14 @@ static int parse_bos(struct libusb_context *ctx, * Get a Binary Object Store (BOS) descriptor * This is a BLOCKING function, which will send requests to the device. * - * \param handle the handle of an open libusb device + * \param dev_handle the handle of an open libusb device * \param bos output location for the BOS descriptor. Only valid if 0 was returned. * Must be freed with \ref libusb_free_bos_descriptor() after use. * \returns 0 on success * \returns LIBUSB_ERROR_NOT_FOUND if the device doesn't have a BOS descriptor * \returns another LIBUSB_ERROR code on error */ -int API_EXPORTED libusb_get_bos_descriptor(libusb_device_handle *handle, +int API_EXPORTED libusb_get_bos_descriptor(libusb_device_handle *dev_handle, struct libusb_bos_descriptor **bos) { struct libusb_bos_descriptor _bos; @@ -906,15 +906,15 @@ int API_EXPORTED libusb_get_bos_descriptor(libusb_device_handle *handle, /* Read the BOS. This generates 2 requests on the bus, * one for the header, and one for the full BOS */ - r = libusb_get_descriptor(handle, LIBUSB_DT_BOS, 0, bos_header, + r = libusb_get_descriptor(dev_handle, LIBUSB_DT_BOS, 0, bos_header, LIBUSB_DT_BOS_SIZE); if (r < 0) { if (r != LIBUSB_ERROR_PIPE) - usbi_err(handle->dev->ctx, "failed to read BOS (%d)", r); + usbi_err(HANDLE_CTX(dev_handle), "failed to read BOS (%d)", r); return r; } if (r < LIBUSB_DT_BOS_SIZE) { - usbi_err(handle->dev->ctx, "short BOS read %d/%d", + usbi_err(HANDLE_CTX(dev_handle), "short BOS read %d/%d", r, LIBUSB_DT_BOS_SIZE); return LIBUSB_ERROR_IO; } @@ -926,12 +926,12 @@ int API_EXPORTED libusb_get_bos_descriptor(libusb_device_handle *handle, if (bos_data == NULL) return LIBUSB_ERROR_NO_MEM; - r = libusb_get_descriptor(handle, LIBUSB_DT_BOS, 0, bos_data, + r = libusb_get_descriptor(dev_handle, LIBUSB_DT_BOS, 0, bos_data, _bos.wTotalLength); if (r >= 0) - r = parse_bos(handle->dev->ctx, bos, bos_data, r, host_endian); + r = parse_bos(HANDLE_CTX(dev_handle), bos, bos_data, r, host_endian); else - usbi_err(handle->dev->ctx, "failed to read BOS (%d)", r); + usbi_err(HANDLE_CTX(dev_handle), "failed to read BOS (%d)", r); free(bos_data); return r; @@ -1135,13 +1135,13 @@ void API_EXPORTED libusb_free_container_id_descriptor( * Wrapper around libusb_get_string_descriptor(). Uses the first language * supported by the device. * - * \param dev a device handle + * \param dev_handle a device handle * \param desc_index the index of the descriptor to retrieve * \param data output buffer for ASCII string descriptor * \param length size of data buffer * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure */ -int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev, +int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle, uint8_t desc_index, unsigned char *data, int length) { unsigned char tbuf[255]; /* Some devices choke on size > 255 */ @@ -1160,7 +1160,7 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev, if (desc_index == 0) return LIBUSB_ERROR_INVALID_PARAM; - r = libusb_get_string_descriptor(dev, 0, 0, tbuf, sizeof(tbuf)); + r = libusb_get_string_descriptor(dev_handle, 0, 0, tbuf, sizeof(tbuf)); if (r < 0) return r; @@ -1169,7 +1169,7 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev, langid = tbuf[2] | (tbuf[3] << 8); - r = libusb_get_string_descriptor(dev, desc_index, langid, tbuf, + r = libusb_get_string_descriptor(dev_handle, desc_index, langid, tbuf, sizeof(tbuf)); if (r < 0) return r; diff --git a/libusb/hotplug.c b/libusb/hotplug.c index 779cb6b32..85d44af55 100644 --- a/libusb/hotplug.c +++ b/libusb/hotplug.c @@ -55,7 +55,7 @@ * * To receive hotplug notification you register a callback by calling * \ref libusb_hotplug_register_callback(). This function will optionally return - * a handle that can be passed to \ref libusb_hotplug_deregister_callback(). + * a callback handle that can be passed to \ref libusb_hotplug_deregister_callback(). * * A callback function must return an int (0 or 1) indicating whether the callback is * expecting additional events. Returning 0 will rearm the callback and 1 will cause @@ -75,7 +75,7 @@ * * Note: If you receive notification that a device has left and you have any * a libusb_device_handles for the device it is up to you to call libusb_close() - * on each handle to free up any remaining resources associated with the device. + * on each device handle to free up any remaining resources associated with the device. * Once a device has left any libusb_device_handle associated with the device * are invalid and will remain so even if the device comes back. * @@ -100,21 +100,21 @@ static int count = 0; int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev, libusb_hotplug_event event, void *user_data) { - static libusb_device_handle *handle = NULL; + static libusb_device_handle *dev_handle = NULL; struct libusb_device_descriptor desc; int rc; (void)libusb_get_device_descriptor(dev, &desc); if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) { - rc = libusb_open(dev, &handle); + rc = libusb_open(dev, &dev_handle); if (LIBUSB_SUCCESS != rc) { printf("Could not open USB device\n"); } } else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) { - if (handle) { - libusb_close(handle); - handle = NULL; + if (dev_handle) { + libusb_close(dev_handle); + dev_handle = NULL; } } else { printf("Unhandled event %d\n", event); @@ -125,7 +125,7 @@ int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev, } int main (void) { - libusb_hotplug_callback_handle handle; + libusb_hotplug_callback_handle callback_handle; int rc; libusb_init(NULL); @@ -133,7 +133,7 @@ int main (void) { rc = libusb_hotplug_register_callback(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, 0x045a, 0x5005, LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, NULL, - &handle); + &callback_handle); if (LIBUSB_SUCCESS != rc) { printf("Error creating a hotplug callback\n"); libusb_exit(NULL); @@ -145,7 +145,7 @@ int main (void) { usleep(10000); } - libusb_hotplug_deregister_callback(NULL, handle); + libusb_hotplug_deregister_callback(NULL, callback_handle); libusb_exit(NULL); return 0; @@ -237,7 +237,7 @@ int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx, libusb_hotplug_event events, libusb_hotplug_flag flags, int vendor_id, int product_id, int dev_class, libusb_hotplug_callback_fn cb_fn, void *user_data, - libusb_hotplug_callback_handle *handle) + libusb_hotplug_callback_handle *callback_handle) { libusb_hotplug_callback *new_callback; static int handle_id = 1; @@ -304,15 +304,14 @@ int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx, } - if (handle) { - *handle = new_callback->handle; - } + if (callback_handle) + *callback_handle = new_callback->handle; return LIBUSB_SUCCESS; } void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx, - libusb_hotplug_callback_handle handle) + libusb_hotplug_callback_handle callback_handle) { struct libusb_hotplug_callback *hotplug_cb; @@ -326,7 +325,7 @@ void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx usbi_mutex_lock(&ctx->hotplug_cbs_lock); list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) { - if (handle == hotplug_cb->handle) { + if (callback_handle == hotplug_cb->handle) { /* Mark this callback for deregistration */ hotplug_cb->needs_free = 1; } diff --git a/libusb/io.c b/libusb/io.c index 91ea0443e..908acfd6b 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -97,7 +97,7 @@ \code unsigned char data[4]; int actual_length; -int r = libusb_bulk_transfer(handle, LIBUSB_ENDPOINT_IN, data, sizeof(data), &actual_length, 0); +int r = libusb_bulk_transfer(dev_handle, LIBUSB_ENDPOINT_IN, data, sizeof(data), &actual_length, 0); if (r == 0 && actual_length == sizeof(data)) { // results of the transaction can now be found in the data buffer // parse them here and report button press @@ -567,12 +567,12 @@ void *event_thread_func(void *ctx) * thread until after their first call to libusb_open(), and should stop the * thread when closing the last open device as follows: \code -void my_close_handle(libusb_device_handle *handle) +void my_close_handle(libusb_device_handle *dev_handle) { if (open_devs == 1) event_thread_run = 0; - libusb_close(handle); // This wakes up libusb_handle_events() + libusb_close(dev_handle); // This wakes up libusb_handle_events() if (open_devs == 1) pthread_join(event_thread); @@ -626,7 +626,7 @@ void my_libusb_exit(void) * descriptors in your main event loop, you must also consider that libusb * sometimes needs to be called into at fixed points in time even when there * is no file descriptor activity, see \ref polltime details. - * + * * In order to know precisely when libusb needs to be called into, libusb * offers you a set of pollable file descriptors and information about when * the next timeout expires. @@ -1627,7 +1627,7 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_device_handle *handle = transfer->dev_handle; + struct libusb_device_handle *dev_handle = transfer->dev_handle; uint8_t flags; int r; @@ -1661,7 +1661,7 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, * this point. */ if (flags & LIBUSB_TRANSFER_FREE_TRANSFER) libusb_free_transfer(transfer); - libusb_unref_device(handle->dev); + libusb_unref_device(dev_handle->dev); return r; } @@ -2759,13 +2759,13 @@ void API_EXPORTED libusb_free_pollfds(const struct libusb_pollfd **pollfds) * device. This function ensures transfers get cancelled appropriately. * Callers of this function must hold the events_lock. */ -void usbi_handle_disconnect(struct libusb_device_handle *handle) +void usbi_handle_disconnect(struct libusb_device_handle *dev_handle) { struct usbi_transfer *cur; struct usbi_transfer *to_cancel; usbi_dbg("device %d.%d", - handle->dev->bus_number, handle->dev->device_address); + dev_handle->dev->bus_number, dev_handle->dev->device_address); /* terminate all pending transfers with the LIBUSB_TRANSFER_NO_DEVICE * status code. @@ -2781,9 +2781,9 @@ void usbi_handle_disconnect(struct libusb_device_handle *handle) while (1) { to_cancel = NULL; - usbi_mutex_lock(&HANDLE_CTX(handle)->flying_transfers_lock); - list_for_each_entry(cur, &HANDLE_CTX(handle)->flying_transfers, list, struct usbi_transfer) - if (USBI_TRANSFER_TO_LIBUSB_TRANSFER(cur)->dev_handle == handle) { + usbi_mutex_lock(&HANDLE_CTX(dev_handle)->flying_transfers_lock); + list_for_each_entry(cur, &HANDLE_CTX(dev_handle)->flying_transfers, list, struct usbi_transfer) + if (USBI_TRANSFER_TO_LIBUSB_TRANSFER(cur)->dev_handle == dev_handle) { usbi_mutex_lock(&cur->flags_lock); if (cur->flags & USBI_TRANSFER_IN_FLIGHT) to_cancel = cur; @@ -2794,7 +2794,7 @@ void usbi_handle_disconnect(struct libusb_device_handle *handle) if (to_cancel) break; } - usbi_mutex_unlock(&HANDLE_CTX(handle)->flying_transfers_lock); + usbi_mutex_unlock(&HANDLE_CTX(dev_handle)->flying_transfers_lock); if (!to_cancel) break; diff --git a/libusb/libusb.h b/libusb/libusb.h index c7dccc08b..7fe01db8f 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -1334,7 +1334,7 @@ int LIBUSB_CALL libusb_get_ss_endpoint_companion_descriptor( struct libusb_ss_endpoint_companion_descriptor **ep_comp); void LIBUSB_CALL libusb_free_ss_endpoint_companion_descriptor( struct libusb_ss_endpoint_companion_descriptor *ep_comp); -int LIBUSB_CALL libusb_get_bos_descriptor(libusb_device_handle *handle, +int LIBUSB_CALL libusb_get_bos_descriptor(libusb_device_handle *dev_handle, struct libusb_bos_descriptor **bos); void LIBUSB_CALL libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos); int LIBUSB_CALL libusb_get_usb_2_0_extension_descriptor( @@ -1367,39 +1367,39 @@ int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev, int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev, unsigned char endpoint); -int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **handle); +int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **dev_handle); void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle); libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle); -int LIBUSB_CALL libusb_set_configuration(libusb_device_handle *dev, +int LIBUSB_CALL libusb_set_configuration(libusb_device_handle *dev_handle, int configuration); -int LIBUSB_CALL libusb_claim_interface(libusb_device_handle *dev, +int LIBUSB_CALL libusb_claim_interface(libusb_device_handle *dev_handle, int interface_number); -int LIBUSB_CALL libusb_release_interface(libusb_device_handle *dev, +int LIBUSB_CALL libusb_release_interface(libusb_device_handle *dev_handle, int interface_number); libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid( libusb_context *ctx, uint16_t vendor_id, uint16_t product_id); -int LIBUSB_CALL libusb_set_interface_alt_setting(libusb_device_handle *dev, +int LIBUSB_CALL libusb_set_interface_alt_setting(libusb_device_handle *dev_handle, int interface_number, int alternate_setting); -int LIBUSB_CALL libusb_clear_halt(libusb_device_handle *dev, +int LIBUSB_CALL libusb_clear_halt(libusb_device_handle *dev_handle, unsigned char endpoint); -int LIBUSB_CALL libusb_reset_device(libusb_device_handle *dev); +int LIBUSB_CALL libusb_reset_device(libusb_device_handle *dev_handle); -int LIBUSB_CALL libusb_alloc_streams(libusb_device_handle *dev, +int LIBUSB_CALL libusb_alloc_streams(libusb_device_handle *dev_handle, uint32_t num_streams, unsigned char *endpoints, int num_endpoints); -int LIBUSB_CALL libusb_free_streams(libusb_device_handle *dev, +int LIBUSB_CALL libusb_free_streams(libusb_device_handle *dev_handle, unsigned char *endpoints, int num_endpoints); -int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle *dev, +int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle *dev_handle, int interface_number); -int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle *dev, +int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle *dev_handle, int interface_number); -int LIBUSB_CALL libusb_attach_kernel_driver(libusb_device_handle *dev, +int LIBUSB_CALL libusb_attach_kernel_driver(libusb_device_handle *dev_handle, int interface_number); int LIBUSB_CALL libusb_set_auto_detach_kernel_driver( - libusb_device_handle *dev, int enable); + libusb_device_handle *dev_handle, int enable); /* async I/O */ @@ -1754,17 +1754,17 @@ int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle, * This is a convenience function which formulates the appropriate control * message to retrieve the descriptor. * - * \param dev a device handle + * \param dev_handle a device handle * \param desc_type the descriptor type, see \ref libusb_descriptor_type * \param desc_index the index of the descriptor to retrieve * \param data output buffer for descriptor * \param length size of data buffer * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure */ -static inline int libusb_get_descriptor(libusb_device_handle *dev, +static inline int libusb_get_descriptor(libusb_device_handle *dev_handle, uint8_t desc_type, uint8_t desc_index, unsigned char *data, int length) { - return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN, + return libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t) ((desc_type << 8) | desc_index), 0, data, (uint16_t) length, 1000); } @@ -1775,7 +1775,7 @@ static inline int libusb_get_descriptor(libusb_device_handle *dev, * message to retrieve the descriptor. The string returned is Unicode, as * detailed in the USB specifications. * - * \param dev a device handle + * \param dev_handle a device handle * \param desc_index the index of the descriptor to retrieve * \param langid the language ID for the string descriptor * \param data output buffer for descriptor @@ -1783,15 +1783,15 @@ static inline int libusb_get_descriptor(libusb_device_handle *dev, * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure * \see libusb_get_string_descriptor_ascii() */ -static inline int libusb_get_string_descriptor(libusb_device_handle *dev, +static inline int libusb_get_string_descriptor(libusb_device_handle *dev_handle, uint8_t desc_index, uint16_t langid, unsigned char *data, int length) { - return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN, + return libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t)((LIBUSB_DT_STRING << 8) | desc_index), langid, data, (uint16_t) length, 1000); } -int LIBUSB_CALL libusb_get_string_descriptor_ascii(libusb_device_handle *dev, +int LIBUSB_CALL libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle, uint8_t desc_index, unsigned char *data, int length); /* polling and timeouts */ @@ -1967,7 +1967,7 @@ typedef int (LIBUSB_CALL *libusb_hotplug_callback_fn)(libusb_context *ctx, * \param[in] dev_class the device class to match or \ref LIBUSB_HOTPLUG_MATCH_ANY * \param[in] cb_fn the function to be invoked on a matching event/device * \param[in] user_data user data to pass to the callback function - * \param[out] handle pointer to store the handle of the allocated callback (can be NULL) + * \param[out] callback_handle pointer to store the handle of the allocated callback (can be NULL) * \returns LIBUSB_SUCCESS on success LIBUSB_ERROR code on failure */ int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx, @@ -1977,7 +1977,7 @@ int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx, int dev_class, libusb_hotplug_callback_fn cb_fn, void *user_data, - libusb_hotplug_callback_handle *handle); + libusb_hotplug_callback_handle *callback_handle); /** \ingroup hotplug * Deregisters a hotplug callback. @@ -1988,10 +1988,10 @@ int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx, * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 * * \param[in] ctx context this callback is registered with - * \param[in] handle the handle of the callback to deregister + * \param[in] callback_handle the handle of the callback to deregister */ void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx, - libusb_hotplug_callback_handle handle); + libusb_hotplug_callback_handle callback_handle); #ifdef __cplusplus } diff --git a/libusb/libusbi.h b/libusb/libusbi.h index 9ffee409d..75a5a8138 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -507,7 +507,7 @@ struct libusb_device *usbi_alloc_device(struct libusb_context *ctx, struct libusb_device *usbi_get_device_by_session_id(struct libusb_context *ctx, unsigned long session_id); int usbi_sanitize_device(struct libusb_device *dev); -void usbi_handle_disconnect(struct libusb_device_handle *handle); +void usbi_handle_disconnect(struct libusb_device_handle *dev_handle); int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, enum libusb_transfer_status status); @@ -704,7 +704,7 @@ struct usbi_os_backend { * Do not worry about freeing the handle on failed open, the upper layers * do this for you. */ - int (*open)(struct libusb_device_handle *handle); + int (*open)(struct libusb_device_handle *dev_handle); /* Close a device such that the handle cannot be used again. Your backend * should destroy any resources that were allocated in the open path. @@ -714,7 +714,7 @@ struct usbi_os_backend { * * This function is called when the user closes a device handle. */ - void (*close)(struct libusb_device_handle *handle); + void (*close)(struct libusb_device_handle *dev_handle); /* Retrieve the device descriptor from a device. * @@ -821,7 +821,7 @@ struct usbi_os_backend { * blocking * - another LIBUSB_ERROR code on other failure. */ - int (*get_configuration)(struct libusb_device_handle *handle, int *config); + int (*get_configuration)(struct libusb_device_handle *dev_handle, int *config); /* Set the active configuration for a device. * @@ -838,7 +838,7 @@ struct usbi_os_backend { * was opened * - another LIBUSB_ERROR code on other failure. */ - int (*set_configuration)(struct libusb_device_handle *handle, int config); + int (*set_configuration)(struct libusb_device_handle *dev_handle, int config); /* Claim an interface. When claimed, the application can then perform * I/O to an interface's endpoints. @@ -857,7 +857,7 @@ struct usbi_os_backend { * was opened * - another LIBUSB_ERROR code on other failure */ - int (*claim_interface)(struct libusb_device_handle *handle, int interface_number); + int (*claim_interface)(struct libusb_device_handle *dev_handle, int interface_number); /* Release a previously claimed interface. * @@ -874,7 +874,7 @@ struct usbi_os_backend { * was opened * - another LIBUSB_ERROR code on other failure */ - int (*release_interface)(struct libusb_device_handle *handle, int interface_number); + int (*release_interface)(struct libusb_device_handle *dev_handle, int interface_number); /* Set the alternate setting for an interface. * @@ -890,7 +890,7 @@ struct usbi_os_backend { * was opened * - another LIBUSB_ERROR code on other failure */ - int (*set_interface_altsetting)(struct libusb_device_handle *handle, + int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle, int interface_number, int altsetting); /* Clear a halt/stall condition on an endpoint. @@ -904,12 +904,12 @@ struct usbi_os_backend { * was opened * - another LIBUSB_ERROR code on other failure */ - int (*clear_halt)(struct libusb_device_handle *handle, + int (*clear_halt)(struct libusb_device_handle *dev_handle, unsigned char endpoint); /* Perform a USB port reset to reinitialize a device. * - * If possible, the handle should still be usable after the reset + * If possible, the device handle should still be usable after the reset * completes, assuming that the device descriptors did not change during * reset and all previous interface state can be restored. * @@ -923,14 +923,14 @@ struct usbi_os_backend { * has been disconnected since it was opened * - another LIBUSB_ERROR code on other failure */ - int (*reset_device)(struct libusb_device_handle *handle); + int (*reset_device)(struct libusb_device_handle *dev_handle); /* Alloc num_streams usb3 bulk streams on the passed in endpoints */ - int (*alloc_streams)(struct libusb_device_handle *handle, + int (*alloc_streams)(struct libusb_device_handle *dev_handle, uint32_t num_streams, unsigned char *endpoints, int num_endpoints); /* Free usb3 bulk streams allocated with alloc_streams */ - int (*free_streams)(struct libusb_device_handle *handle, + int (*free_streams)(struct libusb_device_handle *dev_handle, unsigned char *endpoints, int num_endpoints); /* Determine if a kernel driver is active on an interface. Optional. @@ -945,7 +945,7 @@ struct usbi_os_backend { * was opened * - another LIBUSB_ERROR code on other failure */ - int (*kernel_driver_active)(struct libusb_device_handle *handle, + int (*kernel_driver_active)(struct libusb_device_handle *dev_handle, int interface_number); /* Detach a kernel driver from an interface. Optional. @@ -961,7 +961,7 @@ struct usbi_os_backend { * was opened * - another LIBUSB_ERROR code on other failure */ - int (*detach_kernel_driver)(struct libusb_device_handle *handle, + int (*detach_kernel_driver)(struct libusb_device_handle *dev_handle, int interface_number); /* Attach a kernel driver to an interface. Optional. @@ -978,7 +978,7 @@ struct usbi_os_backend { * preventing reattachment * - another LIBUSB_ERROR code on other failure */ - int (*attach_kernel_driver)(struct libusb_device_handle *handle, + int (*attach_kernel_driver)(struct libusb_device_handle *dev_handle, int interface_number); /* Destroy a device. Optional. diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 9bb57fa66..bb4ce8e1d 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11054 +#define LIBUSB_NANO 11055 From 7ee92df12adb8015451aaecfeccd7dd62cc2314e Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Wed, 24 Feb 2016 01:07:20 -0800 Subject: [PATCH 136/222] Misc: Prefix doxygen references in order to namespace libusb This change add "libusb_" to every group and page definition (and updates all references accordingly) so that generated man pages are namespaced for libusb, thus avoiding possible conflict with other packages. Closes #131 Signed-off-by: Chris Dickens --- libusb/core.c | 96 ++++++++++++++--------------- libusb/descriptor.c | 34 +++++------ libusb/hotplug.c | 8 +-- libusb/io.c | 122 ++++++++++++++++++------------------- libusb/libusb.h | 138 +++++++++++++++++++++--------------------- libusb/strerror.c | 6 +- libusb/sync.c | 14 ++--- libusb/version_nano.h | 2 +- 8 files changed, 210 insertions(+), 210 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 4d6d37717..9d6479423 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -102,7 +102,7 @@ struct list_head active_contexts_list; * * \section API Application Programming Interface (API) * - * See the \ref api page for a complete list of the libusb functions. + * See the \ref libusb_api page for a complete list of the libusb functions. * * \section features Library features * @@ -114,7 +114,7 @@ struct list_head active_contexts_list; * usually won't need to thread) * - Lightweight with lean API * - Compatible with libusb-0.1 through the libusb-compat-0.1 translation layer - * - Hotplug support (on some platforms). See \ref hotplug. + * - Hotplug support (on some platforms). See \ref libusb_hotplug. * * \section gettingstarted Getting Started * @@ -122,7 +122,7 @@ struct list_head active_contexts_list; * links to the different categories of libusb's functionality. * * One decision you will have to make is whether to use the synchronous - * or the asynchronous data transfer interface. The \ref io documentation + * or the asynchronous data transfer interface. The \ref libusb_io documentation * provides some insight into this topic. * * Some example programs can be found in the libusb source distribution under @@ -133,7 +133,7 @@ struct list_head active_contexts_list; * * libusb functions typically return 0 on success or a negative error code * on failure. These negative error codes relate to LIBUSB_ERROR constants - * which are listed on the \ref misc "miscellaneous" documentation page. + * which are listed on the \ref libusb_misc "miscellaneous" documentation page. * * \section msglog Debug message logging * @@ -178,12 +178,12 @@ struct list_head active_contexts_list; * * \section remarks Other remarks * - * libusb does have imperfections. The \ref caveats "caveats" page attempts + * libusb does have imperfections. The \ref libusb_caveats "caveats" page attempts * to document these. */ /** - * \page caveats Caveats + * \page libusb_caveats Caveats * * \section devresets Device resets * @@ -299,7 +299,7 @@ if (cfg != desired) */ /** - * \page contexts Contexts + * \page libusb_contexts Contexts * * It is possible that libusb may be used simultaneously from two independent * libraries linked into the same executable. For example, if your application @@ -338,7 +338,7 @@ if (cfg != desired) */ /** - * \page api Application Programming Interface + * \page libusb_api Application Programming Interface * * This is the complete list of libusb functions, structures and * enumerations in alphabetical order. @@ -486,14 +486,14 @@ if (cfg != desired) */ /** - * @defgroup lib Library initialization/deinitialization + * @defgroup libusb_lib Library initialization/deinitialization * This page details how to initialize and deinitialize libusb. Initialization * must be performed before using any libusb functionality, and similarly you * must not call any libusb functions after deinitialization. */ /** - * @defgroup dev Device handling and enumeration + * @defgroup libusb_dev Device handling and enumeration * The functionality documented below is designed to help with the following * operations: * - Enumerating the USB devices currently attached to the system @@ -603,7 +603,7 @@ libusb_free_device_list(list, 1); * libusb_close(). */ -/** @defgroup misc Miscellaneous */ +/** @defgroup libusb_misc Miscellaneous */ /* we traverse usbfs without knowing how many devices we are going to find. * so we create this discovered_devs model which is similar to a linked-list @@ -775,7 +775,7 @@ struct libusb_device *usbi_get_device_by_session_id(struct libusb_context *ctx, return ret; } -/** @ingroup dev +/** @ingroup libusb_dev * Returns a list of USB devices currently attached to the system. This is * your entry point into finding a USB device to operate. * @@ -855,7 +855,7 @@ ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx, return len; } -/** \ingroup dev +/** \ingroup libusb_dev * Frees a list of devices previously discovered using * libusb_get_device_list(). If the unref_devices parameter is set, the * reference count of each device in the list is decremented by 1. @@ -878,7 +878,7 @@ void API_EXPORTED libusb_free_device_list(libusb_device **list, free(list); } -/** \ingroup dev +/** \ingroup libusb_dev * Get the number of the bus that a device is connected to. * \param dev a device * \returns the bus number @@ -888,7 +888,7 @@ uint8_t API_EXPORTED libusb_get_bus_number(libusb_device *dev) return dev->bus_number; } -/** \ingroup dev +/** \ingroup libusb_dev * Get the number of the port that a device is connected to. * Unless the OS does something funky, or you are hot-plugging USB extension cards, * the port number returned by this call is usually guaranteed to be uniquely tied @@ -907,7 +907,7 @@ uint8_t API_EXPORTED libusb_get_port_number(libusb_device *dev) return dev->port_number; } -/** \ingroup dev +/** \ingroup libusb_dev * Get the list of all port numbers from root for the specified device * * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 @@ -941,7 +941,7 @@ int API_EXPORTED libusb_get_port_numbers(libusb_device *dev, return port_numbers_len - i; } -/** \ingroup dev +/** \ingroup libusb_dev * Deprecated please use libusb_get_port_numbers instead. */ int API_EXPORTED libusb_get_port_path(libusb_context *ctx, libusb_device *dev, @@ -952,7 +952,7 @@ int API_EXPORTED libusb_get_port_path(libusb_context *ctx, libusb_device *dev, return libusb_get_port_numbers(dev, port_numbers, port_numbers_len); } -/** \ingroup dev +/** \ingroup libusb_dev * Get the the parent from the specified device. * \param dev a device * \returns the device parent or NULL if not available @@ -969,7 +969,7 @@ libusb_device * LIBUSB_CALL libusb_get_parent(libusb_device *dev) return dev->parent_dev; } -/** \ingroup dev +/** \ingroup libusb_dev * Get the address of the device on the bus it is connected to. * \param dev a device * \returns the device address @@ -979,7 +979,7 @@ uint8_t API_EXPORTED libusb_get_device_address(libusb_device *dev) return dev->device_address; } -/** \ingroup dev +/** \ingroup libusb_dev * Get the negotiated connection speed for a device. * \param dev a device * \returns a \ref libusb_speed code, where LIBUSB_SPEED_UNKNOWN means that @@ -1015,7 +1015,7 @@ static const struct libusb_endpoint_descriptor *find_endpoint( return NULL; } -/** \ingroup dev +/** \ingroup libusb_dev * Convenience function to retrieve the wMaxPacketSize value for a particular * endpoint in the active device configuration. * @@ -1058,7 +1058,7 @@ int API_EXPORTED libusb_get_max_packet_size(libusb_device *dev, return r; } -/** \ingroup dev +/** \ingroup libusb_dev * Calculate the maximum packet size which a specific endpoint is capable is * sending or receiving in the duration of 1 microframe * @@ -1119,7 +1119,7 @@ int API_EXPORTED libusb_get_max_iso_packet_size(libusb_device *dev, return r; } -/** \ingroup dev +/** \ingroup libusb_dev * Increment the reference count of a device. * \param dev the device to reference * \returns the same device @@ -1133,7 +1133,7 @@ libusb_device * LIBUSB_CALL libusb_ref_device(libusb_device *dev) return dev; } -/** \ingroup dev +/** \ingroup libusb_dev * Decrement the reference count of a device. If the decrement operation * causes the reference count to reach zero, the device shall be destroyed. * \param dev the device to unreference @@ -1205,7 +1205,7 @@ int usbi_clear_event(struct libusb_context *ctx) return 0; } -/** \ingroup dev +/** \ingroup libusb_dev * Open a device and obtain a device handle. A handle allows you to perform * I/O on the device in question. * @@ -1269,7 +1269,7 @@ int API_EXPORTED libusb_open(libusb_device *dev, return 0; } -/** \ingroup dev +/** \ingroup libusb_dev * Convenience function for finding a device with a particular * idVendor/idProduct combination. This function is intended * for those scenarios where you are using libusb to knock up a quick test @@ -1379,7 +1379,7 @@ static void do_close(struct libusb_context *ctx, free(dev_handle); } -/** \ingroup dev +/** \ingroup libusb_dev * Close a device handle. Should be called on all open handles before your * application exits. * @@ -1435,7 +1435,7 @@ void API_EXPORTED libusb_close(libusb_device_handle *dev_handle) libusb_unlock_events(ctx); } -/** \ingroup dev +/** \ingroup libusb_dev * Get the underlying device for a device handle. This function does not modify * the reference count of the returned device, so do not feel compelled to * unreference it when you are done. @@ -1448,7 +1448,7 @@ libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle) return dev_handle->dev; } -/** \ingroup dev +/** \ingroup libusb_dev * Determine the bConfigurationValue of the currently active configuration. * * You could formulate your own control request to obtain this information, @@ -1499,7 +1499,7 @@ int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev_handle, return r; } -/** \ingroup dev +/** \ingroup libusb_dev * Set the active configuration for a device. * * The operating system may or may not have already set an active @@ -1553,7 +1553,7 @@ int API_EXPORTED libusb_set_configuration(libusb_device_handle *dev_handle, return usbi_backend->set_configuration(dev_handle, configuration); } -/** \ingroup dev +/** \ingroup libusb_dev * Claim an interface on a given device handle. You must claim the interface * you wish to use before you can perform I/O on any of its endpoints. * @@ -1606,7 +1606,7 @@ int API_EXPORTED libusb_claim_interface(libusb_device_handle *dev_handle, return r; } -/** \ingroup dev +/** \ingroup libusb_dev * Release an interface previously claimed with libusb_claim_interface(). You * should release all claimed interfaces before closing a device handle. * @@ -1649,7 +1649,7 @@ int API_EXPORTED libusb_release_interface(libusb_device_handle *dev_handle, return r; } -/** \ingroup dev +/** \ingroup libusb_dev * Activate an alternate setting for an interface. The interface must have * been previously claimed with libusb_claim_interface(). * @@ -1694,7 +1694,7 @@ int API_EXPORTED libusb_set_interface_alt_setting(libusb_device_handle *dev_hand alternate_setting); } -/** \ingroup dev +/** \ingroup libusb_dev * Clear the halt/stall condition for an endpoint. Endpoints with halt status * are unable to receive or transmit data until the halt condition is stalled. * @@ -1720,7 +1720,7 @@ int API_EXPORTED libusb_clear_halt(libusb_device_handle *dev_handle, return usbi_backend->clear_halt(dev_handle, endpoint); } -/** \ingroup dev +/** \ingroup libusb_dev * Perform a USB port reset to reinitialize a device. The system will attempt * to restore the previous configuration and alternate settings after the * reset has completed. @@ -1748,7 +1748,7 @@ int API_EXPORTED libusb_reset_device(libusb_device_handle *dev_handle) return usbi_backend->reset_device(dev_handle); } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Allocate up to num_streams usb bulk streams on the specified endpoints. This * function takes an array of endpoints rather then a single endpoint because * some protocols require that endpoints are setup with similar stream ids. @@ -1784,7 +1784,7 @@ int API_EXPORTED libusb_alloc_streams(libusb_device_handle *dev_handle, return LIBUSB_ERROR_NOT_SUPPORTED; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Free usb bulk streams allocated with libusb_alloc_streams(). * * Note streams are automatically free-ed when releasing an interface. @@ -1811,7 +1811,7 @@ int API_EXPORTED libusb_free_streams(libusb_device_handle *dev_handle, return LIBUSB_ERROR_NOT_SUPPORTED; } -/** \ingroup dev +/** \ingroup libusb_dev * Determine if a kernel driver is active on an interface. If a kernel driver * is active, you cannot claim the interface, and libusb will be unable to * perform I/O. @@ -1842,7 +1842,7 @@ int API_EXPORTED libusb_kernel_driver_active(libusb_device_handle *dev_handle, return LIBUSB_ERROR_NOT_SUPPORTED; } -/** \ingroup dev +/** \ingroup libusb_dev * Detach a kernel driver from an interface. If successful, you will then be * able to claim the interface and perform I/O. * @@ -1877,7 +1877,7 @@ int API_EXPORTED libusb_detach_kernel_driver(libusb_device_handle *dev_handle, return LIBUSB_ERROR_NOT_SUPPORTED; } -/** \ingroup dev +/** \ingroup libusb_dev * Re-attach an interface's kernel driver, which was previously detached * using libusb_detach_kernel_driver(). This call is only effective on * Linux and returns LIBUSB_ERROR_NOT_SUPPORTED on all other platforms. @@ -1911,7 +1911,7 @@ int API_EXPORTED libusb_attach_kernel_driver(libusb_device_handle *dev_handle, return LIBUSB_ERROR_NOT_SUPPORTED; } -/** \ingroup dev +/** \ingroup libusb_dev * Enable/disable libusb's automatic kernel driver detachment. When this is * enabled libusb will automatically detach the kernel driver on an interface * when claiming the interface, and attach it when releasing the interface. @@ -1943,7 +1943,7 @@ int API_EXPORTED libusb_set_auto_detach_kernel_driver( return LIBUSB_SUCCESS; } -/** \ingroup lib +/** \ingroup libusb_lib * Set log message verbosity. * * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever @@ -1975,7 +1975,7 @@ void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level) ctx->debug = level; } -/** \ingroup lib +/** \ingroup libusb_lib * Initialize libusb. This function must be called before calling any other * libusb function. * @@ -1986,7 +1986,7 @@ void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level) * \param context Optional output location for context pointer. * Only valid on return code 0. * \returns 0 on success, or a LIBUSB_ERROR code on failure - * \see contexts + * \see libusb_contexts */ int API_EXPORTED libusb_init(libusb_context **context) { @@ -2097,7 +2097,7 @@ int API_EXPORTED libusb_init(libusb_context **context) return r; } -/** \ingroup lib +/** \ingroup libusb_lib * Deinitialize libusb. Should be called after closing all open devices and * before your application terminates. * \param ctx the context to deinitialize, or NULL for the default context @@ -2168,7 +2168,7 @@ void API_EXPORTED libusb_exit(struct libusb_context *ctx) free(ctx); } -/** \ingroup misc +/** \ingroup libusb_misc * Check at runtime if the loaded library has a given capability. * This call should be performed after \ref libusb_init(), to ensure the * backend has updated its capability set. @@ -2390,7 +2390,7 @@ void usbi_log(struct libusb_context *ctx, enum libusb_log_level level, va_end (args); } -/** \ingroup misc +/** \ingroup libusb_misc * Returns a constant NULL-terminated string with the ASCII name of a libusb * error or transfer status code. The caller must not free() the returned * string. @@ -2450,7 +2450,7 @@ DEFAULT_VISIBILITY const char * LIBUSB_CALL libusb_error_name(int error_code) } } -/** \ingroup misc +/** \ingroup libusb_misc * Returns a pointer to const struct libusb_version with the version * (major, minor, micro, nano and rc) of the running library. */ diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 402c91da0..ccf7fe426 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -35,7 +35,7 @@ #define ENDPOINT_DESC_LENGTH 7 #define ENDPOINT_AUDIO_DESC_LENGTH 9 -/** @defgroup desc USB descriptors +/** @defgroup libusb_desc USB descriptors * This page details how to examine the various standard USB descriptors * for detected devices */ @@ -532,7 +532,7 @@ int usbi_device_cache_descriptor(libusb_device *dev) return LIBUSB_SUCCESS; } -/** \ingroup desc +/** \ingroup libusb_desc * Get the USB device descriptor for a given device. * * This is a non-blocking function; the device descriptor is cached in memory. @@ -553,7 +553,7 @@ int API_EXPORTED libusb_get_device_descriptor(libusb_device *dev, return 0; } -/** \ingroup desc +/** \ingroup libusb_desc * Get the USB configuration descriptor for the currently active configuration. * This is a non-blocking function which does not involve any requests being * sent to the device. @@ -600,7 +600,7 @@ int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev, return r; } -/** \ingroup desc +/** \ingroup libusb_desc * Get a USB configuration descriptor based on its index. * This is a non-blocking function which does not involve any requests being * sent to the device. @@ -683,7 +683,7 @@ int usbi_get_config_index_by_value(struct libusb_device *dev, return 0; } -/** \ingroup desc +/** \ingroup libusb_desc * Get a USB configuration descriptor with a specific bConfigurationValue. * This is a non-blocking function which does not involve any requests being * sent to the device. @@ -723,7 +723,7 @@ int API_EXPORTED libusb_get_config_descriptor_by_value(libusb_device *dev, return libusb_get_config_descriptor(dev, (uint8_t) idx, config); } -/** \ingroup desc +/** \ingroup libusb_desc * Free a configuration descriptor obtained from * libusb_get_active_config_descriptor() or libusb_get_config_descriptor(). * It is safe to call this function with a NULL config parameter, in which @@ -741,7 +741,7 @@ void API_EXPORTED libusb_free_config_descriptor( free(config); } -/** \ingroup desc +/** \ingroup libusb_desc * Get an endpoints superspeed endpoint companion descriptor (if any) * * \param ctx the context to operate on, or NULL for the default context @@ -791,7 +791,7 @@ int API_EXPORTED libusb_get_ss_endpoint_companion_descriptor( return LIBUSB_ERROR_NOT_FOUND; } -/** \ingroup desc +/** \ingroup libusb_desc * Free a superspeed endpoint companion descriptor obtained from * libusb_get_ss_endpoint_companion_descriptor(). * It is safe to call this function with a NULL ep_comp parameter, in which @@ -884,7 +884,7 @@ static int parse_bos(struct libusb_context *ctx, return LIBUSB_SUCCESS; } -/** \ingroup desc +/** \ingroup libusb_desc * Get a Binary Object Store (BOS) descriptor * This is a BLOCKING function, which will send requests to the device. * @@ -937,7 +937,7 @@ int API_EXPORTED libusb_get_bos_descriptor(libusb_device_handle *dev_handle, return r; } -/** \ingroup desc +/** \ingroup libusb_desc * Free a BOS descriptor obtained from libusb_get_bos_descriptor(). * It is safe to call this function with a NULL bos parameter, in which * case the function simply returns. @@ -956,7 +956,7 @@ void API_EXPORTED libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos) free(bos); } -/** \ingroup desc +/** \ingroup libusb_desc * Get an USB 2.0 Extension descriptor * * \param ctx the context to operate on, or NULL for the default context @@ -1000,7 +1000,7 @@ int API_EXPORTED libusb_get_usb_2_0_extension_descriptor( return LIBUSB_SUCCESS; } -/** \ingroup desc +/** \ingroup libusb_desc * Free a USB 2.0 Extension descriptor obtained from * libusb_get_usb_2_0_extension_descriptor(). * It is safe to call this function with a NULL usb_2_0_extension parameter, @@ -1014,7 +1014,7 @@ void API_EXPORTED libusb_free_usb_2_0_extension_descriptor( free(usb_2_0_extension); } -/** \ingroup desc +/** \ingroup libusb_desc * Get a SuperSpeed USB Device Capability descriptor * * \param ctx the context to operate on, or NULL for the default context @@ -1058,7 +1058,7 @@ int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor( return LIBUSB_SUCCESS; } -/** \ingroup desc +/** \ingroup libusb_desc * Free a SuperSpeed USB Device Capability descriptor obtained from * libusb_get_ss_usb_device_capability_descriptor(). * It is safe to call this function with a NULL ss_usb_device_cap @@ -1072,7 +1072,7 @@ void API_EXPORTED libusb_free_ss_usb_device_capability_descriptor( free(ss_usb_device_cap); } -/** \ingroup desc +/** \ingroup libusb_desc * Get a Container ID descriptor * * \param ctx the context to operate on, or NULL for the default context @@ -1115,7 +1115,7 @@ int API_EXPORTED libusb_get_container_id_descriptor(struct libusb_context *ctx, return LIBUSB_SUCCESS; } -/** \ingroup desc +/** \ingroup libusb_desc * Free a Container ID descriptor obtained from * libusb_get_container_id_descriptor(). * It is safe to call this function with a NULL container_id parameter, @@ -1129,7 +1129,7 @@ void API_EXPORTED libusb_free_container_id_descriptor( free(container_id); } -/** \ingroup desc +/** \ingroup libusb_desc * Retrieve a string descriptor in C style ASCII. * * Wrapper around libusb_get_string_descriptor(). Uses the first language diff --git a/libusb/hotplug.c b/libusb/hotplug.c index 85d44af55..5db8d0b77 100644 --- a/libusb/hotplug.c +++ b/libusb/hotplug.c @@ -34,14 +34,14 @@ #include "hotplug.h" /** - * @defgroup hotplug Device hotplug event notification + * @defgroup libusb_hotplug Device hotplug event notification * This page details how to use the libusb hotplug interface, where available. * * Be mindful that not all platforms currently implement hotplug notification and * that you should first call on \ref libusb_has_capability() with parameter * \ref LIBUSB_CAP_HAS_HOTPLUG to confirm that hotplug support is available. * - * \page hotplug Device hotplug event notification + * \page libusb_hotplug Device hotplug event notification * * \section hotplug_intro Introduction * @@ -83,8 +83,8 @@ * safe to call any libusb function that takes a libusb_device. It also safe to * open a device and submit asynchronous transfers. However, most other functions * that take a libusb_device_handle are not safe to call. Examples of such - * functions are any of the \ref syncio "synchronous API" functions or the blocking - * functions that retrieve various \ref desc "USB descriptors". These functions must + * functions are any of the \ref libusb_syncio "synchronous API" functions or the blocking + * functions that retrieve various \ref libusb_desc "USB descriptors". These functions must * be used outside of the context of the hotplug callback. * * When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT event the only safe function diff --git a/libusb/io.c b/libusb/io.c index 908acfd6b..74dba4b2d 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -41,7 +41,7 @@ #include "hotplug.h" /** - * \page io Synchronous and asynchronous device I/O + * \page libusb_io Synchronous and asynchronous device I/O * * \section io_intro Introduction * @@ -55,8 +55,8 @@ * * Once you have read through the following discussion, you should consult the * detailed API documentation pages for the details: - * - \ref syncio - * - \ref asyncio + * - \ref libusb_syncio + * - \ref libusb_asyncio * * \section theory Transfers at a logical level * @@ -124,7 +124,7 @@ if (r == 0 && actual_length == sizeof(data)) { * request has been submitted. * * For details on how to use the synchronous API, see the - * \ref syncio "synchronous I/O API documentation" pages. + * \ref libusb_syncio "synchronous I/O API documentation" pages. * * \section async The asynchronous interface * @@ -165,12 +165,12 @@ if (r == 0 && actual_length == sizeof(data)) { * calls to the asynchronous interface. * * For details on how to use the asynchronous API, see the - * \ref asyncio "asynchronous I/O API" documentation pages. + * \ref libusb_asyncio "asynchronous I/O API" documentation pages. */ /** - * \page packetoverflow Packets and overflows + * \page libusb_packetoverflow Packets and overflows * * \section packets Packet abstraction * @@ -212,13 +212,13 @@ if (r == 0 && actual_length == sizeof(data)) { */ /** - * @defgroup asyncio Asynchronous device I/O + * @defgroup libusb_asyncio Asynchronous device I/O * * This page details libusb's asynchronous (non-blocking) API for USB device * I/O. This interface is very powerful but is also quite complex - you will * need to read this page carefully to understand the necessary considerations * and issues surrounding use of this interface. Simplistic applications - * may wish to consider the \ref syncio "synchronous I/O API" instead. + * may wish to consider the \ref libusb_syncio "synchronous I/O API" instead. * * The asynchronous interface is built around the idea of separating transfer * submission and handling of transfer completion (the synchronous model @@ -296,8 +296,8 @@ if (r == 0 && actual_length == sizeof(data)) { * Important Note: The user-specified callback is called from an event * handling context. It is therefore important that no calls are made into * libusb that will attempt to perform any event handling. Examples of such - * functions are any listed in the \ref syncio "synchronous API" and any of - * the blocking functions that retrieve \ref desc "USB descriptors". + * functions are any listed in the \ref libusb_syncio "synchronous API" and any of + * the blocking functions that retrieve \ref libusb_desc "USB descriptors". * * \subsection Deallocation * @@ -343,7 +343,7 @@ if (r == 0 && actual_length == sizeof(data)) { * your application may submit a request for data on an IN endpoint which is * smaller than the data that the device wishes to send. In some circumstances * this will cause an overflow, which is a nasty condition to deal with. See - * the \ref packetoverflow page for discussion. + * the \ref libusb_packetoverflow page for discussion. * * \section asyncctrl Considerations for control transfers * @@ -534,7 +534,7 @@ if (r == 0 && actual_length == sizeof(data)) { * below for details. * * If you prefer a single threaded approach with a single central event loop, - * see the \ref poll "polling and timing" section for how to integrate libusb + * see the \ref libusb_poll "polling and timing" section for how to integrate libusb * into your application's main event loop. * * \section eventthread Using an event handling thread @@ -561,7 +561,7 @@ void *event_thread_func(void *ctx) * libusb_handle_events() will not return. * * There are 2 different ways of dealing with this, depending on if your - * application uses libusb' \ref hotplug "hotplug" support or not. + * application uses libusb' \ref libusb_hotplug "hotplug" support or not. * * Applications which do not use hotplug support, should not start the event * thread until after their first call to libusb_open(), and should stop the @@ -586,7 +586,7 @@ void my_close_handle(libusb_device_handle *dev_handle) * should stop the thread at program exit as follows: \code void my_libusb_exit(void) -{ +{ event_thread_run = 0; libusb_hotplug_deregister_callback(ctx, hotplug_cb_handle); // This wakes up libusb_handle_events() pthread_join(event_thread); @@ -596,12 +596,12 @@ void my_libusb_exit(void) */ /** - * @defgroup poll Polling and timing + * @defgroup libusb_poll Polling and timing * * This page documents libusb's functions for polling events and timing. * These functions are only necessary for users of the - * \ref asyncio "asynchronous API". If you are only using the simpler - * \ref syncio "synchronous API" then you do not need to ever call these + * \ref libusb_asyncio "asynchronous API". If you are only using the simpler + * \ref libusb_syncio "synchronous API" then you do not need to ever call these * functions. * * The justification for the functionality described here has already been @@ -653,7 +653,7 @@ while (user_has_not_requested_exit) * sets of file descriptors or handling timeouts. libusb_handle_events() will * handle those details internally. * - * \section pollmain The more advanced option + * \section libusb_pollmain The more advanced option * * \note This functionality is currently only available on Unix-like platforms. * On Windows, libusb_get_pollfds() simply returns NULL. Applications which @@ -768,10 +768,10 @@ while (user has not requested application exit) { * entities are added to solve these problems. You do not need to be concerned * with these entities otherwise. * - * See the extra documentation: \ref mtasync + * See the extra documentation: \ref libusb_mtasync */ -/** \page mtasync Multi-threaded applications and asynchronous I/O +/** \page libusb_mtasync Multi-threaded applications and asynchronous I/O * * libusb is a thread-safe library, but extra considerations must be applied * to applications which interact with libusb from multiple threads. @@ -779,8 +779,8 @@ while (user has not requested application exit) { * The underlying issue that must be addressed is that all libusb I/O * revolves around monitoring file descriptors through the poll()/select() * system calls. This is directly exposed at the - * \ref asyncio "asynchronous interface" but it is important to note that the - * \ref syncio "synchronous interface" is implemented on top of the + * \ref libusb_asyncio "asynchronous interface" but it is important to note that the + * \ref libusb_syncio "synchronous interface" is implemented on top of the * asynchonrous interface, therefore the same considerations apply. * * The issue is that if two or more threads are concurrently calling poll() @@ -1230,7 +1230,7 @@ static int calculate_timeout(struct usbi_transfer *transfer) return 0; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Allocate a libusb transfer with a specified number of isochronous packet * descriptors. The returned transfer is pre-initialized for you. When the new * transfer is no longer needed, it should be freed with @@ -1275,7 +1275,7 @@ struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer( return transfer; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Free a transfer structure. This should be called for all transfers * allocated with libusb_alloc_transfer(). * @@ -1453,7 +1453,7 @@ static int remove_from_flying_list(struct usbi_transfer *transfer) return r; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Submit a transfer. This function will fire off the USB transfer and then * return immediately. * @@ -1528,7 +1528,7 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer) return r; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Asynchronously cancel a previously submitted transfer. * This function returns immediately, but this does not indicate cancellation * is complete. Your callback function will be invoked at some later time @@ -1577,7 +1577,7 @@ int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer) return r; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Set a transfers bulk stream id. Note users are advised to use * libusb_fill_bulk_stream_transfer() instead of calling this function * directly. @@ -1597,7 +1597,7 @@ void API_EXPORTED libusb_transfer_set_stream_id( itransfer->stream_id = stream_id; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Get a transfers bulk stream id. * * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 @@ -1699,7 +1699,7 @@ void usbi_signal_transfer_completion(struct usbi_transfer *transfer) usbi_mutex_unlock(&ctx->event_data_lock); } -/** \ingroup poll +/** \ingroup libusb_poll * Attempt to acquire the event handling lock. This lock is used to ensure that * only one thread is monitoring libusb event sources at any one time. * @@ -1716,7 +1716,7 @@ void usbi_signal_transfer_completion(struct usbi_transfer *transfer) * \param ctx the context to operate on, or NULL for the default context * \returns 0 if the lock was obtained successfully * \returns 1 if the lock was not obtained (i.e. another thread holds the lock) - * \ref mtasync + * \ref libusb_mtasync */ int API_EXPORTED libusb_try_lock_events(libusb_context *ctx) { @@ -1742,7 +1742,7 @@ int API_EXPORTED libusb_try_lock_events(libusb_context *ctx) return 0; } -/** \ingroup poll +/** \ingroup libusb_poll * Acquire the event handling lock, blocking until successful acquisition if * it is contended. This lock is used to ensure that only one thread is * monitoring libusb event sources at any one time. @@ -1758,7 +1758,7 @@ int API_EXPORTED libusb_try_lock_events(libusb_context *ctx) * as soon as possible. * * \param ctx the context to operate on, or NULL for the default context - * \ref mtasync + * \ref libusb_mtasync */ void API_EXPORTED libusb_lock_events(libusb_context *ctx) { @@ -1767,13 +1767,13 @@ void API_EXPORTED libusb_lock_events(libusb_context *ctx) ctx->event_handler_active = 1; } -/** \ingroup poll +/** \ingroup libusb_poll * Release the lock previously acquired with libusb_try_lock_events() or * libusb_lock_events(). Releasing this lock will wake up any threads blocked * on libusb_wait_for_event(). * * \param ctx the context to operate on, or NULL for the default context - * \ref mtasync + * \ref libusb_mtasync */ void API_EXPORTED libusb_unlock_events(libusb_context *ctx) { @@ -1789,7 +1789,7 @@ void API_EXPORTED libusb_unlock_events(libusb_context *ctx) usbi_mutex_unlock(&ctx->event_waiters_lock); } -/** \ingroup poll +/** \ingroup libusb_poll * Determine if it is still OK for this thread to be doing event handling. * * Sometimes, libusb needs to temporarily pause all event handlers, and this @@ -1797,7 +1797,7 @@ void API_EXPORTED libusb_unlock_events(libusb_context *ctx) * this is the case. * * If this function instructs your thread to give up the events lock, you - * should just continue the usual logic that is documented in \ref mtasync. + * should just continue the usual logic that is documented in \ref libusb_mtasync. * On the next iteration, your thread will fail to obtain the events lock, * and will hence become an event waiter. * @@ -1829,14 +1829,14 @@ int API_EXPORTED libusb_event_handling_ok(libusb_context *ctx) } -/** \ingroup poll +/** \ingroup libusb_poll * Determine if an active thread is handling events (i.e. if anyone is holding * the event handling lock). * * \param ctx the context to operate on, or NULL for the default context * \returns 1 if a thread is handling events * \returns 0 if there are no threads currently handling events - * \ref mtasync + * \ref libusb_mtasync */ int API_EXPORTED libusb_event_handler_active(libusb_context *ctx) { @@ -1856,7 +1856,7 @@ int API_EXPORTED libusb_event_handler_active(libusb_context *ctx) return ctx->event_handler_active; } -/** \ingroup poll +/** \ingroup libusb_poll * Interrupt any active thread that is handling events. This is mainly useful * for interrupting a dedicated event handling thread when an application * wishes to call libusb_exit(). @@ -1864,7 +1864,7 @@ int API_EXPORTED libusb_event_handler_active(libusb_context *ctx) * Since version 1.0.21, \ref LIBUSB_API_VERSION >= 0x01000105 * * \param ctx the context to operate on, or NULL for the default context - * \ref mtasync + * \ref libusb_mtasync */ void API_EXPORTED libusb_interrupt_event_handler(libusb_context *ctx) { @@ -1879,7 +1879,7 @@ void API_EXPORTED libusb_interrupt_event_handler(libusb_context *ctx) usbi_mutex_unlock(&ctx->event_data_lock); } -/** \ingroup poll +/** \ingroup libusb_poll * Acquire the event waiters lock. This lock is designed to be obtained under * the situation where you want to be aware when events are completed, but * some other thread is event handling so calling libusb_handle_events() is not @@ -1896,7 +1896,7 @@ void API_EXPORTED libusb_interrupt_event_handler(libusb_context *ctx) * locking. * * \param ctx the context to operate on, or NULL for the default context - * \ref mtasync + * \ref libusb_mtasync */ void API_EXPORTED libusb_lock_event_waiters(libusb_context *ctx) { @@ -1904,10 +1904,10 @@ void API_EXPORTED libusb_lock_event_waiters(libusb_context *ctx) usbi_mutex_lock(&ctx->event_waiters_lock); } -/** \ingroup poll +/** \ingroup libusb_poll * Release the event waiters lock. * \param ctx the context to operate on, or NULL for the default context - * \ref mtasync + * \ref libusb_mtasync */ void API_EXPORTED libusb_unlock_event_waiters(libusb_context *ctx) { @@ -1915,7 +1915,7 @@ void API_EXPORTED libusb_unlock_event_waiters(libusb_context *ctx) usbi_mutex_unlock(&ctx->event_waiters_lock); } -/** \ingroup poll +/** \ingroup libusb_poll * Wait for another thread to signal completion of an event. Must be called * with the event waiters lock held, see libusb_lock_event_waiters(). * @@ -1938,7 +1938,7 @@ void API_EXPORTED libusb_unlock_event_waiters(libusb_context *ctx) * indicates unlimited timeout. * \returns 0 after a transfer completes or another thread stops event handling * \returns 1 if the timeout expired - * \ref mtasync + * \ref libusb_mtasync */ int API_EXPORTED libusb_wait_for_event(libusb_context *ctx, struct timeval *tv) { @@ -2289,7 +2289,7 @@ static int get_next_timeout(libusb_context *ctx, struct timeval *tv, return 0; } -/** \ingroup poll +/** \ingroup libusb_poll * Handle any pending events. * * libusb determines "pending events" by checking if any timeouts have expired @@ -2313,7 +2313,7 @@ static int get_next_timeout(libusb_context *ctx, struct timeval *tv, * timeval struct for non-blocking mode * \param completed pointer to completion integer to check, or NULL * \returns 0 on success, or a LIBUSB_ERROR code on failure - * \ref mtasync + * \ref libusb_mtasync */ int API_EXPORTED libusb_handle_events_timeout_completed(libusb_context *ctx, struct timeval *tv, int *completed) @@ -2368,7 +2368,7 @@ int API_EXPORTED libusb_handle_events_timeout_completed(libusb_context *ctx, return 0; } -/** \ingroup poll +/** \ingroup libusb_poll * Handle any pending events * * Like libusb_handle_events_timeout_completed(), but without the completed @@ -2390,7 +2390,7 @@ int API_EXPORTED libusb_handle_events_timeout(libusb_context *ctx, return libusb_handle_events_timeout_completed(ctx, tv, NULL); } -/** \ingroup poll +/** \ingroup libusb_poll * Handle any pending events in blocking mode. There is currently a timeout * hardcoded at 60 seconds but we plan to make it unlimited in future. For * finer control over whether this function is blocking or non-blocking, or @@ -2412,7 +2412,7 @@ int API_EXPORTED libusb_handle_events(libusb_context *ctx) return libusb_handle_events_timeout_completed(ctx, &tv, NULL); } -/** \ingroup poll +/** \ingroup libusb_poll * Handle any pending events in blocking mode. * * Like libusb_handle_events(), with the addition of a completed parameter @@ -2424,7 +2424,7 @@ int API_EXPORTED libusb_handle_events(libusb_context *ctx) * \param ctx the context to operate on, or NULL for the default context * \param completed pointer to completion integer to check, or NULL * \returns 0 on success, or a LIBUSB_ERROR code on failure - * \ref mtasync + * \ref libusb_mtasync */ int API_EXPORTED libusb_handle_events_completed(libusb_context *ctx, int *completed) @@ -2435,7 +2435,7 @@ int API_EXPORTED libusb_handle_events_completed(libusb_context *ctx, return libusb_handle_events_timeout_completed(ctx, &tv, completed); } -/** \ingroup poll +/** \ingroup libusb_poll * Handle any pending events by polling file descriptors, without checking if * any other threads are already doing so. Must be called with the event lock * held, see libusb_lock_events(). @@ -2450,7 +2450,7 @@ int API_EXPORTED libusb_handle_events_completed(libusb_context *ctx, * \param tv the maximum time to block waiting for events, or zero for * non-blocking mode * \returns 0 on success, or a LIBUSB_ERROR code on failure - * \ref mtasync + * \ref libusb_mtasync */ int API_EXPORTED libusb_handle_events_locked(libusb_context *ctx, struct timeval *tv) @@ -2468,12 +2468,12 @@ int API_EXPORTED libusb_handle_events_locked(libusb_context *ctx, return handle_events(ctx, &poll_timeout); } -/** \ingroup poll +/** \ingroup libusb_poll * Determines whether your application must apply special timing considerations * when monitoring libusb's file descriptors. * * This function is only useful for applications which retrieve and poll - * libusb's file descriptors in their own main loop (\ref pollmain). + * libusb's file descriptors in their own main loop (\ref libusb_pollmain). * * Ordinarily, libusb's event handler needs to be called into at specific * moments in time (in addition to times when there is activity on the file @@ -2494,7 +2494,7 @@ int API_EXPORTED libusb_handle_events_locked(libusb_context *ctx, * \returns 0 if you must call into libusb at times determined by * libusb_get_next_timeout(), or 1 if all timeout events are handled internally * or through regular activity on the file descriptors. - * \ref pollmain "Polling libusb file descriptors for event handling" + * \ref libusb_pollmain "Polling libusb file descriptors for event handling" */ int API_EXPORTED libusb_pollfds_handle_timeouts(libusb_context *ctx) { @@ -2507,7 +2507,7 @@ int API_EXPORTED libusb_pollfds_handle_timeouts(libusb_context *ctx) #endif } -/** \ingroup poll +/** \ingroup libusb_poll * Determine the next internal timeout that libusb needs to handle. You only * need to use this function if you are calling poll() or select() or similar * on libusb's file descriptors yourself - you do not need to use it if you @@ -2592,7 +2592,7 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx, return 1; } -/** \ingroup poll +/** \ingroup libusb_poll * Register notification functions for file descriptor additions/removals. * These functions will be invoked for every new or removed file descriptor * that libusb uses as an event source. @@ -2691,7 +2691,7 @@ void usbi_remove_pollfd(struct libusb_context *ctx, int fd) ctx->fd_removed_cb(fd, ctx->fd_cb_user_data); } -/** \ingroup poll +/** \ingroup libusb_poll * Retrieve a list of file descriptors that should be polled by your main loop * as libusb event sources. * @@ -2736,7 +2736,7 @@ const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds( #endif } -/** \ingroup poll +/** \ingroup libusb_poll * Free a list of libusb_pollfd structures. This should be called for all * pollfd lists allocated with libusb_get_pollfds(). * diff --git a/libusb/libusb.h b/libusb/libusb.h index 7fe01db8f..5b0d522be 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -84,7 +84,7 @@ typedef unsigned __int32 uint32_t; #endif /* __GNUC__ */ /** \def LIBUSB_CALL - * \ingroup misc + * \ingroup libusb_misc * libusb's Windows calling convention. * * Under Windows, the selection of available compilers and configurations @@ -122,7 +122,7 @@ typedef unsigned __int32 uint32_t; #endif /** \def LIBUSB_API_VERSION - * \ingroup misc + * \ingroup libusb_misc * libusb's API version. * * Since version 1.0.13, to help with feature detection, libusb defines @@ -151,7 +151,7 @@ extern "C" { #endif /** - * \ingroup misc + * \ingroup libusb_misc * Convert a 16-bit value from host-endian to little-endian format. On * little endian systems, this function does nothing. On big endian systems, * the bytes are swapped. @@ -170,7 +170,7 @@ static inline uint16_t libusb_cpu_to_le16(const uint16_t x) } /** \def libusb_le16_to_cpu - * \ingroup misc + * \ingroup libusb_misc * Convert a 16-bit value from little-endian to host-endian format. On * little endian systems, this function does nothing. On big endian systems, * the bytes are swapped. @@ -181,7 +181,7 @@ static inline uint16_t libusb_cpu_to_le16(const uint16_t x) /* standard USB stuff */ -/** \ingroup desc +/** \ingroup libusb_desc * Device and/or Interface Class codes */ enum libusb_class_code { /** In the context of a \ref libusb_device_descriptor "device descriptor", @@ -243,7 +243,7 @@ enum libusb_class_code { LIBUSB_CLASS_VENDOR_SPEC = 0xff }; -/** \ingroup desc +/** \ingroup libusb_desc * Descriptor types as defined by the USB specification. */ enum libusb_descriptor_type { /** Device descriptor. See libusb_device_descriptor. */ @@ -311,7 +311,7 @@ enum libusb_descriptor_type { #define LIBUSB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */ #define LIBUSB_ENDPOINT_DIR_MASK 0x80 -/** \ingroup desc +/** \ingroup libusb_desc * Endpoint direction. Values for bit 7 of the * \ref libusb_endpoint_descriptor::bEndpointAddress "endpoint address" scheme. */ @@ -325,7 +325,7 @@ enum libusb_endpoint_direction { #define LIBUSB_TRANSFER_TYPE_MASK 0x03 /* in bmAttributes */ -/** \ingroup desc +/** \ingroup libusb_desc * Endpoint transfer type. Values for bits 0:1 of the * \ref libusb_endpoint_descriptor::bmAttributes "endpoint attributes" field. */ @@ -346,7 +346,7 @@ enum libusb_transfer_type { LIBUSB_TRANSFER_TYPE_BULK_STREAM = 4, }; -/** \ingroup misc +/** \ingroup libusb_misc * Standard requests, as defined in table 9-5 of the USB 3.0 specifications */ enum libusb_standard_request { /** Request status of the specific recipient */ @@ -394,7 +394,7 @@ enum libusb_standard_request { LIBUSB_SET_ISOCH_DELAY = 0x31, }; -/** \ingroup misc +/** \ingroup libusb_misc * Request type bits of the * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control * transfers. */ @@ -412,7 +412,7 @@ enum libusb_request_type { LIBUSB_REQUEST_TYPE_RESERVED = (0x03 << 5) }; -/** \ingroup misc +/** \ingroup libusb_misc * Recipient bits of the * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control * transfers. Values 4 through 31 are reserved. */ @@ -432,7 +432,7 @@ enum libusb_request_recipient { #define LIBUSB_ISO_SYNC_TYPE_MASK 0x0C -/** \ingroup desc +/** \ingroup libusb_desc * Synchronization type for isochronous endpoints. Values for bits 2:3 of the * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in * libusb_endpoint_descriptor. @@ -453,7 +453,7 @@ enum libusb_iso_sync_type { #define LIBUSB_ISO_USAGE_TYPE_MASK 0x30 -/** \ingroup desc +/** \ingroup libusb_desc * Usage type for isochronous endpoints. Values for bits 4:5 of the * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in * libusb_endpoint_descriptor. @@ -469,7 +469,7 @@ enum libusb_iso_usage_type { LIBUSB_ISO_USAGE_TYPE_IMPLICIT = 2, }; -/** \ingroup desc +/** \ingroup libusb_desc * A structure representing the standard USB device descriptor. This * descriptor is documented in section 9.6.1 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. @@ -523,7 +523,7 @@ struct libusb_device_descriptor { uint8_t bNumConfigurations; }; -/** \ingroup desc +/** \ingroup libusb_desc * A structure representing the standard USB endpoint descriptor. This * descriptor is documented in section 9.6.6 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. @@ -573,7 +573,7 @@ struct libusb_endpoint_descriptor { int extra_length; }; -/** \ingroup desc +/** \ingroup libusb_desc * A structure representing the standard USB interface descriptor. This * descriptor is documented in section 9.6.5 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. @@ -623,7 +623,7 @@ struct libusb_interface_descriptor { int extra_length; }; -/** \ingroup desc +/** \ingroup libusb_desc * A collection of alternate settings for a particular USB interface. */ struct libusb_interface { @@ -635,7 +635,7 @@ struct libusb_interface { int num_altsetting; }; -/** \ingroup desc +/** \ingroup libusb_desc * A structure representing the standard USB configuration descriptor. This * descriptor is documented in section 9.6.3 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. @@ -682,7 +682,7 @@ struct libusb_config_descriptor { int extra_length; }; -/** \ingroup desc +/** \ingroup libusb_desc * A structure representing the superspeed endpoint companion * descriptor. This descriptor is documented in section 9.6.7 of * the USB 3.0 specification. All multiple-byte fields are represented in @@ -714,7 +714,7 @@ struct libusb_ss_endpoint_companion_descriptor { uint16_t wBytesPerInterval; }; -/** \ingroup desc +/** \ingroup libusb_desc * A generic representation of a BOS Device Capability descriptor. It is * advised to check bDevCapabilityType and call the matching * libusb_get_*_descriptor function to get a structure fully matching the type. @@ -738,7 +738,7 @@ struct libusb_bos_dev_capability_descriptor { ; }; -/** \ingroup desc +/** \ingroup libusb_desc * A structure representing the Binary Device Object Store (BOS) descriptor. * This descriptor is documented in section 9.6.2 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. @@ -769,7 +769,7 @@ struct libusb_bos_descriptor { ; }; -/** \ingroup desc +/** \ingroup libusb_desc * A structure representing the USB 2.0 Extension descriptor * This descriptor is documented in section 9.6.2.1 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. @@ -795,7 +795,7 @@ struct libusb_usb_2_0_extension_descriptor { uint32_t bmAttributes; }; -/** \ingroup desc +/** \ingroup libusb_desc * A structure representing the SuperSpeed USB Device Capability descriptor * This descriptor is documented in section 9.6.2.2 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. @@ -837,7 +837,7 @@ struct libusb_ss_usb_device_capability_descriptor { uint16_t bU2DevExitLat; }; -/** \ingroup desc +/** \ingroup libusb_desc * A structure representing the Container ID descriptor. * This descriptor is documented in section 9.6.2.3 of the USB 3.0 specification. * All multiple-byte fields, except UUIDs, are represented in host-endian format. @@ -863,7 +863,7 @@ struct libusb_container_id_descriptor { uint8_t ContainerID[16]; }; -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Setup packet for control transfers. */ struct libusb_control_setup { /** Request type. Bits 0:4 determine recipient, see @@ -899,7 +899,7 @@ struct libusb_context; struct libusb_device; struct libusb_device_handle; -/** \ingroup lib +/** \ingroup libusb_lib * Structure providing the version of the libusb runtime */ struct libusb_version { @@ -922,7 +922,7 @@ struct libusb_version { const char* describe; }; -/** \ingroup lib +/** \ingroup libusb_lib * Structure representing a libusb session. The concept of individual libusb * sessions allows for your program to use two libraries (or dynamically * load two modules) which both independently use libusb. This will prevent @@ -937,11 +937,11 @@ struct libusb_version { * every function call where a context is required. The default context * will be used. * - * For more information, see \ref contexts. + * For more information, see \ref libusb_contexts. */ typedef struct libusb_context libusb_context; -/** \ingroup dev +/** \ingroup libusb_dev * Structure representing a USB device detected on the system. This is an * opaque type for which you are only ever provided with a pointer, usually * originating from libusb_get_device_list(). @@ -959,7 +959,7 @@ typedef struct libusb_context libusb_context; typedef struct libusb_device libusb_device; -/** \ingroup dev +/** \ingroup libusb_dev * Structure representing a handle on a USB device. This is an opaque type for * which you are only ever provided with a pointer, usually originating from * libusb_open(). @@ -969,7 +969,7 @@ typedef struct libusb_device libusb_device; */ typedef struct libusb_device_handle libusb_device_handle; -/** \ingroup dev +/** \ingroup libusb_dev * Speed codes. Indicates the speed at which the device is operating. */ enum libusb_speed { @@ -989,7 +989,7 @@ enum libusb_speed { LIBUSB_SPEED_SUPER = 4, }; -/** \ingroup dev +/** \ingroup libusb_dev * Supported speeds (wSpeedSupported) bitfield. Indicates what * speeds the device supports. */ @@ -1007,7 +1007,7 @@ enum libusb_supported_speed { LIBUSB_SUPER_SPEED_OPERATION = 8, }; -/** \ingroup dev +/** \ingroup libusb_dev * Masks for the bits of the * \ref libusb_usb_2_0_extension_descriptor::bmAttributes "bmAttributes" field * of the USB 2.0 Extension descriptor. @@ -1017,7 +1017,7 @@ enum libusb_usb_2_0_extension_attributes { LIBUSB_BM_LPM_SUPPORT = 2, }; -/** \ingroup dev +/** \ingroup libusb_dev * Masks for the bits of the * \ref libusb_ss_usb_device_capability_descriptor::bmAttributes "bmAttributes" field * field of the SuperSpeed USB Device Capability descriptor. @@ -1027,7 +1027,7 @@ enum libusb_ss_usb_device_capability_attributes { LIBUSB_BM_LTM_SUPPORT = 2, }; -/** \ingroup dev +/** \ingroup libusb_dev * USB capability types */ enum libusb_bos_type { @@ -1044,7 +1044,7 @@ enum libusb_bos_type { LIBUSB_BT_CONTAINER_ID = 4, }; -/** \ingroup misc +/** \ingroup libusb_misc * Error codes. Most libusb functions return 0 on success or one of these * codes on failure. * You can call libusb_error_name() to retrieve a string representation of an @@ -1101,7 +1101,7 @@ enum libusb_error { /* Total number of error codes in enum libusb_error */ #define LIBUSB_ERROR_COUNT 14 -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Transfer status codes */ enum libusb_transfer_status { /** Transfer completed without error. Note that this does not indicate @@ -1131,7 +1131,7 @@ enum libusb_transfer_status { when adding new status codes here. */ }; -/** \ingroup asyncio +/** \ingroup libusb_asyncio * libusb_transfer.flags values */ enum libusb_transfer_flags { /** Report short frames as errors */ @@ -1172,7 +1172,7 @@ enum libusb_transfer_flags { LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1 << 3, }; -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Isochronous packet descriptor. */ struct libusb_iso_packet_descriptor { /** Length of data to request in this packet */ @@ -1187,18 +1187,18 @@ struct libusb_iso_packet_descriptor { struct libusb_transfer; -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Asynchronous transfer callback function type. When submitting asynchronous * transfers, you pass a pointer to a callback function of this type via the * \ref libusb_transfer::callback "callback" member of the libusb_transfer * structure. libusb will call this function later, when the transfer has - * completed or failed. See \ref asyncio for more information. + * completed or failed. See \ref libusb_asyncio for more information. * \param transfer The libusb_transfer struct the callback function is being * notified about. */ typedef void (LIBUSB_CALL *libusb_transfer_cb_fn)(struct libusb_transfer *transfer); -/** \ingroup asyncio +/** \ingroup libusb_asyncio * The generic USB transfer structure. The user populates this structure and * then submits it in order to request a transfer. After the transfer has * completed, the library populates the transfer with the results and passes @@ -1262,7 +1262,7 @@ struct libusb_transfer { ; }; -/** \ingroup misc +/** \ingroup libusb_misc * Capabilities supported by an instance of libusb on the current running * platform. Test if the loaded library supports a given capability by calling * \ref libusb_has_capability(). @@ -1282,7 +1282,7 @@ enum libusb_capability { LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER = 0x0101 }; -/** \ingroup lib +/** \ingroup libusb_lib * Log message levels. * - LIBUSB_LOG_LEVEL_NONE (0) : no messages ever printed by the library (default) * - LIBUSB_LOG_LEVEL_ERROR (1) : error messages are printed to stderr @@ -1403,7 +1403,7 @@ int LIBUSB_CALL libusb_set_auto_detach_kernel_driver( /* async I/O */ -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Get the data section of a control transfer. This convenience function is here * to remind you that the data does not start until 8 bytes into the actual * buffer, as the setup packet comes first. @@ -1421,7 +1421,7 @@ static inline unsigned char *libusb_control_transfer_get_data( return transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Get the control setup packet of a control transfer. This convenience * function is here to remind you that the control setup occupies the first * 8 bytes of the transfer data buffer. @@ -1439,7 +1439,7 @@ static inline struct libusb_control_setup *libusb_control_transfer_get_setup( return (struct libusb_control_setup *)(void *) transfer->buffer; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Helper function to populate the setup packet (first 8 bytes of the data * buffer) for a control transfer. The wIndex, wValue and wLength values should * be given in host-endian byte order. @@ -1483,7 +1483,7 @@ void LIBUSB_CALL libusb_transfer_set_stream_id( uint32_t LIBUSB_CALL libusb_transfer_get_stream_id( struct libusb_transfer *transfer); -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Helper function to populate the required \ref libusb_transfer fields * for a control transfer. * @@ -1529,7 +1529,7 @@ static inline void libusb_fill_control_transfer( transfer->callback = callback; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Helper function to populate the required \ref libusb_transfer fields * for a bulk transfer. * @@ -1557,7 +1557,7 @@ static inline void libusb_fill_bulk_transfer(struct libusb_transfer *transfer, transfer->callback = callback; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Helper function to populate the required \ref libusb_transfer fields * for a bulk transfer using bulk streams. * @@ -1585,7 +1585,7 @@ static inline void libusb_fill_bulk_stream_transfer( libusb_transfer_set_stream_id(transfer, stream_id); } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Helper function to populate the required \ref libusb_transfer fields * for an interrupt transfer. * @@ -1613,7 +1613,7 @@ static inline void libusb_fill_interrupt_transfer( transfer->callback = callback; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Helper function to populate the required \ref libusb_transfer fields * for an isochronous transfer. * @@ -1643,7 +1643,7 @@ static inline void libusb_fill_iso_transfer(struct libusb_transfer *transfer, transfer->callback = callback; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Convenience function to set the length of all packets in an isochronous * transfer, based on the num_iso_packets field in the transfer structure. * @@ -1659,7 +1659,7 @@ static inline void libusb_set_iso_packet_lengths( transfer->iso_packet_desc[i].length = length; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Convenience function to locate the position of an isochronous packet * within the buffer of an isochronous transfer. * @@ -1698,7 +1698,7 @@ static inline unsigned char *libusb_get_iso_packet_buffer( return transfer->buffer + offset; } -/** \ingroup asyncio +/** \ingroup libusb_asyncio * Convenience function to locate the position of an isochronous packet * within the buffer of an isochronous transfer, for transfers where each * packet is of identical size. @@ -1749,7 +1749,7 @@ int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *actual_length, unsigned int timeout); -/** \ingroup desc +/** \ingroup libusb_desc * Retrieve a descriptor from the default control pipe. * This is a convenience function which formulates the appropriate control * message to retrieve the descriptor. @@ -1769,7 +1769,7 @@ static inline int libusb_get_descriptor(libusb_device_handle *dev_handle, 0, data, (uint16_t) length, 1000); } -/** \ingroup desc +/** \ingroup libusb_desc * Retrieve a descriptor from a device. * This is a convenience function which formulates the appropriate control * message to retrieve the descriptor. The string returned is Unicode, as @@ -1818,7 +1818,7 @@ int LIBUSB_CALL libusb_pollfds_handle_timeouts(libusb_context *ctx); int LIBUSB_CALL libusb_get_next_timeout(libusb_context *ctx, struct timeval *tv); -/** \ingroup poll +/** \ingroup libusb_poll * File descriptor for polling */ struct libusb_pollfd { @@ -1832,7 +1832,7 @@ struct libusb_pollfd { short events; }; -/** \ingroup poll +/** \ingroup libusb_poll * Callback function, invoked when a new file descriptor should be added * to the set of file descriptors monitored for events. * \param fd the new file descriptor @@ -1845,7 +1845,7 @@ struct libusb_pollfd { typedef void (LIBUSB_CALL *libusb_pollfd_added_cb)(int fd, short events, void *user_data); -/** \ingroup poll +/** \ingroup libusb_poll * Callback function, invoked when a file descriptor should be removed from * the set of file descriptors being monitored for events. After returning * from this callback, do not use that file descriptor again. @@ -1863,7 +1863,7 @@ void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx, libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, void *user_data); -/** \ingroup hotplug +/** \ingroup libusb_hotplug * Callback handle. * * Callbacks handles are generated by libusb_hotplug_register_callback() @@ -1873,11 +1873,11 @@ void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx, * * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 * - * For more information, see \ref hotplug. + * For more information, see \ref libusb_hotplug. */ typedef int libusb_hotplug_callback_handle; -/** \ingroup hotplug +/** \ingroup libusb_hotplug * * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 * @@ -1890,7 +1890,7 @@ typedef enum { LIBUSB_HOTPLUG_ENUMERATE = 1<<0, } libusb_hotplug_flag; -/** \ingroup hotplug +/** \ingroup libusb_hotplug * * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 * @@ -1905,11 +1905,11 @@ typedef enum { LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT = 0x02, } libusb_hotplug_event; -/** \ingroup hotplug +/** \ingroup libusb_hotplug * Wildcard matching for hotplug events */ #define LIBUSB_HOTPLUG_MATCH_ANY -1 -/** \ingroup hotplug +/** \ingroup libusb_hotplug * Hotplug callback function type. When requesting hotplug event notifications, * you pass a pointer to a callback function of this type. * @@ -1917,7 +1917,7 @@ typedef enum { * recommended the callback do minimal processing before returning. * * libusb will call this function later, when a matching event had happened on - * a matching device. See \ref hotplug for more information. + * a matching device. See \ref libusb_hotplug for more information. * * It is safe to call either libusb_hotplug_register_callback() or * libusb_hotplug_deregister_callback() from within a callback function. @@ -1936,7 +1936,7 @@ typedef int (LIBUSB_CALL *libusb_hotplug_callback_fn)(libusb_context *ctx, libusb_hotplug_event event, void *user_data); -/** \ingroup hotplug +/** \ingroup libusb_hotplug * Register a hotplug callback function * * Register a callback with the libusb_context. The callback will fire @@ -1979,7 +1979,7 @@ int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx, void *user_data, libusb_hotplug_callback_handle *callback_handle); -/** \ingroup hotplug +/** \ingroup libusb_hotplug * Deregisters a hotplug callback. * * Deregister a callback from a libusb_context. This function is safe to call from within diff --git a/libusb/strerror.c b/libusb/strerror.c index a534041a6..d2be0e2a0 100644 --- a/libusb/strerror.c +++ b/libusb/strerror.c @@ -34,7 +34,7 @@ static size_t usbi_locale = 0; -/** \ingroup misc +/** \ingroup libusb_misc * How to add a new \ref libusb_strerror() translation: *
    *
  1. Download the latest \c strerror.c from:
    @@ -125,7 +125,7 @@ static const char* usbi_localized_errors[ARRAYSIZE(usbi_locale_supported)][LIBUS } }; -/** \ingroup misc +/** \ingroup libusb_misc * Set the language, and only the language, not the encoding! used for * translatable libusb messages. * @@ -176,7 +176,7 @@ int API_EXPORTED libusb_setlocale(const char *locale) return LIBUSB_SUCCESS; } -/** \ingroup misc +/** \ingroup libusb_misc * Returns a constant string with a short description of the given error code, * this description is intended for displaying to the end user and will be in * the language set by libusb_setlocale(). diff --git a/libusb/sync.c b/libusb/sync.c index 668909c88..c8514ddd9 100644 --- a/libusb/sync.c +++ b/libusb/sync.c @@ -27,11 +27,11 @@ #include "libusbi.h" /** - * @defgroup syncio Synchronous device I/O + * @defgroup libusb_syncio Synchronous device I/O * * This page documents libusb's synchronous (blocking) API for USB device I/O. * This interface is easy to use but has some limitations. More advanced users - * may wish to consider using the \ref asyncio "asynchronous I/O API" instead. + * may wish to consider using the \ref libusb_asyncio "asynchronous I/O API" instead. */ static void LIBUSB_CALL sync_transfer_cb(struct libusb_transfer *transfer) @@ -60,7 +60,7 @@ static void sync_transfer_wait_for_completion(struct libusb_transfer *transfer) } } -/** \ingroup syncio +/** \ingroup libusb_syncio * Perform a USB control transfer. * * The direction of the transfer is inferred from the bmRequestType field of @@ -221,7 +221,7 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, return r; } -/** \ingroup syncio +/** \ingroup libusb_syncio * Perform a USB bulk transfer. The direction of the transfer is inferred from * the direction bits of the endpoint address. * @@ -259,7 +259,7 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, * transferred) * \returns LIBUSB_ERROR_PIPE if the endpoint halted * \returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see - * \ref packetoverflow + * \ref libusb_packetoverflow * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * \returns LIBUSB_ERROR_BUSY if called from event handling context * \returns another LIBUSB_ERROR code on other failures @@ -272,7 +272,7 @@ int API_EXPORTED libusb_bulk_transfer(struct libusb_device_handle *dev_handle, transferred, timeout, LIBUSB_TRANSFER_TYPE_BULK); } -/** \ingroup syncio +/** \ingroup libusb_syncio * Perform a USB interrupt transfer. The direction of the transfer is inferred * from the direction bits of the endpoint address. * @@ -311,7 +311,7 @@ int API_EXPORTED libusb_bulk_transfer(struct libusb_device_handle *dev_handle, * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out * \returns LIBUSB_ERROR_PIPE if the endpoint halted * \returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see - * \ref packetoverflow + * \ref libusb_packetoverflow * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * \returns LIBUSB_ERROR_BUSY if called from event handling context * \returns another LIBUSB_ERROR code on other error diff --git a/libusb/version_nano.h b/libusb/version_nano.h index bb4ce8e1d..a3134a089 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11055 +#define LIBUSB_NANO 11056 From 7ab9087659dd147b7e3e535b84da10d2f071aa9e Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Wed, 24 Feb 2016 01:21:52 -0800 Subject: [PATCH 137/222] Misc: Add libusb_interrupt_event_handler() to API docs page Signed-off-by: Chris Dickens --- libusb/core.c | 1 + libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libusb/core.c b/libusb/core.c index 9d6479423..b1afafad8 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -415,6 +415,7 @@ if (cfg != desired) * - libusb_hotplug_deregister_callback() * - libusb_hotplug_register_callback() * - libusb_init() + * - libusb_interrupt_event_handler() * - libusb_interrupt_transfer() * - libusb_kernel_driver_active() * - libusb_lock_events() diff --git a/libusb/version_nano.h b/libusb/version_nano.h index a3134a089..6375e49f7 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11056 +#define LIBUSB_NANO 11057 From b99391deb4894bbfff59fab985c99fc55a43169a Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Wed, 24 Feb 2016 01:50:40 -0800 Subject: [PATCH 138/222] Misc: Document the return code for control transfers that are too large Closes #110 Signed-off-by: Chris Dickens --- libusb/io.c | 2 ++ libusb/os/windows_winusb.c | 2 ++ libusb/sync.c | 2 ++ libusb/version_nano.h | 2 +- 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libusb/io.c b/libusb/io.c index 74dba4b2d..2cd6a6e4d 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1463,6 +1463,8 @@ static int remove_from_flying_list(struct usbi_transfer *transfer) * \returns LIBUSB_ERROR_BUSY if the transfer has already been submitted. * \returns LIBUSB_ERROR_NOT_SUPPORTED if the transfer flags are not supported * by the operating system. + * \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than + * the operating system and/or hardware can support * \returns another LIBUSB_ERROR code on other failure */ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index fec6ebe36..a3bc11d5b 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -2673,6 +2673,8 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it transfer_priv->pollable_fd = INVALID_WINFD; size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; + // Windows places upper limits on the control transfer size + // See: https://msdn.microsoft.com/en-us/library/windows/hardware/ff538112.aspx if (size > MAX_CTRL_BUFFER_LENGTH) return LIBUSB_ERROR_INVALID_PARAM; diff --git a/libusb/sync.c b/libusb/sync.c index c8514ddd9..a609f65f4 100644 --- a/libusb/sync.c +++ b/libusb/sync.c @@ -87,6 +87,8 @@ static void sync_transfer_wait_for_completion(struct libusb_transfer *transfer) * device * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * \returns LIBUSB_ERROR_BUSY if called from event handling context + * \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than + * the operating system and/or hardware can support * \returns another LIBUSB_ERROR code on other failures */ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle, diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 6375e49f7..9be763f8d 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11057 +#define LIBUSB_NANO 11058 From a05b282bee6998da3d1a8460b33dc24b69682fb7 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Sat, 30 Jan 2016 02:24:38 -0800 Subject: [PATCH 139/222] Misc: Remove unused definitions for usbi_cond_signal() Signed-off-by: Chris Dickens --- libusb/os/threads_posix.h | 1 - libusb/os/threads_windows.c | 19 ------------------- libusb/os/threads_windows.h | 1 - libusb/version_nano.h | 2 +- 4 files changed, 1 insertion(+), 22 deletions(-) diff --git a/libusb/os/threads_posix.h b/libusb/os/threads_posix.h index 3caeca4c7..ce78cc32f 100644 --- a/libusb/os/threads_posix.h +++ b/libusb/os/threads_posix.h @@ -41,7 +41,6 @@ #define usbi_cond_timedwait pthread_cond_timedwait #define usbi_cond_broadcast pthread_cond_broadcast #define usbi_cond_destroy pthread_cond_destroy -#define usbi_cond_signal pthread_cond_signal #define usbi_tls_key_t pthread_key_t #define usbi_tls_key_create pthread_key_create diff --git a/libusb/os/threads_windows.c b/libusb/os/threads_windows.c index 933807e0c..8a9c02c1a 100644 --- a/libusb/os/threads_windows.c +++ b/libusb/os/threads_windows.c @@ -155,25 +155,6 @@ int usbi_cond_broadcast(usbi_cond_t *cond) return fail ? EINVAL : 0; } -int usbi_cond_signal(usbi_cond_t *cond) -{ - // Assumes mutex is locked; this is not in keeping with POSIX spec, but - // libusb does this anyway, so we simplify by not adding more sync - // primitives to the CV definition! - struct usbi_cond_perthread *pos; - - if (!cond) - return EINVAL; - if (list_empty(&cond->waiters)) - return 0; // no one to wakeup. - pos = list_first_entry(&cond->waiters, struct usbi_cond_perthread, list); - // The wait function will remove its respective item from the list. - if (SetEvent(pos->event)) - return 0; - else - return EINVAL; -} - __inline static int usbi_cond_intwait(usbi_cond_t *cond, usbi_mutex_t *mutex, DWORD timeout_ms) { diff --git a/libusb/os/threads_windows.h b/libusb/os/threads_windows.h index 39dddc866..b9e792292 100644 --- a/libusb/os/threads_windows.h +++ b/libusb/os/threads_windows.h @@ -66,7 +66,6 @@ int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex); int usbi_cond_timedwait(usbi_cond_t *cond, usbi_mutex_t *mutex, const struct timespec *abstime); int usbi_cond_broadcast(usbi_cond_t *cond); -int usbi_cond_signal(usbi_cond_t *cond); int usbi_cond_destroy(usbi_cond_t *cond); int usbi_tls_key_create(usbi_tls_key_t *key, void (*destructor)(void *)); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 9be763f8d..ec8f802f3 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11058 +#define LIBUSB_NANO 11059 From 3a4fd0ac64cf9d4cf8f2a665f2f43f2bb1d25369 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Sat, 30 Jan 2016 02:24:39 -0800 Subject: [PATCH 140/222] core: Remove POSIX threads influence from synchronization code This commit changes the signatures of the synchronization functions to reflect the needs of the library rather than the signature of the pthreads API. The mutex and condition variable attributes parameters have been removed as no part of the core library makes use of them. In addition, the condition variable timed-wait function has been modified to accept the relative time passed in via libusb_wait_for_event(). This allows the implementation-specific code to handle conversion to absolute time as necessary, rather than forcing this to occur. Signed-off-by: Chris Dickens --- libusb/core.c | 10 +++---- libusb/io.c | 38 ++++++++++---------------- libusb/os/threads_posix.c | 42 ++++++++++++++++++++--------- libusb/os/threads_posix.h | 15 +++++++---- libusb/os/threads_windows.c | 50 ++++++++--------------------------- libusb/os/threads_windows.h | 14 +++++----- libusb/os/windows_nt_common.c | 2 +- libusb/os/windows_winusb.c | 2 +- libusb/version_nano.h | 2 +- 9 files changed, 79 insertions(+), 96 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index b1afafad8..31f3d2875 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -676,7 +676,7 @@ struct libusb_device *usbi_alloc_device(struct libusb_context *ctx, if (!dev) return NULL; - r = usbi_mutex_init(&dev->lock, NULL); + r = usbi_mutex_init(&dev->lock); if (r) { free(dev); return NULL; @@ -1242,7 +1242,7 @@ int API_EXPORTED libusb_open(libusb_device *dev, if (!_dev_handle) return LIBUSB_ERROR_NO_MEM; - r = usbi_mutex_init(&_dev_handle->lock, NULL); + r = usbi_mutex_init(&_dev_handle->lock); if (r) { free(_dev_handle); return LIBUSB_ERROR_OTHER; @@ -2036,9 +2036,9 @@ int API_EXPORTED libusb_init(libusb_context **context) usbi_dbg("libusb v%u.%u.%u.%u%s", libusb_version_internal.major, libusb_version_internal.minor, libusb_version_internal.micro, libusb_version_internal.nano, libusb_version_internal.rc); - usbi_mutex_init(&ctx->usb_devs_lock, NULL); - usbi_mutex_init(&ctx->open_devs_lock, NULL); - usbi_mutex_init(&ctx->hotplug_cbs_lock, NULL); + usbi_mutex_init(&ctx->usb_devs_lock); + usbi_mutex_init(&ctx->open_devs_lock); + usbi_mutex_init(&ctx->hotplug_cbs_lock); list_init(&ctx->usb_devs); list_init(&ctx->open_devs); list_init(&ctx->hotplug_cbs); diff --git a/libusb/io.c b/libusb/io.c index 2cd6a6e4d..4d03b8b77 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1124,12 +1124,12 @@ int usbi_io_init(struct libusb_context *ctx) { int r; - usbi_mutex_init(&ctx->flying_transfers_lock, NULL); - usbi_mutex_init_recursive(&ctx->events_lock, NULL); - usbi_mutex_init(&ctx->event_waiters_lock, NULL); - usbi_cond_init(&ctx->event_waiters_cond, NULL); - usbi_mutex_init(&ctx->event_data_lock, NULL); - usbi_tls_key_create(&ctx->event_handling_key, NULL); + usbi_mutex_init(&ctx->flying_transfers_lock); + usbi_mutex_init_recursive(&ctx->events_lock); + usbi_mutex_init(&ctx->event_waiters_lock); + usbi_cond_init(&ctx->event_waiters_cond); + usbi_mutex_init(&ctx->event_data_lock); + usbi_tls_key_create(&ctx->event_handling_key); list_init(&ctx->flying_transfers); list_init(&ctx->ipollfds); list_init(&ctx->hotplug_msgs); @@ -1268,8 +1268,8 @@ struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer( return NULL; itransfer->num_iso_packets = iso_packets; - usbi_mutex_init(&itransfer->lock, NULL); - usbi_mutex_init(&itransfer->flags_lock, NULL); + usbi_mutex_init(&itransfer->lock); + usbi_mutex_init(&itransfer->flags_lock); transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); usbi_dbg("transfer %p", transfer); return transfer; @@ -1944,7 +1944,6 @@ void API_EXPORTED libusb_unlock_event_waiters(libusb_context *ctx) */ int API_EXPORTED libusb_wait_for_event(libusb_context *ctx, struct timeval *tv) { - struct timespec timeout; int r; USBI_GET_CONTEXT(ctx); @@ -1953,22 +1952,13 @@ int API_EXPORTED libusb_wait_for_event(libusb_context *ctx, struct timeval *tv) return 0; } - r = usbi_backend->clock_gettime(USBI_CLOCK_REALTIME, &timeout); - if (r < 0) { - usbi_err(ctx, "failed to read realtime clock, error %d", errno); - return LIBUSB_ERROR_OTHER; - } - - timeout.tv_sec += tv->tv_sec; - timeout.tv_nsec += tv->tv_usec * 1000; - while (timeout.tv_nsec >= 1000000000) { - timeout.tv_nsec -= 1000000000; - timeout.tv_sec++; - } - r = usbi_cond_timedwait(&ctx->event_waiters_cond, - &ctx->event_waiters_lock, &timeout); - return (r == ETIMEDOUT); + &ctx->event_waiters_lock, tv); + + if (r < 0) + return r; + else + return (r == ETIMEDOUT); } static void handle_timeout(struct usbi_transfer *itransfer) diff --git a/libusb/os/threads_posix.c b/libusb/os/threads_posix.c index e8e87bbb4..89b05f38d 100644 --- a/libusb/os/threads_posix.c +++ b/libusb/os/threads_posix.c @@ -21,6 +21,7 @@ #include +#include #if defined(__linux__) || defined(__OpenBSD__) # if defined(__OpenBSD__) # define _BSD_SOURCE @@ -35,31 +36,48 @@ #include "threads_posix.h" -int usbi_mutex_init_recursive(pthread_mutex_t *mutex, pthread_mutexattr_t *attr) +int usbi_mutex_init_recursive(pthread_mutex_t *mutex) { int err; - pthread_mutexattr_t stack_attr; - if (!attr) { - attr = &stack_attr; - err = pthread_mutexattr_init(&stack_attr); - if (err != 0) - return err; - } + pthread_mutexattr_t attr; + + err = pthread_mutexattr_init(&attr); + if (err != 0) + return err; /* mutexattr_settype requires _GNU_SOURCE or _XOPEN_SOURCE >= 500 on Linux */ - err = pthread_mutexattr_settype(attr, PTHREAD_MUTEX_RECURSIVE); + err = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); if (err != 0) goto finish; - err = pthread_mutex_init(mutex, attr); + err = pthread_mutex_init(mutex, &attr); finish: - if (attr == &stack_attr) - pthread_mutexattr_destroy(&stack_attr); + pthread_mutexattr_destroy(&attr); return err; } +int usbi_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, const struct timeval *tv) +{ + struct timespec timeout; + int r; + + r = clock_gettime(CLOCK_REALTIME, &timeout); + if (r < 0) + return r; + + timeout.tv_sec += tv->tv_sec; + timeout.tv_nsec += tv->tv_usec * 1000; + while (timeout.tv_nsec >= 1000000000L) { + timeout.tv_nsec -= 1000000000L; + timeout.tv_sec++; + } + + return pthread_cond_timedwait(cond, mutex, &timeout); +} + int usbi_get_tid(void) { int ret = -1; diff --git a/libusb/os/threads_posix.h b/libusb/os/threads_posix.h index ce78cc32f..2abb820f3 100644 --- a/libusb/os/threads_posix.h +++ b/libusb/os/threads_posix.h @@ -22,6 +22,9 @@ #define LIBUSB_THREADS_POSIX_H #include +#ifdef HAVE_SYS_TIME_H +#include +#endif #define usbi_mutex_static_t pthread_mutex_t #define USBI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER @@ -29,26 +32,28 @@ #define usbi_mutex_static_unlock pthread_mutex_unlock #define usbi_mutex_t pthread_mutex_t -#define usbi_mutex_init pthread_mutex_init +#define usbi_mutex_init(mutex) pthread_mutex_init((mutex), NULL) #define usbi_mutex_lock pthread_mutex_lock #define usbi_mutex_unlock pthread_mutex_unlock #define usbi_mutex_trylock pthread_mutex_trylock #define usbi_mutex_destroy pthread_mutex_destroy #define usbi_cond_t pthread_cond_t -#define usbi_cond_init pthread_cond_init +#define usbi_cond_init(cond) pthread_cond_init((cond), NULL) #define usbi_cond_wait pthread_cond_wait -#define usbi_cond_timedwait pthread_cond_timedwait #define usbi_cond_broadcast pthread_cond_broadcast #define usbi_cond_destroy pthread_cond_destroy #define usbi_tls_key_t pthread_key_t -#define usbi_tls_key_create pthread_key_create +#define usbi_tls_key_create(key) pthread_key_create((key), NULL) #define usbi_tls_key_get pthread_getspecific #define usbi_tls_key_set pthread_setspecific #define usbi_tls_key_delete pthread_key_delete -extern int usbi_mutex_init_recursive(pthread_mutex_t *mutex, pthread_mutexattr_t *attr); +int usbi_mutex_init_recursive(pthread_mutex_t *mutex); + +int usbi_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, const struct timeval *tv); int usbi_get_tid(void); diff --git a/libusb/os/threads_windows.c b/libusb/os/threads_windows.c index 8a9c02c1a..7c2e52dba 100644 --- a/libusb/os/threads_windows.c +++ b/libusb/os/threads_windows.c @@ -25,8 +25,6 @@ #include "libusbi.h" -extern const uint64_t epoch_time; - struct usbi_cond_perthread { struct list_head list; DWORD tid; @@ -41,6 +39,7 @@ int usbi_mutex_static_lock(usbi_mutex_static_t *mutex) SleepEx(0, TRUE); return 0; } + int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) { if (!mutex) @@ -49,9 +48,8 @@ int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) return 0; } -int usbi_mutex_init(usbi_mutex_t *mutex, const usbi_mutexattr_t *attr) +int usbi_mutex_init(usbi_mutex_t *mutex) { - UNUSED(attr); if (!mutex) return EINVAL; *mutex = CreateMutex(NULL, FALSE, NULL); @@ -110,9 +108,8 @@ int usbi_mutex_destroy(usbi_mutex_t *mutex) return 0; } -int usbi_cond_init(usbi_cond_t *cond, const usbi_condattr_t *attr) +int usbi_cond_init(usbi_cond_t *cond) { - UNUSED(attr); if (!cond) return EINVAL; list_init(&cond->waiters); @@ -213,44 +210,19 @@ int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) } int usbi_cond_timedwait(usbi_cond_t *cond, - usbi_mutex_t *mutex, const struct timespec *abstime) + usbi_mutex_t *mutex, const struct timeval *tv) { - FILETIME filetime; - ULARGE_INTEGER rtime; - struct timeval targ_time, cur_time, delta_time; - struct timespec cur_time_ns; DWORD millis; - // GetSystemTimeAsFileTime() is not available on CE - SYSTEMTIME st; - GetSystemTime(&st); - if (!SystemTimeToFileTime(&st, &filetime)) - return 0; - rtime.LowPart = filetime.dwLowDateTime; - rtime.HighPart = filetime.dwHighDateTime; - rtime.QuadPart -= epoch_time; - cur_time_ns.tv_sec = (long)(rtime.QuadPart / 10000000); - cur_time_ns.tv_nsec = (long)((rtime.QuadPart % 10000000) * 100); - TIMESPEC_TO_TIMEVAL(&cur_time, &cur_time_ns); - - TIMESPEC_TO_TIMEVAL(&targ_time, abstime); - timersub(&targ_time, &cur_time, &delta_time); - if (delta_time.tv_sec < 0) { - // abstime already passed? - millis = 0; - } else { - millis = delta_time.tv_usec / 1000; - millis += delta_time.tv_sec * 1000; - if (delta_time.tv_usec % 1000) - millis++; // round up to next millisecond - } - + millis = (DWORD)(tv->tv_sec * 1000) + (tv->tv_usec / 1000); + /* round up to next millisecond */ + if (tv->tv_usec % 1000) + millis++; return usbi_cond_intwait(cond, mutex, millis); } -int usbi_tls_key_create(usbi_tls_key_t *key, void (*destructor)(void *)) +int usbi_tls_key_create(usbi_tls_key_t *key) { - UNUSED(destructor); if (!key) return EINVAL; *key = TlsAlloc(); @@ -265,9 +237,9 @@ void *usbi_tls_key_get(usbi_tls_key_t key) return TlsGetValue(key); } -int usbi_tls_key_set(usbi_tls_key_t key, const void *value) +int usbi_tls_key_set(usbi_tls_key_t key, void *value) { - if (TlsSetValue(key, (LPVOID)value)) + if (TlsSetValue(key, value)) return 0; else return EINVAL; diff --git a/libusb/os/threads_windows.h b/libusb/os/threads_windows.h index b9e792292..8b7faecb5 100644 --- a/libusb/os/threads_windows.h +++ b/libusb/os/threads_windows.h @@ -48,33 +48,31 @@ struct timespec { # define ETIMEDOUT 10060 /* This is the value in winsock.h. */ #endif -#define usbi_mutexattr_t void -#define usbi_condattr_t void #define usbi_tls_key_t DWORD int usbi_mutex_static_lock(usbi_mutex_static_t *mutex); int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex); -int usbi_mutex_init(usbi_mutex_t *mutex, const usbi_mutexattr_t *attr); +int usbi_mutex_init(usbi_mutex_t *mutex); int usbi_mutex_lock(usbi_mutex_t *mutex); int usbi_mutex_unlock(usbi_mutex_t *mutex); int usbi_mutex_trylock(usbi_mutex_t *mutex); int usbi_mutex_destroy(usbi_mutex_t *mutex); -int usbi_cond_init(usbi_cond_t *cond, const usbi_condattr_t *attr); +int usbi_cond_init(usbi_cond_t *cond); int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex); int usbi_cond_timedwait(usbi_cond_t *cond, - usbi_mutex_t *mutex, const struct timespec *abstime); + usbi_mutex_t *mutex, const struct timeval *tv); int usbi_cond_broadcast(usbi_cond_t *cond); int usbi_cond_destroy(usbi_cond_t *cond); -int usbi_tls_key_create(usbi_tls_key_t *key, void (*destructor)(void *)); +int usbi_tls_key_create(usbi_tls_key_t *key); void *usbi_tls_key_get(usbi_tls_key_t key); -int usbi_tls_key_set(usbi_tls_key_t key, const void *value); +int usbi_tls_key_set(usbi_tls_key_t key, void *value); int usbi_tls_key_delete(usbi_tls_key_t key); // all Windows mutexes are recursive -#define usbi_mutex_init_recursive(mutex, attr) usbi_mutex_init((mutex), (attr)) +#define usbi_mutex_init_recursive usbi_mutex_init int usbi_get_tid(void); diff --git a/libusb/os/windows_nt_common.c b/libusb/os/windows_nt_common.c index 650e2fa66..93e6278cd 100644 --- a/libusb/os/windows_nt_common.c +++ b/libusb/os/windows_nt_common.c @@ -156,7 +156,7 @@ static bool htab_create(struct libusb_context *ctx, unsigned long nel) } // Create a mutex - usbi_mutex_init(&htab_write_mutex, NULL); + usbi_mutex_init(&htab_write_mutex); // Change nel to the first prime number not smaller as nel. nel |= 1; diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index a3bc11d5b..3b58b1ad1 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -811,7 +811,7 @@ static int windows_init(struct libusb_context *ctx) } // We need a lock for proper auto-release - usbi_mutex_init(&autoclaim_lock, NULL); + usbi_mutex_init(&autoclaim_lock); // Initialize pollable file descriptors init_polling(); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index ec8f802f3..3422ff20f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11059 +#define LIBUSB_NANO 11060 From 26bb4074131b27dccdba502880c05f7fcc7d7fdf Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Thu, 25 Feb 2016 09:55:25 -0700 Subject: [PATCH 141/222] Add Travis CI configuration Signed-off-by: Nathan Hjelm --- .travis.yml | 14 ++++++++++++++ libusb/version_nano.h | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..005a50457 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,14 @@ +language: c + +compiler: + - gcc + - clang + +os: + - linux + - osx + +install: + - ./autogen.sh + - ./configure + - make -j4 diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 3422ff20f..04b539bff 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11060 +#define LIBUSB_NANO 11061 From 37df2f99c2eada5cf0d5f5b1714d98619f85f097 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Thu, 25 Feb 2016 10:12:55 -0700 Subject: [PATCH 142/222] travis: ensure udev is installed Signed-off-by: Nathan Hjelm --- .travis.yml | 4 ++++ libusb/version_nano.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 005a50457..5a6e39be3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ +sudo: required language: c compiler: @@ -8,6 +9,9 @@ os: - linux - osx +before_install: +if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then apt-get install -qq libudev-dev ; fi + install: - ./autogen.sh - ./configure diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 04b539bff..2424b1cbb 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11061 +#define LIBUSB_NANO 11062 From 6e05325ab2353e95e20e9c5fe610a28a4c4d231d Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Thu, 25 Feb 2016 10:25:07 -0700 Subject: [PATCH 143/222] travis: fix typo Signed-off-by: Nathan Hjelm --- .travis.yml | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5a6e39be3..59eba9107 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ os: - osx before_install: -if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then apt-get install -qq libudev-dev ; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then apt-get install -qq libudev-dev ; fi install: - ./autogen.sh diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 2424b1cbb..79b35c463 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11062 +#define LIBUSB_NANO 11063 From 118dac7ba41283c8d139576fef0e63c8e1c6a9cd Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Thu, 25 Feb 2016 10:25:19 -0800 Subject: [PATCH 144/222] travis: Update config file Use 'script' instead of 'install' to specify build command. Add linux build option with udev disabled. Signed-off-by: Chris Dickens --- .travis.yml | 9 ++++----- libusb/version_nano.h | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 59eba9107..fe1b36182 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,9 +10,8 @@ os: - osx before_install: - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then apt-get install -qq libudev-dev ; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then apt-get update -qq && apt-get install -qq libudev-dev; fi -install: - - ./autogen.sh - - ./configure - - make -j4 +script: + - ./autogen.sh && make -j4 + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./autogen.sh --disable-udev && make -j4; fi diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 79b35c463..3da269c32 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11063 +#define LIBUSB_NANO 11064 From 67b2f4b8c7f273b3881cc2445a7db9986e2ab256 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Thu, 25 Feb 2016 10:56:16 -0800 Subject: [PATCH 145/222] travis: Add sudo to apt-get commands Signed-off-by: Chris Dickens --- .travis.yml | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index fe1b36182..4b004333b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ os: - osx before_install: - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then apt-get update -qq && apt-get install -qq libudev-dev; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update -qq && sudo apt-get install -qq libudev-dev; fi script: - ./autogen.sh && make -j4 diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 3da269c32..2f2638359 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11064 +#define LIBUSB_NANO 11065 From 85c1f7805d23034e2f78faa0aca7e2e27ab27c90 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Thu, 25 Feb 2016 10:05:49 -0700 Subject: [PATCH 146/222] threads_posix: use backend clock_gettime() Some platforms do not implement the optional clock_gettime(). Need to use the backend implementation instead. Signed-off-by: Nathan Hjelm --- libusb/os/threads_posix.c | 3 ++- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libusb/os/threads_posix.c b/libusb/os/threads_posix.c index 89b05f38d..3908907cf 100644 --- a/libusb/os/threads_posix.c +++ b/libusb/os/threads_posix.c @@ -35,6 +35,7 @@ #endif #include "threads_posix.h" +#include "libusbi.h" int usbi_mutex_init_recursive(pthread_mutex_t *mutex) { @@ -64,7 +65,7 @@ int usbi_cond_timedwait(pthread_cond_t *cond, struct timespec timeout; int r; - r = clock_gettime(CLOCK_REALTIME, &timeout); + r = usbi_backend->clock_gettime(USBI_CLOCK_REALTIME, &timeout); if (r < 0) return r; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 2f2638359..a5120d9c6 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11065 +#define LIBUSB_NANO 11066 From 65569f2e41ce2724bce5d32d2d4893ae5dbb8219 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Thu, 25 Feb 2016 13:23:19 -0700 Subject: [PATCH 147/222] travis: test xcode project Signed-off-by: Nathan Hjelm --- .travis.yml | 1 + libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4b004333b..db6b82e96 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,3 +15,4 @@ before_install: script: - ./autogen.sh && make -j4 - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./autogen.sh --disable-udev && make -j4; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then cd Xcode && xcodebuild -project libusb.xcodeproj ; fi diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 2f2638359..a5120d9c6 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11065 +#define LIBUSB_NANO 11066 From 66ceb53f3c9a9b624d08892ebb45e18006500afa Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Thu, 25 Feb 2016 13:49:16 -0800 Subject: [PATCH 148/222] Misc: Convert README to README.md This allows markdown, including displaying Travis build status. Signed-off-by: Chris Dickens --- README => README.md | 6 ++++-- libusb/version_nano.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) rename README => README.md (88%) diff --git a/README b/README.md similarity index 88% rename from README rename to README.md index 9d434f972..44e6a9ac9 100644 --- a/README +++ b/README.md @@ -1,5 +1,6 @@ -libusb -====== +# libusb + +[![Build Status](https://travis-ci.org/libusb/libusb.svg?branch=master)](https://travis-ci.org/libusb/libusb) libusb is a library for USB device access from Linux, Mac OS X, Windows, OpenBSD/NetBSD and Haiku userspace. @@ -26,4 +27,5 @@ http://mailing-list.libusb.info - Ludovic Rousseau - Nathan Hjelm - Chris Dickens + (Please use the mailing list rather than mailing developers directly) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index a5120d9c6..58901b35f 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11066 +#define LIBUSB_NANO 11069 From 42c8f9d87005a853e61f5f1ea194b56a383cdf86 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Thu, 25 Feb 2016 13:53:05 -0800 Subject: [PATCH 149/222] Misc: Add markdown references for COPYING and PORTING files Signed-off-by: Chris Dickens --- README.md | 6 +++--- libusb/version_nano.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 44e6a9ac9..96c8dde76 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,11 @@ libusb is a library for USB device access from Linux, Mac OS X, Windows, OpenBSD/NetBSD and Haiku userspace. It is written in C (Haiku backend in C++) and licensed under the GNU Lesser General Public License version 2.1 or, at your option, any later -version (see COPYING). +version (see [COPYING](COPYING)). libusb is abstracted internally in such a way that it can hopefully -be ported to other operating systems. Please see the PORTING file -for more information. +be ported to other operating systems. Please see the [PORTING](PORTING) +file for more information. libusb homepage: http://libusb.info/ diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 58901b35f..269847ee6 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11069 +#define LIBUSB_NANO 11070 From 1624d8d855633bf19853873a1c88ebe7a8459005 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Thu, 25 Feb 2016 14:13:43 -0800 Subject: [PATCH 150/222] Misc: Link README to README.md to satisfy autotools Signed-off-by: Chris Dickens --- README | 1 + libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 120000 README diff --git a/README b/README new file mode 120000 index 000000000..42061c01a --- /dev/null +++ b/README @@ -0,0 +1 @@ +README.md \ No newline at end of file diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 269847ee6..8c98404a6 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11070 +#define LIBUSB_NANO 11071 From 09f212b730910c3e910265166a6a46f0c8a86d5a Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Thu, 25 Feb 2016 21:36:26 -0700 Subject: [PATCH 151/222] travis: use addons to install packages Signed-off-by: Nathan Hjelm --- .travis.yml | 10 ++++++++-- libusb/version_nano.h | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index db6b82e96..b5f0ce483 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,8 +9,14 @@ os: - linux - osx -before_install: - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update -qq && sudo apt-get install -qq libudev-dev; fi + +addons: + apt: + - autoconf + - automake + - libtool + - m4 + - libudev-dev script: - ./autogen.sh && make -j4 diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 8c98404a6..05e39de9a 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11071 +#define LIBUSB_NANO 11072 From d38788904ad03ba210eb0a298007ca837f05deba Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Thu, 25 Feb 2016 21:40:30 -0700 Subject: [PATCH 152/222] travis: bah. remove tabs Signed-off-by: Nathan Hjelm --- .travis.yml | 8 ++++---- libusb/version_nano.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index b5f0ce483..17a27ee2a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,10 +13,10 @@ os: addons: apt: - autoconf - - automake - - libtool - - m4 - - libudev-dev + - automake + - libtool + - m4 + - libudev-dev script: - ./autogen.sh && make -j4 diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 05e39de9a..9f9eb6583 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11072 +#define LIBUSB_NANO 11073 From 78dc70a860f7bd2ff56ec5506719faa32f4b2182 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Thu, 25 Feb 2016 21:45:15 -0700 Subject: [PATCH 153/222] travis: sources line is needed Signed-off-by: Nathan Hjelm --- .travis.yml | 2 ++ libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 17a27ee2a..f74cbf8ad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,8 @@ addons: - libtool - m4 - libudev-dev + sources: + - ubuntu-toolchain-r-test script: - ./autogen.sh && make -j4 diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 9f9eb6583..d989e9e24 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11073 +#define LIBUSB_NANO 11074 From 6de66bbdb7f1c6db8215867190dc5d0ce52875c2 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Thu, 25 Feb 2016 21:51:10 -0700 Subject: [PATCH 154/222] travis: one more fix. need packages under apt Signed-off-by: Nathan Hjelm --- .travis.yml | 15 ++++++++------- libusb/version_nano.h | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index f74cbf8ad..274553806 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,13 +12,14 @@ os: addons: apt: - - autoconf - - automake - - libtool - - m4 - - libudev-dev - sources: - - ubuntu-toolchain-r-test + packages: + - autoconf + - automake + - libtool + - m4 + - libudev-dev + sources: + - ubuntu-toolchain-r-test script: - ./autogen.sh && make -j4 diff --git a/libusb/version_nano.h b/libusb/version_nano.h index d989e9e24..c896b6590 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11074 +#define LIBUSB_NANO 11075 From 64d583f4dc83e9e1ec5bc9c2269cfd17523eb070 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Thu, 25 Feb 2016 13:35:36 -0700 Subject: [PATCH 155/222] bootstrap: use autoreconf Signed-off-by: Nathan Hjelm --- bootstrap.sh | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 8b2b2c008..dc5653941 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -1,19 +1,6 @@ #!/bin/sh -set -e - -# use libtoolize if available, otherwise look for glibtoolize (darwin) -if (libtoolize --version) < /dev/null > /dev/null 2>&1; then - LIBTOOLIZE=libtoolize -elif (glibtoolize --version) < /dev/null > /dev/null 2>&1; then - LIBTOOLIZE=glibtoolize -else - echo "libtoolize or glibtoolize was not found! Please install libtool." 1>&2 - exit 1 +if ! test -d m4 ; then + mkdir m4 fi - -$LIBTOOLIZE --copy --force || exit 1 -aclocal || exit 1 -autoheader || exit 1 -autoconf || exit 1 -automake -a -c || exit 1 +autoreconf -ivf || exit 1 From 1d54ee1b6687c532eca75925f56eb12e2a34ce42 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 28 Apr 2015 16:46:37 +1000 Subject: [PATCH 156/222] Windows: Fix parent USB device reference leak If windows_get_device_list() found a device that already existed, it would erronenously increment the parent_dev refcount and cause a reference leak - the parent device would never be released. Signed-off-by: Chris Dickens --- libusb/os/windows_winusb.c | 7 +++++++ libusb/version_nano.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 3b58b1ad1..a5c70dbce 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -1523,6 +1523,13 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered } else { usbi_dbg("found existing device for session [%lX] (%u.%u)", session_id, dev->bus_number, dev->device_address); + if (_device_priv(dev)->parent_dev != parent_dev) { + usbi_err(ctx,"program assertion failed - existing device should share parent"); + } else { + // We hold a reference to parent_dev instance, but this device already + // has a parent_dev reference (only one per child) + libusb_unref_device(parent_dev); + } } // Keep track of devices that need unref diff --git a/libusb/version_nano.h b/libusb/version_nano.h index c896b6590..28b8b2eaf 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11075 +#define LIBUSB_NANO 11077 From 926148d5f72d838cabafabe61e02871bc8b6854e Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 28 Apr 2015 16:49:57 +1000 Subject: [PATCH 157/222] Windows: Fix dev_interface_path memory leak when reusing device ref windows_get_device_list was leaking dev_interface_path (in either of two possible places) when a pre-existing device reference was reused. Signed-off-by: Chris Dickens --- libusb/os/windows_winusb.c | 25 ++++++++++++++----------- libusb/version_nano.h | 2 +- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index a5c70dbce..b716278c9 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -1264,7 +1264,7 @@ static int set_hid_interface(struct libusb_context *ctx, struct libusb_device *d for (i = 0; i < priv->hid->nb_interfaces; i++) { if (safe_strcmp(priv->usb_interface[i].path, dev_interface_path) == 0) { usbi_dbg("interface[%d] already set to %s", i, dev_interface_path); - return LIBUSB_SUCCESS; + return LIBUSB_ERROR_ACCESS; } } @@ -1548,6 +1548,9 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered // Setup device switch (pass) { case HCD_PASS: + // If the hcd has already been setup, don't do it again + if (priv->path != NULL) + break; dev->bus_number = (uint8_t)(i + 1); // bus 0 is reserved for disconnected dev->device_address = 0; dev->num_configurations = 0; @@ -1607,21 +1610,21 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered } break; default: // HID_PASS and later - if (parent_priv->apib->id == USB_API_HID) { - usbi_dbg("setting HID interface for [%lX]:", parent_dev->session_data); - r = set_hid_interface(ctx, parent_dev, dev_interface_path); - if (r != LIBUSB_SUCCESS) - LOOP_BREAK(r); - - dev_interface_path = NULL; - } else if (parent_priv->apib->id == USB_API_COMPOSITE) { - usbi_dbg("setting composite interface for [%lX]:", parent_dev->session_data); - switch (set_composite_interface(ctx, parent_dev, dev_interface_path, dev_id_path, api, sub_api)) { + if (parent_priv->apib->id == USB_API_HID || parent_priv->apib->id == USB_API_COMPOSITE) { + if (parent_priv->apib->id == USB_API_HID) { + usbi_dbg("setting HID interface for [%lX]:", parent_dev->session_data); + r = set_hid_interface(ctx, parent_dev, dev_interface_path); + } else { + usbi_dbg("setting composite interface for [%lX]:", parent_dev->session_data); + r = set_composite_interface(ctx, parent_dev, dev_interface_path, dev_id_path, api, sub_api); + } + switch (r) { case LIBUSB_SUCCESS: dev_interface_path = NULL; break; case LIBUSB_ERROR_ACCESS: // interface has already been set => make sure dev_interface_path is freed then + r = LIBUSB_SUCCESS; break; default: LOOP_BREAK(r); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 28b8b2eaf..bd5f24ac5 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11077 +#define LIBUSB_NANO 11078 From c572f9721d8471d43e561e81fd0f3863f38640eb Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Wed, 2 Mar 2016 00:14:50 -0800 Subject: [PATCH 158/222] Windows: Add backend support for get_config_descriptor_by_value() Signed-off-by: Chris Dickens --- libusb/os/windows_winusb.c | 37 ++++++++++++++++++++++++++++++++++--- libusb/version_nano.h | 2 +- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index b716278c9..30e5dd70a 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -1718,18 +1718,49 @@ static int windows_get_config_descriptor(struct libusb_device *dev, uint8_t conf return (int)size; } +static int windows_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue, + unsigned char **buffer, int *host_endian) +{ + struct windows_device_priv *priv = _device_priv(dev); + PUSB_CONFIGURATION_DESCRIPTOR config_header; + uint8_t index; + + *buffer = NULL; + *host_endian = 0; + + if (priv->config_descriptor == NULL) + return LIBUSB_ERROR_NOT_FOUND; + + for (index = 0; index < dev->num_configurations; index++) { + config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptor[index]; + if (config_header->bConfigurationValue == bConfigurationValue) { + *buffer = priv->config_descriptor[index]; + return (int)config_header->wTotalLength; + } + } + + return LIBUSB_ERROR_NOT_FOUND; +} + /* * return the cached copy of the active config descriptor */ static int windows_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian) { struct windows_device_priv *priv = _device_priv(dev); + unsigned char *config_desc; + int r; if (priv->active_config == 0) return LIBUSB_ERROR_NOT_FOUND; - // config index is zero based - return windows_get_config_descriptor(dev, (uint8_t)(priv->active_config-1), buffer, len, host_endian); + r = windows_get_config_descriptor_by_value(dev, priv->active_config, &config_desc, host_endian); + if (r < 0) + return r; + + len = MIN((size_t)r, len); + memcpy(buffer, config_desc, len); + return (int)len; } static int windows_open(struct libusb_device_handle *dev_handle) @@ -2024,7 +2055,7 @@ const struct usbi_os_backend windows_backend = { windows_get_device_descriptor, windows_get_active_config_descriptor, windows_get_config_descriptor, - NULL, /* get_config_descriptor_by_value() */ + windows_get_config_descriptor_by_value, windows_get_configuration, windows_set_configuration, diff --git a/libusb/version_nano.h b/libusb/version_nano.h index bd5f24ac5..c2ada6100 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11078 +#define LIBUSB_NANO 11079 From 7bfc729b69aa00b396f0eb610f7528a288015769 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Wed, 2 Mar 2016 00:16:16 -0800 Subject: [PATCH 159/222] Windows: Fix faulty logic that can pick the wrong config descriptor The WinUSB backend caches the bConfigurationValue of the currently active configuration when the device is enumerated. In some parts of the code, the config descriptor is fetched to correlate interfaces and endpoints by calling libusb_get_config_descriptor() using the cached bConfigurationValue. This is incorrect usage of the function as the input parameter is the zero-based configuration index, which can differ in some devices from the bConfigurationValue. See discussion: http://marc.info/?l=libusb-devel&m=144355607228333 Signed-off-by: Chris Dickens --- libusb/os/windows_winusb.c | 9 ++------- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 30e5dd70a..9fe29566a 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -56,11 +56,6 @@ continue; \ } -// Helper prototypes -static int windows_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian); -// Common calls -static int common_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface); - // WinUSB-like API prototypes static int winusbx_init(int sub_api, struct libusb_context *ctx); static int winusbx_exit(int sub_api); @@ -527,7 +522,7 @@ static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int const struct libusb_interface_descriptor *if_desc; struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - r = libusb_get_config_descriptor(dev_handle->dev, (uint8_t)(priv->active_config-1), &conf_desc); + r = libusb_get_active_config_descriptor(dev_handle->dev, &conf_desc); if (r != LIBUSB_SUCCESS) { usbi_warn(ctx, "could not read config descriptor: error %d", r); return r; @@ -4124,7 +4119,7 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer * iface = setup->index & 0xFF; break; case LIBUSB_RECIPIENT_ENDPOINT: - r = libusb_get_config_descriptor(transfer->dev_handle->dev, (uint8_t)(priv->active_config - 1), &conf_desc); + r = libusb_get_active_config_descriptor(transfer->dev_handle->dev, &conf_desc); if (r == LIBUSB_SUCCESS) { iface = get_interface_by_endpoint(conf_desc, (setup->index & 0xFF)); libusb_free_config_descriptor(conf_desc); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index c2ada6100..0d4a292a0 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11079 +#define LIBUSB_NANO 11080 From 244e3940de2d6d1f8bd7fe2f6a64f920fd8714d3 Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Wed, 2 Mar 2016 14:12:04 +0100 Subject: [PATCH 160/222] README.md: add Coverity badge The libusb project is available on Coverity at https://scan.coverity.com/projects/libusb-libusb Signed-off-by: Ludovic Rousseau --- README.md | 1 + libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 96c8dde76..2da689a7f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # libusb [![Build Status](https://travis-ci.org/libusb/libusb.svg?branch=master)](https://travis-ci.org/libusb/libusb) +[![Coverity Scan Build Status](https://scan.coverity.com/projects/2180/badge.svg)](https://scan.coverity.com/projects/libusb-libusb) libusb is a library for USB device access from Linux, Mac OS X, Windows, OpenBSD/NetBSD and Haiku userspace. diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 0d4a292a0..1f35b5be0 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11080 +#define LIBUSB_NANO 11081 From 680828abf88096d802f8ab4e0e603ae7bc05af7f Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Sat, 27 Feb 2016 17:37:49 +0100 Subject: [PATCH 161/222] core: fix 2 compiler warnings core.c:2361:35: warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare] if (header_len < 0 || header_len >= sizeof(buf)) { ~~~~~~~~~~ ^ ~~~~~~~~~~~ core.c:2370:44: warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare] if (text_len < 0 || text_len + header_len >= sizeof(buf)) { ~~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~ Signed-off-by: Ludovic Rousseau --- libusb/core.c | 4 ++-- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 31f3d2875..5317d2637 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -2358,7 +2358,7 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, "libusb: %s [%s] ", prefix, function); } - if (header_len < 0 || header_len >= sizeof(buf)) { + if (header_len < 0 || header_len >= (int)sizeof(buf)) { /* Somehow snprintf failed to write to the buffer, * remove the header so something useful is output. */ header_len = 0; @@ -2367,7 +2367,7 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, buf[header_len] = '\0'; text_len = vsnprintf(buf + header_len, sizeof(buf) - header_len, format, args); - if (text_len < 0 || text_len + header_len >= sizeof(buf)) { + if (text_len < 0 || text_len + header_len >= (int)sizeof(buf)) { /* Truncated log output. On some platforms a -1 return value means * that the output was truncated. */ text_len = sizeof(buf) - header_len; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 1f35b5be0..2847bad8c 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11081 +#define LIBUSB_NANO 11083 From 4bfa440e5f5339bfaaf5baae763d45b77b64294b Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Sat, 27 Feb 2016 17:42:55 +0100 Subject: [PATCH 162/222] darwin: fix 1 compiler warning os/darwin_usb.c:248:18: warning: comparison of integers of different signs: 'CFIndex' (aka 'long') and 'size_t' (aka 'unsigned long') [-Wsign-compare] if (length < size) { ~~~~~~ ^ ~~~~ Signed-off-by: Ludovic Rousseau --- libusb/os/darwin_usb.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index a19f04a6b..928486642 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -238,7 +238,7 @@ static int get_ioregistry_value_number (io_service_t service, CFStringRef proper return ret; } -static int get_ioregistry_value_data (io_service_t service, CFStringRef property, size_t size, void *p) { +static int get_ioregistry_value_data (io_service_t service, CFStringRef property, ssize_t size, void *p) { CFTypeRef cfData = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0); int ret = 0; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 2847bad8c..4cd53ff1d 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11083 +#define LIBUSB_NANO 11084 From 3661588fe6ccbb2ca7ad9bb51a8f64a2a0161c6c Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Sat, 27 Feb 2016 17:47:12 +0100 Subject: [PATCH 163/222] examples: fix 2 compiler warnings ezusb.c:136:13: warning: comparison of integers of different signs: 'int' and 'size_t' (aka 'unsigned long') [-Wsign-compare] if (status != len) { ~~~~~~ ^ ~~~ ezusb.c:159:13: warning: comparison of integers of different signs: 'int' and 'size_t' (aka 'unsigned long') [-Wsign-compare] if (status != len) { ~~~~~~ ^ ~~~ Signed-off-by: Ludovic Rousseau --- examples/ezusb.c | 4 ++-- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/ezusb.c b/examples/ezusb.c index f369e5094..e3b488d36 100644 --- a/examples/ezusb.c +++ b/examples/ezusb.c @@ -133,7 +133,7 @@ static int ezusb_write(libusb_device_handle *device, const char *label, LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, opcode, addr & 0xFFFF, addr >> 16, (unsigned char*)data, (uint16_t)len, 1000); - if (status != len) { + if (status != (signed)len) { if (status < 0) logerror("%s: %s\n", label, libusb_error_name(status)); else @@ -156,7 +156,7 @@ static int ezusb_read(libusb_device_handle *device, const char *label, LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, opcode, addr & 0xFFFF, addr >> 16, (unsigned char*)data, (uint16_t)len, 1000); - if (status != len) { + if (status != (signed)len) { if (status < 0) logerror("%s: %s\n", label, libusb_error_name(status)); else diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 4cd53ff1d..e27a75475 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11084 +#define LIBUSB_NANO 11085 From 2e78f9525f0558dcb004486baa18a0fcc7ccfb5e Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Sat, 27 Feb 2016 17:49:55 +0100 Subject: [PATCH 164/222] examples: fix 2 compiler warnings sam3u_benchmark.c:54:17: warning: comparison of integers of different signs: 'unsigned int' and 'int' [-Wsign-compare] for (i = 0; i < xfr->num_iso_packets; i++) { ~ ^ ~~~~~~~~~~~~~~~~~~~~ sam3u_benchmark.c:67:16: warning: comparison of integers of different signs: 'unsigned int' and 'int' [-Wsign-compare] for (i = 0; i < xfr->actual_length; i++) { ~ ^ ~~~~~~~~~~~~~~~~~~ Signed-off-by: Ludovic Rousseau --- examples/sam3u_benchmark.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/sam3u_benchmark.c b/examples/sam3u_benchmark.c index 99d6b0f1b..7189b22d1 100644 --- a/examples/sam3u_benchmark.c +++ b/examples/sam3u_benchmark.c @@ -42,7 +42,7 @@ static struct timeval tv_start; static void LIBUSB_CALL cb_xfr(struct libusb_transfer *xfr) { - unsigned int i; + int i; if (xfr->status != LIBUSB_TRANSFER_COMPLETED) { fprintf(stderr, "transfer status %d\n", xfr->status); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index e27a75475..34110b07c 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11085 +#define LIBUSB_NANO 11086 From 686ccc284b9c54984fce6a8d2a29d020ede773a9 Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Sat, 27 Feb 2016 17:52:05 +0100 Subject: [PATCH 165/222] examples: fix 3 compiler warnings fxload.c:202:17: warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare] ...for (j=0; j --- examples/fxload.c | 3 ++- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/fxload.c b/examples/fxload.c index 5dff736db..5aa5226d6 100644 --- a/examples/fxload.c +++ b/examples/fxload.c @@ -89,7 +89,8 @@ int main(int argc, char*argv[]) const char *fx_name[FX_TYPE_MAX] = FX_TYPE_NAMES; const char *ext, *img_name[] = IMG_TYPE_NAMES; int fx_type = FX_TYPE_UNDEFINED, img_type[ARRAYSIZE(path)]; - int i, j, opt, status; + int opt, status; + unsigned int i, j; unsigned vid = 0, pid = 0; unsigned busnum = 0, devaddr = 0, _busnum, _devaddr; libusb_device *dev, **devs; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 34110b07c..340ae63a6 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11086 +#define LIBUSB_NANO 11087 From 765a1fbf8b80c62b98e05e6d89cbe5fe32d76169 Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Sat, 27 Feb 2016 17:17:24 +0100 Subject: [PATCH 166/222] travis-CI: fails compilation on warning The travis-autogen.sh script enable some extra warnings not used by default. The idea is to detect problem as early as possible. --- .travis.yml | 2 +- travis-autogen.sh | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100755 travis-autogen.sh diff --git a/.travis.yml b/.travis.yml index 274553806..585cd6f56 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,5 +23,5 @@ addons: script: - ./autogen.sh && make -j4 - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./autogen.sh --disable-udev && make -j4; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./travis-autogen.sh --disable-udev && make -j4; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then cd Xcode && xcodebuild -project libusb.xcodeproj ; fi diff --git a/travis-autogen.sh b/travis-autogen.sh new file mode 100755 index 000000000..d83e07dc0 --- /dev/null +++ b/travis-autogen.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# Warnings enabled +CFLAGS="-Wall -Wextra" + +CFLAGS+=" -Wbad-function-cast" +#CFLAGS+=" -Wcast-align" +CFLAGS+=" -Wchar-subscripts" +CFLAGS+=" -Wempty-body" +CFLAGS+=" -Wformat" +CFLAGS+=" -Wformat-security" +CFLAGS+=" -Winit-self" +CFLAGS+=" -Winline" +CFLAGS+=" -Wmissing-declarations" +CFLAGS+=" -Wmissing-include-dirs" +CFLAGS+=" -Wmissing-prototypes" +CFLAGS+=" -Wnested-externs" +CFLAGS+=" -Wold-style-definition" +CFLAGS+=" -Wpointer-arith" +CFLAGS+=" -Wredundant-decls" +CFLAGS+=" -Wshadow" +CFLAGS+=" -Wstrict-prototypes" +CFLAGS+=" -Wswitch-enum" +CFLAGS+=" -Wundef" +CFLAGS+=" -Wuninitialized" +CFLAGS+=" -Wunused" +CFLAGS+=" -Wwrite-strings" +CFLAGS+=" -fdiagnostics-color=auto" + +# warnings disabled on purpose +CFLAGS+=" -Wno-unused-parameter" +CFLAGS+=" -Wno-unused-function" +CFLAGS+=" -Wno-deprecated-declarations" + +# should be removed and the code fixed +CFLAGS+=" -Wno-incompatible-pointer-types-discards-qualifiers" + +# fails on warning +CFLAGS+=" -Werror" + +./autogen.sh From 31ff09c35a582cc6870dfd2c9924d62e79d2f933 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Thu, 3 Mar 2016 00:20:33 -0800 Subject: [PATCH 167/222] Windows: Fix MinGW build The integration of UsbDk moved the windows_error_str() function to windows_nt_common.c, but the definition of FACILITY_SETUPAPI (which MinGW headers do not provide) did not follow the move. Signed-off-by: Chris Dickens --- libusb/os/windows_nt_common.h | 5 +++++ libusb/os/windows_winusb.h | 5 ----- libusb/version_nano.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libusb/os/windows_nt_common.h b/libusb/os/windows_nt_common.h index ceb547bf6..9749e0018 100644 --- a/libusb/os/windows_nt_common.h +++ b/libusb/os/windows_nt_common.h @@ -26,6 +26,11 @@ #pragma once +// Missing from MinGW +#if !defined(FACILITY_SETUPAPI) +#define FACILITY_SETUPAPI 15 +#endif + typedef struct USB_CONFIGURATION_DESCRIPTOR { UCHAR bLength; UCHAR bDescriptorType; diff --git a/libusb/os/windows_winusb.h b/libusb/os/windows_winusb.h index d544a7f9e..303f4a6fa 100644 --- a/libusb/os/windows_winusb.h +++ b/libusb/os/windows_winusb.h @@ -43,11 +43,6 @@ #define SPDRP_INSTALL_STATE 34 #endif -// Missing from MinGW -#if !defined(FACILITY_SETUPAPI) -#define FACILITY_SETUPAPI 15 -#endif - #define MAX_CTRL_BUFFER_LENGTH 4096 #define MAX_USB_DEVICES 256 #define MAX_USB_STRING_LENGTH 128 diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 340ae63a6..0336befef 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11087 +#define LIBUSB_NANO 11088 From fc2840f61b89f7805f70b131e5a5dd822ddb00b7 Mon Sep 17 00:00:00 2001 From: hacker2490 Date: Thu, 3 Mar 2016 21:11:20 +0100 Subject: [PATCH 168/222] AppVeyor: initial configuration file Signed-off-by: Ludovic Rousseau --- appveyor.yml | 22 ++++++++++++++++++++++ libusb/version_nano.h | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..af5d08f92 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,22 @@ +version: 1.0.{build} +configuration: +- Debug +- Release +platform: +- x64 +- Win32 +environment: + matrix: + - libusb_2015: msvc\libusb_2015.sln + libusb_2013: msvc\libusb_2013.sln + libusb_2012: msvc\libusb_2012.sln + libusb_2010: msvc\libusb_2010.sln +build_script: +- cmd: >- + msbuild %libusb_2015% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" + + msbuild %libusb_2013% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" + + msbuild %libusb_2012% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" + + msbuild %libusb_2010% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 0336befef..101796629 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11088 +#define LIBUSB_NANO 11090 From fb2b6b2a92a41706a7d4ef4734aba7849c84cdf8 Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Thu, 3 Mar 2016 21:50:15 +0100 Subject: [PATCH 169/222] README.md: add AppVeyor badge Signed-off-by: Ludovic Rousseau --- README.md | 1 + libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2da689a7f..3da801285 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # libusb [![Build Status](https://travis-ci.org/libusb/libusb.svg?branch=master)](https://travis-ci.org/libusb/libusb) +[![Build status](https://ci.appveyor.com/api/projects/status/3qvcj8uceo1bylik?svg=true)](https://ci.appveyor.com/project/LudovicRousseau/libusb) [![Coverity Scan Build Status](https://scan.coverity.com/projects/2180/badge.svg)](https://scan.coverity.com/projects/libusb-libusb) libusb is a library for USB device access from Linux, Mac OS X, diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 101796629..21a637d0b 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11090 +#define LIBUSB_NANO 11089 From 1fd08a1513dc323ddf7fae97888eb09215a1f0b6 Mon Sep 17 00:00:00 2001 From: Stefan Tauner Date: Tue, 19 Jan 2016 00:02:16 +0100 Subject: [PATCH 170/222] Replace obsolete usleep with nanosleep This fixes compiling libusb with uclibc. Closes #141, #165 Signed-off-by: Stefan Tauner --- examples/xusb.c | 4 ++-- libusb/hotplug.c | 3 ++- libusb/os/darwin_usb.c | 3 ++- libusb/os/linux_usbfs.c | 4 ++-- libusb/version_nano.h | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/examples/xusb.c b/examples/xusb.c index 0fdb19d44..8f4fd53c8 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -29,8 +29,8 @@ #if defined(_WIN32) #define msleep(msecs) Sleep(msecs) #else -#include -#define msleep(msecs) usleep(1000*msecs) +#include +#define msleep(msecs) nanosleep(&(struct timespec){delay / 1000, (delay * 1000000) % 1000000000UL}, NULL); #endif #if defined(_MSC_VER) diff --git a/libusb/hotplug.c b/libusb/hotplug.c index 5db8d0b77..bbfd6e79a 100644 --- a/libusb/hotplug.c +++ b/libusb/hotplug.c @@ -94,6 +94,7 @@ \code #include #include +#include #include static int count = 0; @@ -142,7 +143,7 @@ int main (void) { while (count < 2) { libusb_handle_events_completed(NULL, NULL); - usleep(10000); + nanosleep(&(struct timespec){0, 10000000UL}, NULL); } libusb_hotplug_deregister_callback(NULL, callback_handle); diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 928486642..0f346f56b 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -19,6 +19,7 @@ */ #include "config.h" +#include #include #include #include @@ -764,7 +765,7 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da if (kIOReturnSuccess != ret) { usbi_dbg("kernel responded with code: 0x%08x. sleeping for %d ms before trying again", ret, delay/1000); /* sleep for a little while before trying again */ - usleep (delay); + nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL); } } while (kIOReturnSuccess != ret && retries--); diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 217a74784..d154aa9a3 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include "libusbi.h" #include "linux_usbfs.h" @@ -202,7 +202,7 @@ static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent) usbi_err(ctx, "File doesn't exist, wait %d ms and try again", delay/1000); /* Wait 10ms for USB device path creation.*/ - usleep(delay); + nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL); fd = open(path, mode); if (fd != -1) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 21a637d0b..701fca240 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11089 +#define LIBUSB_NANO 11092 From a499ef20a1e49050c93181d64ba84278aef8bb99 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Sat, 5 Mar 2016 08:00:11 -0700 Subject: [PATCH 171/222] xusb: fix typo Signed-off-by: Nathan Hjelm --- examples/xusb.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/xusb.c b/examples/xusb.c index 8f4fd53c8..352a5d74a 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -30,7 +30,7 @@ #define msleep(msecs) Sleep(msecs) #else #include -#define msleep(msecs) nanosleep(&(struct timespec){delay / 1000, (delay * 1000000) % 1000000000UL}, NULL); +#define msleep(msecs) nanosleep(&(struct timespec){msecs / 1000, (msecs * 1000000) % 1000000000UL}, NULL); #endif #if defined(_MSC_VER) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 701fca240..5709b65ea 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11092 +#define LIBUSB_NANO 11091 From 763668cc925b0f07d5320f2bf8038a9d504dc63d Mon Sep 17 00:00:00 2001 From: parafin Date: Thu, 15 Oct 2015 20:12:42 +0300 Subject: [PATCH 172/222] darwin: fix occasional dead-lock on libusb_exit CFRunLoopStop() isn't thread-safe, see for example this bugreport: https://github.com/joyent/libuv/issues/799 Use CFRunLoopSource instead Closes #112 Signed-off-by: Nathan Hjelm --- libusb/os/darwin_usb.c | 17 ++++++++++++++++- libusb/version_nano.h | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 0f346f56b..4e4ab04cf 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -54,6 +54,7 @@ static clock_serv_t clock_realtime; static clock_serv_t clock_monotonic; static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */ +static CFRunLoopSourceRef libusb_darwin_acfls = NULL; /* shutdown signal for event cf loop */ static volatile int32_t initCount = 0; static usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER; @@ -383,6 +384,7 @@ static void *darwin_event_thread_main (void *arg0) { #endif /* hotplug (device arrival/removal) sources */ + CFRunLoopSourceContext libusb_shutdown_cfsourcectx; CFRunLoopSourceRef libusb_notification_cfsource; io_notification_port_t libusb_notification_port; io_iterator_t libusb_rem_device_iterator; @@ -393,6 +395,13 @@ static void *darwin_event_thread_main (void *arg0) { runloop = CFRunLoopGetCurrent (); CFRetain (runloop); + /* add the shutdown cfsource to the run loop */ + memset(&libusb_shutdown_cfsourcectx, 0, sizeof(libusb_shutdown_cfsourcectx)); + libusb_shutdown_cfsourcectx.info = runloop; + libusb_shutdown_cfsourcectx.perform = (void (*)(void *))CFRunLoopStop; + libusb_darwin_acfls = CFRunLoopSourceCreate(NULL, 0, &libusb_shutdown_cfsourcectx); + CFRunLoopAddSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode); + /* add the notification port to the run loop */ libusb_notification_port = IONotificationPortCreate (kIOMasterPortDefault); libusb_notification_cfsource = IONotificationPortGetRunLoopSource (libusb_notification_port); @@ -442,6 +451,9 @@ static void *darwin_event_thread_main (void *arg0) { /* remove the notification cfsource */ CFRunLoopRemoveSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode); + /* remove the shutdown cfsource */ + CFRunLoopRemoveSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode); + /* delete notification port */ IONotificationPortDestroy (libusb_notification_port); @@ -449,8 +461,10 @@ static void *darwin_event_thread_main (void *arg0) { IOObjectRelease (libusb_rem_device_iterator); IOObjectRelease (libusb_add_device_iterator); + CFRelease (libusb_darwin_acfls); CFRelease (runloop); + libusb_darwin_acfls = NULL; libusb_darwin_acfl = NULL; pthread_exit (NULL); @@ -522,7 +536,8 @@ static void darwin_exit (void) { mach_port_deallocate(mach_task_self(), clock_monotonic); /* stop the event runloop and wait for the thread to terminate. */ - CFRunLoopStop (libusb_darwin_acfl); + CFRunLoopSourceSignal(libusb_darwin_acfls); + CFRunLoopWakeUp (libusb_darwin_acfl); pthread_join (libusb_darwin_at, NULL); } } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 5709b65ea..039b1d16b 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11091 +#define LIBUSB_NANO 11093 From 79cc25a0a021aefef6ae811cca85b2bcfa0b610e Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Sun, 6 Mar 2016 13:37:14 +0100 Subject: [PATCH 173/222] darwin: build hotplugtest sample in Xcode The Xcode project now also builds the hotplugtest (from examples/hotplugtest.c) target. --- Xcode/libusb.xcodeproj/project.pbxproj | 96 +++++++++++++++++++++++++- libusb/version_nano.h | 2 +- 2 files changed, 94 insertions(+), 4 deletions(-) diff --git a/Xcode/libusb.xcodeproj/project.pbxproj b/Xcode/libusb.xcodeproj/project.pbxproj index e3713113a..773bd1a8e 100644 --- a/Xcode/libusb.xcodeproj/project.pbxproj +++ b/Xcode/libusb.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ buildPhases = ( ); dependencies = ( + 006AD4281C8C5BBC007F8C6A /* PBXTargetDependency */, 008FC0371628BC9A00BC5BE2 /* PBXTargetDependency */, 008FC0391628BC9A00BC5BE2 /* PBXTargetDependency */, 008FC03B1628BC9A00BC5BE2 /* PBXTargetDependency */, @@ -26,6 +27,9 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 006AD4241C8C5AAE007F8C6A /* hotplugtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 006AD4231C8C5AAE007F8C6A /* hotplugtest.c */; }; + 006AD4251C8C5AC4007F8C6A /* hotplugtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 006AD4231C8C5AAE007F8C6A /* hotplugtest.c */; }; + 006AD4261C8C5AD9007F8C6A /* libusb-1.0.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */; }; 008FBF861628B7E800BC5BE2 /* core.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBF541628B7E800BC5BE2 /* core.c */; }; 008FBF871628B7E800BC5BE2 /* descriptor.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBF551628B7E800BC5BE2 /* descriptor.c */; }; 008FBF881628B7E800BC5BE2 /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBF561628B7E800BC5BE2 /* io.c */; }; @@ -61,6 +65,13 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 006AD4271C8C5BBC007F8C6A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 008FBF281628B79300BC5BE2 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 006AD41B1C8C5A90007F8C6A; + remoteInfo = hotplugtest; + }; 008FC0361628BC9A00BC5BE2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 008FBF281628B79300BC5BE2 /* Project object */; @@ -141,6 +152,15 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + 006AD41A1C8C5A90007F8C6A /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; 008FBFBB1628B9FE00BC5BE2 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -189,6 +209,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 006AD41C1C8C5A90007F8C6A /* hotplugtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = hotplugtest; sourceTree = BUILT_PRODUCTS_DIR; }; + 006AD4231C8C5AAE007F8C6A /* hotplugtest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hotplugtest.c; sourceTree = ""; }; 008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = "libusb-1.0.0.dylib"; sourceTree = BUILT_PRODUCTS_DIR; }; 008FBF541628B7E800BC5BE2 /* core.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = core.c; sourceTree = ""; }; 008FBF551628B7E800BC5BE2 /* descriptor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = descriptor.c; sourceTree = ""; }; @@ -232,6 +254,14 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 006AD4191C8C5A90007F8C6A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 006AD4261C8C5AD9007F8C6A /* libusb-1.0.0.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 008FBF2E1628B79300BC5BE2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -306,6 +336,7 @@ 008FC0051628BBDB00BC5BE2 /* dpfp_threaded */, 008FC0151628BC0300BC5BE2 /* fxload */, 008FC0261628BC6B00BC5BE2 /* listdevs */, + 006AD41C1C8C5A90007F8C6A /* hotplugtest */, ); name = Products; sourceTree = ""; @@ -346,13 +377,14 @@ 008FBFC81628BA0E00BC5BE2 /* examples */ = { isa = PBXGroup; children = ( - 008FBFD71628BA0E00BC5BE2 /* dpfp.c */, 008FBFDB1628BA0E00BC5BE2 /* dpfp_threaded.c */, + 008FBFD71628BA0E00BC5BE2 /* dpfp.c */, 008FBFDC1628BA0E00BC5BE2 /* ezusb.c */, + 008FBFDD1628BA0E00BC5BE2 /* ezusb.h */, 008FBFE11628BA0E00BC5BE2 /* fxload.c */, + 006AD4231C8C5AAE007F8C6A /* hotplugtest.c */, 008FBFE71628BA0E00BC5BE2 /* listdevs.c */, 008FBFED1628BA0E00BC5BE2 /* xusb.c */, - 008FBFDD1628BA0E00BC5BE2 /* ezusb.h */, ); name = examples; path = ../examples; @@ -405,6 +437,23 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + 006AD41B1C8C5A90007F8C6A /* hotplugtest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 006AD4221C8C5A90007F8C6A /* Build configuration list for PBXNativeTarget "hotplugtest" */; + buildPhases = ( + 006AD4181C8C5A90007F8C6A /* Sources */, + 006AD4191C8C5A90007F8C6A /* Frameworks */, + 006AD41A1C8C5A90007F8C6A /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = hotplugtest; + productName = hotplugtest; + productReference = 006AD41C1C8C5A90007F8C6A /* hotplugtest */; + productType = "com.apple.product-type.tool"; + }; 008FBF301628B79300BC5BE2 /* libusb */ = { isa = PBXNativeTarget; buildConfigurationList = 008FBF351628B79300BC5BE2 /* Build configuration list for PBXNativeTarget "libusb" */; @@ -520,6 +569,11 @@ attributes = { LastUpgradeCheck = 0450; ORGANIZATIONNAME = libusb; + TargetAttributes = { + 006AD41B1C8C5A90007F8C6A = { + CreatedOnToolsVersion = 7.2.1; + }; + }; }; buildConfigurationList = 008FBF2B1628B79300BC5BE2 /* Build configuration list for PBXProject "libusb" */; compatibilityVersion = "Xcode 3.1"; @@ -539,12 +593,21 @@ 008FC0041628BBDB00BC5BE2 /* dpfp_threaded */, 008FC0141628BC0300BC5BE2 /* fxload */, 008FC0251628BC6B00BC5BE2 /* listdevs */, + 006AD41B1C8C5A90007F8C6A /* hotplugtest */, 008FC0321628BC9400BC5BE2 /* all */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ + 006AD4181C8C5A90007F8C6A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 006AD4251C8C5AC4007F8C6A /* hotplugtest.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 008FBF2D1628B79300BC5BE2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -558,6 +621,7 @@ 1438D77A17A2ED9F00166101 /* hotplug.c in Sources */, 1438D77D17A2EDCD00166101 /* poll_posix.c in Sources */, 1438D77F17A2F0EA00166101 /* strerror.c in Sources */, + 006AD4241C8C5AAE007F8C6A /* hotplugtest.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -605,6 +669,11 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 006AD4281C8C5BBC007F8C6A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 006AD41B1C8C5A90007F8C6A /* hotplugtest */; + targetProxy = 006AD4271C8C5BBC007F8C6A /* PBXContainerItemProxy */; + }; 008FC0371628BC9A00BC5BE2 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 008FBF301628B79300BC5BE2 /* libusb */; @@ -663,6 +732,20 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ + 006AD4201C8C5A90007F8C6A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 006AD4211C8C5A90007F8C6A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; 008FBF331628B79300BC5BE2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -786,6 +869,14 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 006AD4221C8C5A90007F8C6A /* Build configuration list for PBXNativeTarget "hotplugtest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 006AD4201C8C5A90007F8C6A /* Debug */, + 006AD4211C8C5A90007F8C6A /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; 008FBF2B1628B79300BC5BE2 /* Build configuration list for PBXProject "libusb" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -862,4 +953,3 @@ }; rootObject = 008FBF281628B79300BC5BE2 /* Project object */; } - diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 039b1d16b..c780400e4 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11093 +#define LIBUSB_NANO 11094 From 964cff46ccb929b4b713586215c8d80100c148d2 Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Sun, 6 Mar 2016 13:42:13 +0100 Subject: [PATCH 174/222] examples: fix 3 compiler warnings examples/hotplugtest.c:76:28: warning: implicit conversion loses integer precision: 'long' to 'int' [-Wshorten-64-to-32] vendor_id = (argc > 1) ? strtol (argv[1], NULL, 0) : 0x045a; ~ ^~~~~~~~~~~~~~~~~~~~~~~~~ examples/hotplugtest.c:77:28: warning: implicit conversion loses integer precision: 'long' to 'int' [-Wshorten-64-to-32] product_id = (argc > 2) ? strtol (argv[2], NULL, 0) : 0x5005; ~ ^~~~~~~~~~~~~~~~~~~~~~~~~ examples/hotplugtest.c:78:28: warning: implicit conversion loses integer precision: 'long' to 'int' [-Wshorten-64-to-32] class_id = (argc > 3) ? strtol (argv[3], NULL, 0) : LIBUSB_HOTPLUG_MATCH_ANY; ~ ^~~~~~~~~~~~~~~~~~~~~~~~~ --- examples/hotplugtest.c | 6 +++--- libusb/version_nano.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/hotplugtest.c b/examples/hotplugtest.c index d2c146858..cc873f11b 100644 --- a/examples/hotplugtest.c +++ b/examples/hotplugtest.c @@ -73,9 +73,9 @@ int main(int argc, char *argv[]) int product_id, vendor_id, class_id; int rc; - vendor_id = (argc > 1) ? strtol (argv[1], NULL, 0) : 0x045a; - product_id = (argc > 2) ? strtol (argv[2], NULL, 0) : 0x5005; - class_id = (argc > 3) ? strtol (argv[3], NULL, 0) : LIBUSB_HOTPLUG_MATCH_ANY; + vendor_id = (argc > 1) ? (int)strtol (argv[1], NULL, 0) : 0x045a; + product_id = (argc > 2) ? (int)strtol (argv[2], NULL, 0) : 0x5005; + class_id = (argc > 3) ? (int)strtol (argv[3], NULL, 0) : LIBUSB_HOTPLUG_MATCH_ANY; rc = libusb_init (NULL); if (rc < 0) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index c780400e4..f2124f127 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11094 +#define LIBUSB_NANO 11095 From ce9e72c1386cd5fd4169c320db0240c9231c3bbb Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Sun, 6 Mar 2016 21:37:00 +0100 Subject: [PATCH 175/222] README.md: update AppVeyor badge Signed-off-by: Ludovic Rousseau --- README.md | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3da801285..3fb6061f4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # libusb [![Build Status](https://travis-ci.org/libusb/libusb.svg?branch=master)](https://travis-ci.org/libusb/libusb) -[![Build status](https://ci.appveyor.com/api/projects/status/3qvcj8uceo1bylik?svg=true)](https://ci.appveyor.com/project/LudovicRousseau/libusb) +[![Build status](https://ci.appveyor.com/api/projects/status/h2r5xqfwcpq0jf7o?svg=true)](https://ci.appveyor.com/project/LudovicRousseau/libusb) [![Coverity Scan Build Status](https://scan.coverity.com/projects/2180/badge.svg)](https://scan.coverity.com/projects/libusb-libusb) libusb is a library for USB device access from Linux, Mac OS X, diff --git a/libusb/version_nano.h b/libusb/version_nano.h index f2124f127..2eeb143cc 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11095 +#define LIBUSB_NANO 11096 From 8b42622b077de8ed2a2065ffd68f19b4f8e8c8e9 Mon Sep 17 00:00:00 2001 From: William Skellenger Date: Sun, 3 Jan 2016 21:46:50 -0500 Subject: [PATCH 176/222] android: Fix typo in README Remove the /sdcard copy and not the /system/lib copy Signed-off-by: Ludovic Rousseau --- android/README | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/README b/android/README index 1afecc7d8..29621a59a 100644 --- a/android/README +++ b/android/README @@ -62,7 +62,7 @@ image of a running device: # Install libusb adb push obj/local/armeabi/libusb1.0.so /sdcard/ adb shell su -c "cat > /system/lib/libusb1.0.so < /sdcard/libusb1.0.so" - adb shell rm /system/lib/libusb1.0.so + adb shell rm /sdcard/libusb1.0.so # Install the samples and tests for B in listdevs fxload xusb sam3u_benchmark hotplugtest stress diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 2eeb143cc..73a362081 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11096 +#define LIBUSB_NANO 11098 From ba9eef2f61fb8c4e1615ed074dca94380d6c279b Mon Sep 17 00:00:00 2001 From: William Skellenger Date: Sun, 3 Jan 2016 17:04:54 -0500 Subject: [PATCH 177/222] android: update README Added other $ARCH Signed-off-by: Ludovic Rousseau --- android/README | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/android/README b/android/README index 29621a59a..32024eff0 100644 --- a/android/README +++ b/android/README @@ -24,8 +24,10 @@ The libusb library, examples and tests can then be found in: Where $ARCH is one of: armeabi armeabi-v7a + mips + mips64 x86 - + x86_64 Installing: ----------- From 40fb6ff0a0cb67343b722a6b6227f21142cb18cd Mon Sep 17 00:00:00 2001 From: hacker2490 Date: Thu, 3 Mar 2016 17:01:37 +0530 Subject: [PATCH 178/222] AppVeyor: use a .bat file now - Changes in platform configuration, x86 breaks the build - Solution file does not contain platform for Any CPU,fixing it to Win32 - Added Multiple solutions to appveyor configuration file - Added batch script for VS2010 builds - Added fixes to appveyor.bat file and appveyor.yml - Fixes for Platform and Configuration in appveyor.bat - Fixed windows exit code, Appveyor reports exit on succesful build - Multiple Builds in same platform and configuration,fixed it --- appveyor.yml | 6 +++++- msvc/appveyor.bat | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 msvc/appveyor.bat diff --git a/appveyor.yml b/appveyor.yml index af5d08f92..598db9242 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,6 +5,10 @@ configuration: platform: - x64 - Win32 +build: + project: msvc\libusb_2013.sln + parallel: true + verbosity: detailed environment: matrix: - libusb_2015: msvc\libusb_2015.sln @@ -19,4 +23,4 @@ build_script: msbuild %libusb_2012% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - msbuild %libusb_2010% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" + msvc/appveyor.bat diff --git a/msvc/appveyor.bat b/msvc/appveyor.bat new file mode 100644 index 000000000..779af59d9 --- /dev/null +++ b/msvc/appveyor.bat @@ -0,0 +1,28 @@ +echo on +SetLocal EnableDelayedExpansion + +if [%Configuration%] NEQ [Debug] goto releasex64 +if [%Configuration%] NEQ [Release] goto debugx64 + +:debugx64 +if [%Platform%] NEQ [x64] goto debugWin32 +if [%Configuration%] NEQ [Debug] exit 0 +call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /Debug /x64 +msbuild %libusb_2010% /p:Configuration=Debug,Platform=x64 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" + +:releasex64 +if [%Platform%] NEQ [x64] goto releaseWin32 +if [%Configuration%] NEQ [Release] exit 0 +call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /Release /x64 +msbuild %libusb_2010% /p:Configuration=Release,Platform=x64 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" + +:debugWin32 +if [%Platform%] NEQ [Win32] exit 0 +if [%Configuration%] NEQ [Debug] exit 0 +msbuild %libusb_2010% /p:Configuration=Debug,Platform=Win32 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" + +:releaseWin32 +if [%Platform%] NEQ [Win32] exit 0 +if [%Configuration%] NEQ [Release] exit 0 +msbuild %libusb_2010% /p:Configuration=Release,Platform=Win32 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" + From 98dd33c41ab12db437112b662821e7f133a4eac9 Mon Sep 17 00:00:00 2001 From: Gaurav Date: Fri, 19 Jun 2015 08:53:59 +0530 Subject: [PATCH 179/222] free can handle NULL ptr. free(NULL) is no operation. Contributed by @ya1gaurav. Signed-off-by: Nathan Hjelm --- libusb/descriptor.c | 46 +++++++++++++++++-------------------------- libusb/version_nano.h | 2 +- 2 files changed, 19 insertions(+), 29 deletions(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index ccf7fe426..d784be806 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -94,8 +94,7 @@ int usbi_parse_descriptor(const unsigned char *source, const char *descriptor, static void clear_endpoint(struct libusb_endpoint_descriptor *endpoint) { - if (endpoint->extra) - free((unsigned char *) endpoint->extra); + free(endpoint->extra); } static int parse_endpoint(struct libusb_context *ctx, @@ -193,24 +192,18 @@ static void clear_interface(struct libusb_interface *usb_interface) int i; int j; - if (usb_interface->altsetting) { - for (i = 0; i < usb_interface->num_altsetting; i++) { - struct libusb_interface_descriptor *ifp = - (struct libusb_interface_descriptor *) - usb_interface->altsetting + i; - if (ifp->extra) - free((void *) ifp->extra); - if (ifp->endpoint) { - for (j = 0; j < ifp->bNumEndpoints; j++) - clear_endpoint((struct libusb_endpoint_descriptor *) - ifp->endpoint + j); - free((void *) ifp->endpoint); - } - } - free((void *) usb_interface->altsetting); - usb_interface->altsetting = NULL; + for (i = 0; i < usb_interface->num_altsetting; i++) { + struct libusb_interface_descriptor *ifp = + (struct libusb_interface_descriptor *) + usb_interface->altsetting + i; + free(ifp->extra); + for (j = 0; j < ifp->bNumEndpoints; j++) + clear_endpoint((struct libusb_endpoint_descriptor *) + ifp->endpoint + j); + free(ifp->endpoint); } - + free(usb_interface->altsetting); + usb_interface->altsetting = NULL; } static int parse_interface(libusb_context *ctx, @@ -361,15 +354,12 @@ static int parse_interface(libusb_context *ctx, static void clear_configuration(struct libusb_config_descriptor *config) { - if (config->interface) { - int i; - for (i = 0; i < config->bNumInterfaces; i++) - clear_interface((struct libusb_interface *) - config->interface + i); - free((void *) config->interface); - } - if (config->extra) - free((void *) config->extra); + int i; + for (i = 0; i < config->bNumInterfaces; i++) + clear_interface((struct libusb_interface *) + config->interface + i); + free(config->interface); + free(config->extra); } static int parse_configuration(struct libusb_context *ctx, diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 73a362081..87acb62b7 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11098 +#define LIBUSB_NANO 11099 From e381f33479ed5fa078377c4355fb3fd346c89978 Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Sun, 6 Mar 2016 22:51:46 +0100 Subject: [PATCH 180/222] README.md: update AppVeyor badge (again) Signed-off-by: Ludovic Rousseau --- README.md | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3fb6061f4..21f0239b0 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # libusb [![Build Status](https://travis-ci.org/libusb/libusb.svg?branch=master)](https://travis-ci.org/libusb/libusb) -[![Build status](https://ci.appveyor.com/api/projects/status/h2r5xqfwcpq0jf7o?svg=true)](https://ci.appveyor.com/project/LudovicRousseau/libusb) +[![Build status](https://ci.appveyor.com/api/projects/status/xvrfam94jii4a6lw?svg=true)](https://ci.appveyor.com/project/LudovicRousseau/libusb) [![Coverity Scan Build Status](https://scan.coverity.com/projects/2180/badge.svg)](https://scan.coverity.com/projects/libusb-libusb) libusb is a library for USB device access from Linux, Mac OS X, diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 87acb62b7..21ad37571 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11099 +#define LIBUSB_NANO 11101 From dc7760a99f46dc8965aa2b01e34ba9a7019f7837 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Sun, 6 Mar 2016 15:00:31 -0700 Subject: [PATCH 181/222] core: revert some of prior patch Signed-off-by: Nathan Hjelm --- libusb/descriptor.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index d784be806..14657d19b 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -94,7 +94,7 @@ int usbi_parse_descriptor(const unsigned char *source, const char *descriptor, static void clear_endpoint(struct libusb_endpoint_descriptor *endpoint) { - free(endpoint->extra); + free((void *) endpoint->extra); } static int parse_endpoint(struct libusb_context *ctx, @@ -192,17 +192,19 @@ static void clear_interface(struct libusb_interface *usb_interface) int i; int j; - for (i = 0; i < usb_interface->num_altsetting; i++) { - struct libusb_interface_descriptor *ifp = - (struct libusb_interface_descriptor *) - usb_interface->altsetting + i; - free(ifp->extra); - for (j = 0; j < ifp->bNumEndpoints; j++) - clear_endpoint((struct libusb_endpoint_descriptor *) - ifp->endpoint + j); - free(ifp->endpoint); + if (usb_interface->altsetting) { + for (i = 0; i < usb_interface->num_altsetting; i++) { + struct libusb_interface_descriptor *ifp = + (struct libusb_interface_descriptor *) + usb_interface->altsetting + i; + free((void *) ifp->extra); + for (j = 0; j < ifp->bNumEndpoints; j++) + clear_endpoint((struct libusb_endpoint_descriptor *) + ifp->endpoint + j); + free((void *) ifp->endpoint); + } } - free(usb_interface->altsetting); + free((void *) usb_interface->altsetting); usb_interface->altsetting = NULL; } @@ -355,11 +357,13 @@ static int parse_interface(libusb_context *ctx, static void clear_configuration(struct libusb_config_descriptor *config) { int i; - for (i = 0; i < config->bNumInterfaces; i++) - clear_interface((struct libusb_interface *) - config->interface + i); - free(config->interface); - free(config->extra); + if (config->interface) { + for (i = 0; i < config->bNumInterfaces; i++) + clear_interface((struct libusb_interface *) + config->interface + i); + } + free((void *) config->interface); + free((void *) config->extra); } static int parse_configuration(struct libusb_context *ctx, From 0dcc646bb536c293f6e53c802d85c6bdd416867a Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Sun, 6 Mar 2016 15:04:02 -0700 Subject: [PATCH 182/222] core: re-add one more conditional Signed-off-by: Nathan Hjelm --- libusb/descriptor.c | 8 +++++--- libusb/version_nano.h | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 14657d19b..4c9435fff 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -198,9 +198,11 @@ static void clear_interface(struct libusb_interface *usb_interface) (struct libusb_interface_descriptor *) usb_interface->altsetting + i; free((void *) ifp->extra); - for (j = 0; j < ifp->bNumEndpoints; j++) - clear_endpoint((struct libusb_endpoint_descriptor *) - ifp->endpoint + j); + if (ifp->endpoint) { + for (j = 0; j < ifp->bNumEndpoints; j++) + clear_endpoint((struct libusb_endpoint_descriptor *) + ifp->endpoint + j); + } free((void *) ifp->endpoint); } } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 21ad37571..cb99241e4 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11101 +#define LIBUSB_NANO 11102 From 2040ab109c8470fa5bcaf094fdf8f0488e6cc8f5 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Thu, 10 Mar 2016 12:57:50 -0700 Subject: [PATCH 183/222] configure: bump autoconf version and remove obsolete AM_MAINTAINER_MODE This commit bumps the minimum autoconf version to 2.69. This only affects maintainers and will ensure libusb tarballs have up-to-date configure scripts. At the same time we are removing the AM_MAINTAINER_MODE macro as even its creator recommends against using it. Closes #122 Signed-off-by: Nathan Hjelm --- .travis.yml | 2 ++ configure.ac | 3 +-- libusb/version_nano.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 585cd6f56..d4469b88b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,6 @@ +# Require trusty for now as it has a more recent version of autoconf sudo: required +dist: trusty language: c compiler: diff --git a/configure.ac b/configure.ac index 9f3e639d6..77efdec8a 100644 --- a/configure.ac +++ b/configure.ac @@ -27,14 +27,13 @@ lt_age="1" LTLDFLAGS="-version-info ${lt_current}:${lt_revision}:${lt_age}" AM_INIT_AUTOMAKE -AM_MAINTAINER_MODE AC_CONFIG_SRCDIR([libusb/core.c]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([config.h]) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) -AC_PREREQ([2.50]) +AC_PREREQ([2.69]) AC_PROG_CC AC_PROG_CXX LT_INIT diff --git a/libusb/version_nano.h b/libusb/version_nano.h index cb99241e4..86202f81d 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11102 +#define LIBUSB_NANO 11105 From da27298d21abeaccde12758b8c2b22409ab92eb6 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Sat, 12 Mar 2016 07:29:55 -0700 Subject: [PATCH 184/222] autogen: remove --enable-maintainer-mode Signed-off-by: Nathan Hjelm --- autogen.sh | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/autogen.sh b/autogen.sh index ab87fb311..24f39ee69 100755 --- a/autogen.sh +++ b/autogen.sh @@ -4,5 +4,5 @@ set -e ./bootstrap.sh if test -z "$NOCONFIGURE"; then - exec ./configure --enable-maintainer-mode --enable-examples-build --enable-tests-build "$@" + exec ./configure --enable-examples-build --enable-tests-build "$@" fi diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 86202f81d..0ae95c43d 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11105 +#define LIBUSB_NANO 11104 From 4cfd001b823469c66cddfb53bc11fd8aaf4d09c2 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Sat, 12 Mar 2016 07:31:45 -0700 Subject: [PATCH 185/222] fix nano version Signed-off-by: Nathan Hjelm --- libusb/version_nano.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 0ae95c43d..790d1e496 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11104 +#define LIBUSB_NANO 11106 From a42b524731557e3204c31247f0a7be671057d9ef Mon Sep 17 00:00:00 2001 From: hacker2490 Date: Thu, 3 Mar 2016 17:01:37 +0530 Subject: [PATCH 186/222] AppVeyor: add cygwin and minGW support - Changes in platform configuration, x86 breaks the build - Solution file does not contain platform for Any CPU, fixing it to Win32 - Added Multiple solutions to appveyor configuration file - Added batch script for VS2010 builds - Added fixes to appveyor.bat file and appveyor.yml - Fixes for Platform and Configuration in appveyor.bat - Fixed windows exit code, Appveyor reports exit on succesful build - Multiple Builds in same platform and configuration, fixed it - Added appveyor configuration to compile using MinGW 32-bit and 64-bits - Minor Fixes for batch file and Added cygwin build script Signed-off-by: Ludovic Rousseau --- appveyor.yml | 15 +++++++++++++++ appveyor_cygwin.bat | 14 ++++++++++++++ appveyor_minGW.bat | 24 ++++++++++++++++++++++++ libusb/version_nano.h | 2 +- 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 appveyor_cygwin.bat create mode 100644 appveyor_minGW.bat diff --git a/appveyor.yml b/appveyor.yml index 598db9242..0e6113e0b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,6 +15,17 @@ environment: libusb_2013: msvc\libusb_2013.sln libusb_2012: msvc\libusb_2012.sln libusb_2010: msvc\libusb_2010.sln +install: + +- cmd: >- + rem Copying libusb to cygwin home directory + + xcopy /S C:\projects\libusb C:\cygwin\home\appveyor\ + + rem Copying libusb to MinGW home directory + + xcopy /S C:\projects\libusb C:\msys64\home\appveyor\ + build_script: - cmd: >- msbuild %libusb_2015% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" @@ -24,3 +35,7 @@ build_script: msbuild %libusb_2012% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" msvc/appveyor.bat + + appveyor_minGW.bat + + appveyor_cygwin.bat diff --git a/appveyor_cygwin.bat b/appveyor_cygwin.bat new file mode 100644 index 000000000..5e30794a6 --- /dev/null +++ b/appveyor_cygwin.bat @@ -0,0 +1,14 @@ +echo on +SetLocal EnableDelayedExpansion + +if [%Configuration%] NEQ [Debug] goto releaseWin32 + +:releaseWin32 +if [%Platform%] NEQ [Win32] exit 0 +if [%Configuration%] NEQ [Release] exit 0 +C:\cygwin\bin\bash -e -l -c "mkdir build-Win32-cygwin" +C:\cygwin\bin\bash -e -l -c ./autogen.sh +C:\cygwin\bin\bash -e -l -c "cd build-Win32-cygwin" +C:\cygwin\bin\bash -e -l -c "build-Win32-cygwin/../configure" +C:\cygwin\bin\bash -e -l -c "make -j4" +C:\cygwin\bin\bash -e -l -c "make install" \ No newline at end of file diff --git a/appveyor_minGW.bat b/appveyor_minGW.bat new file mode 100644 index 000000000..70aa30d34 --- /dev/null +++ b/appveyor_minGW.bat @@ -0,0 +1,24 @@ +echo on +SetLocal EnableDelayedExpansion + +if [%Configuration%] NEQ [Debug] goto releasex64 + +:releasex64 +if [%Platform%] NEQ [x64] goto releaseWin32 +if [%Configuration%] NEQ [Release] exit 0 +C:\msys64\usr\bin\bash -e -l -c "mkdir build-x64" +C:\msys64\usr\bin\bash -e -l -c ./autogen.sh +C:\msys64\usr\bin\bash -e -l -c "cd build-x64" +C:\msys64\usr\bin\bash -e -l -c "build-x64/../configure --prefix=/mingw64 --build=--build= --host=x86_64-w64-mingw32" +C:\msys64\usr\bin\bash -e -l -c "make -j4" +C:\msys64\usr\bin\bash -e -l -c "make install" + +:releaseWin32 +if [%Platform%] NEQ [Win32] exit 0 +if [%Configuration%] NEQ [Release] exit 0 +C:\msys64\usr\bin\bash -e -l -c "mkdir build-Win32" +C:\msys64\usr\bin\bash -e -l -c ./autogen.sh +C:\msys64\usr\bin\bash -e -l -c "cd build-Win32" +C:\msys64\usr\bin\bash -e -l -c "build-Win32/../configure --prefix=/mingw32 --build=i686-w64-mingw32 --host=i686-w64-mingw32" +C:\msys64\usr\bin\bash -e -l -c "make -j4" +C:\msys64\usr\bin\bash -e -l -c "make install" \ No newline at end of file diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 790d1e496..795d2bc7a 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11106 +#define LIBUSB_NANO 11108 From 578942b5a90cd36b47b11e0992c2e92a05b70d91 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Sun, 20 Mar 2016 09:48:06 -0600 Subject: [PATCH 187/222] AUTHORS: update my copyright Signed-off-by: Nathan Hjelm --- AUTHORS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index b7d7ac9b4..70d407bd1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,7 +1,7 @@ Copyright © 2001 Johannes Erdfelt Copyright © 2007-2009 Daniel Drake Copyright © 2010-2012 Peter Stuge -Copyright © 2008-2013 Nathan Hjelm +Copyright © 2008-2016 Nathan Hjelm Copyright © 2009-2013 Pete Batard Copyright © 2009-2013 Ludovic Rousseau Copyright © 2010-2012 Michael Plante From 6ec266c9ad99b33f5ef0c13fcdd0b292dfc10866 Mon Sep 17 00:00:00 2001 From: Dom Postorivo Date: Fri, 20 May 2016 04:08:45 +0100 Subject: [PATCH 188/222] Fixed merge issues --- .gitignore | 3 +++ libusb/core.c | 8 ++++---- libusb/io.c | 2 +- libusb/libusbi.h | 3 ++- libusb/os/linux_usbfs.c | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 9b29dceee..6cc97d790 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,6 @@ Release *~ *.orig .dirstamp +*.swn +*.swm +*.swo diff --git a/libusb/core.c b/libusb/core.c index 3b52dc570..c57ab4137 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1292,7 +1292,7 @@ int API_EXPORTED libusb_open2(libusb_device *dev, libusb_device_handle **handle, if (!_handle) return LIBUSB_ERROR_NO_MEM; - r = usbi_mutex_init(&_handle->lock, NULL); + r = usbi_mutex_init(&_handle->lock); if (r) { free(_handle); return LIBUSB_ERROR_OTHER; @@ -2083,9 +2083,9 @@ int API_EXPORTED libusb_init2(libusb_context **context, const char * uspfs_path_ usbi_dbg("libusb v%d.%d.%d.%d", libusb_version_internal.major, libusb_version_internal.minor, libusb_version_internal.micro, libusb_version_internal.nano); - usbi_mutex_init(&ctx->usb_devs_lock, NULL); - usbi_mutex_init(&ctx->open_devs_lock, NULL); - usbi_mutex_init(&ctx->hotplug_cbs_lock, NULL); + usbi_mutex_init(&ctx->usb_devs_lock); + usbi_mutex_init(&ctx->open_devs_lock); + usbi_mutex_init(&ctx->hotplug_cbs_lock); list_init(&ctx->usb_devs); list_init(&ctx->open_devs); list_init(&ctx->hotplug_cbs); diff --git a/libusb/io.c b/libusb/io.c index 4d03b8b77..a8e07ecc0 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -2619,7 +2619,7 @@ void API_EXPORTED libusb_set_pollfd_notifiers(libusb_context *ctx, * Interrupt the iteration of the event handling thread, so that it picks * up the fd change. Callers of this function must hold the event_data_lock. */ -static void usbi_fd_notification(struct libusb_context *ctx) +void usbi_fd_notification(struct libusb_context *ctx) { int pending_events; diff --git a/libusb/libusbi.h b/libusb/libusbi.h index 3054896ef..ce016da33 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -65,6 +65,7 @@ extern "C" { /* Backend specific capabilities */ #define USBI_CAP_HAS_HID_ACCESS 0x00010000 #define USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER 0x00020000 +#define USBI_CAP_HAS_POLLABLE_DEVICE_FD 0x00020000 /* Maximum number of bytes in a log line */ #define USBI_MAX_LOG_LEN 1024 @@ -560,7 +561,7 @@ struct usbi_pollfd { int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events); void usbi_remove_pollfd(struct libusb_context *ctx, int fd); - +void usbi_fd_notification(struct libusb_context *ctx); /* device discovery */ /* we traverse usbfs without knowing how many devices we are going to find. diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 33722f672..464efc47e 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -1405,7 +1405,7 @@ static int op_open2(struct libusb_device_handle *handle, int fd) if (handle->dev->attached) { usbi_dbg("open failed with no device, but device still attached"); linux_device_disconnected(handle->dev->bus_number, - handle->dev->device_address, NULL); + handle->dev->device_address); } usbi_mutex_static_unlock(&linux_hotplug_lock); } From 0b947e5f9b2dfffa4def7007f4fb5b23fe2eb05f Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Sun, 29 May 2016 17:35:09 -0700 Subject: [PATCH 189/222] Windows: Fix false assertion failure message during enumeration Commit 1d54ee1b6687c532eca75925f56eb12e2a34ce42 addressed a device reference leak but introduced a false warning message that occurs for devices detected in early enumeration passes (e.g. hubs). The assertion is meant to warn of a mismatch between parent devices but fails to account for the fact that some devices that are allocated early do not have a parent device assigned until the later enumeration passes. Signed-off-by: Chris Dickens --- libusb/os/windows_winusb.c | 19 +++++++++++-------- libusb/os/windows_winusb.h | 4 +++- libusb/version_nano.h | 2 +- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 9fe29566a..082e8469c 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -1514,16 +1514,20 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered if (dev == NULL) LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - windows_device_priv_init(dev); + priv = windows_device_priv_init(dev); } else { usbi_dbg("found existing device for session [%lX] (%u.%u)", session_id, dev->bus_number, dev->device_address); - if (_device_priv(dev)->parent_dev != parent_dev) { - usbi_err(ctx,"program assertion failed - existing device should share parent"); - } else { - // We hold a reference to parent_dev instance, but this device already - // has a parent_dev reference (only one per child) - libusb_unref_device(parent_dev); + + priv = _device_priv(dev); + if (priv->parent_dev != NULL) { + if (priv->parent_dev != parent_dev) { + usbi_err(ctx, "program assertion failed - existing device should share parent"); + } else { + // We hold a reference to parent_dev instance, but this device already + // has a parent_dev reference (only one per child) + libusb_unref_device(parent_dev); + } } } @@ -1537,7 +1541,6 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered LOOP_BREAK(LIBUSB_ERROR_NO_MEM); } } - priv = _device_priv(dev); } // Setup device diff --git a/libusb/os/windows_winusb.h b/libusb/os/windows_winusb.h index 303f4a6fa..49c1df557 100644 --- a/libusb/os/windows_winusb.h +++ b/libusb/os/windows_winusb.h @@ -224,7 +224,7 @@ static inline struct windows_device_priv *_device_priv(struct libusb_device *dev return (struct windows_device_priv *)dev->os_priv; } -static inline void windows_device_priv_init(struct libusb_device *dev) +static inline struct windows_device_priv *windows_device_priv_init(struct libusb_device *dev) { struct windows_device_priv *p = _device_priv(dev); int i; @@ -247,6 +247,8 @@ static inline void windows_device_priv_init(struct libusb_device *dev) p->usb_interface[i].endpoint = NULL; p->usb_interface[i].restricted_functionality = false; } + + return p; } static inline void windows_device_priv_release(struct libusb_device *dev) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 795d2bc7a..b92475f51 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11108 +#define LIBUSB_NANO 11109 From a283c3b5a3dce8f6f33331b9aa1d95d41c8f241c Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sat, 20 Feb 2016 12:26:12 +0100 Subject: [PATCH 190/222] Add support for persistent device memory. Add a function to allocate memory belonging to a specific device, so that the operating system can DMA straight into it for zerocopy, and also avoid some clearing. Also, this allows up-front memory allocation in the kernel at program startup; memory allocation is otherwise done per-transfer, which can fail in a system where memory has become fragmented over time). This mirrors new functionality going into Linux' USB stack (recently reviewed and acked upstream); only Linux is supported as a backend currently. [Chris Dickens] Modified to fix doxygen documentation, correct parameter naming, reposition function declarations, and address a missing request during the patch review process. Signed-off-by: Chris Dickens --- .amend | 0 libusb/core.c | 56 +++++++++++++++++++++++++++++++++++++++++ libusb/libusb-1.0.def | 4 +++ libusb/libusb.h | 10 +++++++- libusb/libusbi.h | 10 ++++++++ libusb/os/linux_usbfs.c | 30 ++++++++++++++++++++++ libusb/version_nano.h | 2 +- 7 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 .amend diff --git a/.amend b/.amend new file mode 100644 index 000000000..e69de29bb diff --git a/libusb/core.c b/libusb/core.c index 5317d2637..d57edad5c 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -357,6 +357,8 @@ if (cfg != desired) * - libusb_control_transfer_get_setup() * - libusb_cpu_to_le16() * - libusb_detach_kernel_driver() + * - libusb_dev_mem_alloc() + * - libusb_dev_mem_free() * - libusb_error_name() * - libusb_event_handler_active() * - libusb_event_handling_ok() @@ -1812,6 +1814,60 @@ int API_EXPORTED libusb_free_streams(libusb_device_handle *dev_handle, return LIBUSB_ERROR_NOT_SUPPORTED; } +/** \ingroup libusb_asyncio + * Attempts to allocate a block of persistent DMA memory suitable for transfers + * against the given device. If successful, will return a block of memory + * that is suitable for use as "buffer" in \ref libusb_transfer against this + * device. Using this memory instead of regular memory means that the host + * controller can use DMA directly into the buffer to increase performance, and + * also that transfers can no longer fail due to kernel memory fragmentation. + * + * Note that this means you should not modify this memory (or even data on + * the same cache lines) when a transfer is in progress, although it is legal + * to have several transfers going on within the same memory block. + * + * Will return NULL on failure. Many systems do not support such zerocopy + * and will always return NULL. Memory allocated with this function must be + * freed with \ref libusb_dev_mem_free. Specifically, this means that the + * flag \ref LIBUSB_TRANSFER_FREE_BUFFER cannot be used to free memory allocated + * with this function. + * + * Since version 1.0.21, \ref LIBUSB_API_VERSION >= 0x01000105 + * + * \param dev_handle a device handle + * \param length size of desired data buffer + * \returns a pointer to the newly allocated memory, or NULL on failure + */ +DEFAULT_VISIBILITY +unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handle, + size_t length) +{ + if (!dev_handle->dev->attached) + return NULL; + + if (usbi_backend->dev_mem_alloc) + return usbi_backend->dev_mem_alloc(dev_handle, length); + else + return NULL; +} + +/** \ingroup libusb_asyncio + * Free device memory allocated with libusb_dev_mem_alloc(). + * + * \param dev_handle a device handle + * \param buffer pointer to the previously allocated memory + * \param length size of previously allocated memory + * \returns LIBUSB_SUCCESS, or a LIBUSB_ERROR code on failure + */ +int API_EXPORTED libusb_dev_mem_free(libusb_device_handle *dev_handle, + unsigned char *buffer, size_t length) +{ + if (usbi_backend->dev_mem_free) + return usbi_backend->dev_mem_free(dev_handle, buffer, length); + else + return LIBUSB_ERROR_NOT_SUPPORTED; +} + /** \ingroup libusb_dev * Determine if a kernel driver is active on an interface. If a kernel driver * is active, you cannot claim the interface, and libusb will be unable to diff --git a/libusb/libusb-1.0.def b/libusb/libusb-1.0.def index 7b14e0fca..2443d9bef 100644 --- a/libusb/libusb-1.0.def +++ b/libusb/libusb-1.0.def @@ -20,6 +20,10 @@ EXPORTS libusb_control_transfer@32 = libusb_control_transfer libusb_detach_kernel_driver libusb_detach_kernel_driver@8 = libusb_detach_kernel_driver + libusb_dev_mem_alloc + libusb_dev_mem_alloc@8 = libusb_dev_mem_alloc + libusb_dev_mem_free + libusb_dev_mem_free@12 = libusb_dev_mem_free libusb_error_name libusb_error_name@4 = libusb_error_name libusb_event_handler_active diff --git a/libusb/libusb.h b/libusb/libusb.h index 5b0d522be..f73e31cc2 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -1137,7 +1137,10 @@ enum libusb_transfer_flags { /** Report short frames as errors */ LIBUSB_TRANSFER_SHORT_NOT_OK = 1<<0, - /** Automatically free() transfer buffer during libusb_free_transfer() */ + /** Automatically free() transfer buffer during libusb_free_transfer(). + * Note that buffers allocated with libusb_dev_mem_alloc() should not + * be attempted freed in this way, since free() is not an appropriate + * way to release such memory. */ LIBUSB_TRANSFER_FREE_BUFFER = 1<<1, /** Automatically call libusb_free_transfer() after callback returns. @@ -1392,6 +1395,11 @@ int LIBUSB_CALL libusb_alloc_streams(libusb_device_handle *dev_handle, int LIBUSB_CALL libusb_free_streams(libusb_device_handle *dev_handle, unsigned char *endpoints, int num_endpoints); +unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handle, + size_t length); +int LIBUSB_CALL libusb_dev_mem_free(libusb_device_handle *dev_handle, + unsigned char *buffer, size_t length); + int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle *dev_handle, int interface_number); int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle *dev_handle, diff --git a/libusb/libusbi.h b/libusb/libusbi.h index 75a5a8138..b5530d610 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -933,6 +933,16 @@ struct usbi_os_backend { int (*free_streams)(struct libusb_device_handle *dev_handle, unsigned char *endpoints, int num_endpoints); + /* Allocate persistent DMA memory for the given device, suitable for + * zerocopy. May return NULL on failure. Optional to implement. + */ + unsigned char *(*dev_mem_alloc)(struct libusb_device_handle *handle, + size_t len); + + /* Free memory allocated by dev_mem_alloc. */ + int (*dev_mem_free)(struct libusb_device_handle *handle, + unsigned char *buffer, size_t len); + /* Determine if a kernel driver is active on an interface. Optional. * * The presence of a kernel driver on an interface indicates that any diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index d154aa9a3..0689894d5 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -1557,6 +1558,32 @@ static int op_free_streams(struct libusb_device_handle *handle, endpoints, num_endpoints); } +static unsigned char *op_dev_mem_alloc(struct libusb_device_handle *handle, + size_t len) +{ + struct linux_device_handle_priv *hpriv = _device_handle_priv(handle); + unsigned char *buffer = (unsigned char *)mmap(NULL, len, + PROT_READ | PROT_WRITE, MAP_SHARED, hpriv->fd, 0); + if (buffer == MAP_FAILED) { + usbi_err(HANDLE_CTX(handle), "alloc dev mem failed errno %d", + errno); + return NULL; + } + return buffer; +} + +static int op_dev_mem_free(struct libusb_device_handle *handle, + unsigned char *buffer, size_t len) +{ + if (munmap(buffer, len) != 0) { + usbi_err(HANDLE_CTX(handle), "free dev mem failed errno %d", + errno); + return LIBUSB_ERROR_OTHER; + } else { + return LIBUSB_SUCCESS; + } +} + static int op_kernel_driver_active(struct libusb_device_handle *handle, int interface) { @@ -2678,6 +2705,9 @@ const struct usbi_os_backend linux_usbfs_backend = { .alloc_streams = op_alloc_streams, .free_streams = op_free_streams, + .dev_mem_alloc = op_dev_mem_alloc, + .dev_mem_free = op_dev_mem_free, + .kernel_driver_active = op_kernel_driver_active, .detach_kernel_driver = op_detach_kernel_driver, .attach_kernel_driver = op_attach_kernel_driver, diff --git a/libusb/version_nano.h b/libusb/version_nano.h index b92475f51..5921d744b 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11109 +#define LIBUSB_NANO 11110 From c5c4c7cba78d878703857e6dc7ad1f1eb82dba83 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Sun, 29 May 2016 19:19:51 -0700 Subject: [PATCH 191/222] Misc: Add .amend to .gitignore Signed-off-by: Chris Dickens --- .amend | 0 .gitignore | 1 + libusb/version_nano.h | 2 +- 3 files changed, 2 insertions(+), 1 deletion(-) delete mode 100644 .amend diff --git a/.amend b/.amend deleted file mode 100644 index e69de29bb..000000000 diff --git a/.gitignore b/.gitignore index b04936fdb..81bcb81f4 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,4 @@ Release *~ *.orig .dirstamp +.amend diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 5921d744b..0e5bb8f01 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11110 +#define LIBUSB_NANO 11111 From ad6f23480ecfbe10a34a78afde58fdac32d3e457 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Sun, 29 May 2016 19:51:48 -0700 Subject: [PATCH 192/222] Misc: Fix usbi_os_backend structure initialization Backends not using named initializers were broken by the recent addition of commit a283c3b5a3dce8f6f33331b9aa1d95d41c8f241c. Signed-off-by: Chris Dickens --- libusb/os/haiku_usb_raw.cpp | 3 +++ libusb/os/netbsd_usb.c | 3 +++ libusb/os/openbsd_usb.c | 3 +++ libusb/os/wince_usb.c | 3 +++ libusb/os/windows_usbdk.c | 3 +++ libusb/os/windows_winusb.c | 3 +++ libusb/version_nano.h | 2 +- 7 files changed, 19 insertions(+), 1 deletion(-) diff --git a/libusb/os/haiku_usb_raw.cpp b/libusb/os/haiku_usb_raw.cpp index 0f1f7ce9e..77adbd1e6 100644 --- a/libusb/os/haiku_usb_raw.cpp +++ b/libusb/os/haiku_usb_raw.cpp @@ -222,6 +222,9 @@ const struct usbi_os_backend haiku_usb_raw_backend = { /*.alloc_streams =*/ NULL, /*.free_streams =*/ NULL, + /*.dev_mem_alloc =*/ NULL, + /*.dev_mem_free =*/ NULL, + /*.kernel_driver_active =*/ NULL, /*.detach_kernel_driver =*/ NULL, /*.attach_kernel_driver =*/ NULL, diff --git a/libusb/os/netbsd_usb.c b/libusb/os/netbsd_usb.c index f3b274e35..ad1ede73e 100644 --- a/libusb/os/netbsd_usb.c +++ b/libusb/os/netbsd_usb.c @@ -114,6 +114,9 @@ const struct usbi_os_backend netbsd_backend = { NULL, /* alloc_streams */ NULL, /* free_streams */ + NULL, /* dev_mem_alloc() */ + NULL, /* dev_mem_free() */ + NULL, /* kernel_driver_active() */ NULL, /* detach_kernel_driver() */ NULL, /* attach_kernel_driver() */ diff --git a/libusb/os/openbsd_usb.c b/libusb/os/openbsd_usb.c index cee60dbce..c66025711 100644 --- a/libusb/os/openbsd_usb.c +++ b/libusb/os/openbsd_usb.c @@ -117,6 +117,9 @@ const struct usbi_os_backend openbsd_backend = { NULL, /* alloc_streams */ NULL, /* free_streams */ + NULL, /* dev_mem_alloc() */ + NULL, /* dev_mem_free() */ + NULL, /* kernel_driver_active() */ NULL, /* detach_kernel_driver() */ NULL, /* attach_kernel_driver() */ diff --git a/libusb/os/wince_usb.c b/libusb/os/wince_usb.c index fc95e9c7d..85c584be7 100644 --- a/libusb/os/wince_usb.c +++ b/libusb/os/wince_usb.c @@ -881,6 +881,9 @@ const struct usbi_os_backend wince_backend = { NULL, /* alloc_streams */ NULL, /* free_streams */ + NULL, /* dev_mem_alloc() */ + NULL, /* dev_mem_free() */ + wince_kernel_driver_active, wince_detach_kernel_driver, wince_attach_kernel_driver, diff --git a/libusb/os/windows_usbdk.c b/libusb/os/windows_usbdk.c index da12edaa7..7cc579387 100644 --- a/libusb/os/windows_usbdk.c +++ b/libusb/os/windows_usbdk.c @@ -877,6 +877,9 @@ const struct usbi_os_backend usbdk_backend = { NULL, NULL, + NULL, // dev_mem_alloc() + NULL, // dev_mem_free() + usbdk_kernel_driver_active, usbdk_detach_kernel_driver, usbdk_attach_kernel_driver, diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 082e8469c..80e36fb8f 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -2067,6 +2067,9 @@ const struct usbi_os_backend windows_backend = { NULL, /* alloc_streams */ NULL, /* free_streams */ + NULL, /* dev_mem_alloc */ + NULL, /* dev_mem_free */ + windows_kernel_driver_active, windows_detach_kernel_driver, windows_attach_kernel_driver, diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 0e5bb8f01..17cd90cd9 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11111 +#define LIBUSB_NANO 11112 From adb6e39b68699b5d849836f9aaff7640b0f16173 Mon Sep 17 00:00:00 2001 From: FTDI Dev Date: Wed, 2 Mar 2016 16:29:27 +0000 Subject: [PATCH 193/222] Clean failure in discovered_devs_append. Closes #161 Signed-off-by: Chris Dickens --- libusb/core.c | 40 ++++++++++++++++++++++++---------------- libusb/version_nano.h | 2 +- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index d57edad5c..54c10103f 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -627,6 +627,16 @@ static struct discovered_devs *discovered_devs_alloc(void) return ret; } +static void discovered_devs_free(struct discovered_devs *discdevs) +{ + size_t i; + + for (i = 0; i < discdevs->len; i++) + libusb_unref_device(discdevs->devices[i]); + + free(discdevs); +} + /* append a device to the discovered devices collection. may realloc itself, * returning new discdevs. returns NULL on realloc failure. */ struct discovered_devs *discovered_devs_append( @@ -634,6 +644,7 @@ struct discovered_devs *discovered_devs_append( { size_t len = discdevs->len; size_t capacity; + struct discovered_devs *new_discdevs; /* if there is space, just append the device */ if (len < discdevs->capacity) { @@ -645,25 +656,21 @@ struct discovered_devs *discovered_devs_append( /* exceeded capacity, need to grow */ usbi_dbg("need to increase capacity"); capacity = discdevs->capacity + DISCOVERED_DEVICES_SIZE_STEP; - discdevs = usbi_reallocf(discdevs, + /* can't use usbi_reallocf here because in failure cases it would + * free the existing discdevs without unreferencing its devices. */ + new_discdevs = realloc(discdevs, sizeof(*discdevs) + (sizeof(void *) * capacity)); - if (discdevs) { - discdevs->capacity = capacity; - discdevs->devices[len] = libusb_ref_device(dev); - discdevs->len++; + if (!new_discdevs) { + discovered_devs_free(discdevs); + return NULL; } - return discdevs; -} - -static void discovered_devs_free(struct discovered_devs *discdevs) -{ - size_t i; - - for (i = 0; i < discdevs->len; i++) - libusb_unref_device(discdevs->devices[i]); + discdevs = new_discdevs; + discdevs->capacity = capacity; + discdevs->devices[len] = libusb_ref_device(dev); + discdevs->len++; - free(discdevs); + return discdevs; } /* Allocate a new device with a specific session ID. The returned device has @@ -854,7 +861,8 @@ ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx, *list = ret; out: - discovered_devs_free(discdevs); + if (discdevs) + discovered_devs_free(discdevs); return len; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 17cd90cd9..9e02ae02c 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11112 +#define LIBUSB_NANO 11113 From 247c719cb8842a46662e8d62eb31cacc134aee51 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Sun, 29 May 2016 19:44:29 -0700 Subject: [PATCH 194/222] Windows: Clean up referenced devices when memory allocation fails Similar to commit adb6e39b68699b5d849836f9aaff7640b0f16173, drop the use of usbi_reallocf() as the memory would be freed, thereby leaking device references. Signed-off-by: Chris Dickens --- libusb/os/windows_winusb.c | 16 ++++++++-------- libusb/version_nano.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 80e36fb8f..50d403414 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -1305,7 +1305,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered GUID *if_guid; LONG s; // Keep a list of newly allocated devs to unref - libusb_device **unref_list; + libusb_device **unref_list, **new_unref_list; unsigned int unref_size = 64; unsigned int unref_cur = 0; @@ -1535,10 +1535,12 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered unref_list[unref_cur++] = dev; if (unref_cur >= unref_size) { unref_size += 64; - unref_list = usbi_reallocf(unref_list, unref_size * sizeof(libusb_device *)); - if (unref_list == NULL) { + new_unref_list = usbi_reallocf(unref_list, unref_size * sizeof(libusb_device *)); + if (new_unref_list == NULL) { usbi_err(ctx, "could not realloc list for unref - aborting."); LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + } else { + unref_list = new_unref_list; } } } @@ -1640,11 +1642,9 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered safe_free(guid[pass]); // Unref newly allocated devs - if (unref_list != NULL) { - for (i = 0; i < unref_cur; i++) - safe_unref_device(unref_list[i]); - free(unref_list); - } + for (i = 0; i < unref_cur; i++) + safe_unref_device(unref_list[i]); + free(unref_list); return r; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 9e02ae02c..9e268cdbe 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11113 +#define LIBUSB_NANO 11114 From 648fb8691f8b9701d7406bc339ce64b57545934b Mon Sep 17 00:00:00 2001 From: Jeffrey Nichols Date: Mon, 21 Mar 2016 13:53:11 -0400 Subject: [PATCH 195/222] Add support for Intel Alpine Ridge USB 3.1 Controller on Windows 7. Closes #176 Signed-off-by: Chris Dickens --- libusb/os/windows_winusb.c | 5 +++-- libusb/version_nano.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 50d403414..81cceefd9 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -1277,7 +1277,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered { struct discovered_devs *discdevs; HDEVINFO dev_info = { 0 }; - const char *usb_class[] = {"USB", "NUSB3", "IUSB3"}; + const char *usb_class[] = {"USB", "NUSB3", "IUSB3", "IARUSB3"}; SP_DEVINFO_DATA dev_info_data = { 0 }; SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL; GUID hid_guid; @@ -1370,6 +1370,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered // Workaround for a Nec/Renesas USB 3.0 driver bug where root hubs are // being listed under the "NUSB3" PnP Symbolic Name rather than "USB". // The Intel USB 3.0 driver behaves similar, but uses "IUSB3" + // The Intel Alpine Ridge USB 3.1 driver uses "IARUSB3" for (; class_index < ARRAYSIZE(usb_class); class_index++) { if (get_devinfo_data(ctx, &dev_info, &dev_info_data, usb_class[class_index], i)) break; @@ -2182,7 +2183,7 @@ static int common_configure_endpoints(int sub_api, struct libusb_device_handle * } // These names must be uppercase -static const char *hub_driver_names[] = {"USBHUB", "USBHUB3", "USB3HUB", "NUSB3HUB", "RUSB3HUB", "FLXHCIH", "TIHUB3", "ETRONHUB3", "VIAHUB3", "ASMTHUB3", "IUSB3HUB", "VUSB3HUB", "AMDHUB30", "VHHUB"}; +static const char *hub_driver_names[] = {"USBHUB", "USBHUB3", "USB3HUB", "NUSB3HUB", "RUSB3HUB", "FLXHCIH", "TIHUB3", "ETRONHUB3", "VIAHUB3", "ASMTHUB3", "IUSB3HUB", "VUSB3HUB", "AMDHUB30", "VHHUB", "AUSB3HUB"}; static const char *composite_driver_names[] = {"USBCCGP"}; static const char *winusbx_driver_names[] = WINUSBX_DRV_NAMES; static const char *hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"}; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 9e268cdbe..7b2b87c76 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11114 +#define LIBUSB_NANO 11115 From 4770f8473e78071c0078a99afe1117a1a987cb26 Mon Sep 17 00:00:00 2001 From: Dom Postorivo Date: Thu, 30 Jun 2016 12:39:47 -0400 Subject: [PATCH 196/222] added logging to hot spots --- libusb/core.c | 21 ++++++++++++++++++--- libusb/io.c | 10 ++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 04e23549a..2f44fc437 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -831,6 +831,7 @@ ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx, if (usbi_backend->hotplug_poll) usbi_backend->hotplug_poll(); + usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex : locking usb_devs_lock=%d ", ctx->usb_devs_lock.value); usbi_mutex_lock(&ctx->usb_devs_lock); list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) { discdevs = discovered_devs_append(discdevs, dev); @@ -840,6 +841,7 @@ ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx, break; } } + usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex : unlocking usb_devs_lock=%d ", ctx->usb_devs_lock.value); usbi_mutex_unlock(&ctx->usb_devs_lock); } else { /* backend does not provide hotplug support */ @@ -977,7 +979,7 @@ int API_EXPORTED libusb_get_port_path(libusb_context *ctx, libusb_device *dev, * function and make sure that you only access the parent before issuing * \ref libusb_free_device_list(). The reason is that libusb currently does * not maintain a permanent list of device instances, and therefore can - * only guarantee that parents are fully instantiated within a + * only guarantee that parents are fully instantiated within a * libusb_get_device_list() - libusb_free_device_list() block. */ DEFAULT_VISIBILITY @@ -2147,9 +2149,12 @@ int API_EXPORTED libusb_init2(libusb_context **context, const char * uspfs_path_ usbi_dbg("libusb v%d.%d.%d.%d", libusb_version_internal.major, libusb_version_internal.minor, libusb_version_internal.micro, libusb_version_internal.nano); + usbi_mutex_init(&ctx->usb_devs_lock); usbi_mutex_init(&ctx->open_devs_lock); usbi_mutex_init(&ctx->hotplug_cbs_lock); + usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex init: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); + list_init(&ctx->usb_devs); list_init(&ctx->open_devs); list_init(&ctx->hotplug_cbs); @@ -2199,9 +2204,11 @@ int API_EXPORTED libusb_init2(libusb_context **context, const char * uspfs_path_ } usbi_mutex_unlock(&ctx->usb_devs_lock); + usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex before destroy: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); usbi_mutex_destroy(&ctx->open_devs_lock); usbi_mutex_destroy(&ctx->usb_devs_lock); usbi_mutex_destroy(&ctx->hotplug_cbs_lock); + usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex after destroy: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); free(ctx); err_unlock: @@ -2272,7 +2279,9 @@ int API_EXPORTED libusb_init(libusb_context **context) usbi_mutex_init(&ctx->usb_devs_lock); usbi_mutex_init(&ctx->open_devs_lock); usbi_mutex_init(&ctx->hotplug_cbs_lock); - list_init(&ctx->usb_devs); + usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex init: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); + + list_init(&ctx->usb_devs); list_init(&ctx->open_devs); list_init(&ctx->hotplug_cbs); @@ -2321,9 +2330,11 @@ int API_EXPORTED libusb_init(libusb_context **context) } usbi_mutex_unlock(&ctx->usb_devs_lock); + usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex before destroy: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock, ctx->open_devs_lock, ctx->hotplug_cbs_lock); usbi_mutex_destroy(&ctx->open_devs_lock); usbi_mutex_destroy(&ctx->usb_devs_lock); usbi_mutex_destroy(&ctx->hotplug_cbs_lock); + usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex after destroy: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock, ctx->open_devs_lock, ctx->hotplug_cbs_lock); free(ctx); err_unlock: @@ -2396,10 +2407,14 @@ void API_EXPORTED libusb_exit(struct libusb_context *ctx) if (usbi_backend->exit) usbi_backend->exit(); + + usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex before destroy: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); usbi_mutex_destroy(&ctx->open_devs_lock); usbi_mutex_destroy(&ctx->usb_devs_lock); usbi_mutex_destroy(&ctx->hotplug_cbs_lock); - free(ctx); + usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex after destroy: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); + + free(ctx); } /** \ingroup libusb_misc diff --git a/libusb/io.c b/libusb/io.c index a8e07ecc0..88cd831a0 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1129,6 +1129,8 @@ int usbi_io_init(struct libusb_context *ctx) usbi_mutex_init(&ctx->event_waiters_lock); usbi_cond_init(&ctx->event_waiters_cond); usbi_mutex_init(&ctx->event_data_lock); + usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex init: flying_transfers_lock=%d event_waiters_lock=%d event_data_lock=%d", ctx->flying_transfers_lock.value, ctx->event_waiters_lock.value, ctx->hotplug_cbs_lock.value); + usbi_tls_key_create(&ctx->event_handling_key); list_init(&ctx->flying_transfers); list_init(&ctx->ipollfds); @@ -1171,11 +1173,15 @@ int usbi_io_init(struct libusb_context *ctx) usbi_close(ctx->event_pipe[0]); usbi_close(ctx->event_pipe[1]); err: + usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex destroy before: flying_transfers_lock=%d event_waiters_lock=%d event_data_lock=%d", ctx->flying_transfers_lock.value, ctx->event_waiters_lock.value, ctx->hotplug_cbs_lock.value); + usbi_mutex_destroy(&ctx->flying_transfers_lock); usbi_mutex_destroy(&ctx->events_lock); usbi_mutex_destroy(&ctx->event_waiters_lock); usbi_cond_destroy(&ctx->event_waiters_cond); usbi_mutex_destroy(&ctx->event_data_lock); + + usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex destroy after: flying_transfers_lock=%d event_waiters_lock=%d event_data_lock=%d", ctx->flying_transfers_lock.value, ctx->event_waiters_lock.value, ctx->hotplug_cbs_lock.value); usbi_tls_key_delete(ctx->event_handling_key); return r; } @@ -1191,12 +1197,14 @@ void usbi_io_exit(struct libusb_context *ctx) close(ctx->timerfd); } #endif + usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex destroy before: flying_transfers_lock=%d event_waiters_lock=%d event_data_lock=%d", ctx->flying_transfers_lock.value, ctx->event_waiters_lock.value, ctx->hotplug_cbs_lock.value); usbi_mutex_destroy(&ctx->flying_transfers_lock); usbi_mutex_destroy(&ctx->events_lock); usbi_mutex_destroy(&ctx->event_waiters_lock); usbi_cond_destroy(&ctx->event_waiters_cond); usbi_mutex_destroy(&ctx->event_data_lock); usbi_tls_key_delete(ctx->event_handling_key); + usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex destroy after: flying_transfers_lock=%d event_waiters_lock=%d event_data_lock=%d", ctx->flying_transfers_lock.value, ctx->event_waiters_lock.value, ctx->hotplug_cbs_lock.value); if (ctx->pollfds) free(ctx->pollfds); } @@ -2643,10 +2651,12 @@ int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events) usbi_dbg("add fd %d events %d", fd, events); ipollfd->pollfd.fd = fd; ipollfd->pollfd.events = events; + usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex : locking event_data_lock=%d ", ctx->event_data_lock.value); usbi_mutex_lock(&ctx->event_data_lock); list_add_tail(&ipollfd->list, &ctx->ipollfds); ctx->pollfds_cnt++; usbi_fd_notification(ctx); + usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex : unlocking event_data_lock=%d ", ctx->event_data_lock.value); usbi_mutex_unlock(&ctx->event_data_lock); if (ctx->fd_added_cb) From ed70d456bc8d82537d59fefd6c89877de5517c2d Mon Sep 17 00:00:00 2001 From: Dom Postorivo Date: Thu, 30 Jun 2016 14:38:14 -0400 Subject: [PATCH 197/222] Switched to direct android logging --- libusb/core.c | 24 ++++++++++++++---------- libusb/io.c | 20 +++++++++++++------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 2f44fc437..888ca8717 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -45,6 +45,9 @@ #ifdef __ANDROID__ #include +#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, "libusb/core.c",__VA_ARGS__) +#else +#define LOGI(...) ((void) 0) #endif #include "libusbi.h" @@ -831,7 +834,7 @@ ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx, if (usbi_backend->hotplug_poll) usbi_backend->hotplug_poll(); - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex : locking usb_devs_lock=%d ", ctx->usb_devs_lock.value); + LOGI("ctx mutex : locking usb_devs_lock=%d ", ctx->usb_devs_lock.value); usbi_mutex_lock(&ctx->usb_devs_lock); list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) { discdevs = discovered_devs_append(discdevs, dev); @@ -841,7 +844,7 @@ ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx, break; } } - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex : unlocking usb_devs_lock=%d ", ctx->usb_devs_lock.value); + LOGI( "ctx mutex : unlocking usb_devs_lock=%d ", ctx->usb_devs_lock.value); usbi_mutex_unlock(&ctx->usb_devs_lock); } else { /* backend does not provide hotplug support */ @@ -2153,7 +2156,7 @@ int API_EXPORTED libusb_init2(libusb_context **context, const char * uspfs_path_ usbi_mutex_init(&ctx->usb_devs_lock); usbi_mutex_init(&ctx->open_devs_lock); usbi_mutex_init(&ctx->hotplug_cbs_lock); - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex init: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); + LOGI("ctx mutex init: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); list_init(&ctx->usb_devs); list_init(&ctx->open_devs); @@ -2204,11 +2207,12 @@ int API_EXPORTED libusb_init2(libusb_context **context, const char * uspfs_path_ } usbi_mutex_unlock(&ctx->usb_devs_lock); - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex before destroy: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); + LOGI("ctx mutex before destroy: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); usbi_mutex_destroy(&ctx->open_devs_lock); usbi_mutex_destroy(&ctx->usb_devs_lock); usbi_mutex_destroy(&ctx->hotplug_cbs_lock); - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex after destroy: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); + LOGI("ctx mutex after destroy: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); + free(ctx); err_unlock: @@ -2279,7 +2283,7 @@ int API_EXPORTED libusb_init(libusb_context **context) usbi_mutex_init(&ctx->usb_devs_lock); usbi_mutex_init(&ctx->open_devs_lock); usbi_mutex_init(&ctx->hotplug_cbs_lock); - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex init: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); + LOGI("ctx mutex init: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); list_init(&ctx->usb_devs); list_init(&ctx->open_devs); @@ -2330,11 +2334,11 @@ int API_EXPORTED libusb_init(libusb_context **context) } usbi_mutex_unlock(&ctx->usb_devs_lock); - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex before destroy: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock, ctx->open_devs_lock, ctx->hotplug_cbs_lock); + LOGI("ctx mutex before destroy: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); usbi_mutex_destroy(&ctx->open_devs_lock); usbi_mutex_destroy(&ctx->usb_devs_lock); usbi_mutex_destroy(&ctx->hotplug_cbs_lock); - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex after destroy: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock, ctx->open_devs_lock, ctx->hotplug_cbs_lock); + LOGI("ctx mutex after destroy: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); free(ctx); err_unlock: @@ -2408,11 +2412,11 @@ void API_EXPORTED libusb_exit(struct libusb_context *ctx) usbi_backend->exit(); - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex before destroy: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); + LOGI("ctx mutex before destroy: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); usbi_mutex_destroy(&ctx->open_devs_lock); usbi_mutex_destroy(&ctx->usb_devs_lock); usbi_mutex_destroy(&ctx->hotplug_cbs_lock); - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex after destroy: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); + LOGI("ctx mutex after destroy: usb_devs_lock=%d open_devs_lock=%d hotplug_cbs_lock=%d", ctx->usb_devs_lock.value, ctx->open_devs_lock.value, ctx->hotplug_cbs_lock.value); free(ctx); } diff --git a/libusb/io.c b/libusb/io.c index 88cd831a0..bb964619f 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -40,6 +40,12 @@ #include "libusbi.h" #include "hotplug.h" +#ifdef __ANDROID__ +#include +#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, "libusb/io.c",__VA_ARGS__) +#else +#define LOGI(...) ((void) 0) +#endif /** * \page libusb_io Synchronous and asynchronous device I/O * @@ -1129,7 +1135,7 @@ int usbi_io_init(struct libusb_context *ctx) usbi_mutex_init(&ctx->event_waiters_lock); usbi_cond_init(&ctx->event_waiters_cond); usbi_mutex_init(&ctx->event_data_lock); - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex init: flying_transfers_lock=%d event_waiters_lock=%d event_data_lock=%d", ctx->flying_transfers_lock.value, ctx->event_waiters_lock.value, ctx->hotplug_cbs_lock.value); + LOGI("ctx mutex init: flying_transfers_lock=%d event_waiters_lock=%d event_data_lock=%d", ctx->flying_transfers_lock.value, ctx->event_waiters_lock.value, ctx->hotplug_cbs_lock.value); usbi_tls_key_create(&ctx->event_handling_key); list_init(&ctx->flying_transfers); @@ -1173,7 +1179,7 @@ int usbi_io_init(struct libusb_context *ctx) usbi_close(ctx->event_pipe[0]); usbi_close(ctx->event_pipe[1]); err: - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex destroy before: flying_transfers_lock=%d event_waiters_lock=%d event_data_lock=%d", ctx->flying_transfers_lock.value, ctx->event_waiters_lock.value, ctx->hotplug_cbs_lock.value); + LOGI("ctx mutex destroy before: flying_transfers_lock=%d event_waiters_lock=%d event_data_lock=%d", ctx->flying_transfers_lock.value, ctx->event_waiters_lock.value, ctx->hotplug_cbs_lock.value); usbi_mutex_destroy(&ctx->flying_transfers_lock); usbi_mutex_destroy(&ctx->events_lock); @@ -1181,7 +1187,7 @@ int usbi_io_init(struct libusb_context *ctx) usbi_cond_destroy(&ctx->event_waiters_cond); usbi_mutex_destroy(&ctx->event_data_lock); - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex destroy after: flying_transfers_lock=%d event_waiters_lock=%d event_data_lock=%d", ctx->flying_transfers_lock.value, ctx->event_waiters_lock.value, ctx->hotplug_cbs_lock.value); + LOGI("ctx mutex destroy after: flying_transfers_lock=%d event_waiters_lock=%d event_data_lock=%d", ctx->flying_transfers_lock.value, ctx->event_waiters_lock.value, ctx->hotplug_cbs_lock.value); usbi_tls_key_delete(ctx->event_handling_key); return r; } @@ -1197,14 +1203,14 @@ void usbi_io_exit(struct libusb_context *ctx) close(ctx->timerfd); } #endif - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex destroy before: flying_transfers_lock=%d event_waiters_lock=%d event_data_lock=%d", ctx->flying_transfers_lock.value, ctx->event_waiters_lock.value, ctx->hotplug_cbs_lock.value); + LOGI("ctx mutex destroy before: flying_transfers_lock=%d event_waiters_lock=%d event_data_lock=%d", ctx->flying_transfers_lock.value, ctx->event_waiters_lock.value, ctx->hotplug_cbs_lock.value); usbi_mutex_destroy(&ctx->flying_transfers_lock); usbi_mutex_destroy(&ctx->events_lock); usbi_mutex_destroy(&ctx->event_waiters_lock); usbi_cond_destroy(&ctx->event_waiters_cond); usbi_mutex_destroy(&ctx->event_data_lock); usbi_tls_key_delete(ctx->event_handling_key); - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex destroy after: flying_transfers_lock=%d event_waiters_lock=%d event_data_lock=%d", ctx->flying_transfers_lock.value, ctx->event_waiters_lock.value, ctx->hotplug_cbs_lock.value); + LOGI("ctx mutex destroy after: flying_transfers_lock=%d event_waiters_lock=%d event_data_lock=%d", ctx->flying_transfers_lock.value, ctx->event_waiters_lock.value, ctx->hotplug_cbs_lock.value); if (ctx->pollfds) free(ctx->pollfds); } @@ -2651,12 +2657,12 @@ int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events) usbi_dbg("add fd %d events %d", fd, events); ipollfd->pollfd.fd = fd; ipollfd->pollfd.events = events; - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex : locking event_data_lock=%d ", ctx->event_data_lock.value); + LOGI("ctx mutex : locking event_data_lock=%d ", ctx->event_data_lock.value); usbi_mutex_lock(&ctx->event_data_lock); list_add_tail(&ipollfd->list, &ctx->ipollfds); ctx->pollfds_cnt++; usbi_fd_notification(ctx); - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_INFO, "ctx mutex : unlocking event_data_lock=%d ", ctx->event_data_lock.value); + LOGI("ctx mutex : unlocking event_data_lock=%d ", ctx->event_data_lock.value); usbi_mutex_unlock(&ctx->event_data_lock); if (ctx->fd_added_cb) From bcac08d60facba5f92d0ccfe548dea2da86f9113 Mon Sep 17 00:00:00 2001 From: Anil Nair Date: Sat, 2 Apr 2016 06:29:11 +0530 Subject: [PATCH 198/222] Examples: Ported testlibusb from libus-0.1 to libusb-1.0 This commit is based on Nathan's branch https://github.com/hjelmn/libusb-darwin/blob/master/examples/testlibusb1.c Closes #178 Signed-off-by: Nathan Hjelm --- examples/Makefile.am | 2 +- examples/testlibusb.c | 273 ++++++++++++++++++++++++++++++++++++++++++ libusb/version_nano.h | 2 +- 3 files changed, 275 insertions(+), 2 deletions(-) create mode 100755 examples/testlibusb.c diff --git a/examples/Makefile.am b/examples/Makefile.am index 808192741..6185d0074 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1,7 +1,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/libusb LDADD = ../libusb/libusb-1.0.la -noinst_PROGRAMS = listdevs xusb fxload hotplugtest +noinst_PROGRAMS = listdevs xusb fxload hotplugtest testlibusb if HAVE_SIGACTION noinst_PROGRAMS += dpfp diff --git a/examples/testlibusb.c b/examples/testlibusb.c new file mode 100755 index 000000000..b7068c9fa --- /dev/null +++ b/examples/testlibusb.c @@ -0,0 +1,273 @@ +/* +* Test suite program based of libusb-0.1-compat testlibusb +* Copyright (c) 2013 Nathan Hjelm +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include "libusb.h" + +int verbose = 0; + +static void print_endpoint_comp(const struct libusb_ss_endpoint_companion_descriptor *ep_comp) +{ + printf(" USB 3.0 Endpoint Companion:\n"); + printf(" bMaxBurst: %d\n", ep_comp->bMaxBurst); + printf(" bmAttributes: 0x%02x\n", ep_comp->bmAttributes); + printf(" wBytesPerInterval: %d\n", ep_comp->wBytesPerInterval); +} + +static void print_endpoint(const struct libusb_endpoint_descriptor *endpoint) +{ + int i, ret; + + printf(" Endpoint:\n"); + printf(" bEndpointAddress: %02xh\n", endpoint->bEndpointAddress); + printf(" bmAttributes: %02xh\n", endpoint->bmAttributes); + printf(" wMaxPacketSize: %d\n", endpoint->wMaxPacketSize); + printf(" bInterval: %d\n", endpoint->bInterval); + printf(" bRefresh: %d\n", endpoint->bRefresh); + printf(" bSynchAddress: %d\n", endpoint->bSynchAddress); + + for (i = 0; i < endpoint->extra_length;) { + if (LIBUSB_DT_SS_ENDPOINT_COMPANION == endpoint->extra[i + 1]) { + struct libusb_ss_endpoint_companion_descriptor *ep_comp; + + ret = libusb_get_ss_endpoint_companion_descriptor(NULL, endpoint, &ep_comp); + if (LIBUSB_SUCCESS != ret) { + continue; + } + + print_endpoint_comp(ep_comp); + + libusb_free_ss_endpoint_companion_descriptor(ep_comp); + } + + i += endpoint->extra[i]; + } +} + +static void print_altsetting(const struct libusb_interface_descriptor *interface) +{ + int i; + + printf(" Interface:\n"); + printf(" bInterfaceNumber: %d\n", interface->bInterfaceNumber); + printf(" bAlternateSetting: %d\n", interface->bAlternateSetting); + printf(" bNumEndpoints: %d\n", interface->bNumEndpoints); + printf(" bInterfaceClass: %d\n", interface->bInterfaceClass); + printf(" bInterfaceSubClass: %d\n", interface->bInterfaceSubClass); + printf(" bInterfaceProtocol: %d\n", interface->bInterfaceProtocol); + printf(" iInterface: %d\n", interface->iInterface); + + for (i = 0; i < interface->bNumEndpoints; i++) + print_endpoint(&interface->endpoint[i]); +} + +static void print_2_0_ext_cap(struct libusb_usb_2_0_extension_descriptor *usb_2_0_ext_cap) +{ + printf(" USB 2.0 Extension Capabilities:\n"); + printf(" bDevCapabilityType: %d\n", usb_2_0_ext_cap->bDevCapabilityType); + printf(" bmAttributes: 0x%x\n", usb_2_0_ext_cap->bmAttributes); +} + +static void print_ss_usb_cap(struct libusb_ss_usb_device_capability_descriptor *ss_usb_cap) +{ + printf(" USB 3.0 Capabilities:\n"); + printf(" bDevCapabilityType: %d\n", ss_usb_cap->bDevCapabilityType); + printf(" bmAttributes: 0x%x\n", ss_usb_cap->bmAttributes); + printf(" wSpeedSupported: 0x%x\n", ss_usb_cap->wSpeedSupported); + printf(" bFunctionalitySupport: %d\n", ss_usb_cap->bFunctionalitySupport); + printf(" bU1devExitLat: %d\n", ss_usb_cap->bU1DevExitLat); + printf(" bU2devExitLat: %d\n", ss_usb_cap->bU2DevExitLat); +} + +static void print_bos(libusb_device_handle *handle) +{ + struct libusb_bos_descriptor *bos; + int ret; + + ret = libusb_get_bos_descriptor(handle, &bos); + if (0 > ret) { + return; + } + + printf(" Binary Object Store (BOS):\n"); + printf(" wTotalLength: %d\n", bos->wTotalLength); + printf(" bNumDeviceCaps: %d\n", bos->bNumDeviceCaps); + + if(bos->dev_capability[0]->bDevCapabilityType == LIBUSB_BT_USB_2_0_EXTENSION) { + + struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension; + ret = libusb_get_usb_2_0_extension_descriptor(NULL, bos->dev_capability[0],&usb_2_0_extension); + if (0 > ret) { + return; + } + + print_2_0_ext_cap(usb_2_0_extension); + libusb_free_usb_2_0_extension_descriptor(usb_2_0_extension); + } + + if(bos->dev_capability[0]->bDevCapabilityType == LIBUSB_BT_SS_USB_DEVICE_CAPABILITY) { + + struct libusb_ss_usb_device_capability_descriptor *dev_cap; + ret = libusb_get_ss_usb_device_capability_descriptor(NULL, bos->dev_capability[0],&dev_cap); + if (0 > ret) { + return; + } + + print_ss_usb_cap(dev_cap); + libusb_free_ss_usb_device_capability_descriptor(dev_cap); + } + + libusb_free_bos_descriptor(bos); +} + +static void print_interface(const struct libusb_interface *interface) +{ + int i; + + for (i = 0; i < interface->num_altsetting; i++) + print_altsetting(&interface->altsetting[i]); +} + +static void print_configuration(struct libusb_config_descriptor *config) +{ + int i; + + printf(" Configuration:\n"); + printf(" wTotalLength: %d\n", config->wTotalLength); + printf(" bNumInterfaces: %d\n", config->bNumInterfaces); + printf(" bConfigurationValue: %d\n", config->bConfigurationValue); + printf(" iConfiguration: %d\n", config->iConfiguration); + printf(" bmAttributes: %02xh\n", config->bmAttributes); + printf(" MaxPower: %d\n", config->MaxPower); + + for (i = 0; i < config->bNumInterfaces; i++) + print_interface(&config->interface[i]); +} + +static int print_device(libusb_device *dev, int level) +{ + struct libusb_device_descriptor desc; + libusb_device_handle *handle = NULL; + char description[256]; + char string[256]; + int ret, i; + + ret = libusb_get_device_descriptor(dev, &desc); + if (ret < 0) { + fprintf(stderr, "failed to get device descriptor"); + return -1; + } + + ret = libusb_open(dev, &handle); + if (LIBUSB_SUCCESS == ret) { + if (desc.iManufacturer) { + ret = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, string, sizeof(string)); + if (ret > 0) + snprintf(description, sizeof(description), "%s - ", string); + else + snprintf(description, sizeof(description), "%04X - ", + desc.idVendor); + } + else + snprintf(description, sizeof(description), "%04X - ", + desc.idVendor); + + if (desc.iProduct) { + ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct, string, sizeof(string)); + if (ret > 0) + snprintf(description + strlen(description), sizeof(description) - + strlen(description), "%s", string); + else + snprintf(description + strlen(description), sizeof(description) - + strlen(description), "%04X", desc.idProduct); + } + else + snprintf(description + strlen(description), sizeof(description) - + strlen(description), "%04X", desc.idProduct); + } + else { + snprintf(description, sizeof(description), "%04X - %04X", + desc.idVendor, desc.idProduct); + } + + printf("%.*sDev (bus %d, device %d): %s\n", level * 2, " ", + libusb_get_bus_number(dev), libusb_get_device_address(dev), description); + + if (handle && verbose) { + if (desc.iSerialNumber) { + ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, string, sizeof(string)); + if (ret > 0) + printf("%.*s - Serial Number: %s\n", level * 2, + " ", string); + } + } + + if (verbose) { + for (i = 0; i < desc.bNumConfigurations; i++) { + struct libusb_config_descriptor *config; + ret = libusb_get_config_descriptor(dev, i, &config); + if (LIBUSB_SUCCESS != ret) { + printf(" Couldn't retrieve descriptors\n"); + continue; + } + + print_configuration(config); + + libusb_free_config_descriptor(config); + } + + + if (handle && desc.bcdUSB >= 0x0201) { + print_bos(handle); + } + } + + if (handle) + libusb_close(handle); + + return 0; +} + +int main(int argc, char *argv[]) +{ + libusb_device **devs; + ssize_t cnt; + int r, i; + + if (argc > 1 && !strcmp(argv[1], "-v")) + verbose = 1; + + r = libusb_init(NULL); + if (r < 0) + return r; + + cnt = libusb_get_device_list(NULL, &devs); + if (cnt < 0) + return (int)cnt; + + for (i = 0; devs[i]; ++i) { + print_device(devs[i], 0); + } + + libusb_free_device_list(devs, 1); + + libusb_exit(NULL); + return 0; +} diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 7b2b87c76..d9f98436a 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11115 +#define LIBUSB_NANO 11117 From 7dff2d35ca8ee7219e5e6cb39aee53fd9088a2d7 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Thu, 21 Jul 2016 22:26:19 -0600 Subject: [PATCH 199/222] examples: make dpfp_threaded work on OS X OS X does not support unnamed semaphores so the example has been updated to use a named semaphore instead. Signed-off-by: Nathan Hjelm --- examples/dpfp_threaded.c | 17 ++++++++++------- libusb/version_nano.h | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/examples/dpfp_threaded.c b/examples/dpfp_threaded.c index a7502a40e..0c6b3e7dd 100644 --- a/examples/dpfp_threaded.c +++ b/examples/dpfp_threaded.c @@ -1,6 +1,7 @@ /* * libusb example program to manipulate U.are.U 4000B fingerprint scanner. * Copyright © 2007 Daniel Drake + * Copyright © 2016 Nathan Hjelm * * Basic image capture program only, does not consider the powerup quirks or * the fact that image encryption may be enabled. Not expected to work @@ -37,6 +38,7 @@ #define CTRL_OUT (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT) #define USB_RQ 0x04 #define INTR_LENGTH 64 +#define SEM_NAME "/org.libusb.example.dpfp_threaded" enum { MODE_INIT = 0x00, @@ -68,12 +70,12 @@ static int img_idx = 0; static volatile sig_atomic_t do_exit = 0; static pthread_t poll_thread; -static sem_t exit_sem; +static sem_t *exit_sem; static void request_exit(sig_atomic_t code) { do_exit = code; - sem_post(&exit_sem); + sem_post(exit_sem); } static void *poll_thread_main(void *arg) @@ -446,16 +448,18 @@ int main(void) struct sigaction sigact; int r = 1; - r = sem_init(&exit_sem, 0, 0); - if (r) { + exit_sem = sem_open (SEM_NAME, O_CREAT, 0); + if (!exit_sem) { fprintf(stderr, "failed to initialise semaphore error %d", errno); exit(1); } + /* only using this semaphore in this process so go ahead and unlink it now */ + sem_unlink (SEM_NAME); + r = libusb_init(NULL); if (r < 0) { fprintf(stderr, "failed to initialise libusb\n"); - sem_destroy(&exit_sem); exit(1); } @@ -508,7 +512,7 @@ int main(void) } while (!do_exit) - sem_wait(&exit_sem); + sem_wait(exit_sem); printf("shutting down...\n"); pthread_join(poll_thread, NULL); @@ -544,6 +548,5 @@ int main(void) out: libusb_close(devh); libusb_exit(NULL); - sem_destroy(&exit_sem); return r >= 0 ? r : -r; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index d9f98436a..9fdf028f1 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11117 +#define LIBUSB_NANO 11116 From 001f68782c364186cbb116b44f52c6d489973d08 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Thu, 21 Jul 2016 22:31:09 -0600 Subject: [PATCH 200/222] fix nano Signed-off-by: Nathan Hjelm --- libusb/version_nano.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 9fdf028f1..beb50c1ff 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11116 +#define LIBUSB_NANO 11118 From 9afb5c0caf7778d8757ddabadca16aebd7819810 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Thu, 21 Jul 2016 22:38:32 -0600 Subject: [PATCH 201/222] examples: add missing include to dpfp_threaded Signed-off-by: Nathan Hjelm --- examples/dpfp_threaded.c | 1 + libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/dpfp_threaded.c b/examples/dpfp_threaded.c index 0c6b3e7dd..d74531248 100644 --- a/examples/dpfp_threaded.c +++ b/examples/dpfp_threaded.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "libusb.h" diff --git a/libusb/version_nano.h b/libusb/version_nano.h index beb50c1ff..75b9b0682 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11118 +#define LIBUSB_NANO 11119 From bd8d5b5019b72b2dc2d074d96c9992e2f6e7e0b7 Mon Sep 17 00:00:00 2001 From: Joost Muller Date: Wed, 20 Jul 2016 10:58:57 +0200 Subject: [PATCH 202/222] io: Fix race condition in handle_timeout() There is a race between handle_timeout() the completion functions. When one thread is in handle_timeout() and another thread wakes up from a poll(), there exists a window where the transfer has been cancelled, but its USBI_TRANSFER_TIMED_OUT flag is not set yet. Therefore, usbi_handle_transfer_completion() is sometimes called with LIBUSB_TRANSFER_CANCELLED instead of the expected LIBUSB_TRANSFER_TIMED_OUT. This change adds transfer and flag locks to the handle_timeout() function. Closes #197 Signed-off-by: Nathan Hjelm --- libusb/io.c | 57 ++++++++++++++++++++++++++++--------------- libusb/version_nano.h | 2 +- 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/libusb/io.c b/libusb/io.c index 4d03b8b77..894446150 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1530,6 +1530,34 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer) return r; } +static int cancel_transfer_locked(struct libusb_transfer *transfer) +{ + struct usbi_transfer *itransfer = + LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); + int r; + if (!(itransfer->flags & USBI_TRANSFER_IN_FLIGHT) + || (itransfer->flags & USBI_TRANSFER_CANCELLING)) { + return LIBUSB_ERROR_NOT_FOUND; + } + + r = usbi_backend->cancel_transfer(itransfer); + if (r < 0) { + if (r != LIBUSB_ERROR_NOT_FOUND && + r != LIBUSB_ERROR_NO_DEVICE) + usbi_err(TRANSFER_CTX(transfer), + "cancel transfer failed error %d", r); + else + usbi_dbg("cancel transfer failed error %d", r); + + if (r == LIBUSB_ERROR_NO_DEVICE) + itransfer->flags |= USBI_TRANSFER_DEVICE_DISAPPEARED; + } + + itransfer->flags |= USBI_TRANSFER_CANCELLING; + + return r; +} + /** \ingroup libusb_asyncio * Asynchronously cancel a previously submitted transfer. * This function returns immediately, but this does not indicate cancellation @@ -1553,27 +1581,9 @@ int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer) usbi_dbg("transfer %p", transfer ); usbi_mutex_lock(&itransfer->lock); usbi_mutex_lock(&itransfer->flags_lock); - if (!(itransfer->flags & USBI_TRANSFER_IN_FLIGHT) - || (itransfer->flags & USBI_TRANSFER_CANCELLING)) { - r = LIBUSB_ERROR_NOT_FOUND; - goto out; - } - r = usbi_backend->cancel_transfer(itransfer); - if (r < 0) { - if (r != LIBUSB_ERROR_NOT_FOUND && - r != LIBUSB_ERROR_NO_DEVICE) - usbi_err(TRANSFER_CTX(transfer), - "cancel transfer failed error %d", r); - else - usbi_dbg("cancel transfer failed error %d", r); - if (r == LIBUSB_ERROR_NO_DEVICE) - itransfer->flags |= USBI_TRANSFER_DEVICE_DISAPPEARED; - } - - itransfer->flags |= USBI_TRANSFER_CANCELLING; + r = cancel_transfer_locked(transfer); -out: usbi_mutex_unlock(&itransfer->flags_lock); usbi_mutex_unlock(&itransfer->lock); return r; @@ -1967,13 +1977,20 @@ static void handle_timeout(struct usbi_transfer *itransfer) USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); int r; + usbi_mutex_lock(&itransfer->lock); + usbi_mutex_lock(&itransfer->flags_lock); + itransfer->flags |= USBI_TRANSFER_TIMEOUT_HANDLED; - r = libusb_cancel_transfer(transfer); + r = cancel_transfer_locked(transfer); + if (r == 0) itransfer->flags |= USBI_TRANSFER_TIMED_OUT; else usbi_warn(TRANSFER_CTX(transfer), "async cancel failed %d errno=%d", r, errno); + + usbi_mutex_unlock(&itransfer->flags_lock); + usbi_mutex_unlock(&itransfer->lock); } static int handle_timeouts_locked(struct libusb_context *ctx) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 75b9b0682..3687c25b3 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11119 +#define LIBUSB_NANO 11120 From 7ce85c4679a31a7193d8d4651604ef2776a007ac Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Thu, 21 Jul 2016 23:12:56 -0600 Subject: [PATCH 203/222] libusb 1.0.21-rc1 Signed-off-by: Nathan Hjelm --- ChangeLog | 9 +++++++++ libusb/version.h | 4 ++-- libusb/version_nano.h | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index fc5fc2ad5..53416f4dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,15 @@ For detailed information about the changes below, please see the git log or visit: http://log.libusb.info +2016-07-20: v1.0.21: +* Darwin: Ignore root hub simulation devices +* Darwin: Improved support for OS X El Capitan +* Windows: Add Visual Studio 2015 support +* Prevent attempts to recursively hande events +* Fix race condition in handle_timeout() +* Allow transferred argument to be optional in bulk APIs +* Various other bug fixes and improvements + 2015-09-13: v1.0.20 * Add Haiku support * Fix multiple memory and resource leaks (#16, #52, #76, #81) diff --git a/libusb/version.h b/libusb/version.h index 0e3a3633d..e1a28e0d8 100644 --- a/libusb/version.h +++ b/libusb/version.h @@ -7,12 +7,12 @@ #define LIBUSB_MINOR 0 #endif #ifndef LIBUSB_MICRO -#define LIBUSB_MICRO 20 +#define LIBUSB_MICRO 21 #endif #ifndef LIBUSB_NANO #define LIBUSB_NANO 0 #endif /* LIBUSB_RC is the release candidate suffix. Should normally be empty. */ #ifndef LIBUSB_RC -#define LIBUSB_RC "" +#define LIBUSB_RC "-rc1" #endif diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 3687c25b3..867375ce1 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11120 +#define LIBUSB_NANO 11121 From 3564c18d83251b2201644f1c669c6faebe267134 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Fri, 22 Jul 2016 12:57:40 +0100 Subject: [PATCH 204/222] windows: use appropriate version for VS2015 solution files * Closes #193 --- libusb/version_nano.h | 2 +- msvc/libusb_2015.sln | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 867375ce1..a952e6c9e 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11121 +#define LIBUSB_NANO 11122 diff --git a/msvc/libusb_2015.sln b/msvc/libusb_2015.sln index c6bd0effe..f93ebc12d 100644 --- a/msvc/libusb_2015.sln +++ b/msvc/libusb_2015.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.21005.1 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "libusb_static_2015.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}" EndProject From 69767330ff9b30736624d60b2e6bc2cdb6382e2e Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Fri, 22 Jul 2016 06:38:09 -0600 Subject: [PATCH 205/222] changelog: add missing entry Signed-off-by: Nathan Hjelm --- ChangeLog | 1 + libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 53416f4dd..15d6903df 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ visit: http://log.libusb.info 2016-07-20: v1.0.21: * Darwin: Ignore root hub simulation devices * Darwin: Improved support for OS X El Capitan +* Linux: Support preallocating kernel memory for zerocopy USB * Windows: Add Visual Studio 2015 support * Prevent attempts to recursively hande events * Fix race condition in handle_timeout() diff --git a/libusb/version_nano.h b/libusb/version_nano.h index a952e6c9e..3790b5fd9 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11122 +#define LIBUSB_NANO 11123 From eefd32213ec191967acc3b40b5c7c61064bc1273 Mon Sep 17 00:00:00 2001 From: Lei Chen Date: Fri, 19 Feb 2016 11:58:39 +0800 Subject: [PATCH 206/222] Solaris backend Closes #177 Signed-off-by: Nathan Hjelm --- configure.ac | 16 +- libusb-1.0.pc.in | 2 +- libusb/Makefile.am | 5 + libusb/core.c | 2 + libusb/libusbi.h | 12 +- libusb/os/sunos_usb.c | 1292 +++++++++++++++++++++++++++++++++++++++++ libusb/os/sunos_usb.h | 74 +++ libusb/version_nano.h | 2 +- 8 files changed, 1401 insertions(+), 4 deletions(-) create mode 100644 libusb/os/sunos_usb.c create mode 100644 libusb/os/sunos_usb.h diff --git a/configure.ac b/configure.ac index 77efdec8a..c00af332d 100644 --- a/configure.ac +++ b/configure.ac @@ -94,8 +94,13 @@ case $host in backend="haiku" threads="posix" ;; +*-solaris*) + AC_MSG_RESULT([SunOS]) + backend="sunos" + threads="posix" + ;; *) - AC_MSG_ERROR([unsupported operating system]) + AC_MSG_ERROR([unsupported operating system $host]) esac case $backend in @@ -154,6 +159,14 @@ openbsd) AC_CHECK_HEADERS([poll.h]) AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument]) ;; +sunos) + AC_DEFINE(OS_SUNOS, 1, [SunOS backend]) + AC_SUBST(OS_SUNOS) + THREAD_CFLAGS="-pthread" + LIBS="-pthread -ldevinfo" + AC_CHECK_HEADERS([poll.h]) + AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument]) + ;; netbsd) AC_DEFINE(OS_NETBSD, 1, [NetBSD backend]) AC_SUBST(OS_NETBSD) @@ -192,6 +205,7 @@ AC_SUBST(LIBS) AM_CONDITIONAL(OS_LINUX, test "x$backend" = xlinux) AM_CONDITIONAL(OS_DARWIN, test "x$backend" = xdarwin) AM_CONDITIONAL(OS_OPENBSD, test "x$backend" = xopenbsd) +AM_CONDITIONAL(OS_SUNOS, test "x$backend" = xsunos) AM_CONDITIONAL(OS_NETBSD, test "x$backend" = xnetbsd) AM_CONDITIONAL(OS_WINDOWS, test "x$backend" = xwindows) AM_CONDITIONAL(OS_HAIKU, test "x$backend" = xhaiku) diff --git a/libusb-1.0.pc.in b/libusb-1.0.pc.in index aa023b319..4aba609e6 100644 --- a/libusb-1.0.pc.in +++ b/libusb-1.0.pc.in @@ -4,7 +4,7 @@ libdir=@libdir@ includedir=@includedir@ Name: libusb-1.0 -Description: C API for USB device access from Linux, Mac OS X, Windows and OpenBSD/NetBSD userspace +Description: C API for USB device access from Linux, Mac OS X, Windows, OpenBSD/NetBSD and Solaris userspace Version: @VERSION@ Libs: -L${libdir} -lusb-1.0 Libs.private: @LIBS@ diff --git a/libusb/Makefile.am b/libusb/Makefile.am index 15042d3d7..b1b892d9c 100644 --- a/libusb/Makefile.am +++ b/libusb/Makefile.am @@ -12,6 +12,7 @@ LINUX_USBFS_SRC = os/linux_usbfs.h os/linux_usbfs.c DARWIN_USB_SRC = os/darwin_usb.h os/darwin_usb.c OPENBSD_USB_SRC = os/openbsd_usb.c NETBSD_USB_SRC = os/netbsd_usb.c +SUNOS_USB_SRC = os/sunos_usb.c os/sunos_usb.h WINDOWS_COMMON_SRC = os/windows_nt_common.h os/windows_nt_common.c \ os/windows_common.h libusb-1.0.rc libusb-1.0.def WINDOWS_USB_SRC = os/windows_winusb.h os/windows_winusb.c @@ -51,6 +52,10 @@ if OS_NETBSD OS_SRC = $(NETBSD_USB_SRC) endif +if OS_SUNOS +OS_SRC = $(SUNOS_USB_SRC) +endif + if OS_HAIKU noinst_LTLIBRARIES = libusb_haiku.la libusb_haiku_la_SOURCES = $(HAIKU_USB_SRC) diff --git a/libusb/core.c b/libusb/core.c index 54c10103f..06342c87d 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -64,6 +64,8 @@ const struct usbi_os_backend * const usbi_backend = &windows_backend; const struct usbi_os_backend * const usbi_backend = &wince_backend; #elif defined(OS_HAIKU) const struct usbi_os_backend * const usbi_backend = &haiku_usb_raw_backend; +#elif defined (OS_SUNOS) +const struct usbi_os_backend * const usbi_backend = &sunos_backend; #else #error "Unsupported OS" #endif diff --git a/libusb/libusbi.h b/libusb/libusbi.h index b5530d610..ca54a4621 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -387,7 +387,11 @@ struct libusb_device { #else [0] /* non-standard, but usually working code */ #endif +#if defined(OS_SUNOS) + __attribute__ ((aligned (8))); +#else ; +#endif }; struct libusb_device_handle { @@ -404,7 +408,11 @@ struct libusb_device_handle { #else [0] /* non-standard, but usually working code */ #endif +#if defined(OS_SUNOS) + __attribute__ ((aligned (8))); +#else ; +#endif }; enum { @@ -527,7 +535,8 @@ int usbi_signal_event(struct libusb_context *ctx); int usbi_clear_event(struct libusb_context *ctx); /* Internal abstraction for poll (needs struct usbi_transfer on Windows) */ -#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD) || defined(OS_HAIKU) +#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD) ||\ + defined(OS_HAIKU) || defined(OS_SUNOS) #include #include "os/poll_posix.h" #elif defined(OS_WINDOWS) || defined(OS_WINCE) @@ -1136,6 +1145,7 @@ extern const struct usbi_os_backend windows_backend; extern const struct usbi_os_backend usbdk_backend; extern const struct usbi_os_backend wince_backend; extern const struct usbi_os_backend haiku_usb_raw_backend; +extern const struct usbi_os_backend sunos_backend; extern struct list_head active_contexts_list; extern usbi_mutex_static_t active_contexts_lock; diff --git a/libusb/os/sunos_usb.c b/libusb/os/sunos_usb.c new file mode 100644 index 000000000..cb608976b --- /dev/null +++ b/libusb/os/sunos_usb.c @@ -0,0 +1,1292 @@ +/* + * + * Copyright (c) 2016, Oracle and/or its affiliates. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libusbi.h" +#include "sunos_usb.h" + +/* + * Backend functions + */ +static int sunos_init(struct libusb_context *); +static void sunos_exit(void); +static int sunos_get_device_list(struct libusb_context *, + struct discovered_devs **); +static int sunos_open(struct libusb_device_handle *); +static void sunos_close(struct libusb_device_handle *); +static int sunos_get_device_descriptor(struct libusb_device *, + uint8_t*, int *); +static int sunos_get_active_config_descriptor(struct libusb_device *, + uint8_t*, size_t, int *); +static int sunos_get_config_descriptor(struct libusb_device *, uint8_t, + uint8_t*, size_t, int *); +static int sunos_get_configuration(struct libusb_device_handle *, int *); +static int sunos_set_configuration(struct libusb_device_handle *, int); +static int sunos_claim_interface(struct libusb_device_handle *, int); +static int sunos_release_interface(struct libusb_device_handle *, int); +static int sunos_set_interface_altsetting(struct libusb_device_handle *, + int, int); +static int sunos_clear_halt(struct libusb_device_handle *, uint8_t); +static int sunos_reset_device(struct libusb_device_handle *); +static void sunos_destroy_device(struct libusb_device *); +static int sunos_submit_transfer(struct usbi_transfer *); +static int sunos_cancel_transfer(struct usbi_transfer *); +static void sunos_clear_transfer_priv(struct usbi_transfer *); +static int sunos_handle_transfer_completion(struct usbi_transfer *); +static int sunos_clock_gettime(int, struct timespec *); + +/* + * Private functions + */ +static int _errno_to_libusb(int); +static int sunos_usb_get_status(int fd); + +static int sunos_init(struct libusb_context *ctx) +{ + return (LIBUSB_SUCCESS); +} + +static void sunos_exit(void) +{ + usbi_dbg(""); +} + +static int +sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev) +{ + int proplen; + int n, *addr, *port_prop; + char *phypath; + uint8_t *rdata; + struct libusb_device_descriptor *descr; + sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; + + /* Device descriptors */ + proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, + "usb-dev-descriptor", &rdata); + if (proplen <= 0) { + + return (LIBUSB_ERROR_IO); + } + + descr = (struct libusb_device_descriptor *)rdata; + bcopy(descr, &dpriv->dev_descr, LIBUSB_DT_DEVICE_SIZE); + dpriv->dev_descr.bcdUSB = libusb_cpu_to_le16(descr->bcdUSB); + dpriv->dev_descr.idVendor = libusb_cpu_to_le16(descr->idVendor); + dpriv->dev_descr.idProduct = libusb_cpu_to_le16(descr->idProduct); + dpriv->dev_descr.bcdDevice = libusb_cpu_to_le16(descr->bcdDevice); + + /* Raw configuration descriptors */ + proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, + "usb-raw-cfg-descriptors", &rdata); + if (proplen <= 0) { + usbi_dbg("can't find raw config descriptors"); + + return (LIBUSB_ERROR_IO); + } + dpriv->raw_cfgdescr = calloc(1, proplen); + if (dpriv->raw_cfgdescr == NULL) { + return (LIBUSB_ERROR_NO_MEM); + } else { + bcopy(rdata, dpriv->raw_cfgdescr, proplen); + dpriv->cfgvalue = ((struct libusb_config_descriptor *) + rdata)->bConfigurationValue; + } + + n = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", &port_prop); + + if ((n != 1) || (*port_prop <= 0)) { + return (LIBUSB_ERROR_IO); + } + dev->port_number = *port_prop; + + /* device physical path */ + phypath = di_devfs_path(node); + if (phypath) { + dpriv->phypath = strdup(phypath); + di_devfs_path_free(phypath); + } else { + free(dpriv->raw_cfgdescr); + + return (LIBUSB_ERROR_IO); + } + + /* address */ + n = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "assigned-address", &addr); + if (n != 1 || *addr == 0) { + usbi_dbg("can't get address"); + } else { + dev->device_address = *addr; + } + + /* speed */ + if (di_prop_exists(DDI_DEV_T_ANY, node, "low-speed") == 1) { + dev->speed = LIBUSB_SPEED_LOW; + } else if (di_prop_exists(DDI_DEV_T_ANY, node, "high-speed") == 1) { + dev->speed = LIBUSB_SPEED_HIGH; + } else if (di_prop_exists(DDI_DEV_T_ANY, node, "full-speed") == 1) { + dev->speed = LIBUSB_SPEED_FULL; + } else if (di_prop_exists(DDI_DEV_T_ANY, node, "super-speed") == 1) { + dev->speed = LIBUSB_SPEED_SUPER; + } + + usbi_dbg("vid=%x pid=%x, path=%s, bus_nmber=0x%x, port_number=%d, " + "speed=%d", dpriv->dev_descr.idVendor, dpriv->dev_descr.idProduct, + dpriv->phypath, dev->bus_number, dev->port_number, dev->speed); + + return (LIBUSB_SUCCESS); +} + + +static int +sunos_add_devices(di_devlink_t link, void *arg) +{ + struct devlink_cbarg *largs = (struct devlink_cbarg *)arg; + struct node_args *nargs; + di_node_t myself, pnode; + uint64_t session_id = 0; + uint16_t bdf = 0; + struct libusb_device *dev; + sunos_dev_priv_t *devpriv; + const char *path, *newpath; + int n, i; + int *addr_prop; + uint8_t bus_number = 0; + + nargs = (struct node_args *)largs->nargs; + myself = largs->myself; + if (nargs->last_ugenpath) { + /* the same node's links */ + return (DI_WALK_CONTINUE); + } + + /* + * Construct session ID. + * session ID = ...parent hub addr|hub addr|dev addr. + */ + pnode = myself; + i = 0; + while (pnode != DI_NODE_NIL) { + if (di_prop_exists(DDI_DEV_T_ANY, pnode, "root-hub") == 1) { + /* walk to root */ + uint32_t *regbuf = NULL; + uint32_t reg; + + n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode, "reg", + (int **)®buf); + reg = regbuf[0]; + bdf = (PCI_REG_BUS_G(reg) << 8) | + (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); + session_id |= (bdf << i * 8); + + /* same as 'unit-address' property */ + bus_number = + (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); + + usbi_dbg("device bus address=%s:%x", + di_bus_addr(pnode), bus_number); + + break; + } + + /* usb_addr */ + n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode, + "assigned-address", &addr_prop); + if ((n != 1) || (addr_prop[0] == 0)) { + usbi_dbg("cannot get valid usb_addr"); + + return (DI_WALK_CONTINUE); + } + + session_id |= ((addr_prop[0] & 0xff) << i * 8); + if (++i > 7) + break; + + pnode = di_parent_node(pnode); + } + + path = di_devlink_path(link); + dev = usbi_get_device_by_session_id(nargs->ctx, session_id); + if (dev == NULL) { + dev = usbi_alloc_device(nargs->ctx, session_id); + if (dev == NULL) { + usbi_dbg("can't alloc device"); + + return (DI_WALK_TERMINATE); + } + devpriv = (sunos_dev_priv_t *)dev->os_priv; + if ((newpath = strrchr(path, '/')) == NULL) { + libusb_unref_device(dev); + + return (DI_WALK_TERMINATE); + } + devpriv->ugenpath = strndup(path, strlen(path) - + strlen(newpath)); + dev->bus_number = bus_number; + + if (sunos_fill_in_dev_info(myself, dev) != LIBUSB_SUCCESS) { + libusb_unref_device(dev); + + return (DI_WALK_TERMINATE); + } + if (usbi_sanitize_device(dev) < 0) { + libusb_unref_device(dev); + usbi_dbg("sanatize failed: "); + return (DI_WALK_TERMINATE); + } + } else { + usbi_dbg("Dev %s exists", path); + } + + devpriv = (sunos_dev_priv_t *)dev->os_priv; + if (nargs->last_ugenpath == NULL) { + /* first device */ + nargs->last_ugenpath = devpriv->ugenpath; + + if (discovered_devs_append(*(nargs->discdevs), dev) == NULL) { + usbi_dbg("cannot append device"); + } + + /* + * we alloc and hence ref this dev. We don't need to ref it + * hereafter. Front end or app should take care of their ref. + */ + libusb_unref_device(dev); + } + + usbi_dbg("Device %s %s id=0x%llx, devcount:%d, bdf=%x", + devpriv->ugenpath, path, (uint64_t)session_id, + (*nargs->discdevs)->len, bdf); + + return (DI_WALK_CONTINUE); +} + +static int +sunos_walk_minor_node_link(di_node_t node, void *args) +{ + di_minor_t minor = DI_MINOR_NIL; + char *minor_path; + struct devlink_cbarg arg; + struct node_args *nargs = (struct node_args *)args; + di_devlink_handle_t devlink_hdl = nargs->dlink_hdl; + + /* walk each minor to find ugen devices */ + while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { + minor_path = di_devfs_minor_path(minor); + arg.nargs = args; + arg.myself = node; + arg.minor = minor; + (void) di_devlink_walk(devlink_hdl, + "^usb/[0-9a-f]+[.][0-9a-f]+", minor_path, + DI_PRIMARY_LINK, (void *)&arg, sunos_add_devices); + di_devfs_path_free(minor_path); + } + + /* switch to a different node */ + nargs->last_ugenpath = NULL; + + return (DI_WALK_CONTINUE); +} + +int +sunos_get_device_list(struct libusb_context * ctx, + struct discovered_devs **discdevs) +{ + di_node_t root_node; + struct node_args args; + di_devlink_handle_t devlink_hdl; + + args.ctx = ctx; + args.discdevs = discdevs; + args.last_ugenpath = NULL; + if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { + usbi_dbg("di_int() failed: %s", strerror(errno)); + return (LIBUSB_ERROR_IO); + } + + if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { + di_fini(root_node); + usbi_dbg("di_devlink_init() failed: %s", strerror(errno)); + + return (LIBUSB_ERROR_IO); + } + args.dlink_hdl = devlink_hdl; + + /* walk each node to find USB devices */ + if (di_walk_node(root_node, DI_WALK_SIBFIRST, &args, + sunos_walk_minor_node_link) == -1) { + usbi_dbg("di_walk_node() failed: %s", strerror(errno)); + di_fini(root_node); + + return (LIBUSB_ERROR_IO); + } + + di_fini(root_node); + di_devlink_fini(&devlink_hdl); + + usbi_dbg("%d devices", (*discdevs)->len); + + return ((*discdevs)->len); +} + +static int +sunos_usb_open_ep0(sunos_dev_handle_priv_t *hpriv, sunos_dev_priv_t *dpriv) +{ + char filename[PATH_MAX + 1]; + + if (hpriv->eps[0].datafd > 0) { + + return (LIBUSB_SUCCESS); + } + snprintf(filename, PATH_MAX, "%s/cntrl0", dpriv->ugenpath); + + usbi_dbg("opening %s", filename); + hpriv->eps[0].datafd = open(filename, O_RDWR); + if (hpriv->eps[0].datafd < 0) { + return(_errno_to_libusb(errno)); + } + + snprintf(filename, PATH_MAX, "%s/cntrl0stat", dpriv->ugenpath); + hpriv->eps[0].statfd = open(filename, O_RDONLY); + if (hpriv->eps[0].statfd < 0) { + close(hpriv->eps[0].datafd); + hpriv->eps[0].datafd = -1; + + return(_errno_to_libusb(errno)); + } + + return (LIBUSB_SUCCESS); +} + +static void +sunos_usb_close_all_eps(sunos_dev_handle_priv_t *hdev) +{ + int i; + + /* not close ep0 */ + for (i = 1; i < USB_MAXENDPOINTS; i++) { + if (hdev->eps[i].datafd != -1) { + (void) close(hdev->eps[i].datafd); + hdev->eps[i].datafd = -1; + } + if (hdev->eps[i].statfd != -1) { + (void) close(hdev->eps[i].statfd); + hdev->eps[i].statfd = -1; + } + } +} + +static void +sunos_usb_close_ep0(sunos_dev_handle_priv_t *hdev, sunos_dev_priv_t *dpriv) +{ + if (hdev->eps[0].datafd >= 0) { + close(hdev->eps[0].datafd); + close(hdev->eps[0].statfd); + hdev->eps[0].datafd = -1; + hdev->eps[0].statfd = -1; + } +} + +static uchar_t +sunos_usb_ep_index(uint8_t ep_addr) +{ + return ((ep_addr & LIBUSB_ENDPOINT_ADDRESS_MASK) + + ((ep_addr & LIBUSB_ENDPOINT_DIR_MASK) ? 16 : 0)); +} + +static int +sunos_find_interface(struct libusb_device_handle *hdev, + uint8_t endpoint, uint8_t *interface) +{ + struct libusb_config_descriptor *config; + int r; + int iface_idx; + + r = libusb_get_active_config_descriptor(hdev->dev, &config); + if (r < 0) { + return (LIBUSB_ERROR_INVALID_PARAM); + } + + for (iface_idx = 0; iface_idx < config->bNumInterfaces; iface_idx++) { + const struct libusb_interface *iface = + &config->interface[iface_idx]; + int altsetting_idx; + + for (altsetting_idx = 0; altsetting_idx < iface->num_altsetting; + altsetting_idx++) { + const struct libusb_interface_descriptor *altsetting = + &iface->altsetting[altsetting_idx]; + int ep_idx; + + for (ep_idx = 0; ep_idx < altsetting->bNumEndpoints; + ep_idx++) { + const struct libusb_endpoint_descriptor *ep = + &altsetting->endpoint[ep_idx]; + if (ep->bEndpointAddress == endpoint) { + *interface = iface_idx; + libusb_free_config_descriptor(config); + + return (LIBUSB_SUCCESS); + } + } + } + } + libusb_free_config_descriptor(config); + + return (LIBUSB_ERROR_INVALID_PARAM); +} + +static int +sunos_check_device_and_status_open(struct libusb_device_handle *hdl, + uint8_t ep_addr, int ep_type) +{ + char filename[PATH_MAX + 1], statfilename[PATH_MAX + 1]; + char cfg_num[16], alt_num[16]; + int fd, fdstat, mode; + uint8_t ifc = 0; + uint8_t ep_index; + sunos_dev_handle_priv_t *hpriv; + + usbi_dbg("open ep 0x%02x", ep_addr); + hpriv = (sunos_dev_handle_priv_t *)hdl->os_priv; + ep_index = sunos_usb_ep_index(ep_addr); + /* ep already opened */ + if ((hpriv->eps[ep_index].datafd > 0) && + (hpriv->eps[ep_index].statfd > 0)) { + usbi_dbg("ep 0x%02x already opened, return success", + ep_addr); + + return (0); + } + + if (sunos_find_interface(hdl, ep_addr, &ifc) < 0) { + usbi_dbg("can't find interface for endpoint 0x%02x", + ep_addr); + + return (LIBUSB_ERROR_ACCESS); + } + + /* create filename */ + if (hpriv->config_index > 0) { + (void) snprintf(cfg_num, sizeof (cfg_num), "cfg%d", + hpriv->config_index + 1); + } else { + bzero(cfg_num, sizeof (cfg_num)); + } + + if (hpriv->altsetting[ifc] > 0) { + (void) snprintf(alt_num, sizeof (alt_num), ".%d", + hpriv->altsetting[ifc]); + } else { + bzero(alt_num, sizeof (alt_num)); + } + + (void) snprintf(filename, PATH_MAX, "%s/%sif%d%s%s%d", + hpriv->dpriv->ugenpath, cfg_num, ifc, alt_num, + (ep_addr & LIBUSB_ENDPOINT_DIR_MASK) ? "in" : + "out", (ep_addr & LIBUSB_ENDPOINT_ADDRESS_MASK)); + (void) snprintf(statfilename, PATH_MAX, "%sstat", filename); + + /* + * for interrupt IN endpoints, we need to enable one xfer + * mode before opening the endpoint + */ + if ((ep_type == LIBUSB_TRANSFER_TYPE_INTERRUPT) && + (ep_addr & LIBUSB_ENDPOINT_IN)) { + char control = USB_EP_INTR_ONE_XFER; + int count; + + /* open the status device node for the ep first RDWR */ + if ((fdstat = open(statfilename, O_RDWR)) == -1) { + usbi_dbg("can't open %s RDWR: %d", + statfilename, errno); + } else { + count = write(fdstat, &control, sizeof (control)); + if (count != 1) { + /* this should have worked */ + usbi_dbg("can't write to %s: %d", + statfilename, errno); + (void) close(fdstat); + + return (errno); + } + /* close status node and open xfer node first */ + close (fdstat); + } + } + + /* open the xfer node first in case alt needs to be changed */ + if (ep_type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { + mode = O_RDWR; + } else if (ep_addr & LIBUSB_ENDPOINT_IN) { + mode = O_RDONLY; + } else { + mode = O_WRONLY; + } + + /* + * IMPORTANT: must open data xfer node first and then open stat node + * Otherwise, it will fail on multi-config or multi-altsetting devices + * with "Device Busy" error. See ugen_epxs_switch_cfg_alt() and + * ugen_epxs_check_alt_switch() in ugen driver source code. + */ + if ((fd = open(filename, mode)) == -1) { + usbi_dbg("can't open %s: %d(%s)", filename, errno, + strerror(errno)); + + return (errno); + } + /* open the status node */ + if ((fdstat = open(statfilename, O_RDONLY)) == -1) { + usbi_dbg("can't open %s: %d", statfilename, errno); + + (void) close(fd); + + return (errno); + } + + hpriv->eps[ep_index].datafd = fd; + hpriv->eps[ep_index].statfd = fdstat; + usbi_dbg("ep=0x%02x datafd=%d, statfd=%d", ep_addr, fd, fdstat); + + return (0); +} + +int +sunos_open(struct libusb_device_handle *handle) +{ + sunos_dev_handle_priv_t *hpriv; + sunos_dev_priv_t *dpriv; + int i; + int ret; + + hpriv = (sunos_dev_handle_priv_t *)handle->os_priv; + dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; + hpriv->dpriv = dpriv; + + /* set all file descriptors to "closed" */ + for (i = 0; i < USB_MAXENDPOINTS; i++) { + hpriv->eps[i].datafd = -1; + hpriv->eps[i].statfd = -1; + } + + if ((ret = sunos_usb_open_ep0(hpriv, dpriv)) != LIBUSB_SUCCESS) { + usbi_dbg("fail: %d", ret); + return (ret); + } + + return (LIBUSB_SUCCESS); +} + +void +sunos_close(struct libusb_device_handle *handle) +{ + sunos_dev_handle_priv_t *hpriv; + sunos_dev_priv_t *dpriv; + + usbi_dbg(""); + if (!handle) { + return; + } + + hpriv = (sunos_dev_handle_priv_t *)handle->os_priv; + if (!hpriv) { + return; + } + dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; + if (!dpriv) { + return; + } + + sunos_usb_close_all_eps(hpriv); + sunos_usb_close_ep0(hpriv, dpriv); +} + +int +sunos_get_device_descriptor(struct libusb_device *dev, uint8_t *buf, + int *host_endian) +{ + sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; + + memcpy(buf, &dpriv->dev_descr, LIBUSB_DT_DEVICE_SIZE); + *host_endian = 0; + + return (LIBUSB_SUCCESS); +} + +int +sunos_get_active_config_descriptor(struct libusb_device *dev, + uint8_t *buf, size_t len, int *host_endian) +{ + sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; + struct libusb_config_descriptor *cfg; + int proplen; + di_node_t node; + uint8_t *rdata; + + /* + * Keep raw configuration descriptors updated, in case config + * has ever been changed through setCfg. + */ + if ((node = di_init(dpriv->phypath, DINFOCPYALL)) == DI_NODE_NIL) { + usbi_dbg("di_int() failed: %s", strerror(errno)); + return (LIBUSB_ERROR_IO); + } + proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, + "usb-raw-cfg-descriptors", &rdata); + if (proplen <= 0) { + usbi_dbg("can't find raw config descriptors"); + + return (LIBUSB_ERROR_IO); + } + dpriv->raw_cfgdescr = realloc(dpriv->raw_cfgdescr, proplen); + if (dpriv->raw_cfgdescr == NULL) { + return (LIBUSB_ERROR_NO_MEM); + } else { + bcopy(rdata, dpriv->raw_cfgdescr, proplen); + dpriv->cfgvalue = ((struct libusb_config_descriptor *) + rdata)->bConfigurationValue; + } + di_fini(node); + + cfg = (struct libusb_config_descriptor *)dpriv->raw_cfgdescr; + len = MIN(len, libusb_le16_to_cpu(cfg->wTotalLength)); + memcpy(buf, dpriv->raw_cfgdescr, len); + *host_endian = 0; + usbi_dbg("path:%s len %d", dpriv->phypath, len); + + return (len); +} + +int +sunos_get_config_descriptor(struct libusb_device *dev, uint8_t idx, + uint8_t *buf, size_t len, int *host_endian) +{ + /* XXX */ + return(sunos_get_active_config_descriptor(dev, buf, len, host_endian)); +} + +int +sunos_get_configuration(struct libusb_device_handle *handle, int *config) +{ + sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; + + *config = dpriv->cfgvalue; + + usbi_dbg("bConfigurationValue %d", *config); + + return (LIBUSB_SUCCESS); +} + +int +sunos_set_configuration(struct libusb_device_handle *handle, int config) +{ + sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; + sunos_dev_handle_priv_t *hpriv; + + usbi_dbg("bConfigurationValue %d", config); + hpriv = (sunos_dev_handle_priv_t *)handle->os_priv; + + if (dpriv->ugenpath == NULL) + return (LIBUSB_ERROR_NOT_SUPPORTED); + + if (config < 1 || config > dpriv->dev_descr.bNumConfigurations) + return (LIBUSB_ERROR_INVALID_PARAM); + + dpriv->cfgvalue = config; + hpriv->config_index = config - 1; + + return (LIBUSB_SUCCESS); +} + +int +sunos_claim_interface(struct libusb_device_handle *handle, int iface) +{ + usbi_dbg("iface %d", iface); + if (iface < 0) { + return (LIBUSB_ERROR_INVALID_PARAM); + } + + return (LIBUSB_SUCCESS); +} + +int +sunos_release_interface(struct libusb_device_handle *handle, int iface) +{ + sunos_dev_handle_priv_t *hpriv = + (sunos_dev_handle_priv_t *)handle->os_priv; + + usbi_dbg("iface %d", iface); + if (iface < 0) { + return (LIBUSB_ERROR_INVALID_PARAM); + } + + /* XXX: can we release it? */ + hpriv->altsetting[iface] = 0; + + return (LIBUSB_SUCCESS); +} + +int +sunos_set_interface_altsetting(struct libusb_device_handle *handle, int iface, + int altsetting) +{ + sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; + sunos_dev_handle_priv_t *hpriv = + (sunos_dev_handle_priv_t *)handle->os_priv; + + usbi_dbg("iface %d, setting %d", iface, altsetting); + + if (iface < 0 || altsetting < 0) { + return (LIBUSB_ERROR_INVALID_PARAM); + } + if (dpriv->ugenpath == NULL) + return (LIBUSB_ERROR_NOT_FOUND); + + /* XXX: can we switch altsetting? */ + hpriv->altsetting[iface] = altsetting; + + return (LIBUSB_SUCCESS); +} + +static void +usb_dump_data(unsigned char *data, size_t size) +{ + int i; + + if (getenv("LIBUSB_DEBUG") == NULL) { + return; + } + + (void) fprintf(stderr, "data dump:"); + for (i = 0; i < size; i++) { + if (i % 16 == 0) { + (void) fprintf(stderr, "\n%08x ", i); + } + (void) fprintf(stderr, "%02x ", (uchar_t)data[i]); + } + (void) fprintf(stderr, "\n"); +} + +static void +sunos_async_callback(union sigval arg) +{ + struct sunos_transfer_priv *tpriv = + (struct sunos_transfer_priv *)arg.sival_ptr; + struct libusb_transfer *xfer = tpriv->transfer; + struct aiocb *aiocb = &tpriv->aiocb; + int ret; + sunos_dev_handle_priv_t *hpriv; + uint8_t ep; + + hpriv = (sunos_dev_handle_priv_t *)xfer->dev_handle->os_priv; + ep = sunos_usb_ep_index(xfer->endpoint); + + ret = aio_error(aiocb); + if (ret != 0) { + xfer->status = sunos_usb_get_status(hpriv->eps[ep].statfd); + } else { + xfer->actual_length = + LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)->transferred = + aio_return(aiocb); + } + + usb_dump_data(xfer->buffer, xfer->actual_length); + + usbi_dbg("ret=%d, len=%d, actual_len=%d", ret, xfer->length, + xfer->actual_length); + + /* async notification */ + usbi_signal_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)); +} + +static int +sunos_do_async_io(struct libusb_transfer *transfer) +{ + int ret = -1; + struct aiocb *aiocb; + sunos_dev_handle_priv_t *hpriv; + uint8_t ep; + struct sunos_transfer_priv *tpriv; + + usbi_dbg(""); + + tpriv = usbi_transfer_get_os_priv(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)); + hpriv = (sunos_dev_handle_priv_t *)transfer->dev_handle->os_priv; + ep = sunos_usb_ep_index(transfer->endpoint); + + tpriv->transfer = transfer; + aiocb = &tpriv->aiocb; + bzero(aiocb, sizeof (*aiocb)); + aiocb->aio_fildes = hpriv->eps[ep].datafd; + aiocb->aio_buf = transfer->buffer; + aiocb->aio_nbytes = transfer->length; + aiocb->aio_lio_opcode = + ((transfer->endpoint & LIBUSB_ENDPOINT_DIR_MASK) == + LIBUSB_ENDPOINT_IN) ? LIO_READ:LIO_WRITE; + aiocb->aio_sigevent.sigev_notify = SIGEV_THREAD; + aiocb->aio_sigevent.sigev_value.sival_ptr = tpriv; + aiocb->aio_sigevent.sigev_notify_function = sunos_async_callback; + + if (aiocb->aio_lio_opcode == LIO_READ) { + ret = aio_read(aiocb); + } else { + ret = aio_write(aiocb); + } + + return (ret); +} + +/* return the number of bytes read/written */ +static int +usb_do_io(int fd, int stat_fd, char *data, size_t size, int flag, int *status) +{ + int error; + int ret = -1; + + usbi_dbg("usb_do_io(): datafd=%d statfd=%d size=0x%x flag=%s", + fd, stat_fd, size, flag? "WRITE":"READ"); + + switch (flag) { + case READ: + errno = 0; + ret = read(fd, data, size); + usb_dump_data(data, size); + break; + case WRITE: + usb_dump_data(data, size); + errno = 0; + ret = write(fd, data, size); + break; + } + + usbi_dbg("usb_do_io(): amount=%d", ret); + + if (ret < 0) { + int save_errno = errno; + + usbi_dbg("TID=%x io %s errno=%d(%s) ret=%d", pthread_self(), + flag?"WRITE":"READ", errno, strerror(errno), ret); + + /* sunos_usb_get_status will do a read and overwrite errno */ + error = sunos_usb_get_status(stat_fd); + usbi_dbg("io status=%d errno=%d(%s)", error, + save_errno, strerror(save_errno)); + + if (status) { + *status = save_errno; + } + + return (save_errno); + + } else if (status) { + *status = 0; + } + + return (ret); +} + +static int +solaris_submit_ctrl_on_default(struct libusb_transfer *transfer) +{ + int ret = -1, setup_ret; + int status; + sunos_dev_handle_priv_t *hpriv; + struct libusb_device_handle *hdl = transfer->dev_handle; + uint16_t wLength; + uint8_t *data = transfer->buffer; + + hpriv = (sunos_dev_handle_priv_t *)hdl->os_priv; + wLength = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; + + if (hpriv->eps[0].datafd == -1) { + usbi_dbg("ep0 not opened"); + + return (LIBUSB_ERROR_NOT_FOUND); + } + + if ((data[0] & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) { + usbi_dbg("IN request"); + ret = usb_do_io(hpriv->eps[0].datafd, + hpriv->eps[0].statfd, (char *)data, LIBUSB_CONTROL_SETUP_SIZE, + WRITE, (int *)&status); + } else { + usbi_dbg("OUT request"); + ret = usb_do_io(hpriv->eps[0].datafd, hpriv->eps[0].statfd, + transfer->buffer, transfer->length, WRITE, + (int *)&transfer->status); + } + + setup_ret = ret; + if (ret < LIBUSB_CONTROL_SETUP_SIZE) { + usbi_dbg("error sending control msg: %d", ret); + + return (LIBUSB_ERROR_IO); + } + + ret = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; + + /* Read the remaining bytes for IN request */ + if ((wLength) && ((data[0] & LIBUSB_ENDPOINT_DIR_MASK) == + LIBUSB_ENDPOINT_IN)) { + usbi_dbg("DATA: %d", transfer->length - setup_ret); + ret = usb_do_io(hpriv->eps[0].datafd, + hpriv->eps[0].statfd, + (char *)transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, + wLength, READ, (int *)&transfer->status); + } + + if (ret >= 0) { + transfer->actual_length = ret; + LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)->transferred = ret; + } + usbi_dbg("Done: ctrl data bytes %d", ret); + + /* sync transfer handling */ + ret = usbi_handle_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer), + transfer->status); + + return (ret); +} + +int +sunos_clear_halt(struct libusb_device_handle *handle, uint8_t endpoint) +{ + int ret; + + usbi_dbg("endpoint=0x%02x", endpoint); + + ret = libusb_control_transfer(handle, LIBUSB_ENDPOINT_OUT | + LIBUSB_RECIPIENT_ENDPOINT | LIBUSB_REQUEST_TYPE_STANDARD, + LIBUSB_REQUEST_CLEAR_FEATURE, 0, endpoint, NULL, 0, 1000); + + usbi_dbg("ret=%d", ret); + + return (ret); +} + +int +sunos_reset_device(struct libusb_device_handle *handle) +{ + usbi_dbg(""); + + return (LIBUSB_ERROR_NOT_SUPPORTED); +} + +void +sunos_destroy_device(struct libusb_device *dev) +{ + sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; + + usbi_dbg(""); + + free(dpriv->raw_cfgdescr); + free(dpriv->ugenpath); + free(dpriv->phypath); +} + +int +sunos_submit_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer; + struct libusb_device_handle *hdl; + int err = 0; + + transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + hdl = transfer->dev_handle; + + err = sunos_check_device_and_status_open(hdl, + transfer->endpoint, transfer->type); + if (err < 0) { + + return (_errno_to_libusb(err)); + } + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + /* sync transfer */ + usbi_dbg("CTRL transfer: %d", transfer->length); + err = solaris_submit_ctrl_on_default(transfer); + break; + + case LIBUSB_TRANSFER_TYPE_BULK: + /* fallthru */ + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + if (transfer->type == LIBUSB_TRANSFER_TYPE_BULK) + usbi_dbg("BULK transfer: %d", transfer->length); + else + usbi_dbg("INTR transfer: %d", transfer->length); + err = sunos_do_async_io(transfer); + break; + + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + /* Isochronous/Stream is not supported */ + + /* fallthru */ + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) + usbi_dbg("ISOC transfer: %d", transfer->length); + else + usbi_dbg("BULK STREAM transfer: %d", transfer->length); + err = LIBUSB_ERROR_NOT_SUPPORTED; + break; + } + + return (err); +} + +int +sunos_cancel_transfer(struct usbi_transfer *itransfer) +{ + sunos_xfer_priv_t *tpriv; + sunos_dev_handle_priv_t *hpriv; + struct libusb_transfer *transfer; + struct aiocb *aiocb; + uint8_t ep; + int ret; + + tpriv = usbi_transfer_get_os_priv(itransfer); + aiocb = &tpriv->aiocb; + transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + hpriv = (sunos_dev_handle_priv_t *)transfer->dev_handle->os_priv; + ep = sunos_usb_ep_index(transfer->endpoint); + + ret = aio_cancel(hpriv->eps[ep].datafd, aiocb); + + usbi_dbg("aio->fd=%d fd=%d ret = %d, %s", aiocb->aio_fildes, + hpriv->eps[ep].datafd, ret, (ret == AIO_CANCELED)? + strerror(0):strerror(errno)); + + if (ret != AIO_CANCELED) { + ret = _errno_to_libusb(errno); + } else { + /* + * we don't need to call usbi_handle_transfer_cancellation(), + * because we'll handle everything in sunos_async_callback. + */ + ret = LIBUSB_SUCCESS; + } + + return (ret); +} + +void +sunos_clear_transfer_priv(struct usbi_transfer *itransfer) +{ + usbi_dbg(""); + + /* Nothing to do */ +} + +int +sunos_handle_transfer_completion(struct usbi_transfer *itransfer) +{ + return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED); +} + +int +sunos_clock_gettime(int clkid, struct timespec *tp) +{ + usbi_dbg("clock %d", clkid); + + if (clkid == USBI_CLOCK_REALTIME) + return clock_gettime(CLOCK_REALTIME, tp); + + if (clkid == USBI_CLOCK_MONOTONIC) + return clock_gettime(CLOCK_MONOTONIC, tp); + + return (LIBUSB_ERROR_INVALID_PARAM); +} + +int +_errno_to_libusb(int err) +{ + usbi_dbg("error: %s (%d)", strerror(err), err); + + switch (err) { + case EIO: + return (LIBUSB_ERROR_IO); + case EACCES: + return (LIBUSB_ERROR_ACCESS); + case ENOENT: + return (LIBUSB_ERROR_NO_DEVICE); + case ENOMEM: + return (LIBUSB_ERROR_NO_MEM); + case ETIMEDOUT: + return (LIBUSB_ERROR_TIMEOUT); + } + + return (LIBUSB_ERROR_OTHER); +} + +/* + * sunos_usb_get_status: + * gets status of endpoint + * + * Returns: ugen's last cmd status + */ +static int +sunos_usb_get_status(int fd) +{ + int status, ret; + + usbi_dbg("sunos_usb_get_status(): fd=%d", fd); + + ret = read(fd, &status, sizeof (status)); + if (ret == sizeof (status)) { + switch (status) { + case USB_LC_STAT_NOERROR: + usbi_dbg("No Error"); + break; + case USB_LC_STAT_CRC: + usbi_dbg("CRC Timeout Detected\n"); + break; + case USB_LC_STAT_BITSTUFFING: + usbi_dbg("Bit Stuffing Violation\n"); + break; + case USB_LC_STAT_DATA_TOGGLE_MM: + usbi_dbg("Data Toggle Mismatch\n"); + break; + case USB_LC_STAT_STALL: + usbi_dbg("End Point Stalled\n"); + break; + case USB_LC_STAT_DEV_NOT_RESP: + usbi_dbg("Device is Not Responding\n"); + break; + case USB_LC_STAT_PID_CHECKFAILURE: + usbi_dbg("PID Check Failure\n"); + break; + case USB_LC_STAT_UNEXP_PID: + usbi_dbg("Unexpected PID\n"); + break; + case USB_LC_STAT_DATA_OVERRUN: + usbi_dbg("Data Exceeded Size\n"); + break; + case USB_LC_STAT_DATA_UNDERRUN: + usbi_dbg("Less data received\n"); + break; + case USB_LC_STAT_BUFFER_OVERRUN: + usbi_dbg("Buffer Size Exceeded\n"); + break; + case USB_LC_STAT_BUFFER_UNDERRUN: + usbi_dbg("Buffer Underrun\n"); + break; + case USB_LC_STAT_TIMEOUT: + usbi_dbg("Command Timed Out\n"); + break; + case USB_LC_STAT_NOT_ACCESSED: + usbi_dbg("Not Accessed by h/w\n"); + break; + case USB_LC_STAT_UNSPECIFIED_ERR: + usbi_dbg("Unspecified Error\n"); + break; + case USB_LC_STAT_NO_BANDWIDTH: + usbi_dbg("No Bandwidth\n"); + break; + case USB_LC_STAT_HW_ERR: + usbi_dbg("Host Controller h/w Error\n"); + break; + case USB_LC_STAT_SUSPENDED: + usbi_dbg("Device was Suspended\n"); + break; + case USB_LC_STAT_DISCONNECTED: + usbi_dbg("Device was Disconnected\n"); + break; + case USB_LC_STAT_INTR_BUF_FULL: + usbi_dbg("Interrupt buffer was full\n"); + break; + case USB_LC_STAT_INVALID_REQ: + usbi_dbg("Request was Invalid\n"); + break; + case USB_LC_STAT_INTERRUPTED: + usbi_dbg("Request was Interrupted\n"); + break; + case USB_LC_STAT_NO_RESOURCES: + usbi_dbg("No resources available for " + "request\n"); + break; + case USB_LC_STAT_INTR_POLLING_FAILED: + usbi_dbg("Failed to Restart Poll"); + break; + default: + usbi_dbg("Error Not Determined %d\n", + status); + break; + } + } else { + usbi_dbg("read stat error: %s",strerror(errno)); + status = -1; + } + + return (status); +} + +const struct usbi_os_backend sunos_backend = { + .name = "Solaris", + .caps = 0, + .init = sunos_init, + .exit = sunos_exit, + .get_device_list = sunos_get_device_list, + .get_device_descriptor = sunos_get_device_descriptor, + .get_active_config_descriptor = sunos_get_active_config_descriptor, + .get_config_descriptor = sunos_get_config_descriptor, + .hotplug_poll = NULL, + .open = sunos_open, + .close = sunos_close, + .get_configuration = sunos_get_configuration, + .set_configuration = sunos_set_configuration, + + .claim_interface = sunos_claim_interface, + .release_interface = sunos_release_interface, + .set_interface_altsetting = sunos_set_interface_altsetting, + .clear_halt = sunos_clear_halt, + .reset_device = sunos_reset_device, /* TODO */ + .alloc_streams = NULL, + .free_streams = NULL, + .kernel_driver_active = NULL, + .detach_kernel_driver = NULL, + .attach_kernel_driver = NULL, + .destroy_device = sunos_destroy_device, + .submit_transfer = sunos_submit_transfer, + .cancel_transfer = sunos_cancel_transfer, + .handle_events = NULL, + .clear_transfer_priv = sunos_clear_transfer_priv, + .handle_transfer_completion = sunos_handle_transfer_completion, + .clock_gettime = sunos_clock_gettime, + .device_priv_size = sizeof(sunos_dev_priv_t), + .device_handle_priv_size = sizeof(sunos_dev_handle_priv_t), + .transfer_priv_size = sizeof(sunos_xfer_priv_t), +}; diff --git a/libusb/os/sunos_usb.h b/libusb/os/sunos_usb.h new file mode 100644 index 000000000..574166031 --- /dev/null +++ b/libusb/os/sunos_usb.h @@ -0,0 +1,74 @@ +/* + * + * Copyright (c) 2016, Oracle and/or its affiliates. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LIBUSB_SUNOS_H +#define LIBUSB_SUNOS_H + +#include +#include +#include "libusbi.h" + +#define READ 0 +#define WRITE 1 + +typedef struct sunos_device_priv { + uint8_t cfgvalue; /* active config value */ + uint8_t *raw_cfgdescr; /* active config descriptor */ + struct libusb_device_descriptor dev_descr; /* usb device descriptor */ + char *ugenpath; /* name of the ugen(4) node */ + char *phypath; /* physical path */ +} sunos_dev_priv_t; + +typedef struct endpoint { + int datafd; /* data file */ + int statfd; /* state file */ +} sunos_ep_priv_t; + +typedef struct sunos_device_handle_priv { + uint8_t altsetting[USB_MAXINTERFACES]; /* a interface's alt */ + uint8_t config_index; + sunos_ep_priv_t eps[USB_MAXENDPOINTS]; + sunos_dev_priv_t *dpriv; /* device private */ +} sunos_dev_handle_priv_t; + +typedef struct sunos_transfer_priv { + struct aiocb aiocb; + struct libusb_transfer *transfer; +} sunos_xfer_priv_t; + +struct node_args { + struct libusb_context *ctx; + struct discovered_devs **discdevs; + const char *last_ugenpath; + di_devlink_handle_t dlink_hdl; +}; + +struct devlink_cbarg { + struct node_args *nargs; /* di node walk arguments */ + di_node_t myself; /* the di node */ + di_minor_t minor; +}; + +/* AIO callback args */ +struct aio_callback_args{ + struct libusb_transfer *transfer; + struct aiocb aiocb; +}; + +#endif /* LIBUSB_SUNOS_H */ diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 3790b5fd9..99f342290 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11123 +#define LIBUSB_NANO 11124 From bb014d8dc7748854a735eb69319d1577f2dde24a Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Sun, 24 Jul 2016 20:01:15 -0600 Subject: [PATCH 207/222] changelog: add entry for new solaris backend Signed-off-by: Nathan Hjelm --- ChangeLog | 1 + libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 15d6903df..3b07a8f50 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ visit: http://log.libusb.info * Darwin: Ignore root hub simulation devices * Darwin: Improved support for OS X El Capitan * Linux: Support preallocating kernel memory for zerocopy USB +* Solaris: Add solaris backend * Windows: Add Visual Studio 2015 support * Prevent attempts to recursively hande events * Fix race condition in handle_timeout() diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 99f342290..aa2b6a349 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11124 +#define LIBUSB_NANO 11125 From 5ffcedfbca8cd7e7e25e373c14f286b1b2d3d0be Mon Sep 17 00:00:00 2001 From: Anil Nair Date: Sun, 24 Jul 2016 21:12:26 +0530 Subject: [PATCH 208/222] Updated TODO link Closes #198 Signed-off-by: Nathan Hjelm --- TODO | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/TODO b/TODO index 19dd1d0e6..1e13760ef 100644 --- a/TODO +++ b/TODO @@ -1,2 +1,2 @@ Please see the libusb roadmap by visiting: -https://github.com/libusb/libusb/issues/milestones?direction=asc&sort=due_date +https://github.com/libusb/libusb/milestones?direction=asc&sort=due_date&state=open diff --git a/libusb/version_nano.h b/libusb/version_nano.h index aa2b6a349..917591a98 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11125 +#define LIBUSB_NANO 11126 From d682143729faf08d8b508041b1118e570f4eff6e Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Sun, 24 Jul 2016 20:04:34 -0600 Subject: [PATCH 209/222] on to 1.0.21-rc2 Signed-off-by: Nathan Hjelm --- libusb/version.h | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/version.h b/libusb/version.h index e1a28e0d8..4ee1f278c 100644 --- a/libusb/version.h +++ b/libusb/version.h @@ -14,5 +14,5 @@ #endif /* LIBUSB_RC is the release candidate suffix. Should normally be empty. */ #ifndef LIBUSB_RC -#define LIBUSB_RC "-rc1" +#define LIBUSB_RC "-rc2" #endif diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 917591a98..a806b19ac 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11126 +#define LIBUSB_NANO 11127 From 2682e21d3d7e1e5ebd6dfe07f193efe48caa3e14 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 10 Aug 2016 12:17:00 +0200 Subject: [PATCH 210/222] Revert "io: Fix race condition in handle_timeout()" This reverts commit bd8d5b5019b72b2dc2d074d96c9992e2f6e7e0b7. Chris Dickens and me have been working on a patch-set refactoring the transfer flag handling which fixes this differently. Revert this commit so that the refactoring changes can be merged cleanly. Signed-off-by: Hans de Goede --- libusb/io.c | 57 +++++++++++++++---------------------------- libusb/version_nano.h | 2 +- 2 files changed, 21 insertions(+), 38 deletions(-) diff --git a/libusb/io.c b/libusb/io.c index 894446150..4d03b8b77 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1530,34 +1530,6 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer) return r; } -static int cancel_transfer_locked(struct libusb_transfer *transfer) -{ - struct usbi_transfer *itransfer = - LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); - int r; - if (!(itransfer->flags & USBI_TRANSFER_IN_FLIGHT) - || (itransfer->flags & USBI_TRANSFER_CANCELLING)) { - return LIBUSB_ERROR_NOT_FOUND; - } - - r = usbi_backend->cancel_transfer(itransfer); - if (r < 0) { - if (r != LIBUSB_ERROR_NOT_FOUND && - r != LIBUSB_ERROR_NO_DEVICE) - usbi_err(TRANSFER_CTX(transfer), - "cancel transfer failed error %d", r); - else - usbi_dbg("cancel transfer failed error %d", r); - - if (r == LIBUSB_ERROR_NO_DEVICE) - itransfer->flags |= USBI_TRANSFER_DEVICE_DISAPPEARED; - } - - itransfer->flags |= USBI_TRANSFER_CANCELLING; - - return r; -} - /** \ingroup libusb_asyncio * Asynchronously cancel a previously submitted transfer. * This function returns immediately, but this does not indicate cancellation @@ -1581,9 +1553,27 @@ int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer) usbi_dbg("transfer %p", transfer ); usbi_mutex_lock(&itransfer->lock); usbi_mutex_lock(&itransfer->flags_lock); + if (!(itransfer->flags & USBI_TRANSFER_IN_FLIGHT) + || (itransfer->flags & USBI_TRANSFER_CANCELLING)) { + r = LIBUSB_ERROR_NOT_FOUND; + goto out; + } + r = usbi_backend->cancel_transfer(itransfer); + if (r < 0) { + if (r != LIBUSB_ERROR_NOT_FOUND && + r != LIBUSB_ERROR_NO_DEVICE) + usbi_err(TRANSFER_CTX(transfer), + "cancel transfer failed error %d", r); + else + usbi_dbg("cancel transfer failed error %d", r); - r = cancel_transfer_locked(transfer); + if (r == LIBUSB_ERROR_NO_DEVICE) + itransfer->flags |= USBI_TRANSFER_DEVICE_DISAPPEARED; + } + + itransfer->flags |= USBI_TRANSFER_CANCELLING; +out: usbi_mutex_unlock(&itransfer->flags_lock); usbi_mutex_unlock(&itransfer->lock); return r; @@ -1977,20 +1967,13 @@ static void handle_timeout(struct usbi_transfer *itransfer) USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); int r; - usbi_mutex_lock(&itransfer->lock); - usbi_mutex_lock(&itransfer->flags_lock); - itransfer->flags |= USBI_TRANSFER_TIMEOUT_HANDLED; - r = cancel_transfer_locked(transfer); - + r = libusb_cancel_transfer(transfer); if (r == 0) itransfer->flags |= USBI_TRANSFER_TIMED_OUT; else usbi_warn(TRANSFER_CTX(transfer), "async cancel failed %d errno=%d", r, errno); - - usbi_mutex_unlock(&itransfer->flags_lock); - usbi_mutex_unlock(&itransfer->lock); } static int handle_timeouts_locked(struct libusb_context *ctx) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index a806b19ac..e92bc7130 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11127 +#define LIBUSB_NANO 11128 From a5302ff86db391e6797a32693c242ddade5a09c2 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Mon, 26 Oct 2015 14:11:53 +0100 Subject: [PATCH 211/222] core: Change event handling lock to traditional (non-recursive) type The event handling lock was previously required to be of the recursive type because the libusb_close() path requires the lock and may be called by a thread that is handling events (e.g. from within a transfer or hotplug callback). With commit 960a6e75, it is possible to determine whether the current function is being called from an event handling context, thus the recursive lock type is no longer necessary. References: * http://libusb.org/ticket/82 * 74282582cc879f091ad1d847411337bc3fa78a2b * c775c2f43037cd235b65410583179195e25f9c4a Signed-off-by: Chris Dickens Reviewed-by: Hans de Goede [hdegoede@redhat.com: rebase on top of current master] Signed-off-by: Hans de Goede --- libusb/core.c | 60 ++++++++++++++++++++----------------- libusb/io.c | 2 +- libusb/os/threads_posix.c | 22 -------------- libusb/os/threads_posix.h | 2 -- libusb/os/threads_windows.h | 3 -- libusb/version_nano.h | 2 +- 6 files changed, 34 insertions(+), 57 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 06342c87d..2e3816cc6 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1340,8 +1340,6 @@ static void do_close(struct libusb_context *ctx, struct usbi_transfer *itransfer; struct usbi_transfer *tmp; - libusb_lock_events(ctx); - /* remove any transfers in flight that are for this device */ usbi_mutex_lock(&ctx->flying_transfers_lock); @@ -1380,8 +1378,6 @@ static void do_close(struct libusb_context *ctx, } usbi_mutex_unlock(&ctx->flying_transfers_lock); - libusb_unlock_events(ctx); - usbi_mutex_lock(&ctx->open_devs_lock); list_del(&dev_handle->list); usbi_mutex_unlock(&ctx->open_devs_lock); @@ -1406,6 +1402,7 @@ static void do_close(struct libusb_context *ctx, void API_EXPORTED libusb_close(libusb_device_handle *dev_handle) { struct libusb_context *ctx; + int handling_events; int pending_events; if (!dev_handle) @@ -1413,39 +1410,46 @@ void API_EXPORTED libusb_close(libusb_device_handle *dev_handle) usbi_dbg(""); ctx = HANDLE_CTX(dev_handle); + handling_events = usbi_handling_events(ctx); /* Similarly to libusb_open(), we want to interrupt all event handlers * at this point. More importantly, we want to perform the actual close of * the device while holding the event handling lock (preventing any other * thread from doing event handling) because we will be removing a file - * descriptor from the polling loop. */ - - /* Record that we are closing a device. - * Only signal an event if there are no prior pending events. */ - usbi_mutex_lock(&ctx->event_data_lock); - pending_events = usbi_pending_events(ctx); - ctx->device_close++; - if (!pending_events) - usbi_signal_event(ctx); - usbi_mutex_unlock(&ctx->event_data_lock); - - /* take event handling lock */ - libusb_lock_events(ctx); + * descriptor from the polling loop. If this is being called by the current + * event handler, we can bypass the interruption code because we already + * hold the event handling lock. */ + + if (!handling_events) { + /* Record that we are closing a device. + * Only signal an event if there are no prior pending events. */ + usbi_mutex_lock(&ctx->event_data_lock); + pending_events = usbi_pending_events(ctx); + ctx->device_close++; + if (!pending_events) + usbi_signal_event(ctx); + usbi_mutex_unlock(&ctx->event_data_lock); + + /* take event handling lock */ + libusb_lock_events(ctx); + } /* Close the device */ do_close(ctx, dev_handle); - /* We're done with closing this device. - * Clear the event pipe if there are no further pending events. */ - usbi_mutex_lock(&ctx->event_data_lock); - ctx->device_close--; - pending_events = usbi_pending_events(ctx); - if (!pending_events) - usbi_clear_event(ctx); - usbi_mutex_unlock(&ctx->event_data_lock); - - /* Release event handling lock and wake up event waiters */ - libusb_unlock_events(ctx); + if (!handling_events) { + /* We're done with closing this device. + * Clear the event pipe if there are no further pending events. */ + usbi_mutex_lock(&ctx->event_data_lock); + ctx->device_close--; + pending_events = usbi_pending_events(ctx); + if (!pending_events) + usbi_clear_event(ctx); + usbi_mutex_unlock(&ctx->event_data_lock); + + /* Release event handling lock and wake up event waiters */ + libusb_unlock_events(ctx); + } } /** \ingroup libusb_dev diff --git a/libusb/io.c b/libusb/io.c index 4d03b8b77..3bd167560 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1125,7 +1125,7 @@ int usbi_io_init(struct libusb_context *ctx) int r; usbi_mutex_init(&ctx->flying_transfers_lock); - usbi_mutex_init_recursive(&ctx->events_lock); + usbi_mutex_init(&ctx->events_lock); usbi_mutex_init(&ctx->event_waiters_lock); usbi_cond_init(&ctx->event_waiters_cond); usbi_mutex_init(&ctx->event_data_lock); diff --git a/libusb/os/threads_posix.c b/libusb/os/threads_posix.c index 3908907cf..a4f270bbe 100644 --- a/libusb/os/threads_posix.c +++ b/libusb/os/threads_posix.c @@ -37,28 +37,6 @@ #include "threads_posix.h" #include "libusbi.h" -int usbi_mutex_init_recursive(pthread_mutex_t *mutex) -{ - int err; - pthread_mutexattr_t attr; - - err = pthread_mutexattr_init(&attr); - if (err != 0) - return err; - - /* mutexattr_settype requires _GNU_SOURCE or _XOPEN_SOURCE >= 500 on Linux */ - err = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - if (err != 0) - goto finish; - - err = pthread_mutex_init(mutex, &attr); - -finish: - pthread_mutexattr_destroy(&attr); - - return err; -} - int usbi_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timeval *tv) { diff --git a/libusb/os/threads_posix.h b/libusb/os/threads_posix.h index 2abb820f3..7ec70b1b5 100644 --- a/libusb/os/threads_posix.h +++ b/libusb/os/threads_posix.h @@ -50,8 +50,6 @@ #define usbi_tls_key_set pthread_setspecific #define usbi_tls_key_delete pthread_key_delete -int usbi_mutex_init_recursive(pthread_mutex_t *mutex); - int usbi_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timeval *tv); diff --git a/libusb/os/threads_windows.h b/libusb/os/threads_windows.h index 8b7faecb5..e97ee7875 100644 --- a/libusb/os/threads_windows.h +++ b/libusb/os/threads_windows.h @@ -71,9 +71,6 @@ void *usbi_tls_key_get(usbi_tls_key_t key); int usbi_tls_key_set(usbi_tls_key_t key, void *value); int usbi_tls_key_delete(usbi_tls_key_t key); -// all Windows mutexes are recursive -#define usbi_mutex_init_recursive usbi_mutex_init - int usbi_get_tid(void); #endif /* LIBUSB_THREADS_WINDOWS_H */ diff --git a/libusb/version_nano.h b/libusb/version_nano.h index e92bc7130..74e5d3b94 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11128 +#define LIBUSB_NANO 11129 From e9d9c7382c596aeba67849d110eca0d28ed20386 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 6 Jun 2016 16:40:54 +0200 Subject: [PATCH 212/222] wince: Do not differ between cancel / timeout ourselves (itransfer->flags & USBI_TRANSFER_TIMED_OUT) is already checked by usbi_handle_transfer_cancellation(), which wince_transfer_callback() will call when status == LIBUSB_TRANSFER_CANCELLED. Leave this up to the core, so that future changes to timeout handling do no break wince. Signed-off-by: Hans de Goede --- Note: untested --- libusb/os/wince_usb.c | 9 ++------- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/libusb/os/wince_usb.c b/libusb/os/wince_usb.c index 85c584be7..89b5e657c 100644 --- a/libusb/os/wince_usb.c +++ b/libusb/os/wince_usb.c @@ -720,13 +720,8 @@ static void wince_transfer_callback( status = LIBUSB_TRANSFER_TIMED_OUT; break; case ERROR_OPERATION_ABORTED: - if (itransfer->flags & USBI_TRANSFER_TIMED_OUT) { - usbi_dbg("detected timeout"); - status = LIBUSB_TRANSFER_TIMED_OUT; - } else { - usbi_dbg("detected operation aborted"); - status = LIBUSB_TRANSFER_CANCELLED; - } + usbi_dbg("detected operation aborted"); + status = LIBUSB_TRANSFER_CANCELLED; break; default: usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error: %s", windows_error_str(io_result)); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 74e5d3b94..335ae072d 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11129 +#define LIBUSB_NANO 11130 From 4eaabb12d877da7ce14733285064d8ac6e088da6 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 6 Jun 2016 16:43:18 +0200 Subject: [PATCH 213/222] winnt: Do not differ between cancel / timeout ourselves (itransfer->flags & USBI_TRANSFER_TIMED_OUT) is already checked by usbi_handle_transfer_cancellation(), make windows_transfer_callback() call usbi_handle_transfer_cancellation() when status == LIBUSB_TRANSFER_CANCELLED like all other os backends do, and leave USBI_TRANSFER_TIMED_OUT handling up to the core, so that future changes to timeout handling do no break winnt. Signed-off-by: Hans de Goede --- Note: untested --- libusb/os/windows_nt_common.c | 16 +++++++--------- libusb/version_nano.h | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libusb/os/windows_nt_common.c b/libusb/os/windows_nt_common.c index 93e6278cd..68eb4a792 100644 --- a/libusb/os/windows_nt_common.c +++ b/libusb/os/windows_nt_common.c @@ -501,14 +501,9 @@ static void windows_transfer_callback(struct usbi_transfer *itransfer, uint32_t istatus = windows_copy_transfer_data(itransfer, io_size); if (istatus != LIBUSB_TRANSFER_COMPLETED) usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus); - if (itransfer->flags & USBI_TRANSFER_TIMED_OUT) { - usbi_dbg("detected timeout"); - status = LIBUSB_TRANSFER_TIMED_OUT; - } - else { - usbi_dbg("detected operation aborted"); - status = LIBUSB_TRANSFER_CANCELLED; - } + + usbi_dbg("detected operation aborted"); + status = LIBUSB_TRANSFER_CANCELLED; break; default: usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %u: %s", io_result, windows_error_str(io_result)); @@ -516,7 +511,10 @@ static void windows_transfer_callback(struct usbi_transfer *itransfer, uint32_t break; } windows_clear_transfer_priv(itransfer); // Cancel polling - usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); + if (status == LIBUSB_TRANSFER_CANCELLED) + usbi_handle_transfer_cancellation(itransfer); + else + usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); } void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size) diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 335ae072d..3fdb62575 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11130 +#define LIBUSB_NANO 11131 From 138b661f4214e9fc10e836f3a8abebeb166da896 Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Mon, 26 Oct 2015 14:18:33 +0100 Subject: [PATCH 214/222] core: Refactor code related to transfer flags and timeout handling Commit a886bb02 sped up the library a bit by removing the serialization of transfer submission with respect to the flying_transfers list, but it introduced two separate issues. 1) A deadlock scenario is possible given the following sequence: - Thread A submits transfer with very short timeout (say 1ms) -> takes transfer->lock -> adds transfer to flying_transfers list and arms timerfd -> actually calls backend to submit transfer, but it fails - Thread B is doing event handling and sees the timerfd trigger -> takes ctx->flying_transfers_lock -> finds the transfer above on the list -> calls libusb_cancel_transfer() for this transfer --> takes transfer->lock - Thread A sees the transfer failed to submit -> removes transfer from flying_transfers list --> takes ctx->flying_transfers_lock (still holding transfer->lock) ** DEADLOCK ** 2) The transfer state flags (e.g. submitting, in-flight) were protected by transfer->flags_lock, but the timeout-related flags were OR'ed in during timeout handling operations outside of the lock. This leads to the possibility that transfer state might get overwritten. This change corrects these issues and simplifies the transfer submission code a bit by separating the state and timeout flags into their own flag variables. The state flags are protected by the transfer lock. The timeout flags are protected by the flying_transfers_lock. The transfer submission code sheds some weight because it no longer needs to worry about the timing of events that modify the transfer state flags. These flags are always viewed and modified under the protection of the transfer lock. Since libusb_submit_transfer() holds the transfer lock for the entire duration of the operation, the other code paths that would possibly touch the transfer (e.g. usbi_handle_disconnect() and usbi_handle_transfer_completion()) have to wait for transfer submission to fully complete. This eliminates any possible race conditions. Signed-off-by: Chris Dickens [hdegoede@redhat.com: Reworked libusb_submit_transfer changes so that in case both flying_transfer_lock and itransfer->lock are taken flying_transfers_lock is always taken first] [hdegoede@redhat.com: Removed some unrelated changes (will be submitted as separate patches)] Signed-off-by: Hans de Goede --- libusb/core.c | 4 +- libusb/io.c | 144 ++++++++++++++++++++++------------------- libusb/libusbi.h | 43 ++++++------ libusb/os/darwin_usb.c | 10 +-- libusb/version_nano.h | 2 +- 5 files changed, 104 insertions(+), 99 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 2e3816cc6..d1e93c84b 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1351,10 +1351,10 @@ static void do_close(struct libusb_context *ctx, if (transfer->dev_handle != dev_handle) continue; - if (!(itransfer->flags & USBI_TRANSFER_DEVICE_DISAPPEARED)) { + if (!(itransfer->state_flags & USBI_TRANSFER_DEVICE_DISAPPEARED)) { usbi_err(ctx, "Device handle closed while transfer was still being processed, but the device is still connected as far as we know"); - if (itransfer->flags & USBI_TRANSFER_CANCELLING) + if (itransfer->state_flags & USBI_TRANSFER_CANCELLING) usbi_warn(ctx, "A cancellation for an in-flight transfer hasn't completed but closing the device handle"); else usbi_err(ctx, "A cancellation hasn't even been scheduled on the transfer for which the device is closing"); diff --git a/libusb/io.c b/libusb/io.c index 3bd167560..3757f4481 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1269,7 +1269,6 @@ struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer( itransfer->num_iso_packets = iso_packets; usbi_mutex_init(&itransfer->lock); - usbi_mutex_init(&itransfer->flags_lock); transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); usbi_dbg("transfer %p", transfer); return transfer; @@ -1304,7 +1303,6 @@ void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer) itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); usbi_mutex_destroy(&itransfer->lock); - usbi_mutex_destroy(&itransfer->flags_lock); free(itransfer); } @@ -1339,8 +1337,8 @@ static int arm_timerfd_for_next_timeout(struct libusb_context *ctx) if (!timerisset(cur_tv)) goto disarm; - /* act on first transfer that is not already cancelled */ - if (!(transfer->flags & USBI_TRANSFER_TIMEOUT_HANDLED)) { + /* act on first transfer that has not already been handled */ + if (!(transfer->timeout_flags & USBI_TRANSFER_TIMEOUT_HANDLED)) { int r; const struct itimerspec it = { {0, 0}, { cur_tv->tv_sec, cur_tv->tv_usec * 1000 } }; @@ -1374,8 +1372,6 @@ static int add_to_flying_list(struct usbi_transfer *transfer) int r = 0; int first = 1; - usbi_mutex_lock(&ctx->flying_transfers_lock); - /* if we have no other flying transfers, start the list with this one */ if (list_empty(&ctx->flying_transfers)) { list_add(&transfer->list, &ctx->flying_transfers); @@ -1428,7 +1424,6 @@ static int add_to_flying_list(struct usbi_transfer *transfer) if (r) list_del(&transfer->list); - usbi_mutex_unlock(&ctx->flying_transfers_lock); return r; } @@ -1471,62 +1466,79 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer) { struct usbi_transfer *itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); - int remove = 0; + struct libusb_context *ctx = TRANSFER_CTX(transfer); int r; usbi_dbg("transfer %p", transfer); + + /* + * Important note on locking, this function takes / releases locks + * in the following order: + * take flying_transfers_lock + * take itransfer->lock + * clear transfer + * add to flying_transfers list + * release flying_transfers_lock + * submit transfer + * release itransfer->lock + * if submit failed: + * take flying_transfers_lock + * remove from flying_transfers list + * release flying_transfers_lock + * + * Note that it takes locks in the order a-b and then releases them + * in the same order a-b. This is somewhat unusual but not wrong, + * release order is not important as long as *all* locks are released + * before re-acquiring any locks. + * + * This means that the ordering of first releasing itransfer->lock + * and then re-acquiring the flying_transfers_list on error is + * important and must not be changed! + * + * This is done this way because when we take both locks we must always + * take flying_transfers_lock first to avoid ab-ba style deadlocks with + * the timeout handling and usbi_handle_disconnect paths. + * + * And we cannot release itransfer->lock before the submission is + * complete otherwise timeout handling for transfers with short + * timeouts may run before submission. + */ + usbi_mutex_lock(&ctx->flying_transfers_lock); usbi_mutex_lock(&itransfer->lock); - usbi_mutex_lock(&itransfer->flags_lock); - if (itransfer->flags & USBI_TRANSFER_IN_FLIGHT) { - r = LIBUSB_ERROR_BUSY; - goto out; + if (itransfer->state_flags & USBI_TRANSFER_IN_FLIGHT) { + usbi_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&itransfer->lock); + return LIBUSB_ERROR_BUSY; } itransfer->transferred = 0; - itransfer->flags = 0; + itransfer->state_flags = 0; + itransfer->timeout_flags = 0; r = calculate_timeout(itransfer); if (r < 0) { - r = LIBUSB_ERROR_OTHER; - goto out; + usbi_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&itransfer->lock); + return LIBUSB_ERROR_OTHER; } - itransfer->flags |= USBI_TRANSFER_SUBMITTING; - usbi_mutex_unlock(&itransfer->flags_lock); r = add_to_flying_list(itransfer); if (r) { - usbi_mutex_lock(&itransfer->flags_lock); - itransfer->flags = 0; - goto out; + usbi_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&itransfer->lock); + return r; } + usbi_mutex_unlock(&ctx->flying_transfers_lock); - /* keep a reference to this device */ - libusb_ref_device(transfer->dev_handle->dev); r = usbi_backend->submit_transfer(itransfer); - - usbi_mutex_lock(&itransfer->flags_lock); - itransfer->flags &= ~USBI_TRANSFER_SUBMITTING; if (r == LIBUSB_SUCCESS) { - /* check for two possible special conditions: - * 1) device disconnect occurred immediately after submission - * 2) transfer completed before we got here to update the flags - */ - if (itransfer->flags & USBI_TRANSFER_DEVICE_DISAPPEARED) { - usbi_backend->clear_transfer_priv(itransfer); - remove = 1; - r = LIBUSB_ERROR_NO_DEVICE; - } - else if (!(itransfer->flags & USBI_TRANSFER_COMPLETED)) { - itransfer->flags |= USBI_TRANSFER_IN_FLIGHT; - } - } else { - remove = 1; - } -out: - usbi_mutex_unlock(&itransfer->flags_lock); - if (remove) { - libusb_unref_device(transfer->dev_handle->dev); - remove_from_flying_list(itransfer); + itransfer->state_flags |= USBI_TRANSFER_IN_FLIGHT; + /* keep a reference to this device */ + libusb_ref_device(transfer->dev_handle->dev); } usbi_mutex_unlock(&itransfer->lock); + + if (r != LIBUSB_SUCCESS) + remove_from_flying_list(itransfer); + return r; } @@ -1552,9 +1564,8 @@ int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer) usbi_dbg("transfer %p", transfer ); usbi_mutex_lock(&itransfer->lock); - usbi_mutex_lock(&itransfer->flags_lock); - if (!(itransfer->flags & USBI_TRANSFER_IN_FLIGHT) - || (itransfer->flags & USBI_TRANSFER_CANCELLING)) { + if (!(itransfer->state_flags & USBI_TRANSFER_IN_FLIGHT) + || (itransfer->state_flags & USBI_TRANSFER_CANCELLING)) { r = LIBUSB_ERROR_NOT_FOUND; goto out; } @@ -1568,13 +1579,12 @@ int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer) usbi_dbg("cancel transfer failed error %d", r); if (r == LIBUSB_ERROR_NO_DEVICE) - itransfer->flags |= USBI_TRANSFER_DEVICE_DISAPPEARED; + itransfer->state_flags |= USBI_TRANSFER_DEVICE_DISAPPEARED; } - itransfer->flags |= USBI_TRANSFER_CANCELLING; + itransfer->state_flags |= USBI_TRANSFER_CANCELLING; out: - usbi_mutex_unlock(&itransfer->flags_lock); usbi_mutex_unlock(&itransfer->lock); return r; } @@ -1637,10 +1647,9 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, if (r < 0) usbi_err(ITRANSFER_CTX(itransfer), "failed to set timer for next timeout, errno=%d", errno); - usbi_mutex_lock(&itransfer->flags_lock); - itransfer->flags &= ~USBI_TRANSFER_IN_FLIGHT; - itransfer->flags |= USBI_TRANSFER_COMPLETED; - usbi_mutex_unlock(&itransfer->flags_lock); + usbi_mutex_lock(&itransfer->lock); + itransfer->state_flags &= ~USBI_TRANSFER_IN_FLIGHT; + usbi_mutex_unlock(&itransfer->lock); if (status == LIBUSB_TRANSFER_COMPLETED && transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) { @@ -1676,7 +1685,7 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer) { /* if the URB was cancelled due to timeout, report timeout to the user */ - if (transfer->flags & USBI_TRANSFER_TIMED_OUT) { + if (transfer->timeout_flags & USBI_TRANSFER_TIMED_OUT) { usbi_dbg("detected timeout cancellation"); return usbi_handle_transfer_completion(transfer, LIBUSB_TRANSFER_TIMED_OUT); } @@ -1967,10 +1976,10 @@ static void handle_timeout(struct usbi_transfer *itransfer) USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); int r; - itransfer->flags |= USBI_TRANSFER_TIMEOUT_HANDLED; + itransfer->timeout_flags |= USBI_TRANSFER_TIMEOUT_HANDLED; r = libusb_cancel_transfer(transfer); if (r == 0) - itransfer->flags |= USBI_TRANSFER_TIMED_OUT; + itransfer->timeout_flags |= USBI_TRANSFER_TIMED_OUT; else usbi_warn(TRANSFER_CTX(transfer), "async cancel failed %d errno=%d", r, errno); @@ -2003,7 +2012,7 @@ static int handle_timeouts_locked(struct libusb_context *ctx) return 0; /* ignore timeouts we've already handled */ - if (transfer->flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT)) + if (transfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT)) continue; /* if transfer has non-expired timeout, nothing more to do */ @@ -2549,7 +2558,7 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx, /* find next transfer which hasn't already been processed as timed out */ list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { - if (transfer->flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT)) + if (transfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT)) continue; /* if we've reached transfers of infinte timeout, we're done looking */ @@ -2766,9 +2775,10 @@ void usbi_handle_disconnect(struct libusb_device_handle *dev_handle) * possible scenarios: * 1. the transfer is currently in-flight, in which case we terminate the * transfer here - * 2. the transfer is not in-flight (or is but hasn't been marked as such), - * in which case we record that the device disappeared and this will be - * handled by libusb_submit_transfer() + * 2. the transfer has been added to the flying transfer list by + * libusb_submit_transfer, has failed to submit and + * libusb_submit_transfer is waiting for us to release the + * flying_transfers_lock to remove it, so we ignore it */ while (1) { @@ -2776,12 +2786,10 @@ void usbi_handle_disconnect(struct libusb_device_handle *dev_handle) usbi_mutex_lock(&HANDLE_CTX(dev_handle)->flying_transfers_lock); list_for_each_entry(cur, &HANDLE_CTX(dev_handle)->flying_transfers, list, struct usbi_transfer) if (USBI_TRANSFER_TO_LIBUSB_TRANSFER(cur)->dev_handle == dev_handle) { - usbi_mutex_lock(&cur->flags_lock); - if (cur->flags & USBI_TRANSFER_IN_FLIGHT) + usbi_mutex_lock(&cur->lock); + if (cur->state_flags & USBI_TRANSFER_IN_FLIGHT) to_cancel = cur; - else - cur->flags |= USBI_TRANSFER_DEVICE_DISAPPEARED; - usbi_mutex_unlock(&cur->flags_lock); + usbi_mutex_unlock(&cur->lock); if (to_cancel) break; diff --git a/libusb/libusbi.h b/libusb/libusbi.h index ca54a4621..cc0906c19 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -277,6 +277,8 @@ struct libusb_context { * the list, URBs that will time out later are placed after, and urbs with * infinite timeout are always placed at the very end. */ struct list_head flying_transfers; + /* Note paths taking both this and usbi_transfer->lock must always + * take this lock first */ usbi_mutex_t flying_transfers_lock; /* user callbacks for pollfd changes */ @@ -440,7 +442,8 @@ struct usbi_transfer { struct timeval timeout; int transferred; uint32_t stream_id; - uint8_t flags; + uint8_t state_flags; /* Protected by usbi_transfer->lock */ + uint8_t timeout_flags; /* Protected by the flying_stransfers_lock */ /* this lock is held during libusb_submit_transfer() and * libusb_cancel_transfer() (allowing the OS backend to prevent duplicate @@ -448,38 +451,32 @@ struct usbi_transfer { * should also take this lock in the handle_events path, to prevent the user * cancelling the transfer from another thread while you are processing * its completion (presumably there would be races within your OS backend - * if this were possible). */ + * if this were possible). + * Note paths taking both this and the flying_transfers_lock must + * always take the flying_transfers_lock first */ usbi_mutex_t lock; - - /* this lock should be held whenever viewing or modifying flags - * relating to the transfer state */ - usbi_mutex_t flags_lock; }; -enum usbi_transfer_flags { - /* The transfer has timed out */ - USBI_TRANSFER_TIMED_OUT = 1 << 0, - - /* Set by backend submit_transfer() if the OS handles timeout */ - USBI_TRANSFER_OS_HANDLES_TIMEOUT = 1 << 1, +enum usbi_transfer_state_flags { + /* Transfer successfully submitted by backend */ + USBI_TRANSFER_IN_FLIGHT = 1 << 0, /* Cancellation was requested via libusb_cancel_transfer() */ - USBI_TRANSFER_CANCELLING = 1 << 2, + USBI_TRANSFER_CANCELLING = 1 << 1, /* Operation on the transfer failed because the device disappeared */ - USBI_TRANSFER_DEVICE_DISAPPEARED = 1 << 3, - - /* Transfer is currently being submitted */ - USBI_TRANSFER_SUBMITTING = 1 << 4, - - /* Transfer successfully submitted by backend */ - USBI_TRANSFER_IN_FLIGHT = 1 << 5, + USBI_TRANSFER_DEVICE_DISAPPEARED = 1 << 2, +}; - /* Completion handler has run */ - USBI_TRANSFER_COMPLETED = 1 << 6, +enum usbi_transfer_timeout_flags { + /* Set by backend submit_transfer() if the OS handles timeout */ + USBI_TRANSFER_OS_HANDLES_TIMEOUT = 1 << 0, /* The transfer timeout has been handled */ - USBI_TRANSFER_TIMEOUT_HANDLED = 1 << 7, + USBI_TRANSFER_TIMEOUT_HANDLED = 1 << 1, + + /* The transfer timeout was successfully processed */ + USBI_TRANSFER_TIMED_OUT = 1 << 2, }; #define USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \ diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 4e4ab04cf..7912282e6 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -1561,7 +1561,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) { ret = (*(cInterface->interface))->WritePipeAsync(cInterface->interface, pipeRef, transfer->buffer, transfer->length, darwin_async_io_callback, itransfer); } else { - itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; + itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; if (IS_XFERIN(transfer)) ret = (*(cInterface->interface))->ReadPipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer, @@ -1593,7 +1593,7 @@ static int submit_stream_transfer(struct usbi_transfer *itransfer) { return LIBUSB_ERROR_NOT_FOUND; } - itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; + itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; if (IS_XFERIN(transfer)) ret = (*(cInterface->interface))->ReadStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id, @@ -1721,7 +1721,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) { tpriv->req.completionTimeout = transfer->timeout; tpriv->req.noDataTimeout = transfer->timeout; - itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; + itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; /* all transfers in libusb-1.0 are async */ @@ -1870,7 +1870,7 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) } static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_t result) { - if (itransfer->flags & USBI_TRANSFER_TIMED_OUT) + if (itransfer->timeout_flags & USBI_TRANSFER_TIMED_OUT) result = kIOUSBTransactionTimeout; switch (result) { @@ -1887,7 +1887,7 @@ static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_ return LIBUSB_TRANSFER_OVERFLOW; case kIOUSBTransactionTimeout: usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: timed out"); - itransfer->flags |= USBI_TRANSFER_TIMED_OUT; + itransfer->timeout_flags |= USBI_TRANSFER_TIMED_OUT; return LIBUSB_TRANSFER_TIMED_OUT; default: usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: %s (value = 0x%08x)", darwin_error_str (result), result); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 3fdb62575..de73e8607 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11131 +#define LIBUSB_NANO 11132 From 06e86793be2efe098022fcba20be8624285132f1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 6 Jun 2016 16:53:53 +0200 Subject: [PATCH 215/222] core: Do not arm timer-fd for transfers where the os handles timeout Signed-off-by: Hans de Goede --- libusb/io.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/io.c b/libusb/io.c index 3757f4481..13388cc26 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1338,7 +1338,7 @@ static int arm_timerfd_for_next_timeout(struct libusb_context *ctx) goto disarm; /* act on first transfer that has not already been handled */ - if (!(transfer->timeout_flags & USBI_TRANSFER_TIMEOUT_HANDLED)) { + if (!(transfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))) { int r; const struct itimerspec it = { {0, 0}, { cur_tv->tv_sec, cur_tv->tv_usec * 1000 } }; diff --git a/libusb/version_nano.h b/libusb/version_nano.h index de73e8607..f39bf48db 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11132 +#define LIBUSB_NANO 11133 From d5a1418d9fbab126ded971d34eb8e27cfaa58b3d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 6 Jun 2016 16:54:42 +0200 Subject: [PATCH 216/222] core: Test for LIBUSB_SUCCESS instead of 0 in handle_timeout() Signed-off-by: Hans de Goede --- libusb/io.c | 2 +- libusb/version_nano.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/io.c b/libusb/io.c index 13388cc26..aa6cfca55 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1978,7 +1978,7 @@ static void handle_timeout(struct usbi_transfer *itransfer) itransfer->timeout_flags |= USBI_TRANSFER_TIMEOUT_HANDLED; r = libusb_cancel_transfer(transfer); - if (r == 0) + if (r == LIBUSB_SUCCESS) itransfer->timeout_flags |= USBI_TRANSFER_TIMED_OUT; else usbi_warn(TRANSFER_CTX(transfer), diff --git a/libusb/version_nano.h b/libusb/version_nano.h index f39bf48db..9fb8855f3 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11133 +#define LIBUSB_NANO 11134 From efcfe05a2a572b67a5fbacdc855ac678b2ce8380 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 6 Jun 2016 17:42:12 +0200 Subject: [PATCH 217/222] core: Fix do_close locking Put the lock / unlock calls around the part of the code which actually checks the flags which the lock protect. Signed-off-by: Hans de Goede --- libusb/core.c | 4 ++-- libusb/version_nano.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index d1e93c84b..99aab7bb0 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1351,6 +1351,7 @@ static void do_close(struct libusb_context *ctx, if (transfer->dev_handle != dev_handle) continue; + usbi_mutex_lock(&itransfer->lock); if (!(itransfer->state_flags & USBI_TRANSFER_DEVICE_DISAPPEARED)) { usbi_err(ctx, "Device handle closed while transfer was still being processed, but the device is still connected as far as we know"); @@ -1359,15 +1360,14 @@ static void do_close(struct libusb_context *ctx, else usbi_err(ctx, "A cancellation hasn't even been scheduled on the transfer for which the device is closing"); } + usbi_mutex_unlock(&itransfer->lock); /* remove from the list of in-flight transfers and make sure * we don't accidentally use the device handle in the future * (or that such accesses will be easily caught and identified as a crash) */ - usbi_mutex_lock(&itransfer->lock); list_del(&itransfer->list); transfer->dev_handle = NULL; - usbi_mutex_unlock(&itransfer->lock); /* it is up to the user to free up the actual transfer struct. this is * just making sure that we don't attempt to process the transfer after diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 9fb8855f3..6995b335e 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11134 +#define LIBUSB_NANO 11135 From ce59e6ea12852f25025fef5ef42da9e271049a59 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 6 Jun 2016 17:43:23 +0200 Subject: [PATCH 218/222] core: Fix unlocked access to timeout_flags There is a race between handle_timeout() and the completion functions. When one thread is in handle_timeout() and another thread wakes up from a poll(), there exists a window where the transfer has been cancelled, but USBI_TRANSFER_TIMED_OUT is not yet set in timeout_flags. Therefore, usbi_handle_transfer_completion() is sometimes called with LIBUSB_TRANSFER_CANCELLED instead of the expected LIBUSB_TRANSFER_TIMED_OUT. timeout_flags is protected by the flying_transfers_lock, this commit makes usbi_handle_transfer_cancellation() take that lock before checking for USBI_TRANSFER_TIMED_OUT in timeout_flags, fixing this. Reported-by: Joost Muller Signed-off-by: Hans de Goede --- libusb/io.c | 9 ++++++++- libusb/version_nano.h | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/libusb/io.c b/libusb/io.c index aa6cfca55..b3f7df05f 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1684,8 +1684,15 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, * will attempt to take the lock. */ int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer) { + struct libusb_context *ctx = ITRANSFER_CTX(transfer); + uint8_t timed_out; + + usbi_mutex_lock(&ctx->flying_transfers_lock); + timed_out = transfer->timeout_flags & USBI_TRANSFER_TIMED_OUT; + usbi_mutex_unlock(&ctx->flying_transfers_lock); + /* if the URB was cancelled due to timeout, report timeout to the user */ - if (transfer->timeout_flags & USBI_TRANSFER_TIMED_OUT) { + if (timed_out) { usbi_dbg("detected timeout cancellation"); return usbi_handle_transfer_completion(transfer, LIBUSB_TRANSFER_TIMED_OUT); } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 6995b335e..bb7624f12 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11135 +#define LIBUSB_NANO 11137 From 9542c38cf2cbd911bd7e3ec161e564b3ae63d4fe Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 8 Jun 2016 10:34:05 +0200 Subject: [PATCH 219/222] core: Move calculate_timeout call to add_to_flying_transfers This cleans-up libusb_submit_transfer a bit by avoiding an error exit path with unlock calls. Signed-off-by: Hans de Goede --- libusb/io.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/libusb/io.c b/libusb/io.c index b3f7df05f..836362827 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1369,9 +1369,13 @@ static int add_to_flying_list(struct usbi_transfer *transfer) struct usbi_transfer *cur; struct timeval *timeout = &transfer->timeout; struct libusb_context *ctx = ITRANSFER_CTX(transfer); - int r = 0; + int r; int first = 1; + r = calculate_timeout(transfer); + if (r) + return r; + /* if we have no other flying transfers, start the list with this one */ if (list_empty(&ctx->flying_transfers)) { list_add(&transfer->list, &ctx->flying_transfers); @@ -1513,13 +1517,6 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer) itransfer->transferred = 0; itransfer->state_flags = 0; itransfer->timeout_flags = 0; - r = calculate_timeout(itransfer); - if (r < 0) { - usbi_mutex_unlock(&ctx->flying_transfers_lock); - usbi_mutex_unlock(&itransfer->lock); - return LIBUSB_ERROR_OTHER; - } - r = add_to_flying_list(itransfer); if (r) { usbi_mutex_unlock(&ctx->flying_transfers_lock); From 00e36c829fe87a3d285d7a774eb8a1ca8797d0c0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 7 Jun 2016 12:12:38 +0200 Subject: [PATCH 220/222] linux_usbfs: Deal with receiving POLLERR before all transfers have completed The linux kernel will set its internal device state to USB_STATE_NOTATTACHED as soon as it detects the disconnect, and then start a worker thread to deal with the actual disconnection, kill outstanding urbs, etc. The usbfs poll implementation will return POLL_ERR as soon as ps->dev->state == USB_STATE_NOTATTACHED. The kernel will not wakeup the poll until it is done with processing the disconnection. But if we happen to call poll() between the state change and the disconnection being fully processed, we may not be able to reap all outstanding transfers, even on kernels with the USBFS_CAP_REAP_AFTER_DISCONNECT capability. This commit deals with this by trying to reap as many transfers as possible on disconnect on USBFS_CAP_REAP_AFTER_DISCONNECT capable kernels and then calling usbi_handle_disconnect(handle) to deal with any remaining ones. On USBFS_CAP_REAP_AFTER_DISCONNECT capable kernels this will be a no-op unless we hit the race. Signed-off-by: Hans de Goede --- libusb/os/linux_usbfs.c | 10 +++++++--- libusb/version_nano.h | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 0689894d5..9cbeb8005 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -2638,10 +2638,14 @@ static int op_handle_events(struct libusb_context *ctx, handle->dev->device_address); usbi_mutex_static_unlock(&linux_hotplug_lock); - if (!(hpriv->caps & USBFS_CAP_REAP_AFTER_DISCONNECT)) { - usbi_handle_disconnect(handle); - continue; + if (hpriv->caps & USBFS_CAP_REAP_AFTER_DISCONNECT) { + do { + r = reap_for_handle(handle); + } while (r == 0); } + + usbi_handle_disconnect(handle); + continue; } do { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index bb7624f12..b394a2ee9 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11137 +#define LIBUSB_NANO 11138 From 88778414eac1cc6f37b85e6902d6fa2aa221b7c4 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 11 Aug 2016 11:12:56 +0200 Subject: [PATCH 221/222] core: Document why we drop the flying_transfers_lock before submit_transfer Signed-off-by: Hans de Goede --- libusb/io.c | 4 ++++ libusb/version_nano.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libusb/io.c b/libusb/io.c index 836362827..bf2b5fa42 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1523,6 +1523,10 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer) usbi_mutex_unlock(&itransfer->lock); return r; } + /* + * We must release the flying transfers lock here, because with + * some backends the submit_transfer method is synchroneous. + */ usbi_mutex_unlock(&ctx->flying_transfers_lock); r = usbi_backend->submit_transfer(itransfer); diff --git a/libusb/version_nano.h b/libusb/version_nano.h index b394a2ee9..299c4641c 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11138 +#define LIBUSB_NANO 11139 From e5b09f34553df82ebced2c2dce91a50980c2786a Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Sun, 21 Aug 2016 20:32:39 -0600 Subject: [PATCH 222/222] release: on to 1.0.21-rc3 Signed-off-by: Nathan Hjelm --- ChangeLog | 4 +++- libusb/version.h | 2 +- libusb/version_nano.h | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3b07a8f50..70319bceb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,12 +2,14 @@ For detailed information about the changes below, please see the git log or visit: http://log.libusb.info 2016-07-20: v1.0.21: +* Core: Refactor code related to transfer flags and timeout handling * Darwin: Ignore root hub simulation devices * Darwin: Improved support for OS X El Capitan * Linux: Support preallocating kernel memory for zerocopy USB +* Linux: Deal with receiving POLLERR before all transfers have completed * Solaris: Add solaris backend * Windows: Add Visual Studio 2015 support -* Prevent attempts to recursively hande events +* Prevent attempts to recursively handle events * Fix race condition in handle_timeout() * Allow transferred argument to be optional in bulk APIs * Various other bug fixes and improvements diff --git a/libusb/version.h b/libusb/version.h index 4ee1f278c..54d638200 100644 --- a/libusb/version.h +++ b/libusb/version.h @@ -14,5 +14,5 @@ #endif /* LIBUSB_RC is the release candidate suffix. Should normally be empty. */ #ifndef LIBUSB_RC -#define LIBUSB_RC "-rc2" +#define LIBUSB_RC "-rc3" #endif diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 299c4641c..43ace0cbf 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11139 +#define LIBUSB_NANO 11140