diff options
author | Pete Batard <pbatard@gmail.com> | 2011-03-09 00:35:55 +0000 |
---|---|---|
committer | Pete Batard <pbatard@gmail.com> | 2011-03-09 00:35:55 +0000 |
commit | 328439204a53a81ec8f11fbb7218a612e5a6e0c9 (patch) | |
tree | bc915aed63510c37d19237767104c26ea924b493 | |
parent | fc8743533d6cc5beccf00d276cfcdd3af4793bd0 (diff) | |
download | libusb-328439204a53a81ec8f11fbb7218a612e5a6e0c9.tar.gz |
merge -> pbr336
-rw-r--r-- | _README.txt | 14 | ||||
-rw-r--r-- | _bd.cmd | 2 | ||||
-rw-r--r-- | _bm.sh | 8 | ||||
-rwxr-xr-x | autogen.sh | 4 | ||||
-rw-r--r-- | configure.ac | 103 | ||||
-rw-r--r-- | examples/xusb.c | 322 | ||||
-rw-r--r-- | libusb/Makefile.am | 6 | ||||
-rw-r--r-- | libusb/core.c | 1 | ||||
-rw-r--r-- | libusb/io.c | 63 | ||||
-rw-r--r-- | libusb/libusb-1.0.def | 368 | ||||
-rw-r--r-- | libusb/libusb.h | 3 | ||||
-rw-r--r-- | libusb/libusbi.h | 6 | ||||
-rw-r--r-- | libusb/os/darwin_usb.c | 57 | ||||
-rw-r--r-- | libusb/os/darwin_usb.h | 2 | ||||
-rw-r--r-- | libusb/os/linux_usbfs.c | 162 | ||||
-rw-r--r-- | libusb/os/poll_posix.h | 2 | ||||
-rw-r--r-- | libusb/os/poll_windows.h | 2 | ||||
-rw-r--r-- | libusb/os/windows_usb.c | 1223 | ||||
-rw-r--r-- | libusb/os/windows_usb.h | 182 | ||||
-rw-r--r-- | libusb/sync.c | 8 | ||||
-rw-r--r-- | msvc/config.h | 10 |
21 files changed, 524 insertions, 2024 deletions
diff --git a/_README.txt b/_README.txt index fd9d809..00bf27f 100644 --- a/_README.txt +++ b/_README.txt @@ -7,9 +7,9 @@ o Visual Studio: - Open existing or create a new project for your application - - Copy the libusb.h into your project and make sure that the location where - the file reside appears in the 'Additional Include Directories' section - (Configuration Properties -> C/C++ -> General). + - Copy libusb.h, from the include\libusb-1.0\ directory, into your project and + make sure that the location where the file reside appears in the 'Additional + Include Directories' section (Configuration Properties -> C/C++ -> General). - Copy the relevant .lib file from MS32\ or MS64\ and add 'libusb-1.0.lib' to your 'Additional Dependencies' (Configuration Properties -> Linker -> Input) Also make sure that the directory where libusb-1.0.lib resides is added to @@ -43,10 +43,10 @@ o WDK/DDK: easily be achieved, in the DDK environment, by running 'ddk_build /MT' o MinGW/cygwin - - Copy libusb.h to your default include directory and the relevant MinGW32\ or - MinGW64\ .a file to your default library directory. Or, if you don't want to - use the default locations, make sure that you feed the relevant -I and -L - options to the compiler. + - Copy libusb.h, from include/libusb-1.0/ to your default include directory, + and copy the MinGW32/ or MinGW64/ .a files to your default library directory. + Or, if you don't want to use the default locations, make sure that you feed + the relevant -I and -L options to the compiler. - Add the '-lusb-1.0' linker option when compiling. o Additional information: @@ -9,8 +9,6 @@ for %%A in (MS32 MS64) do mkdir E:\dailies\%DATE%\%%A for %%A in (MS32 MS64) do mkdir E:\dailies\%DATE%\%%A\static for %%A in (MS32 MS64) do mkdir E:\dailies\%DATE%\%%A\dll for %%A in (source bin32 bin64) do mkdir E:\dailies\%DATE%\examples\%%A -copy libusb\libusb.h E:\dailies\%DATE%\ -copy libusb\libusb-1.0.def E:\dailies\%DATE%\ copy examples\lsusb.c E:\dailies\%DATE%\examples\source copy examples\xusb.c E:\dailies\%DATE%\examples\source copy msvc\stdint.h E:\dailies\%DATE%\examples\source @@ -3,12 +3,16 @@ # !!!THIS SCRIPT IS FOR INTERNAL DEVELOPER USE ONLY!!! date=`date +%Y.%m.%d` +target=e:/dailies/$date +mkdir -p $target/include/libusb-1.0 +cp -v libusb/libusb-1.0.def $target +cp -v libusb/libusb.h $target/include/libusb-1.0 # # 32 bit binaries # target=e:/dailies/$date/MinGW32 -git clean -f -d -x +git clean -fdx # Not using debug (-g) in CFLAGS DRAMATICALLY reduces the size of the binaries export CFLAGS="-O2 -m32" export LDFLAGS="-m32" @@ -44,4 +48,4 @@ mkdir -p $target/static mkdir -p $target/dll cp -v libusb/.libs/libusb-1.0.a $target/static cp -v libusb/.libs/libusb-1.0.dll $target/dll -cp -v libusb/.libs/libusb-1.0.dll.a $target/dll
\ No newline at end of file +cp -v libusb/.libs/libusb-1.0.dll.a $target/dll @@ -6,7 +6,7 @@ create_def() echo "rebuidling libusb-1.0.def file" echo "LIBRARY" > libusb/libusb-1.0.def echo "EXPORTS" >> libusb/libusb-1.0.def - sed -n -e "s/.*API_EXPORTED.*\([[:blank:]]\)\(libusb.*\)(.*/ \2/p" libusb/*.c >> libusb/libusb-1.0.def~ + sed -n -e "s/.*API_EXPORTED.*\([[:blank:]]\)\(libusb.*\)(.*/ \2/p" libusb/*.c > libusb/libusb-1.0.def~ sed -n -e "s/.*LIBUSB_CALL.*\([[:blank:]]\)\(libusb.*\)(.*/ \2/p" libusb/*.c >> libusb/libusb-1.0.def~ # We need to manually define a whole set of DLL aliases if we want the MS # DLLs to be usable with dynamically linked MinGW executables. This is @@ -14,7 +14,7 @@ create_def() # calls in MinGW generated objects, and .def based MS generated DLLs don't # have such a decoration => linking to MS DLL will fail without aliases. # Currently, the maximum size is 32 and all sizes are multiples of 4 - for i in 00 04 08 12 16 20 24 28 32 + for i in 0 4 8 12 16 20 24 28 32 do sed -n -e "s/.*API_EXPORTED.*\([[:blank:]]\)\(libusb.*\)(.*/ \2@$i = \2/p" libusb/*.c >> libusb/libusb-1.0.def~ sed -n -e "s/.*LIBUSB_CALL.*\([[:blank:]]\)\(libusb.*\)(.*/ \2@$i = \2/p" libusb/*.c >> libusb/libusb-1.0.def~ diff --git a/configure.ac b/configure.ac index cac9846..9540575 100644 --- a/configure.ac +++ b/configure.ac @@ -17,11 +17,11 @@ AC_SUBST([LIBUSB_VERSION_NANO], [LIBUSB_NANO]) lt_current="1" lt_revision="0" lt_age="1" -AC_SUBST(lt_current) -AC_SUBST(lt_revision) -AC_SUBST(lt_age) +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]) AM_CONFIG_HEADER([config.h]) @@ -32,75 +32,71 @@ AC_PROG_CC AC_PROG_LIBTOOL AC_C_INLINE AM_PROG_CC_C_O -AC_DEFINE([_GNU_SOURCE], [], [Use GNU extensions]) +AC_DEFINE([_GNU_SOURCE], 1, [Use GNU extensions]) -AM_MAINTAINER_MODE +LTLDFLAGS="${LTLDFLAGS} -no-undefined" AC_MSG_CHECKING([operating system]) -PC_LIBS_PRIVATE= case $host in *-linux*) - AC_DEFINE(OS_LINUX, [], [Linux backend]) + AC_DEFINE(OS_LINUX, 1, [Linux backend]) AC_SUBST(OS_LINUX) - AC_DEFINE([THREADS_POSIX], [], [Use Posix Threads]) AC_MSG_RESULT([Linux]) backend="linux" AC_CHECK_LIB(rt, clock_gettime, PC_LIBS_PRIVATE="-lrt") - LIBS="${LIBS} ${PC_LIBS_PRIVATE}" threads="posix" THREAD_CFLAGS="-pthread" PC_LIBS_PRIVATE="${PC_LIBS_PRIVATE} -pthread" - AM_CFLAGS="-std=gnu99" - AM_LDFLAGS="" + AC_CHECK_HEADERS([poll.h]) + AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument]) ;; *-darwin*) - AC_DEFINE(OS_DARWIN, [], [Darwin backend]) + AC_DEFINE(OS_DARWIN, 1, [Darwin backend]) AC_SUBST(OS_DARWIN) - AC_DEFINE([THREADS_POSIX], [], [Use Posix Threads]) - AC_MSG_RESULT([Darwin/MacOS X]) + AC_MSG_RESULT([Darwin/Mac OS X]) backend="darwin" threads="posix" - THREAD_CFLAGS="-pthread" - AM_CFLAGS="-std=gnu99" - PC_LIBS_PRIVATE="-Wl,-framework,IOKit -Wl,-framework,CoreFoundation -Wl,-prebind -no-undefined -pthread" - AM_LDFLAGS=${PC_LIBS_PRIVATE} + PC_LIBS_PRIVATE="-Wl,-framework,IOKit -Wl,-framework,CoreFoundation" + LTLDFLAGS="${LTLDFLAGS} -Wl,-prebind" + AC_CHECK_HEADERS([poll.h]) + AC_CHECK_TYPE([nfds_t], + [AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])], + [AC_DEFINE([POLL_NFDS_TYPE],[unsigned int],[type of second poll() argument])], + [#include <poll.h>]) ;; *-mingw*) - AC_DEFINE(OS_WINDOWS, [], [Windows backend]) - AC_SUBST(OS_WINDOWS) AC_MSG_RESULT([Windows]) backend="windows" - threads="windows" - create_import_lib="yes" - LIBS="${LIBS} ${PC_LIBS_PRIVATE}" - # -avoid-version to avoid a naming scheme such as libusb-0.dll - AM_LDFLAGS="-no-undefined -avoid-version -Wl,--add-stdcall-alias" - AM_CFLAGS="-std=c99" - AC_CHECK_TOOL(RC, windres, no) AC_CHECK_TOOL(DLLTOOL, dlltool, false) ;; *-cygwin*) - AC_DEFINE(OS_WINDOWS, [], [Windows backend]) - AC_SUBST(OS_WINDOWS) - AC_DEFINE([THREADS_POSIX], [], [Use Posix Threads]) - AC_MSG_RESULT([Windows]) + AC_MSG_RESULT([Cygwin (using Windows backend)]) backend="windows" threads="posix" - LIBS="${LIBS} ${PC_LIBS_PRIVATE}" - AM_CFLAGS="-std=gnu99" - AM_LDFLAGS="-no-undefined -avoid-version" - AC_CHECK_TOOL(RC, windres, no) ;; *) AC_MSG_ERROR([unsupported operating system]) esac +if test "$backend" = windows; then + AC_DEFINE(OS_WINDOWS, 1, [Windows backend]) + AC_SUBST(OS_WINDOWS) + PC_LIBS_PRIVATE="" + LTLDFLAGS="${LTLDFLAGS} -avoid-version -Wl,--add-stdcall-alias" + AC_CHECK_TOOL(RC, windres, no) + AC_DEFINE([POLL_NFDS_TYPE],[unsigned int],[type of second poll() argument]) +fi +AC_SUBST(THREAD_CFLAGS) AC_SUBST(PC_LIBS_PRIVATE) - -AM_CONDITIONAL([OS_LINUX], [test "x$backend" = "xlinux"]) -AM_CONDITIONAL([OS_DARWIN], [test "x$backend" = "xdarwin"]) -AM_CONDITIONAL([OS_WINDOWS], [test "x$backend" = "xwindows"]) -AM_CONDITIONAL([THREADS_POSIX], [test "x$threads" = "xposix"]) -AM_CONDITIONAL([CREATE_IMPORT_LIB], [test "x$create_import_lib" = "xyes"]) +LIBS="${LIBS} ${PC_LIBS_PRIVATE}" + +AM_CONDITIONAL(OS_LINUX, test "x$backend" = xlinux) +AM_CONDITIONAL(OS_DARWIN, test "x$backend" = xdarwin) +AM_CONDITIONAL(OS_WINDOWS, test "x$backend" = xwindows) +AM_CONDITIONAL(THREADS_POSIX, test "x$threads" = xposix) +AM_CONDITIONAL(CREATE_IMPORT_LIB, test "x$create_import_lib" = "xyes") +if test "$threads" = posix; then + AC_DEFINE(THREADS_POSIX, 1, [Use POSIX Threads]) +fi # timerfd AC_CHECK_HEADER([sys/timerfd.h], [timerfd_h=1], [timerfd_h=0]) @@ -124,7 +120,7 @@ if test "x$use_timerfd" = "xno"; then else if test "x$timerfd_h" = "x1" -a "x$tfd_hdr_ok" = "xyes"; then AC_MSG_RESULT([yes]) - AC_DEFINE(USBI_TIMERFD_AVAILABLE, [], [timerfd headers available]) + AC_DEFINE(USBI_TIMERFD_AVAILABLE, 1, [timerfd headers available]) else AC_MSG_RESULT([no (header not available)]) fi @@ -168,14 +164,14 @@ AM_CONDITIONAL([BUILD_EXAMPLES], [test "x$build_examples" != "xno"]) # Restore gnu89 inline semantics on gcc 4.3 and newer saved_cflags="$CFLAGS" CFLAGS="$CFLAGS -fgnu89-inline" -AC_COMPILE_IFELSE(AC_LANG_PROGRAM([]), inline_cflags="-fgnu89-inline", inline_cflags="") +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], inline_cflags="-fgnu89-inline", inline_cflags="") CFLAGS="$saved_cflags" # check for -fvisibility=hidden compiler support (GCC >= 3.4) saved_cflags="$CFLAGS" # -Werror required for cygwin CFLAGS="$CFLAGS -Werror -fvisibility=hidden" -AC_COMPILE_IFELSE(AC_LANG_PROGRAM([]), +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], [VISIBILITY_CFLAGS="-fvisibility=hidden" AC_DEFINE([DEFAULT_VISIBILITY], [__attribute__((visibility("default")))], [Default visibility]) ], [ VISIBILITY_CFLAGS="" @@ -186,7 +182,7 @@ CFLAGS="$saved_cflags" # check for -Wno-pointer-sign compiler support (GCC >= 4) saved_cflags="$CFLAGS" CFLAGS="$CFLAGS -Wno-pointer-sign" -AC_COMPILE_IFELSE(AC_LANG_PROGRAM([]), +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], nopointersign_cflags="-Wno-pointer-sign", nopointersign_cflags="") CFLAGS="$saved_cflags" @@ -197,14 +193,17 @@ AM_CONDITIONAL([HAVE_SIGACTION], [test "x$have_sigaction" = "xyes"]) # headers not available on all platforms but required on others AC_CHECK_HEADERS([sys/time.h]) -AC_SUBST([THREAD_CFLAGS]) - -AM_CFLAGS="$AM_CFLAGS $inline_cflags -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration $nopointersign_cflags -Wshadow" +AM_CFLAGS="-std=gnu99 $inline_cflags -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration $nopointersign_cflags -Wshadow" AC_SUBST(VISIBILITY_CFLAGS) AC_SUBST(AM_CFLAGS) -AC_SUBST(AM_LDFLAGS) - -AC_CONFIG_FILES([libusb-1.0.pc] [Makefile] [libusb/Makefile] [libusb/libusb_version.h] [examples/Makefile] [doc/Makefile] [doc/doxygen.cfg]) +AC_SUBST(LTLDFLAGS) + +AC_CONFIG_FILES([libusb-1.0.pc]) +AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([libusb/Makefile]) +AC_CONFIG_FILES([libusb/libusb_version.h]) +AC_CONFIG_FILES([examples/Makefile]) +AC_CONFIG_FILES([doc/Makefile]) +AC_CONFIG_FILES([doc/doxygen.cfg]) AC_OUTPUT - diff --git a/examples/xusb.c b/examples/xusb.c index ed69f5a..0c03fb6 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -1,12 +1,9 @@ /* - * xusb: libusb-winusb specific test program - * Copyright (c) 2009-2010 Pete Batard <pbatard@gmail.com> + * xusb: Generic USB test program + * Copyright (c) 2009-2011 Pete Batard <pbatard@gmail.com> * Based on lsusb, copyright (c) 2007 Daniel Drake <dsd@gentoo.org> * With contributions to Mass Storage test by Alan Stern. * - * This test program tries to access an USB device through WinUSB. - * To access your device, modify this source and add your VID/PID. - * * 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 @@ -22,7 +19,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <config.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> @@ -31,7 +27,7 @@ #include "libusb.h" -#ifdef OS_WINDOWS +#if defined(_MSC_VER) #define msleep(msecs) Sleep(msecs) #else #include <unistd.h> @@ -85,14 +81,9 @@ inline static int perr(char const *format, ...) // HID Class-Specific Requests values. See section 7.2 of the HID specifications #define HID_GET_REPORT 0x01 -#define HID_GET_IDLE 0x02 -#define HID_GET_PROTOCOL 0x03 #define HID_SET_REPORT 0x09 -#define HID_SET_IDLE 0x0A -#define HID_SET_PROTOCOL 0x0B #define HID_REPORT_TYPE_INPUT 0x01 #define HID_REPORT_TYPE_OUTPUT 0x02 -#define HID_REPORT_TYPE_FEATURE 0x03 // Mass Storage Requests values. See section 3 of the Bulk-Only Mass Storage Class specifications #define BOMS_RESET 0xFF @@ -138,10 +129,10 @@ static uint8_t cdb_length[256] = { }; enum test_type { + USE_GENERIC, + USE_PS3, USE_XBOX, - USE_KEY, - USE_JTAG, - USE_HID, + USE_SCSI, } test_mode; uint16_t VID, PID; @@ -173,7 +164,96 @@ void display_buffer_hex(unsigned char *buffer, unsigned size) printf("\n" ); } +int initalize_ps3(libusb_device_handle *handle) +{ + int r; + uint8_t input_report[49]; + CALL_CHECK(libusb_control_transfer(handle, 0x80, 0x06, 0x0001, 0x0, input_report, 0x12, 1000)); + CALL_CHECK(libusb_control_transfer(handle, 0x80, 0x06, 0x0002, 0x0, input_report, 0x09, 1000)); + CALL_CHECK(libusb_control_transfer(handle, 0x80, 0x06, 0x0002, 0x0, input_report, 0x29, 1000)); + CALL_CHECK(libusb_control_transfer(handle, 0xa1, 0x01, 0x03f2, 0x0, input_report, 0x11, 1000)); + CALL_CHECK(libusb_control_transfer(handle, 0xa1, 0x01, 0x03f5, 0x0, input_report, 0x08, 1000)); + return 0; +} +// The PS3 Controller is really a HID device that got its HID Report Descriptors +// removed by Sony +int display_ps3_status(libusb_device_handle *handle) +{ + int r; + uint8_t input_report[49]; + + //Ensure the controller is initialized and ready to send its state + initalize_ps3(handle); + + printf("\nReading PS3 Input Report...\n"); + CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, + HID_GET_REPORT, (HID_REPORT_TYPE_INPUT<<8)|0x01, 0, input_report, 49, 1000)); + switch(input_report[2]){ /** Direction pad plus start, select, and joystick buttons */ + case 0x01: + printf("\tSELECT pressed\n"); + break; + case 0x02: + printf("\tLEFT 3 pressed\n"); + break; + case 0x04: + printf("\tRIGHT 3 pressed\n"); + break; + case 0x08: + printf("\tSTART presed\n"); + break; + case 0x10: + printf("\tUP pressed\n"); + break; + case 0x20: + printf("\tRIGHT pressed\n"); + break; + case 0x40: + printf("\tDOWN pressed\n"); + break; + case 0x80: + printf("\tLEFT pressed\n"); + break; + } + switch(input_report[3]){ /** Shapes plus top right and left buttons */ + case 0x01: + printf("\tLEFT 2 pressed\n"); + break; + case 0x02: + printf("\tRIGHT 2 pressed\n"); + break; + case 0x04: + printf("\tLEFT 1 pressed\n"); + break; + case 0x08: + printf("\tRIGHT 1 presed\n"); + break; + case 0x10: + printf("\tTRIANGLE pressed\n"); + break; + case 0x20: + printf("\tCIRCLE pressed\n"); + break; + case 0x40: + printf("\tCROSS pressed\n"); + break; + case 0x80: + printf("\tSQUARE pressed\n"); + break; + } + printf("\tPS button: %d\n", input_report[4]); + printf("\tLeft Analog (X,Y): (%d,%d)\n", input_report[6], input_report[7]); + printf("\tRight Analog (X,Y): (%d,%d)\n", input_report[8], input_report[9]); + printf("\tL2 Value: %d\tR2 Value: %d\n", input_report[18], input_report[19]); + printf("\tL1 Value: %d\tR1 Value: %d\n", input_report[20], input_report[21]); + printf("\tRoll (x axis): %d Yaw (y axis): %d Pitch (z axis) %d\n", + //(((input_report[42] + 128) % 256) - 128), + (int8_t)(input_report[42]), + (int8_t)(input_report[44]), + (int8_t)(input_report[46])); + printf("\tAcceleration: %d\n\n", (int8_t)(input_report[48])); + return 0; +} // The XBOX Controller is really a HID device that got its HID Report Descriptors // removed by Microsoft. // Input/Output reports described at http://euc.jp/periphs/xbox-controller.ja.html @@ -441,166 +521,11 @@ int test_mass_storage(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t fclose(fd); } } + free(data); return 0; } -// HID -int get_hid_record_size(uint8_t *hid_report_descriptor, int size, int type) -{ - uint8_t i, j = 0; - uint8_t offset; - int record_size[3] = {0, 0, 0}; - int nb_bits = 0, nb_items = 0; - bool found_bits, found_items, found_record_marker; - - found_bits = false; - found_items = false; - found_record_marker = false; - for (i = hid_report_descriptor[0]+1; i < size; i += offset) { - offset = (hid_report_descriptor[i]&0x03) + 1; - if (offset == 4) - offset = 5; - switch (hid_report_descriptor[i] & 0xFC) { - case 0x74: // bitsize - nb_bits = hid_report_descriptor[i+1]; - found_bits = true; - break; - case 0x94: // count - nb_items = 0; - for (j=1; j<offset; j++) { - nb_items = ((uint32_t)hid_report_descriptor[i+j]) << (8*(j-1)); - } - found_items = true; - break; - case 0x80: // input - found_record_marker = true; - j = 0; - break; - case 0x90: // output - found_record_marker = true; - j = 1; - break; - case 0xb0: // feature - found_record_marker = true; - j = 2; - break; - case 0xC0: // end of collection - nb_items = 0; - nb_bits = 0; - break; - default: - continue; - } - if (found_record_marker) { - found_bits = false; - found_items = false; - found_record_marker = false; - record_size[j] += nb_items*nb_bits; - } - } - if ((type < HID_REPORT_TYPE_INPUT) || (type > HID_REPORT_TYPE_FEATURE)) { - return 0; - } else { - return (record_size[type - HID_REPORT_TYPE_INPUT]+7)/8; - } -} - -int test_hid(libusb_device_handle *handle, uint8_t endpoint_in) -{ - int r, size, descriptor_size; - uint8_t hid_report_descriptor[256]; - uint8_t *report_buffer; - FILE *fd; - size_t junk; - - printf("\nReading HID Report Descriptors:\n"); - descriptor_size = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_STANDARD|LIBUSB_RECIPIENT_INTERFACE, - LIBUSB_REQUEST_GET_DESCRIPTOR, LIBUSB_DT_REPORT<<8, 0, hid_report_descriptor, 256, 1000); - if (descriptor_size < 0) { - printf("failed\n"); - return -1; - } - display_buffer_hex(hid_report_descriptor, descriptor_size); - if ((binary_dump) && ((fd = fopen(binary_name, "w")) != NULL)) { - junk = fwrite(hid_report_descriptor, 1, descriptor_size, fd); - fclose(fd); - } - - size = get_hid_record_size(hid_report_descriptor, descriptor_size, HID_REPORT_TYPE_FEATURE); - if (size <= 0) { - printf("\nSkipping Feature Report readout (None detected)\n"); - } else { - report_buffer = calloc(size, 1); - if (report_buffer == NULL) { - return -1; - } - - printf("\nReading Feature Report (length %d)...\n", size); - r = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, - HID_GET_REPORT, (HID_REPORT_TYPE_FEATURE<<8)|0, 0, report_buffer, (uint16_t)size, 5000); - if (r >= 0) { - display_buffer_hex(report_buffer, size); - } else { - switch(r) { - case LIBUSB_ERROR_NOT_FOUND: - printf(" No Feature Report available for this device\n"); - break; - case LIBUSB_ERROR_PIPE: - printf(" Detected stall - resetting pipe...\n"); - libusb_clear_halt(handle, 0); - break; - default: - printf(" Error: %s\n", libusb_strerror(r)); - break; - } - } - free(report_buffer); - } - - size = get_hid_record_size(hid_report_descriptor, descriptor_size, HID_REPORT_TYPE_INPUT); - if (size <= 0) { - printf("\nSkipping Input Report readout (None detected)\n"); - } else { - report_buffer = calloc(size, 1); - if (report_buffer == NULL) { - return -1; - } - - printf("\nReading Input Report (length %d)...\n", size); - r = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, - HID_GET_REPORT, (HID_REPORT_TYPE_INPUT<<8)|0x00, 0, report_buffer, (uint16_t)size, 5000); - if (r >= 0) { - display_buffer_hex(report_buffer, size); - } else { - switch(r) { - case LIBUSB_ERROR_TIMEOUT: - printf(" Timeout! Please make sure you act on the device within the 5 seconds allocated...\n"); - break; - case LIBUSB_ERROR_PIPE: - printf(" Detected stall - resetting pipe...\n"); - libusb_clear_halt(handle, 0); - break; - default: - printf(" Error: %s\n", libusb_strerror(r)); - break; - } - } - - // Attempt a bulk read from endpoint 0 (this should just return a raw input report) - printf("\nTesting interrupt read using endpoint %02X...\n", endpoint_in); - r = libusb_interrupt_transfer(handle, endpoint_in, report_buffer, size, &size, 5000); - if (r >= 0) { - display_buffer_hex(report_buffer, size); - } else { - printf(" %s\n", libusb_strerror(r)); - } - - free(report_buffer); - } - return 0; -} - int test_device(uint16_t vid, uint16_t pid) { libusb_device_handle *handle; @@ -614,7 +539,6 @@ int test_device(uint16_t vid, uint16_t pid) // Attaching/detaching the kernel driver is only relevant for Linux int iface_detached = -1; #endif - bool test_scsi = false; struct libusb_device_descriptor dev_desc; char string[128]; uint8_t string_index[3]; // indexes of the string descriptors @@ -670,7 +594,7 @@ int test_device(uint16_t vid, uint16_t pid) || (conf_desc->usb_interface[i].altsetting[j].bInterfaceSubClass == 0x06) ) && (conf_desc->usb_interface[i].altsetting[j].bInterfaceProtocol == 0x50) ) { // Mass storage devices that can use basic SCSI commands - test_scsi = true; + test_mode = USE_SCSI; } for (k=0; k<conf_desc->usb_interface[i].altsetting[j].bNumEndpoints; k++) { endpoint = &conf_desc->usb_interface[i].altsetting[j].endpoint[k]; @@ -718,23 +642,21 @@ int test_device(uint16_t vid, uint16_t pid) } switch(test_mode) { + case USE_PS3: + CALL_CHECK(display_ps3_status(handle)); + break; case USE_XBOX: CALL_CHECK(display_xbox_status(handle)); CALL_CHECK(set_xbox_actuators(handle, 128, 222)); msleep(2000); CALL_CHECK(set_xbox_actuators(handle, 0, 0)); break; - case USE_HID: - test_hid(handle, endpoint_in); - break; + case USE_SCSI: + CALL_CHECK(test_mass_storage(handle, endpoint_in, endpoint_out)); default: break; } - if (test_scsi) { - CALL_CHECK(test_mass_storage(handle, endpoint_in, endpoint_out)); - } - printf("\n"); for (iface = 0; iface<nb_ifaces; iface++) { printf("Releasing interface %d...\n", iface); @@ -765,10 +687,10 @@ int main(int argc, char** argv) unsigned tmp_vid, tmp_pid; uint16_t endian_test = 0xBE00; - // Default to HID, expecting VID:PID + // Default to generic, expecting VID:PID VID = 0; PID = 0; - test_mode = USE_HID; + test_mode = USE_GENERIC; if (((uint8_t*)&endian_test)[0] == 0xBE) { printf("Despite their natural superiority for end users, big endian\n" @@ -793,13 +715,7 @@ int main(int argc, char** argv) } binary_dump = true; break; - case 'i': - // IBM HID Optical mouse - 1 interface - if (!VID && !PID) { - VID = 0x04B3; - PID = 0x3108; - } - test_mode = USE_HID; + case 'g': break; case 'j': // OLIMEX ARM-USB-TINY JTAG, 2 channel composite device - 2 interfaces @@ -807,7 +723,6 @@ int main(int argc, char** argv) VID = 0x15BA; PID = 0x0004; } - test_mode = USE_JTAG; break; case 'k': // Generic 2 GB USB Key (SCSI Transparent/Bulk Only) - 1 interface @@ -815,20 +730,13 @@ int main(int argc, char** argv) VID = 0x0204; PID = 0x6025; } - test_mode = USE_KEY; break; // The following tests will force VID:PID if already provided - case 'l': - // Plantronics DSP 400, 2 channel HID composite device - 1 HID interface - VID = 0x047F; - PID = 0x0CA1; - test_mode = USE_HID; - break; - case 's': - // Microsoft Sidewinder Precision Pro Joystick - 1 HID interface - VID = 0x045E; - PID = 0x0008; - test_mode = USE_HID; + case 'p': + // Sony PS3 Controller - 1 interface + VID = 0x054C; + PID = 0x0268; + test_mode = USE_PS3; break; case 'x': // Microsoft XBox Controller Type S - 1 interface @@ -861,15 +769,14 @@ int main(int argc, char** argv) } if ((show_help) || (argc == 1) || (argc > 7)) { - printf("usage: %s [-d] [-b [file]] [-h] [-i] [-j] [-k] [-l] [-s] [-x] [vid:pid]\n", argv[0]); + printf("usage: %s [-d] [-b [file]] [-h] [-i] [-j] [-k] [-x] [vid:pid]\n", argv[0]); printf(" -h: display usage\n"); printf(" -d: enable debug output (if library was compiled with debug enabled)\n"); - printf(" -b: dump raw HID report descriptor or Mass Storage first block to binary file\n"); - printf(" -i: test generic HID device (default)\n"); + printf(" -b: dump Mass Storage first block to binary file\n"); + printf(" -g: short generic test (default)\n"); printf(" -k: test generic Mass Storage USB device (using WinUSB)\n"); printf(" -j: test FTDI based JTAG device (using WinUSB)\n"); - printf(" -l: test Plantronics Headset (using HID)\n"); - printf(" -s: test Microsoft Sidewinder Precision Pro (using HID)\n"); + printf(" -p: test Sony PS3 SixAxis controller (using WinUSB)\n"); printf(" -x: test Microsoft XBox Controller Type S (using WinUSB)\n"); return 0; } @@ -889,4 +796,3 @@ int main(int argc, char** argv) return 0; } - diff --git a/libusb/Makefile.am b/libusb/Makefile.am index 59eb5c4..2b6ca7b 100644 --- a/libusb/Makefile.am +++ b/libusb/Makefile.am @@ -1,7 +1,7 @@ all: libusb-1.0.la if CREATE_IMPORT_LIB # Rebuild the import lib from the .def so that MS and MinGW DLLs can be interchanged - $(DLLTOOL) $(DLLTOOLFLAGS) --kill-at --input-def libusb-1.0.def --dllname libusb-1.0.dll --output-lib .libs/libusb-1.0.dll.a + $(DLLTOOL) $(DLLTOOLFLAGS) --kill-at --input-def $(srcdir)/libusb-1.0.def --dllname libusb-1.0.dll --output-lib .libs/libusb-1.0.dll.a endif lib_LTLIBRARIES = libusb-1.0.la @@ -30,11 +30,11 @@ OS_SRC += os/threads_windows.c endif .rc.lo: - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(RC) $(RCFLAGS) -i $< -o $@ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(RC) $(RCFLAGS) -I. -i $< -o $@ endif libusb_1_0_la_CFLAGS = $(VISIBILITY_CFLAGS) $(AM_CFLAGS) $(THREAD_CFLAGS) -libusb_1_0_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(lt_current):$(lt_revision):$(lt_age) +libusb_1_0_la_LDFLAGS = $(LTLDFLAGS) libusb_1_0_la_SOURCES = libusbi.h core.c descriptor.c io.c sync.c $(OS_SRC) \ os/linux_usbfs.h os/darwin_usb.h os/windows_usb.h \ os/threads_posix.h os/threads_windows.h \ diff --git a/libusb/core.c b/libusb/core.c index f09c6cd..32811c1 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -706,7 +706,6 @@ int API_EXPORTED libusb_get_port_path(libusb_context *ctx, libusb_device *dev, u // TODO: see how the other backends want to implement HCDs as parents if (dev->port_number == 0) break; - usbi_dbg("another one (addy: %d)", dev->device_address); if (--i<0) { return LIBUSB_ERROR_OVERFLOW; } diff --git a/libusb/io.c b/libusb/io.c index b23c76b..dd56857 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1793,7 +1793,7 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) { int r; struct usbi_pollfd *ipollfd; - nfds_t nfds = 0; + POLL_NFDS_TYPE nfds = 0; struct pollfd *fds; int i = -1; int timeout_ms; @@ -1937,8 +1937,8 @@ static int get_next_timeout(libusb_context *ctx, struct timeval *tv, * non-blocking mode * \returns 0 on success, or a LIBUSB_ERROR code on failure */ -int API_EXPORTED libusb_handle_events_timeout_check(libusb_context *ctx, - struct timeval *tv, int *completed) +int API_EXPORTED libusb_handle_events_timeout(libusb_context *ctx, + struct timeval *tv) { int r; struct timeval poll_timeout; @@ -1952,12 +1952,8 @@ int API_EXPORTED libusb_handle_events_timeout_check(libusb_context *ctx, retry: if (libusb_try_lock_events(ctx) == 0) { - r = 0; - if (completed == NULL || !*completed) { - /* we obtained the event lock: do our own event handling */ - usbi_dbg("doing our own event handling"); - r = handle_events(ctx, &poll_timeout); - } + /* we obtained the event lock: do our own event handling */ + r = handle_events(ctx, &poll_timeout); libusb_unlock_events(ctx); return r; } @@ -1966,18 +1962,16 @@ retry: * notify event completion. */ libusb_lock_event_waiters(ctx); - if (completed == NULL || !*completed) { - if (!libusb_event_handler_active(ctx)) { - /* we hit a race: whoever was event handling earlier finished in the - * time it took us to reach this point. try the cycle again. */ - libusb_unlock_event_waiters(ctx); - usbi_dbg("event handler was active but went away, retrying"); - goto retry; - } - - usbi_dbg("another thread is doing event handling, wait for notification"); - r = libusb_wait_for_event(ctx, &poll_timeout); + if (!libusb_event_handler_active(ctx)) { + /* we hit a race: whoever was event handling earlier finished in the + * time it took us to reach this point. try the cycle again. */ + libusb_unlock_event_waiters(ctx); + usbi_dbg("event handler was active but went away, retrying"); + goto retry; } + + usbi_dbg("another thread is doing event handling"); + r = libusb_wait_for_event(ctx, &poll_timeout); libusb_unlock_event_waiters(ctx); if (r < 0) @@ -1988,21 +1982,6 @@ retry: return 0; } -int API_EXPORTED libusb_handle_events_timeout(libusb_context *ctx, - struct timeval *tv) -{ - return libusb_handle_events_timeout_check(ctx, tv, NULL); -} - -int API_EXPORTED libusb_handle_events_check(libusb_context *ctx, - int *completed) -{ - struct timeval tv; - tv.tv_sec = 60; - tv.tv_usec = 0; - return libusb_handle_events_timeout_check(ctx, &tv, completed); -} - /** \ingroup 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 @@ -2017,7 +1996,7 @@ int API_EXPORTED libusb_handle_events(libusb_context *ctx) struct timeval tv; tv.tv_sec = 60; tv.tv_usec = 0; - return libusb_handle_events_timeout_check(ctx, &tv, NULL); + return libusb_handle_events_timeout(ctx, &tv); } /** \ingroup poll @@ -2145,24 +2124,22 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx, if (transfer->flags & (USBI_TRANSFER_TIMED_OUT | USBI_TRANSFER_OS_HANDLES_TIMEOUT)) continue; + /* no timeout for this transfer? */ + if (!timerisset(&transfer->timeout)) + continue; + found = 1; break; } usbi_mutex_unlock(&ctx->flying_transfers_lock); if (!found) { - usbi_dbg("all URBs have already been processed for timeouts"); + usbi_dbg("no URB with timeout or all handled by OS; no timeout!"); return 0; } next_timeout = &transfer->timeout; - /* no timeout for next transfer */ - if (!timerisset(next_timeout)) { - usbi_dbg("no URBs with timeouts, no timeout!"); - return 0; - } - r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &cur_ts); if (r < 0) { usbi_err(ctx, "failed to read monotonic clock, errno=%d", errno); diff --git a/libusb/libusb-1.0.def b/libusb/libusb-1.0.def index d437796..1ae2756 100644 --- a/libusb/libusb-1.0.def +++ b/libusb/libusb-1.0.def @@ -1,602 +1,582 @@ LIBRARY EXPORTS libusb_alloc_transfer - libusb_alloc_transfer@00 = libusb_alloc_transfer - libusb_alloc_transfer@04 = libusb_alloc_transfer - libusb_alloc_transfer@08 = libusb_alloc_transfer + libusb_alloc_transfer@0 = libusb_alloc_transfer libusb_alloc_transfer@12 = libusb_alloc_transfer libusb_alloc_transfer@16 = libusb_alloc_transfer libusb_alloc_transfer@20 = libusb_alloc_transfer libusb_alloc_transfer@24 = libusb_alloc_transfer libusb_alloc_transfer@28 = libusb_alloc_transfer libusb_alloc_transfer@32 = libusb_alloc_transfer + libusb_alloc_transfer@4 = libusb_alloc_transfer + libusb_alloc_transfer@8 = libusb_alloc_transfer libusb_attach_kernel_driver - libusb_attach_kernel_driver@00 = libusb_attach_kernel_driver - libusb_attach_kernel_driver@04 = libusb_attach_kernel_driver - libusb_attach_kernel_driver@08 = libusb_attach_kernel_driver + libusb_attach_kernel_driver@0 = libusb_attach_kernel_driver libusb_attach_kernel_driver@12 = libusb_attach_kernel_driver libusb_attach_kernel_driver@16 = libusb_attach_kernel_driver libusb_attach_kernel_driver@20 = libusb_attach_kernel_driver libusb_attach_kernel_driver@24 = libusb_attach_kernel_driver libusb_attach_kernel_driver@28 = libusb_attach_kernel_driver libusb_attach_kernel_driver@32 = libusb_attach_kernel_driver + libusb_attach_kernel_driver@4 = libusb_attach_kernel_driver + libusb_attach_kernel_driver@8 = libusb_attach_kernel_driver libusb_bulk_transfer - libusb_bulk_transfer@00 = libusb_bulk_transfer - libusb_bulk_transfer@04 = libusb_bulk_transfer - libusb_bulk_transfer@08 = libusb_bulk_transfer + libusb_bulk_transfer@0 = libusb_bulk_transfer libusb_bulk_transfer@12 = libusb_bulk_transfer libusb_bulk_transfer@16 = libusb_bulk_transfer libusb_bulk_transfer@20 = libusb_bulk_transfer libusb_bulk_transfer@24 = libusb_bulk_transfer libusb_bulk_transfer@28 = libusb_bulk_transfer libusb_bulk_transfer@32 = libusb_bulk_transfer + libusb_bulk_transfer@4 = libusb_bulk_transfer + libusb_bulk_transfer@8 = libusb_bulk_transfer libusb_cancel_transfer - libusb_cancel_transfer@00 = libusb_cancel_transfer - libusb_cancel_transfer@04 = libusb_cancel_transfer - libusb_cancel_transfer@08 = libusb_cancel_transfer + libusb_cancel_transfer@0 = libusb_cancel_transfer libusb_cancel_transfer@12 = libusb_cancel_transfer libusb_cancel_transfer@16 = libusb_cancel_transfer libusb_cancel_transfer@20 = libusb_cancel_transfer libusb_cancel_transfer@24 = libusb_cancel_transfer libusb_cancel_transfer@28 = libusb_cancel_transfer libusb_cancel_transfer@32 = libusb_cancel_transfer + libusb_cancel_transfer@4 = libusb_cancel_transfer + libusb_cancel_transfer@8 = libusb_cancel_transfer libusb_claim_interface - libusb_claim_interface@00 = libusb_claim_interface - libusb_claim_interface@04 = libusb_claim_interface - libusb_claim_interface@08 = libusb_claim_interface + libusb_claim_interface@0 = libusb_claim_interface libusb_claim_interface@12 = libusb_claim_interface libusb_claim_interface@16 = libusb_claim_interface libusb_claim_interface@20 = libusb_claim_interface libusb_claim_interface@24 = libusb_claim_interface libusb_claim_interface@28 = libusb_claim_interface libusb_claim_interface@32 = libusb_claim_interface + libusb_claim_interface@4 = libusb_claim_interface + libusb_claim_interface@8 = libusb_claim_interface libusb_clear_halt - libusb_clear_halt@00 = libusb_clear_halt - libusb_clear_halt@04 = libusb_clear_halt - libusb_clear_halt@08 = libusb_clear_halt + libusb_clear_halt@0 = libusb_clear_halt libusb_clear_halt@12 = libusb_clear_halt libusb_clear_halt@16 = libusb_clear_halt libusb_clear_halt@20 = libusb_clear_halt libusb_clear_halt@24 = libusb_clear_halt libusb_clear_halt@28 = libusb_clear_halt libusb_clear_halt@32 = libusb_clear_halt + libusb_clear_halt@4 = libusb_clear_halt + libusb_clear_halt@8 = libusb_clear_halt libusb_close - libusb_close@00 = libusb_close - libusb_close@04 = libusb_close - libusb_close@08 = libusb_close + libusb_close@0 = libusb_close libusb_close@12 = libusb_close libusb_close@16 = libusb_close libusb_close@20 = libusb_close libusb_close@24 = libusb_close libusb_close@28 = libusb_close libusb_close@32 = libusb_close + libusb_close@4 = libusb_close + libusb_close@8 = libusb_close libusb_control_transfer - libusb_control_transfer@00 = libusb_control_transfer - libusb_control_transfer@04 = libusb_control_transfer - libusb_control_transfer@08 = libusb_control_transfer + libusb_control_transfer@0 = libusb_control_transfer libusb_control_transfer@12 = libusb_control_transfer libusb_control_transfer@16 = libusb_control_transfer libusb_control_transfer@20 = libusb_control_transfer libusb_control_transfer@24 = libusb_control_transfer libusb_control_transfer@28 = libusb_control_transfer libusb_control_transfer@32 = libusb_control_transfer + libusb_control_transfer@4 = libusb_control_transfer + libusb_control_transfer@8 = libusb_control_transfer libusb_detach_kernel_driver - libusb_detach_kernel_driver@00 = libusb_detach_kernel_driver - libusb_detach_kernel_driver@04 = libusb_detach_kernel_driver - libusb_detach_kernel_driver@08 = libusb_detach_kernel_driver + libusb_detach_kernel_driver@0 = libusb_detach_kernel_driver libusb_detach_kernel_driver@12 = libusb_detach_kernel_driver libusb_detach_kernel_driver@16 = libusb_detach_kernel_driver libusb_detach_kernel_driver@20 = libusb_detach_kernel_driver libusb_detach_kernel_driver@24 = libusb_detach_kernel_driver libusb_detach_kernel_driver@28 = libusb_detach_kernel_driver libusb_detach_kernel_driver@32 = libusb_detach_kernel_driver + libusb_detach_kernel_driver@4 = libusb_detach_kernel_driver + libusb_detach_kernel_driver@8 = libusb_detach_kernel_driver libusb_event_handler_active - libusb_event_handler_active@00 = libusb_event_handler_active - libusb_event_handler_active@04 = libusb_event_handler_active - libusb_event_handler_active@08 = libusb_event_handler_active + libusb_event_handler_active@0 = libusb_event_handler_active libusb_event_handler_active@12 = libusb_event_handler_active libusb_event_handler_active@16 = libusb_event_handler_active libusb_event_handler_active@20 = libusb_event_handler_active libusb_event_handler_active@24 = libusb_event_handler_active libusb_event_handler_active@28 = libusb_event_handler_active libusb_event_handler_active@32 = libusb_event_handler_active + libusb_event_handler_active@4 = libusb_event_handler_active + libusb_event_handler_active@8 = libusb_event_handler_active libusb_event_handling_ok - libusb_event_handling_ok@00 = libusb_event_handling_ok - libusb_event_handling_ok@04 = libusb_event_handling_ok - libusb_event_handling_ok@08 = libusb_event_handling_ok + libusb_event_handling_ok@0 = libusb_event_handling_ok libusb_event_handling_ok@12 = libusb_event_handling_ok libusb_event_handling_ok@16 = libusb_event_handling_ok libusb_event_handling_ok@20 = libusb_event_handling_ok libusb_event_handling_ok@24 = libusb_event_handling_ok libusb_event_handling_ok@28 = libusb_event_handling_ok libusb_event_handling_ok@32 = libusb_event_handling_ok + libusb_event_handling_ok@4 = libusb_event_handling_ok + libusb_event_handling_ok@8 = libusb_event_handling_ok libusb_exit - libusb_exit@00 = libusb_exit - libusb_exit@04 = libusb_exit - libusb_exit@08 = libusb_exit + libusb_exit@0 = libusb_exit libusb_exit@12 = libusb_exit libusb_exit@16 = libusb_exit libusb_exit@20 = libusb_exit libusb_exit@24 = libusb_exit libusb_exit@28 = libusb_exit libusb_exit@32 = libusb_exit + libusb_exit@4 = libusb_exit + libusb_exit@8 = libusb_exit libusb_free_config_descriptor - libusb_free_config_descriptor@00 = libusb_free_config_descriptor - libusb_free_config_descriptor@04 = libusb_free_config_descriptor - libusb_free_config_descriptor@08 = libusb_free_config_descriptor + libusb_free_config_descriptor@0 = libusb_free_config_descriptor libusb_free_config_descriptor@12 = libusb_free_config_descriptor libusb_free_config_descriptor@16 = libusb_free_config_descriptor libusb_free_config_descriptor@20 = libusb_free_config_descriptor libusb_free_config_descriptor@24 = libusb_free_config_descriptor libusb_free_config_descriptor@28 = libusb_free_config_descriptor libusb_free_config_descriptor@32 = libusb_free_config_descriptor + libusb_free_config_descriptor@4 = libusb_free_config_descriptor + libusb_free_config_descriptor@8 = libusb_free_config_descriptor libusb_free_device_list - libusb_free_device_list@00 = libusb_free_device_list - libusb_free_device_list@04 = libusb_free_device_list - libusb_free_device_list@08 = libusb_free_device_list + libusb_free_device_list@0 = libusb_free_device_list libusb_free_device_list@12 = libusb_free_device_list libusb_free_device_list@16 = libusb_free_device_list libusb_free_device_list@20 = libusb_free_device_list libusb_free_device_list@24 = libusb_free_device_list libusb_free_device_list@28 = libusb_free_device_list libusb_free_device_list@32 = libusb_free_device_list + libusb_free_device_list@4 = libusb_free_device_list + libusb_free_device_list@8 = libusb_free_device_list libusb_free_transfer - libusb_free_transfer@00 = libusb_free_transfer - libusb_free_transfer@04 = libusb_free_transfer - libusb_free_transfer@08 = libusb_free_transfer + libusb_free_transfer@0 = libusb_free_transfer libusb_free_transfer@12 = libusb_free_transfer libusb_free_transfer@16 = libusb_free_transfer libusb_free_transfer@20 = libusb_free_transfer libusb_free_transfer@24 = libusb_free_transfer libusb_free_transfer@28 = libusb_free_transfer libusb_free_transfer@32 = libusb_free_transfer + libusb_free_transfer@4 = libusb_free_transfer + libusb_free_transfer@8 = libusb_free_transfer libusb_get_active_config_descriptor - libusb_get_active_config_descriptor@00 = libusb_get_active_config_descriptor - libusb_get_active_config_descriptor@04 = libusb_get_active_config_descriptor - libusb_get_active_config_descriptor@08 = libusb_get_active_config_descriptor + libusb_get_active_config_descriptor@0 = libusb_get_active_config_descriptor libusb_get_active_config_descriptor@12 = libusb_get_active_config_descriptor libusb_get_active_config_descriptor@16 = libusb_get_active_config_descriptor libusb_get_active_config_descriptor@20 = libusb_get_active_config_descriptor libusb_get_active_config_descriptor@24 = libusb_get_active_config_descriptor libusb_get_active_config_descriptor@28 = libusb_get_active_config_descriptor libusb_get_active_config_descriptor@32 = libusb_get_active_config_descriptor + libusb_get_active_config_descriptor@4 = libusb_get_active_config_descriptor + libusb_get_active_config_descriptor@8 = libusb_get_active_config_descriptor libusb_get_bus_number - libusb_get_bus_number@00 = libusb_get_bus_number - libusb_get_bus_number@04 = libusb_get_bus_number - libusb_get_bus_number@08 = libusb_get_bus_number + libusb_get_bus_number@0 = libusb_get_bus_number libusb_get_bus_number@12 = libusb_get_bus_number libusb_get_bus_number@16 = libusb_get_bus_number libusb_get_bus_number@20 = libusb_get_bus_number libusb_get_bus_number@24 = libusb_get_bus_number libusb_get_bus_number@28 = libusb_get_bus_number libusb_get_bus_number@32 = libusb_get_bus_number + libusb_get_bus_number@4 = libusb_get_bus_number + libusb_get_bus_number@8 = libusb_get_bus_number libusb_get_config_descriptor - libusb_get_config_descriptor@00 = libusb_get_config_descriptor - libusb_get_config_descriptor@04 = libusb_get_config_descriptor - libusb_get_config_descriptor@08 = libusb_get_config_descriptor + libusb_get_config_descriptor@0 = libusb_get_config_descriptor libusb_get_config_descriptor@12 = libusb_get_config_descriptor libusb_get_config_descriptor@16 = libusb_get_config_descriptor libusb_get_config_descriptor@20 = libusb_get_config_descriptor libusb_get_config_descriptor@24 = libusb_get_config_descriptor libusb_get_config_descriptor@28 = libusb_get_config_descriptor libusb_get_config_descriptor@32 = libusb_get_config_descriptor + libusb_get_config_descriptor@4 = libusb_get_config_descriptor + libusb_get_config_descriptor@8 = libusb_get_config_descriptor libusb_get_config_descriptor_by_value - libusb_get_config_descriptor_by_value@00 = libusb_get_config_descriptor_by_value - libusb_get_config_descriptor_by_value@04 = libusb_get_config_descriptor_by_value - libusb_get_config_descriptor_by_value@08 = libusb_get_config_descriptor_by_value + libusb_get_config_descriptor_by_value@0 = libusb_get_config_descriptor_by_value libusb_get_config_descriptor_by_value@12 = libusb_get_config_descriptor_by_value libusb_get_config_descriptor_by_value@16 = libusb_get_config_descriptor_by_value libusb_get_config_descriptor_by_value@20 = libusb_get_config_descriptor_by_value libusb_get_config_descriptor_by_value@24 = libusb_get_config_descriptor_by_value libusb_get_config_descriptor_by_value@28 = libusb_get_config_descriptor_by_value libusb_get_config_descriptor_by_value@32 = libusb_get_config_descriptor_by_value + libusb_get_config_descriptor_by_value@4 = libusb_get_config_descriptor_by_value + libusb_get_config_descriptor_by_value@8 = libusb_get_config_descriptor_by_value libusb_get_configuration - libusb_get_configuration@00 = libusb_get_configuration - libusb_get_configuration@04 = libusb_get_configuration - libusb_get_configuration@08 = libusb_get_configuration + libusb_get_configuration@0 = libusb_get_configuration libusb_get_configuration@12 = libusb_get_configuration libusb_get_configuration@16 = libusb_get_configuration libusb_get_configuration@20 = libusb_get_configuration libusb_get_configuration@24 = libusb_get_configuration libusb_get_configuration@28 = libusb_get_configuration libusb_get_configuration@32 = libusb_get_configuration + libusb_get_configuration@4 = libusb_get_configuration + libusb_get_configuration@8 = libusb_get_configuration libusb_get_device - libusb_get_device@00 = libusb_get_device - libusb_get_device@04 = libusb_get_device - libusb_get_device@08 = libusb_get_device + libusb_get_device@0 = libusb_get_device libusb_get_device@12 = libusb_get_device libusb_get_device@16 = libusb_get_device libusb_get_device@20 = libusb_get_device libusb_get_device@24 = libusb_get_device libusb_get_device@28 = libusb_get_device libusb_get_device@32 = libusb_get_device + libusb_get_device@4 = libusb_get_device + libusb_get_device@8 = libusb_get_device libusb_get_device_address - libusb_get_device_address@00 = libusb_get_device_address - libusb_get_device_address@04 = libusb_get_device_address - libusb_get_device_address@08 = libusb_get_device_address + libusb_get_device_address@0 = libusb_get_device_address libusb_get_device_address@12 = libusb_get_device_address libusb_get_device_address@16 = libusb_get_device_address libusb_get_device_address@20 = libusb_get_device_address libusb_get_device_address@24 = libusb_get_device_address libusb_get_device_address@28 = libusb_get_device_address libusb_get_device_address@32 = libusb_get_device_address + libusb_get_device_address@4 = libusb_get_device_address + libusb_get_device_address@8 = libusb_get_device_address libusb_get_device_descriptor - libusb_get_device_descriptor@00 = libusb_get_device_descriptor - libusb_get_device_descriptor@04 = libusb_get_device_descriptor - libusb_get_device_descriptor@08 = libusb_get_device_descriptor + libusb_get_device_descriptor@0 = libusb_get_device_descriptor libusb_get_device_descriptor@12 = libusb_get_device_descriptor libusb_get_device_descriptor@16 = libusb_get_device_descriptor libusb_get_device_descriptor@20 = libusb_get_device_descriptor libusb_get_device_descriptor@24 = libusb_get_device_descriptor libusb_get_device_descriptor@28 = libusb_get_device_descriptor libusb_get_device_descriptor@32 = libusb_get_device_descriptor + libusb_get_device_descriptor@4 = libusb_get_device_descriptor + libusb_get_device_descriptor@8 = libusb_get_device_descriptor libusb_get_device_list - libusb_get_device_list@00 = libusb_get_device_list - libusb_get_device_list@04 = libusb_get_device_list - libusb_get_device_list@08 = libusb_get_device_list + libusb_get_device_list@0 = libusb_get_device_list libusb_get_device_list@12 = libusb_get_device_list libusb_get_device_list@16 = libusb_get_device_list libusb_get_device_list@20 = libusb_get_device_list libusb_get_device_list@24 = libusb_get_device_list libusb_get_device_list@28 = libusb_get_device_list libusb_get_device_list@32 = libusb_get_device_list + libusb_get_device_list@4 = libusb_get_device_list + libusb_get_device_list@8 = libusb_get_device_list libusb_get_max_iso_packet_size - libusb_get_max_iso_packet_size@00 = libusb_get_max_iso_packet_size - libusb_get_max_iso_packet_size@04 = libusb_get_max_iso_packet_size - libusb_get_max_iso_packet_size@08 = libusb_get_max_iso_packet_size + libusb_get_max_iso_packet_size@0 = libusb_get_max_iso_packet_size libusb_get_max_iso_packet_size@12 = libusb_get_max_iso_packet_size libusb_get_max_iso_packet_size@16 = libusb_get_max_iso_packet_size libusb_get_max_iso_packet_size@20 = libusb_get_max_iso_packet_size libusb_get_max_iso_packet_size@24 = libusb_get_max_iso_packet_size libusb_get_max_iso_packet_size@28 = libusb_get_max_iso_packet_size libusb_get_max_iso_packet_size@32 = libusb_get_max_iso_packet_size + libusb_get_max_iso_packet_size@4 = libusb_get_max_iso_packet_size + libusb_get_max_iso_packet_size@8 = libusb_get_max_iso_packet_size libusb_get_max_packet_size - libusb_get_max_packet_size@00 = libusb_get_max_packet_size - libusb_get_max_packet_size@04 = libusb_get_max_packet_size - libusb_get_max_packet_size@08 = libusb_get_max_packet_size + libusb_get_max_packet_size@0 = libusb_get_max_packet_size libusb_get_max_packet_size@12 = libusb_get_max_packet_size libusb_get_max_packet_size@16 = libusb_get_max_packet_size libusb_get_max_packet_size@20 = libusb_get_max_packet_size libusb_get_max_packet_size@24 = libusb_get_max_packet_size libusb_get_max_packet_size@28 = libusb_get_max_packet_size libusb_get_max_packet_size@32 = libusb_get_max_packet_size + libusb_get_max_packet_size@4 = libusb_get_max_packet_size + libusb_get_max_packet_size@8 = libusb_get_max_packet_size libusb_get_next_timeout - libusb_get_next_timeout@00 = libusb_get_next_timeout - libusb_get_next_timeout@04 = libusb_get_next_timeout - libusb_get_next_timeout@08 = libusb_get_next_timeout + libusb_get_next_timeout@0 = libusb_get_next_timeout libusb_get_next_timeout@12 = libusb_get_next_timeout libusb_get_next_timeout@16 = libusb_get_next_timeout libusb_get_next_timeout@20 = libusb_get_next_timeout libusb_get_next_timeout@24 = libusb_get_next_timeout libusb_get_next_timeout@28 = libusb_get_next_timeout libusb_get_next_timeout@32 = libusb_get_next_timeout + libusb_get_next_timeout@4 = libusb_get_next_timeout + libusb_get_next_timeout@8 = libusb_get_next_timeout libusb_get_parent - libusb_get_parent@00 = libusb_get_parent - libusb_get_parent@04 = libusb_get_parent - libusb_get_parent@08 = libusb_get_parent + libusb_get_parent@0 = libusb_get_parent libusb_get_parent@12 = libusb_get_parent libusb_get_parent@16 = libusb_get_parent libusb_get_parent@20 = libusb_get_parent libusb_get_parent@24 = libusb_get_parent libusb_get_parent@28 = libusb_get_parent libusb_get_parent@32 = libusb_get_parent + libusb_get_parent@4 = libusb_get_parent + libusb_get_parent@8 = libusb_get_parent libusb_get_pollfds - libusb_get_pollfds@00 = libusb_get_pollfds - libusb_get_pollfds@04 = libusb_get_pollfds - libusb_get_pollfds@08 = libusb_get_pollfds + libusb_get_pollfds@0 = libusb_get_pollfds libusb_get_pollfds@12 = libusb_get_pollfds libusb_get_pollfds@16 = libusb_get_pollfds libusb_get_pollfds@20 = libusb_get_pollfds libusb_get_pollfds@24 = libusb_get_pollfds libusb_get_pollfds@28 = libusb_get_pollfds libusb_get_pollfds@32 = libusb_get_pollfds + libusb_get_pollfds@4 = libusb_get_pollfds + libusb_get_pollfds@8 = libusb_get_pollfds libusb_get_port_number - libusb_get_port_number@00 = libusb_get_port_number - libusb_get_port_number@04 = libusb_get_port_number - libusb_get_port_number@08 = libusb_get_port_number + libusb_get_port_number@0 = libusb_get_port_number libusb_get_port_number@12 = libusb_get_port_number libusb_get_port_number@16 = libusb_get_port_number libusb_get_port_number@20 = libusb_get_port_number libusb_get_port_number@24 = libusb_get_port_number libusb_get_port_number@28 = libusb_get_port_number libusb_get_port_number@32 = libusb_get_port_number + libusb_get_port_number@4 = libusb_get_port_number + libusb_get_port_number@8 = libusb_get_port_number libusb_get_port_path - libusb_get_port_path@00 = libusb_get_port_path - libusb_get_port_path@04 = libusb_get_port_path - libusb_get_port_path@08 = libusb_get_port_path + libusb_get_port_path@0 = libusb_get_port_path libusb_get_port_path@12 = libusb_get_port_path libusb_get_port_path@16 = libusb_get_port_path libusb_get_port_path@20 = libusb_get_port_path libusb_get_port_path@24 = libusb_get_port_path libusb_get_port_path@28 = libusb_get_port_path libusb_get_port_path@32 = libusb_get_port_path + libusb_get_port_path@4 = libusb_get_port_path + libusb_get_port_path@8 = libusb_get_port_path libusb_get_string_descriptor_ascii - libusb_get_string_descriptor_ascii@00 = libusb_get_string_descriptor_ascii - libusb_get_string_descriptor_ascii@04 = libusb_get_string_descriptor_ascii - libusb_get_string_descriptor_ascii@08 = libusb_get_string_descriptor_ascii + libusb_get_string_descriptor_ascii@0 = libusb_get_string_descriptor_ascii libusb_get_string_descriptor_ascii@12 = libusb_get_string_descriptor_ascii libusb_get_string_descriptor_ascii@16 = libusb_get_string_descriptor_ascii libusb_get_string_descriptor_ascii@20 = libusb_get_string_descriptor_ascii libusb_get_string_descriptor_ascii@24 = libusb_get_string_descriptor_ascii libusb_get_string_descriptor_ascii@28 = libusb_get_string_descriptor_ascii libusb_get_string_descriptor_ascii@32 = libusb_get_string_descriptor_ascii + libusb_get_string_descriptor_ascii@4 = libusb_get_string_descriptor_ascii + libusb_get_string_descriptor_ascii@8 = libusb_get_string_descriptor_ascii libusb_getversion - libusb_getversion@00 = libusb_getversion - libusb_getversion@04 = libusb_getversion - libusb_getversion@08 = libusb_getversion + libusb_getversion@0 = libusb_getversion libusb_getversion@12 = libusb_getversion libusb_getversion@16 = libusb_getversion libusb_getversion@20 = libusb_getversion libusb_getversion@24 = libusb_getversion libusb_getversion@28 = libusb_getversion libusb_getversion@32 = libusb_getversion + libusb_getversion@4 = libusb_getversion + libusb_getversion@8 = libusb_getversion libusb_handle_events - libusb_handle_events@00 = libusb_handle_events - libusb_handle_events@04 = libusb_handle_events - libusb_handle_events@08 = libusb_handle_events + libusb_handle_events@0 = libusb_handle_events libusb_handle_events@12 = libusb_handle_events libusb_handle_events@16 = libusb_handle_events libusb_handle_events@20 = libusb_handle_events libusb_handle_events@24 = libusb_handle_events libusb_handle_events@28 = libusb_handle_events libusb_handle_events@32 = libusb_handle_events - libusb_handle_events_check - libusb_handle_events_check@00 = libusb_handle_events_check - libusb_handle_events_check@04 = libusb_handle_events_check - libusb_handle_events_check@08 = libusb_handle_events_check - libusb_handle_events_check@12 = libusb_handle_events_check - libusb_handle_events_check@16 = libusb_handle_events_check - libusb_handle_events_check@20 = libusb_handle_events_check - libusb_handle_events_check@24 = libusb_handle_events_check - libusb_handle_events_check@28 = libusb_handle_events_check - libusb_handle_events_check@32 = libusb_handle_events_check + libusb_handle_events@4 = libusb_handle_events + libusb_handle_events@8 = libusb_handle_events libusb_handle_events_locked - libusb_handle_events_locked@00 = libusb_handle_events_locked - libusb_handle_events_locked@04 = libusb_handle_events_locked - libusb_handle_events_locked@08 = libusb_handle_events_locked + libusb_handle_events_locked@0 = libusb_handle_events_locked libusb_handle_events_locked@12 = libusb_handle_events_locked libusb_handle_events_locked@16 = libusb_handle_events_locked libusb_handle_events_locked@20 = libusb_handle_events_locked libusb_handle_events_locked@24 = libusb_handle_events_locked libusb_handle_events_locked@28 = libusb_handle_events_locked libusb_handle_events_locked@32 = libusb_handle_events_locked + libusb_handle_events_locked@4 = libusb_handle_events_locked + libusb_handle_events_locked@8 = libusb_handle_events_locked libusb_handle_events_timeout - libusb_handle_events_timeout@00 = libusb_handle_events_timeout - libusb_handle_events_timeout@04 = libusb_handle_events_timeout - libusb_handle_events_timeout@08 = libusb_handle_events_timeout + libusb_handle_events_timeout@0 = libusb_handle_events_timeout libusb_handle_events_timeout@12 = libusb_handle_events_timeout libusb_handle_events_timeout@16 = libusb_handle_events_timeout libusb_handle_events_timeout@20 = libusb_handle_events_timeout libusb_handle_events_timeout@24 = libusb_handle_events_timeout libusb_handle_events_timeout@28 = libusb_handle_events_timeout libusb_handle_events_timeout@32 = libusb_handle_events_timeout - libusb_handle_events_timeout_check - libusb_handle_events_timeout_check@00 = libusb_handle_events_timeout_check - libusb_handle_events_timeout_check@04 = libusb_handle_events_timeout_check - libusb_handle_events_timeout_check@08 = libusb_handle_events_timeout_check - libusb_handle_events_timeout_check@12 = libusb_handle_events_timeout_check - libusb_handle_events_timeout_check@16 = libusb_handle_events_timeout_check - libusb_handle_events_timeout_check@20 = libusb_handle_events_timeout_check - libusb_handle_events_timeout_check@24 = libusb_handle_events_timeout_check - libusb_handle_events_timeout_check@28 = libusb_handle_events_timeout_check - libusb_handle_events_timeout_check@32 = libusb_handle_events_timeout_check + libusb_handle_events_timeout@4 = libusb_handle_events_timeout + libusb_handle_events_timeout@8 = libusb_handle_events_timeout libusb_init - libusb_init@00 = libusb_init - libusb_init@04 = libusb_init - libusb_init@08 = libusb_init + libusb_init@0 = libusb_init libusb_init@12 = libusb_init libusb_init@16 = libusb_init libusb_init@20 = libusb_init libusb_init@24 = libusb_init libusb_init@28 = libusb_init libusb_init@32 = libusb_init + libusb_init@4 = libusb_init + libusb_init@8 = libusb_init libusb_interrupt_transfer - libusb_interrupt_transfer@00 = libusb_interrupt_transfer - libusb_interrupt_transfer@04 = libusb_interrupt_transfer - libusb_interrupt_transfer@08 = libusb_interrupt_transfer + libusb_interrupt_transfer@0 = libusb_interrupt_transfer libusb_interrupt_transfer@12 = libusb_interrupt_transfer libusb_interrupt_transfer@16 = libusb_interrupt_transfer libusb_interrupt_transfer@20 = libusb_interrupt_transfer libusb_interrupt_transfer@24 = libusb_interrupt_transfer libusb_interrupt_transfer@28 = libusb_interrupt_transfer libusb_interrupt_transfer@32 = libusb_interrupt_transfer + libusb_interrupt_transfer@4 = libusb_interrupt_transfer + libusb_interrupt_transfer@8 = libusb_interrupt_transfer libusb_kernel_driver_active - libusb_kernel_driver_active@00 = libusb_kernel_driver_active - libusb_kernel_driver_active@04 = libusb_kernel_driver_active - libusb_kernel_driver_active@08 = libusb_kernel_driver_active + libusb_kernel_driver_active@0 = libusb_kernel_driver_active libusb_kernel_driver_active@12 = libusb_kernel_driver_active libusb_kernel_driver_active@16 = libusb_kernel_driver_active libusb_kernel_driver_active@20 = libusb_kernel_driver_active libusb_kernel_driver_active@24 = libusb_kernel_driver_active libusb_kernel_driver_active@28 = libusb_kernel_driver_active libusb_kernel_driver_active@32 = libusb_kernel_driver_active + libusb_kernel_driver_active@4 = libusb_kernel_driver_active + libusb_kernel_driver_active@8 = libusb_kernel_driver_active libusb_lock_event_waiters - libusb_lock_event_waiters@00 = libusb_lock_event_waiters - libusb_lock_event_waiters@04 = libusb_lock_event_waiters - libusb_lock_event_waiters@08 = libusb_lock_event_waiters + libusb_lock_event_waiters@0 = libusb_lock_event_waiters libusb_lock_event_waiters@12 = libusb_lock_event_waiters libusb_lock_event_waiters@16 = libusb_lock_event_waiters libusb_lock_event_waiters@20 = libusb_lock_event_waiters libusb_lock_event_waiters@24 = libusb_lock_event_waiters libusb_lock_event_waiters@28 = libusb_lock_event_waiters libusb_lock_event_waiters@32 = libusb_lock_event_waiters + libusb_lock_event_waiters@4 = libusb_lock_event_waiters + libusb_lock_event_waiters@8 = libusb_lock_event_waiters libusb_lock_events - libusb_lock_events@00 = libusb_lock_events - libusb_lock_events@04 = libusb_lock_events - libusb_lock_events@08 = libusb_lock_events + libusb_lock_events@0 = libusb_lock_events libusb_lock_events@12 = libusb_lock_events libusb_lock_events@16 = libusb_lock_events libusb_lock_events@20 = libusb_lock_events libusb_lock_events@24 = libusb_lock_events libusb_lock_events@28 = libusb_lock_events libusb_lock_events@32 = libusb_lock_events + libusb_lock_events@4 = libusb_lock_events + libusb_lock_events@8 = libusb_lock_events libusb_open - libusb_open@00 = libusb_open - libusb_open@04 = libusb_open - libusb_open@08 = libusb_open + libusb_open@0 = libusb_open libusb_open@12 = libusb_open libusb_open@16 = libusb_open libusb_open@20 = libusb_open libusb_open@24 = libusb_open libusb_open@28 = libusb_open libusb_open@32 = libusb_open + libusb_open@4 = libusb_open + libusb_open@8 = libusb_open libusb_open_device_with_vid_pid - libusb_open_device_with_vid_pid@00 = libusb_open_device_with_vid_pid - libusb_open_device_with_vid_pid@04 = libusb_open_device_with_vid_pid - libusb_open_device_with_vid_pid@08 = libusb_open_device_with_vid_pid + libusb_open_device_with_vid_pid@0 = libusb_open_device_with_vid_pid libusb_open_device_with_vid_pid@12 = libusb_open_device_with_vid_pid libusb_open_device_with_vid_pid@16 = libusb_open_device_with_vid_pid libusb_open_device_with_vid_pid@20 = libusb_open_device_with_vid_pid libusb_open_device_with_vid_pid@24 = libusb_open_device_with_vid_pid libusb_open_device_with_vid_pid@28 = libusb_open_device_with_vid_pid libusb_open_device_with_vid_pid@32 = libusb_open_device_with_vid_pid + libusb_open_device_with_vid_pid@4 = libusb_open_device_with_vid_pid + libusb_open_device_with_vid_pid@8 = libusb_open_device_with_vid_pid libusb_pollfds_handle_timeouts - libusb_pollfds_handle_timeouts@00 = libusb_pollfds_handle_timeouts - libusb_pollfds_handle_timeouts@04 = libusb_pollfds_handle_timeouts - libusb_pollfds_handle_timeouts@08 = libusb_pollfds_handle_timeouts + libusb_pollfds_handle_timeouts@0 = libusb_pollfds_handle_timeouts libusb_pollfds_handle_timeouts@12 = libusb_pollfds_handle_timeouts libusb_pollfds_handle_timeouts@16 = libusb_pollfds_handle_timeouts libusb_pollfds_handle_timeouts@20 = libusb_pollfds_handle_timeouts libusb_pollfds_handle_timeouts@24 = libusb_pollfds_handle_timeouts libusb_pollfds_handle_timeouts@28 = libusb_pollfds_handle_timeouts libusb_pollfds_handle_timeouts@32 = libusb_pollfds_handle_timeouts + libusb_pollfds_handle_timeouts@4 = libusb_pollfds_handle_timeouts + libusb_pollfds_handle_timeouts@8 = libusb_pollfds_handle_timeouts libusb_ref_device - libusb_ref_device@00 = libusb_ref_device - libusb_ref_device@04 = libusb_ref_device - libusb_ref_device@08 = libusb_ref_device + libusb_ref_device@0 = libusb_ref_device libusb_ref_device@12 = libusb_ref_device libusb_ref_device@16 = libusb_ref_device libusb_ref_device@20 = libusb_ref_device libusb_ref_device@24 = libusb_ref_device libusb_ref_device@28 = libusb_ref_device libusb_ref_device@32 = libusb_ref_device + libusb_ref_device@4 = libusb_ref_device + libusb_ref_device@8 = libusb_ref_device libusb_release_interface - libusb_release_interface@00 = libusb_release_interface - libusb_release_interface@04 = libusb_release_interface - libusb_release_interface@08 = libusb_release_interface + libusb_release_interface@0 = libusb_release_interface libusb_release_interface@12 = libusb_release_interface libusb_release_interface@16 = libusb_release_interface libusb_release_interface@20 = libusb_release_interface libusb_release_interface@24 = libusb_release_interface libusb_release_interface@28 = libusb_release_interface libusb_release_interface@32 = libusb_release_interface + libusb_release_interface@4 = libusb_release_interface + libusb_release_interface@8 = libusb_release_interface libusb_reset_device - libusb_reset_device@00 = libusb_reset_device - libusb_reset_device@04 = libusb_reset_device - libusb_reset_device@08 = libusb_reset_device + libusb_reset_device@0 = libusb_reset_device libusb_reset_device@12 = libusb_reset_device libusb_reset_device@16 = libusb_reset_device libusb_reset_device@20 = libusb_reset_device libusb_reset_device@24 = libusb_reset_device libusb_reset_device@28 = libusb_reset_device libusb_reset_device@32 = libusb_reset_device + libusb_reset_device@4 = libusb_reset_device + libusb_reset_device@8 = libusb_reset_device libusb_set_configuration - libusb_set_configuration@00 = libusb_set_configuration - libusb_set_configuration@04 = libusb_set_configuration - libusb_set_configuration@08 = libusb_set_configuration + libusb_set_configuration@0 = libusb_set_configuration libusb_set_configuration@12 = libusb_set_configuration libusb_set_configuration@16 = libusb_set_configuration libusb_set_configuration@20 = libusb_set_configuration libusb_set_configuration@24 = libusb_set_configuration libusb_set_configuration@28 = libusb_set_configuration libusb_set_configuration@32 = libusb_set_configuration + libusb_set_configuration@4 = libusb_set_configuration + libusb_set_configuration@8 = libusb_set_configuration libusb_set_debug - libusb_set_debug@00 = libusb_set_debug - libusb_set_debug@04 = libusb_set_debug - libusb_set_debug@08 = libusb_set_debug + libusb_set_debug@0 = libusb_set_debug libusb_set_debug@12 = libusb_set_debug libusb_set_debug@16 = libusb_set_debug libusb_set_debug@20 = libusb_set_debug libusb_set_debug@24 = libusb_set_debug libusb_set_debug@28 = libusb_set_debug libusb_set_debug@32 = libusb_set_debug + libusb_set_debug@4 = libusb_set_debug + libusb_set_debug@8 = libusb_set_debug libusb_set_interface_alt_setting - libusb_set_interface_alt_setting@00 = libusb_set_interface_alt_setting - libusb_set_interface_alt_setting@04 = libusb_set_interface_alt_setting - libusb_set_interface_alt_setting@08 = libusb_set_interface_alt_setting + libusb_set_interface_alt_setting@0 = libusb_set_interface_alt_setting libusb_set_interface_alt_setting@12 = libusb_set_interface_alt_setting libusb_set_interface_alt_setting@16 = libusb_set_interface_alt_setting libusb_set_interface_alt_setting@20 = libusb_set_interface_alt_setting libusb_set_interface_alt_setting@24 = libusb_set_interface_alt_setting libusb_set_interface_alt_setting@28 = libusb_set_interface_alt_setting libusb_set_interface_alt_setting@32 = libusb_set_interface_alt_setting + libusb_set_interface_alt_setting@4 = libusb_set_interface_alt_setting + libusb_set_interface_alt_setting@8 = libusb_set_interface_alt_setting libusb_set_pollfd_notifiers - libusb_set_pollfd_notifiers@00 = libusb_set_pollfd_notifiers - libusb_set_pollfd_notifiers@04 = libusb_set_pollfd_notifiers - libusb_set_pollfd_notifiers@08 = libusb_set_pollfd_notifiers + libusb_set_pollfd_notifiers@0 = libusb_set_pollfd_notifiers libusb_set_pollfd_notifiers@12 = libusb_set_pollfd_notifiers libusb_set_pollfd_notifiers@16 = libusb_set_pollfd_notifiers libusb_set_pollfd_notifiers@20 = libusb_set_pollfd_notifiers libusb_set_pollfd_notifiers@24 = libusb_set_pollfd_notifiers libusb_set_pollfd_notifiers@28 = libusb_set_pollfd_notifiers libusb_set_pollfd_notifiers@32 = libusb_set_pollfd_notifiers + libusb_set_pollfd_notifiers@4 = libusb_set_pollfd_notifiers + libusb_set_pollfd_notifiers@8 = libusb_set_pollfd_notifiers libusb_strerror - libusb_strerror@00 = libusb_strerror - libusb_strerror@04 = libusb_strerror - libusb_strerror@08 = libusb_strerror + libusb_strerror@0 = libusb_strerror libusb_strerror@12 = libusb_strerror libusb_strerror@16 = libusb_strerror libusb_strerror@20 = libusb_strerror libusb_strerror@24 = libusb_strerror libusb_strerror@28 = libusb_strerror libusb_strerror@32 = libusb_strerror + libusb_strerror@4 = libusb_strerror + libusb_strerror@8 = libusb_strerror libusb_submit_transfer - libusb_submit_transfer@00 = libusb_submit_transfer - libusb_submit_transfer@04 = libusb_submit_transfer - libusb_submit_transfer@08 = libusb_submit_transfer + libusb_submit_transfer@0 = libusb_submit_transfer libusb_submit_transfer@12 = libusb_submit_transfer libusb_submit_transfer@16 = libusb_submit_transfer libusb_submit_transfer@20 = libusb_submit_transfer libusb_submit_transfer@24 = libusb_submit_transfer libusb_submit_transfer@28 = libusb_submit_transfer libusb_submit_transfer@32 = libusb_submit_transfer + libusb_submit_transfer@4 = libusb_submit_transfer + libusb_submit_transfer@8 = libusb_submit_transfer libusb_try_lock_events - libusb_try_lock_events@00 = libusb_try_lock_events - libusb_try_lock_events@04 = libusb_try_lock_events - libusb_try_lock_events@08 = libusb_try_lock_events + libusb_try_lock_events@0 = libusb_try_lock_events libusb_try_lock_events@12 = libusb_try_lock_events libusb_try_lock_events@16 = libusb_try_lock_events libusb_try_lock_events@20 = libusb_try_lock_events libusb_try_lock_events@24 = libusb_try_lock_events libusb_try_lock_events@28 = libusb_try_lock_events libusb_try_lock_events@32 = libusb_try_lock_events + libusb_try_lock_events@4 = libusb_try_lock_events + libusb_try_lock_events@8 = libusb_try_lock_events libusb_unlock_event_waiters - libusb_unlock_event_waiters@00 = libusb_unlock_event_waiters - libusb_unlock_event_waiters@04 = libusb_unlock_event_waiters - libusb_unlock_event_waiters@08 = libusb_unlock_event_waiters + libusb_unlock_event_waiters@0 = libusb_unlock_event_waiters libusb_unlock_event_waiters@12 = libusb_unlock_event_waiters libusb_unlock_event_waiters@16 = libusb_unlock_event_waiters libusb_unlock_event_waiters@20 = libusb_unlock_event_waiters libusb_unlock_event_waiters@24 = libusb_unlock_event_waiters libusb_unlock_event_waiters@28 = libusb_unlock_event_waiters libusb_unlock_event_waiters@32 = libusb_unlock_event_waiters + libusb_unlock_event_waiters@4 = libusb_unlock_event_waiters + libusb_unlock_event_waiters@8 = libusb_unlock_event_waiters libusb_unlock_events - libusb_unlock_events@00 = libusb_unlock_events - libusb_unlock_events@04 = libusb_unlock_events - libusb_unlock_events@08 = libusb_unlock_events + libusb_unlock_events@0 = libusb_unlock_events libusb_unlock_events@12 = libusb_unlock_events libusb_unlock_events@16 = libusb_unlock_events libusb_unlock_events@20 = libusb_unlock_events libusb_unlock_events@24 = libusb_unlock_events libusb_unlock_events@28 = libusb_unlock_events libusb_unlock_events@32 = libusb_unlock_events + libusb_unlock_events@4 = libusb_unlock_events + libusb_unlock_events@8 = libusb_unlock_events libusb_unref_device - libusb_unref_device@00 = libusb_unref_device - libusb_unref_device@04 = libusb_unref_device - libusb_unref_device@08 = libusb_unref_device + libusb_unref_device@0 = libusb_unref_device libusb_unref_device@12 = libusb_unref_device libusb_unref_device@16 = libusb_unref_device libusb_unref_device@20 = libusb_unref_device libusb_unref_device@24 = libusb_unref_device libusb_unref_device@28 = libusb_unref_device libusb_unref_device@32 = libusb_unref_device + libusb_unref_device@4 = libusb_unref_device + libusb_unref_device@8 = libusb_unref_device libusb_wait_for_event - libusb_wait_for_event@00 = libusb_wait_for_event - libusb_wait_for_event@04 = libusb_wait_for_event - libusb_wait_for_event@08 = libusb_wait_for_event + libusb_wait_for_event@0 = libusb_wait_for_event libusb_wait_for_event@12 = libusb_wait_for_event libusb_wait_for_event@16 = libusb_wait_for_event libusb_wait_for_event@20 = libusb_wait_for_event libusb_wait_for_event@24 = libusb_wait_for_event libusb_wait_for_event@28 = libusb_wait_for_event libusb_wait_for_event@32 = libusb_wait_for_event + libusb_wait_for_event@4 = libusb_wait_for_event + libusb_wait_for_event@8 = libusb_wait_for_event diff --git a/libusb/libusb.h b/libusb/libusb.h index 4719dd1..d466109 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -1296,10 +1296,7 @@ int LIBUSB_CALL libusb_wait_for_event(libusb_context *ctx, struct timeval *tv); int LIBUSB_CALL libusb_handle_events_timeout(libusb_context *ctx, struct timeval *tv); -int LIBUSB_CALL libusb_handle_events_timeout_check(libusb_context *ctx, - struct timeval *tv, int *completed); int LIBUSB_CALL libusb_handle_events(libusb_context *ctx); -int LIBUSB_CALL libusb_handle_events_check(libusb_context *ctx, int *completed); int LIBUSB_CALL libusb_handle_events_locked(libusb_context *ctx, struct timeval *tv); int LIBUSB_CALL libusb_pollfds_handle_timeouts(libusb_context *ctx); diff --git a/libusb/libusbi.h b/libusb/libusbi.h index 8ade9c7..322ebbc 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -26,6 +26,9 @@ #include <stddef.h> #include <stdint.h> #include <time.h> +#ifdef HAVE_POLL_H +#include <poll.h> +#endif #include <libusb.h> #include "libusb_version.h" @@ -194,6 +197,7 @@ static inline void usbi_dbg(const char *format, ...) #endif #if defined(OS_LINUX) || defined(OS_DARWIN) +#include <unistd.h> #include <os/poll_posix.h> #elif defined(OS_WINDOWS) #include <os/poll_windows.h> @@ -831,7 +835,7 @@ struct usbi_os_backend { * Return 0 on success, or a LIBUSB_ERROR code on failure. */ int (*handle_events)(struct libusb_context *ctx, - struct pollfd *fds, nfds_t nfds, int num_ready); + struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready); /* Get time from specified clock. At least two clocks must be implemented by the backend: USBI_CLOCK_REALTIME, and USBI_CLOCK_MONOTONIC. diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 37b8e2c..169fa1a 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -672,10 +672,19 @@ static int darwin_open (struct libusb_device_handle *dev_handle) { return darwin_to_libusb (kresult); } } else { - priv->is_open = 1; - /* create async event source */ kresult = (*(dpriv->device))->CreateDeviceAsyncEventSource (dpriv->device, &priv->cfSource); + if (kresult != kIOReturnSuccess) { + usbi_err (HANDLE_CTX (dev_handle), "CreateDeviceAsyncEventSource: %s", darwin_error_str(kresult)); + + (*(dpriv->device))->USBDeviceClose (dpriv->device); + (*(dpriv->device))->Release (dpriv->device); + + dpriv->device = NULL; + return darwin_to_libusb (kresult); + } + + priv->is_open = 1; CFRetain (libusb_darwin_acfl); @@ -1173,10 +1182,18 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { /* are we reading or writing? */ is_read = transfer->endpoint & LIBUSB_ENDPOINT_IN; - /* construct an array of IOUSBIsocFrames */ - tpriv->isoc_framelist = (IOUSBIsocFrame*) calloc (transfer->num_iso_packets, sizeof(IOUSBIsocFrame)); - if (!tpriv->isoc_framelist) - return LIBUSB_ERROR_NO_MEM; + /* construct an array of IOUSBIsocFrames, reuse the old one if possible */ + if (tpriv->isoc_framelist && tpriv->num_iso_packets != transfer->num_iso_packets) { + free(tpriv->isoc_framelist); + tpriv->isoc_framelist = NULL; + } + + if (!tpriv->isoc_framelist) { + tpriv->num_iso_packets = transfer->num_iso_packets; + tpriv->isoc_framelist = (IOUSBIsocFrame*) calloc (transfer->num_iso_packets, sizeof(IOUSBIsocFrame)); + if (!tpriv->isoc_framelist) + return LIBUSB_ERROR_NO_MEM; + } /* copy the frame list from the libusb descriptor (the structures differ only is member order) */ for (i = 0 ; i < transfer->num_iso_packets ; i++) @@ -1202,7 +1219,10 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { } /* schedule for a frame a little in the future */ - frame += 2; + frame += 4; + + if (cInterface->frames[transfer->endpoint] && frame < cInterface->frames[transfer->endpoint]) + frame = cInterface->frames[transfer->endpoint]; /* submit the request */ if (is_read) @@ -1214,6 +1234,8 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback, itransfer); + cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets / 8; + if (kresult != kIOReturnSuccess) { usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", is_read ? "In" : "Out", darwin_error_str(kresult)); @@ -1228,6 +1250,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_control_setup *setup = (struct libusb_control_setup *) transfer->buffer; struct darwin_device_priv *dpriv = (struct darwin_device_priv *)transfer->dev_handle->dev->os_priv; + struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv; struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); IOReturn kresult; @@ -1249,7 +1272,23 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) { itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; /* all transfers in libusb-1.0 are async */ - kresult = (*(dpriv->device))->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer); + + if (transfer->endpoint) { + struct __darwin_interface *cInterface; + uint8_t pipeRef, iface; + + if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) { + usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); + + return LIBUSB_ERROR_NOT_FOUND; + } + + cInterface = &priv->interfaces[iface]; + + kresult = (*(cInterface->interface))->ControlRequestAsyncTO (cInterface->interface, pipeRef, &(tpriv->req), darwin_async_io_callback, itransfer); + } else + /* control request on endpoint 0 */ + kresult = (*(dpriv->device))->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer); if (kresult != kIOReturnSuccess) usbi_err (TRANSFER_CTX (transfer), "control request failed: %s", darwin_error_str(kresult)); @@ -1421,7 +1460,7 @@ static void darwin_handle_callback (struct usbi_transfer *itransfer, kern_return usbi_handle_transfer_completion (itransfer, darwin_transfer_status (itransfer, result)); } -static int op_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds_t nfds, int num_ready) { +static int op_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) { struct usbi_transfer *itransfer; UInt32 io_size; IOReturn kresult; diff --git a/libusb/os/darwin_usb.h b/libusb/os/darwin_usb.h index a71d464..9ffd6df 100644 --- a/libusb/os/darwin_usb.h +++ b/libusb/os/darwin_usb.h @@ -139,6 +139,7 @@ struct darwin_device_handle_priv { usb_interface_t **interface; uint8_t num_endpoints; CFRunLoopSourceRef cfSource; + uint64_t frames[256]; uint8_t endpoint_addrs[USB_MAXENDPOINTS]; } interfaces[USB_MAXINTERFACES]; }; @@ -146,6 +147,7 @@ struct darwin_device_handle_priv { struct darwin_transfer_priv { /* Isoc */ IOUSBIsocFrame *isoc_framelist; + size_t num_iso_packets; /* Control */ #if !defined (LIBUSB_NO_TIMEOUT_DEVICE) diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 867893c..72db57a 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -363,7 +363,7 @@ static int sysfs_get_active_config(struct libusb_device *dev, int *config) char tmp[4] = {0, 0, 0, 0}; long num; int fd; - size_t r; + ssize_t r; fd = __open_sysfs_attr(dev, "bConfigurationValue"); if (fd < 0) @@ -407,7 +407,7 @@ static int seek_to_next_config(struct libusb_context *ctx, int fd, struct libusb_config_descriptor config; unsigned char tmp[6]; off_t off; - int r; + ssize_t r; /* read first 6 bytes of descriptor */ r = read(fd, tmp, sizeof(tmp)); @@ -1331,6 +1331,39 @@ static void op_destroy_device(struct libusb_device *dev) free(priv->sysfs_dir); } +/* URBs are discarded in reverse order of submission to avoid races. */ +static int discard_urbs(struct usbi_transfer *itransfer, int first, int last_plus_one) +{ + struct libusb_transfer *transfer = + __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct linux_transfer_priv *tpriv = + usbi_transfer_get_os_priv(itransfer); + struct linux_device_handle_priv *dpriv = + __device_handle_priv(transfer->dev_handle); + int i, ret = 0; + struct usbfs_urb *urb; + + for (i = last_plus_one - 1; i >= first; i--) { + if (LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type) + urb = tpriv->iso_urbs[i]; + else + urb = &tpriv->urbs[i]; + + if (0 == ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, urb)) + continue; + + if (EINVAL == errno) { + usbi_dbg("URB not found --> assuming ready to be reaped"); + ret = LIBUSB_ERROR_NOT_FOUND; + } else { + usbi_warn(TRANSFER_CTX(transfer), + "unrecognised discard errno %d", errno); + ret = LIBUSB_ERROR_OTHER; + } + } + return ret; +} + static void free_iso_urbs(struct linux_transfer_priv *tpriv) { int i; @@ -1409,8 +1442,6 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer, r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urb); if (r < 0) { - int j; - if (errno == ENODEV) { r = LIBUSB_ERROR_NO_DEVICE; } else { @@ -1454,14 +1485,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer, if (COMPLETED_EARLY == tpriv->reap_action) return 0; - /* The URBs are discarded in reverse order of - * submission, to avoid races. */ - for (j = i - 1; j >= 0; j--) { - int tmp = ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, &urbs[j]); - if (tmp && errno != EINVAL) - usbi_warn(TRANSFER_CTX(transfer), - "unrecognised discard errno %d", errno); - } + discard_urbs(itransfer, 0, i); usbi_dbg("reporting successful submission but waiting for %d " "discards before reporting error", i); @@ -1577,8 +1601,6 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) for (i = 0; i < num_urbs; i++) { int r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urbs[i]); if (r < 0) { - int j; - if (errno == ENODEV) { r = LIBUSB_ERROR_NO_DEVICE; } else { @@ -1613,12 +1635,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) /* The URBs we haven't submitted yet we count as already * retired. */ tpriv->num_retired = num_urbs - i; - for (j = i - 1; j >= 0; j--) { - int tmp = ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, urbs[j]); - if (tmp && errno != EINVAL) - usbi_warn(TRANSFER_CTX(transfer), - "unrecognised discard errno %d", errno); - } + discard_urbs(itransfer, 0, i); usbi_dbg("reporting successful submission but waiting for %d " "discards before reporting error", i); @@ -1650,6 +1667,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) return LIBUSB_ERROR_NO_MEM; memset(urb, 0, sizeof(struct usbfs_urb)); tpriv->urbs = urb; + tpriv->num_urbs = 1; tpriv->reap_action = NORMAL; urb->usercontext = itransfer; @@ -1693,98 +1711,32 @@ static int op_submit_transfer(struct usbi_transfer *itransfer) } } -static int cancel_control_transfer(struct usbi_transfer *itransfer) -{ - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - struct libusb_transfer *transfer = - __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_device_handle_priv *dpriv = - __device_handle_priv(transfer->dev_handle); - int r; - - if (!tpriv->urbs) - return LIBUSB_ERROR_NOT_FOUND; - - tpriv->reap_action = CANCELLED; - r = ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, tpriv->urbs); - if(r) { - if (errno == EINVAL) { - usbi_dbg("URB not found --> assuming ready to be reaped"); - return 0; - } else { - usbi_err(TRANSFER_CTX(transfer), - "unrecognised DISCARD code %d", errno); - return LIBUSB_ERROR_OTHER; - } - } - - return 0; -} - -static int cancel_bulk_transfer(struct usbi_transfer *itransfer) -{ - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - struct libusb_transfer *transfer = - __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_device_handle_priv *dpriv = - __device_handle_priv(transfer->dev_handle); - int i; - - if (!tpriv->urbs) - return LIBUSB_ERROR_NOT_FOUND; - - if (tpriv->reap_action != ERROR) - tpriv->reap_action = CANCELLED; - - for (i = tpriv->num_urbs - 1; i >= 0; i--) { - int tmp = ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, &tpriv->urbs[i]); - if (tmp && errno != EINVAL) - usbi_warn(TRANSFER_CTX(transfer), - "unrecognised discard errno %d", errno); - } - return 0; -} - -static int cancel_iso_transfer(struct usbi_transfer *itransfer) -{ - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - struct libusb_transfer *transfer = - __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_device_handle_priv *dpriv = - __device_handle_priv(transfer->dev_handle); - int i; - - if (!tpriv->iso_urbs) - return LIBUSB_ERROR_NOT_FOUND; - - tpriv->reap_action = CANCELLED; - for (i = tpriv->num_urbs - 1; i >= 0; i--) { - int tmp = ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, tpriv->iso_urbs[i]); - if (tmp && errno != EINVAL) - usbi_warn(TRANSFER_CTX(transfer), - "unrecognised discard errno %d", errno); - } - return 0; -} - static int op_cancel_transfer(struct usbi_transfer *itransfer) { + struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); struct libusb_transfer *transfer = __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - return cancel_control_transfer(itransfer); case LIBUSB_TRANSFER_TYPE_BULK: + if (tpriv->reap_action == ERROR) + break; + /* else, fall through */ + case LIBUSB_TRANSFER_TYPE_CONTROL: case LIBUSB_TRANSFER_TYPE_INTERRUPT: - return cancel_bulk_transfer(itransfer); case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return cancel_iso_transfer(itransfer); + tpriv->reap_action = CANCELLED; + break; default: usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); return LIBUSB_ERROR_INVALID_PARAM; } + + if (!tpriv->urbs) + return LIBUSB_ERROR_NOT_FOUND; + + return discard_urbs(itransfer, 0, tpriv->num_urbs); } static void op_clear_transfer_priv(struct usbi_transfer *itransfer) @@ -1814,7 +1766,6 @@ static int handle_bulk_completion(struct usbi_transfer *itransfer, { struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); struct libusb_transfer *transfer = __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_device_handle_priv *dpriv = __device_handle_priv(transfer->dev_handle); int urb_idx = urb - tpriv->urbs; usbi_mutex_lock(&itransfer->lock); @@ -1928,16 +1879,7 @@ cancel_remaining: /* cancel remaining urbs and wait for their completion before * reporting results */ - for (int i = tpriv->num_urbs - 1; i > urb_idx; i--) { - /* remaining URBs with continuation flag are - * automatically cancelled by the kernel */ - if (tpriv->urbs[i].flags & USBFS_URB_BULK_CONTINUATION) - continue; - int tmp = ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, &tpriv->urbs[i]); - if (tmp && errno != EINVAL) - usbi_warn(TRANSFER_CTX(transfer), - "unrecognised discard errno %d", errno); - } + discard_urbs(itransfer, urb_idx + 1, tpriv->num_urbs); out_unlock: usbi_mutex_unlock(&itransfer->lock); @@ -2142,7 +2084,7 @@ static int reap_for_handle(struct libusb_device_handle *handle) } static int op_handle_events(struct libusb_context *ctx, - struct pollfd *fds, nfds_t nfds, int num_ready) + struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) { int r; int i = 0; diff --git a/libusb/os/poll_posix.h b/libusb/os/poll_posix.h index 17298a5..f8c9e21 100644 --- a/libusb/os/poll_posix.h +++ b/libusb/os/poll_posix.h @@ -1,8 +1,6 @@ #ifndef __LIBUSB_POLL_POSIX_H__ #define __LIBUSB_POLL_POSIX_H__ -#include <unistd.h> -#include <poll.h> #define usbi_write write #define usbi_read read #define usbi_close close diff --git a/libusb/os/poll_windows.h b/libusb/os/poll_windows.h index 36e3915..fee89f5 100644 --- a/libusb/os/poll_windows.h +++ b/libusb/os/poll_windows.h @@ -63,8 +63,6 @@ struct pollfd { short revents; /* returned events */ }; -typedef unsigned int nfds_t; - // access modes enum rw_type { RW_NONE, diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c index f2532a9..6d3da1e 100644 --- a/libusb/os/windows_usb.c +++ b/libusb/os/windows_usb.c @@ -3,7 +3,6 @@ * Copyright (c) 2009-2010 Pete Batard <pbatard@gmail.com> * With contributions from Michael Plante, Orin Eman et al. * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer - * HID Reports IOCTLs inspired from HIDAPI by Alan Ott, Signal 11 Software * Hash table functions adapted from glibc, by Ulrich Drepper et al. * Major code testing contribution by Xiaofan Chen * @@ -68,16 +67,12 @@ static int windows_clock_gettime(int clk_id, struct timespec *tp); unsigned __stdcall windows_clock_gettime_threaded(void* param); // Common calls static int common_configure_endpoints(struct libusb_device_handle *dev_handle, int iface); -// HUB (limited) API prototypes -static int hub_open(struct libusb_device_handle *dev_handle); -static void hub_close(struct libusb_device_handle *dev_handle); // WinUSB, libusbK API prototypes static int winusb_init(struct libusb_context *ctx); static int winusb_exit(void); static int winusb_open(struct libusb_device_handle *dev_handle); static void winusb_close(struct libusb_device_handle *dev_handle); static int winusb_configure_endpoints(struct libusb_device_handle *dev_handle, int iface); -static int winusb_configure_endpoints(struct libusb_device_handle *dev_handle, int iface); static int winusb_claim_interface(struct libusb_device_handle *dev_handle, int iface); static int winusb_release_interface(struct libusb_device_handle *dev_handle, int iface); static int winusb_submit_control_transfer(struct usbi_transfer *itransfer); @@ -104,21 +99,6 @@ static int libusbk_abort_transfers(struct usbi_transfer *itransfer); static int libusbk_abort_control(struct usbi_transfer *itransfer); static int libusbk_reset_device(struct libusb_device_handle *dev_handle); static int libusbk_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size); - -// HID API prototypes -static int hid_init(struct libusb_context *ctx); -static int hid_exit(void); -static int hid_open(struct libusb_device_handle *dev_handle); -static void hid_close(struct libusb_device_handle *dev_handle); -static int hid_claim_interface(struct libusb_device_handle *dev_handle, int iface); -static int hid_release_interface(struct libusb_device_handle *dev_handle, int iface); -static int hid_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting); -static int hid_submit_control_transfer(struct usbi_transfer *itransfer); -static int hid_submit_bulk_transfer(struct usbi_transfer *itransfer); -static int hid_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint); -static int hid_abort_transfers(struct usbi_transfer *itransfer); -static int hid_reset_device(struct libusb_device_handle *dev_handle); -static int hid_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size); // Composite API prototypes static int composite_init(struct libusb_context *ctx); static int composite_exit(void); @@ -185,8 +165,6 @@ bool api_winusb_available = false; bool api_libusbk_available = false; #define CHECK_WINUSB_AVAILABLE do { if ( ((!k) && (!api_winusb_available)) || ((k) && (!api_libusbk_available)) ) \ return LIBUSB_ERROR_ACCESS; } while (0) -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)) { @@ -709,7 +687,6 @@ static int auto_claim(struct libusb_transfer *transfer, int *interface_number, i switch(api_type) { case USB_API_WINUSB: case USB_API_LIBUSBK: - case USB_API_HID: break; default: return LIBUSB_ERROR_INVALID_PARAM; @@ -1097,8 +1074,12 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d priv->depth = parent_priv->depth + 1; priv->parent_dev = parent_dev; dev->parent_dev = parent_dev; - memset(&conn_info, 0, sizeof(conn_info)); + // If the device address is already set, we can stop here + if (dev->device_address != 0) { + return LIBUSB_SUCCESS; + } + memset(&conn_info, 0, sizeof(conn_info)); 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); @@ -1213,7 +1194,7 @@ static int set_composite_interface(struct libusb_context* ctx, struct libusb_dev return LIBUSB_ERROR_NO_DEVICE; } - // Because MI_## are not necessarily in sequential order (some composite HID + // Because MI_## are not necessarily in sequential order (some composite // 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; @@ -1231,44 +1212,19 @@ static int set_composite_interface(struct libusb_context* ctx, struct libusb_dev device_id, interface_number); } - // HID devices can have multiple collections (COL##) for each MI_## interface if (priv->usb_interface[interface_number].path != NULL) { - if (api != USB_API_HID) { - usbi_warn(ctx, "program assertion failed %s is not an USB HID collection", device_id); - return LIBUSB_ERROR_OTHER; - } - usbi_dbg("interface[%d] already set - ignoring HID collection: %s", - interface_number, device_id); + usbi_warn(ctx, "interface[%d] already set - ignoring: %s", interface_number, device_id); return LIBUSB_ERROR_ACCESS; } usbi_dbg("interface[%d] = %s", interface_number, dev_interface_path); priv->usb_interface[interface_number].path = dev_interface_path; priv->usb_interface[interface_number].apib = &usb_api_backend[api]; - if ((api == USB_API_HID) && (priv->hid == NULL)) { - priv->hid = calloc(1, sizeof(struct hid_device_priv)); - } priv->composite_api_flags |= 1<<api; return LIBUSB_SUCCESS; } -static int set_hid_interface(struct libusb_context* ctx, struct libusb_device* dev, - char* dev_interface_path) -{ - struct windows_device_priv *priv = __device_priv(dev); - - if (priv->hid == NULL) { - usbi_err(ctx, "program assertion failed: parent is not HID"); - return LIBUSB_ERROR_NO_DEVICE; - } - priv->usb_interface[priv->hid->nb_interfaces].path = dev_interface_path; - priv->usb_interface[priv->hid->nb_interfaces].apib = &usb_api_backend[USB_API_HID]; - usbi_dbg("interface[%d] = %s", priv->hid->nb_interfaces, dev_interface_path); - priv->hid->nb_interfaces++; - return LIBUSB_SUCCESS; -} - /* * get_device_list: libusb backend device enumeration function */ @@ -1278,14 +1234,12 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered HDEVINFO dev_info; SP_DEVINFO_DATA dev_info_data; SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL; - GUID hid_guid; #define MAX_ENUM_GUIDS 64 const GUID* guid[MAX_ENUM_GUIDS]; #define HCD_PASS 0 #define HUB_PASS 1 #define GEN_PASS 2 #define DEV_PASS 3 -#define HID_PASS 4 int r = LIBUSB_SUCCESS; unsigned int nb_guids, pass, i, j, ancestor; char path[MAX_PATH_LENGTH]; @@ -1311,17 +1265,14 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered // PASS 3 : (re)enumerate generic USB devices (including driverless) // and list additional USB device interface GUIDs to explore // PASS 4 : (re)enumerate master USB devices that have a device interface - // PASS 5+: (re)enumerate device interfaced GUIDs (including HID) and - // set the device interfaces. + // PASS 5+: (re)enumerate device interfaced GUIDs and set the device interfaces. // Init the GUID table guid[HCD_PASS] = &GUID_DEVINTERFACE_USB_HOST_CONTROLLER; guid[HUB_PASS] = &GUID_DEVINTERFACE_USB_HUB; guid[GEN_PASS] = NULL; guid[DEV_PASS] = &GUID_DEVINTERFACE_USB_DEVICE; - HidD_GetHidGuid(&hid_guid); - guid[HID_PASS] = &hid_guid; - nb_guids = HID_PASS+1; + nb_guids = DEV_PASS+1; unref_list = malloc(unref_size*sizeof(libusb_device*)); if (unref_list == NULL) { @@ -1344,9 +1295,6 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered case GEN_PASS: usbi_dbg("PROCESSING GENs"); break; - case HID_PASS: - usbi_dbg("PROCESSING HIDs %s", guid_to_string(guid[pass])); - break; default: usbi_dbg("PROCESSING EXTs %s", guid_to_string(guid[pass])); break; @@ -1450,9 +1398,6 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered } } break; - case HID_PASS: - api = USB_API_HID; - break; default: // Get the API type (after checking that the driver installation is OK) if ( (!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_INSTALL_STATE, @@ -1486,7 +1431,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered 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); + usbi_dbg("unlisted ancestor for '%s' (newly connected, etc.) - ignoring", dev_id_path); continue; } parent_priv = __device_priv(parent_dev); @@ -1525,7 +1470,8 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered } } } else { - usbi_dbg("found existing device for session [%X]", session_id); + usbi_dbg("found existing device for session [%X] (%d.%d)", + session_id, dev->bus_number, dev->device_address); } priv = __device_priv(dev); } @@ -1541,20 +1487,15 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered priv->path = dev_interface_path; dev_interface_path = NULL; break; case DEV_PASS: + // If the device has already been setup, don't do it again + if (priv->path != NULL) + break; // Take care of API initialization priv->path = dev_interface_path; dev_interface_path = NULL; priv->apib = &usb_api_backend[api]; switch(api) { case USB_API_COMPOSITE: break; - case USB_API_HID: - safe_free(priv->hid); - priv->hid = calloc(1, sizeof(struct hid_device_priv)); - 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 = malloc(safe_strlen(priv->path)+1); @@ -1588,13 +1529,8 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered r = LIBUSB_SUCCESS; } 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) { + default: // later passes + 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)) { case LIBUSB_SUCCESS: @@ -1614,7 +1550,7 @@ 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 = DEV_PASS+1; pass < nb_guids; pass++) { safe_free(guid[pass]); } @@ -1871,7 +1807,6 @@ static 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); usbi_free_fd(transfer_priv->pollable_fd.fd); - safe_free(transfer_priv->hid_buffer); #if defined(AUTO_CLAIM) // When auto claim is in use, attempt to release the auto-claimed interface auto_release(itransfer); @@ -2056,10 +1991,10 @@ static void windows_handle_callback (struct usbi_transfer *itransfer, uint32_t i } } -static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds_t nfds, int num_ready) +static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) { struct windows_transfer_priv* transfer_priv = NULL; - nfds_t i = 0; + POLL_NFDS_TYPE i = 0; bool found = false; struct usbi_transfer *transfer; DWORD io_size, io_result; @@ -2336,7 +2271,6 @@ const char* hub_driver_names[] = {"USBHUB"}; const char* composite_driver_names[] = {"USBCCGP"}; const char* winusb_driver_names[] = {"WINUSB"}; const char* libusbK_driver_names[] = {"LIBUSBK"}; -const char* hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"}; const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { { USB_API_UNSUPPORTED, @@ -2368,8 +2302,8 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { sizeof(hub_driver_names)/sizeof(hub_driver_names[0]), unsupported_init, unsupported_exit, - hub_open, - hub_close, + unsupported_open, + unsupported_close, unsupported_configure_endpoints, unsupported_claim_interface, unsupported_set_interface_altsetting, @@ -2448,46 +2382,11 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { libusbk_abort_control, libusbk_abort_transfers, libusbk_copy_transfer_data, - }, { - USB_API_HID, - "HID API", - &CLASS_GUID_HID, - hid_driver_names, - sizeof(hid_driver_names)/sizeof(hid_driver_names[0]), - hid_init, - hid_exit, - hid_open, - hid_close, - common_configure_endpoints, - hid_claim_interface, - hid_set_interface_altsetting, - hid_release_interface, - hid_clear_halt, - hid_reset_device, - hid_submit_bulk_transfer, - unsupported_submit_iso_transfer, - hid_submit_control_transfer, - hid_abort_transfers, - hid_abort_transfers, - hid_copy_transfer_data, }, }; /* - * HUB API functions - only cached descriptors readout for now - * might be expanded if - */ -static int hub_open(struct libusb_device_handle *dev_handle) -{ - return LIBUSB_SUCCESS; -} - -static void hub_close(struct libusb_device_handle *dev_handle) -{ -} - -/* * WinUSB, libusbK API functions */ @@ -2807,23 +2706,16 @@ static int libusbk_release_interface(struct libusb_device_handle *dev_handle, in /* * Return the first valid interface (of the same API type), for control transfers */ -static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_id) +static int winusb_get_valid_interface(struct libusb_device_handle *dev_handle) { struct windows_device_handle_priv *handle_priv = __device_handle_priv(dev_handle); - struct windows_device_priv *priv = __device_priv(dev_handle->dev); int i; - if ((api_id < USB_API_WINUSB) || (api_id > USB_API_HID)) { - usbi_dbg("unsupported API ID"); - return -1; - } - for (i=0; i<USB_MAXINTERFACES; i++) { if ( (handle_priv->interface_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) ) { + && (handle_priv->interface_handle[i].api_handle != INVALID_HANDLE_VALUE) ) { return i; } } @@ -2875,7 +2767,7 @@ static int _winusb_submit_control_transfer(struct usbi_transfer *itransfer, bool if (size > MAX_CTRL_BUFFER_LENGTH) return LIBUSB_ERROR_INVALID_PARAM; - current_interface = get_valid_interface(transfer->dev_handle, k?USB_API_LIBUSBK:USB_API_WINUSB); + current_interface = winusb_get_valid_interface(transfer->dev_handle); if (current_interface < 0) { #if defined(AUTO_CLAIM) if (auto_claim(transfer, ¤t_interface, k?USB_API_LIBUSBK:USB_API_WINUSB) != LIBUSB_SUCCESS) { @@ -2897,7 +2789,7 @@ static int _winusb_submit_control_transfer(struct usbi_transfer *itransfer, bool } // Sending of set configuration control requests from WinUSB creates issues - if ( (LIBUSB_REQ_TYPE(setup->request_type) == LIBUSB_REQUEST_TYPE_STANDARD) + 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"); @@ -3224,1049 +3116,6 @@ static int libusbk_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t } /* - * Internal HID Support functions (from libusb-win32) - * 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_wcslen(WCHAR *str) -{ - int i = 0; - 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) -{ - struct libusb_device_descriptor d; - - d.bLength = LIBUSB_DT_DEVICE_SIZE; - d.bDescriptorType = LIBUSB_DT_DEVICE; - d.bcdUSB = 0x0200; /* 2.00 */ - d.bDeviceClass = 0; - d.bDeviceSubClass = 0; - d.bDeviceProtocol = 0; - d.bMaxPacketSize0 = 64; /* fix this! */ - d.idVendor = (uint16_t)dev->vid; - d.idProduct = (uint16_t)dev->pid; - d.bcdDevice = 0x0100; - d.iManufacturer = dev->string_index[0]; - d.iProduct = dev->string_index[1]; - d.iSerialNumber = dev->string_index[2]; - d.bNumConfigurations = 1; - - 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) -{ - char num_endpoints = 0; - size_t config_total_len = 0; - char tmp[HID_MAX_CONFIG_DESC_SIZE]; - struct libusb_config_descriptor *cd; - struct libusb_interface_descriptor *id; - struct libusb_hid_descriptor *hd; - struct libusb_endpoint_descriptor *ed; - size_t tmp_size; - - if (dev->input_report_size) - num_endpoints++; - if (dev->output_report_size) - num_endpoints++; - - 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 - + LIBUSB_DT_INTERFACE_SIZE); - ed = (struct libusb_endpoint_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE - + LIBUSB_DT_INTERFACE_SIZE - + LIBUSB_DT_HID_SIZE); - - cd->bLength = LIBUSB_DT_CONFIG_SIZE; - cd->bDescriptorType = LIBUSB_DT_CONFIG; - cd->wTotalLength = (uint16_t) config_total_len; - cd->bNumInterfaces = 1; - cd->bConfigurationValue = 1; - cd->iConfiguration = 0; - cd->bmAttributes = 1 << 7; /* bus powered */ - cd->MaxPower = 50; - - id->bLength = LIBUSB_DT_INTERFACE_SIZE; - id->bDescriptorType = LIBUSB_DT_INTERFACE; - id->bInterfaceNumber = 0; - id->bAlternateSetting = 0; - id->bNumEndpoints = num_endpoints; - id->bInterfaceClass = 3; - id->bInterfaceSubClass = 0; - id->bInterfaceProtocol = 0; - id->iInterface = 0; - - tmp_size = LIBUSB_DT_HID_SIZE; - _hid_get_hid_descriptor(dev, hd, &tmp_size); - - if (dev->input_report_size) { - ed->bLength = LIBUSB_DT_ENDPOINT_SIZE; - ed->bDescriptorType = LIBUSB_DT_ENDPOINT; - ed->bEndpointAddress = HID_IN_EP; - ed->bmAttributes = 3; - ed->wMaxPacketSize = dev->input_report_size - 1; - ed->bInterval = 10; - - ed++; - } - - if (dev->output_report_size) { - ed->bLength = LIBUSB_DT_ENDPOINT_SIZE; - ed->bDescriptorType = LIBUSB_DT_ENDPOINT; - ed->bEndpointAddress = HID_OUT_EP; - ed->bmAttributes = 3; - ed->wMaxPacketSize = dev->output_report_size - 1; - ed->bInterval = 10; - } - - 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) -{ - void *tmp = NULL; - size_t tmp_size = 0; - int i; - - /* language ID, EN-US */ - char string_langid[] = { - 0x09, - 0x04 - }; - - if ((*size < 2) || (*size > 255)) { - return LIBUSB_ERROR_OVERFLOW; - } - - if (_index == 0) { - tmp = string_langid; - tmp_size = sizeof(string_langid)+2; - } else { - 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); - break; - } - } - if (i == 3) { // not found - return LIBUSB_ERROR_INVALID_PARAM; - } - } - - if(!tmp_size) { - return LIBUSB_ERROR_INVALID_PARAM; - } - - 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); - return LIBUSB_COMPLETED; -} - -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]; - size_t report_len = MAX_HID_DESCRIPTOR_SIZE; - - _hid_get_report_descriptor(dev, tmp, &report_len); - - d.bLength = LIBUSB_DT_HID_SIZE; - d.bDescriptorType = LIBUSB_DT_HID; - d.bcdHID = 0x0110; /* 1.10 */ - d.bCountryCode = 0; - d.bNumDescriptors = 1; - d.bClassDescriptorType = LIBUSB_DT_REPORT; - d.wClassDescriptorLength = (uint16_t)report_len; - - 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) -{ - uint8_t d[MAX_HID_DESCRIPTOR_SIZE]; - size_t i = 0; - - /* usage page (0xFFA0 == vendor defined) */ - d[i++] = 0x06; d[i++] = 0xA0; d[i++] = 0xFF; - /* usage (vendor defined) */ - d[i++] = 0x09; d[i++] = 0x01; - /* start collection (application) */ - d[i++] = 0xA1; d[i++] = 0x01; - /* input report */ - if (dev->input_report_size) { - /* usage (vendor defined) */ - d[i++] = 0x09; d[i++] = 0x01; - /* logical minimum (0) */ - d[i++] = 0x15; d[i++] = 0x00; - /* logical maximum (255) */ - d[i++] = 0x25; d[i++] = 0xFF; - /* report size (8 bits) */ - d[i++] = 0x75; d[i++] = 0x08; - /* report count */ - d[i++] = 0x95; d[i++] = (uint8_t)dev->input_report_size - 1; - /* input (data, variable, absolute) */ - d[i++] = 0x81; d[i++] = 0x00; - } - /* output report */ - if (dev->output_report_size) { - /* usage (vendor defined) */ - d[i++] = 0x09; d[i++] = 0x02; - /* logical minimum (0) */ - d[i++] = 0x15; d[i++] = 0x00; - /* logical maximum (255) */ - d[i++] = 0x25; d[i++] = 0xFF; - /* report size (8 bits) */ - d[i++] = 0x75; d[i++] = 0x08; - /* report count */ - d[i++] = 0x95; d[i++] = (uint8_t)dev->output_report_size - 1; - /* output (data, variable, absolute) */ - d[i++] = 0x91; d[i++] = 0x00; - } - /* feature report */ - if (dev->feature_report_size) { - /* usage (vendor defined) */ - d[i++] = 0x09; d[i++] = 0x03; - /* logical minimum (0) */ - d[i++] = 0x15; d[i++] = 0x00; - /* logical maximum (255) */ - d[i++] = 0x25; d[i++] = 0xFF; - /* report size (8 bits) */ - d[i++] = 0x75; d[i++] = 0x08; - /* report count */ - d[i++] = 0x95; d[i++] = (uint8_t)dev->feature_report_size - 1; - /* feature (data, variable, absolute) */ - d[i++] = 0xb2; d[i++] = 0x02; d[i++] = 0x01; - } - - /* end collection */ - d[i++] = 0xC0; - - 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) -{ - switch(type) { - case LIBUSB_DT_DEVICE: - usbi_dbg("LIBUSB_DT_DEVICE"); - return _hid_get_device_descriptor(dev, data, size); - case LIBUSB_DT_CONFIG: - usbi_dbg("LIBUSB_DT_CONFIG"); - if (!_index) - return _hid_get_config_descriptor(dev, data, size); - return LIBUSB_ERROR_INVALID_PARAM; - case LIBUSB_DT_STRING: - usbi_dbg("LIBUSB_DT_STRING"); - return _hid_get_string_descriptor(dev, _index, data, size); - case LIBUSB_DT_HID: - usbi_dbg("LIBUSB_DT_HID"); - if (!_index) - return _hid_get_hid_descriptor(dev, data, size); - return LIBUSB_ERROR_INVALID_PARAM; - case LIBUSB_DT_REPORT: - usbi_dbg("LIBUSB_DT_REPORT"); - if (!_index) - return _hid_get_report_descriptor(dev, data, size); - return LIBUSB_ERROR_INVALID_PARAM; - case LIBUSB_DT_PHYSICAL: - usbi_dbg("LIBUSB_DT_PHYSICAL"); - if (HidD_GetPhysicalDescriptor(hid_handle, data, (ULONG)*size)) - return LIBUSB_COMPLETED; - return LIBUSB_ERROR_OTHER; - } - usbi_dbg("unsupported"); - return LIBUSB_ERROR_INVALID_PARAM; -} - -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) { - usbi_dbg("program assertion failed: hid_buffer is not NULL"); - } - - if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) { - usbi_dbg("invalid size (%d)", *size); - return LIBUSB_ERROR_INVALID_PARAM; - } - - 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; - } - - // Add a trailing byte to detect overflows - buf = (uint8_t*)calloc(expected_size+1, 1); - if (buf == NULL) { - return LIBUSB_ERROR_NO_MEM; - } - 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 (GetLastError() != ERROR_IO_PENDING) { - usbi_dbg("Failed to Read HID Report: %s", windows_error_str(0)); - safe_free(buf); - return LIBUSB_ERROR_IO; - } - // Asynchronous wait - tp->hid_buffer = buf; - tp->hid_dest = (uint8_t*)data; // copy dest, as not necessarily the start of the transfer buffer - return LIBUSB_SUCCESS; - } - - // Transfer completed synchronously => copy and discard extra buffer - if (read_size == 0) { - usbi_warn(NULL, "program assertion failed - read completed synchronously, but no data was read"); - *size = 0; - } else { - 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!"); - } else { - r = LIBUSB_COMPLETED; - } - - *size = MIN((size_t)read_size, *size); - if (id == 0) { - // Discard report ID - memcpy(data, buf+1, *size); - } 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) -{ - uint8_t *buf = NULL; - DWORD ioctl_code, write_size= (DWORD)*size; - - 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 (%d)", *size); - return LIBUSB_ERROR_INVALID_PARAM; - } - - 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; - } - - 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) { - write_size++; - } - buf = malloc(write_size); - if (buf == NULL) { - return LIBUSB_ERROR_NO_MEM; - } - if (id == 0) { - buf[0] = 0; - memcpy(buf + 1, data, *size); - } else { - // 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) { - 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) - if (!DeviceIoControl(hid_handle, ioctl_code, buf, write_size, - buf, write_size, &write_size, overlapped)) { - if (GetLastError() != ERROR_IO_PENDING) { - usbi_dbg("Failed to Write HID Output Report: %s", windows_error_str(0)); - safe_free(buf); - return LIBUSB_ERROR_IO; - } - tp->hid_buffer = buf; - tp->hid_dest = NULL; - return LIBUSB_SUCCESS; - } - - // Transfer completed synchronously - *size = write_size; - 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) -{ - 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) ) - return LIBUSB_ERROR_INVALID_PARAM; - - if (LIBUSB_REQ_OUT(request_type) && request == HID_REQ_SET_REPORT) - return _hid_set_report(dev, hid_handle, report_id, data, tp, size, overlapped, report_type); - - if (LIBUSB_REQ_IN(request_type) && request == HID_REQ_GET_REPORT) - return _hid_get_report(dev, hid_handle, report_id, data, tp, size, overlapped, report_type); - - return LIBUSB_ERROR_INVALID_PARAM; -} - - -/* - * HID API functions - */ -static int hid_init(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); - - api_hid_available = true; - return LIBUSB_SUCCESS; -} - -static int hid_exit(void) -{ - return LIBUSB_SUCCESS; -} - -// NB: open and close must ensure that they only handle interface of -// the right API type, as these functions can be called wholesale from -// composite_open(), with interfaces belonging to different APIs -static int hid_open(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]; - 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) ) { - 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); - /* - * http://www.lvr.com/hidfaq.htm: Why do I receive "Access denied" when attempting to access my HID? - * "Windows 2000 and later have exclusive read/write access to HIDs that are configured as a system - * keyboards or mice. An application can obtain a handle to a system keyboard or mouse by not - * requesting READ or WRITE access with CreateFile. Applications can then use HidD_SetFeature and - * HidD_GetFeature (if the device supports Feature reports)." - */ - if (hid_handle == INVALID_HANDLE_VALUE) { - usbi_warn(ctx, "could not open HID device in R/W mode (keyboard or mouse?) - trying without"); - hid_handle = CreateFileA(priv->usb_interface[i].path, 0, FILE_SHARE_WRITE | FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); - 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 - return LIBUSB_ERROR_NO_DEVICE; - case ERROR_ACCESS_DENIED: - return LIBUSB_ERROR_ACCESS; - default: - return LIBUSB_ERROR_IO; - } - } - priv->usb_interface[i].restricted_functionality = true; - } - handle_priv->interface_handle[i].api_handle = hid_handle; - } - } - - hid_attributes.Size = sizeof(hid_attributes); - do { - if (!HidD_GetAttributes(hid_handle, &hid_attributes)) { - usbi_err(ctx, "could not gain access to HID top collection (HidD_GetAttributes)"); - break; - } - - priv->hid->vid = hid_attributes.VendorID; - 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); - - // Get the maximum input and output report size - if (!HidD_GetPreparsedData(hid_handle, &preparsed_data) || !preparsed_data) { - usbi_err(ctx, "could not read HID preparsed data (HidD_GetPreparsedData)"); - break; - } - if (HidP_GetCaps(preparsed_data, &capabilities) != HIDP_STATUS_SUCCESS) { - usbi_err(ctx, "could not parse HID capabilities (HidP_GetCaps)"); - break; - } - - // Find out if interrupt will need report IDs - size[0] = capabilities.NumberInputValueCaps; - size[1] = capabilities.NumberOutputValueCaps; - size[2] = capabilities.NumberFeatureValueCaps; - for (j=0; j<3; j++) { - usbi_dbg("%d HID %s report value(s) found", size[j], type[j]); - priv->hid->uses_report_ids[j] = false; - if (size[j] > 0) { - value_caps = malloc(size[j] * sizeof(HIDP_VALUE_CAPS)); - if ( (value_caps != NULL) - && (HidP_GetValueCaps(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++) { - usbi_dbg(" Report ID: 0x%02X", value_caps[i].ReportID); - if (value_caps[i].ReportID != 0) { - nb_ids[1]++; - } else { - nb_ids[0]++; - } - } - if (nb_ids[1] != 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 { - usbi_warn(ctx, " could not process %s report IDs", type[j]); - } - safe_free(value_caps); - } - } - - // Set the report sizes - priv->hid->input_report_size = capabilities.InputReportByteLength; - priv->hid->output_report_size = capabilities.OutputReportByteLength; - priv->hid->feature_report_size = capabilities.FeatureReportByteLength; - - // 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 { - 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 { - 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 { - priv->hid->string[2][0] = 0; - } - } while(0); - - if (preparsed_data) { - HidD_FreePreparsedData(preparsed_data); - } - - return LIBUSB_SUCCESS; -} - -static void hid_close(struct libusb_device_handle *dev_handle) -{ - struct windows_device_priv *priv = __device_priv(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = __device_handle_priv(dev_handle); - HANDLE file_handle; - int i; - - if (!api_hid_available) - return; - - 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)) { - CloseHandle(file_handle); - } - } - } -} - -static int hid_claim_interface(struct libusb_device_handle *dev_handle, int iface) -{ - struct windows_device_handle_priv *handle_priv = __device_handle_priv(dev_handle); - struct windows_device_priv *priv = __device_priv(dev_handle->dev); - - 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 - } - - // 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 - } - - handle_priv->interface_handle[iface].dev_handle = INTERFACE_CLAIMED; - - usbi_dbg("claimed interface %d", iface); - handle_priv->active_interface = iface; - - return LIBUSB_SUCCESS; -} - -static int hid_release_interface(struct libusb_device_handle *dev_handle, int iface) -{ - struct windows_device_handle_priv *handle_priv = __device_handle_priv(dev_handle); - struct windows_device_priv *priv = __device_priv(dev_handle->dev); - - CHECK_HID_AVAILABLE; - - 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 - } - - handle_priv->interface_handle[iface].dev_handle = INVALID_HANDLE_VALUE; - - return LIBUSB_SUCCESS; -} - -static int hid_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - - CHECK_HID_AVAILABLE; - - if (altsetting > 255) { - return LIBUSB_ERROR_INVALID_PARAM; - } - - if (altsetting != 0) { - usbi_err(ctx, "set interface altsetting not supported for altsetting >0"); - return LIBUSB_ERROR_NOT_SUPPORTED; - } - - return LIBUSB_SUCCESS; -} - -static int hid_submit_control_transfer(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_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; - HANDLE hid_handle; - struct winfd wfd; - int current_interface, config; - size_t size; - int r = LIBUSB_ERROR_INVALID_PARAM; - - CHECK_HID_AVAILABLE; - - transfer_priv->pollable_fd = INVALID_WINFD; - safe_free(transfer_priv->hid_buffer); - transfer_priv->hid_dest = NULL; - size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; - - 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 defined(AUTO_CLAIM) - if (auto_claim(transfer, ¤t_interface, USB_API_HID) != LIBUSB_SUCCESS) { - return LIBUSB_ERROR_NOT_FOUND; - } -#else - usbi_warn(ctx, "no interface available for control transfer"); - return LIBUSB_ERROR_NOT_FOUND; -#endif - } - - 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, _O_RDONLY); - if (wfd.fd < 0) { - return LIBUSB_ERROR_NO_MEM; - } - - switch(LIBUSB_REQ_TYPE(setup->request_type)) { - case LIBUSB_REQUEST_TYPE_STANDARD: - switch(setup->request) { - case LIBUSB_REQUEST_GET_DESCRIPTOR: - r = _hid_get_descriptor(priv->hid, wfd.handle, LIBUSB_REQ_RECIPIENT(setup->request_type), - (setup->value >> 8) & 0xFF, setup->value & 0xFF, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, &size); - break; - case LIBUSB_REQUEST_GET_CONFIGURATION: - 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; - r = LIBUSB_COMPLETED; - } - break; - case LIBUSB_REQUEST_SET_CONFIGURATION: - if (setup->value == priv->active_config) { - r = LIBUSB_COMPLETED; - } else { - usbi_warn(ctx, "cannot set configuration other than the default one"); - r = LIBUSB_ERROR_INVALID_PARAM; - } - break; - case LIBUSB_REQUEST_GET_INTERFACE: - size = 1; - ((uint8_t*)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = 0; - r = LIBUSB_COMPLETED; - break; - case LIBUSB_REQUEST_SET_INTERFACE: - r = hid_set_interface_altsetting(transfer->dev_handle, setup->index, setup->value); - if (r == LIBUSB_SUCCESS) { - r = LIBUSB_COMPLETED; - } - break; - default: - usbi_warn(ctx, "unsupported HID control request"); - r = LIBUSB_ERROR_INVALID_PARAM; - break; - } - break; - case LIBUSB_REQUEST_TYPE_CLASS: - 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; - default: - usbi_warn(ctx, "unsupported HID control request"); - r = LIBUSB_ERROR_INVALID_PARAM; - break; - } - - if (r == LIBUSB_COMPLETED) { - // Force request to be completed synchronously. Transferred size has been set by previous call - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - // http://msdn.microsoft.com/en-us/library/ms684342%28VS.85%29.aspx - // set InternalHigh to the number of bytes transferred - wfd.overlapped->InternalHigh = (DWORD)size; - r = LIBUSB_SUCCESS; - } - - if (r == LIBUSB_SUCCESS) { - // Use priv_transfer to store data needed for async polling - transfer_priv->pollable_fd = wfd; - transfer_priv->interface_number = (uint8_t)current_interface; - } else { - usbi_free_fd(wfd.fd); - } - - return r; -} - -static int hid_submit_bulk_transfer(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 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); - struct winfd wfd; - HANDLE hid_handle; - bool direction_in, ret; - int current_interface, length; - DWORD size; - int r = LIBUSB_SUCCESS; - - CHECK_HID_AVAILABLE; - - transfer_priv->pollable_fd = INVALID_WINFD; - transfer_priv->hid_dest = NULL; - safe_free(transfer_priv->hid_buffer); - - current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface); - - hid_handle = handle_priv->interface_handle[current_interface].api_handle; - direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN; - - wfd = usbi_create_fd(hid_handle, direction_in?_O_RDONLY:_O_WRONLY); - // Always use the handle returned from usbi_create_fd (wfd.handle) - 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 { - 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) { - 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: 0x%02X)", length, transfer_priv->hid_buffer[0]); - 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 { - // 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)); - usbi_free_fd(wfd.fd); - safe_free(transfer_priv->hid_buffer); - return LIBUSB_ERROR_IO; - } - } else { - // Only write operations that completed synchronously need to free up - // hid_buffer. For reads, copy_transfer_data() handles that process. - if (!direction_in) { - safe_free(transfer_priv->hid_buffer); - } - if (size == 0) { - usbi_err(ctx, "program assertion failed - no data was transferred"); - size = 1; - } - if (size > (size_t)length) { - usbi_err(ctx, "OVERFLOW!"); - r = LIBUSB_ERROR_OVERFLOW; - } - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - wfd.overlapped->InternalHigh = size; - } - - transfer_priv->pollable_fd = wfd; - transfer_priv->interface_number = (uint8_t)current_interface; - - return r; -} - -static int hid_abort_transfers(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_device_handle_priv *handle_priv = __device_handle_priv(transfer->dev_handle); - HANDLE hid_handle; - int current_interface; - - CHECK_HID_AVAILABLE; - - current_interface = transfer_priv->interface_number; - hid_handle = handle_priv->interface_handle[current_interface].api_handle; - CancelIo(hid_handle); - - return LIBUSB_SUCCESS; -} - -static int hid_reset_device(struct libusb_device_handle *dev_handle) -{ - struct windows_device_handle_priv *handle_priv = __device_handle_priv(dev_handle); - HANDLE hid_handle; - int current_interface; - - CHECK_HID_AVAILABLE; - - // 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)) { - HidD_FlushQueue(hid_handle); - } - } - return LIBUSB_SUCCESS; -} - -static int hid_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = __device_handle_priv(dev_handle); - struct windows_device_priv *priv = __device_priv(dev_handle->dev); - HANDLE hid_handle; - int current_interface; - - CHECK_HID_AVAILABLE; - - current_interface = interface_by_endpoint(priv, handle_priv, endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear"); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface); - hid_handle = handle_priv->interface_handle[current_interface].api_handle; - - // No endpoint selection with Microsoft's implementation, so we try to flush the - // whole interface. Should be OK for most case scenarios - if (!HidD_FlushQueue(hid_handle)) { - usbi_err(ctx, "Flushing of HID queue failed: %s", windows_error_str(0)); - // Device was probably disconnected - return LIBUSB_ERROR_NO_DEVICE; - } - - return LIBUSB_SUCCESS; -} - -// This extra function is only needed for HID -static int hid_copy_transfer_data(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); - int r = LIBUSB_TRANSFER_COMPLETED; - uint32_t corrected_size = io_size; - - 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 - // First, check for overflow - if (corrected_size > transfer_priv->hid_expected_size) { - usbi_err(ctx, "OVERFLOW!"); - corrected_size = (uint32_t)transfer_priv->hid_expected_size; - r = LIBUSB_TRANSFER_OVERFLOW; - } - - 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); - } else { - memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer, corrected_size); - } - transfer_priv->hid_dest = NULL; - } - // For write, we just need to free the hid buffer - safe_free(transfer_priv->hid_buffer); - } - itransfer->transferred += corrected_size; - return r; -} - - -/* * Composite API functions */ static int composite_init(struct libusb_context *ctx) @@ -4335,20 +3184,12 @@ static int composite_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_device_priv *priv = __device_priv(transfer->dev_handle->dev); - int i, pass; - - // Interface shouldn't matter for control, but it does in practice, with Windows' - // restrictions with regards to accessing HID keyboards and mice. Try a 2 pass approach - for (pass = 0; pass < 2; pass++) { - for (i=0; i<USB_MAXINTERFACES; i++) { - if (priv->usb_interface[i].path != NULL) { - if ((pass == 0) && (priv->usb_interface[i].restricted_functionality)) { - usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)", i); - continue; - } - usbi_dbg("using interface %d", i); - return priv->usb_interface[i].apib->submit_control_transfer(itransfer); - } + int i; + + for (i=0; i<USB_MAXINTERFACES; i++) { + if (priv->usb_interface[i].path != NULL) { + usbi_dbg("using interface %d", i); + return priv->usb_interface[i].apib->submit_control_transfer(itransfer); } } diff --git a/libusb/os/windows_usb.h b/libusb/os/windows_usb.h index 644ab6a..fc2c5b7 100644 --- a/libusb/os/windows_usb.h +++ b/libusb/os/windows_usb.h @@ -80,8 +80,6 @@ inline void upperize(char* str) { #define MAX_CTRL_BUFFER_LENGTH 4096 #define MAX_USB_DEVICES 256 #define MAX_USB_STRING_LENGTH 128 -#define MAX_HID_REPORT_SIZE 1024 -#define MAX_HID_DESCRIPTOR_SIZE 256 #define MAX_GUID_STRING_LENGTH 40 #define MAX_PATH_LENGTH 128 #define MAX_KEY_LENGTH 256 @@ -91,11 +89,6 @@ inline void upperize(char* str) { #define LIST_SEPARATOR ';' #define HTAB_SIZE 1021 -// Handle code for HID interface that have been claimed ("dibs") -#define INTERFACE_CLAIMED ((HANDLE)(intptr_t)0xD1B5) -// Additional return code for HID operations that completed synchronously -#define LIBUSB_COMPLETED (LIBUSB_SUCCESS + 1) - // http://msdn.microsoft.com/en-us/library/ff545978.aspx // http://msdn.microsoft.com/en-us/library/ff545972.aspx // http://msdn.microsoft.com/en-us/library/ff545982.aspx @@ -119,11 +112,9 @@ const GUID GUID_NULL = { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x #define USB_API_COMPOSITE 2 #define USB_API_WINUSB 3 #define USB_API_LIBUSBK 4 -#define USB_API_HID 5 -#define USB_API_MAX 6 +#define USB_API_MAX 5 #define CLASS_GUID_UNSUPPORTED GUID_NULL -const GUID CLASS_GUID_HID = { 0x745A17A0, 0x74D3, 0x11D0, {0xB6, 0xFE, 0x00, 0xA0, 0xC9, 0x0F, 0x57, 0xDA} }; const GUID CLASS_GUID_LIBUSB_WINUSB = { 0x78A1C341, 0x4539, 0x11D3, {0xB8, 0x8D, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x71} }; const GUID CLASS_GUID_LIBUSBK = { 0xECFB0CFD, 0x74C4, 0x4F52, {0xBB, 0xF7, 0x34, 0x34, 0x61, 0xCD, 0x72, 0xAC} }; const GUID CLASS_GUID_COMPOSITE = { 0x36FC9E60, 0xC465, 0x11cF, {0x80, 0x56, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} }; @@ -163,71 +154,6 @@ extern const struct windows_usb_api_backend usb_api_backend[USB_API_MAX]; * private structures definition * with inline pseudo constructors/destructors */ - -// TODO (v2+): move hid desc to libusb.h? -struct libusb_hid_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdHID; - uint8_t bCountryCode; - uint8_t bNumDescriptors; - uint8_t bClassDescriptorType; - uint16_t wClassDescriptorLength; -}; -#define LIBUSB_DT_HID_SIZE 9 -#define HID_MAX_CONFIG_DESC_SIZE (LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE \ - + LIBUSB_DT_HID_SIZE + 2 * LIBUSB_DT_ENDPOINT_SIZE) -#define HID_MAX_REPORT_SIZE 1024 -#define HID_IN_EP 0x81 -#define HID_OUT_EP 0x02 -#define LIBUSB_REQ_RECIPIENT(request_type) ((request_type) & 0x1F) -#define LIBUSB_REQ_TYPE(request_type) ((request_type) & (0x03 << 5)) -#define LIBUSB_REQ_IN(request_type) ((request_type) & LIBUSB_ENDPOINT_IN) -#define LIBUSB_REQ_OUT(request_type) (!LIBUSB_REQ_IN(request_type)) - -// The following are used for HID reports IOCTLs -#define HID_CTL_CODE(id) \ - CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_NEITHER, FILE_ANY_ACCESS) -#define HID_BUFFER_CTL_CODE(id) \ - CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HID_IN_CTL_CODE(id) \ - CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_IN_DIRECT, FILE_ANY_ACCESS) -#define HID_OUT_CTL_CODE(id) \ - CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS) - -#define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100) -#define IOCTL_HID_GET_INPUT_REPORT HID_OUT_CTL_CODE(104) -#define IOCTL_HID_SET_FEATURE HID_IN_CTL_CODE(100) -#define IOCTL_HID_SET_OUTPUT_REPORT HID_IN_CTL_CODE(101) - -enum libusb_hid_request_type { - HID_REQ_GET_REPORT = 0x01, - HID_REQ_GET_IDLE = 0x02, - HID_REQ_GET_PROTOCOL = 0x03, - HID_REQ_SET_REPORT = 0x09, - HID_REQ_SET_IDLE = 0x0A, - HID_REQ_SET_PROTOCOL = 0x0B -}; - -enum libusb_hid_report_type { - HID_REPORT_TYPE_INPUT = 0x01, - HID_REPORT_TYPE_OUTPUT = 0x02, - HID_REPORT_TYPE_FEATURE = 0x03 -}; - -struct hid_device_priv { - uint16_t vid; - uint16_t pid; - uint8_t config; - uint8_t nb_interfaces; - bool uses_report_ids[3]; // input, ouptput, feature - uint16_t input_report_size; - uint16_t output_report_size; - uint16_t feature_report_size; - WCHAR string[3][MAX_USB_STRING_LENGTH]; - uint8_t string_index[3]; // man, prod, ser -}; - typedef struct libusb_device_descriptor USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR; struct windows_device_priv { uint8_t depth; // distance to HCD @@ -240,11 +166,8 @@ struct windows_device_priv { struct windows_usb_api_backend const *apib; // an API backend (multiple drivers support), int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS) uint8_t *endpoint; - bool restricted_functionality; // indicates if the interface functionality is restricted - // by Windows (eg. HID keyboards or mice cannot do R/W) } usb_interface[USB_MAXINTERFACES]; - uint8_t composite_api_flags; // HID and composite devices require additional data - struct hid_device_priv *hid; + uint8_t composite_api_flags; // composite devices require additional data uint8_t active_config; USB_DEVICE_DESCRIPTOR dev_descriptor; unsigned char **config_descriptor; // list of pointers to the cached config descriptors @@ -263,7 +186,6 @@ static inline void windows_device_priv_init(libusb_device* dev) { p->path = NULL; p->apib = &usb_api_backend[USB_API_UNSUPPORTED]; p->composite_api_flags = 0; - p->hid = NULL; p->active_config = 0; p->config_descriptor = NULL; memset(&(p->dev_descriptor), 0, sizeof(USB_DEVICE_DESCRIPTOR)); @@ -272,7 +194,6 @@ static inline void windows_device_priv_init(libusb_device* dev) { p->usb_interface[i].apib = &usb_api_backend[USB_API_UNSUPPORTED]; p->usb_interface[i].nb_endpoints = 0; p->usb_interface[i].endpoint = NULL; - p->usb_interface[i].restricted_functionality = false; } } @@ -285,7 +206,6 @@ static inline void windows_device_priv_release(libusb_device* dev) { safe_free(p->config_descriptor[i]); } safe_free(p->config_descriptor); - safe_free(p->hid); for (i=0; i<USB_MAXINTERFACES; i++) { safe_free(p->usb_interface[i].path); safe_free(p->usb_interface[i].endpoint); @@ -315,9 +235,6 @@ static inline struct windows_device_handle_priv *__device_handle_priv( struct windows_transfer_priv { struct winfd pollable_fd; uint8_t interface_number; - uint8_t *hid_buffer; // 1 byte extended data buffer, required for HID - uint8_t *hid_dest; // transfer buffer destination, required for HID - size_t hid_expected_size; }; // used to match a device driver (including filter drivers) against a supported API @@ -576,7 +493,6 @@ typedef struct _USB_HUB_NAME_FIXED { } u; } USB_HUB_NAME_FIXED; - typedef struct _USB_HUB_INFORMATION { USB_HUB_DESCRIPTOR HubDescriptor; BOOLEAN HubIsBusPowered; @@ -712,97 +628,3 @@ DLL_DECLARE(WINAPI, BOOL, LUsbK_ResetPipe, (WINUSB_INTERFACE_HANDLE, UCHAR)); DLL_DECLARE(WINAPI, BOOL, LUsbK_AbortPipe, (WINUSB_INTERFACE_HANDLE, UCHAR)); DLL_DECLARE(WINAPI, BOOL, LUsbK_FlushPipe, (WINUSB_INTERFACE_HANDLE, UCHAR)); DLL_DECLARE(WINAPI, BOOL, LUsbK_ResetDevice, (WINUSB_INTERFACE_HANDLE)); - -/* hid.dll interface */ - -#define HIDP_STATUS_SUCCESS 0x110000 -typedef void* PHIDP_PREPARSED_DATA; - -#pragma pack(1) -typedef struct { - ULONG Size; - USHORT VendorID; - USHORT ProductID; - USHORT VersionNumber; -} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; -#pragma pack() - -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; -} HIDP_CAPS, *PHIDP_CAPS; - -typedef enum _HIDP_REPORT_TYPE { - 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; - 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; - } 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)); diff --git a/libusb/sync.c b/libusb/sync.c index d040d98..f6dc2a7 100644 --- a/libusb/sync.c +++ b/libusb/sync.c @@ -102,13 +102,13 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle, } while (!completed) { - r = libusb_handle_events_check(HANDLE_CTX(dev_handle), &completed); + r = libusb_handle_events(HANDLE_CTX(dev_handle)); if (r < 0) { if (r == LIBUSB_ERROR_INTERRUPTED) continue; libusb_cancel_transfer(transfer); while (!completed) - if (libusb_handle_events_check(HANDLE_CTX(dev_handle), &completed) < 0) + if (libusb_handle_events(HANDLE_CTX(dev_handle)) < 0) break; libusb_free_transfer(transfer); return r; @@ -172,13 +172,13 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, } while (!completed) { - r = libusb_handle_events_check(HANDLE_CTX(dev_handle), &completed); + r = libusb_handle_events(HANDLE_CTX(dev_handle)); if (r < 0) { if (r == LIBUSB_ERROR_INTERRUPTED) continue; libusb_cancel_transfer(transfer); while (!completed) - if (libusb_handle_events_check(HANDLE_CTX(dev_handle), &completed) < 0) + if (libusb_handle_events(HANDLE_CTX(dev_handle)) < 0) break; libusb_free_transfer(transfer); return r; diff --git a/msvc/config.h b/msvc/config.h index 29261fe..0430858 100644 --- a/msvc/config.h +++ b/msvc/config.h @@ -20,11 +20,5 @@ /* Windows backend */ #define OS_WINDOWS /**/ -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Backend handles timeout */ -/* #undef USBI_OS_HANDLES_TIMEOUT */ - -/* timerfd headers available */ -/* #undef USBI_TIMERFD_AVAILABLE */ +/* type of second poll() argument */ +#define POLL_NFDS_TYPE unsigned int |