diff --git a/Externals/.gitignore b/Externals/.gitignore new file mode 100644 index 0000000000..bd54cb0bdc --- /dev/null +++ b/Externals/.gitignore @@ -0,0 +1,8 @@ +libusb/android +libusb/appveyor* +libusb/doc +libusb/examples +libusb/msvc/* +!libusb/msvc/config.h +libusb/tests +libusb/Xcode diff --git a/Externals/libusb/.travis.yml b/Externals/libusb/.travis.yml new file mode 100644 index 0000000000..f5d194ac35 --- /dev/null +++ b/Externals/libusb/.travis.yml @@ -0,0 +1,49 @@ +language: c + +matrix: + include: + - os: linux + dist: trusty + sudo: required + compiler: gcc + - os: linux + dist: trusty + sudo: required + compiler: clang + - os: osx + osx_image: xcode8 + compiler: gcc + - os: osx + osx_image: xcode8 + compiler: clang + - os: osx + osx_image: xcode7.1 + compiler: gcc + - os: osx + osx_image: xcode7.1 + compiler: clang + - os: osx + osx_image: beta-xcode6.2 + compiler: gcc + - os: osx + osx_image: beta-xcode6.2 + compiler: clang + +addons: + homebrew: + update: true + brewfile: true + apt: + packages: + - autoconf + - automake + - libtool + - m4 + - libudev-dev + sources: + - ubuntu-toolchain-r-test + +script: + - ./autogen.sh && make clean && make + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./travis-autogen.sh --disable-udev && make clean && make ; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then cd Xcode && xcodebuild -project libusb.xcodeproj ; fi diff --git a/Externals/libusb/AUTHORS b/Externals/libusb/AUTHORS index 70d407bd19..e90ad9bb2a 100644 --- a/Externals/libusb/AUTHORS +++ b/Externals/libusb/AUTHORS @@ -8,14 +8,19 @@ Copyright © 2010-2012 Michael Plante Copyright © 2011-2013 Hans de Goede Copyright © 2012-2013 Martin Pieuchot Copyright © 2012-2013 Toby Gray -Copyright © 2013-2015 Chris Dickens +Copyright © 2013-2018 Chris Dickens Other contributors: +Adrian Bunk Akshay Jaggi Alan Ott Alan Stern Alex Vatchenko Andrew Fernandes +Andy Chunyu +Andy McFadden +Angus Gratton +Anil Nair Anthony Clay Antonio Ospite Artem Egorkine @@ -23,12 +28,17 @@ Aurelien Jarno Bastien Nocera Bei Zhang Benjamin Dobell +Brent Rector Carl Karsten +Christophe Zeitouny Colin Walters Dave Camarillo David Engraf David Moore Davidlohr Bueso +Dmitry Fleytman +Doug Johnston +Evan Hunter Federico Manzan Felipe Balbi Florian Albrechtskirchinger @@ -41,23 +51,34 @@ Hans Ulrich Niedermann Hector Martin Hoi-Ho Chan Ilya Konstantinov +Jakub Klama James Hanko +Jeffrey Nichols +Johann Richard John Sheu +Jonathon Jongsma +Joost Muller +Josh Gao Joshua Blake Justin Bischoff +KIMURA Masaru Karsten Koenig Konrad Rzepecki Kuangye Guo Lars Kanis Lars Wirzenius +Lei Chen Luca Longinotti Marcus Meissner Markus Heidelberg Martin Ettl Martin Koegler +Matthew Stapleton Matthias Bolte +Michel Zou Mike Frysinger Mikhail Gusarov +Morgan Leborgne Moritz Fischer Ларионов Даниил Nicholas Corgan @@ -66,10 +87,17 @@ Orin Eman Paul Fertser Pekka Nikander Rob Walker +Romain Vimont +Roman Kalashnikov +Sameeh Jubran Sean McBride Sebastian Pipping +Sergey Serb Simon Haggett Simon Newton +Stefan Agner +Stefan Tauner +Steinar H. Gunderson Thomas Röfer Tim Hutt Tim Roberts @@ -81,9 +109,11 @@ Uri Lublin Vasily Khoruzhick Vegard Storheil Eriksen Venkatesh Shukla +Vianney le Clément de Saint-Marcq +Victor Toso Vitali Lovich +William Skellenger Xiaofan Chen Zoltán Kovács Роман Донченко parafin -xantares diff --git a/Externals/libusb/Brewfile b/Externals/libusb/Brewfile new file mode 100644 index 0000000000..c028148f3c --- /dev/null +++ b/Externals/libusb/Brewfile @@ -0,0 +1,4 @@ +brew 'automake' +brew 'libtool' +brew 'autoconf' +brew 'm4' diff --git a/Externals/libusb/ChangeLog b/Externals/libusb/ChangeLog index 2b076b34ac..df7b9a67c7 100644 --- a/Externals/libusb/ChangeLog +++ b/Externals/libusb/ChangeLog @@ -1,6 +1,41 @@ For detailed information about the changes below, please see the git log or visit: http://log.libusb.info +2019-04-05: v1.0.23 (in progress) +* Add German translation (#446) +* Add Hungarian translation (#493) +* Android: Improved support for Android +* configure.ac: Fix detection of clock_gettime library (#439) +* Darwin(macOS): Switch from using ResetDevice to USBDeviceReEnumerate (#455) +* Darwin(macOS): Remove code that changed the device class used (#428) +* Darwin(macOS): Reduce hotplug timeout to 1ms (from 5s) +* New API libusb_set_log_cb() to redirect global and per context log + messages to the provided log handling function +* New API libusb_wrap_sys_device to allow the user to specify the + usb device to use. +* Solaris: Break infinite recursion in backend clock_gettime +* Solaris: Enable timerfd on sunos when available +* Windows: Add support for isochronous transfers with WinUSB +* Various other bug fixes and improvements + +2018-03-24: v1.0.22: +* New libusb_set_option() API +* Fix transfer timeout not being cleared upon resubmission +* Report super speed plus devices on modern Linux and macOS +* Darwin: Improve support for macOS Sierra and High Sierra +* Darwin: SDK fixes and improvements +* Linux: Let initialization succeed when no devices are present +* Linux: Mark internal file descriptors with CLOEXEC flag +* Solaris: Add support for attach/detach kernel driver +* Windows: Add dynamic UsbDk backend selection +* Windows: Add isochronous transfer support via libusbK +* Windows: Add Visual Studio 2017 support +* Windows: Fix enumeration problems on Windows 8 and later +* Windows: Major rework of poll() emulation +* Windows: Numerous HID API fixes +* Windows: Support cancelation of individual transfers (Vista and later) +* Various other bug fixes and improvements + 2016-10-01: v1.0.21: * Core: Refactor code related to transfer flags and timeout handling * Darwin: Ignore root hub simulation devices diff --git a/Externals/libusb/DOLPHIN b/Externals/libusb/DOLPHIN deleted file mode 100644 index dae7a9c3c6..0000000000 --- a/Externals/libusb/DOLPHIN +++ /dev/null @@ -1,7 +0,0 @@ -Dolphin-specific changes (as of 2016-11-20) -------------------------------------------- - -- removed all toplevel directories save msvc/ & libusb/ -- removed all files save AUTHORS, Changelog, COPYING, INSTALL, NEWS, - PORTING, README and TODO -- patched the VS project file to insert dolphin-specific props diff --git a/Externals/libusb/INSTALL_WIN.txt b/Externals/libusb/INSTALL_WIN.txt new file mode 100644 index 0000000000..a37d643a9b --- /dev/null +++ b/Externals/libusb/INSTALL_WIN.txt @@ -0,0 +1,73 @@ +Installation Instructions for Windows +************************************* + +If you are compiling for MinGW or cygwin, please refer to the INSTALL file. + +If you are using Microsoft Visual Studio: +- Open the relevant solution file in /msvc: + libusb.dsw for MSVC6, libusb_2005.sln for Visual Studio 2005 or 2008, + libusb_2010.sln for Visual Studio 2010, + libusb_2012.sln for Visual Studio 2012 or later, + libusb_wince.sln for Windows CE support in Visual Studio 2005. +- If you want to debug the library, uncomment the ENABLE_DEBUG_LOGGING define + in msvc\config.h +- Select your configuration and compile the project + +Note that if you are using Visual Studio Express, you may have to install the +Windows SDK to be able to compile the 64 bit version of the library. + +If you are using the freely available Windows DDK/WDK (Driver Development Kit) +- If you want to debug the library, uncomment the ENABLE_DEBUG_LOGGING define + in msvc\config.h +- Open one of the relevant Free Build or Checked Build prompt for your target + platform +- Navigate to the msvc\ directory where the ddk_build.cmd file is located, and + run 'ddk_build' +- To produce a DLL rather than a static library, use: 'ddk_build DLL' +- To produce a static library that uses LIBCMT[d] instead of MSVCRT[d] (/MT[d] + vs /MD[d] in Visual Studio) use: 'ddk_build /MT' + +Note that using the Windows DDK, it is possible to compile both the 32 and 64 +bit versions of the library. + +If you are building for Windows CE then you will need the Windows CE Standard 5.00 SDK. + +Destination directories +*********************** + +The 32 bit binaries compiled either from Visual Studio or the DDK are placed in +a Win32\ directory at the root of the library +The 64 bit binaries are placed in an x64\ directory +Windows CE binaries are placed in one of the following directories, depending +on the target processor: ARMV4I, MIPSII, MIPSII_FP, MIPSIV, MIPSIV_FP, SH4 or x86. + + +Troubleshooting +*************** + +If the compilation process complains about missing libraries, ensure that the +default library paths for your project points to the relevant directories. +If needed, these libraries can be obtained by installing either the latest +Windows SDK or the DDK (Links provided at the end of this file). + +For Windows CE it is necessary to install the CE USB Kernel Wrapper driver for +libusb to function on a device. + +Links +***** + +Additional information related to the Windows backend: + http://windows.libusb.info + +Latest Windows Driver (Development) Kit (WDK): + http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=36a2630f-5d56-43b5-b996-7633f2ec14ff + +Latest Microsoft Windows SDK: + http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=c17ba869-9671-4330-a63e-1fd44e0e2505 + +Windows CE Standard 5.00 SDK: + http://www.microsoft.com/en-gb/download/details.aspx?id=17310 + +Windows CE USB Kernel Wrapper Driver: + https://github.com/RealVNC/CEUSBKWrapper + diff --git a/Externals/libusb/Makefile.am b/Externals/libusb/Makefile.am new file mode 100644 index 0000000000..0155625ac1 --- /dev/null +++ b/Externals/libusb/Makefile.am @@ -0,0 +1,28 @@ +AUTOMAKE_OPTIONS = dist-bzip2 no-dist-gzip +ACLOCAL_AMFLAGS = -I m4 +DISTCLEANFILES = libusb-1.0.pc +EXTRA_DIST = TODO PORTING msvc libusb/libusb-1.0.def libusb/version_nano.h \ + examples/getopt/getopt.c examples/getopt/getopt1.c examples/getopt/getopt.h \ + android Xcode +SUBDIRS = libusb doc + +if BUILD_EXAMPLES +SUBDIRS += examples +endif + +if BUILD_TESTS +SUBDIRS += tests +endif + +pkgconfigdir=$(libdir)/pkgconfig +pkgconfig_DATA=libusb-1.0.pc + +.PHONY: dist-up + +reldir = .release/$(distdir) +dist-up: dist + rm -rf $(reldir) + mkdir -p $(reldir) + cp $(distdir).tar.bz2 $(reldir) + rsync -rv $(reldir) frs.sourceforge.net:/home/frs/project/l/li/libusb/libusb-1.0/ + rm -rf $(reldir) diff --git a/Externals/libusb/README b/Externals/libusb/README deleted file mode 100644 index 0554e4eb03..0000000000 --- a/Externals/libusb/README +++ /dev/null @@ -1,33 +0,0 @@ -# libusb - -[![Build Status](https://travis-ci.org/libusb/libusb.svg?branch=master)](https://travis-ci.org/libusb/libusb) -[![Build status](https://ci.appveyor.com/api/projects/status/xvrfam94jii4a6lw?svg=true)](https://ci.appveyor.com/project/LudovicRousseau/libusb) -[![Coverity Scan Build Status](https://scan.coverity.com/projects/2180/badge.svg)](https://scan.coverity.com/projects/libusb-libusb) - -libusb is a library for USB device access from Linux, Mac OS X, -Windows, OpenBSD/NetBSD and Haiku userspace. -It is written in C (Haiku backend in C++) and licensed under the GNU -Lesser General Public License version 2.1 or, at your option, any later -version (see [COPYING](COPYING)). - -libusb is abstracted internally in such a way that it can hopefully -be ported to other operating systems. Please see the [PORTING](PORTING) -file for more information. - -libusb homepage: -http://libusb.info/ - -Developers will wish to consult the API documentation: -http://api.libusb.info - -Use the mailing list for questions, comments, etc: -http://mailing-list.libusb.info - -- Pete Batard -- Hans de Goede -- Xiaofan Chen -- Ludovic Rousseau -- Nathan Hjelm -- Chris Dickens - -(Please use the mailing list rather than mailing developers directly) diff --git a/Externals/libusb/README b/Externals/libusb/README new file mode 120000 index 0000000000..42061c01a1 --- /dev/null +++ b/Externals/libusb/README @@ -0,0 +1 @@ +README.md \ No newline at end of file diff --git a/Externals/libusb/README.git b/Externals/libusb/README.git new file mode 100644 index 0000000000..eab938cb2d --- /dev/null +++ b/Externals/libusb/README.git @@ -0,0 +1,41 @@ +Notes related to git compilation: +-------------------------------- + +If you retrieved the libusb repository from git and are using a gcc based +toolchain, be mindful that you should have the autotools installed (autoconf, +automake) and will need to run either ./autogen.sh or ./bootstrap.sh to produce +the configure file. + +The difference between autogen.sh and bootstrap.sh is that the former invokes +configure with a default set of options, and will therefore generate a Makefile, +whereas the latter does not invoke configure at all. If using autogen.sh, note +that you can also append options, that will be passed as is to configure. + +OS X-specific notes: +------------------- + +Starting with Xcode 4.3, neither Xcode.app nor the Xcode 'command line tools' +includes autotools and so running either autogen.sh or bootstrap.sh will result +in the message: + +libtoolize or glibtoolize was not found! Please install libtool. + +To proceed, you must find and install it from somewhere. + +Alternatively, you can use the Xcode project at Xcode/libusb.xcodeproj. + +Notes related to submitting new developments: +-------------------------------------------- + +If you submit a new development to libusb (eg: new backend), that is unlikely +to fit in a couple of small patches, we would kindly suggest that you create a +public account on github, if you don't have one already, and then fork a new +libusb repository under this account from https://github.com/libusb/libusb. + +Then you can create a git branch for your work, that we will be able to better +reference and test. + +We also suggest that, if you are planning to bring in a large development, you +try to involve the libusb community early by letting the mailing list know, as +you may find that other people might be eager to help you out. +See http://mailing-list.libusb.info for details on how to join the mailing list. \ No newline at end of file diff --git a/Externals/libusb/README.md b/Externals/libusb/README.md new file mode 100644 index 0000000000..0e7228a9fe --- /dev/null +++ b/Externals/libusb/README.md @@ -0,0 +1,32 @@ +# libusb + +[![Build Status](https://travis-ci.org/libusb/libusb.svg?branch=master)](https://travis-ci.org/libusb/libusb) +[![Build status](https://ci.appveyor.com/api/projects/status/xvrfam94jii4a6lw?svg=true)](https://ci.appveyor.com/project/LudovicRousseau/libusb) +[![Coverity Scan Build Status](https://scan.coverity.com/projects/2180/badge.svg)](https://scan.coverity.com/projects/libusb-libusb) + +libusb is a library for USB device access from Linux, macOS, +Windows, OpenBSD/NetBSD and Haiku userspace. +It is written in C (Haiku backend in C++) and licensed under the GNU +Lesser General Public License version 2.1 or, at your option, any later +version (see [COPYING](COPYING)). + +libusb is abstracted internally in such a way that it can hopefully +be ported to other operating systems. Please see the [PORTING](PORTING) +file for more information. + +libusb homepage: +http://libusb.info/ + +Developers will wish to consult the API documentation: +http://api.libusb.info + +Use the mailing list for questions, comments, etc: +http://mailing-list.libusb.info + +- Hans de Goede +- Xiaofan Chen +- Ludovic Rousseau +- Nathan Hjelm +- Chris Dickens + +(Please use the mailing list rather than mailing developers directly) diff --git a/Externals/libusb/autogen.sh b/Externals/libusb/autogen.sh new file mode 100755 index 0000000000..24f39ee695 --- /dev/null +++ b/Externals/libusb/autogen.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +set -e + +./bootstrap.sh +if test -z "$NOCONFIGURE"; then + exec ./configure --enable-examples-build --enable-tests-build "$@" +fi diff --git a/Externals/libusb/bootstrap.sh b/Externals/libusb/bootstrap.sh new file mode 100755 index 0000000000..dc56539411 --- /dev/null +++ b/Externals/libusb/bootstrap.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +if ! test -d m4 ; then + mkdir m4 +fi +autoreconf -ivf || exit 1 diff --git a/Externals/libusb/configure.ac b/Externals/libusb/configure.ac new file mode 100644 index 0000000000..76f67d9b49 --- /dev/null +++ b/Externals/libusb/configure.ac @@ -0,0 +1,332 @@ +dnl These m4 macros are whitespace sensitive and break if moved around much. +m4_define([LU_VERSION_H], m4_include([libusb/version.h])) +m4_define([LU_DEFINE_VERSION_ATOM], + [m4_define([$1], m4_bregexp(LU_VERSION_H, + [^#define\s*$1\s*\([0-9]*\).*], [\1]))]) +m4_define([LU_DEFINE_VERSION_RC_ATOM], + [m4_define([$1], m4_bregexp(LU_VERSION_H, + [^#define\s*$1\s*"\(-rc[0-9]*\)".*], [\1]))]) +dnl The m4_bregexp() returns (only) the numbers following the #define named +dnl in the first macro parameter. m4_define() then defines the name for use +dnl in AC_INIT. + +LU_DEFINE_VERSION_ATOM([LIBUSB_MAJOR]) +LU_DEFINE_VERSION_ATOM([LIBUSB_MINOR]) +LU_DEFINE_VERSION_ATOM([LIBUSB_MICRO]) +LU_DEFINE_VERSION_RC_ATOM([LIBUSB_RC]) + +AC_INIT([libusb],[LIBUSB_MAJOR[.]LIBUSB_MINOR[.]LIBUSB_MICRO[]LIBUSB_RC],[libusb-devel@lists.sourceforge.net],[libusb],[http://libusb.info]) + +# Library versioning +# These numbers should be tweaked on every release. Read carefully: +# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html +# http://sourceware.org/autobook/autobook/autobook_91.html +lt_current=2 +lt_revision=0 +lt_age=1 +LTLDFLAGS="-version-info ${lt_current}:${lt_revision}:${lt_age}" + +AM_INIT_AUTOMAKE + +AC_CONFIG_SRCDIR([libusb/core.c]) +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_HEADERS([config.h]) +m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) + +AC_PREREQ([2.69]) +AC_PROG_CC +AC_PROG_CXX +LT_INIT +LT_LANG([Windows Resource]) +AC_C_INLINE +AM_PROG_CC_C_O +AC_DEFINE([_GNU_SOURCE], 1, [Use GNU extensions]) + +LTLDFLAGS="${LTLDFLAGS} -no-undefined" + +AC_MSG_CHECKING([operating system]) + +dnl on linux-android platform, some functions are in different places +case $host in +*-linux-android*) + AC_MSG_RESULT([This is a Linux-Android system]) + is_backend_android=yes + ;; +*) + is_backend_android=no +esac + +case $host in +*-linux* | *-uclinux*) + AC_MSG_RESULT([Linux]) + backend=linux + threads=posix + ;; +*-darwin*) + AC_MSG_RESULT([Darwin/Mac OS X]) + backend=darwin + threads=posix + ;; +*-openbsd*) + AC_MSG_RESULT([OpenBSD]) + backend=openbsd + threads=posix + ;; +*-netbsd*) + AC_MSG_RESULT([NetBSD]) + backend=netbsd + threads=posix + ;; +*-mingw* | *msys*) + AC_MSG_RESULT([Windows]) + backend=windows + threads=windows + create_import_lib=yes + AM_CFLAGS="${AM_CFLAGS} -fno-omit-frame-pointer" + ;; +*-cygwin*) + AC_MSG_RESULT([Cygwin (using Windows backend)]) + backend=windows + threads=posix + ;; +*-haiku*) + AC_MSG_RESULT([Haiku]) + backend=haiku + threads=posix + ;; +*-solaris*) + AC_MSG_RESULT([SunOS]) + backend=sunos + threads=posix + ;; +*) + AC_MSG_ERROR([unsupported operating system $host]) +esac + +case $backend in +linux) + AC_DEFINE(OS_LINUX, 1, [Linux backend]) + AC_SUBST(OS_LINUX) + AC_SEARCH_LIBS([clock_gettime], [rt], [], [], [-pthread]) + AC_ARG_ENABLE([udev], + [AC_HELP_STRING([--enable-udev], [use udev for device enumeration and hotplug support (recommended) [default=yes]])], + [], [enable_udev=yes]) + if test "x$enable_udev" = xyes ; then + # system has udev. use it or fail! + AC_CHECK_HEADERS([libudev.h], [], [AC_MSG_ERROR([udev support requested but libudev header not installed])]) + AC_CHECK_LIB([udev], [udev_new], [], [AC_MSG_ERROR([udev support requested but libudev not installed])]) + AC_DEFINE(USE_UDEV, 1, [Use udev for device enumeration/hotplug]) + else + AC_CHECK_HEADERS([asm/types.h], [], []) + AC_CHECK_HEADERS([sys/socket.h linux/netlink.h], [], [AC_MSG_ERROR([Linux netlink headers not found])], [ +#ifdef HAVE_ASM_TYPES_H +#include +#endif +#include +]) + fi + AC_SUBST(USE_UDEV) + + if test "x$is_backend_android" != xyes; then + THREAD_CFLAGS="-pthread" + LIBS="${LIBS} -pthread" + fi + + AC_CHECK_HEADERS([poll.h]) + AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument]) + ;; +darwin) + AC_DEFINE(OS_DARWIN, 1, [Darwin backend]) + AC_SUBST(OS_DARWIN) + LIBS="-lobjc -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 ]) + ;; +openbsd) + AC_DEFINE(OS_OPENBSD, 1, [OpenBSD backend]) + AC_SUBST(OS_OPENBSD) + THREAD_CFLAGS="-pthread" + LIBS="-pthread" + AC_CHECK_HEADERS([poll.h]) + AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument]) + ;; +sunos) + AC_DEFINE(OS_SUNOS, 1, [SunOS backend]) + AC_SUBST(OS_SUNOS) + THREAD_CFLAGS="-pthread" + LIBS="-pthread -ldevinfo" + AC_CHECK_HEADERS([poll.h]) + AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument]) + ;; +netbsd) + AC_DEFINE(OS_NETBSD, 1, [NetBSD backend]) + AC_SUBST(OS_NETBSD) + THREAD_CFLAGS="-pthread" + LIBS="-pthread" + AC_CHECK_HEADERS([poll.h]) + AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument]) + ;; +windows) + AC_DEFINE(OS_WINDOWS, 1, [Windows backend]) + AC_SUBST(OS_WINDOWS) + LIBS="" + LTLDFLAGS="${LTLDFLAGS} -avoid-version -Wl,--add-stdcall-alias" + AC_DEFINE([POLL_NFDS_TYPE],[unsigned int],[type of second poll() argument]) + AC_DEFINE([WINVER], 0x0501, [Oldest Windows version supported]) + AC_DEFINE([_WIN32_WINNT], 0x0501, [Oldest Windows version supported]) + ;; +haiku) + AC_DEFINE(OS_HAIKU, 1, [Haiku backend]) + AC_SUBST(OS_HAIKU) + LIBS="${LIBS} -lbe" + AC_CHECK_HEADERS([poll.h]) + AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument]) + ;; +esac + +AC_SUBST(LIBS) + +AM_CONDITIONAL(OS_LINUX, test "x$backend" = xlinux) +AM_CONDITIONAL(OS_DARWIN, test "x$backend" = xdarwin) +AM_CONDITIONAL(OS_OPENBSD, test "x$backend" = xopenbsd) +AM_CONDITIONAL(OS_SUNOS, test "x$backend" = xsunos) +AM_CONDITIONAL(OS_NETBSD, test "x$backend" = xnetbsd) +AM_CONDITIONAL(OS_WINDOWS, test "x$backend" = xwindows) +AM_CONDITIONAL(OS_HAIKU, test "x$backend" = xhaiku) +AM_CONDITIONAL(THREADS_POSIX, test "x$threads" = xposix) +AM_CONDITIONAL(CREATE_IMPORT_LIB, test "x$create_import_lib" = xyes) +AM_CONDITIONAL(USE_UDEV, test "x$enable_udev" = xyes) +if test "x$threads" = xposix; then + AC_DEFINE(THREADS_POSIX, 1, [Use POSIX Threads]) +fi + +# timerfd +AC_CHECK_HEADER([sys/timerfd.h], [timerfd_h=1], [timerfd_h=0]) +AC_ARG_ENABLE([timerfd], + [AS_HELP_STRING([--enable-timerfd], + [use timerfd for timing [default=auto]])], + [use_timerfd=$enableval], [use_timerfd=auto]) + +if test "x$use_timerfd" = xyes -a "x$timerfd_h" = x0; then + AC_MSG_ERROR([timerfd header not available; glibc 2.9+ required]) +fi + +AC_CHECK_DECLS([TFD_NONBLOCK, TFD_CLOEXEC], [tfd_hdr_ok=yes], [tfd_hdr_ok=no], [#include ]) +if test "x$use_timerfd" = xyes -a "x$tfd_hdr_ok" = xno; then + AC_MSG_ERROR([timerfd header not usable; glibc 2.9+ required]) +fi + +AC_MSG_CHECKING([whether to use timerfd for timing]) +if test "x$use_timerfd" = xno; then + AC_MSG_RESULT([no (disabled by user)]) +else + if test "x$timerfd_h" = x1 -a "x$tfd_hdr_ok" = xyes; then + AC_MSG_RESULT([yes]) + AC_DEFINE(USBI_TIMERFD_AVAILABLE, 1, [timerfd headers available]) + else + AC_MSG_RESULT([no (header not available)]) + fi +fi + +AC_CHECK_FUNCS([pipe2]) +AC_CHECK_TYPES([struct timespec]) + +# Message logging +AC_ARG_ENABLE([log], [AS_HELP_STRING([--disable-log], [disable all logging])], + [log_enabled=$enableval], + [log_enabled=yes]) +if test "x$log_enabled" != xno; then + AC_DEFINE([ENABLE_LOGGING], 1, [Message logging]) +fi + +AC_ARG_ENABLE([debug-log], [AS_HELP_STRING([--enable-debug-log], + [start with debug message logging enabled [default=no]])], + [debug_log_enabled=$enableval], + [debug_log_enabled=no]) +if test "x$debug_log_enabled" != xno; then + AC_DEFINE([ENABLE_DEBUG_LOGGING], 1, [Start with debug message logging enabled]) +fi + +AC_ARG_ENABLE([system-log], [AS_HELP_STRING([--enable-system-log], + [output logging messages to system wide log, if supported by the OS [default=no]])], + [system_log_enabled=$enableval], + [system_log_enabled=no]) +if test "x$system_log_enabled" != xno; then + AC_DEFINE([USE_SYSTEM_LOGGING_FACILITY], 1, [Enable output to system log]) + + # Check if syslog is available in standard C library + AC_CHECK_HEADERS(syslog.h) + AC_CHECK_FUNC([syslog], [have_syslog=yes], [have_syslog=no]) + if test "x$have_syslog" != xno; then + AC_DEFINE([HAVE_SYSLOG_FUNC], 1, [syslog() function available]) + fi +fi + +# Examples build +AC_ARG_ENABLE([examples-build], [AS_HELP_STRING([--enable-examples-build], + [build example applications [default=no]])], + [build_examples=$enableval], + [build_examples=no]) +AM_CONDITIONAL(BUILD_EXAMPLES, test "x$build_examples" != xno) + +# Tests build +AC_ARG_ENABLE([tests-build], [AS_HELP_STRING([--enable-tests-build], + [build test applications [default=no]])], + [build_tests=$enableval], + [build_tests=no]) +AM_CONDITIONAL(BUILD_TESTS, test "x$build_tests" != xno) + +# headers not available on all platforms but required on others +AC_CHECK_HEADERS([sys/time.h]) + +# sigaction not available on MinGW +AC_CHECK_FUNC([sigaction], [have_sigaction=yes], [have_sigaction=no]) +AM_CONDITIONAL(HAVE_SIGACTION, test "x$have_sigaction" = xyes) + +# 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([])], + [VISIBILITY_CFLAGS="-fvisibility=hidden" + AC_DEFINE([DEFAULT_VISIBILITY], [__attribute__((visibility("default")))], [Default visibility])], + [VISIBILITY_CFLAGS="" + AC_DEFINE([DEFAULT_VISIBILITY], [], [Default visibility])], + ]) +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([])], + nopointersign_cflags="-Wno-pointer-sign", nopointersign_cflags="") +CFLAGS="$saved_cflags" + +# check for -std=gnu99 compiler support +saved_cflags="$CFLAGS" +CFLAGS="-std=gnu99" +AC_MSG_CHECKING([whether CC supports -std=gnu99]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], + [AC_MSG_RESULT([yes])] + [AM_CFLAGS="${AM_CFLAGS} -std=gnu99"], + [AC_MSG_RESULT([no])] +) +CFLAGS="$saved_cflags" + +AM_CFLAGS="${AM_CFLAGS} -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration $nopointersign_cflags -Wshadow ${THREAD_CFLAGS} ${VISIBILITY_CFLAGS}" + +AC_SUBST(AM_CFLAGS) +AC_SUBST(LTLDFLAGS) + +AC_CONFIG_FILES([libusb-1.0.pc]) +AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([libusb/Makefile]) +AC_CONFIG_FILES([examples/Makefile]) +AC_CONFIG_FILES([tests/Makefile]) +AC_CONFIG_FILES([doc/Makefile]) +AC_CONFIG_FILES([doc/doxygen.cfg]) +AC_OUTPUT diff --git a/Externals/libusb/libusb-1.0.pc.in b/Externals/libusb/libusb-1.0.pc.in new file mode 100644 index 0000000000..4aba609e6a --- /dev/null +++ b/Externals/libusb/libusb-1.0.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libusb-1.0 +Description: C API for USB device access from Linux, Mac OS X, Windows, OpenBSD/NetBSD and Solaris userspace +Version: @VERSION@ +Libs: -L${libdir} -lusb-1.0 +Libs.private: @LIBS@ +Cflags: -I${includedir}/libusb-1.0 diff --git a/Externals/libusb/libusb/Makefile.am b/Externals/libusb/libusb/Makefile.am index 0eca02e857..e4da62eb35 100644 --- a/Externals/libusb/libusb/Makefile.am +++ b/Externals/libusb/libusb/Makefile.am @@ -13,10 +13,12 @@ DARWIN_USB_SRC = os/darwin_usb.h os/darwin_usb.c OPENBSD_USB_SRC = os/openbsd_usb.c NETBSD_USB_SRC = os/netbsd_usb.c SUNOS_USB_SRC = os/sunos_usb.c os/sunos_usb.h -WINDOWS_COMMON_SRC = os/windows_nt_common.h os/windows_nt_common.c \ - os/windows_common.h libusb-1.0.rc libusb-1.0.def -WINDOWS_USB_SRC = os/windows_winusb.h os/windows_winusb.c os/windows_usbdk.h \ - os/windows_usbdk.c $(COMMON_WINDOWS_SRC) +WINDOWS_USB_SRC = libusb-1.0.def libusb-1.0.rc \ + os/windows_common.h \ + os/windows_nt_common.h os/windows_nt_common.c \ + os/windows_nt_shared_types.h \ + os/windows_usbdk.h os/windows_usbdk.c \ + os/windows_winusb.h os/windows_winusb.c WINCE_USB_SRC = os/wince_usb.h os/wince_usb.c HAIKU_USB_SRC = os/haiku_usb.h os/haiku_usb_backend.cpp \ os/haiku_usb_raw.h os/haiku_usb_raw.cpp os/haiku_pollfs.cpp @@ -25,8 +27,8 @@ EXTRA_DIST = $(POSIX_POLL_SRC) $(POSIX_THREADS_SRC) \ $(WINDOWS_POLL_SRC) $(WINDOWS_THREADS_SRC) \ $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) \ $(OPENBSD_USB_SRC) $(NETBSD_USB_SRC) \ - $(WINDOWS_COMMON_SRC) $(WINDOWS_USB_SRC) $(WINDOWS_USBDK_SRC) \ - $(WINCE_USB_SRC) $(HAIKU_USB_SRC) \ + $(WINDOWS_USB_SRC) $(WINCE_USB_SRC) \ + $(HAIKU_USB_SRC) \ os/linux_udev.c os/linux_netlink.c if OS_LINUX @@ -63,7 +65,7 @@ libusb_1_0_la_LIBADD = libusb_haiku.la endif if OS_WINDOWS -OS_SRC = $(WINDOWS_USB_SRC) $(WINDOWS_COMMON_SRC) +OS_SRC = $(WINDOWS_USB_SRC) .rc.lo: $(AM_V_GEN)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(RCFLAGS) -i $< -o $@ diff --git a/Externals/libusb/libusb/core.c b/Externals/libusb/libusb/core.c index 5d59210dc5..741bf99a5f 100644 --- a/Externals/libusb/libusb/core.c +++ b/Externals/libusb/libusb/core.c @@ -44,33 +44,16 @@ #include "libusbi.h" #include "hotplug.h" -#if defined(OS_LINUX) -const struct usbi_os_backend * const usbi_backend = &linux_usbfs_backend; -#elif defined(OS_DARWIN) -const struct usbi_os_backend * const usbi_backend = &darwin_backend; -#elif defined(OS_OPENBSD) -const struct usbi_os_backend * const usbi_backend = &openbsd_backend; -#elif defined(OS_NETBSD) -const struct usbi_os_backend * const usbi_backend = &netbsd_backend; -#elif defined(OS_WINDOWS) -const struct usbi_os_backend * usbi_backend; -#elif defined(OS_WINCE) -const struct usbi_os_backend * const usbi_backend = &wince_backend; -#elif defined(OS_HAIKU) -const struct usbi_os_backend * const usbi_backend = &haiku_usb_raw_backend; -#elif defined (OS_SUNOS) -const struct usbi_os_backend * const usbi_backend = &sunos_backend; -#else -#error "Unsupported OS" -#endif - struct libusb_context *usbi_default_context = NULL; static const struct libusb_version libusb_version_internal = { LIBUSB_MAJOR, LIBUSB_MINOR, LIBUSB_MICRO, LIBUSB_NANO, LIBUSB_RC, "http://libusb.info" }; static int default_context_refcnt = 0; static usbi_mutex_static_t default_context_lock = USBI_MUTEX_INITIALIZER; -static struct timeval timestamp_origin = { 0, 0 }; +static struct timespec timestamp_origin = { 0, 0 }; +#ifndef USE_SYSTEM_LOGGING_FACILITY +static libusb_log_cb log_handler = NULL; +#endif usbi_mutex_static_t active_contexts_lock = USBI_MUTEX_INITIALIZER; struct list_head active_contexts_list; @@ -136,15 +119,17 @@ struct list_head active_contexts_list; * libusb uses stderr for all logging. By default, logging is set to NONE, * which means that no output will be produced. However, unless the library * has been compiled with logging disabled, then any application calls to - * libusb_set_debug(), or the setting of the environmental variable - * LIBUSB_DEBUG outside of the application, can result in logging being - * produced. Your application should therefore not close stderr, but instead - * direct it to the null device if its output is undesirable. + * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level), or the setting of the + * environmental variable LIBUSB_DEBUG outside of the application, can result + * in logging being produced. Your application should therefore not close + * stderr, but instead direct it to the null device if its output is + * undesirable. * - * The libusb_set_debug() function can be used to enable logging of certain - * messages. Under standard configuration, libusb doesn't really log much - * so you are advised to use this function to enable all error/warning/ - * informational messages. It will help debug problems with your software. + * The libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) function can be + * used to enable logging of certain messages. Under standard configuration, + * libusb doesn't really log much so you are advised to use this function + * to enable all error/warning/ informational messages. It will help debug + * problems with your software. * * The logged messages are unstructured. There is no one-to-one correspondence * between messages being logged and success or failure return codes from @@ -159,18 +144,20 @@ struct list_head active_contexts_list; * * The LIBUSB_DEBUG environment variable can be used to enable message logging * at run-time. This environment variable should be set to a log level number, - * which is interpreted the same as the libusb_set_debug() parameter. When this + * which is interpreted the same as the + * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) parameter. When this * environment variable is set, the message logging verbosity level is fixed - * and libusb_set_debug() effectively does nothing. + * and libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) effectively does + * nothing. * * libusb can be compiled without any logging functions, useful for embedded - * systems. In this case, libusb_set_debug() and the LIBUSB_DEBUG environment - * variable have no effects. + * systems. In this case, libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) + * and the LIBUSB_DEBUG environment variable have no effects. * * libusb can also be compiled with verbose debugging messages always. When * the library is compiled in this way, all messages of all verbosities are - * always logged. libusb_set_debug() and the LIBUSB_DEBUG environment variable - * have no effects. + * always logged. libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) and + * the LIBUSB_DEBUG environment variable have no effects. * * \section remarks Other remarks * @@ -181,6 +168,20 @@ struct list_head active_contexts_list; /** * \page libusb_caveats Caveats * + * \section fork Fork considerations + * + * libusb is not designed to work across fork() calls. Depending on + * the platform, there may be resources in the parent process that are not + * available to the child (e.g. the hotplug monitor thread on Linux). In + * addition, since the parent and child will share libusb's internal file + * descriptors, using libusb in any way from the child could cause the parent + * process's \ref libusb_context to get into an inconsistent state. + * + * On Linux, libusb's file descriptors will be marked as CLOEXEC, which means + * that it is safe to fork() and exec() without worrying about the child + * process needing to clean up state or having access to these file descriptors. + * Other platforms may not be so forgiving, so consider yourself warned! + * * \section devresets Device resets * * The libusb_reset_device() function allows you to reset a device. If your @@ -285,7 +286,6 @@ if (cfg != desired) * information about the end of the short packet, and the user probably wanted * that surplus data to arrive in the next logical transfer. * - * * \section zlp Zero length packets * * - libusb is able to send a packet of zero length to an endpoint simply by @@ -304,7 +304,7 @@ if (cfg != desired) * developed modules may both use libusb. * * libusb is written to allow for these multiple user scenarios. The two - * "instances" of libusb will not interfere: libusb_set_debug() calls + * "instances" of libusb will not interfere: libusb_set_option() calls * from one user will not affect the same settings for other users, other * users can continue using libusb after one of them calls libusb_exit(), etc. * @@ -427,8 +427,10 @@ if (cfg != desired) * - libusb_set_auto_detach_kernel_driver() * - libusb_set_configuration() * - libusb_set_debug() + * - libusb_set_log_cb() * - libusb_set_interface_alt_setting() * - libusb_set_iso_packet_lengths() + * - libusb_set_option() * - libusb_setlocale() * - libusb_set_pollfd_notifiers() * - libusb_strerror() @@ -472,6 +474,7 @@ if (cfg != desired) * - \ref libusb_iso_sync_type * - \ref libusb_iso_usage_type * - \ref libusb_log_level + * - \ref libusb_option * - \ref libusb_request_recipient * - \ref libusb_request_type * - \ref libusb_speed @@ -623,26 +626,6 @@ static struct discovered_devs *discovered_devs_alloc(void) return ret; } -#ifdef OS_WINDOWS -static int is_usbdk_driver_installed(void) -{ - int usbdk_installed = 0; - - SC_HANDLE managerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); - if (managerHandle) - { - SC_HANDLE serviceHandle = OpenService(managerHandle, TEXT("UsbDk"), GENERIC_READ); - if (serviceHandle) - { - usbdk_installed = 1; - CloseServiceHandle(serviceHandle); - } - CloseServiceHandle(managerHandle); - } - return usbdk_installed; -} -#endif - static void discovered_devs_free(struct discovered_devs *discdevs) { size_t i; @@ -694,7 +677,7 @@ struct discovered_devs *discovered_devs_append( struct libusb_device *usbi_alloc_device(struct libusb_context *ctx, unsigned long session_id) { - size_t priv_size = usbi_backend->device_priv_size; + size_t priv_size = usbi_backend.device_priv_size; struct libusb_device *dev = calloc(1, sizeof(*dev) + priv_size); int r; @@ -838,8 +821,8 @@ ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx, /* backend provides hotplug support */ struct libusb_device *dev; - if (usbi_backend->hotplug_poll) - usbi_backend->hotplug_poll(); + if (usbi_backend.hotplug_poll) + usbi_backend.hotplug_poll(); usbi_mutex_lock(&ctx->usb_devs_lock); list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) { @@ -853,7 +836,7 @@ ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx, usbi_mutex_unlock(&ctx->usb_devs_lock); } else { /* backend does not provide hotplug support */ - r = usbi_backend->get_device_list(ctx, &discdevs); + r = usbi_backend.get_device_list(ctx, &discdevs); } if (r < 0) { @@ -862,8 +845,8 @@ ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx, } /* convert discovered_devs into a list */ - len = discdevs->len; - ret = calloc(len + 1, sizeof(struct libusb_device *)); + len = (ssize_t)discdevs->len; + ret = calloc((size_t)len + 1, sizeof(struct libusb_device *)); if (!ret) { len = LIBUSB_ERROR_NO_MEM; goto out; @@ -1096,7 +1079,9 @@ out: * If acting on an isochronous or interrupt endpoint, this function will * multiply the value found in bits 0:10 by the number of transactions per * microframe (determined by bits 11:12). Otherwise, this function just - * returns the numeric value found in bits 0:10. + * returns the numeric value found in bits 0:10. For USB 3.0 device, it + * will attempts to retrieve the Endpoint Companion Descriptor to return + * wBytesPerInterval. * * This function is useful for setting up isochronous transfers, for example * you might pass the return value from this function to @@ -1116,9 +1101,11 @@ int API_EXPORTED libusb_get_max_iso_packet_size(libusb_device *dev, { struct libusb_config_descriptor *config; const struct libusb_endpoint_descriptor *ep; + struct libusb_ss_endpoint_companion_descriptor *ss_ep_cmp; enum libusb_transfer_type ep_type; uint16_t val; int r; + int speed; r = libusb_get_active_config_descriptor(dev, &config); if (r < 0) { @@ -1133,13 +1120,25 @@ int API_EXPORTED libusb_get_max_iso_packet_size(libusb_device *dev, goto out; } - val = ep->wMaxPacketSize; - ep_type = (enum libusb_transfer_type) (ep->bmAttributes & 0x3); + speed = libusb_get_device_speed( dev ); + if (speed == LIBUSB_SPEED_SUPER) { + r = libusb_get_ss_endpoint_companion_descriptor(dev->ctx, ep, &ss_ep_cmp); + if (r == LIBUSB_SUCCESS) { + r = ss_ep_cmp->wBytesPerInterval; + libusb_free_ss_endpoint_companion_descriptor(ss_ep_cmp); + } + } - r = val & 0x07ff; - if (ep_type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS - || ep_type == LIBUSB_TRANSFER_TYPE_INTERRUPT) - r *= (1 + ((val >> 11) & 3)); + /* If the device isn't a SuperSpeed device or retrieving the SS endpoint didn't worked. */ + if (speed != LIBUSB_SPEED_SUPER || r < 0) { + val = ep->wMaxPacketSize; + ep_type = (enum libusb_transfer_type) (ep->bmAttributes & 0x3); + + r = val & 0x07ff; + if (ep_type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS + || ep_type == LIBUSB_TRANSFER_TYPE_INTERRUPT) + r *= (1 + ((val >> 11) & 3)); + } out: libusb_free_config_descriptor(config); @@ -1181,8 +1180,8 @@ void API_EXPORTED libusb_unref_device(libusb_device *dev) libusb_unref_device(dev->parent_dev); - if (usbi_backend->destroy_device) - usbi_backend->destroy_device(dev); + if (usbi_backend.destroy_device) + usbi_backend.destroy_device(dev); if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { /* backend does not support hotplug */ @@ -1232,6 +1231,78 @@ int usbi_clear_event(struct libusb_context *ctx) return 0; } +/** \ingroup libusb_dev + * Wrap a platform-specific system device handle and obtain a libusb device + * handle for the underlying device. The handle allows you to use libusb to + * perform I/O on the device in question. + * + * On Linux, the system device handle must be a valid file descriptor opened + * on the device node. + * + * The system device handle must remain open until libusb_close() is called. + * The system device handle will not be closed by libusb_close(). + * + * Internally, this function creates a temporary device and makes it + * available to you through libusb_get_device(). This device is destroyed + * during libusb_close(). The device shall not be opened through libusb_open(). + * + * This is a non-blocking function; no requests are sent over the bus. + * + * \param ctx the context to operate on, or NULL for the default context + * \param sys_dev the platform-specific system device handle + * \param dev_handle output location for the returned device handle pointer. Only + * populated when the return code is 0. + * \returns 0 on success + * \returns LIBUSB_ERROR_NO_MEM on memory allocation failure + * \returns LIBUSB_ERROR_ACCESS if the user has insufficient permissions + * \returns LIBUSB_ERROR_NOT_SUPPORTED if the operation is not supported on this + * platform + * \returns another LIBUSB_ERROR code on other failure + */ +int API_EXPORTED libusb_wrap_sys_device(libusb_context *ctx, intptr_t sys_dev, + libusb_device_handle **dev_handle) +{ + struct libusb_device_handle *_dev_handle; + size_t priv_size = usbi_backend.device_handle_priv_size; + int r; + usbi_dbg("wrap_sys_device %p", (void *)sys_dev); + + USBI_GET_CONTEXT(ctx); + + if (!usbi_backend.wrap_sys_device) + return LIBUSB_ERROR_NOT_SUPPORTED; + + _dev_handle = malloc(sizeof(*_dev_handle) + priv_size); + if (!_dev_handle) + return LIBUSB_ERROR_NO_MEM; + + r = usbi_mutex_init(&_dev_handle->lock); + if (r) { + free(_dev_handle); + return LIBUSB_ERROR_OTHER; + } + + _dev_handle->dev = NULL; + _dev_handle->auto_detach_kernel_driver = 0; + _dev_handle->claimed_interfaces = 0; + memset(&_dev_handle->os_priv, 0, priv_size); + + r = usbi_backend.wrap_sys_device(ctx, _dev_handle, sys_dev); + if (r < 0) { + usbi_dbg("wrap_sys_device %p returns %d", (void *)sys_dev, r); + usbi_mutex_destroy(&_dev_handle->lock); + free(_dev_handle); + return r; + } + + usbi_mutex_lock(&ctx->open_devs_lock); + list_add(&_dev_handle->list, &ctx->open_devs); + usbi_mutex_unlock(&ctx->open_devs_lock); + *dev_handle = _dev_handle; + + return 0; +} + /** \ingroup libusb_dev * Open a device and obtain a device handle. A handle allows you to perform * I/O on the device in question. @@ -1256,7 +1327,7 @@ int API_EXPORTED libusb_open(libusb_device *dev, { struct libusb_context *ctx = DEVICE_CTX(dev); struct libusb_device_handle *_dev_handle; - size_t priv_size = usbi_backend->device_handle_priv_size; + size_t priv_size = usbi_backend.device_handle_priv_size; int r; usbi_dbg("open %d.%d", dev->bus_number, dev->device_address); @@ -1279,7 +1350,7 @@ int API_EXPORTED libusb_open(libusb_device *dev, _dev_handle->claimed_interfaces = 0; memset(&_dev_handle->os_priv, 0, priv_size); - r = usbi_backend->open(_dev_handle); + r = usbi_backend.open(_dev_handle); if (r < 0) { usbi_dbg("open %d.%d returns %d", dev->bus_number, dev->device_address, r); libusb_unref_device(dev); @@ -1396,7 +1467,7 @@ static void do_close(struct libusb_context *ctx, list_del(&dev_handle->list); usbi_mutex_unlock(&ctx->open_devs_lock); - usbi_backend->close(dev_handle); + usbi_backend.close(dev_handle); libusb_unref_device(dev_handle->dev); usbi_mutex_destroy(&dev_handle->lock); free(dev_handle); @@ -1505,8 +1576,8 @@ int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev_handle, int r = LIBUSB_ERROR_NOT_SUPPORTED; usbi_dbg(""); - if (usbi_backend->get_configuration) - r = usbi_backend->get_configuration(dev_handle, config); + if (usbi_backend.get_configuration) + r = usbi_backend.get_configuration(dev_handle, config); if (r == LIBUSB_ERROR_NOT_SUPPORTED) { uint8_t tmp = 0; @@ -1581,7 +1652,7 @@ int API_EXPORTED libusb_set_configuration(libusb_device_handle *dev_handle, int configuration) { usbi_dbg("configuration %d", configuration); - return usbi_backend->set_configuration(dev_handle, configuration); + return usbi_backend.set_configuration(dev_handle, configuration); } /** \ingroup libusb_dev @@ -1625,12 +1696,12 @@ int API_EXPORTED libusb_claim_interface(libusb_device_handle *dev_handle, return LIBUSB_ERROR_NO_DEVICE; usbi_mutex_lock(&dev_handle->lock); - if (dev_handle->claimed_interfaces & (1 << interface_number)) + if (dev_handle->claimed_interfaces & (1U << interface_number)) goto out; - r = usbi_backend->claim_interface(dev_handle, interface_number); + r = usbi_backend.claim_interface(dev_handle, interface_number); if (r == 0) - dev_handle->claimed_interfaces |= 1 << interface_number; + dev_handle->claimed_interfaces |= 1U << interface_number; out: usbi_mutex_unlock(&dev_handle->lock); @@ -1666,14 +1737,14 @@ int API_EXPORTED libusb_release_interface(libusb_device_handle *dev_handle, return LIBUSB_ERROR_INVALID_PARAM; usbi_mutex_lock(&dev_handle->lock); - if (!(dev_handle->claimed_interfaces & (1 << interface_number))) { + if (!(dev_handle->claimed_interfaces & (1U << interface_number))) { r = LIBUSB_ERROR_NOT_FOUND; goto out; } - r = usbi_backend->release_interface(dev_handle, interface_number); + r = usbi_backend.release_interface(dev_handle, interface_number); if (r == 0) - dev_handle->claimed_interfaces &= ~(1 << interface_number); + dev_handle->claimed_interfaces &= ~(1U << interface_number); out: usbi_mutex_unlock(&dev_handle->lock); @@ -1715,13 +1786,13 @@ int API_EXPORTED libusb_set_interface_alt_setting(libusb_device_handle *dev_hand return LIBUSB_ERROR_NO_DEVICE; } - if (!(dev_handle->claimed_interfaces & (1 << interface_number))) { + if (!(dev_handle->claimed_interfaces & (1U << interface_number))) { usbi_mutex_unlock(&dev_handle->lock); return LIBUSB_ERROR_NOT_FOUND; } usbi_mutex_unlock(&dev_handle->lock); - return usbi_backend->set_interface_altsetting(dev_handle, interface_number, + return usbi_backend.set_interface_altsetting(dev_handle, interface_number, alternate_setting); } @@ -1748,7 +1819,7 @@ int API_EXPORTED libusb_clear_halt(libusb_device_handle *dev_handle, if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; - return usbi_backend->clear_halt(dev_handle, endpoint); + return usbi_backend.clear_halt(dev_handle, endpoint); } /** \ingroup libusb_dev @@ -1776,7 +1847,7 @@ int API_EXPORTED libusb_reset_device(libusb_device_handle *dev_handle) if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; - return usbi_backend->reset_device(dev_handle); + return usbi_backend.reset_device(dev_handle); } /** \ingroup libusb_asyncio @@ -1808,8 +1879,8 @@ int API_EXPORTED libusb_alloc_streams(libusb_device_handle *dev_handle, if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; - if (usbi_backend->alloc_streams) - return usbi_backend->alloc_streams(dev_handle, num_streams, endpoints, + if (usbi_backend.alloc_streams) + return usbi_backend.alloc_streams(dev_handle, num_streams, endpoints, num_endpoints); else return LIBUSB_ERROR_NOT_SUPPORTED; @@ -1835,8 +1906,8 @@ int API_EXPORTED libusb_free_streams(libusb_device_handle *dev_handle, if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; - if (usbi_backend->free_streams) - return usbi_backend->free_streams(dev_handle, endpoints, + if (usbi_backend.free_streams) + return usbi_backend.free_streams(dev_handle, endpoints, num_endpoints); else return LIBUSB_ERROR_NOT_SUPPORTED; @@ -1873,8 +1944,8 @@ unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handl if (!dev_handle->dev->attached) return NULL; - if (usbi_backend->dev_mem_alloc) - return usbi_backend->dev_mem_alloc(dev_handle, length); + if (usbi_backend.dev_mem_alloc) + return usbi_backend.dev_mem_alloc(dev_handle, length); else return NULL; } @@ -1890,8 +1961,8 @@ unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handl int API_EXPORTED libusb_dev_mem_free(libusb_device_handle *dev_handle, unsigned char *buffer, size_t length) { - if (usbi_backend->dev_mem_free) - return usbi_backend->dev_mem_free(dev_handle, buffer, length); + if (usbi_backend.dev_mem_free) + return usbi_backend.dev_mem_free(dev_handle, buffer, length); else return LIBUSB_ERROR_NOT_SUPPORTED; } @@ -1921,8 +1992,8 @@ int API_EXPORTED libusb_kernel_driver_active(libusb_device_handle *dev_handle, if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; - if (usbi_backend->kernel_driver_active) - return usbi_backend->kernel_driver_active(dev_handle, interface_number); + if (usbi_backend.kernel_driver_active) + return usbi_backend.kernel_driver_active(dev_handle, interface_number); else return LIBUSB_ERROR_NOT_SUPPORTED; } @@ -1956,8 +2027,8 @@ int API_EXPORTED libusb_detach_kernel_driver(libusb_device_handle *dev_handle, if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; - if (usbi_backend->detach_kernel_driver) - return usbi_backend->detach_kernel_driver(dev_handle, interface_number); + if (usbi_backend.detach_kernel_driver) + return usbi_backend.detach_kernel_driver(dev_handle, interface_number); else return LIBUSB_ERROR_NOT_SUPPORTED; } @@ -1990,8 +2061,8 @@ int API_EXPORTED libusb_attach_kernel_driver(libusb_device_handle *dev_handle, if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; - if (usbi_backend->attach_kernel_driver) - return usbi_backend->attach_kernel_driver(dev_handle, interface_number); + if (usbi_backend.attach_kernel_driver) + return usbi_backend.attach_kernel_driver(dev_handle, interface_number); else return LIBUSB_ERROR_NOT_SUPPORTED; } @@ -2021,7 +2092,7 @@ int API_EXPORTED libusb_attach_kernel_driver(libusb_device_handle *dev_handle, int API_EXPORTED libusb_set_auto_detach_kernel_driver( libusb_device_handle *dev_handle, int enable) { - if (!(usbi_backend->caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER)) + if (!(usbi_backend.caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER)) return LIBUSB_ERROR_NOT_SUPPORTED; dev_handle->auto_detach_kernel_driver = enable; @@ -2029,37 +2100,143 @@ int API_EXPORTED libusb_set_auto_detach_kernel_driver( } /** \ingroup libusb_lib - * Set log message verbosity. - * - * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever - * printed. If you choose to increase the message verbosity level, ensure - * that your application does not close the stdout/stderr file descriptors. - * - * You are advised to use level LIBUSB_LOG_LEVEL_WARNING. libusb is conservative - * with its message logging and most of the time, will only log messages that - * explain error conditions and other oddities. This will help you debug - * your software. - * - * If the LIBUSB_DEBUG environment variable was set when libusb was - * initialized, this function does nothing: the message verbosity is fixed - * to the value in the environment variable. - * - * If libusb was compiled without any message logging, this function does - * nothing: you'll never get any messages. - * - * If libusb was compiled with verbose debug message logging, this function - * does nothing: you'll always get messages from all levels. - * - * \param ctx the context to operate on, or NULL for the default context - * \param level debug level to set + * \deprecated Use libusb_set_option() instead using the + * \ref LIBUSB_OPTION_LOG_LEVEL option. */ void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level) { +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) USBI_GET_CONTEXT(ctx); - if (!ctx->debug_fixed) - ctx->debug = level; + if (!ctx->debug_fixed) { + level = CLAMP(level, LIBUSB_LOG_LEVEL_NONE, LIBUSB_LOG_LEVEL_DEBUG); + ctx->debug = (enum libusb_log_level)level; + } +#else + UNUSED(ctx); + UNUSED(level); +#endif } +/** \ingroup libusb_lib + * Set log handler. + * + * libusb will redirect its log messages to the provided callback function. + * libusb supports redirection of per context and global log messages. + * Log messages sent to the context will be sent to the global log handler too. + * + * If libusb is compiled without message logging or USE_SYSTEM_LOGGING_FACILITY + * is defined then global callback function will never be called. + * If ENABLE_DEBUG_LOGGING is defined then per context callback function will + * never be called. + * + * \param ctx context on which to assign log handler, or NULL for the default + * context. Parameter ignored if only LIBUSB_LOG_CB_GLOBAL mode is requested. + * \param cb pointer to the callback function, or NULL to stop log + * messages redirection + * \param mode mode of callback function operation. Several modes can be + * selected for a single callback function, see \ref libusb_log_cb_mode for + * a description. + * \see libusb_log_cb, libusb_log_cb_mode + */ +void API_EXPORTED libusb_set_log_cb(libusb_context *ctx, libusb_log_cb cb, + int mode) +{ +#if !defined(USE_SYSTEM_LOGGING_FACILITY) + if (mode & LIBUSB_LOG_CB_GLOBAL) { + log_handler = cb; + } +#endif +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) + if (mode & LIBUSB_LOG_CB_CONTEXT) { + USBI_GET_CONTEXT(ctx); + ctx->log_handler = cb; + } +#else + UNUSED(ctx); +#if defined(USE_SYSTEM_LOGGING_FACILITY) + UNUSED(cb); + UNUSED(mode); +#endif +#endif +} + +/** \ingroup libusb_lib + * Set an option in the library. + * + * Use this function to configure a specific option within the library. + * + * Some options require one or more arguments to be provided. Consult each + * option's documentation for specific requirements. + * + * Since version 1.0.22, \ref LIBUSB_API_VERSION >= 0x01000106 + * + * \param ctx context on which to operate + * \param option which option to set + * \param ... any required arguments for the specified option + * + * \returns LIBUSB_SUCCESS on success + * \returns LIBUSB_ERROR_INVALID_PARAM if the option or arguments are invalid + * \returns LIBUSB_ERROR_NOT_SUPPORTED if the option is valid but not supported + * on this platform + */ +int API_EXPORTED libusb_set_option(libusb_context *ctx, + enum libusb_option option, ...) +{ + int arg, r = LIBUSB_SUCCESS; + va_list ap; + + USBI_GET_CONTEXT(ctx); + + va_start(ap, option); + switch (option) { + case LIBUSB_OPTION_LOG_LEVEL: + arg = va_arg(ap, int); + if (arg < LIBUSB_LOG_LEVEL_NONE || arg > LIBUSB_LOG_LEVEL_DEBUG) { + r = LIBUSB_ERROR_INVALID_PARAM; + break; + } +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) + if (!ctx->debug_fixed) + ctx->debug = (enum libusb_log_level)arg; +#endif + break; + + /* Handle all backend-specific options here */ + case LIBUSB_OPTION_USE_USBDK: + if (usbi_backend.set_option) + r = usbi_backend.set_option(ctx, option, ap); + else + r = LIBUSB_ERROR_NOT_SUPPORTED; + break; + + default: + r = LIBUSB_ERROR_INVALID_PARAM; + } + va_end(ap); + + return r; +} + +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) +/* returns the log level as defined in the LIBUSB_DEBUG environment variable. + * if LIBUSB_DEBUG is not present or not a number, returns LIBUSB_LOG_LEVEL_NONE. + * value is clamped to ensure it is within the valid range of possibilities. + */ +static enum libusb_log_level get_env_debug_level(void) +{ + const char *dbg = getenv("LIBUSB_DEBUG"); + enum libusb_log_level level; + if (dbg) { + int dbg_level = atoi(dbg); + dbg_level = CLAMP(dbg_level, LIBUSB_LOG_LEVEL_NONE, LIBUSB_LOG_LEVEL_DEBUG); + level = (enum libusb_log_level)dbg_level; + } else { + level = LIBUSB_LOG_LEVEL_NONE; + } + return level; +} +#endif + /** \ingroup libusb_lib * Initialize libusb. This function must be called before calling any other * libusb function. @@ -2076,28 +2253,15 @@ void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level) int API_EXPORTED libusb_init(libusb_context **context) { struct libusb_device *dev, *next; - char *dbg = getenv("LIBUSB_DEBUG"); + size_t priv_size = usbi_backend.context_priv_size; struct libusb_context *ctx; static int first_init = 1; int r = 0; -#ifdef OS_WINDOWS - if (is_usbdk_driver_installed()) - { - usbi_backend = &usbdk_backend; - usbi_dbg("libusb will work with UsbDk backend"); - } - else - { - usbi_backend = &windows_backend; - usbi_dbg("libusb will work with windows_backend"); - } -#endif - usbi_mutex_static_lock(&default_context_lock); if (!timestamp_origin.tv_sec) { - usbi_gettimeofday(×tamp_origin, NULL); + usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, ×tamp_origin); } if (!context && usbi_default_context) { @@ -2107,22 +2271,18 @@ int API_EXPORTED libusb_init(libusb_context **context) return 0; } - ctx = calloc(1, sizeof(*ctx)); + ctx = calloc(1, sizeof(*ctx) + priv_size); if (!ctx) { r = LIBUSB_ERROR_NO_MEM; goto err_unlock; } -#ifdef ENABLE_DEBUG_LOGGING - ctx->debug = LIBUSB_LOG_LEVEL_DEBUG; +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) + ctx->debug = get_env_debug_level(); + if (ctx->debug != LIBUSB_LOG_LEVEL_NONE) + ctx->debug_fixed = 1; #endif - if (dbg) { - ctx->debug = atoi(dbg); - if (ctx->debug) - ctx->debug_fixed = 1; - } - /* default context should be initialized before calling usbi_dbg */ if (!usbi_default_context) { usbi_default_context = ctx; @@ -2139,6 +2299,7 @@ int API_EXPORTED libusb_init(libusb_context **context) list_init(&ctx->usb_devs); list_init(&ctx->open_devs); list_init(&ctx->hotplug_cbs); + ctx->next_hotplug_cb_handle = 1; usbi_mutex_static_lock(&active_contexts_lock); if (first_init) { @@ -2148,8 +2309,8 @@ int API_EXPORTED libusb_init(libusb_context **context) list_add (&ctx->list, &active_contexts_list); usbi_mutex_static_unlock(&active_contexts_lock); - if (usbi_backend->init) { - r = usbi_backend->init(ctx); + if (usbi_backend.init) { + r = usbi_backend.init(ctx); if (r) goto err_free_ctx; } @@ -2166,8 +2327,8 @@ int API_EXPORTED libusb_init(libusb_context **context) return 0; err_backend_exit: - if (usbi_backend->exit) - usbi_backend->exit(); + if (usbi_backend.exit) + usbi_backend.exit(ctx); err_free_ctx: if (ctx == usbi_default_context) { usbi_default_context = NULL; @@ -2204,6 +2365,7 @@ void API_EXPORTED libusb_exit(struct libusb_context *ctx) { struct libusb_device *dev, *next; struct timeval tv = { 0, 0 }; + int destroying_default_context = 0; usbi_dbg(""); USBI_GET_CONTEXT(ctx); @@ -2218,16 +2380,25 @@ void API_EXPORTED libusb_exit(struct libusb_context *ctx) return; } usbi_dbg("destroying default context"); - usbi_default_context = NULL; - } - usbi_mutex_static_unlock(&default_context_lock); + + /* + * Setting this flag without unlocking the default context, as + * we are actually destroying the default context. + * usbi_default_context is not set to NULL yet, as all activities + * would only stop after usbi_backend->exit() returns. + */ + destroying_default_context = 1; + } else { + // Unlock default context, as we're not modifying it. + usbi_mutex_static_unlock(&default_context_lock); + } usbi_mutex_static_lock(&active_contexts_lock); list_del (&ctx->list); usbi_mutex_static_unlock(&active_contexts_lock); if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { - usbi_hotplug_deregister_all(ctx); + usbi_hotplug_deregister(ctx, 1); /* * Ensure any pending unplug events are read from the hotplug @@ -2257,13 +2428,18 @@ void API_EXPORTED libusb_exit(struct libusb_context *ctx) usbi_warn(ctx, "application left some devices open"); usbi_io_exit(ctx); - if (usbi_backend->exit) - usbi_backend->exit(); + if (usbi_backend.exit) + usbi_backend.exit(ctx); usbi_mutex_destroy(&ctx->open_devs_lock); usbi_mutex_destroy(&ctx->usb_devs_lock); usbi_mutex_destroy(&ctx->hotplug_cbs_lock); free(ctx); + + if (destroying_default_context) { + usbi_default_context = NULL; + usbi_mutex_static_unlock(&default_context_lock); + } } /** \ingroup libusb_misc @@ -2280,111 +2456,109 @@ int API_EXPORTED libusb_has_capability(uint32_t capability) case LIBUSB_CAP_HAS_CAPABILITY: return 1; case LIBUSB_CAP_HAS_HOTPLUG: - return !(usbi_backend->get_device_list); + return !(usbi_backend.get_device_list); case LIBUSB_CAP_HAS_HID_ACCESS: - return (usbi_backend->caps & USBI_CAP_HAS_HID_ACCESS); + return (usbi_backend.caps & USBI_CAP_HAS_HID_ACCESS); case LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER: - return (usbi_backend->caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER); + return (usbi_backend.caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER); } return 0; } +#ifdef ENABLE_LOGGING + /* this is defined in libusbi.h if needed */ -#ifdef LIBUSB_GETTIMEOFDAY_WIN32 +#ifdef LIBUSB_PRINTF_WIN32 /* - * gettimeofday - * Implementation according to: - * The Open Group Base Specifications Issue 6 - * IEEE Std 1003.1, 2004 Edition + * Prior to VS2015, Microsoft did not provide the snprintf() function and + * provided a vsnprintf() that did not guarantee NULL-terminated output. + * Microsoft did provide a _snprintf() function, but again it did not + * guarantee NULL-terminated output. + * + * The below implementations guarantee NULL-terminated output and are + * C99 compliant. */ -/* - * THIS SOFTWARE IS NOT COPYRIGHTED - * - * This source code is offered for use in the public domain. You may - * use, modify or distribute it freely. - * - * This code is distributed in the hope that it will be useful but - * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY - * DISCLAIMED. This includes but is not limited to warranties of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Contributed by: - * Danny Smith - */ - -/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */ -#define _W32_FT_OFFSET (116444736000000000) - -int usbi_gettimeofday(struct timeval *tp, void *tzp) +int usbi_snprintf(char *str, size_t size, const char *format, ...) { - union { - unsigned __int64 ns100; /* Time since 1 Jan 1601, in 100ns units */ - FILETIME ft; - } _now; - UNUSED(tzp); + va_list ap; + int ret; - if(tp) { -#if defined(OS_WINCE) - SYSTEMTIME st; - GetSystemTime(&st); - SystemTimeToFileTime(&st, &_now.ft); -#else - GetSystemTimeAsFileTime (&_now.ft); -#endif - tp->tv_usec=(long)((_now.ns100 / 10) % 1000000 ); - tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000); - } - /* Always return 0 as per Open Group Base Specifications Issue 6. - Do not set errno on error. */ - return 0; + va_start(ap, format); + ret = usbi_vsnprintf(str, size, format, ap); + va_end(ap); + + return ret; } -#endif -static void usbi_log_str(struct libusb_context *ctx, - enum libusb_log_level level, const char * str) +int usbi_vsnprintf(char *str, size_t size, const char *format, va_list ap) +{ + int ret; + + ret = _vsnprintf(str, size, format, ap); + if (ret < 0 || ret == (int)size) { + /* Output is truncated, ensure buffer is NULL-terminated and + * determine how many characters would have been written. */ + str[size - 1] = '\0'; + if (ret < 0) + ret = _vsnprintf(NULL, 0, format, ap); + } + + return ret; +} +#endif /* LIBUSB_PRINTF_WIN32 */ + +static void usbi_log_str(enum libusb_log_level level, const char *str) { #if defined(USE_SYSTEM_LOGGING_FACILITY) #if defined(OS_WINDOWS) || defined(OS_WINCE) - /* Windows CE only supports the Unicode version of OutputDebugString. */ +#if !defined(UNICODE) + OutputDebugStringA(str); +#else WCHAR wbuf[USBI_MAX_LOG_LEN]; - MultiByteToWideChar(CP_UTF8, 0, str, -1, wbuf, sizeof(wbuf)); - OutputDebugStringW(wbuf); + if (MultiByteToWideChar(CP_UTF8, 0, str, -1, wbuf, sizeof(wbuf)) != 0) + OutputDebugStringW(wbuf); +#endif #elif defined(__ANDROID__) int priority = ANDROID_LOG_UNKNOWN; switch (level) { - case LIBUSB_LOG_LEVEL_INFO: priority = ANDROID_LOG_INFO; break; - case LIBUSB_LOG_LEVEL_WARNING: priority = ANDROID_LOG_WARN; break; + case LIBUSB_LOG_LEVEL_NONE: return; case LIBUSB_LOG_LEVEL_ERROR: priority = ANDROID_LOG_ERROR; break; + case LIBUSB_LOG_LEVEL_WARNING: priority = ANDROID_LOG_WARN; break; + case LIBUSB_LOG_LEVEL_INFO: priority = ANDROID_LOG_INFO; break; case LIBUSB_LOG_LEVEL_DEBUG: priority = ANDROID_LOG_DEBUG; break; } __android_log_write(priority, "libusb", str); #elif defined(HAVE_SYSLOG_FUNC) int syslog_level = LOG_INFO; switch (level) { - case LIBUSB_LOG_LEVEL_INFO: syslog_level = LOG_INFO; break; - case LIBUSB_LOG_LEVEL_WARNING: syslog_level = LOG_WARNING; break; + case LIBUSB_LOG_LEVEL_NONE: return; case LIBUSB_LOG_LEVEL_ERROR: syslog_level = LOG_ERR; break; + case LIBUSB_LOG_LEVEL_WARNING: syslog_level = LOG_WARNING; break; + case LIBUSB_LOG_LEVEL_INFO: syslog_level = LOG_INFO; break; case LIBUSB_LOG_LEVEL_DEBUG: syslog_level = LOG_DEBUG; break; } syslog(syslog_level, "%s", str); -#else /* All of gcc, Clang, XCode seem to use #warning */ +#else /* All of gcc, Clang, Xcode seem to use #warning */ #warning System logging is not supported on this platform. Logging to stderr will be used instead. fputs(str, stderr); #endif #else - fputs(str, stderr); + /* Global log handler */ + if (log_handler != NULL) + log_handler(NULL, level, str); + else + fputs(str, stderr); #endif /* USE_SYSTEM_LOGGING_FACILITY */ - UNUSED(ctx); UNUSED(level); } void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, const char *function, const char *format, va_list args) { - const char *prefix = ""; + const char *prefix; char buf[USBI_MAX_LOG_LEN]; - struct timeval now; + struct timespec now; int global_debug, header_len, text_len; static int has_debug_header_been_displayed = 0; @@ -2392,18 +2566,15 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, global_debug = 1; UNUSED(ctx); #else - int ctx_level = 0; + enum libusb_log_level ctx_level = LIBUSB_LOG_LEVEL_NONE; USBI_GET_CONTEXT(ctx); - if (ctx) { + if (ctx) ctx_level = ctx->debug; - } else { - char *dbg = getenv("LIBUSB_DEBUG"); - if (dbg) - ctx_level = atoi(dbg); - } - global_debug = (ctx_level == LIBUSB_LOG_LEVEL_DEBUG); - if (!ctx_level) + else + ctx_level = get_env_debug_level(); + + if (ctx_level == LIBUSB_LOG_LEVEL_NONE) return; if (level == LIBUSB_LOG_LEVEL_WARNING && ctx_level < LIBUSB_LOG_LEVEL_WARNING) return; @@ -2411,36 +2582,38 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, return; if (level == LIBUSB_LOG_LEVEL_DEBUG && ctx_level < LIBUSB_LOG_LEVEL_DEBUG) return; + + global_debug = (ctx_level == LIBUSB_LOG_LEVEL_DEBUG); #endif - usbi_gettimeofday(&now, NULL); + usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, &now); if ((global_debug) && (!has_debug_header_been_displayed)) { has_debug_header_been_displayed = 1; - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_DEBUG, "[timestamp] [threadID] facility level [function call] " USBI_LOG_LINE_END); - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_DEBUG, "--------------------------------------------------------------------------------" USBI_LOG_LINE_END); + usbi_log_str(LIBUSB_LOG_LEVEL_DEBUG, "[timestamp] [threadID] facility level [function call] " USBI_LOG_LINE_END); + usbi_log_str(LIBUSB_LOG_LEVEL_DEBUG, "--------------------------------------------------------------------------------" USBI_LOG_LINE_END); } - if (now.tv_usec < timestamp_origin.tv_usec) { + if (now.tv_nsec < timestamp_origin.tv_nsec) { now.tv_sec--; - now.tv_usec += 1000000; + now.tv_nsec += 1000000000L; } now.tv_sec -= timestamp_origin.tv_sec; - now.tv_usec -= timestamp_origin.tv_usec; + now.tv_nsec -= timestamp_origin.tv_nsec; switch (level) { - case LIBUSB_LOG_LEVEL_INFO: - prefix = "info"; + case LIBUSB_LOG_LEVEL_NONE: + return; + case LIBUSB_LOG_LEVEL_ERROR: + prefix = "error"; break; case LIBUSB_LOG_LEVEL_WARNING: prefix = "warning"; break; - case LIBUSB_LOG_LEVEL_ERROR: - prefix = "error"; + case LIBUSB_LOG_LEVEL_INFO: + prefix = "info"; break; case LIBUSB_LOG_LEVEL_DEBUG: prefix = "debug"; break; - case LIBUSB_LOG_LEVEL_NONE: - return; default: prefix = "unknown"; break; @@ -2448,8 +2621,8 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, if (global_debug) { header_len = snprintf(buf, sizeof(buf), - "[%2d.%06d] [%08x] libusb: %s [%s] ", - (int)now.tv_sec, (int)now.tv_usec, usbi_get_tid(), prefix, function); + "[%2ld.%06ld] [%08x] libusb: %s [%s] ", + (long)now.tv_sec, (long)(now.tv_nsec / 1000L), usbi_get_tid(), prefix, function); } else { header_len = snprintf(buf, sizeof(buf), "libusb: %s [%s] ", prefix, function); @@ -2462,20 +2635,26 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, } /* Make sure buffer is NUL terminated */ buf[header_len] = '\0'; - text_len = vsnprintf(buf + header_len, sizeof(buf) - header_len, + text_len = vsnprintf(buf + header_len, sizeof(buf) - (size_t)header_len, format, args); if (text_len < 0 || text_len + header_len >= (int)sizeof(buf)) { /* Truncated log output. On some platforms a -1 return value means * that the output was truncated. */ - text_len = sizeof(buf) - header_len; + text_len = (int)sizeof(buf) - header_len; } - if (header_len + text_len + sizeof(USBI_LOG_LINE_END) >= sizeof(buf)) { + if (header_len + text_len + (int)sizeof(USBI_LOG_LINE_END) >= (int)sizeof(buf)) { /* Need to truncate the text slightly to fit on the terminator. */ - text_len -= (header_len + text_len + sizeof(USBI_LOG_LINE_END)) - sizeof(buf); + text_len -= (header_len + text_len + (int)sizeof(USBI_LOG_LINE_END)) - (int)sizeof(buf); } strcpy(buf + header_len + text_len, USBI_LOG_LINE_END); - usbi_log_str(ctx, level, buf); + usbi_log_str(level, buf); + + /* Per context log handler */ +#ifndef ENABLE_DEBUG_LOGGING + if (ctx && ctx->log_handler) + ctx->log_handler(ctx, level, buf); +#endif } void usbi_log(struct libusb_context *ctx, enum libusb_log_level level, @@ -2488,6 +2667,8 @@ void usbi_log(struct libusb_context *ctx, enum libusb_log_level level, va_end (args); } +#endif /* ENABLE_LOGGING */ + /** \ingroup libusb_misc * Returns a constant NULL-terminated string with the ASCII name of a libusb * error or transfer status code. The caller must not free() the returned diff --git a/Externals/libusb/libusb/descriptor.c b/Externals/libusb/libusb/descriptor.c index 4c9435fffe..53905e6eb7 100644 --- a/Externals/libusb/libusb/descriptor.c +++ b/Externals/libusb/libusb/descriptor.c @@ -62,7 +62,7 @@ int usbi_parse_descriptor(const unsigned char *source, const char *descriptor, if (host_endian) { memcpy(dp, sp, 2); } else { - w = (sp[1] << 8) | sp[0]; + w = (uint16_t)((sp[1] << 8) | sp[0]); *((uint16_t *)dp) = w; } sp += 2; @@ -74,8 +74,8 @@ int usbi_parse_descriptor(const unsigned char *source, const char *descriptor, if (host_endian) { memcpy(dp, sp, 4); } else { - d = (sp[3] << 24) | (sp[2] << 16) | - (sp[1] << 8) | sp[0]; + d = (uint32_t)((sp[3] << 24) | (sp[2] << 16) | + (sp[1] << 8) | sp[0]); *((uint32_t *)dp) = d; } sp += 4; @@ -168,13 +168,13 @@ static int parse_endpoint(struct libusb_context *ctx, /* Copy any unknown descriptors into a storage area for drivers */ /* to later parse */ len = (int)(buffer - begin); - if (!len) { + if (len <= 0) { endpoint->extra = NULL; endpoint->extra_length = 0; return parsed; } - extra = malloc(len); + extra = malloc((size_t)len); endpoint->extra = extra; if (!extra) { endpoint->extra_length = 0; @@ -230,7 +230,7 @@ static int parse_interface(libusb_context *ctx, (struct libusb_interface_descriptor *) usb_interface->altsetting; altsetting = usbi_reallocf(altsetting, sizeof(struct libusb_interface_descriptor) * - (usb_interface->num_altsetting + 1)); + ((size_t)usb_interface->num_altsetting + 1)); if (!altsetting) { r = LIBUSB_ERROR_NO_MEM; goto err; @@ -307,8 +307,8 @@ static int parse_interface(libusb_context *ctx, /* Copy any unknown descriptors into a storage area for */ /* drivers to later parse */ len = (int)(buffer - begin); - if (len) { - ifp->extra = malloc(len); + if (len > 0) { + ifp->extra = malloc((size_t)len); if (!ifp->extra) { r = LIBUSB_ERROR_NO_MEM; goto err; @@ -333,7 +333,7 @@ static int parse_interface(libusb_context *ctx, goto err; if (r == 0) { ifp->bNumEndpoints = (uint8_t)i; - break;; + break; } buffer += r; @@ -453,10 +453,10 @@ static int parse_configuration(struct libusb_context *ctx, /* Copy any unknown descriptors into a storage area for */ /* drivers to later parse */ len = (int)(buffer - begin); - if (len) { + if (len > 0) { /* FIXME: We should realloc and append here */ if (!config->extra_length) { - config->extra = malloc(len); + config->extra = malloc((size_t)len); if (!config->extra) { r = LIBUSB_ERROR_NO_MEM; goto err; @@ -492,7 +492,7 @@ static int raw_desc_to_config(struct libusb_context *ctx, { struct libusb_config_descriptor *_config = malloc(sizeof(*_config)); int r; - + if (!_config) return LIBUSB_ERROR_NO_MEM; @@ -504,7 +504,7 @@ static int raw_desc_to_config(struct libusb_context *ctx, } else if (r > 0) { usbi_warn(ctx, "still %d bytes of descriptor data left", r); } - + *config = _config; return LIBUSB_SUCCESS; } @@ -513,7 +513,7 @@ int usbi_device_cache_descriptor(libusb_device *dev) { int r, host_endian = 0; - r = usbi_backend->get_device_descriptor(dev, (unsigned char *) &dev->device_descriptor, + r = usbi_backend.get_device_descriptor(dev, (unsigned char *) &dev->device_descriptor, &host_endian); if (r < 0) return r; @@ -572,7 +572,7 @@ int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev, int host_endian = 0; int r; - r = usbi_backend->get_active_config_descriptor(dev, tmp, + r = usbi_backend.get_active_config_descriptor(dev, tmp, LIBUSB_DT_CONFIG_SIZE, &host_endian); if (r < 0) return r; @@ -587,7 +587,7 @@ int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev, if (!buf) return LIBUSB_ERROR_NO_MEM; - r = usbi_backend->get_active_config_descriptor(dev, buf, + r = usbi_backend.get_active_config_descriptor(dev, buf, _config.wTotalLength, &host_endian); if (r >= 0) r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config); @@ -625,7 +625,7 @@ int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev, if (config_index >= dev->num_configurations) return LIBUSB_ERROR_NOT_FOUND; - r = usbi_backend->get_config_descriptor(dev, config_index, tmp, + r = usbi_backend.get_config_descriptor(dev, config_index, tmp, LIBUSB_DT_CONFIG_SIZE, &host_endian); if (r < 0) return r; @@ -640,7 +640,7 @@ int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev, if (!buf) return LIBUSB_ERROR_NO_MEM; - r = usbi_backend->get_config_descriptor(dev, config_index, buf, + r = usbi_backend.get_config_descriptor(dev, config_index, buf, _config.wTotalLength, &host_endian); if (r >= 0) r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config); @@ -663,7 +663,7 @@ int usbi_get_config_index_by_value(struct libusb_device *dev, for (i = 0; i < dev->num_configurations; i++) { unsigned char tmp[6]; int host_endian; - int r = usbi_backend->get_config_descriptor(dev, i, tmp, sizeof(tmp), + int r = usbi_backend.get_config_descriptor(dev, i, tmp, sizeof(tmp), &host_endian); if (r < 0) { *idx = -1; @@ -702,8 +702,8 @@ int API_EXPORTED libusb_get_config_descriptor_by_value(libusb_device *dev, int r, idx, host_endian; unsigned char *buf = NULL; - if (usbi_backend->get_config_descriptor_by_value) { - r = usbi_backend->get_config_descriptor_by_value(dev, + if (usbi_backend.get_config_descriptor_by_value) { + r = usbi_backend.get_config_descriptor_by_value(dev, bConfigurationValue, &buf, &host_endian); if (r < 0) return r; @@ -1060,7 +1060,8 @@ int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor( * It is safe to call this function with a NULL ss_usb_device_cap * parameter, in which case the function simply returns. * - * \param ss_usb_device_cap the USB 2.0 Extension descriptor to free + * \param ss_usb_device_cap the SuperSpeed USB Device Capability descriptor + * to free */ void API_EXPORTED libusb_free_ss_usb_device_capability_descriptor( struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap) @@ -1117,7 +1118,7 @@ int API_EXPORTED libusb_get_container_id_descriptor(struct libusb_context *ctx, * It is safe to call this function with a NULL container_id parameter, * in which case the function simply returns. * - * \param container_id the USB 2.0 Extension descriptor to free + * \param container_id the Container ID descriptor to free */ void API_EXPORTED libusb_free_container_id_descriptor( struct libusb_container_id_descriptor *container_id) @@ -1163,7 +1164,7 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_ha if (r < 4) return LIBUSB_ERROR_IO; - langid = tbuf[2] | (tbuf[3] << 8); + langid = (uint16_t)(tbuf[2] | (tbuf[3] << 8)); r = libusb_get_string_descriptor(dev_handle, desc_index, langid, tbuf, sizeof(tbuf)); @@ -1176,7 +1177,8 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_ha if (tbuf[0] > r) return LIBUSB_ERROR_IO; - for (di = 0, si = 2; si < tbuf[0]; si += 2) { + di = 0; + for (si = 2; si < tbuf[0]; si += 2) { if (di >= (length - 1)) break; diff --git a/Externals/libusb/libusb/hotplug.c b/Externals/libusb/libusb/hotplug.c index bbfd6e79a1..a4320bc42e 100644 --- a/Externals/libusb/libusb/hotplug.c +++ b/Externals/libusb/libusb/hotplug.c @@ -154,36 +154,30 @@ int main (void) { \endcode */ -static int usbi_hotplug_match_cb (struct libusb_context *ctx, +static int usbi_hotplug_match_cb(struct libusb_context *ctx, struct libusb_device *dev, libusb_hotplug_event event, struct libusb_hotplug_callback *hotplug_cb) { - /* Handle lazy deregistration of callback */ - if (hotplug_cb->needs_free) { - /* Free callback */ - return 1; - } - - if (!(hotplug_cb->events & event)) { + if (!(hotplug_cb->flags & event)) { return 0; } - if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->vendor_id && + if ((hotplug_cb->flags & USBI_HOTPLUG_VENDOR_ID_VALID) && hotplug_cb->vendor_id != dev->device_descriptor.idVendor) { return 0; } - if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->product_id && + if ((hotplug_cb->flags & USBI_HOTPLUG_PRODUCT_ID_VALID) && hotplug_cb->product_id != dev->device_descriptor.idProduct) { return 0; } - if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->dev_class && + if ((hotplug_cb->flags & USBI_HOTPLUG_DEV_CLASS_VALID) && hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) { return 0; } - return hotplug_cb->cb (ctx, dev, event, hotplug_cb->user_data); + return hotplug_cb->cb(ctx, dev, event, hotplug_cb->user_data); } void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, @@ -195,8 +189,13 @@ void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, usbi_mutex_lock(&ctx->hotplug_cbs_lock); list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) { + if (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE) { + /* process deregistration in usbi_hotplug_deregister() */ + continue; + } + usbi_mutex_unlock(&ctx->hotplug_cbs_lock); - ret = usbi_hotplug_match_cb (ctx, dev, event, hotplug_cb); + ret = usbi_hotplug_match_cb(ctx, dev, event, hotplug_cb); usbi_mutex_lock(&ctx->hotplug_cbs_lock); if (ret) { @@ -206,15 +205,13 @@ void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, } usbi_mutex_unlock(&ctx->hotplug_cbs_lock); - - /* the backend is expected to call the callback for each active transfer */ } void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev, libusb_hotplug_event event) { int pending_events; - libusb_hotplug_message *message = calloc(1, sizeof(*message)); + struct libusb_hotplug_message *message = calloc(1, sizeof(*message)); if (!message) { usbi_err(ctx, "error allocating hotplug message"); @@ -240,59 +237,70 @@ int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx, libusb_hotplug_callback_fn cb_fn, void *user_data, libusb_hotplug_callback_handle *callback_handle) { - libusb_hotplug_callback *new_callback; - static int handle_id = 1; - - /* check for hotplug support */ - if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { - return LIBUSB_ERROR_NOT_SUPPORTED; - } + struct libusb_hotplug_callback *new_callback; /* check for sane values */ - if ((LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) || + if ((!events || (~(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) & events)) || + (flags && (~LIBUSB_HOTPLUG_ENUMERATE & flags)) || + (LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) || (LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) || (LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) || !cb_fn) { return LIBUSB_ERROR_INVALID_PARAM; } + /* check for hotplug support */ + if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { + return LIBUSB_ERROR_NOT_SUPPORTED; + } + USBI_GET_CONTEXT(ctx); - new_callback = (libusb_hotplug_callback *)calloc(1, sizeof (*new_callback)); + new_callback = calloc(1, sizeof(*new_callback)); if (!new_callback) { return LIBUSB_ERROR_NO_MEM; } - new_callback->ctx = ctx; - new_callback->vendor_id = vendor_id; - new_callback->product_id = product_id; - new_callback->dev_class = dev_class; - new_callback->flags = flags; - new_callback->events = events; + new_callback->flags = (uint8_t)events; + if (LIBUSB_HOTPLUG_MATCH_ANY != vendor_id) { + new_callback->flags |= USBI_HOTPLUG_VENDOR_ID_VALID; + new_callback->vendor_id = (uint16_t)vendor_id; + } + if (LIBUSB_HOTPLUG_MATCH_ANY != product_id) { + new_callback->flags |= USBI_HOTPLUG_PRODUCT_ID_VALID; + new_callback->product_id = (uint16_t)product_id; + } + if (LIBUSB_HOTPLUG_MATCH_ANY != dev_class) { + new_callback->flags |= USBI_HOTPLUG_DEV_CLASS_VALID; + new_callback->dev_class = (uint8_t)dev_class; + } new_callback->cb = cb_fn; new_callback->user_data = user_data; - new_callback->needs_free = 0; usbi_mutex_lock(&ctx->hotplug_cbs_lock); - /* protect the handle by the context hotplug lock. it doesn't matter if the same handle - * is used for different contexts only that the handle is unique for this context */ - new_callback->handle = handle_id++; + /* protect the handle by the context hotplug lock */ + new_callback->handle = ctx->next_hotplug_cb_handle++; + + /* handle the unlikely case of overflow */ + if (ctx->next_hotplug_cb_handle < 0) + ctx->next_hotplug_cb_handle = 1; list_add(&new_callback->list, &ctx->hotplug_cbs); usbi_mutex_unlock(&ctx->hotplug_cbs_lock); + usbi_dbg("new hotplug cb %p with handle %d", new_callback, new_callback->handle); - if (flags & LIBUSB_HOTPLUG_ENUMERATE) { - int i, len; + if ((flags & LIBUSB_HOTPLUG_ENUMERATE) && (events & LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)) { + ssize_t i, len; struct libusb_device **devs; - len = (int) libusb_get_device_list(ctx, &devs); + len = libusb_get_device_list(ctx, &devs); if (len < 0) { libusb_hotplug_deregister_callback(ctx, new_callback->handle); - return len; + return (int)len; } for (i = 0; i < len; i++) { @@ -311,10 +319,11 @@ int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx, return LIBUSB_SUCCESS; } -void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx, +void API_EXPORTED libusb_hotplug_deregister_callback(struct libusb_context *ctx, libusb_hotplug_callback_handle callback_handle) { struct libusb_hotplug_callback *hotplug_cb; + int deregistered = 0; /* check for hotplug support */ if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { @@ -323,28 +332,42 @@ void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx USBI_GET_CONTEXT(ctx); + usbi_dbg("deregister hotplug cb %d", callback_handle); + usbi_mutex_lock(&ctx->hotplug_cbs_lock); - list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list, - struct libusb_hotplug_callback) { + list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) { if (callback_handle == hotplug_cb->handle) { /* Mark this callback for deregistration */ - hotplug_cb->needs_free = 1; + hotplug_cb->flags |= USBI_HOTPLUG_NEEDS_FREE; + deregistered = 1; } } usbi_mutex_unlock(&ctx->hotplug_cbs_lock); - usbi_hotplug_notification(ctx, NULL, 0); + if (deregistered) { + int pending_events; + + usbi_mutex_lock(&ctx->event_data_lock); + pending_events = usbi_pending_events(ctx); + ctx->event_flags |= USBI_EVENT_HOTPLUG_CB_DEREGISTERED; + if (!pending_events) + usbi_signal_event(ctx); + usbi_mutex_unlock(&ctx->event_data_lock); + } } -void usbi_hotplug_deregister_all(struct libusb_context *ctx) { +void usbi_hotplug_deregister(struct libusb_context *ctx, int forced) +{ struct libusb_hotplug_callback *hotplug_cb, *next; usbi_mutex_lock(&ctx->hotplug_cbs_lock); - list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, - struct libusb_hotplug_callback) { - list_del(&hotplug_cb->list); - free(hotplug_cb); + list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) { + if (forced || (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE)) { + usbi_dbg("freeing hotplug cb %p with handle %d", hotplug_cb, + hotplug_cb->handle); + list_del(&hotplug_cb->list); + free(hotplug_cb); + } } - usbi_mutex_unlock(&ctx->hotplug_cbs_lock); } diff --git a/Externals/libusb/libusb/hotplug.h b/Externals/libusb/libusb/hotplug.h index 2bec81b06c..75b2695f4c 100644 --- a/Externals/libusb/libusb/hotplug.h +++ b/Externals/libusb/libusb/hotplug.h @@ -19,12 +19,34 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#if !defined(USBI_HOTPLUG_H) +#ifndef USBI_HOTPLUG_H #define USBI_HOTPLUG_H -#ifndef LIBUSBI_H #include "libusbi.h" -#endif + +enum usbi_hotplug_flags { + /* This callback is interested in device arrivals */ + USBI_HOTPLUG_DEVICE_ARRIVED = LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, + + /* This callback is interested in device removals */ + USBI_HOTPLUG_DEVICE_LEFT = LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, + + /* IMPORTANT: The values for the below entries must start *after* + * the highest value of the above entries!!! + */ + + /* The vendor_id field is valid for matching */ + USBI_HOTPLUG_VENDOR_ID_VALID = (1U << 3), + + /* The product_id field is valid for matching */ + USBI_HOTPLUG_PRODUCT_ID_VALID = (1U << 4), + + /* The dev_class field is valid for matching */ + USBI_HOTPLUG_DEV_CLASS_VALID = (1U << 5), + + /* This callback has been unregistered and needs to be freed */ + USBI_HOTPLUG_NEEDS_FREE = (1U << 6), +}; /** \ingroup hotplug * The hotplug callback structure. The user populates this structure with @@ -32,23 +54,17 @@ * to receive notification of hotplug events. */ struct libusb_hotplug_callback { - /** Context this callback is associated with */ - struct libusb_context *ctx; + /** Flags that control how this callback behaves */ + uint8_t flags; - /** Vendor ID to match or LIBUSB_HOTPLUG_MATCH_ANY */ - int vendor_id; + /** Vendor ID to match (if flags says this is valid) */ + uint16_t vendor_id; - /** Product ID to match or LIBUSB_HOTPLUG_MATCH_ANY */ - int product_id; + /** Product ID to match (if flags says this is valid) */ + uint16_t product_id; - /** Device class to match or LIBUSB_HOTPLUG_MATCH_ANY */ - int dev_class; - - /** Hotplug callback flags */ - libusb_hotplug_flag flags; - - /** Event(s) that will trigger this callback */ - libusb_hotplug_event events; + /** Device class to match (if flags says this is valid) */ + uint8_t dev_class; /** Callback function to invoke for matching event/device */ libusb_hotplug_callback_fn cb; @@ -59,15 +75,10 @@ struct libusb_hotplug_callback { /** User data that will be passed to the callback function */ void *user_data; - /** Callback is marked for deletion */ - int needs_free; - /** List this callback is registered in (ctx->hotplug_cbs) */ struct list_head list; }; -typedef struct libusb_hotplug_callback libusb_hotplug_callback; - struct libusb_hotplug_message { /** The hotplug event that occurred */ libusb_hotplug_event event; @@ -79,9 +90,7 @@ struct libusb_hotplug_message { struct list_head list; }; -typedef struct libusb_hotplug_message libusb_hotplug_message; - -void usbi_hotplug_deregister_all(struct libusb_context *ctx); +void usbi_hotplug_deregister(struct libusb_context *ctx, int forced); void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, libusb_hotplug_event event); void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev, diff --git a/Externals/libusb/libusb/io.c b/Externals/libusb/libusb/io.c index bf2b5fa428..ef2b7c496f 100644 --- a/Externals/libusb/libusb/io.c +++ b/Externals/libusb/libusb/io.c @@ -27,9 +27,6 @@ #include #include #include -#ifdef HAVE_SIGNAL_H -#include -#endif #ifdef HAVE_SYS_TIME_H #include #endif @@ -1147,8 +1144,8 @@ int usbi_io_init(struct libusb_context *ctx) goto err_close_pipe; #ifdef USBI_TIMERFD_AVAILABLE - ctx->timerfd = timerfd_create(usbi_backend->get_timerfd_clockid(), - TFD_NONBLOCK); + ctx->timerfd = timerfd_create(usbi_backend.get_timerfd_clockid(), + TFD_NONBLOCK | TFD_CLOEXEC); if (ctx->timerfd >= 0) { usbi_dbg("using timerfd for timeouts"); r = usbi_add_pollfd(ctx, ctx->timerfd, POLLIN); @@ -1197,8 +1194,7 @@ void usbi_io_exit(struct libusb_context *ctx) usbi_cond_destroy(&ctx->event_waiters_cond); usbi_mutex_destroy(&ctx->event_data_lock); usbi_tls_key_delete(ctx->event_handling_key); - if (ctx->pollfds) - free(ctx->pollfds); + free(ctx->pollfds); } static int calculate_timeout(struct usbi_transfer *transfer) @@ -1208,10 +1204,12 @@ static int calculate_timeout(struct usbi_transfer *transfer) unsigned int timeout = USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout; - if (!timeout) + if (!timeout) { + timerclear(&transfer->timeout); return 0; + } - r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, ¤t_time); + r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, ¤t_time); if (r < 0) { usbi_err(ITRANSFER_CTX(transfer), "failed to read monotonic clock, errno=%d", errno); @@ -1250,7 +1248,7 @@ static int calculate_timeout(struct usbi_transfer *transfer) * use it on a non-isochronous endpoint. If you do this, ensure that at time * of submission, num_iso_packets is 0 and that type is set appropriately. * - * \param iso_packets number of isochronous packet descriptors to allocate + * \param iso_packets number of isochronous packet descriptors to allocate. Must be non-negative. * \returns a newly allocated transfer, or NULL on error */ DEFAULT_VISIBILITY @@ -1258,12 +1256,18 @@ struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer( int iso_packets) { struct libusb_transfer *transfer; - size_t os_alloc_size = usbi_backend->transfer_priv_size; - size_t alloc_size = sizeof(struct usbi_transfer) + size_t os_alloc_size; + size_t alloc_size; + struct usbi_transfer *itransfer; + + assert(iso_packets >= 0); + + os_alloc_size = usbi_backend.transfer_priv_size; + alloc_size = sizeof(struct usbi_transfer) + sizeof(struct libusb_transfer) - + (sizeof(struct libusb_iso_packet_descriptor) * iso_packets) + + (sizeof(struct libusb_iso_packet_descriptor) * (size_t)iso_packets) + os_alloc_size; - struct usbi_transfer *itransfer = calloc(1, alloc_size); + itransfer = calloc(1, alloc_size); if (!itransfer) return NULL; @@ -1298,7 +1302,7 @@ void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer) return; usbi_dbg("transfer %p", transfer); - if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER && transfer->buffer) + if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER) free(transfer->buffer); itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); @@ -1529,7 +1533,7 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer) */ usbi_mutex_unlock(&ctx->flying_transfers_lock); - r = usbi_backend->submit_transfer(itransfer); + r = usbi_backend.submit_transfer(itransfer); if (r == LIBUSB_SUCCESS) { itransfer->state_flags |= USBI_TRANSFER_IN_FLIGHT; /* keep a reference to this device */ @@ -1570,7 +1574,7 @@ int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer) r = LIBUSB_ERROR_NOT_FOUND; goto out; } - r = usbi_backend->cancel_transfer(itransfer); + r = usbi_backend.cancel_transfer(itransfer); if (r < 0) { if (r != LIBUSB_ERROR_NOT_FOUND && r != LIBUSB_ERROR_NO_DEVICE) @@ -1707,15 +1711,19 @@ int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer) * function will be called the next time an event handler runs. */ void usbi_signal_transfer_completion(struct usbi_transfer *transfer) { - struct libusb_context *ctx = ITRANSFER_CTX(transfer); - int pending_events; + libusb_device_handle *dev_handle = USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->dev_handle; - usbi_mutex_lock(&ctx->event_data_lock); - pending_events = usbi_pending_events(ctx); - list_add_tail(&transfer->completed_list, &ctx->completed_transfers); - if (!pending_events) - usbi_signal_event(ctx); - usbi_mutex_unlock(&ctx->event_data_lock); + if (dev_handle) { + struct libusb_context *ctx = HANDLE_CTX(dev_handle); + int pending_events; + + usbi_mutex_lock(&ctx->event_data_lock); + pending_events = usbi_pending_events(ctx); + list_add_tail(&transfer->completed_list, &ctx->completed_transfers); + if (!pending_events) + usbi_signal_event(ctx); + usbi_mutex_unlock(&ctx->event_data_lock); + } } /** \ingroup libusb_poll @@ -1887,14 +1895,17 @@ int API_EXPORTED libusb_event_handler_active(libusb_context *ctx) */ void API_EXPORTED libusb_interrupt_event_handler(libusb_context *ctx) { + int pending_events; USBI_GET_CONTEXT(ctx); usbi_dbg(""); usbi_mutex_lock(&ctx->event_data_lock); - if (!usbi_pending_events(ctx)) { - ctx->event_flags |= USBI_EVENT_USER_INTERRUPT; + + pending_events = usbi_pending_events(ctx); + ctx->event_flags |= USBI_EVENT_USER_INTERRUPT; + if (!pending_events) usbi_signal_event(ctx); - } + usbi_mutex_unlock(&ctx->event_data_lock); } @@ -2004,7 +2015,7 @@ static int handle_timeouts_locked(struct libusb_context *ctx) return 0; /* get current time */ - r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &systime_ts); + r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, &systime_ts); if (r < 0) return r; @@ -2077,13 +2088,19 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) struct pollfd *fds = NULL; int i = -1; int timeout_ms; - int special_event; /* prevent attempts to recursively handle events (e.g. calling into * libusb_handle_events() from within a hotplug or transfer callback) */ + usbi_mutex_lock(&ctx->event_data_lock); + r = 0; if (usbi_handling_events(ctx)) - return LIBUSB_ERROR_BUSY; - usbi_start_event_handling(ctx); + r = LIBUSB_ERROR_BUSY; + else + usbi_start_event_handling(ctx); + usbi_mutex_unlock(&ctx->event_data_lock); + + if (r) + return r; /* there are certain fds that libusb uses internally, currently: * @@ -2105,10 +2122,8 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) if (ctx->event_flags & USBI_EVENT_POLLFDS_MODIFIED) { usbi_dbg("poll fds modified, reallocating"); - if (ctx->pollfds) { - free(ctx->pollfds); - ctx->pollfds = NULL; - } + free(ctx->pollfds); + ctx->pollfds = NULL; /* sanity check - it is invalid for a context to have fewer than the * required internal fds (memory corruption?) */ @@ -2138,6 +2153,7 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) } fds = ctx->pollfds; nfds = ctx->pollfds_cnt; + usbi_inc_fds_ref(fds, nfds); usbi_mutex_unlock(&ctx->event_data_lock); timeout_ms = (int)(tv->tv_sec * 1000) + (tv->tv_usec / 1000); @@ -2146,32 +2162,30 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) if (tv->tv_usec % 1000) timeout_ms++; -redo_poll: usbi_dbg("poll() %d fds with timeout in %dms", nfds, timeout_ms); r = usbi_poll(fds, nfds, timeout_ms); usbi_dbg("poll() returned %d", r); if (r == 0) { r = handle_timeouts(ctx); goto done; - } - else if (r == -1 && errno == EINTR) { + } else if (r == -1 && errno == EINTR) { r = LIBUSB_ERROR_INTERRUPTED; goto done; - } - else if (r < 0) { + } else if (r < 0) { usbi_err(ctx, "poll failed %d err=%d", r, errno); r = LIBUSB_ERROR_IO; goto done; } - special_event = 0; - /* fds[0] is always the event pipe */ if (fds[0].revents) { - libusb_hotplug_message *message = NULL; + struct list_head hotplug_msgs; struct usbi_transfer *itransfer; + int hotplug_cb_deregistered = 0; int ret = 0; + list_init(&hotplug_msgs); + usbi_dbg("caught a fish on the event pipe"); /* take the the event data lock while processing events */ @@ -2186,6 +2200,12 @@ redo_poll: ctx->event_flags &= ~USBI_EVENT_USER_INTERRUPT; } + if (ctx->event_flags & USBI_EVENT_HOTPLUG_CB_DEREGISTERED) { + usbi_dbg("someone unregistered a hotplug cb"); + ctx->event_flags &= ~USBI_EVENT_HOTPLUG_CB_DEREGISTERED; + hotplug_cb_deregistered = 1; + } + /* check if someone is closing a device */ if (ctx->device_close) usbi_dbg("someone is closing a device"); @@ -2193,9 +2213,7 @@ redo_poll: /* check for any pending hotplug messages */ if (!list_empty(&ctx->hotplug_msgs)) { usbi_dbg("hotplug message received"); - special_event = 1; - message = list_first_entry(&ctx->hotplug_msgs, libusb_hotplug_message, list); - list_del(&message->list); + list_cut(&hotplug_msgs, &ctx->hotplug_msgs); } /* complete any pending transfers */ @@ -2203,7 +2221,7 @@ redo_poll: itransfer = list_first_entry(&ctx->completed_transfers, struct usbi_transfer, completed_list); list_del(&itransfer->completed_list); usbi_mutex_unlock(&ctx->event_data_lock); - ret = usbi_backend->handle_transfer_completion(itransfer); + ret = usbi_backend.handle_transfer_completion(itransfer); if (ret) usbi_err(ctx, "backend handle_transfer_completion failed with error %d", ret); usbi_mutex_lock(&ctx->event_data_lock); @@ -2215,14 +2233,21 @@ redo_poll: usbi_mutex_unlock(&ctx->event_data_lock); - /* process the hotplug message, if any */ - if (message) { + if (hotplug_cb_deregistered) + usbi_hotplug_deregister(ctx, 0); + + /* process the hotplug messages, if any */ + while (!list_empty(&hotplug_msgs)) { + struct libusb_hotplug_message *message = + list_first_entry(&hotplug_msgs, struct libusb_hotplug_message, list); + usbi_hotplug_match(ctx, message->device, message->event); /* the device left, dereference the device */ if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == message->event) libusb_unref_device(message->device); + list_del(&message->list); free(message); } @@ -2233,7 +2258,7 @@ redo_poll: } if (0 == --r) - goto handled; + goto done; } #ifdef USBI_TIMERFD_AVAILABLE @@ -2242,7 +2267,6 @@ redo_poll: /* timerfd indicates that a timeout has expired */ int ret; usbi_dbg("timerfd triggered"); - special_event = 1; ret = handle_timerfd_trigger(ctx); if (ret < 0) { @@ -2252,22 +2276,17 @@ redo_poll: } if (0 == --r) - goto handled; + goto done; } #endif - r = usbi_backend->handle_events(ctx, fds + internal_nfds, nfds - internal_nfds, r); + r = usbi_backend.handle_events(ctx, fds + internal_nfds, nfds - internal_nfds, r); if (r) usbi_err(ctx, "backend handle_events failed with error %d", r); -handled: - if (r == 0 && special_event) { - timeout_ms = 0; - goto redo_poll; - } - done: usbi_end_event_handling(ctx); + usbi_dec_fds_ref(fds, nfds); return r; } @@ -2583,7 +2602,7 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx, return 0; } - r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &cur_ts); + r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, &cur_ts); if (r < 0) { usbi_err(ctx, "failed to read monotonic clock, errno=%d", errno); return 0; @@ -2595,7 +2614,7 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx, timerclear(tv); } else { timersub(&next_timeout, &cur_tv, tv); - usbi_dbg("next timeout in %d.%06ds", tv->tv_sec, tv->tv_usec); + usbi_dbg("next timeout in %ld.%06lds", (long)tv->tv_sec, (long)tv->tv_usec); } return 1; @@ -2752,15 +2771,12 @@ out: * Since version 1.0.20, \ref LIBUSB_API_VERSION >= 0x01000104 * * It is legal to call this function with a NULL pollfd list. In this case, - * the function will simply return safely. + * the function will simply do nothing. * * \param pollfds the list of libusb_pollfd structures to free */ void API_EXPORTED libusb_free_pollfds(const struct libusb_pollfd **pollfds) { - if (!pollfds) - return; - free((void *)pollfds); } @@ -2811,7 +2827,7 @@ void usbi_handle_disconnect(struct libusb_device_handle *dev_handle) USBI_TRANSFER_TO_LIBUSB_TRANSFER(to_cancel)); usbi_mutex_lock(&to_cancel->lock); - usbi_backend->clear_transfer_priv(to_cancel); + usbi_backend.clear_transfer_priv(to_cancel); usbi_mutex_unlock(&to_cancel->lock); usbi_handle_transfer_completion(to_cancel, LIBUSB_TRANSFER_NO_DEVICE); } diff --git a/Externals/libusb/libusb/libusb-1.0.def b/Externals/libusb/libusb/libusb-1.0.def index 2443d9bef4..6eba4ff008 100644 --- a/Externals/libusb/libusb/libusb-1.0.def +++ b/Externals/libusb/libusb/libusb-1.0.def @@ -126,10 +126,10 @@ EXPORTS libusb_interrupt_transfer@24 = libusb_interrupt_transfer libusb_kernel_driver_active libusb_kernel_driver_active@8 = libusb_kernel_driver_active - libusb_lock_events - libusb_lock_events@4 = libusb_lock_events libusb_lock_event_waiters libusb_lock_event_waiters@4 = libusb_lock_event_waiters + libusb_lock_events + libusb_lock_events@4 = libusb_lock_events libusb_open libusb_open@8 = libusb_open libusb_open_device_with_vid_pid @@ -148,12 +148,16 @@ EXPORTS libusb_set_configuration@8 = libusb_set_configuration libusb_set_debug libusb_set_debug@8 = libusb_set_debug + libusb_set_log_cb + libusb_set_log_cb@12 = libusb_set_log_cb libusb_set_interface_alt_setting libusb_set_interface_alt_setting@12 = libusb_set_interface_alt_setting - libusb_setlocale - libusb_setlocale@4 = libusb_setlocale + libusb_set_option + _libusb_set_option = libusb_set_option libusb_set_pollfd_notifiers libusb_set_pollfd_notifiers@16 = libusb_set_pollfd_notifiers + libusb_setlocale + libusb_setlocale@4 = libusb_setlocale libusb_strerror libusb_strerror@4 = libusb_strerror libusb_submit_transfer @@ -164,10 +168,10 @@ EXPORTS libusb_transfer_set_stream_id@8 = libusb_transfer_set_stream_id libusb_try_lock_events libusb_try_lock_events@4 = libusb_try_lock_events - libusb_unlock_events - libusb_unlock_events@4 = libusb_unlock_events libusb_unlock_event_waiters libusb_unlock_event_waiters@4 = libusb_unlock_event_waiters + libusb_unlock_events + libusb_unlock_events@4 = libusb_unlock_events libusb_unref_device libusb_unref_device@4 = libusb_unref_device libusb_wait_for_event diff --git a/Externals/libusb/libusb/libusb.h b/Externals/libusb/libusb/libusb.h index f73e31cc26..8a6b0bfa9f 100644 --- a/Externals/libusb/libusb/libusb.h +++ b/Externals/libusb/libusb/libusb.h @@ -3,7 +3,7 @@ * Copyright © 2001 Johannes Erdfelt * Copyright © 2007-2008 Daniel Drake * Copyright © 2012 Pete Batard - * Copyright © 2012 Nathan Hjelm + * Copyright © 2012-2018 Nathan Hjelm * For more information, please visit: http://libusb.info * * This library is free software; you can redistribute it and/or @@ -54,13 +54,19 @@ typedef unsigned __int32 uint32_t; #include #endif -#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__) +#if defined(__linux__) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__) #include #endif #include #include +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +#define ZERO_SIZED_ARRAY /* [] - valid C99 code */ +#else +#define ZERO_SIZED_ARRAY 0 /* [0] - non-standard, but usually working code */ +#endif + /* 'interface' might be defined as a macro on Windows, so we need to * undefine it so as not to break the current libusb API, because * libusb_config_descriptor has an 'interface' member @@ -79,6 +85,8 @@ typedef unsigned __int32 uint32_t; #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) #define LIBUSB_DEPRECATED_FOR(f) \ __attribute__((deprecated("Use " #f " instead"))) +#elif __GNUC__ >= 3 +#define LIBUSB_DEPRECATED_FOR(f) __attribute__((deprecated)) #else #define LIBUSB_DEPRECATED_FOR(f) #endif /* __GNUC__ */ @@ -141,7 +149,7 @@ typedef unsigned __int32 uint32_t; * Internally, LIBUSB_API_VERSION is defined as follows: * (libusb major << 24) | (libusb minor << 16) | (16 bit incremental) */ -#define LIBUSB_API_VERSION 0x01000105 +#define LIBUSB_API_VERSION 0x01000107 /* The following is kept for compatibility, but will be deprecated in the future */ #define LIBUSBX_API_VERSION LIBUSB_API_VERSION @@ -569,7 +577,7 @@ struct libusb_endpoint_descriptor { * it will store them here, should you wish to parse them. */ const unsigned char *extra; - /** Length of the extra descriptors, in bytes. */ + /** Length of the extra descriptors, in bytes. Must be non-negative. */ int extra_length; }; @@ -619,7 +627,7 @@ struct libusb_interface_descriptor { * it will store them here, should you wish to parse them. */ const unsigned char *extra; - /** Length of the extra descriptors, in bytes. */ + /** Length of the extra descriptors, in bytes. Must be non-negative. */ int extra_length; }; @@ -631,7 +639,8 @@ struct libusb_interface { * by the num_altsetting field. */ const struct libusb_interface_descriptor *altsetting; - /** The number of alternate settings that belong to this interface */ + /** The number of alternate settings that belong to this interface. + * Must be non-negative. */ int num_altsetting; }; @@ -678,7 +687,7 @@ struct libusb_config_descriptor { * descriptors, it will store them here, should you wish to parse them. */ const unsigned char *extra; - /** Length of the extra descriptors, in bytes. */ + /** Length of the extra descriptors, in bytes. Must be non-negative. */ int extra_length; }; @@ -729,13 +738,7 @@ struct libusb_bos_dev_capability_descriptor { /** Device Capability type */ uint8_t bDevCapabilityType; /** Device Capability data (bLength - 3 bytes) */ - uint8_t dev_capability_data -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif - ; + uint8_t dev_capability_data[ZERO_SIZED_ARRAY]; }; /** \ingroup libusb_desc @@ -760,13 +763,7 @@ struct libusb_bos_descriptor { uint8_t bNumDeviceCaps; /** bNumDeviceCap Device Capability Descriptors */ - struct libusb_bos_dev_capability_descriptor *dev_capability -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif - ; + struct libusb_bos_dev_capability_descriptor *dev_capability[ZERO_SIZED_ARRAY]; }; /** \ingroup libusb_desc @@ -927,7 +924,7 @@ struct libusb_version { * sessions allows for your program to use two libraries (or dynamically * load two modules) which both independently use libusb. This will prevent * interference between the individual libusb users - for example - * libusb_set_debug() will not affect the other user of the library, and + * libusb_set_option() will not affect the other user of the library, and * libusb_exit() will not destroy resources that the other user is still * using. * @@ -987,6 +984,9 @@ enum libusb_speed { /** The device is operating at super speed (5000MBit/s). */ LIBUSB_SPEED_SUPER = 4, + + /** The device is operating at super speed plus (10000MBit/s). */ + LIBUSB_SPEED_SUPER_PLUS = 5, }; /** \ingroup libusb_dev @@ -1135,19 +1135,19 @@ enum libusb_transfer_status { * libusb_transfer.flags values */ enum libusb_transfer_flags { /** Report short frames as errors */ - LIBUSB_TRANSFER_SHORT_NOT_OK = 1<<0, + LIBUSB_TRANSFER_SHORT_NOT_OK = 1U << 0, /** Automatically free() transfer buffer during libusb_free_transfer(). * Note that buffers allocated with libusb_dev_mem_alloc() should not * be attempted freed in this way, since free() is not an appropriate * way to release such memory. */ - LIBUSB_TRANSFER_FREE_BUFFER = 1<<1, + LIBUSB_TRANSFER_FREE_BUFFER = 1U << 1, /** Automatically call libusb_free_transfer() after callback returns. * If this flag is set, it is illegal to call libusb_free_transfer() * from your transfer callback, as this will result in a double-free * when this flag is acted upon. */ - LIBUSB_TRANSFER_FREE_TRANSFER = 1<<2, + LIBUSB_TRANSFER_FREE_TRANSFER = 1U << 2, /** Terminate transfers that are a multiple of the endpoint's * wMaxPacketSize with an extra zero length packet. This is useful @@ -1172,7 +1172,7 @@ enum libusb_transfer_flags { * * Available since libusb-1.0.9. */ - LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1 << 3, + LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1U << 3, }; /** \ingroup libusb_asyncio @@ -1220,7 +1220,7 @@ struct libusb_transfer { /** Type of the endpoint from \ref libusb_transfer_type */ unsigned char type; - /** Timeout for this transfer in millseconds. A value of 0 indicates no + /** Timeout for this transfer in milliseconds. A value of 0 indicates no * timeout. */ unsigned int timeout; @@ -1233,7 +1233,7 @@ struct libusb_transfer { * to determine if errors occurred. */ enum libusb_transfer_status status; - /** Length of the data buffer */ + /** Length of the data buffer. Must be non-negative. */ int length; /** Actual length of data that was transferred. Read-only, and only for @@ -1252,17 +1252,11 @@ struct libusb_transfer { unsigned char *buffer; /** Number of isochronous packets. Only used for I/O with isochronous - * endpoints. */ + * endpoints. Must be non-negative. */ int num_iso_packets; /** Isochronous packet descriptors, for isochronous transfers only. */ - struct libusb_iso_packet_descriptor iso_packet_desc -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif - ; + struct libusb_iso_packet_descriptor iso_packet_desc[ZERO_SIZED_ARRAY]; }; /** \ingroup libusb_misc @@ -1290,22 +1284,46 @@ enum libusb_capability { * - LIBUSB_LOG_LEVEL_NONE (0) : no messages ever printed by the library (default) * - LIBUSB_LOG_LEVEL_ERROR (1) : error messages are printed to stderr * - LIBUSB_LOG_LEVEL_WARNING (2) : warning and error messages are printed to stderr - * - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stdout, warning - * and error messages are printed to stderr - * - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stdout, - * warnings and errors to stderr + * - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stderr + * - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stderr */ enum libusb_log_level { LIBUSB_LOG_LEVEL_NONE = 0, - LIBUSB_LOG_LEVEL_ERROR, - LIBUSB_LOG_LEVEL_WARNING, - LIBUSB_LOG_LEVEL_INFO, - LIBUSB_LOG_LEVEL_DEBUG, + LIBUSB_LOG_LEVEL_ERROR = 1, + LIBUSB_LOG_LEVEL_WARNING = 2, + LIBUSB_LOG_LEVEL_INFO = 3, + LIBUSB_LOG_LEVEL_DEBUG = 4, }; +/** \ingroup libusb_lib + * Log callback mode. + * \see libusb_set_log_cb() + */ +enum libusb_log_cb_mode { + + /** Callback function handling all log mesages. */ + LIBUSB_LOG_CB_GLOBAL = 1 << 0, + + /** Callback function handling context related log mesages. */ + LIBUSB_LOG_CB_CONTEXT = 1 << 1 +}; + +/** \ingroup libusb_lib + * Callback function for handling log messages. + * \param ctx the context which is related to the log message, or NULL if it + * is a global log message + * \param level the log level, see \ref libusb_log_level for a description + * \param str the log message + * \see libusb_set_log_cb() + */ +typedef void (LIBUSB_CALL *libusb_log_cb)(libusb_context *ctx, + enum libusb_log_level level, const char *str); + int LIBUSB_CALL libusb_init(libusb_context **ctx); void LIBUSB_CALL libusb_exit(libusb_context *ctx); +LIBUSB_DEPRECATED_FOR(libusb_set_option) void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level); +void LIBUSB_CALL libusb_set_log_cb(libusb_context *ctx, libusb_log_cb cb, int mode); const struct libusb_version * LIBUSB_CALL libusb_get_version(void); int LIBUSB_CALL libusb_has_capability(uint32_t capability); const char * LIBUSB_CALL libusb_error_name(int errcode); @@ -1370,6 +1388,7 @@ int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev, int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev, unsigned char endpoint); +int LIBUSB_CALL libusb_wrap_sys_device(libusb_context *ctx, intptr_t sys_dev, libusb_device_handle **dev_handle); int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **dev_handle); void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle); libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle); @@ -1892,10 +1911,10 @@ typedef int libusb_hotplug_callback_handle; * Flags for hotplug events */ typedef enum { /** Default value when not using any flags. */ - LIBUSB_HOTPLUG_NO_FLAGS = 0, + LIBUSB_HOTPLUG_NO_FLAGS = 0U, /** Arm the callback and fire it for all matching currently attached devices. */ - LIBUSB_HOTPLUG_ENUMERATE = 1<<0, + LIBUSB_HOTPLUG_ENUMERATE = 1U << 0, } libusb_hotplug_flag; /** \ingroup libusb_hotplug @@ -1905,12 +1924,12 @@ typedef enum { * Hotplug events */ typedef enum { /** A device has been plugged in and is ready to use */ - LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = 0x01, + LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = 0x01U, /** A device has left and is no longer available. * It is the user's responsibility to call libusb_close on any handle associated with a disconnected device. * It is safe to call libusb_get_device_descriptor on a device that has left */ - LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT = 0x02, + LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT = 0x02U, } libusb_hotplug_event; /** \ingroup libusb_hotplug @@ -2001,6 +2020,45 @@ int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx, void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx, libusb_hotplug_callback_handle callback_handle); +/** \ingroup libusb_lib + * Available option values for libusb_set_option(). + */ +enum libusb_option { + /** Set the log message verbosity. + * + * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever + * printed. If you choose to increase the message verbosity level, ensure + * that your application does not close the stderr file descriptor. + * + * You are advised to use level LIBUSB_LOG_LEVEL_WARNING. libusb is conservative + * with its message logging and most of the time, will only log messages that + * explain error conditions and other oddities. This will help you debug + * your software. + * + * If the LIBUSB_DEBUG environment variable was set when libusb was + * initialized, this function does nothing: the message verbosity is fixed + * to the value in the environment variable. + * + * If libusb was compiled without any message logging, this function does + * nothing: you'll never get any messages. + * + * If libusb was compiled with verbose debug message logging, this function + * does nothing: you'll always get messages from all levels. + */ + LIBUSB_OPTION_LOG_LEVEL, + + /** Use the UsbDk backend for a specific context, if available. + * + * This option should be set immediately after calling libusb_init(), otherwise + * unspecified behavior may occur. + * + * Only valid on Windows. + */ + LIBUSB_OPTION_USE_USBDK, +}; + +int LIBUSB_CALL libusb_set_option(libusb_context *ctx, enum libusb_option option, ...); + #ifdef __cplusplus } #endif diff --git a/Externals/libusb/libusb/libusbi.h b/Externals/libusb/libusb/libusbi.h index dcc996e179..d2adfebc54 100644 --- a/Externals/libusb/libusb/libusbi.h +++ b/Externals/libusb/libusb/libusbi.h @@ -24,7 +24,7 @@ #include #include - +#include #include #include #include @@ -39,6 +39,20 @@ #include "libusb.h" #include "version.h" +/* Attribute to ensure that a structure member is aligned to a natural + * pointer alignment. Used for os_priv member. */ +#if defined(_MSC_VER) +#if defined(_WIN64) +#define PTR_ALIGNED __declspec(align(8)) +#else +#define PTR_ALIGNED __declspec(align(4)) +#endif +#elif defined(__GNUC__) +#define PTR_ALIGNED __attribute__((aligned(sizeof(void *)))) +#else +#define PTR_ALIGNED +#endif + /* Inside the libusb code, mark all public functions as follows: * return_type API_EXPORTED function_name(params) { ... } * But if the function returns a pointer, mark it as follows: @@ -48,6 +62,16 @@ */ #define API_EXPORTED LIBUSB_CALL DEFAULT_VISIBILITY +/* Macro to decorate printf-like functions, in order to get + * compiler warnings about format string mistakes. + */ +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) +#define USBI_PRINTFLIKE(formatarg, firstvararg) \ + __attribute__((__format__ (__printf__, formatarg, firstvararg))) +#else +#define USBI_PRINTFLIKE(formatarg, firstvararg) +#endif + #ifdef __cplusplus extern "C" { #endif @@ -139,6 +163,19 @@ static inline void list_del(struct list_head *entry) entry->next = entry->prev = NULL; } +static inline void list_cut(struct list_head *list, struct list_head *head) +{ + if (list_empty(head)) + return; + + list->next = head->next; + list->next->prev = list; + list->prev = head->prev; + list->prev->next = list; + + list_init(head); +} + static inline void *usbi_reallocf(void *ptr, size_t size) { void *ret = realloc(ptr, size); @@ -151,6 +188,9 @@ static inline void *usbi_reallocf(void *ptr, size_t size) const typeof( ((type *)0)->member ) *mptr = (ptr); \ (type *)( (char *)mptr - offsetof(type,member) );}) +#ifndef CLAMP +#define CLAMP(val, min, max) ((val) < (min) ? (min) : ((val) > (max) ? (max) : (val))) +#endif #ifndef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif @@ -175,29 +215,33 @@ static inline void *usbi_reallocf(void *ptr, size_t size) } while (0) #endif +#ifdef ENABLE_LOGGING + +#if defined(_MSC_VER) && (_MSC_VER < 1900) +#define snprintf usbi_snprintf +#define vsnprintf usbi_vsnprintf +int usbi_snprintf(char *dst, size_t size, const char *format, ...); +int usbi_vsnprintf(char *dst, size_t size, const char *format, va_list ap); +#define LIBUSB_PRINTF_WIN32 +#endif /* defined(_MSC_VER) && (_MSC_VER < 1900) */ + void usbi_log(struct libusb_context *ctx, enum libusb_log_level level, - const char *function, const char *format, ...); + const char *function, const char *format, ...) USBI_PRINTFLIKE(4, 5); void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, - const char *function, const char *format, va_list args); + const char *function, const char *format, va_list args) USBI_PRINTFLIKE(4, 0); -#if !defined(_MSC_VER) || _MSC_VER >= 1400 +#if !defined(_MSC_VER) || (_MSC_VER >= 1400) -#ifdef ENABLE_LOGGING #define _usbi_log(ctx, level, ...) usbi_log(ctx, level, __FUNCTION__, __VA_ARGS__) -#define usbi_dbg(...) _usbi_log(NULL, LIBUSB_LOG_LEVEL_DEBUG, __VA_ARGS__) -#else -#define _usbi_log(ctx, level, ...) do { (void)(ctx); } while(0) -#define usbi_dbg(...) do {} while(0) -#endif -#define usbi_info(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_INFO, __VA_ARGS__) -#define usbi_warn(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_WARNING, __VA_ARGS__) #define usbi_err(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_ERROR, __VA_ARGS__) +#define usbi_warn(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_WARNING, __VA_ARGS__) +#define usbi_info(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_INFO, __VA_ARGS__) +#define usbi_dbg(...) _usbi_log(NULL, LIBUSB_LOG_LEVEL_DEBUG, __VA_ARGS__) -#else /* !defined(_MSC_VER) || _MSC_VER >= 1400 */ +#else /* !defined(_MSC_VER) || (_MSC_VER >= 1400) */ -#ifdef ENABLE_LOGGING #define LOG_BODY(ctxt, level) \ { \ va_list args; \ @@ -205,24 +249,26 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, usbi_log_v(ctxt, level, "", format, args); \ va_end(args); \ } -#else -#define LOG_BODY(ctxt, level) \ -{ \ - (void)(ctxt); \ -} -#endif -static inline void usbi_info(struct libusb_context *ctx, const char *format, ...) - LOG_BODY(ctx, LIBUSB_LOG_LEVEL_INFO) -static inline void usbi_warn(struct libusb_context *ctx, const char *format, ...) - LOG_BODY(ctx, LIBUSB_LOG_LEVEL_WARNING) static inline void usbi_err(struct libusb_context *ctx, const char *format, ...) LOG_BODY(ctx, LIBUSB_LOG_LEVEL_ERROR) - +static inline void usbi_warn(struct libusb_context *ctx, const char *format, ...) + LOG_BODY(ctx, LIBUSB_LOG_LEVEL_WARNING) +static inline void usbi_info(struct libusb_context *ctx, const char *format, ...) + LOG_BODY(ctx, LIBUSB_LOG_LEVEL_INFO) static inline void usbi_dbg(const char *format, ...) LOG_BODY(NULL, LIBUSB_LOG_LEVEL_DEBUG) -#endif /* !defined(_MSC_VER) || _MSC_VER >= 1400 */ +#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1400) */ + +#else /* ENABLE_LOGGING */ + +#define usbi_err(ctx, ...) do { (void)ctx; } while (0) +#define usbi_warn(ctx, ...) do { (void)ctx; } while (0) +#define usbi_info(ctx, ...) do { (void)ctx; } while (0) +#define usbi_dbg(...) do {} while (0) + +#endif /* ENABLE_LOGGING */ #define USBI_GET_CONTEXT(ctx) \ do { \ @@ -254,8 +300,11 @@ extern struct libusb_context *usbi_default_context; struct pollfd; struct libusb_context { - int debug; +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) + enum libusb_log_level debug; int debug_fixed; + libusb_log_cb log_handler; +#endif /* internal event pipe, used for signalling occurrence of an internal event. */ int event_pipe[2]; @@ -270,6 +319,7 @@ struct libusb_context { /* A list of registered hotplug callbacks */ struct list_head hotplug_cbs; + libusb_hotplug_callback_handle next_hotplug_cb_handle; usbi_mutex_t hotplug_cbs_lock; /* this is a list of in-flight transfer handles, sorted by timeout @@ -331,14 +381,19 @@ struct libusb_context { #endif struct list_head list; + + PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY]; }; enum usbi_event_flags { /* The list of pollfds has been modified */ - USBI_EVENT_POLLFDS_MODIFIED = 1 << 0, + USBI_EVENT_POLLFDS_MODIFIED = 1U << 0, /* The user has interrupted the event handler */ - USBI_EVENT_USER_INTERRUPT = 1 << 1, + USBI_EVENT_USER_INTERRUPT = 1U << 1, + + /* A hotplug callback deregistration is pending */ + USBI_EVENT_HOTPLUG_CB_DEREGISTERED = 1U << 2, }; /* Macros for managing event handling state */ @@ -383,17 +438,7 @@ struct libusb_device { struct libusb_device_descriptor device_descriptor; int attached; - unsigned char os_priv -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif -#if defined(OS_SUNOS) - __attribute__ ((aligned (8))); -#else - ; -#endif + PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY]; }; struct libusb_device_handle { @@ -404,17 +449,8 @@ struct libusb_device_handle { struct list_head list; struct libusb_device *dev; int auto_detach_kernel_driver; - unsigned char os_priv -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif -#if defined(OS_SUNOS) - __attribute__ ((aligned (8))); -#else - ; -#endif + + PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY]; }; enum { @@ -459,24 +495,24 @@ struct usbi_transfer { enum usbi_transfer_state_flags { /* Transfer successfully submitted by backend */ - USBI_TRANSFER_IN_FLIGHT = 1 << 0, + USBI_TRANSFER_IN_FLIGHT = 1U << 0, /* Cancellation was requested via libusb_cancel_transfer() */ - USBI_TRANSFER_CANCELLING = 1 << 1, + USBI_TRANSFER_CANCELLING = 1U << 1, /* Operation on the transfer failed because the device disappeared */ - USBI_TRANSFER_DEVICE_DISAPPEARED = 1 << 2, + USBI_TRANSFER_DEVICE_DISAPPEARED = 1U << 2, }; enum usbi_transfer_timeout_flags { /* Set by backend submit_transfer() if the OS handles timeout */ - USBI_TRANSFER_OS_HANDLES_TIMEOUT = 1 << 0, + USBI_TRANSFER_OS_HANDLES_TIMEOUT = 1U << 0, /* The transfer timeout has been handled */ - USBI_TRANSFER_TIMEOUT_HANDLED = 1 << 1, + USBI_TRANSFER_TIMEOUT_HANDLED = 1U << 1, /* The transfer timeout was successfully processed */ - USBI_TRANSFER_TIMED_OUT = 1 << 2, + USBI_TRANSFER_TIMED_OUT = 1U << 2, }; #define USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \ @@ -488,9 +524,10 @@ enum usbi_transfer_timeout_flags { static inline void *usbi_transfer_get_os_priv(struct usbi_transfer *transfer) { + assert(transfer->num_iso_packets >= 0); return ((unsigned char *)transfer) + sizeof(struct usbi_transfer) + sizeof(struct libusb_transfer) - + (transfer->num_iso_packets + + ((size_t)transfer->num_iso_packets * sizeof(struct libusb_iso_packet_descriptor)); } @@ -540,19 +577,6 @@ int usbi_clear_event(struct libusb_context *ctx); #include "os/poll_windows.h" #endif -#if (defined(OS_WINDOWS) || defined(OS_WINCE)) && !defined(__GNUC__) -#define snprintf _snprintf -#define vsnprintf _vsnprintf -int usbi_gettimeofday(struct timeval *tp, void *tzp); -#define LIBUSB_GETTIMEOFDAY_WIN32 -#define HAVE_USBI_GETTIMEOFDAY -#else -#ifdef HAVE_GETTIMEOFDAY -#define usbi_gettimeofday(tv, tz) gettimeofday((tv), (tz)) -#define HAVE_USBI_GETTIMEOFDAY -#endif -#endif - struct usbi_pollfd { /* must come first */ struct libusb_pollfd pollfd; @@ -573,13 +597,7 @@ void usbi_remove_pollfd(struct libusb_context *ctx, int fd); struct discovered_devs { size_t len; size_t capacity; - struct libusb_device *devices -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif - ; + struct libusb_device *devices[ZERO_SIZED_ARRAY]; }; struct discovered_devs *discovered_devs_append( @@ -612,7 +630,17 @@ struct usbi_os_backend { * * This function is called when the user deinitializes the library. */ - void (*exit)(void); + void (*exit)(struct libusb_context *ctx); + + /* Set a backend-specific option. Optional. + * + * This function is called when the user calls libusb_set_option() and + * the option is not handled by the core library. + * + * Return 0 on success, or a LIBUSB_ERROR code on failure. + */ + int (*set_option)(struct libusb_context *ctx, enum libusb_option option, + va_list args); /* Enumerate all the USB devices on the system, returning them in a list * of discovered devices. @@ -685,6 +713,34 @@ struct usbi_os_backend { */ void (*hotplug_poll)(void); + /* Wrap a platform-specific device handle for I/O and other USB + * operations. The device handle is preallocated for you. + * + * Your backend should allocate any internal resources required for I/O + * and other operations so that those operations can happen (hopefully) + * without hiccup. This is also a good place to inform libusb that it + * should monitor certain file descriptors related to this device - + * see the usbi_add_pollfd() function. + * + * Your backend should also initialize the device structure + * (dev_handle->dev), which is NULL at the beginning of the call. + * + * This function should not generate any bus I/O and should not block. + * + * This function is called when the user attempts to wrap an existing + * platform-specific device handle for a device. + * + * Return: + * - 0 on success + * - LIBUSB_ERROR_ACCESS if the user has insufficient permissions + * - another LIBUSB_ERROR code on other failure + * + * Do not worry about freeing the handle on failed open, the upper layers + * do this for you. + */ + int (*wrap_sys_device)(struct libusb_context *ctx, + struct libusb_device_handle *dev_handle, intptr_t sys_dev); + /* Open a device for I/O and other USB operations. The device handle * is preallocated for you, you can retrieve the device in question * through handle->dev. @@ -1115,6 +1171,11 @@ struct usbi_os_backend { clockid_t (*get_timerfd_clockid)(void); #endif + /* Number of bytes to reserve for per-context private backend data. + * This private data area is accessible through the "os_priv" field of + * struct libusb_context. */ + size_t context_priv_size; + /* Number of bytes to reserve for per-device private backend data. * This private data area is accessible through the "os_priv" field of * struct libusb_device. */ @@ -1132,21 +1193,7 @@ struct usbi_os_backend { size_t transfer_priv_size; }; -#if defined(OS_WINDOWS) -extern const struct usbi_os_backend * usbi_backend; -#else -extern const struct usbi_os_backend * const usbi_backend; -#endif - -extern const struct usbi_os_backend linux_usbfs_backend; -extern const struct usbi_os_backend darwin_backend; -extern const struct usbi_os_backend openbsd_backend; -extern const struct usbi_os_backend netbsd_backend; -extern const struct usbi_os_backend windows_backend; -extern const struct usbi_os_backend usbdk_backend; -extern const struct usbi_os_backend wince_backend; -extern const struct usbi_os_backend haiku_usb_raw_backend; -extern const struct usbi_os_backend sunos_backend; +extern const struct usbi_os_backend usbi_backend; extern struct list_head active_contexts_list; extern usbi_mutex_static_t active_contexts_lock; diff --git a/Externals/libusb/libusb/os/darwin_usb.c b/Externals/libusb/libusb/os/darwin_usb.c index c2285cd7cb..f6e853b46b 100644 --- a/Externals/libusb/libusb/os/darwin_usb.c +++ b/Externals/libusb/libusb/os/darwin_usb.c @@ -1,7 +1,8 @@ /* -*- Mode: C; indent-tabs-mode:nil -*- */ /* * darwin backend for libusb 1.0 - * Copyright © 2008-2016 Nathan Hjelm + * Copyright © 2008-2019 Nathan Hjelm + * Copyright © 2019 Google LLC. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,6 +20,7 @@ */ #include "config.h" +#include #include #include #include @@ -36,6 +38,10 @@ #include #include +/* Suppress warnings about the use of the deprecated objc_registerThreadWithCollector + * function. Its use is also conditionalized to only older deployment targets. */ +#define OBJC_SILENCE_GC_DEPRECATIONS 1 + #include #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200 #include @@ -55,6 +61,14 @@ _Atomic int32_t initCount = ATOMIC_VAR_INIT(0); #define libusb_darwin_atomic_fetch_add(x, y) (OSAtomicAdd32Barrier(y, x) - y) static volatile int32_t initCount = 0; + +#endif + +/* On 10.12 and later, use newly available clock_*() functions */ +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200 +#define OSX_USE_CLOCK_GETTIME 1 +#else +#define OSX_USE_CLOCK_GETTIME 0 #endif #include "darwin_usb.h" @@ -63,17 +77,17 @@ static volatile int32_t initCount = 0; static pthread_mutex_t libusb_darwin_at_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t libusb_darwin_at_cond = PTHREAD_COND_INITIALIZER; -static pthread_once_t darwin_init_once = PTHREAD_ONCE_INIT; - +#if !OSX_USE_CLOCK_GETTIME static clock_serv_t clock_realtime; static clock_serv_t clock_monotonic; +#endif static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */ static CFRunLoopSourceRef libusb_darwin_acfls = NULL; /* shutdown signal for event cf loop */ static usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER; static struct list_head darwin_cached_devices = {&darwin_cached_devices, &darwin_cached_devices}; -static char *darwin_device_class = kIOUSBDeviceClassName; +static const char *darwin_device_class = kIOUSBDeviceClassName; #define DARWIN_CACHED_DEVICE(a) ((struct darwin_cached_device *) (((struct darwin_device_priv *)((a)->os_priv))->dev)) @@ -86,11 +100,11 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, int static int darwin_reset_device(struct libusb_device_handle *dev_handle); static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0); -static int darwin_scan_devices(struct libusb_context *ctx); -static int process_new_device (struct libusb_context *ctx, io_service_t service); +static enum libusb_error darwin_scan_devices(struct libusb_context *ctx); +static enum libusb_error process_new_device (struct libusb_context *ctx, io_service_t service); #if defined(ENABLE_LOGGING) -static const char *darwin_error_str (int result) { +static const char *darwin_error_str (IOReturn result) { static char string_buffer[50]; switch (result) { case kIOReturnSuccess: @@ -130,7 +144,7 @@ static const char *darwin_error_str (int result) { } #endif -static int darwin_to_libusb (int result) { +static enum libusb_error darwin_to_libusb (IOReturn result) { switch (result) { case kIOReturnUnderrun: case kIOReturnSuccess: @@ -177,14 +191,14 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui /* current interface */ struct darwin_interface *cInterface; - int8_t i, iface; + uint8_t i, iface; usbi_dbg ("converting ep address 0x%02x to pipeRef and interface", ep); for (iface = 0 ; iface < USB_MAXINTERFACES ; iface++) { cInterface = &priv->interfaces[iface]; - if (dev_handle->claimed_interfaces & (1 << iface)) { + if (dev_handle->claimed_interfaces & (1U << iface)) { for (i = 0 ; i < cInterface->num_endpoints ; i++) { if (cInterface->endpoint_addrs[i] == ep) { *pipep = i + 1; @@ -196,7 +210,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui *interface_out = cInterface; usbi_dbg ("pipe %d on interface %d matches", *pipep, iface); - return 0; + return LIBUSB_SUCCESS; } } } @@ -208,7 +222,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui return LIBUSB_ERROR_NOT_FOUND; } -static int usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 location) { +static IOReturn usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 location) { CFMutableDictionaryRef matchingDict = IOServiceMatching(darwin_device_class); if (!matchingDict) @@ -219,44 +233,46 @@ static int usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 loca &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (propertyMatchDict) { - /* there are no unsigned CFNumber types so treat the value as signed. the os seems to do this - internally (CFNumberType of locationID is 3) */ - CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location); + /* there are no unsigned CFNumber types so treat the value as signed. the OS seems to do this + internally (CFNumberType of locationID is kCFNumberSInt32Type) */ + CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location); + if (propertyMatchDict && locationCF) { CFDictionarySetValue (propertyMatchDict, CFSTR(kUSBDevicePropertyLocationID), locationCF); - /* release our reference to the CFNumber (CFDictionarySetValue retains it) */ - CFRelease (locationCF); - CFDictionarySetValue (matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict); - /* release out reference to the CFMutableDictionaryRef (CFDictionarySetValue retains it) */ - CFRelease (propertyMatchDict); } /* else we can still proceed as long as the caller accounts for the possibility of other devices in the iterator */ + + /* release our references as per the Create Rule */ + if (propertyMatchDict) + CFRelease (propertyMatchDict); + if (locationCF) + CFRelease (locationCF); } return IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, deviceIterator); } /* Returns 1 on success, 0 on failure. */ -static int get_ioregistry_value_number (io_service_t service, CFStringRef property, CFNumberType type, void *p) { +static bool get_ioregistry_value_number (io_service_t service, CFStringRef property, CFNumberType type, void *p) { CFTypeRef cfNumber = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0); - int ret = 0; + Boolean success = 0; if (cfNumber) { if (CFGetTypeID(cfNumber) == CFNumberGetTypeID()) { - ret = CFNumberGetValue(cfNumber, type, p); + success = CFNumberGetValue(cfNumber, type, p); } CFRelease (cfNumber); } - return ret; + return (success != 0); } -static int get_ioregistry_value_data (io_service_t service, CFStringRef property, ssize_t size, void *p) { +/* Returns 1 on success, 0 on failure. */ +static bool get_ioregistry_value_data (io_service_t service, CFStringRef property, ssize_t size, void *p) { CFTypeRef cfData = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0); - int ret = 0; + bool success = false; if (cfData) { if (CFGetTypeID (cfData) == CFDataGetTypeID ()) { @@ -266,28 +282,42 @@ static int get_ioregistry_value_data (io_service_t service, CFStringRef property } CFDataGetBytes (cfData, CFRangeMake(0, size), p); - ret = 1; + success = true; } CFRelease (cfData); } - return ret; + return success; } static usb_device_t **darwin_device_from_service (io_service_t service) { io_cf_plugin_ref_t *plugInInterface = NULL; usb_device_t **device; - kern_return_t result; + IOReturn kresult; SInt32 score; + const int max_retries = 5; - result = IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID, - kIOCFPlugInInterfaceID, &plugInInterface, - &score); + /* The IOCreatePlugInInterfaceForService function might consistently return + an "out of resources" error with certain USB devices the first time we run + it. The reason is still unclear, but retrying fixes the problem */ + for (int count = 0; count < max_retries; count++) { + kresult = IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, &plugInInterface, + &score); + if (kIOReturnSuccess == kresult && plugInInterface) { + break; + } - if (kIOReturnSuccess != result || !plugInInterface) { - usbi_dbg ("could not set up plugin for service: %s", darwin_error_str (result)); + usbi_dbg ("set up plugin for service retry: %s", darwin_error_str (kresult)); + + /* sleep for a little while before trying again */ + nanosleep(&(struct timespec){.tv_sec = 0, .tv_nsec = 1000}, NULL); + } + + if (kIOReturnSuccess != kresult || !plugInInterface) { + usbi_dbg ("could not set up plugin for service: %s", darwin_error_str (kresult)); return NULL; } @@ -300,6 +330,7 @@ static usb_device_t **darwin_device_from_service (io_service_t service) } static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) { + UNUSED(ptr); struct libusb_context *ctx; io_service_t service; @@ -308,7 +339,7 @@ static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) { while ((service = IOIteratorNext(add_devices))) { /* add this device to each active context's device list */ list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { - process_new_device (ctx, service);; + process_new_device (ctx, service); } IOObjectRelease(service); @@ -318,6 +349,7 @@ static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) { } static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { + UNUSED(ptr); struct libusb_device *dev = NULL; struct libusb_context *ctx; struct darwin_cached_device *old_device; @@ -340,11 +372,20 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { usbi_mutex_lock(&darwin_cached_devices_lock); list_for_each_entry(old_device, &darwin_cached_devices, list, struct darwin_cached_device) { if (old_device->session == session) { - darwin_deref_cached_device (old_device); + if (old_device->in_reenumerate) { + /* device is re-enumerating. do not dereference the device at this time. libusb_reset_device() + * will deref if needed. */ + usbi_dbg ("detected device detatched due to re-enumeration"); + } else { + darwin_deref_cached_device (old_device); + } break; } } usbi_mutex_unlock(&darwin_cached_devices_lock); + if (old_device->in_reenumerate) { + continue; + } list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { usbi_dbg ("notifying context %p of device disconnect", ctx); @@ -364,8 +405,8 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { static void darwin_hotplug_poll (void) { - /* not sure if 5 seconds will be too long/short but it should work ok */ - mach_timespec_t timeout = {.tv_sec = 5, .tv_nsec = 0}; + /* not sure if 1 ms will be too long/short but it should work ok */ + mach_timespec_t timeout = {.tv_sec = 0, .tv_nsec = 1000000ul}; /* since a kernel thread may nodify the IOInterators used for * hotplug notidication we can't just clear the iterators. @@ -499,43 +540,24 @@ static void __attribute__((destructor)) _darwin_finalize(void) { usbi_mutex_unlock(&darwin_cached_devices_lock); } -static void darwin_check_version (void) { - /* adjust for changes in the USB stack in xnu 15 */ - int sysctl_args[] = {CTL_KERN, KERN_OSRELEASE}; - long version; - char version_string[256] = {'\0',}; - size_t length = 256; - - sysctl(sysctl_args, 2, version_string, &length, NULL, 0); - - errno = 0; - version = strtol (version_string, NULL, 10); - if (0 == errno && version >= 15) { - darwin_device_class = "IOUSBHostDevice"; - } -} - static int darwin_init(struct libusb_context *ctx) { - host_name_port_t host_self; int rc; - rc = pthread_once (&darwin_init_once, darwin_check_version); - if (rc) { - return LIBUSB_ERROR_OTHER; - } - rc = darwin_scan_devices (ctx); if (LIBUSB_SUCCESS != rc) { return rc; } if (libusb_darwin_atomic_fetch_add (&initCount, 1) == 0) { - /* create the clocks that will be used */ +#if !OSX_USE_CLOCK_GETTIME + /* create the clocks that will be used if clock_gettime() is not available */ + host_name_port_t host_self; host_self = mach_host_self(); host_get_clock_service(host_self, CALENDAR_CLOCK, &clock_realtime); host_get_clock_service(host_self, SYSTEM_CLOCK, &clock_monotonic); mach_port_deallocate(mach_task_self(), host_self); +#endif pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, ctx); @@ -548,10 +570,13 @@ static int darwin_init(struct libusb_context *ctx) { return rc; } -static void darwin_exit (void) { +static void darwin_exit (struct libusb_context *ctx) { + UNUSED(ctx); if (libusb_darwin_atomic_fetch_add (&initCount, -1) == 1) { +#if !OSX_USE_CLOCK_GETTIME mach_port_deallocate(mach_task_self(), clock_realtime); mach_port_deallocate(mach_task_self(), clock_monotonic); +#endif /* stop the event runloop and wait for the thread to terminate. */ CFRunLoopSourceSignal(libusb_darwin_acfls); @@ -568,7 +593,7 @@ static int darwin_get_device_descriptor(struct libusb_device *dev, unsigned char *host_endian = 0; - return 0; + return LIBUSB_SUCCESS; } static int get_configuration_index (struct libusb_device *dev, int config_value) { @@ -604,7 +629,8 @@ static int darwin_get_active_config_descriptor(struct libusb_device *dev, unsign if (config_index < 0) return config_index; - return darwin_get_config_descriptor (dev, config_index, buffer, len, host_endian); + assert(config_index >= 0 && config_index <= UINT8_MAX); + return darwin_get_config_descriptor (dev, (UInt8)config_index, buffer, len, host_endian); } static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) { @@ -636,12 +662,12 @@ static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t confi } /* check whether the os has configured the device */ -static int darwin_check_configuration (struct libusb_context *ctx, struct darwin_cached_device *dev) { +static enum libusb_error darwin_check_configuration (struct libusb_context *ctx, struct darwin_cached_device *dev) { usb_device_t **darwin_device = dev->device; IOUSBConfigurationDescriptorPtr configDesc; IOUSBFindInterfaceRequest request; - kern_return_t kresult; + IOReturn kresult; io_iterator_t interface_iterator; io_service_t firstInterface; @@ -655,7 +681,7 @@ static int darwin_check_configuration (struct libusb_context *ctx, struct darwin if (0x05ac == dev->dev_descriptor.idVendor && 0x8005 == dev->dev_descriptor.idProduct) { usbi_dbg ("ignoring configuration on root hub simulation"); dev->active_config = 0; - return 0; + return LIBUSB_SUCCESS; } /* find the first configuration */ @@ -673,7 +699,7 @@ static int darwin_check_configuration (struct libusb_context *ctx, struct darwin request.bAlternateSetting = kIOUSBFindInterfaceDontCare; kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator); - if (kresult) + if (kresult != kIOReturnSuccess) return darwin_to_libusb (kresult); /* iterate once */ @@ -698,20 +724,22 @@ static int darwin_check_configuration (struct libusb_context *ctx, struct darwin usbi_dbg ("active config: %u, first config: %u", dev->active_config, dev->first_config); - return 0; + return LIBUSB_SUCCESS; } -static int darwin_request_descriptor (usb_device_t **device, UInt8 desc, UInt8 desc_index, void *buffer, size_t buffer_size) { +static IOReturn darwin_request_descriptor (usb_device_t **device, UInt8 desc, UInt8 desc_index, void *buffer, size_t buffer_size) { IOUSBDevRequestTO req; + assert(buffer_size <= UINT16_MAX); + memset (buffer, 0, buffer_size); /* Set up request for descriptor/ */ req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); req.bRequest = kUSBRqGetDescriptor; - req.wValue = desc << 8; + req.wValue = (UInt16)(desc << 8); req.wIndex = desc_index; - req.wLength = buffer_size; + req.wLength = (UInt16)buffer_size; req.pData = buffer; req.noDataTimeout = 20; req.completionTimeout = 100; @@ -719,12 +747,13 @@ static int darwin_request_descriptor (usb_device_t **device, UInt8 desc, UInt8 d return (*device)->DeviceRequestTO (device, &req); } -static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct darwin_cached_device *dev) { +static enum libusb_error darwin_cache_device_descriptor (struct libusb_context *ctx, struct darwin_cached_device *dev) { usb_device_t **device = dev->device; - int retries = 1, delay = 30000; + int retries = 1; + long delay = 30000; // microseconds int unsuspended = 0, try_unsuspend = 1, try_reconfigure = 1; int is_open = 0; - int ret = 0, ret2; + IOReturn ret = 0, ret2; UInt8 bDeviceClass; UInt16 idProduct, idVendor; @@ -777,7 +806,7 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da (void)(*device)->GetUSBDeviceInformation (device, &info); /* note that the device was suspended */ - if (info & (1 << kUSBInformationDeviceIsSuspendedBit) || 0 == info) + if (info & (1U << kUSBInformationDeviceIsSuspendedBit) || 0 == info) try_unsuspend = 1; #endif @@ -796,9 +825,9 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da } if (kIOReturnSuccess != ret) { - usbi_dbg("kernel responded with code: 0x%08x. sleeping for %d ms before trying again", ret, delay/1000); + usbi_dbg("kernel responded with code: 0x%08x. sleeping for %ld ms before trying again", ret, delay/1000); /* sleep for a little while before trying again */ - nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL); + nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000}, NULL); } } while (kIOReturnSuccess != ret && retries--); @@ -848,17 +877,18 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da return LIBUSB_SUCCESS; } -static int get_device_port (io_service_t service, UInt8 *port) { - kern_return_t result; +/* Returns 1 on success, 0 on failure. */ +static bool get_device_port (io_service_t service, UInt8 *port) { + IOReturn kresult; io_service_t parent; - int ret = 0; + bool ret = false; if (get_ioregistry_value_number (service, CFSTR("PortNum"), kCFNumberSInt8Type, port)) { - return 1; + return true; } - result = IORegistryEntryGetParentEntry (service, kIOServicePlane, &parent); - if (kIOReturnSuccess == result) { + kresult = IORegistryEntryGetParentEntry (service, kIOServicePlane, &parent); + if (kIOReturnSuccess == kresult) { ret = get_ioregistry_value_data (parent, CFSTR("port"), 1, port); IOObjectRelease (parent); } @@ -866,29 +896,45 @@ static int get_device_port (io_service_t service, UInt8 *port) { return ret; } -static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t service, - struct darwin_cached_device **cached_out) { +/* Returns 1 on success, 0 on failure. */ +static bool get_device_parent_sessionID(io_service_t service, UInt64 *parent_sessionID) { + IOReturn kresult; + io_service_t parent; + + /* Walk up the tree in the IOService plane until we find a parent that has a sessionID */ + parent = service; + while((kresult = IORegistryEntryGetParentEntry (parent, kIOUSBPlane, &parent)) == kIOReturnSuccess) { + if (get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, parent_sessionID)) { + /* Success */ + return true; + } + } + + /* We ran out of parents */ + return false; +} + +static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io_service_t service, + struct darwin_cached_device **cached_out) { struct darwin_cached_device *new_device; UInt64 sessionID = 0, parent_sessionID = 0; - int ret = LIBUSB_SUCCESS; + UInt32 locationID = 0; + enum libusb_error ret = LIBUSB_SUCCESS; usb_device_t **device; - io_service_t parent; - kern_return_t result; UInt8 port = 0; + bool reuse_device = false; /* get some info from the io registry */ (void) get_ioregistry_value_number (service, CFSTR("sessionID"), kCFNumberSInt64Type, &sessionID); + (void) get_ioregistry_value_number (service, CFSTR("locationID"), kCFNumberSInt32Type, &locationID); if (!get_device_port (service, &port)) { usbi_dbg("could not get connected port number"); } usbi_dbg("finding cached device for sessionID 0x%" PRIx64, sessionID); - result = IORegistryEntryGetParentEntry (service, kIOUSBPlane, &parent); - - if (kIOReturnSuccess == result) { - (void) get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, &parent_sessionID); - IOObjectRelease(parent); + if (get_device_parent_sessionID(service, &parent_sessionID)) { + usbi_dbg("parent sessionID: 0x%" PRIx64, parent_sessionID); } usbi_mutex_lock(&darwin_cached_devices_lock); @@ -896,7 +942,15 @@ static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t ser *cached_out = NULL; list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) { - usbi_dbg("matching sessionID 0x%" PRIx64 " against cached device with sessionID 0x%" PRIx64, sessionID, new_device->session); + usbi_dbg("matching sessionID/locationID 0x%" PRIx64 "/0x%x against cached device with sessionID/locationID 0x%" PRIx64 "/0x%x", + sessionID, locationID, new_device->session, new_device->location); + if (new_device->location == locationID && new_device->in_reenumerate) { + usbi_dbg ("found cached device with matching location that is being re-enumerated"); + new_device->session = sessionID; + reuse_device = true; + break; + } + if (new_device->session == sessionID) { usbi_dbg("using cached device for device"); *cached_out = new_device; @@ -915,25 +969,28 @@ static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t ser break; } - new_device = calloc (1, sizeof (*new_device)); - if (!new_device) { - ret = LIBUSB_ERROR_NO_MEM; - break; + if (!reuse_device) { + new_device = calloc (1, sizeof (*new_device)); + if (!new_device) { + ret = LIBUSB_ERROR_NO_MEM; + break; + } + + /* add this device to the cached device list */ + list_add(&new_device->list, &darwin_cached_devices); + + (*device)->GetDeviceAddress (device, (USBDeviceAddress *)&new_device->address); + + /* keep a reference to this device */ + darwin_ref_cached_device(new_device); + + new_device->session = sessionID; + (*device)->GetLocationID (device, &new_device->location); + new_device->port = port; + new_device->parent_session = parent_sessionID; } - /* add this device to the cached device list */ - list_add(&new_device->list, &darwin_cached_devices); - - (*device)->GetDeviceAddress (device, (USBDeviceAddress *)&new_device->address); - - /* keep a reference to this device */ - darwin_ref_cached_device(new_device); - new_device->device = device; - new_device->session = sessionID; - (*device)->GetLocationID (device, &new_device->location); - new_device->port = port; - new_device->parent_session = parent_sessionID; /* cache the device descriptor */ ret = darwin_cache_device_descriptor(ctx, new_device); @@ -957,16 +1014,15 @@ static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t ser return ret; } -static int process_new_device (struct libusb_context *ctx, io_service_t service) { +static enum libusb_error process_new_device (struct libusb_context *ctx, io_service_t service) { struct darwin_device_priv *priv; struct libusb_device *dev = NULL; struct darwin_cached_device *cached_device; UInt8 devSpeed; - int ret = 0; + enum libusb_error ret = LIBUSB_SUCCESS; do { ret = darwin_get_cached_device (ctx, service, &cached_device); - if (ret < 0 || !cached_device->can_enumerate) { return ret; } @@ -997,7 +1053,8 @@ static int process_new_device (struct libusb_context *ctx, io_service_t service) } dev->port_number = cached_device->port; dev->bus_number = cached_device->location >> 24; - dev->device_address = cached_device->address; + assert(cached_device->address <= UINT8_MAX); + dev->device_address = (uint8_t)cached_device->address; (*(priv->dev->device))->GetDeviceSpeed (priv->dev->device, &devSpeed); @@ -1005,8 +1062,11 @@ static int process_new_device (struct libusb_context *ctx, io_service_t service) case kUSBDeviceSpeedLow: dev->speed = LIBUSB_SPEED_LOW; break; case kUSBDeviceSpeedFull: dev->speed = LIBUSB_SPEED_FULL; break; case kUSBDeviceSpeedHigh: dev->speed = LIBUSB_SPEED_HIGH; break; -#if DeviceVersion >= 500 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 case kUSBDeviceSpeedSuper: dev->speed = LIBUSB_SPEED_SUPER; break; +#endif +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 + case kUSBDeviceSpeedSuperPlus: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break; #endif default: usbi_warn (ctx, "Got unknown device speed %d", devSpeed); @@ -1018,9 +1078,13 @@ static int process_new_device (struct libusb_context *ctx, io_service_t service) usbi_dbg ("found device with address %d port = %d parent = %p at %p", dev->device_address, dev->port_number, (void *) dev->parent_dev, priv->dev->sys_path); + } while (0); - if (0 == ret) { + if (cached_device->in_reenumerate) { + usbi_dbg ("cached device in reset state. reset complete..."); + cached_device->in_reenumerate = false; + } else if (0 == ret) { usbi_connect_device (dev); } else { libusb_unref_device (dev); @@ -1029,10 +1093,10 @@ static int process_new_device (struct libusb_context *ctx, io_service_t service) return ret; } -static int darwin_scan_devices(struct libusb_context *ctx) { +static enum libusb_error darwin_scan_devices(struct libusb_context *ctx) { io_iterator_t deviceIterator; io_service_t service; - kern_return_t kresult; + IOReturn kresult; kresult = usb_setup_device_iterator (&deviceIterator, 0); if (kresult != kIOReturnSuccess) @@ -1046,7 +1110,7 @@ static int darwin_scan_devices(struct libusb_context *ctx) { IOObjectRelease(deviceIterator); - return 0; + return LIBUSB_SUCCESS; } static int darwin_open (struct libusb_device_handle *dev_handle) { @@ -1065,9 +1129,9 @@ static int darwin_open (struct libusb_device_handle *dev_handle) { } /* it is possible to perform some actions on a device that is not open so do not return an error */ - priv->is_open = 0; + priv->is_open = false; } else { - priv->is_open = 1; + priv->is_open = true; } /* create async event source */ @@ -1079,7 +1143,7 @@ static int darwin_open (struct libusb_device_handle *dev_handle) { (*(dpriv->device))->USBDeviceClose (dpriv->device); } - priv->is_open = 0; + priv->is_open = false; return darwin_to_libusb (kresult); } @@ -1114,7 +1178,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) { /* make sure all interfaces are released */ for (i = 0 ; i < USB_MAXINTERFACES ; i++) - if (dev_handle->claimed_interfaces & (1 << i)) + if (dev_handle->claimed_interfaces & (1U << i)) libusb_release_interface (dev_handle, i); if (0 == dpriv->open_count) { @@ -1129,7 +1193,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) { if (priv->is_open) { /* close the device */ kresult = (*(dpriv->device))->USBDeviceClose(dpriv->device); - if (kresult) { + if (kresult != kIOReturnSuccess) { /* Log the fact that we had a problem closing the file, however failing a * close isn't really an error, so return success anyway */ usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceClose: %s", darwin_error_str(kresult)); @@ -1143,40 +1207,42 @@ static int darwin_get_configuration(struct libusb_device_handle *dev_handle, int *config = (int) dpriv->active_config; - return 0; + return LIBUSB_SUCCESS; } -static int darwin_set_configuration(struct libusb_device_handle *dev_handle, int config) { +static enum libusb_error darwin_set_configuration(struct libusb_device_handle *dev_handle, int config) { struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); IOReturn kresult; int i; + assert(config >= 0 && config <= UINT8_MAX); + /* Setting configuration will invalidate the interface, so we need to reclaim it. First, dispose of existing interfaces, if any. */ for (i = 0 ; i < USB_MAXINTERFACES ; i++) - if (dev_handle->claimed_interfaces & (1 << i)) + if (dev_handle->claimed_interfaces & (1U << i)) darwin_release_interface (dev_handle, i); - kresult = (*(dpriv->device))->SetConfiguration (dpriv->device, config); + kresult = (*(dpriv->device))->SetConfiguration (dpriv->device, (UInt8)config); if (kresult != kIOReturnSuccess) return darwin_to_libusb (kresult); /* Reclaim any interfaces. */ for (i = 0 ; i < USB_MAXINTERFACES ; i++) - if (dev_handle->claimed_interfaces & (1 << i)) + if (dev_handle->claimed_interfaces & (1U << i)) darwin_claim_interface (dev_handle, i); - dpriv->active_config = config; + dpriv->active_config = (UInt8)config; - return 0; + return LIBUSB_SUCCESS; } -static int darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_service_t *usbInterfacep) { +static IOReturn darwin_get_interface (usb_device_t **darwin_device, int ifc, io_service_t *usbInterfacep) { IOUSBFindInterfaceRequest request; - kern_return_t kresult; + IOReturn kresult; io_iterator_t interface_iterator; UInt8 bInterfaceNumber; - int ret; + bool ret; *usbInterfacep = IO_OBJECT_NULL; @@ -1187,7 +1253,7 @@ static int darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_s request.bAlternateSetting = kIOUSBFindInterfaceDontCare; kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator); - if (kresult) + if (kresult != kIOReturnSuccess) return kresult; while ((*usbInterfacep = IOIteratorNext(interface_iterator))) { @@ -1205,33 +1271,33 @@ static int darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_s /* done with the interface iterator */ IOObjectRelease(interface_iterator); - return 0; + return kIOReturnSuccess; } -static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) { +static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle, int iface) { struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; /* current interface */ struct darwin_interface *cInterface = &priv->interfaces[iface]; - kern_return_t kresult; + IOReturn kresult; - u_int8_t numep, direction, number; - u_int8_t dont_care1, dont_care3; - u_int16_t dont_care2; + UInt8 numep, direction, number; + UInt8 dont_care1, dont_care3; + UInt16 dont_care2; int rc; usbi_dbg ("building table of endpoints."); /* retrieve the total number of endpoints on this interface */ kresult = (*(cInterface->interface))->GetNumEndpoints(cInterface->interface, &numep); - if (kresult) { + if (kresult != kIOReturnSuccess) { usbi_err (HANDLE_CTX (dev_handle), "can't get number of endpoints for interface: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } /* iterate through pipe references */ - for (int i = 1 ; i <= numep ; i++) { + for (UInt8 i = 1 ; i <= numep ; i++) { kresult = (*(cInterface->interface))->GetPipeProperties(cInterface->interface, i, &direction, &number, &dont_care1, &dont_care2, &dont_care3); @@ -1242,7 +1308,7 @@ static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) { UInt8 alt_setting; kresult = (*(cInterface->interface))->GetAlternateSetting (cInterface->interface, &alt_setting); - if (kresult) { + if (kresult != kIOReturnSuccess) { usbi_err (HANDLE_CTX (dev_handle), "can't get alternate setting for interface"); return darwin_to_libusb (kresult); } @@ -1256,7 +1322,7 @@ static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) { cInterface->endpoint_addrs[i - 1] = endpoint_desc->bEndpointAddress; } else { - cInterface->endpoint_addrs[i - 1] = (((kUSBIn == direction) << kUSBRqDirnShift) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK)); + cInterface->endpoint_addrs[i - 1] = (UInt8)(((kUSBIn == direction) << kUSBRqDirnShift) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK)); } usbi_dbg ("interface: %i pipe %i: dir: %i number: %i", iface, i, cInterface->endpoint_addrs[i - 1] >> kUSBRqDirnShift, @@ -1265,21 +1331,24 @@ static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) { cInterface->num_endpoints = numep; - return 0; + return LIBUSB_SUCCESS; } static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int iface) { struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; io_service_t usbInterface = IO_OBJECT_NULL; - IOReturn kresult; + IOReturn kresult; + enum libusb_error ret; IOCFPlugInInterface **plugInInterface = NULL; SInt32 score; + assert(iface >= 0 && iface <= UINT8_MAX); + /* current interface */ struct darwin_interface *cInterface = &priv->interfaces[iface]; - kresult = darwin_get_interface (dpriv->device, iface, &usbInterface); + kresult = darwin_get_interface (dpriv->device, (uint8_t)iface, &usbInterface); if (kresult != kIOReturnSuccess) return darwin_to_libusb (kresult); @@ -1288,14 +1357,14 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i usbi_info (HANDLE_CTX (dev_handle), "no interface found; setting configuration: %d", dpriv->first_config); /* set the configuration */ - kresult = darwin_set_configuration (dev_handle, dpriv->first_config); - if (kresult != LIBUSB_SUCCESS) { + ret = darwin_set_configuration (dev_handle, dpriv->first_config); + if (ret != LIBUSB_SUCCESS) { usbi_err (HANDLE_CTX (dev_handle), "could not set configuration"); - return kresult; + return ret; } - kresult = darwin_get_interface (dpriv->device, iface, &usbInterface); - if (kresult) { + kresult = darwin_get_interface (dpriv->device, (uint8_t)iface, &usbInterface); + if (kresult != kIOReturnSuccess) { usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } @@ -1313,7 +1382,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i /* ignore release error */ (void)IOObjectRelease (usbInterface); - if (kresult) { + if (kresult != kIOReturnSuccess) { usbi_err (HANDLE_CTX (dev_handle), "IOCreatePlugInInterfaceForService: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } @@ -1325,30 +1394,30 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i /* Do the actual claim */ kresult = (*plugInInterface)->QueryInterface(plugInInterface, - CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), + CFUUIDGetUUIDBytes(InterfaceInterfaceID), (LPVOID)&cInterface->interface); /* We no longer need the intermediate plug-in */ /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */ (*plugInInterface)->Release (plugInInterface); - if (kresult || !cInterface->interface) { + if (kresult != kIOReturnSuccess || !cInterface->interface) { usbi_err (HANDLE_CTX (dev_handle), "QueryInterface: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } /* claim the interface */ kresult = (*(cInterface->interface))->USBInterfaceOpen(cInterface->interface); - if (kresult) { + if (kresult != kIOReturnSuccess) { usbi_err (HANDLE_CTX (dev_handle), "USBInterfaceOpen: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } /* update list of endpoints */ - kresult = get_endpoints (dev_handle, iface); - if (kresult) { + ret = get_endpoints (dev_handle, iface); + if (ret) { /* this should not happen */ darwin_release_interface (dev_handle, iface); usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table"); - return kresult; + return ret; } cInterface->cfSource = NULL; @@ -1369,7 +1438,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i usbi_dbg ("interface opened"); - return 0; + return LIBUSB_SUCCESS; } static int darwin_release_interface(struct libusb_device_handle *dev_handle, int iface) { @@ -1393,7 +1462,7 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, int } kresult = (*(cInterface->interface))->USBInterfaceClose(cInterface->interface); - if (kresult) + if (kresult != kIOReturnSuccess) usbi_warn (HANDLE_CTX (dev_handle), "USBInterfaceClose: %s", darwin_error_str(kresult)); kresult = (*(cInterface->interface))->Release(cInterface->interface); @@ -1408,6 +1477,7 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, int static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) { struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; IOReturn kresult; + enum libusb_error ret; /* current interface */ struct darwin_interface *cInterface = &priv->interfaces[iface]; @@ -1415,17 +1485,18 @@ static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_hand if (!cInterface->interface) return LIBUSB_ERROR_NO_DEVICE; - kresult = (*(cInterface->interface))->SetAlternateInterface (cInterface->interface, altsetting); + assert(altsetting >= 0 && altsetting <= UINT8_MAX); + kresult = (*(cInterface->interface))->SetAlternateInterface (cInterface->interface, (UInt8)altsetting); if (kresult != kIOReturnSuccess) darwin_reset_device (dev_handle); /* update list of endpoints */ - kresult = get_endpoints (dev_handle, iface); - if (kresult) { + ret = get_endpoints (dev_handle, iface); + if (ret) { /* this should not happen */ darwin_release_interface (dev_handle, iface); usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table"); - return kresult; + return ret; } return darwin_to_libusb (kresult); @@ -1446,72 +1517,144 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c /* newer versions of darwin support clearing additional bits on the device's endpoint */ kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef); - if (kresult) + if (kresult != kIOReturnSuccess) usbi_warn (HANDLE_CTX (dev_handle), "ClearPipeStall: %s", darwin_error_str (kresult)); return darwin_to_libusb (kresult); } -static int darwin_reset_device(struct libusb_device_handle *dev_handle) { +static int darwin_restore_state (struct libusb_device_handle *dev_handle, int8_t active_config, + unsigned long claimed_interfaces) { struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); - IOUSBDeviceDescriptor descriptor; - IOUSBConfigurationDescriptorPtr cached_configuration; - IOUSBConfigurationDescriptor configuration; - bool reenumerate = false; - IOReturn kresult; - int i; + struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; + int open_count = dpriv->open_count; + int ret; - kresult = (*(dpriv->device))->ResetDevice (dpriv->device); - if (kresult) { - usbi_err (HANDLE_CTX (dev_handle), "ResetDevice: %s", darwin_error_str (kresult)); - return darwin_to_libusb (kresult); - } + /* clear claimed interfaces temporarily */ + dev_handle->claimed_interfaces = 0; - do { - usbi_dbg ("darwin/reset_device: checking if device descriptor changed"); + /* close and re-open the device */ + priv->is_open = false; + dpriv->open_count = 1; - /* ignore return code. if we can't get a descriptor it might be worthwhile re-enumerating anway */ - (void) darwin_request_descriptor (dpriv->device, kUSBDeviceDesc, 0, &descriptor, sizeof (descriptor)); + /* clean up open interfaces */ + (void) darwin_close (dev_handle); - /* check if the device descriptor has changed */ - if (0 != memcmp (&dpriv->dev_descriptor, &descriptor, sizeof (descriptor))) { - reenumerate = true; - break; - } - - /* check if any configuration descriptor has changed */ - for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) { - usbi_dbg ("darwin/reset_device: checking if configuration descriptor %d changed", i); - - (void) darwin_request_descriptor (dpriv->device, kUSBConfDesc, i, &configuration, sizeof (configuration)); - (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration); - - if (!cached_configuration || 0 != memcmp (cached_configuration, &configuration, sizeof (configuration))) { - reenumerate = true; - break; - } - } - } while (0); - - if (reenumerate) { - usbi_dbg ("darwin/reset_device: device requires reenumeration"); - (void) (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device, 0); + /* re-open the device */ + ret = darwin_open (dev_handle); + dpriv->open_count = open_count; + if (LIBUSB_SUCCESS != ret) { + /* could not restore configuration */ return LIBUSB_ERROR_NOT_FOUND; } - usbi_dbg ("darwin/reset_device: device reset complete"); + if (dpriv->active_config != active_config) { + usbi_dbg ("darwin/restore_state: restoring configuration %d...", active_config); + + ret = darwin_set_configuration (dev_handle, active_config); + if (LIBUSB_SUCCESS != ret) { + usbi_dbg ("darwin/restore_state: could not restore configuration"); + return LIBUSB_ERROR_NOT_FOUND; + } + } + + usbi_dbg ("darwin/restore_state: reclaiming interfaces"); + + if (claimed_interfaces) { + for (int iface = 0 ; iface < USB_MAXINTERFACES ; ++iface) { + if (!(claimed_interfaces & (1U << iface))) { + continue; + } + + usbi_dbg ("darwin/restore_state: re-claiming interface %d", iface); + + ret = darwin_claim_interface (dev_handle, iface); + if (LIBUSB_SUCCESS != ret) { + usbi_dbg ("darwin/restore_state: could not claim interface %d", iface); + return LIBUSB_ERROR_NOT_FOUND; + } + + dev_handle->claimed_interfaces |= 1U << iface; + } + } + + usbi_dbg ("darwin/restore_state: device state restored"); return LIBUSB_SUCCESS; } +static int darwin_reset_device(struct libusb_device_handle *dev_handle) { + struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); + unsigned long claimed_interfaces = dev_handle->claimed_interfaces; + int8_t active_config = dpriv->active_config; + IOUSBDeviceDescriptor descriptor; + IOUSBConfigurationDescriptorPtr cached_configuration; + IOUSBConfigurationDescriptor *cached_configurations; + IOReturn kresult; + UInt8 i; + + if (dpriv->in_reenumerate) { + /* ack, two (or more) threads are trying to reset the device! abort! */ + return LIBUSB_ERROR_NOT_FOUND; + } + + dpriv->in_reenumerate = true; + + /* store copies of descriptors so they can be compared after the reset */ + memcpy (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor)); + cached_configurations = alloca (sizeof (*cached_configurations) * descriptor.bNumConfigurations); + + for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) { + (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration); + memcpy (cached_configurations + i, cached_configuration, sizeof (cached_configurations[i])); + } + + /* from macOS 10.11 ResetDevice no longer does anything so just use USBDeviceReEnumerate */ + kresult = (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device, 0); + if (kresult != kIOReturnSuccess) { + usbi_err (HANDLE_CTX (dev_handle), "USBDeviceReEnumerate: %s", darwin_error_str (kresult)); + dpriv->in_reenumerate = false; + return darwin_to_libusb (kresult); + } + + usbi_dbg ("darwin/reset_device: waiting for re-enumeration to complete..."); + + while (dpriv->in_reenumerate) { + struct timespec delay = {.tv_sec = 0, .tv_nsec = 1000}; + nanosleep (&delay, NULL); + } + + /* compare descriptors */ + usbi_dbg ("darwin/reset_device: checking whether descriptors changed"); + + if (memcmp (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor))) { + /* device descriptor changed. need to return not found. */ + usbi_dbg ("darwin/reset_device: device descriptor changed"); + return LIBUSB_ERROR_NOT_FOUND; + } + + for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) { + (void) (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration); + if (memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i]))) { + usbi_dbg ("darwin/reset_device: configuration descriptor %d changed", i); + return LIBUSB_ERROR_NOT_FOUND; + } + } + + usbi_dbg ("darwin/reset_device: device reset complete. restoring state..."); + + return darwin_restore_state (dev_handle, active_config, claimed_interfaces); +} + static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle, int interface) { struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); io_service_t usbInterface; CFTypeRef driver; IOReturn kresult; - kresult = darwin_get_interface (dpriv->device, interface, &usbInterface); - if (kresult) { + assert(interface >= 0 && interface <= UINT8_MAX); + kresult = darwin_get_interface (dpriv->device, (uint8_t)interface, &usbInterface); + if (kresult != kIOReturnSuccess) { usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); @@ -1591,21 +1734,21 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) { if (transferType == kUSBInterrupt) { if (IS_XFERIN(transfer)) ret = (*(cInterface->interface))->ReadPipeAsync(cInterface->interface, pipeRef, transfer->buffer, - transfer->length, darwin_async_io_callback, itransfer); + (UInt32)transfer->length, darwin_async_io_callback, itransfer); else ret = (*(cInterface->interface))->WritePipeAsync(cInterface->interface, pipeRef, transfer->buffer, - transfer->length, darwin_async_io_callback, itransfer); + (UInt32)transfer->length, darwin_async_io_callback, itransfer); } else { itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; if (IS_XFERIN(transfer)) ret = (*(cInterface->interface))->ReadPipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer, - transfer->length, transfer->timeout, transfer->timeout, - darwin_async_io_callback, (void *)itransfer); + (UInt32)transfer->length, transfer->timeout, transfer->timeout, + darwin_async_io_callback, itransfer); else ret = (*(cInterface->interface))->WritePipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer, - transfer->length, transfer->timeout, transfer->timeout, - darwin_async_io_callback, (void *)itransfer); + (UInt32)transfer->length, transfer->timeout, transfer->timeout, + darwin_async_io_callback, itransfer); } if (ret) @@ -1632,12 +1775,12 @@ static int submit_stream_transfer(struct usbi_transfer *itransfer) { if (IS_XFERIN(transfer)) ret = (*(cInterface->interface))->ReadStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id, - transfer->buffer, transfer->length, transfer->timeout, - transfer->timeout, darwin_async_io_callback, (void *)itransfer); + transfer->buffer, (UInt32)transfer->length, transfer->timeout, + transfer->timeout, darwin_async_io_callback, itransfer); else ret = (*(cInterface->interface))->WriteStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id, - transfer->buffer, transfer->length, transfer->timeout, - transfer->timeout, darwin_async_io_callback, (void *)itransfer); + transfer->buffer, (UInt32)transfer->length, transfer->timeout, + transfer->timeout, darwin_async_io_callback, itransfer); if (ret) usbi_err (TRANSFER_CTX (transfer), "bulk stream transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out", @@ -1660,22 +1803,25 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { struct darwin_interface *cInterface; - /* construct an array of IOUSBIsocFrames, reuse the old one if possible */ - if (tpriv->isoc_framelist && tpriv->num_iso_packets != transfer->num_iso_packets) { + /* construct an array of IOUSBIsocFrames, reuse the old one if the sizes are the same */ + if (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)); + tpriv->isoc_framelist = (IOUSBIsocFrame*) calloc ((size_t)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++) - tpriv->isoc_framelist[i].frReqCount = transfer->iso_packet_desc[i].length; + for (i = 0 ; i < transfer->num_iso_packets ; i++) { + unsigned int length = transfer->iso_packet_desc[i].length; + assert(length <= UINT16_MAX); + tpriv->isoc_framelist[i].frReqCount = (UInt16)length; + } /* determine the interface/endpoint to use */ if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) { @@ -1690,7 +1836,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { /* Last but not least we need the bus frame number */ kresult = (*(cInterface->interface))->GetBusFrameNumber(cInterface->interface, &frame, &atTime); - if (kresult) { + if (kresult != kIOReturnSuccess) { usbi_err (TRANSFER_CTX (transfer), "failed to get bus frame number: %d", kresult); free(tpriv->isoc_framelist); tpriv->isoc_framelist = NULL; @@ -1710,19 +1856,19 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { /* submit the request */ if (IS_XFERIN(transfer)) kresult = (*(cInterface->interface))->ReadIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame, - transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback, + (UInt32)transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback, itransfer); else kresult = (*(cInterface->interface))->WriteIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame, - transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback, + (UInt32)transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback, itransfer); if (LIBUSB_SPEED_FULL == transfer->dev_handle->dev->speed) /* Full speed */ - cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets * (1 << (interval - 1)); + cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (interval - 1)); else /* High/super speed */ - cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets * (1 << (interval - 1)) / 8; + cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (interval - 1)) / 8; if (kresult != kIOReturnSuccess) { usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", IS_XFERIN(transfer) ? "In" : "Out", @@ -1742,7 +1888,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) { IOReturn kresult; - bzero(&tpriv->req, sizeof(tpriv->req)); + memset(&tpriv->req, 0, sizeof(tpriv->req)); /* IOUSBDeviceInterface expects the request in cpu endianness */ tpriv->req.bmRequestType = setup->bmRequestType; @@ -1904,7 +2050,7 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) usbi_signal_transfer_completion(itransfer); } -static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_t result) { +static enum libusb_transfer_status darwin_transfer_status (struct usbi_transfer *itransfer, IOReturn result) { if (itransfer->timeout_flags & USBI_TRANSFER_TIMED_OUT) result = kIOUSBTransactionTimeout; @@ -1933,10 +2079,10 @@ static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_ static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - int isIsoc = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type; - int isBulk = LIBUSB_TRANSFER_TYPE_BULK == transfer->type; - int isControl = LIBUSB_TRANSFER_TYPE_CONTROL == transfer->type; - int isInterrupt = LIBUSB_TRANSFER_TYPE_INTERRUPT == transfer->type; + bool isIsoc = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type; + bool isBulk = LIBUSB_TRANSFER_TYPE_BULK == transfer->type; + bool isControl = LIBUSB_TRANSFER_TYPE_CONTROL == transfer->type; + bool isInterrupt = LIBUSB_TRANSFER_TYPE_INTERRUPT == transfer->type; int i; if (!isIsoc && !isBulk && !isControl && !isInterrupt) { @@ -1953,7 +2099,7 @@ static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) { for (i = 0; i < transfer->num_iso_packets ; i++) { struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i]; - lib_desc->status = darwin_to_libusb (tpriv->isoc_framelist[i].frStatus); + lib_desc->status = darwin_transfer_status (itransfer, tpriv->isoc_framelist[i].frStatus); lib_desc->actual_length = tpriv->isoc_framelist[i].frActCount; } } else if (!isIsoc) @@ -1965,6 +2111,7 @@ static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) { } static int darwin_clock_gettime(int clk_id, struct timespec *tp) { +#if !OSX_USE_CLOCK_GETTIME mach_timespec_t sys_time; clock_serv_t clock_ref; @@ -1986,7 +2133,17 @@ static int darwin_clock_gettime(int clk_id, struct timespec *tp) { tp->tv_sec = sys_time.tv_sec; tp->tv_nsec = sys_time.tv_nsec; - return 0; + return LIBUSB_SUCCESS; +#else + switch (clk_id) { + case USBI_CLOCK_MONOTONIC: + return clock_gettime(CLOCK_MONOTONIC, tp); + case USBI_CLOCK_REALTIME: + return clock_gettime(CLOCK_REALTIME, tp); + default: + return LIBUSB_ERROR_INVALID_PARAM; + } +#endif } #if InterfaceVersion >= 550 @@ -2021,7 +2178,8 @@ static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32 return darwin_to_libusb(rc); } - return num_streams; + assert(num_streams <= INT_MAX); + return (int)num_streams; } static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigned char *endpoints, int num_endpoints) { @@ -2047,7 +2205,7 @@ static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigne } #endif -const struct usbi_os_backend darwin_backend = { +const struct usbi_os_backend usbi_backend = { .name = "Darwin", .caps = 0, .init = darwin_init, diff --git a/Externals/libusb/libusb/os/darwin_usb.h b/Externals/libusb/libusb/os/darwin_usb.h index 118043421a..3d76baf1cf 100644 --- a/Externals/libusb/libusb/os/darwin_usb.h +++ b/Externals/libusb/libusb/os/darwin_usb.h @@ -1,6 +1,7 @@ /* * darwin backend for libusb 1.0 - * Copyright © 2008-2015 Nathan Hjelm + * Copyright © 2008-2019 Nathan Hjelm + * Copyright © 2019 Google LLC. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,6 +21,8 @@ #if !defined(LIBUSB_DARWIN_H) #define LIBUSB_DARWIN_H +#include + #include "libusbi.h" #include @@ -28,37 +31,58 @@ #include /* IOUSBInterfaceInferface */ -#if defined (kIOUSBInterfaceInterfaceID700) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9 + +/* New in OS 10.12.0. */ +#if defined (kIOUSBInterfaceInterfaceID800) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) + +#define usb_interface_t IOUSBInterfaceInterface800 +#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID800 +#define InterfaceVersion 800 + +/* New in OS 10.10.0. */ +#elif defined (kIOUSBInterfaceInterfaceID700) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101000) #define usb_interface_t IOUSBInterfaceInterface700 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID700 #define InterfaceVersion 700 -#elif defined (kIOUSBInterfaceInterfaceID550) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9 +/* New in OS 10.9.0. */ +#elif defined (kIOUSBInterfaceInterfaceID650) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) + +#define usb_interface_t IOUSBInterfaceInterface650 +#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID650 +#define InterfaceVersion 650 + +/* New in OS 10.8.2 but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBInterfaceInterfaceID550) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) #define usb_interface_t IOUSBInterfaceInterface550 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID550 #define InterfaceVersion 550 -#elif defined (kIOUSBInterfaceInterfaceID500) +/* New in OS 10.7.3 but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBInterfaceInterfaceID500) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) #define usb_interface_t IOUSBInterfaceInterface500 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID500 #define InterfaceVersion 500 -#elif defined (kIOUSBInterfaceInterfaceID300) +/* New in OS 10.5.0. */ +#elif defined (kIOUSBInterfaceInterfaceID300) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) #define usb_interface_t IOUSBInterfaceInterface300 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID300 #define InterfaceVersion 300 -#elif defined (kIOUSBInterfaceInterfaceID245) +/* New in OS 10.4.5 (or 10.4.6?) but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBInterfaceInterfaceID245) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) #define usb_interface_t IOUSBInterfaceInterface245 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID245 #define InterfaceVersion 245 -#elif defined (kIOUSBInterfaceInterfaceID220) +/* New in OS 10.4.0. */ +#elif defined (kIOUSBInterfaceInterfaceID220) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1040) #define usb_interface_t IOUSBInterfaceInterface220 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220 @@ -66,43 +90,57 @@ #else -#error "IOUSBFamily is too old. Please upgrade your OS" +#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target" #endif /* IOUSBDeviceInterface */ -#if defined (kIOUSBDeviceInterfaceID500) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9 + +/* New in OS 10.9.0. */ +#if defined (kIOUSBDeviceInterfaceID650) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) + +#define usb_device_t IOUSBDeviceInterface650 +#define DeviceInterfaceID kIOUSBDeviceInterfaceID650 +#define DeviceVersion 650 + +/* New in OS 10.7.3 but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBDeviceInterfaceID500) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) #define usb_device_t IOUSBDeviceInterface500 #define DeviceInterfaceID kIOUSBDeviceInterfaceID500 #define DeviceVersion 500 -#elif defined (kIOUSBDeviceInterfaceID320) +/* New in OS 10.5.4 but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBDeviceInterfaceID320) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1060) #define usb_device_t IOUSBDeviceInterface320 #define DeviceInterfaceID kIOUSBDeviceInterfaceID320 #define DeviceVersion 320 -#elif defined (kIOUSBDeviceInterfaceID300) +/* New in OS 10.5.0. */ +#elif defined (kIOUSBDeviceInterfaceID300) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) #define usb_device_t IOUSBDeviceInterface300 #define DeviceInterfaceID kIOUSBDeviceInterfaceID300 #define DeviceVersion 300 -#elif defined (kIOUSBDeviceInterfaceID245) +/* New in OS 10.4.5 (or 10.4.6?) but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBDeviceInterfaceID245) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) #define usb_device_t IOUSBDeviceInterface245 #define DeviceInterfaceID kIOUSBDeviceInterfaceID245 #define DeviceVersion 245 -#elif defined (kIOUSBDeviceInterfaceID220) +/* New in OS 10.2.3 but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBDeviceInterfaceID197) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1030) + #define usb_device_t IOUSBDeviceInterface197 #define DeviceInterfaceID kIOUSBDeviceInterfaceID197 #define DeviceVersion 197 #else -#error "IOUSBFamily is too old. Please upgrade your OS" +#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target" #endif @@ -120,13 +158,14 @@ struct darwin_cached_device { UInt32 location; UInt64 parent_session; UInt64 session; - UInt16 address; + USBDeviceAddress address; char sys_path[21]; usb_device_t **device; int open_count; UInt8 first_config, active_config, port; int can_enumerate; int refcount; + bool in_reenumerate; }; struct darwin_device_priv { @@ -134,7 +173,7 @@ struct darwin_device_priv { }; struct darwin_device_handle_priv { - int is_open; + bool is_open; CFRunLoopSourceRef cfSource; struct darwin_interface { diff --git a/Externals/libusb/libusb/os/haiku_usb_backend.cpp b/Externals/libusb/libusb/os/haiku_usb_backend.cpp index d3de8cc080..01fba25e1a 100644 --- a/Externals/libusb/libusb/os/haiku_usb_backend.cpp +++ b/Externals/libusb/libusb/os/haiku_usb_backend.cpp @@ -243,7 +243,7 @@ USBDeviceHandle::~USBDeviceHandle() if (fRawFD > 0) close(fRawFD); for(int i = 0; i < 32; i++) { - if (fClaimedInterfaces & (1 << i)) + if (fClaimedInterfaces & (1U << i)) ReleaseInterface(i); } delete_sem(fTransfersSem); @@ -256,7 +256,7 @@ USBDeviceHandle::ClaimInterface(int inumber) { int status = fUSBDevice->ClaimInterface(inumber); if (status == LIBUSB_SUCCESS) - fClaimedInterfaces |= (1 << inumber); + fClaimedInterfaces |= (1U << inumber); return status; } @@ -264,7 +264,7 @@ int USBDeviceHandle::ReleaseInterface(int inumber) { fUSBDevice->ReleaseInterface(inumber); - fClaimedInterfaces &= ~(1 << inumber); + fClaimedInterfaces &= ~(1U << inumber); return LIBUSB_SUCCESS; } @@ -388,15 +388,15 @@ int USBDevice::ClaimInterface(int interface) { if (interface > ActiveConfiguration()->number_interfaces) return LIBUSB_ERROR_NOT_FOUND; - if (fClaimedInterfaces & (1 << interface)) + if (fClaimedInterfaces & (1U << interface)) return LIBUSB_ERROR_BUSY; - fClaimedInterfaces |= (1 << interface); + fClaimedInterfaces |= (1U << interface); return LIBUSB_SUCCESS; } int USBDevice::ReleaseInterface(int interface) { - fClaimedInterfaces &= ~(1 << interface); + fClaimedInterfaces &= ~(1U << interface); return LIBUSB_SUCCESS; } diff --git a/Externals/libusb/libusb/os/haiku_usb_raw.cpp b/Externals/libusb/libusb/os/haiku_usb_raw.cpp index 77adbd1e60..7c399d19d3 100644 --- a/Externals/libusb/libusb/os/haiku_usb_raw.cpp +++ b/Externals/libusb/libusb/os/haiku_usb_raw.cpp @@ -29,6 +29,9 @@ USBRoster gUsbRoster; int32 gInitCount = 0; +static int haiku_get_config_descriptor(struct libusb_device *, uint8_t, + unsigned char *, size_t, int *); + static int haiku_init(struct libusb_context *ctx) { @@ -38,8 +41,9 @@ haiku_init(struct libusb_context *ctx) } static void -haiku_exit(void) +haiku_exit(struct libusb_context *ctx) { + UNUSED(ctx); if (atomic_add(&gInitCount, -1) == 1) gUsbRoster.Stop(); } @@ -82,12 +86,7 @@ static int haiku_get_active_config_descriptor(struct libusb_device *device, unsigned char *buffer, size_t len, int *host_endian) { USBDevice *dev = *((USBDevice **)device->os_priv); - const usb_configuration_descriptor *act_config = dev->ActiveConfiguration(); - if (len > act_config->total_length) - return LIBUSB_ERROR_OVERFLOW; - memcpy(buffer, act_config, len); - *host_endian = 0; - return LIBUSB_SUCCESS; + return haiku_get_config_descriptor(device, dev->ActiveConfigurationIndex(), buffer, len, host_endian); } static int @@ -99,8 +98,9 @@ haiku_get_config_descriptor(struct libusb_device *device, uint8_t config_index, usbi_err(DEVICE_CTX(device), "failed getting configuration descriptor"); return LIBUSB_ERROR_INVALID_PARAM; } - if (len > config->total_length) + if (len > config->total_length) { len = config->total_length; + } memcpy(buffer, config, len); *host_endian = 0; return len; @@ -195,56 +195,59 @@ haiku_clock_gettime(int clkid, struct timespec *tp) return LIBUSB_ERROR_INVALID_PARAM; } -const struct usbi_os_backend haiku_usb_raw_backend = { - /*.name =*/ "Haiku usbfs", - /*.caps =*/ 0, - /*.init =*/ haiku_init, - /*.exit =*/ haiku_exit, - /*.get_device_list =*/ NULL, - /*.hotplug_poll =*/ NULL, - /*.open =*/ haiku_open, - /*.close =*/ haiku_close, - /*.get_device_descriptor =*/ haiku_get_device_descriptor, - /*.get_active_config_descriptor =*/ haiku_get_active_config_descriptor, - /*.get_config_descriptor =*/ haiku_get_config_descriptor, - /*.get_config_descriptor_by_value =*/ NULL, +const struct usbi_os_backend usbi_backend = { + .name = "Haiku usbfs", + .caps = 0, + .init = haiku_init, + .exit = haiku_exit, + .set_option = NULL, + .get_device_list = NULL, + .hotplug_poll = NULL, + .wrap_sys_device = NULL, + .open = haiku_open, + .close = haiku_close, + .get_device_descriptor = haiku_get_device_descriptor, + .get_active_config_descriptor = haiku_get_active_config_descriptor, + .get_config_descriptor = haiku_get_config_descriptor, + .get_config_descriptor_by_value = NULL, - /*.get_configuration =*/ NULL, - /*.set_configuration =*/ haiku_set_configuration, - /*.claim_interface =*/ haiku_claim_interface, - /*.release_interface =*/ haiku_release_interface, + .get_configuration = NULL, + .set_configuration = haiku_set_configuration, + .claim_interface = haiku_claim_interface, + .release_interface = haiku_release_interface, - /*.set_interface_altsetting =*/ haiku_set_altsetting, - /*.clear_halt =*/ NULL, - /*.reset_device =*/ NULL, + .set_interface_altsetting = haiku_set_altsetting, + .clear_halt = NULL, + .reset_device = NULL, - /*.alloc_streams =*/ NULL, - /*.free_streams =*/ NULL, + .alloc_streams = NULL, + .free_streams = NULL, - /*.dev_mem_alloc =*/ NULL, - /*.dev_mem_free =*/ NULL, + .dev_mem_alloc = NULL, + .dev_mem_free = NULL, - /*.kernel_driver_active =*/ NULL, - /*.detach_kernel_driver =*/ NULL, - /*.attach_kernel_driver =*/ NULL, + .kernel_driver_active = NULL, + .detach_kernel_driver = NULL, + .attach_kernel_driver = NULL, - /*.destroy_device =*/ NULL, + .destroy_device = NULL, - /*.submit_transfer =*/ haiku_submit_transfer, - /*.cancel_transfer =*/ haiku_cancel_transfer, - /*.clear_transfer_priv =*/ haiku_clear_transfer_priv, + .submit_transfer = haiku_submit_transfer, + .cancel_transfer = haiku_cancel_transfer, + .clear_transfer_priv = haiku_clear_transfer_priv, - /*.handle_events =*/ NULL, - /*.handle_transfer_completion =*/ haiku_handle_transfer_completion, + .handle_events = NULL, + .handle_transfer_completion = haiku_handle_transfer_completion, - /*.clock_gettime =*/ haiku_clock_gettime, + .clock_gettime = haiku_clock_gettime, #ifdef USBI_TIMERFD_AVAILABLE - /*.get_timerfd_clockid =*/ NULL, + .get_timerfd_clockid = NULL, #endif - /*.device_priv_size =*/ sizeof(USBDevice *), - /*.device_handle_priv_size =*/ sizeof(USBDeviceHandle *), - /*.transfer_priv_size =*/ sizeof(USBTransfer *), + .context_priv_size = 0, + .device_priv_size = sizeof(USBDevice *), + .device_handle_priv_size = sizeof(USBDeviceHandle *), + .transfer_priv_size = sizeof(USBTransfer *), }; diff --git a/Externals/libusb/libusb/os/linux_netlink.c b/Externals/libusb/libusb/os/linux_netlink.c index 60cf3ad1bd..c1ad1ec51f 100644 --- a/Externals/libusb/libusb/os/linux_netlink.c +++ b/Externals/libusb/libusb/os/linux_netlink.c @@ -45,24 +45,33 @@ #define NL_GROUP_KERNEL 1 +#ifndef SOCK_CLOEXEC +#define SOCK_CLOEXEC 0 +#endif + +#ifndef SOCK_NONBLOCK +#define SOCK_NONBLOCK 0 +#endif + static int linux_netlink_socket = -1; static int netlink_control_pipe[2] = { -1, -1 }; static pthread_t libusb_linux_event_thread; static void *linux_netlink_event_thread_main(void *arg); -static int set_fd_cloexec_nb(int fd) +static int set_fd_cloexec_nb(int fd, int socktype) { int flags; #if defined(FD_CLOEXEC) - flags = fcntl(fd, F_GETFD); - if (flags == -1) { - usbi_err(NULL, "failed to get netlink fd flags (%d)", errno); - return -1; - } + /* Make sure the netlink socket file descriptor is marked as CLOEXEC */ + if (!(socktype & SOCK_CLOEXEC)) { + flags = fcntl(fd, F_GETFD); + if (flags == -1) { + usbi_err(NULL, "failed to get netlink fd flags (%d)", errno); + return -1; + } - if (!(flags & FD_CLOEXEC)) { if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { usbi_err(NULL, "failed to set netlink fd flags (%d)", errno); return -1; @@ -70,13 +79,14 @@ static int set_fd_cloexec_nb(int fd) } #endif - flags = fcntl(fd, F_GETFL); - if (flags == -1) { - usbi_err(NULL, "failed to get netlink fd status flags (%d)", errno); - return -1; - } + /* Make sure the netlink socket is non-blocking */ + if (!(socktype & SOCK_NONBLOCK)) { + flags = fcntl(fd, F_GETFL); + if (flags == -1) { + usbi_err(NULL, "failed to get netlink fd status flags (%d)", errno); + return -1; + } - if (!(flags & O_NONBLOCK)) { if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { usbi_err(NULL, "failed to set netlink fd status flags (%d)", errno); return -1; @@ -89,21 +99,15 @@ static int set_fd_cloexec_nb(int fd) int linux_netlink_start_event_monitor(void) { struct sockaddr_nl sa_nl = { .nl_family = AF_NETLINK, .nl_groups = NL_GROUP_KERNEL }; - int socktype = SOCK_RAW; + int socktype = SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC; int opt = 1; int ret; -#if defined(SOCK_CLOEXEC) - socktype |= SOCK_CLOEXEC; -#endif -#if defined(SOCK_NONBLOCK) - socktype |= SOCK_NONBLOCK; -#endif - linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT); if (linux_netlink_socket == -1 && errno == EINVAL) { usbi_dbg("failed to create netlink socket of type %d, attempting SOCK_RAW", socktype); - linux_netlink_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT); + socktype = SOCK_RAW; + linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT); } if (linux_netlink_socket == -1) { @@ -111,7 +115,7 @@ int linux_netlink_start_event_monitor(void) goto err; } - ret = set_fd_cloexec_nb(linux_netlink_socket); + ret = set_fd_cloexec_nb(linux_netlink_socket, socktype); if (ret == -1) goto err_close_socket; @@ -162,7 +166,7 @@ int linux_netlink_stop_event_monitor(void) /* Write some dummy data to the control pipe and * wait for the thread to exit */ - r = usbi_write(netlink_control_pipe[1], &dummy, sizeof(dummy)); + r = write(netlink_control_pipe[1], &dummy, sizeof(dummy)); if (r <= 0) usbi_warn(NULL, "netlink control pipe signal failed"); @@ -356,7 +360,8 @@ static int linux_netlink_read_message(void) static void *linux_netlink_event_thread_main(void *arg) { char dummy; - ssize_t r; + int r; + ssize_t nb; struct pollfd fds[] = { { .fd = netlink_control_pipe[0], .events = POLLIN }, @@ -368,11 +373,15 @@ static void *linux_netlink_event_thread_main(void *arg) usbi_dbg("netlink event thread entering"); - while (poll(fds, 2, -1) >= 0) { + while ((r = poll(fds, 2, -1)) >= 0 || errno == EINTR) { + if (r < 0) { + /* temporary failure */ + continue; + } if (fds[0].revents & POLLIN) { /* activity on control pipe, read the byte and exit */ - r = usbi_read(netlink_control_pipe[0], &dummy, sizeof(dummy)); - if (r <= 0) + nb = read(netlink_control_pipe[0], &dummy, sizeof(dummy)); + if (nb <= 0) usbi_warn(NULL, "netlink control pipe read failed"); break; } diff --git a/Externals/libusb/libusb/os/linux_udev.c b/Externals/libusb/libusb/os/linux_udev.c index ea27142ed9..bea03e3a88 100644 --- a/Externals/libusb/libusb/os/linux_udev.c +++ b/Externals/libusb/libusb/os/linux_udev.c @@ -82,17 +82,33 @@ int linux_udev_start_event_monitor(void) udev_monitor_fd = udev_monitor_get_fd(udev_monitor); +#if defined(FD_CLOEXEC) + /* Make sure the udev file descriptor is marked as CLOEXEC */ + r = fcntl(udev_monitor_fd, F_GETFD); + if (r == -1) { + usbi_err(NULL, "geting udev monitor fd flags (%d)", errno); + goto err_free_monitor; + } + if (!(r & FD_CLOEXEC)) { + if (fcntl(udev_monitor_fd, F_SETFD, r | FD_CLOEXEC) == -1) { + usbi_err(NULL, "setting udev monitor fd flags (%d)", errno); + goto err_free_monitor; + } + } +#endif + /* Some older versions of udev are not non-blocking by default, * so make sure this is set */ r = fcntl(udev_monitor_fd, F_GETFL); if (r == -1) { - usbi_err(NULL, "getting udev monitor fd flags (%d)", errno); + usbi_err(NULL, "getting udev monitor fd status flags (%d)", errno); goto err_free_monitor; } - r = fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK); - if (r) { - usbi_err(NULL, "setting udev monitor fd flags (%d)", errno); - goto err_free_monitor; + if (!(r & O_NONBLOCK)) { + if (fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK) == -1) { + usbi_err(NULL, "setting udev monitor fd status flags (%d)", errno); + goto err_free_monitor; + } } r = usbi_pipe(udev_control_pipe); @@ -134,7 +150,7 @@ int linux_udev_stop_event_monitor(void) /* Write some dummy data to the control pipe and * wait for the thread to exit */ - r = usbi_write(udev_control_pipe[1], &dummy, sizeof(dummy)); + r = write(udev_control_pipe[1], &dummy, sizeof(dummy)); if (r <= 0) { usbi_warn(NULL, "udev control pipe signal failed"); } @@ -162,6 +178,7 @@ static void *linux_udev_event_thread_main(void *arg) { char dummy; int r; + ssize_t nb; struct udev_device* udev_dev; struct pollfd fds[] = { {.fd = udev_control_pipe[0], @@ -172,11 +189,15 @@ static void *linux_udev_event_thread_main(void *arg) usbi_dbg("udev event thread entering."); - while (poll(fds, 2, -1) >= 0) { + while ((r = poll(fds, 2, -1)) >= 0 || errno == EINTR) { + if (r < 0) { + /* temporary failure */ + continue; + } if (fds[0].revents & POLLIN) { /* activity on control pipe, read the byte and exit */ - r = usbi_read(udev_control_pipe[0], &dummy, sizeof(dummy)); - if (r <= 0) { + nb = read(udev_control_pipe[0], &dummy, sizeof(dummy)); + if (nb <= 0) { usbi_warn(NULL, "udev control pipe read failed"); } break; @@ -211,7 +232,7 @@ static int udev_device_info(struct libusb_context *ctx, int detached, } return linux_get_device_address(ctx, detached, busnum, devaddr, - dev_node, *sys_name); + dev_node, *sys_name, -1); } static void udev_hotplug_event(struct udev_device* udev_dev) @@ -270,6 +291,7 @@ int linux_udev_scan_devices(struct libusb_context *ctx) udev_enumerate_scan_devices(enumerator); devices = udev_enumerate_get_list_entry(enumerator); + entry = NULL; udev_list_entry_foreach(entry, devices) { const char *path = udev_list_entry_get_name(entry); uint8_t busnum = 0, devaddr = 0; diff --git a/Externals/libusb/libusb/os/linux_usbfs.c b/Externals/libusb/libusb/os/linux_usbfs.c index 9cbeb80052..84f59c3426 100644 --- a/Externals/libusb/libusb/os/linux_usbfs.c +++ b/Externals/libusb/libusb/os/linux_usbfs.c @@ -81,6 +81,19 @@ static const char *usbfs_path = NULL; /* use usbdev*.* device names in /dev instead of the usbfs bus directories */ static int usbdev_names = 0; +/* Linux has changed the maximum length of an individual isochronous packet + * over time. Initially this limit was 1,023 bytes, but Linux 2.6.18 + * (commit 3612242e527eb47ee4756b5350f8bdf791aa5ede) increased this value to + * 8,192 bytes to support higher bandwidth devices. Linux 3.10 + * (commit e2e2f0ea1c935edcf53feb4c4c8fdb4f86d57dd9) further increased this + * value to 49,152 bytes to support super speed devices. + */ +static unsigned int max_iso_packet_len = 0; + +/* Linux 2.6.23 adds support for O_CLOEXEC when opening files, which marks the + * close-on-exec flag in the underlying file descriptor. */ +static int supports_flag_cloexec = -1; + /* Linux 2.6.32 adds support for a bulk continuation URB flag. this basically * allows us to mark URBs as being part of a specific logical transfer when * we submit them to the kernel. then, on any error except a cancellation, all @@ -136,6 +149,12 @@ static int detach_kernel_driver_and_claim(struct libusb_device_handle *, int); static int linux_default_scan_devices (struct libusb_context *ctx); #endif +struct kernel_version { + int major; + int minor; + int sublevel; +}; + struct linux_device_priv { char *sysfs_dir; unsigned char *descriptors; @@ -146,6 +165,7 @@ struct linux_device_priv { struct linux_device_handle_priv { int fd; int fd_removed; + int fd_keep; uint32_t caps; }; @@ -180,6 +200,16 @@ struct linux_transfer_priv { int iso_packet_offset; }; +static int _open(const char *path, int flags) +{ +#if defined(O_CLOEXEC) + if (supports_flag_cloexec) + return open(path, flags | O_CLOEXEC); + else +#endif + return open(path, flags); +} + static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent) { struct libusb_context *ctx = DEVICE_CTX(dev); @@ -194,7 +224,7 @@ static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent) snprintf(path, PATH_MAX, "%s/%03d/%03d", usbfs_path, dev->bus_number, dev->device_address); - fd = open(path, mode); + fd = _open(path, mode); if (fd != -1) return fd; /* Success */ @@ -205,7 +235,7 @@ static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent) /* Wait 10ms for USB device path creation.*/ nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL); - fd = open(path, mode); + fd = _open(path, mode); if (fd != -1) return fd; /* Success */ } @@ -311,8 +341,10 @@ static const char *find_usbfs_path(void) /* On udev based systems without any usb-devices /dev/bus/usb will not * exist. So if we've not found anything and we're using udev for hotplug - * simply assume /dev/bus/usb rather then making libusb_init fail. */ -#if defined(USE_UDEV) + * simply assume /dev/bus/usb rather then making libusb_init fail. + * Make the same assumption for Android where SELinux policies might block us + * from reading /dev on newer devices. */ +#if defined(USE_UDEV) || defined(__ANDROID__) if (ret == NULL) ret = "/dev/bus/usb"; #endif @@ -342,39 +374,59 @@ static clockid_t find_monotonic_clock(void) return CLOCK_REALTIME; } -static int kernel_version_ge(int major, int minor, int sublevel) +static int get_kernel_version(struct libusb_context *ctx, + struct kernel_version *ver) { struct utsname uts; - int atoms, kmajor, kminor, ksublevel; + int atoms; - if (uname(&uts) < 0) - return -1; - atoms = sscanf(uts.release, "%d.%d.%d", &kmajor, &kminor, &ksublevel); - if (atoms < 1) + if (uname(&uts) < 0) { + usbi_err(ctx, "uname failed, errno %d", errno); return -1; + } - if (kmajor > major) + atoms = sscanf(uts.release, "%d.%d.%d", &ver->major, &ver->minor, &ver->sublevel); + if (atoms < 1) { + usbi_err(ctx, "failed to parse uname release '%s'", uts.release); + return -1; + } + + if (atoms < 2) + ver->minor = -1; + if (atoms < 3) + ver->sublevel = -1; + + usbi_dbg("reported kernel version is %s", uts.release); + + return 0; +} + +static int kernel_version_ge(const struct kernel_version *ver, + int major, int minor, int sublevel) +{ + if (ver->major > major) return 1; - if (kmajor < major) + else if (ver->major < major) return 0; /* kmajor == major */ - if (atoms < 2) + if (ver->minor == -1 && ver->sublevel == -1) return 0 == minor && 0 == sublevel; - if (kminor > minor) + else if (ver->minor > minor) return 1; - if (kminor < minor) + else if (ver->minor < minor) return 0; /* kminor == minor */ - if (atoms < 3) + if (ver->sublevel == -1) return 0 == sublevel; - return ksublevel >= sublevel; + return ver->sublevel >= sublevel; } static int op_init(struct libusb_context *ctx) { + struct kernel_version kversion; struct stat statbuf; int r; @@ -387,13 +439,17 @@ static int op_init(struct libusb_context *ctx) if (monotonic_clkid == -1) monotonic_clkid = find_monotonic_clock(); + if (get_kernel_version(ctx, &kversion) < 0) + return LIBUSB_ERROR_OTHER; + + if (supports_flag_cloexec == -1) { + /* O_CLOEXEC flag available from Linux 2.6.23 */ + supports_flag_cloexec = kernel_version_ge(&kversion,2,6,23); + } + if (supports_flag_bulk_continuation == -1) { /* bulk continuation URB flag available from Linux 2.6.32 */ - supports_flag_bulk_continuation = kernel_version_ge(2,6,32); - if (supports_flag_bulk_continuation == -1) { - usbi_err(ctx, "error checking for bulk continuation support"); - return LIBUSB_ERROR_OTHER; - } + supports_flag_bulk_continuation = kernel_version_ge(&kversion,2,6,32); } if (supports_flag_bulk_continuation) @@ -401,32 +457,31 @@ static int op_init(struct libusb_context *ctx) if (-1 == supports_flag_zero_packet) { /* zero length packet URB flag fixed since Linux 2.6.31 */ - supports_flag_zero_packet = kernel_version_ge(2,6,31); - if (-1 == supports_flag_zero_packet) { - usbi_err(ctx, "error checking for zero length packet support"); - return LIBUSB_ERROR_OTHER; - } + supports_flag_zero_packet = kernel_version_ge(&kversion,2,6,31); } if (supports_flag_zero_packet) usbi_dbg("zero length packet flag supported"); + if (!max_iso_packet_len) { + if (kernel_version_ge(&kversion,3,10,0)) + max_iso_packet_len = 49152; + else if (kernel_version_ge(&kversion,2,6,18)) + max_iso_packet_len = 8192; + else + max_iso_packet_len = 1023; + } + + usbi_dbg("max iso packet length is (likely) %u bytes", max_iso_packet_len); + if (-1 == sysfs_has_descriptors) { /* sysfs descriptors has all descriptors since Linux 2.6.26 */ - sysfs_has_descriptors = kernel_version_ge(2,6,26); - if (-1 == sysfs_has_descriptors) { - usbi_err(ctx, "error checking for sysfs descriptors"); - return LIBUSB_ERROR_OTHER; - } + sysfs_has_descriptors = kernel_version_ge(&kversion,2,6,26); } if (-1 == sysfs_can_relate_devices) { /* sysfs has busnum since Linux 2.6.22 */ - sysfs_can_relate_devices = kernel_version_ge(2,6,22); - if (-1 == sysfs_can_relate_devices) { - usbi_err(ctx, "error checking for sysfs busnum"); - return LIBUSB_ERROR_OTHER; - } + sysfs_can_relate_devices = kernel_version_ge(&kversion,2,6,22); } if (sysfs_can_relate_devices || sysfs_has_descriptors) { @@ -463,8 +518,9 @@ static int op_init(struct libusb_context *ctx) return r; } -static void op_exit(void) +static void op_exit(struct libusb_context *ctx) { + UNUSED(ctx); usbi_mutex_static_lock(&linux_hotplug_startstop_lock); assert(init_count != 0); if (!--init_count) { @@ -478,8 +534,10 @@ static int linux_start_event_monitor(void) { #if defined(USE_UDEV) return linux_udev_start_event_monitor(); -#else +#elif !defined(__ANDROID__) return linux_netlink_start_event_monitor(); +#else + return LIBUSB_SUCCESS; #endif } @@ -487,20 +545,22 @@ static int linux_stop_event_monitor(void) { #if defined(USE_UDEV) return linux_udev_stop_event_monitor(); -#else +#elif !defined(__ANDROID__) return linux_netlink_stop_event_monitor(); +#else + return LIBUSB_SUCCESS; #endif } static int linux_scan_devices(struct libusb_context *ctx) { - int ret; + int ret = 0; usbi_mutex_static_lock(&linux_hotplug_lock); #if defined(USE_UDEV) ret = linux_udev_scan_devices(ctx); -#else +#elif !defined(__ANDROID__) ret = linux_default_scan_devices(ctx); #endif @@ -513,7 +573,7 @@ static void op_hotplug_poll(void) { #if defined(USE_UDEV) linux_udev_hotplug_poll(); -#else +#elif !defined(__ANDROID__) linux_netlink_hotplug_poll(); #endif } @@ -526,7 +586,7 @@ static int _open_sysfs_attr(struct libusb_device *dev, const char *attr) snprintf(filename, PATH_MAX, "%s/%s/%s", SYSFS_DEVICE_PATH, priv->sysfs_dir, attr); - fd = open(filename, O_RDONLY); + fd = _open(filename, O_RDONLY); if (fd < 0) { usbi_err(DEVICE_CTX(dev), "open %s failed ret=%d errno=%d", filename, fd, errno); @@ -542,12 +602,12 @@ static int __read_sysfs_attr(struct libusb_context *ctx, { char filename[PATH_MAX]; FILE *f; - int r, value; + int fd, r, value; snprintf(filename, PATH_MAX, "%s/%s/%s", SYSFS_DEVICE_PATH, devname, attr); - f = fopen(filename, "r"); - if (f == NULL) { + fd = _open(filename, O_RDONLY); + if (fd == -1) { if (errno == ENOENT) { /* File doesn't exist. Assume the device has been disconnected (see trac ticket #70). */ @@ -557,6 +617,13 @@ static int __read_sysfs_attr(struct libusb_context *ctx, return LIBUSB_ERROR_IO; } + f = fdopen(fd, "r"); + if (f == NULL) { + usbi_err(ctx, "fdopen %s failed errno=%d", filename, errno); + close(fd); + return LIBUSB_ERROR_OTHER; + } + r = fscanf(f, "%d", &value); fclose(f); if (r != 1) { @@ -576,7 +643,7 @@ static int op_get_device_descriptor(struct libusb_device *dev, { struct linux_device_priv *priv = _device_priv(dev); - *host_endian = sysfs_has_descriptors ? 0 : 1; + *host_endian = (priv->sysfs_dir && sysfs_has_descriptors) ? 0 : 1; memcpy(buffer, priv->descriptors, DEVICE_DESC_LENGTH); return 0; @@ -627,14 +694,23 @@ static int sysfs_get_active_config(struct libusb_device *dev, int *config) int linux_get_device_address (struct libusb_context *ctx, int detached, uint8_t *busnum, uint8_t *devaddr,const char *dev_node, - const char *sys_name) + const char *sys_name, int fd) { + char proc_path[PATH_MAX], fd_path[PATH_MAX]; int sysfs_attr; + ssize_t r; usbi_dbg("getting address for device: %s detached: %d", sys_name, detached); /* can't use sysfs to read the bus and device number if the * device has been detached */ if (!sysfs_can_relate_devices || detached || NULL == sys_name) { + if (NULL == dev_node && fd >= 0) { + /* try to retrieve the device node from fd */ + snprintf(proc_path, PATH_MAX, "/proc/self/fd/%d", fd); + r = readlink(proc_path, fd_path, PATH_MAX); + if (r > 0) + dev_node = fd_path; + } if (NULL == dev_node) { return LIBUSB_ERROR_OTHER; } @@ -644,6 +720,8 @@ int linux_get_device_address (struct libusb_context *ctx, int detached, sscanf (dev_node, "/dev/bus/usb/%hhu/%hhu", busnum, devaddr); } else if (!strncmp(dev_node, "/proc/bus/usb", 13)) { sscanf (dev_node, "/proc/bus/usb/%hhu/%hhu", busnum, devaddr); + } else { + return LIBUSB_ERROR_OTHER; } return LIBUSB_SUCCESS; @@ -696,9 +774,11 @@ static int seek_to_next_descriptor(struct libusb_context *ctx, } /* Return offset to next config */ -static int seek_to_next_config(struct libusb_context *ctx, +static int seek_to_next_config(struct libusb_device *dev, unsigned char *buffer, int size) { + struct libusb_context *ctx = DEVICE_CTX(dev); + struct linux_device_priv *priv = _device_priv(dev); struct libusb_config_descriptor config; if (size == 0) @@ -725,7 +805,7 @@ static int seek_to_next_config(struct libusb_context *ctx, * config descriptor with verified bLength fields, with descriptors * with an invalid bLength removed. */ - if (sysfs_has_descriptors) { + if (priv->sysfs_dir && sysfs_has_descriptors) { int next = seek_to_next_descriptor(ctx, LIBUSB_DT_CONFIG, buffer, size); if (next == LIBUSB_ERROR_NOT_FOUND) @@ -754,7 +834,6 @@ static int seek_to_next_config(struct libusb_context *ctx, static int op_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t value, unsigned char **buffer, int *host_endian) { - struct libusb_context *ctx = DEVICE_CTX(dev); struct linux_device_priv *priv = _device_priv(dev); unsigned char *descriptors = priv->descriptors; int size = priv->descriptors_len; @@ -770,7 +849,7 @@ static int op_get_config_descriptor_by_value(struct libusb_device *dev, /* Seek till the config is found, or till "EOF" */ while (1) { - int next = seek_to_next_config(ctx, descriptors, size); + int next = seek_to_next_config(dev, descriptors, size); if (next < 0) return next; config = (struct libusb_config_descriptor *)descriptors; @@ -786,16 +865,16 @@ static int op_get_config_descriptor_by_value(struct libusb_device *dev, static int op_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian) { + struct linux_device_priv *priv = _device_priv(dev); int r, config; unsigned char *config_desc; - if (sysfs_can_relate_devices) { + if (priv->sysfs_dir && sysfs_can_relate_devices) { r = sysfs_get_active_config(dev, &config); if (r < 0) return r; } else { /* Use cached bConfigurationValue */ - struct linux_device_priv *priv = _device_priv(dev); config = priv->active_config; } if (config == -1) @@ -806,7 +885,7 @@ static int op_get_active_config_descriptor(struct libusb_device *dev, if (r < 0) return r; - len = MIN(len, r); + len = MIN(len, (size_t)r); memcpy(buffer, config_desc, len); return len; } @@ -827,7 +906,7 @@ static int op_get_config_descriptor(struct libusb_device *dev, /* Seek till the config is found, or till "EOF" */ for (i = 0; ; i++) { - r = seek_to_next_config(DEVICE_CTX(dev), descriptors, size); + r = seek_to_next_config(dev, descriptors, size); if (r < 0) return r; if (i == config_index) @@ -836,7 +915,7 @@ static int op_get_config_descriptor(struct libusb_device *dev, descriptors += r; } - len = MIN(len, r); + len = MIN(len, (size_t)r); memcpy(buffer, descriptors, len); return len; } @@ -886,7 +965,7 @@ static int usbfs_get_active_config(struct libusb_device *dev, int fd) } static int initialize_device(struct libusb_device *dev, uint8_t busnum, - uint8_t devaddr, const char *sysfs_dir) + uint8_t devaddr, const char *sysfs_dir, int wrapped_fd) { struct linux_device_priv *priv = _device_priv(dev); struct libusb_context *ctx = DEVICE_CTX(dev); @@ -911,6 +990,7 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum, case 12: dev->speed = LIBUSB_SPEED_FULL; break; case 480: dev->speed = LIBUSB_SPEED_HIGH; break; case 5000: dev->speed = LIBUSB_SPEED_SUPER; break; + case 10000: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break; default: usbi_warn(DEVICE_CTX(dev), "Unknown device speed: %d Mbps", speed); } @@ -918,10 +998,18 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum, } /* cache descriptors in memory */ - if (sysfs_has_descriptors) + if (sysfs_dir && sysfs_has_descriptors) { fd = _open_sysfs_attr(dev, "descriptors"); - else + } else if (wrapped_fd < 0) { fd = _get_usbfs_fd(dev, O_RDONLY, 0); + } else { + fd = wrapped_fd; + r = lseek(fd, 0, SEEK_SET); + if (r < 0) { + usbi_err(ctx, "seek failed ret=%d errno=%d", r, errno); + return LIBUSB_ERROR_IO; + } + } if (fd < 0) return fd; @@ -930,11 +1018,12 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum, priv->descriptors = usbi_reallocf(priv->descriptors, descriptors_size); if (!priv->descriptors) { - close(fd); + if (fd != wrapped_fd) + close(fd); return LIBUSB_ERROR_NO_MEM; } /* usbfs has holes in the file */ - if (!sysfs_has_descriptors) { + if (!(sysfs_dir && sysfs_has_descriptors)) { memset(priv->descriptors + priv->descriptors_len, 0, descriptors_size - priv->descriptors_len); } @@ -943,13 +1032,15 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum, if (r < 0) { usbi_err(ctx, "read descriptor failed ret=%d errno=%d", fd, errno); - close(fd); + if (fd != wrapped_fd) + close(fd); return LIBUSB_ERROR_IO; } priv->descriptors_len += r; } while (priv->descriptors_len == descriptors_size); - close(fd); + if (fd != wrapped_fd) + close(fd); if (priv->descriptors_len < DEVICE_DESC_LENGTH) { usbi_err(ctx, "short descriptor read (%d)", @@ -957,11 +1048,14 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum, return LIBUSB_ERROR_IO; } - if (sysfs_can_relate_devices) + if (sysfs_dir && sysfs_can_relate_devices) return LIBUSB_SUCCESS; /* cache active config */ - fd = _get_usbfs_fd(dev, O_RDWR, 1); + if (wrapped_fd < 0) + fd = _get_usbfs_fd(dev, O_RDWR, 1); + else + fd = wrapped_fd; if (fd < 0) { /* cannot send a control message to determine the active * config. just assume the first one is active. */ @@ -981,7 +1075,8 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum, } r = usbfs_get_active_config(dev, fd); - close(fd); + if (wrapped_fd < 0) + close(fd); return r; } @@ -1029,9 +1124,11 @@ retry: usbi_mutex_lock(&ctx->usb_devs_lock); list_for_each_entry(it, &ctx->usb_devs, list, struct libusb_device) { struct linux_device_priv *priv = _device_priv(it); - if (0 == strcmp (priv->sysfs_dir, parent_sysfs_dir)) { - dev->parent_dev = libusb_ref_device(it); - break; + if (priv->sysfs_dir) { + if (0 == strcmp (priv->sysfs_dir, parent_sysfs_dir)) { + dev->parent_dev = libusb_ref_device(it); + break; + } } } usbi_mutex_unlock(&ctx->usb_devs_lock); @@ -1080,7 +1177,7 @@ int linux_enumerate_device(struct libusb_context *ctx, if (!dev) return LIBUSB_ERROR_NO_MEM; - r = initialize_device(dev, busnum, devaddr, sysfs_dir); + r = initialize_device(dev, busnum, devaddr, sysfs_dir, -1); if (r < 0) goto out; r = usbi_sanitize_device(dev); @@ -1223,7 +1320,7 @@ static int sysfs_scan_device(struct libusb_context *ctx, const char *devname) uint8_t busnum, devaddr; int ret; - ret = linux_get_device_address (ctx, 0, &busnum, &devaddr, NULL, devname); + ret = linux_get_device_address (ctx, 0, &busnum, &devaddr, NULL, devname, -1); if (LIBUSB_SUCCESS != ret) { return ret; } @@ -1237,11 +1334,12 @@ static int sysfs_get_device_list(struct libusb_context *ctx) { DIR *devices = opendir(SYSFS_DEVICE_PATH); struct dirent *entry; - int r = LIBUSB_ERROR_IO; + int num_devices = 0; + int num_enumerated = 0; if (!devices) { usbi_err(ctx, "opendir devices failed errno=%d", errno); - return r; + return LIBUSB_ERROR_IO; } while ((entry = readdir(devices))) { @@ -1249,16 +1347,23 @@ static int sysfs_get_device_list(struct libusb_context *ctx) || strchr(entry->d_name, ':')) continue; + num_devices++; + if (sysfs_scan_device(ctx, entry->d_name)) { usbi_dbg("failed to enumerate dir entry %s", entry->d_name); continue; } - r = 0; + num_enumerated++; } closedir(devices); - return r; + + /* successful if at least one device was enumerated or no devices were found */ + if (num_enumerated || !num_devices) + return LIBUSB_SUCCESS; + else + return LIBUSB_ERROR_IO; } static int linux_default_scan_devices (struct libusb_context *ctx) @@ -1280,28 +1385,14 @@ static int linux_default_scan_devices (struct libusb_context *ctx) } #endif -static int op_open(struct libusb_device_handle *handle) +static int initialize_handle(struct libusb_device_handle *handle, int fd) { struct linux_device_handle_priv *hpriv = _device_handle_priv(handle); int r; - hpriv->fd = _get_usbfs_fd(handle->dev, O_RDWR, 0); - if (hpriv->fd < 0) { - if (hpriv->fd == LIBUSB_ERROR_NO_DEVICE) { - /* device will still be marked as attached if hotplug monitor thread - * hasn't processed remove event yet */ - usbi_mutex_static_lock(&linux_hotplug_lock); - if (handle->dev->attached) { - usbi_dbg("open failed with no device, but device still attached"); - linux_device_disconnected(handle->dev->bus_number, - handle->dev->device_address); - } - usbi_mutex_static_unlock(&linux_hotplug_lock); - } - return hpriv->fd; - } + hpriv->fd = fd; - r = ioctl(hpriv->fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps); + r = ioctl(fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps); if (r < 0) { if (errno == ENOTTY) usbi_dbg("getcap not available"); @@ -1314,9 +1405,82 @@ static int op_open(struct libusb_device_handle *handle) hpriv->caps |= USBFS_CAP_BULK_CONTINUATION; } - r = usbi_add_pollfd(HANDLE_CTX(handle), hpriv->fd, POLLOUT); + return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->fd, POLLOUT); +} + +static int op_wrap_sys_device(struct libusb_context *ctx, + struct libusb_device_handle *handle, intptr_t sys_dev) +{ + struct linux_device_handle_priv *hpriv = _device_handle_priv(handle); + int fd = (int)sys_dev; + uint8_t busnum, devaddr; + struct usbfs_connectinfo ci; + struct libusb_device *dev; + int r; + + r = linux_get_device_address(ctx, 1, &busnum, &devaddr, NULL, NULL, fd); + if (r < 0) { + r = ioctl(fd, IOCTL_USBFS_CONNECTINFO, &ci); + if (r < 0) { + usbi_err(ctx, "connectinfo failed (%d)", errno); + return LIBUSB_ERROR_IO; + } + /* There is no ioctl to get the bus number. We choose 0 here + * as linux starts numbering buses from 1. */ + busnum = 0; + devaddr = ci.devnum; + } + + /* Session id is unused as we do not add the device to the list of + * connected devices. */ + usbi_dbg("allocating new device for fd %d", fd); + dev = usbi_alloc_device(ctx, 0); + if (!dev) + return LIBUSB_ERROR_NO_MEM; + + r = initialize_device(dev, busnum, devaddr, NULL, fd); if (r < 0) - close(hpriv->fd); + goto out; + r = usbi_sanitize_device(dev); + if (r < 0) + goto out; + /* Consider the device as connected, but do not add it to the managed + * device list. */ + dev->attached = 1; + handle->dev = dev; + + r = initialize_handle(handle, fd); + hpriv->fd_keep = 1; + +out: + if (r < 0) + libusb_unref_device(dev); + return r; +} + +static int op_open(struct libusb_device_handle *handle) +{ + int fd, r; + + fd = _get_usbfs_fd(handle->dev, O_RDWR, 0); + if (fd < 0) { + if (fd == LIBUSB_ERROR_NO_DEVICE) { + /* device will still be marked as attached if hotplug monitor thread + * hasn't processed remove event yet */ + usbi_mutex_static_lock(&linux_hotplug_lock); + if (handle->dev->attached) { + usbi_dbg("open failed with no device, but device still attached"); + linux_device_disconnected(handle->dev->bus_number, + handle->dev->device_address); + } + usbi_mutex_static_unlock(&linux_hotplug_lock); + } + return fd; + } + + r = initialize_handle(handle, fd); + if (r < 0) + close(fd); return r; } @@ -1327,21 +1491,23 @@ static void op_close(struct libusb_device_handle *dev_handle) /* fd may have already been removed by POLLERR condition in op_handle_events() */ if (!hpriv->fd_removed) usbi_remove_pollfd(HANDLE_CTX(dev_handle), hpriv->fd); - close(hpriv->fd); + if (!hpriv->fd_keep) + close(hpriv->fd); } static int op_get_configuration(struct libusb_device_handle *handle, int *config) { + struct linux_device_priv *priv = _device_priv(handle->dev); int r; - if (sysfs_can_relate_devices) { + if (priv->sysfs_dir && sysfs_can_relate_devices) { r = sysfs_get_active_config(handle->dev, config); } else { r = usbfs_get_active_config(handle->dev, _device_handle_priv(handle)->fd); if (r == LIBUSB_SUCCESS) - *config = _device_priv(handle->dev)->active_config; + *config = priv->active_config; } if (r < 0) return r; @@ -1683,10 +1849,7 @@ static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle, strcpy(dc.driver, "usbfs"); dc.flags = USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER; r = ioctl(fd, IOCTL_USBFS_DISCONNECT_CLAIM, &dc); - if (r == 0 || (r != 0 && errno != ENOTTY)) { - if (r == 0) - return 0; - + if (r != 0 && errno != ENOTTY) { switch (errno) { case EBUSY: return LIBUSB_ERROR_BUSY; @@ -1698,7 +1861,8 @@ static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle, usbi_err(HANDLE_CTX(handle), "disconnect-and-claim failed errno %d", errno); return LIBUSB_ERROR_OTHER; - } + } else if (r == 0) + return 0; /* Fallback code for kernels which don't support the disconnect-and-claim ioctl */ @@ -1971,38 +2135,43 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) struct linux_device_handle_priv *dpriv = _device_handle_priv(transfer->dev_handle); struct usbfs_urb **urbs; - size_t alloc_size; int num_packets = transfer->num_iso_packets; - int i; - int this_urb_len = 0; - int num_urbs = 1; - int packet_offset = 0; + int num_packets_remaining; + int i, j; + int num_urbs; unsigned int packet_len; + unsigned int total_len = 0; unsigned char *urb_buffer = transfer->buffer; - /* usbfs places arbitrary limits on iso URBs. this limit has changed - * at least three times, and it's difficult to accurately detect which - * limit this running kernel might impose. so we attempt to submit - * whatever the user has provided. if the kernel rejects the request - * due to its size, we return an error indicating such to the user. - */ + if (num_packets < 1) + return LIBUSB_ERROR_INVALID_PARAM; - /* calculate how many URBs we need */ + /* usbfs places arbitrary limits on iso URBs. this limit has changed + * at least three times, but we attempt to detect this limit during + * init and check it here. if the kernel rejects the request due to + * its size, we return an error indicating such to the user. + */ for (i = 0; i < num_packets; i++) { - unsigned int space_remaining = MAX_ISO_BUFFER_LENGTH - this_urb_len; packet_len = transfer->iso_packet_desc[i].length; - if (packet_len > space_remaining) { - num_urbs++; - this_urb_len = packet_len; - /* check that we can actually support this packet length */ - if (this_urb_len > MAX_ISO_BUFFER_LENGTH) - return LIBUSB_ERROR_INVALID_PARAM; - } else { - this_urb_len += packet_len; + if (packet_len > max_iso_packet_len) { + usbi_warn(TRANSFER_CTX(transfer), + "iso packet length of %u bytes exceeds maximum of %u bytes", + packet_len, max_iso_packet_len); + return LIBUSB_ERROR_INVALID_PARAM; } + + total_len += packet_len; } - usbi_dbg("need %d %dk URBs for transfer", num_urbs, MAX_ISO_BUFFER_LENGTH / 1024); + + if (transfer->length < (int)total_len) + return LIBUSB_ERROR_INVALID_PARAM; + + /* usbfs limits the number of iso packets per URB */ + num_urbs = (num_packets + (MAX_ISO_PACKETS_PER_URB - 1)) / MAX_ISO_PACKETS_PER_URB; + + usbi_dbg("need %d urbs for new transfer with length %d", num_urbs, + transfer->length); urbs = calloc(num_urbs, sizeof(*urbs)); if (!urbs) @@ -2015,31 +2184,15 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) tpriv->iso_packet_offset = 0; /* allocate + initialize each URB with the correct number of packets */ - for (i = 0; i < num_urbs; i++) { + num_packets_remaining = num_packets; + for (i = 0, j = 0; i < num_urbs; i++) { + int num_packets_in_urb = MIN(num_packets_remaining, MAX_ISO_PACKETS_PER_URB); struct usbfs_urb *urb; - unsigned int space_remaining_in_urb = MAX_ISO_BUFFER_LENGTH; - int urb_packet_offset = 0; - unsigned char *urb_buffer_orig = urb_buffer; - int j; + size_t alloc_size; int k; - /* swallow up all the packets we can fit into this URB */ - while (packet_offset < transfer->num_iso_packets) { - packet_len = transfer->iso_packet_desc[packet_offset].length; - if (packet_len <= space_remaining_in_urb) { - /* throw it in */ - urb_packet_offset++; - packet_offset++; - space_remaining_in_urb -= packet_len; - urb_buffer += packet_len; - } else { - /* it can't fit, save it for the next URB */ - break; - } - } - alloc_size = sizeof(*urb) - + (urb_packet_offset * sizeof(struct usbfs_iso_packet_desc)); + + (num_packets_in_urb * sizeof(struct usbfs_iso_packet_desc)); urb = calloc(1, alloc_size); if (!urb) { free_iso_urbs(tpriv); @@ -2048,10 +2201,10 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) urbs[i] = urb; /* populate packet lengths */ - for (j = 0, k = packet_offset - urb_packet_offset; - k < packet_offset; k++, j++) { - packet_len = transfer->iso_packet_desc[k].length; - urb->iso_frame_desc[j].length = packet_len; + for (k = 0; k < num_packets_in_urb; j++, k++) { + packet_len = transfer->iso_packet_desc[j].length; + urb->buffer_length += packet_len; + urb->iso_frame_desc[k].length = packet_len; } urb->usercontext = itransfer; @@ -2059,8 +2212,11 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) /* FIXME: interface for non-ASAP data? */ urb->flags = USBFS_URB_ISO_ASAP; urb->endpoint = transfer->endpoint; - urb->number_of_packets = urb_packet_offset; - urb->buffer = urb_buffer_orig; + urb->number_of_packets = num_packets_in_urb; + urb->buffer = urb_buffer; + + urb_buffer += urb->buffer_length; + num_packets_remaining -= num_packets_in_urb; } /* submit URBs */ @@ -2073,6 +2229,10 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) usbi_warn(TRANSFER_CTX(transfer), "submiturb failed, transfer too large"); r = LIBUSB_ERROR_INVALID_PARAM; + } else if (errno == EMSGSIZE) { + usbi_warn(TRANSFER_CTX(transfer), + "submiturb failed, iso packet length too large"); + r = LIBUSB_ERROR_INVALID_PARAM; } else { usbi_err(TRANSFER_CTX(transfer), "submiturb failed error %d errno=%d", r, errno); @@ -2211,7 +2371,6 @@ static void op_clear_transfer_priv(struct usbi_transfer *itransfer) USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - /* urbs can be freed also in submit_transfer so lock mutex first */ switch (transfer->type) { case LIBUSB_TRANSFER_TYPE_CONTROL: case LIBUSB_TRANSFER_TYPE_BULK: @@ -2557,7 +2716,7 @@ static int reap_for_handle(struct libusb_device_handle *handle) { struct linux_device_handle_priv *hpriv = _device_handle_priv(handle); int r; - struct usbfs_urb *urb; + struct usbfs_urb *urb = NULL; struct usbi_transfer *itransfer; struct libusb_transfer *transfer; @@ -2683,7 +2842,7 @@ static clockid_t op_get_timerfd_clockid(void) } #endif -const struct usbi_os_backend linux_usbfs_backend = { +const struct usbi_os_backend usbi_backend = { .name = "Linux usbfs", .caps = USBI_CAP_HAS_HID_ACCESS|USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER, .init = op_init, @@ -2695,6 +2854,7 @@ const struct usbi_os_backend linux_usbfs_backend = { .get_config_descriptor = op_get_config_descriptor, .get_config_descriptor_by_value = op_get_config_descriptor_by_value, + .wrap_sys_device = op_wrap_sys_device, .open = op_open, .close = op_close, .get_configuration = op_get_configuration, diff --git a/Externals/libusb/libusb/os/linux_usbfs.h b/Externals/libusb/libusb/os/linux_usbfs.h index 8bd3ebcb16..a57eb413b6 100644 --- a/Externals/libusb/libusb/os/linux_usbfs.h +++ b/Externals/libusb/libusb/os/linux_usbfs.h @@ -81,10 +81,11 @@ struct usbfs_iso_packet_desc { unsigned int status; }; -#define MAX_ISO_BUFFER_LENGTH 49152 * 128 #define MAX_BULK_BUFFER_LENGTH 16384 #define MAX_CTRL_BUFFER_LENGTH 4096 +#define MAX_ISO_PACKETS_PER_URB 128 + struct usbfs_urb { unsigned char type; unsigned char endpoint; @@ -186,7 +187,7 @@ void linux_device_disconnected(uint8_t busnum, uint8_t devaddr); int linux_get_device_address (struct libusb_context *ctx, int detached, uint8_t *busnum, uint8_t *devaddr, const char *dev_node, - const char *sys_name); + const char *sys_name, int fd); int linux_enumerate_device(struct libusb_context *ctx, uint8_t busnum, uint8_t devaddr, const char *sysfs_dir); diff --git a/Externals/libusb/libusb/os/netbsd_usb.c b/Externals/libusb/libusb/os/netbsd_usb.c index ad1ede73e1..79aeca970e 100644 --- a/Externals/libusb/libusb/os/netbsd_usb.c +++ b/Externals/libusb/libusb/os/netbsd_usb.c @@ -86,11 +86,12 @@ static int _sync_control_transfer(struct usbi_transfer *); static int _sync_gen_transfer(struct usbi_transfer *); static int _access_endpoint(struct libusb_transfer *); -const struct usbi_os_backend netbsd_backend = { +const struct usbi_os_backend usbi_backend = { "Synchronous NetBSD backend", 0, NULL, /* init() */ NULL, /* exit() */ + NULL, /* set_option() */ netbsd_get_device_list, NULL, /* hotplug_poll */ netbsd_open, @@ -131,6 +132,7 @@ const struct usbi_os_backend netbsd_backend = { netbsd_handle_transfer_completion, netbsd_clock_gettime, + 0, /* context_priv_size */ sizeof(struct device_priv), sizeof(struct handle_priv), 0, /* transfer_priv_size */ @@ -212,8 +214,9 @@ error: int netbsd_open(struct libusb_device_handle *handle) { - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; + struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; + int i; dpriv->fd = open(dpriv->devnode, O_RDWR); if (dpriv->fd < 0) { @@ -222,6 +225,9 @@ netbsd_open(struct libusb_device_handle *handle) return _errno_to_libusb(errno); } + for (i = 0; i < USB_MAX_ENDPOINTS; i++) + hpriv->endpoints[i] = -1; + usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd); return (LIBUSB_SUCCESS); @@ -230,7 +236,6 @@ netbsd_open(struct libusb_device_handle *handle) void netbsd_close(struct libusb_device_handle *handle) { - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; usbi_dbg("close: fd %d", dpriv->fd); diff --git a/Externals/libusb/libusb/os/openbsd_usb.c b/Externals/libusb/libusb/os/openbsd_usb.c index c660257114..f174e496c4 100644 --- a/Externals/libusb/libusb/os/openbsd_usb.c +++ b/Externals/libusb/libusb/os/openbsd_usb.c @@ -89,11 +89,12 @@ static int _access_endpoint(struct libusb_transfer *); static int _bus_open(int); -const struct usbi_os_backend openbsd_backend = { +const struct usbi_os_backend usbi_backend = { "Synchronous OpenBSD backend", 0, NULL, /* init() */ NULL, /* exit() */ + NULL, /* set_option() */ obsd_get_device_list, NULL, /* hotplug_poll */ obsd_open, @@ -134,6 +135,7 @@ const struct usbi_os_backend openbsd_backend = { obsd_handle_transfer_completion, obsd_clock_gettime, + 0, /* context_priv_size */ sizeof(struct device_priv), sizeof(struct handle_priv), 0, /* transfer_priv_size */ @@ -246,7 +248,6 @@ obsd_get_device_list(struct libusb_context * ctx, int obsd_open(struct libusb_device_handle *handle) { - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; char devnode[16]; @@ -270,7 +271,6 @@ obsd_open(struct libusb_device_handle *handle) void obsd_close(struct libusb_device_handle *handle) { - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; if (dpriv->devname) { diff --git a/Externals/libusb/libusb/os/poll_posix.c b/Externals/libusb/libusb/os/poll_posix.c index e2f55a57a1..337714aa6b 100644 --- a/Externals/libusb/libusb/os/poll_posix.c +++ b/Externals/libusb/libusb/os/poll_posix.c @@ -29,25 +29,56 @@ int usbi_pipe(int pipefd[2]) { +#if defined(HAVE_PIPE2) + int ret = pipe2(pipefd, O_CLOEXEC); +#else int ret = pipe(pipefd); +#endif + if (ret != 0) { + usbi_err(NULL, "failed to create pipe (%d)", errno); return ret; } + +#if !defined(HAVE_PIPE2) && defined(FD_CLOEXEC) + ret = fcntl(pipefd[0], F_GETFD); + if (ret == -1) { + usbi_err(NULL, "failed to get pipe fd flags (%d)", errno); + goto err_close_pipe; + } + ret = fcntl(pipefd[0], F_SETFD, ret | FD_CLOEXEC); + if (ret == -1) { + usbi_err(NULL, "failed to set pipe fd flags (%d)", errno); + goto err_close_pipe; + } + + ret = fcntl(pipefd[1], F_GETFD); + if (ret == -1) { + usbi_err(NULL, "failed to get pipe fd flags (%d)", errno); + goto err_close_pipe; + } + ret = fcntl(pipefd[1], F_SETFD, ret | FD_CLOEXEC); + if (ret == -1) { + usbi_err(NULL, "failed to set pipe fd flags (%d)", errno); + goto err_close_pipe; + } +#endif + ret = fcntl(pipefd[1], F_GETFL); if (ret == -1) { - usbi_dbg("Failed to get pipe fd flags: %d", errno); + usbi_err(NULL, "failed to get pipe fd status flags (%d)", errno); goto err_close_pipe; } ret = fcntl(pipefd[1], F_SETFL, ret | O_NONBLOCK); - if (ret != 0) { - usbi_dbg("Failed to set non-blocking on new pipe: %d", errno); + if (ret == -1) { + usbi_err(NULL, "failed to set pipe fd status flags (%d)", errno); goto err_close_pipe; } return 0; err_close_pipe: - usbi_close(pipefd[0]); - usbi_close(pipefd[1]); + close(pipefd[0]); + close(pipefd[1]); return ret; } diff --git a/Externals/libusb/libusb/os/poll_posix.h b/Externals/libusb/libusb/os/poll_posix.h index 5b4b2c905e..bc0239caa2 100644 --- a/Externals/libusb/libusb/os/poll_posix.h +++ b/Externals/libusb/libusb/os/poll_posix.h @@ -8,4 +8,7 @@ int usbi_pipe(int pipefd[2]); +#define usbi_inc_fds_ref(x, y) +#define usbi_dec_fds_ref(x, y) + #endif /* LIBUSB_POLL_POSIX_H */ diff --git a/Externals/libusb/libusb/os/poll_windows.c b/Externals/libusb/libusb/os/poll_windows.c index 9825607512..208953b4b9 100644 --- a/Externals/libusb/libusb/os/poll_windows.c +++ b/Externals/libusb/libusb/os/poll_windows.c @@ -1,9 +1,6 @@ /* * poll_windows: poll compatibility wrapper for Windows - * Copyright © 2012-2013 RealVNC Ltd. - * Copyright © 2009-2010 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of poll implementation from libusb-win32, by Stephan Meyer et al. + * Copyright © 2017 Chris Dickens * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -31,9 +28,6 @@ * - obtain a Windows HANDLE to a file or device that has been opened in * OVERLAPPED mode * - call usbi_create_fd with this handle to obtain a custom fd. - * Note that if you need simultaneous R/W access, you need to call create_fd - * twice, once in RW_READ and once in RW_WRITE mode to obtain 2 separate - * pollable fds * - leave the core functions call the poll routine and flag POLLIN/POLLOUT * * The pipe pollable synchronous I/O works using the overlapped event associated @@ -42,465 +36,176 @@ */ #include +#include #include -#include #include #include "libusbi.h" - -// Uncomment to debug the polling layer -//#define DEBUG_POLL_WINDOWS -#if defined(DEBUG_POLL_WINDOWS) -#define poll_dbg usbi_dbg -#else -// MSVC++ < 2005 cannot use a variadic argument and non MSVC -// compilers produce warnings if parenthesis are omitted. -#if defined(_MSC_VER) && (_MSC_VER < 1400) -#define poll_dbg -#else -#define poll_dbg(...) -#endif -#endif - -#if defined(_PREFAST_) -#pragma warning(disable:28719) -#endif - -#define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0) +#include "windows_common.h" // public fd data -const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, NULL, NULL, RW_NONE}; -struct winfd poll_fd[MAX_FDS]; -// internal fd data -struct { - CRITICAL_SECTION mutex; // lock for fds - // Additional variables for XP CancelIoEx partial emulation - HANDLE original_handle; - DWORD thread_id; -} _poll_fd[MAX_FDS]; +const struct winfd INVALID_WINFD = { -1, NULL }; -// globals -BOOLEAN is_polling_set = FALSE; -LONG pipe_number = 0; -static volatile LONG compat_spinlock = 0; +// private data +struct file_descriptor { + enum fd_type { FD_TYPE_PIPE, FD_TYPE_TRANSFER } type; + OVERLAPPED overlapped; + int refcount; +}; -#if !defined(_WIN32_WCE) -// CancelIoEx, available on Vista and later only, provides the ability to cancel -// a single transfer (OVERLAPPED) when used. As it may not be part of any of the -// platform headers, we hook into the Kernel32 system DLL directly to seek it. -static BOOL (__stdcall *pCancelIoEx)(HANDLE, LPOVERLAPPED) = NULL; -#define Use_Duplicate_Handles (pCancelIoEx == NULL) +static usbi_mutex_static_t fd_table_lock = USBI_MUTEX_INITIALIZER; +static struct file_descriptor *fd_table[MAX_FDS]; -static inline void setup_cancel_io(void) +static struct file_descriptor *create_fd(enum fd_type type) { - HMODULE hKernel32 = GetModuleHandleA("KERNEL32"); - if (hKernel32 != NULL) { - pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED)) - GetProcAddress(hKernel32, "CancelIoEx"); - } - usbi_dbg("Will use CancelIo%s for I/O cancellation", - Use_Duplicate_Handles?"":"Ex"); -} - -static inline BOOL cancel_io(int _index) -{ - if ((_index < 0) || (_index >= MAX_FDS)) { - return FALSE; - } - - if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE) - || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) { - return TRUE; - } - if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) { - // Cancel outstanding transfer via the specific callback - (*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer); - return TRUE; - } - if (pCancelIoEx != NULL) { - return (*pCancelIoEx)(poll_fd[_index].handle, poll_fd[_index].overlapped); - } - if (_poll_fd[_index].thread_id == GetCurrentThreadId()) { - return CancelIo(poll_fd[_index].handle); - } - usbi_warn(NULL, "Unable to cancel I/O that was started from another thread"); - return FALSE; -} -#else -#define Use_Duplicate_Handles FALSE - -static __inline void setup_cancel_io() -{ - // No setup needed on WinCE -} - -static __inline BOOL cancel_io(int _index) -{ - if ((_index < 0) || (_index >= MAX_FDS)) { - return FALSE; - } - if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE) - || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) { - return TRUE; - } - if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) { - // Cancel outstanding transfer via the specific callback - (*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer); - } - return TRUE; -} -#endif - -// Init -void init_polling(void) -{ - int i; - - while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) { - SleepEx(0, TRUE); - } - if (!is_polling_set) { - setup_cancel_io(); - for (i=0; ioverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (fd->overlapped.hEvent == NULL) { + free(fd); return NULL; } - overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if(overlapped->hEvent == NULL) { - free (overlapped); - return NULL; - } - return overlapped; + fd->type = type; + fd->refcount = 1; + return fd; } -static void free_overlapped(OVERLAPPED *overlapped) +static void free_fd(struct file_descriptor *fd) { - if (overlapped == NULL) - return; - - if ( (overlapped->hEvent != 0) - && (overlapped->hEvent != INVALID_HANDLE_VALUE) ) { - CloseHandle(overlapped->hEvent); - } - free(overlapped); -} - -void exit_polling(void) -{ - int i; - - while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) { - SleepEx(0, TRUE); - } - if (is_polling_set) { - is_polling_set = FALSE; - - for (i=0; ioverlapped.hEvent); + free(fd); } /* - * Create a fake pipe. - * As libusb only uses pipes for signaling, all we need from a pipe is an - * event. To that extent, we create a single wfd and overlapped as a means - * to access that event. - */ -int usbi_pipe(int filedes[2]) -{ - int i; - OVERLAPPED* overlapped; - - CHECK_INIT_POLLING; - - overlapped = create_overlapped(); - - if (overlapped == NULL) { - return -1; - } - // The overlapped must have status pending for signaling to work in poll - overlapped->Internal = STATUS_PENDING; - overlapped->InternalHigh = 0; - - for (i=0; i= 0) { - LeaveCriticalSection(&_poll_fd[i].mutex); - continue; - } - - // Use index as the unique fd number - poll_fd[i].fd = i; - // Read end of the "pipe" - filedes[0] = poll_fd[i].fd; - // We can use the same handle for both ends - filedes[1] = filedes[0]; - - poll_fd[i].handle = DUMMY_HANDLE; - poll_fd[i].overlapped = overlapped; - // There's no polling on the write end, so we just use READ for our needs - poll_fd[i].rw = RW_READ; - _poll_fd[i].original_handle = INVALID_HANDLE_VALUE; - LeaveCriticalSection(&_poll_fd[i].mutex); - return 0; - } - } - free_overlapped(overlapped); - return -1; -} - -/* - * Create both an fd and an OVERLAPPED from an open Windows handle, so that - * it can be used with our polling function + * Create both an fd and an OVERLAPPED, so that it can be used with our + * polling function * The handle MUST support overlapped transfers (usually requires CreateFile * with FILE_FLAG_OVERLAPPED) * Return a pollable file descriptor struct, or INVALID_WINFD on error * * Note that the fd returned by this function is a per-transfer fd, rather * than a per-session fd and cannot be used for anything else but our - * custom functions (the fd itself points to the NUL: device) + * custom functions. * if you plan to do R/W on the same handle, you MUST create 2 fds: one for * read and one for write. Using a single R/W fd is unsupported and will * produce unexpected results */ -struct winfd usbi_create_fd(HANDLE handle, int access_mode, struct usbi_transfer *itransfer, cancel_transfer *cancel_fn) +struct winfd usbi_create_fd(void) { - int i; - struct winfd wfd = INVALID_WINFD; - OVERLAPPED* overlapped = NULL; - - CHECK_INIT_POLLING; - - if ((handle == 0) || (handle == INVALID_HANDLE_VALUE)) { - return INVALID_WINFD; - } - - wfd.itransfer = itransfer; - wfd.cancel_fn = cancel_fn; - - if ((access_mode != RW_READ) && (access_mode != RW_WRITE)) { - usbi_warn(NULL, "only one of RW_READ or RW_WRITE are supported. " - "If you want to poll for R/W simultaneously, create multiple fds from the same handle."); - return INVALID_WINFD; - } - if (access_mode == RW_READ) { - wfd.rw = RW_READ; - } else { - wfd.rw = RW_WRITE; - } - - overlapped = create_overlapped(); - if(overlapped == NULL) { - return INVALID_WINFD; - } - - for (i=0; i= 0) { - LeaveCriticalSection(&_poll_fd[i].mutex); - continue; - } - // Use index as the unique fd number - wfd.fd = i; - // Attempt to emulate some of the CancelIoEx behaviour on platforms - // that don't have it - if (Use_Duplicate_Handles) { - _poll_fd[i].thread_id = GetCurrentThreadId(); - if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), - &wfd.handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) { - usbi_dbg("could not duplicate handle for CancelIo - using original one"); - wfd.handle = handle; - // Make sure we won't close the original handle on fd deletion then - _poll_fd[i].original_handle = INVALID_HANDLE_VALUE; - } else { - _poll_fd[i].original_handle = handle; - } - } else { - wfd.handle = handle; - } - wfd.overlapped = overlapped; - memcpy(&poll_fd[i], &wfd, sizeof(struct winfd)); - LeaveCriticalSection(&_poll_fd[i].mutex); - return wfd; - } - } - free_overlapped(overlapped); - return INVALID_WINFD; -} - -static void _free_index(int _index) -{ - // Cancel any async IO (Don't care about the validity of our handles for this) - cancel_io(_index); - // close the duplicate handle (if we have an actual duplicate) - if (Use_Duplicate_Handles) { - if (_poll_fd[_index].original_handle != INVALID_HANDLE_VALUE) { - CloseHandle(poll_fd[_index].handle); - } - _poll_fd[_index].original_handle = INVALID_HANDLE_VALUE; - _poll_fd[_index].thread_id = 0; - } - free_overlapped(poll_fd[_index].overlapped); - poll_fd[_index] = INVALID_WINFD; -} - -/* - * Release a pollable file descriptor. - * - * Note that the associated Windows handle is not closed by this call - */ -void usbi_free_fd(struct winfd *wfd) -{ - int _index; - - CHECK_INIT_POLLING; - - _index = _fd_to_index_and_lock(wfd->fd); - if (_index < 0) { - return; - } - _free_index(_index); - *wfd = INVALID_WINFD; - LeaveCriticalSection(&_poll_fd[_index].mutex); -} - -/* - * The functions below perform various conversions between fd, handle and OVERLAPPED - */ -struct winfd fd_to_winfd(int fd) -{ - int i; + struct file_descriptor *fd; struct winfd wfd; - CHECK_INIT_POLLING; - - if (fd < 0) + fd = create_fd(FD_TYPE_TRANSFER); + if (fd == NULL) return INVALID_WINFD; - for (i=0; ioverlapped; + + return wfd; } -struct winfd handle_to_winfd(HANDLE handle) +int usbi_inc_fds_ref(struct pollfd *fds, unsigned int nfds) { - int i; - struct winfd wfd; - - CHECK_INIT_POLLING; - - if ((handle == 0) || (handle == INVALID_HANDLE_VALUE)) - return INVALID_WINFD; - - for (i=0; irefcount++; } - return INVALID_WINFD; + usbi_mutex_static_unlock(&fd_table_lock); } -struct winfd overlapped_to_winfd(OVERLAPPED* overlapped) +int usbi_dec_fds_ref(struct pollfd *fds, unsigned int nfds) { - int i; - struct winfd wfd; + int n; + struct file_descriptor *fd; - CHECK_INIT_POLLING; - - if (overlapped == NULL) - return INVALID_WINFD; - - for (i=0; irefcount--; + if (fd->refcount == 0) + { + if (fd->type == FD_TYPE_PIPE) { + // InternalHigh is our reference count + fd->overlapped.InternalHigh--; + if (fd->overlapped.InternalHigh == 0) + free_fd(fd); } - memcpy(&wfd, &poll_fd[i], sizeof(struct winfd)); - LeaveCriticalSection(&_poll_fd[i].mutex); - return wfd; + else { + free_fd(fd); + } + fd_table[fds[n].fd] = NULL; } } - return INVALID_WINFD; + usbi_mutex_static_unlock(&fd_table_lock); } + +static int check_pollfds(struct pollfd *fds, unsigned int nfds, + HANDLE *wait_handles, DWORD *nb_wait_handles) +{ + struct file_descriptor *fd; + unsigned int n; + int nready = 0; + + usbi_mutex_static_lock(&fd_table_lock); + + for (n = 0; n < nfds; ++n) { + fds[n].revents = 0; + + // Keep it simple - only allow either POLLIN *or* POLLOUT + assert((fds[n].events == POLLIN) || (fds[n].events == POLLOUT)); + if ((fds[n].events != POLLIN) && (fds[n].events != POLLOUT)) { + fds[n].revents = POLLNVAL; + nready++; + continue; + } + + if ((fds[n].fd >= 0) && (fds[n].fd < MAX_FDS)) + fd = fd_table[fds[n].fd]; + else + fd = NULL; + + assert(fd != NULL); + if (fd == NULL) { + fds[n].revents = POLLNVAL; + nready++; + continue; + } + + if (HasOverlappedIoCompleted(&fd->overlapped) + && (WaitForSingleObject(fd->overlapped.hEvent, 0) == WAIT_OBJECT_0)) { + fds[n].revents = fds[n].events; + nready++; + } else if (wait_handles != NULL) { + if (*nb_wait_handles == MAXIMUM_WAIT_OBJECTS) { + usbi_warn(NULL, "too many HANDLEs to wait on"); + continue; + } + wait_handles[*nb_wait_handles] = fd->overlapped.hEvent; + (*nb_wait_handles)++; + } + } + + usbi_mutex_static_unlock(&fd_table_lock); + + return nready; +} /* * POSIX poll equivalent, using Windows OVERLAPPED * Currently, this function only accepts one of POLLIN or POLLOUT per fd @@ -508,143 +213,121 @@ struct winfd overlapped_to_winfd(OVERLAPPED* overlapped) */ int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout) { - unsigned i; - int _index, object_index, triggered; - HANDLE *handles_to_wait_on; - int *handle_to_index; - DWORD nb_handles_to_wait_on = 0; + HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS]; + DWORD nb_wait_handles = 0; DWORD ret; + int nready; - CHECK_INIT_POLLING; - - triggered = 0; - handles_to_wait_on = (HANDLE*) calloc(nfds+1, sizeof(HANDLE)); // +1 for fd_update - handle_to_index = (int*) calloc(nfds, sizeof(int)); - if ((handles_to_wait_on == NULL) || (handle_to_index == NULL)) { - errno = ENOMEM; - triggered = -1; - goto poll_exit; - } - - for (i = 0; i < nfds; ++i) { - fds[i].revents = 0; - - // Only one of POLLIN or POLLOUT can be selected with this version of poll (not both) - if ((fds[i].events & ~POLLIN) && (!(fds[i].events & POLLOUT))) { - fds[i].revents |= POLLERR; - errno = EACCES; - usbi_warn(NULL, "unsupported set of events"); - triggered = -1; - goto poll_exit; - } - - _index = _fd_to_index_and_lock(fds[i].fd); - poll_dbg("fd[%d]=%d: (overlapped=%p) got events %04X", i, poll_fd[_index].fd, poll_fd[_index].overlapped, fds[i].events); - - if ( (_index < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE) - || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL)) { - fds[i].revents |= POLLNVAL | POLLERR; - errno = EBADF; - if (_index >= 0) { - LeaveCriticalSection(&_poll_fd[_index].mutex); - } - usbi_warn(NULL, "invalid fd"); - triggered = -1; - goto poll_exit; - } - - // IN or OUT must match our fd direction - if ((fds[i].events & POLLIN) && (poll_fd[_index].rw != RW_READ)) { - fds[i].revents |= POLLNVAL | POLLERR; - errno = EBADF; - usbi_warn(NULL, "attempted POLLIN on fd without READ access"); - LeaveCriticalSection(&_poll_fd[_index].mutex); - triggered = -1; - goto poll_exit; - } - - if ((fds[i].events & POLLOUT) && (poll_fd[_index].rw != RW_WRITE)) { - fds[i].revents |= POLLNVAL | POLLERR; - errno = EBADF; - usbi_warn(NULL, "attempted POLLOUT on fd without WRITE access"); - LeaveCriticalSection(&_poll_fd[_index].mutex); - triggered = -1; - goto poll_exit; - } - - // The following macro only works if overlapped I/O was reported pending - if ( (HasOverlappedIoCompleted(poll_fd[_index].overlapped)) - || (HasOverlappedIoCompletedSync(poll_fd[_index].overlapped)) ) { - poll_dbg(" completed"); - // checks above should ensure this works: - fds[i].revents = fds[i].events; - triggered++; - } else { - handles_to_wait_on[nb_handles_to_wait_on] = poll_fd[_index].overlapped->hEvent; - handle_to_index[nb_handles_to_wait_on] = i; - nb_handles_to_wait_on++; - } - LeaveCriticalSection(&_poll_fd[_index].mutex); - } + nready = check_pollfds(fds, nfds, wait_handles, &nb_wait_handles); // If nothing was triggered, wait on all fds that require it - if ((timeout != 0) && (triggered == 0) && (nb_handles_to_wait_on != 0)) { - if (timeout < 0) { - poll_dbg("starting infinite wait for %u handles...", (unsigned int)nb_handles_to_wait_on); - } else { - poll_dbg("starting %d ms wait for %u handles...", timeout, (unsigned int)nb_handles_to_wait_on); - } - ret = WaitForMultipleObjects(nb_handles_to_wait_on, handles_to_wait_on, - FALSE, (timeout<0)?INFINITE:(DWORD)timeout); - object_index = ret-WAIT_OBJECT_0; - if ((object_index >= 0) && ((DWORD)object_index < nb_handles_to_wait_on)) { - poll_dbg(" completed after wait"); - i = handle_to_index[object_index]; - _index = _fd_to_index_and_lock(fds[i].fd); - fds[i].revents = fds[i].events; - triggered++; - if (_index >= 0) { - LeaveCriticalSection(&_poll_fd[_index].mutex); - } - } else if (ret == WAIT_TIMEOUT) { - poll_dbg(" timed out"); - triggered = 0; // 0 = timeout - } else { - errno = EIO; - triggered = -1; // error + if ((nready == 0) && (nb_wait_handles != 0) && (timeout != 0)) { + ret = WaitForMultipleObjects(nb_wait_handles, wait_handles, + FALSE, (timeout < 0) ? INFINITE : (DWORD)timeout); + if (ret < (WAIT_OBJECT_0 + nb_wait_handles)) { + nready = check_pollfds(fds, nfds, NULL, NULL); + } else if (ret != WAIT_TIMEOUT) { + if (ret == WAIT_FAILED) + usbi_err(NULL, "WaitForMultipleObjects failed: %u", (unsigned int)GetLastError()); + nready = -1; } } -poll_exit: - if (handles_to_wait_on != NULL) { - free(handles_to_wait_on); - } - if (handle_to_index != NULL) { - free(handle_to_index); - } - return triggered; + return nready; } /* - * close a fake pipe fd + * close a fake file descriptor */ -int usbi_close(int fd) +int usbi_close(int _fd) { - int _index; - int r = -1; + struct file_descriptor *fd; - CHECK_INIT_POLLING; + if (_fd < 0 || _fd >= MAX_FDS) + goto err_badfd; - _index = _fd_to_index_and_lock(fd); + usbi_mutex_static_lock(&fd_table_lock); + fd = fd_table[_fd]; + fd->refcount--; + if(fd->refcount==0) + { fd_table[_fd] = NULL; - if (_index < 0) { - errno = EBADF; - } else { - free_overlapped(poll_fd[_index].overlapped); - poll_fd[_index] = INVALID_WINFD; - LeaveCriticalSection(&_poll_fd[_index].mutex); + if (fd->type == FD_TYPE_PIPE) { + // InternalHigh is our reference count + fd->overlapped.InternalHigh--; + if (fd->overlapped.InternalHigh == 0) + free_fd(fd); + } + else { + free_fd(fd); + } } - return r; + usbi_mutex_static_unlock(&fd_table_lock); + + if (fd == NULL) + goto err_badfd; + + return 0; + +err_badfd: + errno = EBADF; + return -1; +} + +/* +* Create a fake pipe. +* As libusb only uses pipes for signaling, all we need from a pipe is an +* event. To that extent, we create a single wfd and overlapped as a means +* to access that event. +*/ +int usbi_pipe(int filedes[2]) +{ + struct file_descriptor *fd; + int r_fd = -1, w_fd = -1; + int i; + + fd = create_fd(FD_TYPE_PIPE); + if (fd == NULL) { + errno = ENOMEM; + return -1; + } + + // Use InternalHigh as a reference count + fd->overlapped.Internal = STATUS_PENDING; + fd->overlapped.InternalHigh = 2; + + usbi_mutex_static_lock(&fd_table_lock); + do { + for (i = 0; i < MAX_FDS; i++) { + if (fd_table[i] != NULL) + continue; + if (r_fd == -1) { + r_fd = i; + } else if (w_fd == -1) { + w_fd = i; + break; + } + } + + if (i == MAX_FDS) + break; + + fd_table[r_fd] = fd; + fd_table[w_fd] = fd; + + } while (0); + usbi_mutex_static_unlock(&fd_table_lock); + + if (i == MAX_FDS) { + free_fd(fd); + errno = EMFILE; + return -1; + } + + filedes[0] = r_fd; + filedes[1] = w_fd; + + return 0; } /* @@ -652,35 +335,37 @@ int usbi_close(int fd) */ ssize_t usbi_write(int fd, const void *buf, size_t count) { - int _index; + int error = EBADF; + UNUSED(buf); - CHECK_INIT_POLLING; + if (fd < 0 || fd >= MAX_FDS) + goto err_out; if (count != sizeof(unsigned char)) { usbi_err(NULL, "this function should only used for signaling"); - return -1; + error = EINVAL; + goto err_out; } - _index = _fd_to_index_and_lock(fd); - - if ( (_index < 0) || (poll_fd[_index].overlapped == NULL) ) { - errno = EBADF; - if (_index >= 0) { - LeaveCriticalSection(&_poll_fd[_index].mutex); - } - return -1; + usbi_mutex_static_lock(&fd_table_lock); + if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) { + assert(fd_table[fd]->overlapped.Internal == STATUS_PENDING); + assert(fd_table[fd]->overlapped.InternalHigh == 2); + fd_table[fd]->overlapped.Internal = STATUS_WAIT_0; + SetEvent(fd_table[fd]->overlapped.hEvent); + error = 0; } + usbi_mutex_static_unlock(&fd_table_lock); - poll_dbg("set pipe event (fd = %d, thread = %08X)", _index, (unsigned int)GetCurrentThreadId()); - SetEvent(poll_fd[_index].overlapped->hEvent); - poll_fd[_index].overlapped->Internal = STATUS_WAIT_0; - // If two threads write on the pipe at the same time, we need to - // process two separate reads => use the overlapped as a counter - poll_fd[_index].overlapped->InternalHigh++; + if (error) + goto err_out; - LeaveCriticalSection(&_poll_fd[_index].mutex); return sizeof(unsigned char); + +err_out: + errno = error; + return -1; } /* @@ -688,41 +373,35 @@ ssize_t usbi_write(int fd, const void *buf, size_t count) */ ssize_t usbi_read(int fd, void *buf, size_t count) { - int _index; - ssize_t r = -1; + int error = EBADF; + UNUSED(buf); - CHECK_INIT_POLLING; + if (fd < 0 || fd >= MAX_FDS) + goto err_out; if (count != sizeof(unsigned char)) { usbi_err(NULL, "this function should only used for signaling"); - return -1; + error = EINVAL; + goto err_out; } - _index = _fd_to_index_and_lock(fd); - - if (_index < 0) { - errno = EBADF; - return -1; + usbi_mutex_static_lock(&fd_table_lock); + if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) { + assert(fd_table[fd]->overlapped.Internal == STATUS_WAIT_0); + assert(fd_table[fd]->overlapped.InternalHigh == 2); + fd_table[fd]->overlapped.Internal = STATUS_PENDING; + ResetEvent(fd_table[fd]->overlapped.hEvent); + error = 0; } + usbi_mutex_static_unlock(&fd_table_lock); - if (WaitForSingleObject(poll_fd[_index].overlapped->hEvent, INFINITE) != WAIT_OBJECT_0) { - usbi_warn(NULL, "waiting for event failed: %u", (unsigned int)GetLastError()); - errno = EIO; - goto out; - } + if (error) + goto err_out; - poll_dbg("clr pipe event (fd = %d, thread = %08X)", _index, (unsigned int)GetCurrentThreadId()); - poll_fd[_index].overlapped->InternalHigh--; - // Don't reset unless we don't have any more events to process - if (poll_fd[_index].overlapped->InternalHigh <= 0) { - ResetEvent(poll_fd[_index].overlapped->hEvent); - poll_fd[_index].overlapped->Internal = STATUS_PENDING; - } + return sizeof(unsigned char); - r = sizeof(unsigned char); - -out: - LeaveCriticalSection(&_poll_fd[_index].mutex); - return r; +err_out: + errno = error; + return -1; } diff --git a/Externals/libusb/libusb/os/poll_windows.h b/Externals/libusb/libusb/os/poll_windows.h index aa4c985dae..980870d827 100644 --- a/Externals/libusb/libusb/os/poll_windows.h +++ b/Externals/libusb/libusb/os/poll_windows.h @@ -2,6 +2,7 @@ * Windows compat: POSIX compatibility wrapper * Copyright © 2012-2013 RealVNC Ltd. * Copyright © 2009-2010 Pete Batard + * Copyright © 2016-2018 Chris Dickens * With contributions from Michael Plante, Orin Eman et al. * Parts of poll implementation from libusb-win32, by Stephan Meyer et al. * @@ -40,21 +41,6 @@ #define DUMMY_HANDLE ((HANDLE)(LONG_PTR)-2) -/* Windows versions */ -enum windows_version { - WINDOWS_CE = -2, - WINDOWS_UNDEFINED = -1, - WINDOWS_UNSUPPORTED = 0, - WINDOWS_XP = 0x51, - WINDOWS_2003 = 0x52, // Also XP x64 - WINDOWS_VISTA = 0x60, - WINDOWS_7 = 0x61, - WINDOWS_8 = 0x62, - WINDOWS_8_1_OR_LATER = 0x63, - WINDOWS_MAX -}; -extern int windows_version; - #define MAX_FDS 256 #define POLLIN 0x0001 /* There is data to read */ @@ -65,45 +51,28 @@ extern int windows_version; #define POLLNVAL 0x0020 /* Invalid request: fd not open */ struct pollfd { - int fd; /* file descriptor */ - short events; /* requested events */ - short revents; /* returned events */ + int fd; /* file descriptor */ + short events; /* requested events */ + short revents; /* returned events */ }; -// access modes -enum rw_type { - RW_NONE, - RW_READ, - RW_WRITE, -}; - -// fd struct that can be used for polling on Windows -typedef int cancel_transfer(struct usbi_transfer *itransfer); - struct winfd { - int fd; // what's exposed to libusb core - HANDLE handle; // what we need to attach overlapped to the I/O op, so we can poll it - OVERLAPPED* overlapped; // what will report our I/O status - struct usbi_transfer *itransfer; // Associated transfer, or NULL if completed - cancel_transfer *cancel_fn; // Function pointer to cancel transfer API - enum rw_type rw; // I/O transfer direction: read *XOR* write (NOT BOTH) + int fd; // what's exposed to libusb core + OVERLAPPED *overlapped; // what will report our I/O status }; + extern const struct winfd INVALID_WINFD; +struct winfd usbi_create_fd(void); + int usbi_pipe(int pipefd[2]); int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout); ssize_t usbi_write(int fd, const void *buf, size_t count); ssize_t usbi_read(int fd, void *buf, size_t count); int usbi_close(int fd); -void init_polling(void); -void exit_polling(void); -struct winfd usbi_create_fd(HANDLE handle, int access_mode, - struct usbi_transfer *transfer, cancel_transfer *cancel_fn); -void usbi_free_fd(struct winfd* winfd); -struct winfd fd_to_winfd(int fd); -struct winfd handle_to_winfd(HANDLE handle); -struct winfd overlapped_to_winfd(OVERLAPPED* overlapped); +int usbi_inc_fds_ref(struct pollfd *fds, unsigned int nfds); +int usbi_dec_fds_ref(struct pollfd *fds, unsigned int nfds); /* * Timeval operations diff --git a/Externals/libusb/libusb/os/sunos_usb.c b/Externals/libusb/libusb/os/sunos_usb.c index cb608976b6..6a3f633f97 100644 --- a/Externals/libusb/libusb/os/sunos_usb.c +++ b/Externals/libusb/libusb/os/sunos_usb.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -28,21 +29,34 @@ #include #include #include +#include #include #include #include +#include +#include #include +#include #include #include #include "libusbi.h" #include "sunos_usb.h" +#define UPDATEDRV_PATH "/usr/sbin/update_drv" +#define UPDATEDRV "update_drv" + +typedef list_t string_list_t; +typedef struct string_node { + char *string; + list_node_t link; +} string_node_t; + /* * Backend functions */ static int sunos_init(struct libusb_context *); -static void sunos_exit(void); +static void sunos_exit(struct libusb_context *); static int sunos_get_device_list(struct libusb_context *, struct discovered_devs **); static int sunos_open(struct libusb_device_handle *); @@ -67,6 +81,162 @@ static int sunos_cancel_transfer(struct usbi_transfer *); static void sunos_clear_transfer_priv(struct usbi_transfer *); static int sunos_handle_transfer_completion(struct usbi_transfer *); static int sunos_clock_gettime(int, struct timespec *); +static int sunos_kernel_driver_active(struct libusb_device_handle *, int interface); +static int sunos_detach_kernel_driver (struct libusb_device_handle *dev, int interface_number); +static int sunos_attach_kernel_driver (struct libusb_device_handle *dev, int interface_number); +static int sunos_usb_open_ep0(sunos_dev_handle_priv_t *hpriv, sunos_dev_priv_t *dpriv); +static int sunos_usb_ioctl(struct libusb_device *dev, int cmd); + +static struct devctl_iocdata iocdata; +static int sunos_get_link(di_devlink_t devlink, void *arg) +{ + walk_link_t *larg = (walk_link_t *)arg; + const char *p; + const char *q; + + if (larg->path) { + char *content = (char *)di_devlink_content(devlink); + char *start = strstr(content, "/devices/"); + start += strlen("/devices"); + usbi_dbg("%s", start); + + /* line content must have minor node */ + if (start == NULL || + strncmp(start, larg->path, larg->len) != 0 || + start[larg->len] != ':') + return (DI_WALK_CONTINUE); + } + + p = di_devlink_path(devlink); + q = strrchr(p, '/'); + usbi_dbg("%s", q); + + *(larg->linkpp) = strndup(p, strlen(p) - strlen(q)); + + return (DI_WALK_TERMINATE); +} + + +static int sunos_physpath_to_devlink( + const char *node_path, const char *match, char **link_path) +{ + walk_link_t larg; + di_devlink_handle_t hdl; + + *link_path = NULL; + larg.linkpp = link_path; + if ((hdl = di_devlink_init(NULL, 0)) == NULL) { + usbi_dbg("di_devlink_init failure"); + return (-1); + } + + larg.len = strlen(node_path); + larg.path = (char *)node_path; + + (void) di_devlink_walk(hdl, match, NULL, DI_PRIMARY_LINK, + (void *)&larg, sunos_get_link); + + (void) di_devlink_fini(&hdl); + + if (*link_path == NULL) { + usbi_dbg("there is no devlink for this path"); + return (-1); + } + + return 0; +} + +static int +sunos_usb_ioctl(struct libusb_device *dev, int cmd) +{ + int fd; + nvlist_t *nvlist; + char *end; + char *phypath; + char *hubpath; + char path_arg[PATH_MAX]; + sunos_dev_priv_t *dpriv; + devctl_ap_state_t devctl_ap_state; + + dpriv = (sunos_dev_priv_t *)dev->os_priv; + phypath = dpriv->phypath; + + end = strrchr(phypath, '/'); + if (end == NULL) + return (-1); + hubpath = strndup(phypath, end - phypath); + if (hubpath == NULL) + return (-1); + + end = strrchr(hubpath, '@'); + if (end == NULL) { + free(hubpath); + return (-1); + } + end++; + usbi_dbg("unitaddr: %s", end); + + nvlist_alloc(&nvlist, NV_UNIQUE_NAME_TYPE, KM_NOSLEEP); + nvlist_add_int32(nvlist, "port", dev->port_number); + //find the hub path + snprintf(path_arg, sizeof(path_arg), "/devices%s:hubd", hubpath); + usbi_dbg("ioctl hub path: %s", path_arg); + + fd = open(path_arg, O_RDONLY); + if (fd < 0) { + usbi_err(DEVICE_CTX(dev), "open failed: %d (%s)", errno, strerror(errno)); + nvlist_free(nvlist); + free(hubpath); + return (-1); + } + + memset(&iocdata, 0, sizeof(iocdata)); + memset(&devctl_ap_state, 0, sizeof(devctl_ap_state)); + + nvlist_pack(nvlist, (char **)&iocdata.nvl_user, &iocdata.nvl_usersz, NV_ENCODE_NATIVE, 0); + + iocdata.cmd = DEVCTL_AP_GETSTATE; + iocdata.flags = 0; + iocdata.c_nodename = "hub"; + iocdata.c_unitaddr = end; + iocdata.cpyout_buf = &devctl_ap_state; + usbi_dbg("%p, %d", iocdata.nvl_user, iocdata.nvl_usersz); + + errno = 0; + if (ioctl(fd, DEVCTL_AP_GETSTATE, &iocdata) == -1) { + usbi_err(DEVICE_CTX(dev), "ioctl failed: fd %d, cmd %x, errno %d (%s)", + fd, DEVCTL_AP_GETSTATE, errno, strerror(errno)); + } else { + usbi_dbg("dev rstate: %d", devctl_ap_state.ap_rstate); + usbi_dbg("dev ostate: %d", devctl_ap_state.ap_ostate); + } + + errno = 0; + iocdata.cmd = cmd; + if (ioctl(fd, (int)cmd, &iocdata) != 0) { + usbi_err(DEVICE_CTX(dev), "ioctl failed: fd %d, cmd %x, errno %d (%s)", + fd, cmd, errno, strerror(errno)); + sleep(2); + } + + close(fd); + free(iocdata.nvl_user); + nvlist_free(nvlist); + free(hubpath); + + return (-errno); +} + +static int +sunos_kernel_driver_active(struct libusb_device_handle *dev, int interface) +{ + sunos_dev_priv_t *dpriv; + dpriv = (sunos_dev_priv_t *)dev->dev->os_priv; + + usbi_dbg("%s", dpriv->ugenpath); + + return (dpriv->ugenpath == NULL); +} /* * Private functions @@ -79,20 +249,239 @@ static int sunos_init(struct libusb_context *ctx) return (LIBUSB_SUCCESS); } -static void sunos_exit(void) +static void sunos_exit(struct libusb_context *ctx) { usbi_dbg(""); } +static string_list_t * +sunos_new_string_list(void) +{ + string_list_t *list; + + list = calloc(1, sizeof(*list)); + if (list != NULL) + list_create(list, sizeof(string_node_t), + offsetof(string_node_t, link)); + + return (list); +} + +static int +sunos_append_to_string_list(string_list_t *list, const char *arg) +{ + string_node_t *np; + + np = calloc(1, sizeof(*np)); + if (!np) + return (-1); + + np->string = strdup(arg); + if (!np->string) { + free(np); + return (-1); + } + + list_insert_tail(list, np); + + return (0); +} + +static void +sunos_free_string_list(string_list_t *list) +{ + string_node_t *np; + + while ((np = list_remove_head(list)) != NULL) { + free(np->string); + free(np); + } + + free(list); +} + +static char ** +sunos_build_argv_list(string_list_t *list) +{ + char **argv_list; + string_node_t *np; + int n; + + n = 1; /* Start at 1 for NULL terminator */ + for (np = list_head(list); np != NULL; np = list_next(list, np)) + n++; + + argv_list = calloc(n, sizeof(char *)); + if (argv_list == NULL) + return NULL; + + n = 0; + for (np = list_head(list); np != NULL; np = list_next(list, np)) + argv_list[n++] = np->string; + + return (argv_list); +} + + +static int +sunos_exec_command(struct libusb_context *ctx, const char *path, + string_list_t *list) +{ + pid_t pid; + int status; + int waitstat; + int exit_status; + char **argv_list; + + argv_list = sunos_build_argv_list(list); + if (argv_list == NULL) + return (-1); + + pid = fork(); + if (pid == 0) { + /* child */ + execv(path, argv_list); + _exit(127); + } else if (pid > 0) { + /* parent */ + do { + waitstat = waitpid(pid, &status, 0); + } while ((waitstat == -1 && errno == EINTR) || + (waitstat == 0 && !WIFEXITED(status) && !WIFSIGNALED(status))); + + if (waitstat == 0) { + if (WIFEXITED(status)) + exit_status = WEXITSTATUS(status); + else + exit_status = WTERMSIG(status); + } else { + usbi_err(ctx, "waitpid failed: errno %d (%s)", errno, strerror(errno)); + exit_status = -1; + } + } else { + /* fork failed */ + usbi_err(ctx, "fork failed: errno %d (%s)", errno, strerror(errno)); + exit_status = -1; + } + + free(argv_list); + + return (exit_status); +} + +static int +sunos_detach_kernel_driver(struct libusb_device_handle *dev_handle, + int interface_number) +{ + struct libusb_context *ctx = HANDLE_CTX(dev_handle); + string_list_t *list; + char path_arg[PATH_MAX]; + sunos_dev_priv_t *dpriv; + int r; + + dpriv = (sunos_dev_priv_t *)dev_handle->dev->os_priv; + snprintf(path_arg, sizeof(path_arg), "\'\"%s\"\'", dpriv->phypath); + usbi_dbg("%s", path_arg); + + list = sunos_new_string_list(); + if (list == NULL) + return (LIBUSB_ERROR_NO_MEM); + + /* attach ugen driver */ + r = 0; + r |= sunos_append_to_string_list(list, UPDATEDRV); + r |= sunos_append_to_string_list(list, "-a"); /* add rule */ + r |= sunos_append_to_string_list(list, "-i"); /* specific device */ + r |= sunos_append_to_string_list(list, path_arg); /* physical path */ + r |= sunos_append_to_string_list(list, "ugen"); + if (r) { + sunos_free_string_list(list); + return (LIBUSB_ERROR_NO_MEM); + } + + r = sunos_exec_command(ctx, UPDATEDRV_PATH, list); + sunos_free_string_list(list); + if (r < 0) + return (LIBUSB_ERROR_OTHER); + + /* reconfigure the driver node */ + r = 0; + r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_DISCONNECT); + r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE); + if (r) + usbi_warn(HANDLE_CTX(dev_handle), "one or more ioctls failed"); + + snprintf(path_arg, sizeof(path_arg), "^usb/%x.%x", dpriv->dev_descr.idVendor, + dpriv->dev_descr.idProduct); + sunos_physpath_to_devlink(dpriv->phypath, path_arg, &dpriv->ugenpath); + + if (access(dpriv->ugenpath, F_OK) == -1) { + usbi_err(HANDLE_CTX(dev_handle), "fail to detach kernel driver"); + return (LIBUSB_ERROR_IO); + } + + return sunos_usb_open_ep0((sunos_dev_handle_priv_t *)dev_handle->os_priv, dpriv); +} + +static int +sunos_attach_kernel_driver(struct libusb_device_handle *dev_handle, + int interface_number) +{ + struct libusb_context *ctx = HANDLE_CTX(dev_handle); + string_list_t *list; + char path_arg[PATH_MAX]; + sunos_dev_priv_t *dpriv; + int r; + + /* we open the dev in detach driver, so we need close it first. */ + sunos_close(dev_handle); + + dpriv = (sunos_dev_priv_t *)dev_handle->dev->os_priv; + snprintf(path_arg, sizeof(path_arg), "\'\"%s\"\'", dpriv->phypath); + usbi_dbg("%s", path_arg); + + list = sunos_new_string_list(); + if (list == NULL) + return (LIBUSB_ERROR_NO_MEM); + + /* detach ugen driver */ + r = 0; + r |= sunos_append_to_string_list(list, UPDATEDRV); + r |= sunos_append_to_string_list(list, "-d"); /* add rule */ + r |= sunos_append_to_string_list(list, "-i"); /* specific device */ + r |= sunos_append_to_string_list(list, path_arg); /* physical path */ + r |= sunos_append_to_string_list(list, "ugen"); + if (r) { + sunos_free_string_list(list); + return (LIBUSB_ERROR_NO_MEM); + } + + r = sunos_exec_command(ctx, UPDATEDRV_PATH, list); + sunos_free_string_list(list); + if (r < 0) + return (LIBUSB_ERROR_OTHER); + + /* reconfigure the driver node */ + r = 0; + r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE); + r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_DISCONNECT); + r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE); + if (r) + usbi_warn(HANDLE_CTX(dev_handle), "one or more ioctls failed"); + + return 0; +} + static int sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev) { int proplen; - int n, *addr, *port_prop; + int *i, n, *addr, *port_prop; char *phypath; uint8_t *rdata; struct libusb_device_descriptor *descr; sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; + char match_str[PATH_MAX]; /* Device descriptors */ proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, @@ -137,7 +526,11 @@ sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev) phypath = di_devfs_path(node); if (phypath) { dpriv->phypath = strdup(phypath); + snprintf(match_str, sizeof(match_str), "^usb/%x.%x", dpriv->dev_descr.idVendor, dpriv->dev_descr.idProduct); + usbi_dbg("match is %s", match_str); + sunos_physpath_to_devlink(dpriv->phypath, match_str, &dpriv->ugenpath); di_devfs_path_free(phypath); + } else { free(dpriv->raw_cfgdescr); @@ -153,13 +546,13 @@ sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev) } /* speed */ - if (di_prop_exists(DDI_DEV_T_ANY, node, "low-speed") == 1) { + if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "low-speed", &i) >= 0) { dev->speed = LIBUSB_SPEED_LOW; - } else if (di_prop_exists(DDI_DEV_T_ANY, node, "high-speed") == 1) { + } else if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "high-speed", &i) >= 0) { dev->speed = LIBUSB_SPEED_HIGH; - } else if (di_prop_exists(DDI_DEV_T_ANY, node, "full-speed") == 1) { + } else if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "full-speed", &i) >= 0) { dev->speed = LIBUSB_SPEED_FULL; - } else if (di_prop_exists(DDI_DEV_T_ANY, node, "super-speed") == 1) { + } else if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "super-speed", &i) >= 0) { dev->speed = LIBUSB_SPEED_SUPER; } @@ -170,111 +563,98 @@ sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev) return (LIBUSB_SUCCESS); } - static int sunos_add_devices(di_devlink_t link, void *arg) { struct devlink_cbarg *largs = (struct devlink_cbarg *)arg; struct node_args *nargs; - di_node_t myself, pnode; + di_node_t myself, dn; uint64_t session_id = 0; - uint16_t bdf = 0; + uint64_t sid = 0; + uint64_t bdf = 0; struct libusb_device *dev; sunos_dev_priv_t *devpriv; - const char *path, *newpath; - int n, i; + int n, *j; + int i = 0; int *addr_prop; uint8_t bus_number = 0; + uint32_t * regbuf = NULL; + uint32_t reg; nargs = (struct node_args *)largs->nargs; myself = largs->myself; - if (nargs->last_ugenpath) { - /* the same node's links */ - return (DI_WALK_CONTINUE); - } /* * Construct session ID. - * session ID = ...parent hub addr|hub addr|dev addr. + * session ID = dev_addr | hub addr |parent hub addr|...|root hub bdf + * 8 bits 8bits 8 bits 16bits */ - pnode = myself; - i = 0; - while (pnode != DI_NODE_NIL) { - if (di_prop_exists(DDI_DEV_T_ANY, pnode, "root-hub") == 1) { - /* walk to root */ - uint32_t *regbuf = NULL; - uint32_t reg; + if (myself == DI_NODE_NIL) + return (DI_WALK_CONTINUE); - n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode, "reg", - (int **)®buf); - reg = regbuf[0]; - bdf = (PCI_REG_BUS_G(reg) << 8) | - (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); - session_id |= (bdf << i * 8); + dn = myself; + /* find the root hub */ + while (di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "root-hub", &j) != 0) { + usbi_dbg("find_root_hub:%s", di_devfs_path(dn)); + n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, + "assigned-address", &addr_prop); + session_id |= ((addr_prop[0] & 0xff) << i++ * 8); + dn = di_parent_node(dn); + } - /* same as 'unit-address' property */ - bus_number = - (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); + /* dn is the root hub node */ + n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "reg", (int **)®buf); + reg = regbuf[0]; + bdf = (PCI_REG_BUS_G(reg) << 8) | (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); + /* bdf must larger than i*8 bits */ + session_id |= (bdf << i * 8); + bus_number = (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); - usbi_dbg("device bus address=%s:%x", - di_bus_addr(pnode), bus_number); - - break; - } + usbi_dbg("device bus address=%s:%x, name:%s", + di_bus_addr(myself), bus_number, di_node_name(dn)); + usbi_dbg("session id org:%lx", session_id); + /* dn is the usb device */ + for (dn = di_child_node(myself); dn != DI_NODE_NIL; dn = di_sibling_node(dn)) { + usbi_dbg("device path:%s", di_devfs_path(dn)); + /* skip hub devices, because its driver can not been unload */ + if (di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "usb-port-count", &addr_prop) != -1) + continue; /* usb_addr */ - n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode, + n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "assigned-address", &addr_prop); if ((n != 1) || (addr_prop[0] == 0)) { usbi_dbg("cannot get valid usb_addr"); - - return (DI_WALK_CONTINUE); + continue; } - session_id |= ((addr_prop[0] & 0xff) << i * 8); - if (++i > 7) - break; + sid = (session_id << 8) | (addr_prop[0] & 0xff) ; + usbi_dbg("session id %lx", sid); - pnode = di_parent_node(pnode); - } - - path = di_devlink_path(link); - dev = usbi_get_device_by_session_id(nargs->ctx, session_id); - if (dev == NULL) { - dev = usbi_alloc_device(nargs->ctx, session_id); + dev = usbi_get_device_by_session_id(nargs->ctx, sid); if (dev == NULL) { - usbi_dbg("can't alloc device"); + dev = usbi_alloc_device(nargs->ctx, sid); + if (dev == NULL) { + usbi_dbg("can't alloc device"); + continue; + } + devpriv = (sunos_dev_priv_t *)dev->os_priv; + dev->bus_number = bus_number; - return (DI_WALK_TERMINATE); + if (sunos_fill_in_dev_info(dn, dev) != LIBUSB_SUCCESS) { + libusb_unref_device(dev); + usbi_dbg("get infomation fail"); + continue; + } + if (usbi_sanitize_device(dev) < 0) { + libusb_unref_device(dev); + usbi_dbg("sanatize failed: "); + return (DI_WALK_TERMINATE); + } + } else { + devpriv = (sunos_dev_priv_t *)dev->os_priv; + usbi_dbg("Dev %s exists", devpriv->ugenpath); } - devpriv = (sunos_dev_priv_t *)dev->os_priv; - if ((newpath = strrchr(path, '/')) == NULL) { - libusb_unref_device(dev); - - return (DI_WALK_TERMINATE); - } - devpriv->ugenpath = strndup(path, strlen(path) - - strlen(newpath)); - dev->bus_number = bus_number; - - if (sunos_fill_in_dev_info(myself, dev) != LIBUSB_SUCCESS) { - libusb_unref_device(dev); - - return (DI_WALK_TERMINATE); - } - if (usbi_sanitize_device(dev) < 0) { - libusb_unref_device(dev); - usbi_dbg("sanatize failed: "); - return (DI_WALK_TERMINATE); - } - } else { - usbi_dbg("Dev %s exists", path); - } - - devpriv = (sunos_dev_priv_t *)dev->os_priv; - if (nargs->last_ugenpath == NULL) { - /* first device */ - nargs->last_ugenpath = devpriv->ugenpath; if (discovered_devs_append(*(nargs->discdevs), dev) == NULL) { usbi_dbg("cannot append device"); @@ -285,11 +665,11 @@ sunos_add_devices(di_devlink_t link, void *arg) * hereafter. Front end or app should take care of their ref. */ libusb_unref_device(dev); - } - usbi_dbg("Device %s %s id=0x%llx, devcount:%d, bdf=%x", - devpriv->ugenpath, path, (uint64_t)session_id, - (*nargs->discdevs)->len, bdf); + usbi_dbg("Device %s %s id=0x%llx, devcount:%d, bdf=%x", + devpriv->ugenpath, di_devfs_path(dn), (uint64_t)sid, + (*nargs->discdevs)->len, bdf); + } return (DI_WALK_CONTINUE); } @@ -303,14 +683,14 @@ sunos_walk_minor_node_link(di_node_t node, void *args) struct node_args *nargs = (struct node_args *)args; di_devlink_handle_t devlink_hdl = nargs->dlink_hdl; - /* walk each minor to find ugen devices */ + /* walk each minor to find usb devices */ while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { minor_path = di_devfs_minor_path(minor); arg.nargs = args; arg.myself = node; arg.minor = minor; (void) di_devlink_walk(devlink_hdl, - "^usb/[0-9a-f]+[.][0-9a-f]+", minor_path, + "^usb/hub[0-9]+", minor_path, DI_PRIMARY_LINK, (void *)&arg, sunos_add_devices); di_devfs_path_free(minor_path); } @@ -496,7 +876,7 @@ sunos_check_device_and_status_open(struct libusb_device_handle *hdl, usbi_dbg("can't find interface for endpoint 0x%02x", ep_addr); - return (LIBUSB_ERROR_ACCESS); + return (EACCES); } /* create filename */ @@ -603,6 +983,11 @@ sunos_open(struct libusb_device_handle *handle) hpriv->eps[i].statfd = -1; } + if (sunos_kernel_driver_active(handle, 0)) { + /* pretend we can open the device */ + return (LIBUSB_SUCCESS); + } + if ((ret = sunos_usb_open_ep0(hpriv, dpriv)) != LIBUSB_SUCCESS) { usbi_dbg("fail: %d", ret); return (ret); @@ -811,26 +1196,32 @@ sunos_async_callback(union sigval arg) int ret; sunos_dev_handle_priv_t *hpriv; uint8_t ep; + libusb_device_handle *dev_handle; - hpriv = (sunos_dev_handle_priv_t *)xfer->dev_handle->os_priv; - ep = sunos_usb_ep_index(xfer->endpoint); + dev_handle = xfer->dev_handle; - ret = aio_error(aiocb); - if (ret != 0) { - xfer->status = sunos_usb_get_status(hpriv->eps[ep].statfd); - } else { - xfer->actual_length = - LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)->transferred = - aio_return(aiocb); + /* libusb can forcibly interrupt transfer in do_close() */ + if (dev_handle != NULL) { + hpriv = (sunos_dev_handle_priv_t *)dev_handle->os_priv; + ep = sunos_usb_ep_index(xfer->endpoint); + + ret = aio_error(aiocb); + if (ret != 0) { + xfer->status = sunos_usb_get_status(hpriv->eps[ep].statfd); + } else { + xfer->actual_length = + LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)->transferred = + aio_return(aiocb); + } + + usb_dump_data(xfer->buffer, xfer->actual_length); + + usbi_dbg("ret=%d, len=%d, actual_len=%d", ret, xfer->length, + xfer->actual_length); + + /* async notification */ + usbi_signal_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)); } - - usb_dump_data(xfer->buffer, xfer->actual_length); - - usbi_dbg("ret=%d, len=%d, actual_len=%d", ret, xfer->length, - xfer->actual_length); - - /* async notification */ - usbi_signal_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)); } static int @@ -975,9 +1366,15 @@ solaris_submit_ctrl_on_default(struct libusb_transfer *transfer) } usbi_dbg("Done: ctrl data bytes %d", ret); - /* sync transfer handling */ + /** + * Sync transfer handling. + * We should release transfer lock here and later get it back + * as usbi_handle_transfer_completion() takes its own transfer lock. + */ + usbi_mutex_unlock(&LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)->lock); ret = usbi_handle_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer), transfer->status); + usbi_mutex_lock(&LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)->lock); return (ret); } @@ -1010,9 +1407,7 @@ void sunos_destroy_device(struct libusb_device *dev) { sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; - - usbi_dbg(""); - + usbi_dbg("destroy everyting"); free(dpriv->raw_cfgdescr); free(dpriv->ugenpath); free(dpriv->phypath); @@ -1120,8 +1515,6 @@ sunos_handle_transfer_completion(struct usbi_transfer *itransfer) int sunos_clock_gettime(int clkid, struct timespec *tp) { - usbi_dbg("clock %d", clkid); - if (clkid == USBI_CLOCK_REALTIME) return clock_gettime(CLOCK_REALTIME, tp); @@ -1254,7 +1647,14 @@ sunos_usb_get_status(int fd) return (status); } -const struct usbi_os_backend sunos_backend = { +#ifdef USBI_TIMERFD_AVAILABLE +static clockid_t op_get_timerfd_clockid(void) +{ + return CLOCK_MONOTONIC; +} +#endif + +const struct usbi_os_backend usbi_backend = { .name = "Solaris", .caps = 0, .init = sunos_init, @@ -1276,9 +1676,9 @@ const struct usbi_os_backend sunos_backend = { .reset_device = sunos_reset_device, /* TODO */ .alloc_streams = NULL, .free_streams = NULL, - .kernel_driver_active = NULL, - .detach_kernel_driver = NULL, - .attach_kernel_driver = NULL, + .kernel_driver_active = sunos_kernel_driver_active, + .detach_kernel_driver = sunos_detach_kernel_driver, + .attach_kernel_driver = sunos_attach_kernel_driver, .destroy_device = sunos_destroy_device, .submit_transfer = sunos_submit_transfer, .cancel_transfer = sunos_cancel_transfer, @@ -1286,6 +1686,9 @@ const struct usbi_os_backend sunos_backend = { .clear_transfer_priv = sunos_clear_transfer_priv, .handle_transfer_completion = sunos_handle_transfer_completion, .clock_gettime = sunos_clock_gettime, +#ifdef USBI_TIMERFD_AVAILABLE + .get_timerfd_clockid = op_get_timerfd_clockid, +#endif .device_priv_size = sizeof(sunos_dev_priv_t), .device_handle_priv_size = sizeof(sunos_dev_handle_priv_t), .transfer_priv_size = sizeof(sunos_xfer_priv_t), diff --git a/Externals/libusb/libusb/os/sunos_usb.h b/Externals/libusb/libusb/os/sunos_usb.h index 5741660319..52bb3d33a0 100644 --- a/Externals/libusb/libusb/os/sunos_usb.h +++ b/Externals/libusb/libusb/os/sunos_usb.h @@ -65,6 +65,12 @@ struct devlink_cbarg { di_minor_t minor; }; +typedef struct walk_link { + char *path; + int len; + char **linkpp; +} walk_link_t; + /* AIO callback args */ struct aio_callback_args{ struct libusb_transfer *transfer; diff --git a/Externals/libusb/libusb/os/threads_posix.c b/Externals/libusb/libusb/os/threads_posix.c index a4f270bbe5..16a7578b81 100644 --- a/Externals/libusb/libusb/os/threads_posix.c +++ b/Externals/libusb/libusb/os/threads_posix.c @@ -29,7 +29,7 @@ # include # include #elif defined(__APPLE__) -# include +# include #elif defined(__CYGWIN__) # include #endif @@ -43,7 +43,7 @@ int usbi_cond_timedwait(pthread_cond_t *cond, struct timespec timeout; int r; - r = usbi_backend->clock_gettime(USBI_CLOCK_REALTIME, &timeout); + r = usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, &timeout); if (r < 0) return r; @@ -59,7 +59,7 @@ int usbi_cond_timedwait(pthread_cond_t *cond, int usbi_get_tid(void) { - int ret = -1; + int ret; #if defined(__ANDROID__) ret = gettid(); #elif defined(__linux__) @@ -69,10 +69,11 @@ int usbi_get_tid(void) real thread support. For 5.1 and earlier, -1 is returned. */ ret = syscall(SYS_getthrid); #elif defined(__APPLE__) - ret = mach_thread_self(); - mach_port_deallocate(mach_task_self(), ret); + ret = (int)pthread_mach_thread_np(pthread_self()); #elif defined(__CYGWIN__) ret = GetCurrentThreadId(); +#else + ret = -1; #endif /* TODO: NetBSD thread ID support */ return ret; diff --git a/Externals/libusb/libusb/os/threads_posix.h b/Externals/libusb/libusb/os/threads_posix.h index 7ec70b1b52..9f1ef94bc7 100644 --- a/Externals/libusb/libusb/os/threads_posix.h +++ b/Externals/libusb/libusb/os/threads_posix.h @@ -26,32 +26,76 @@ #include #endif -#define usbi_mutex_static_t pthread_mutex_t -#define USBI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER -#define usbi_mutex_static_lock pthread_mutex_lock -#define usbi_mutex_static_unlock pthread_mutex_unlock +#define USBI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +typedef pthread_mutex_t usbi_mutex_static_t; +static inline void usbi_mutex_static_lock(usbi_mutex_static_t *mutex) +{ + (void)pthread_mutex_lock(mutex); +} +static inline void usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) +{ + (void)pthread_mutex_unlock(mutex); +} -#define usbi_mutex_t pthread_mutex_t -#define usbi_mutex_init(mutex) pthread_mutex_init((mutex), NULL) -#define usbi_mutex_lock pthread_mutex_lock -#define usbi_mutex_unlock pthread_mutex_unlock -#define usbi_mutex_trylock pthread_mutex_trylock -#define usbi_mutex_destroy pthread_mutex_destroy +typedef pthread_mutex_t usbi_mutex_t; +static inline int usbi_mutex_init(usbi_mutex_t *mutex) +{ + return pthread_mutex_init(mutex, NULL); +} +static inline void usbi_mutex_lock(usbi_mutex_t *mutex) +{ + (void)pthread_mutex_lock(mutex); +} +static inline void usbi_mutex_unlock(usbi_mutex_t *mutex) +{ + (void)pthread_mutex_unlock(mutex); +} +static inline int usbi_mutex_trylock(usbi_mutex_t *mutex) +{ + return pthread_mutex_trylock(mutex); +} +static inline void usbi_mutex_destroy(usbi_mutex_t *mutex) +{ + (void)pthread_mutex_destroy(mutex); +} -#define usbi_cond_t pthread_cond_t -#define usbi_cond_init(cond) pthread_cond_init((cond), NULL) -#define usbi_cond_wait pthread_cond_wait -#define usbi_cond_broadcast pthread_cond_broadcast -#define usbi_cond_destroy pthread_cond_destroy +typedef pthread_cond_t usbi_cond_t; +static inline void usbi_cond_init(pthread_cond_t *cond) +{ + (void)pthread_cond_init(cond, NULL); +} +static inline int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) +{ + return pthread_cond_wait(cond, mutex); +} +int usbi_cond_timedwait(usbi_cond_t *cond, + usbi_mutex_t *mutex, const struct timeval *tv); +static inline void usbi_cond_broadcast(usbi_cond_t *cond) +{ + (void)pthread_cond_broadcast(cond); +} +static inline void usbi_cond_destroy(usbi_cond_t *cond) +{ + (void)pthread_cond_destroy(cond); +} -#define usbi_tls_key_t pthread_key_t -#define usbi_tls_key_create(key) pthread_key_create((key), NULL) -#define usbi_tls_key_get pthread_getspecific -#define usbi_tls_key_set pthread_setspecific -#define usbi_tls_key_delete pthread_key_delete - -int usbi_cond_timedwait(pthread_cond_t *cond, - pthread_mutex_t *mutex, const struct timeval *tv); +typedef pthread_key_t usbi_tls_key_t; +static inline void usbi_tls_key_create(usbi_tls_key_t *key) +{ + (void)pthread_key_create(key, NULL); +} +static inline void *usbi_tls_key_get(usbi_tls_key_t key) +{ + return pthread_getspecific(key); +} +static inline void usbi_tls_key_set(usbi_tls_key_t key, void *ptr) +{ + (void)pthread_setspecific(key, ptr); +} +static inline void usbi_tls_key_delete(usbi_tls_key_t key) +{ + (void)pthread_key_delete(key); +} int usbi_get_tid(void); diff --git a/Externals/libusb/libusb/os/threads_windows.c b/Externals/libusb/libusb/os/threads_windows.c index 7c2e52dba6..409c490553 100644 --- a/Externals/libusb/libusb/os/threads_windows.c +++ b/Externals/libusb/libusb/os/threads_windows.c @@ -20,189 +20,67 @@ #include -#include #include #include "libusbi.h" struct usbi_cond_perthread { struct list_head list; - DWORD tid; HANDLE event; }; -int usbi_mutex_static_lock(usbi_mutex_static_t *mutex) +void usbi_mutex_static_lock(usbi_mutex_static_t *mutex) { - if (!mutex) - return EINVAL; - while (InterlockedExchange(mutex, 1) == 1) + while (InterlockedExchange(mutex, 1L) == 1L) SleepEx(0, TRUE); - return 0; } -int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) +void usbi_cond_init(usbi_cond_t *cond) { - if (!mutex) - return EINVAL; - InterlockedExchange(mutex, 0); - return 0; -} - -int usbi_mutex_init(usbi_mutex_t *mutex) -{ - if (!mutex) - return EINVAL; - *mutex = CreateMutex(NULL, FALSE, NULL); - if (!*mutex) - return ENOMEM; - return 0; -} - -int usbi_mutex_lock(usbi_mutex_t *mutex) -{ - DWORD result; - - if (!mutex) - return EINVAL; - result = WaitForSingleObject(*mutex, INFINITE); - if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) - return 0; // acquired (ToDo: check that abandoned is ok) - else - return EINVAL; // don't know how this would happen - // so don't know proper errno -} - -int usbi_mutex_unlock(usbi_mutex_t *mutex) -{ - if (!mutex) - return EINVAL; - if (ReleaseMutex(*mutex)) - return 0; - else - return EPERM; -} - -int usbi_mutex_trylock(usbi_mutex_t *mutex) -{ - DWORD result; - - if (!mutex) - return EINVAL; - result = WaitForSingleObject(*mutex, 0); - if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) - return 0; // acquired (ToDo: check that abandoned is ok) - else if (result == WAIT_TIMEOUT) - return EBUSY; - else - return EINVAL; // don't know how this would happen - // so don't know proper error -} - -int usbi_mutex_destroy(usbi_mutex_t *mutex) -{ - // It is not clear if CloseHandle failure is due to failure to unlock. - // If so, this should be errno=EBUSY. - if (!mutex || !CloseHandle(*mutex)) - return EINVAL; - *mutex = NULL; - return 0; -} - -int usbi_cond_init(usbi_cond_t *cond) -{ - if (!cond) - return EINVAL; list_init(&cond->waiters); list_init(&cond->not_waiting); - return 0; } -int usbi_cond_destroy(usbi_cond_t *cond) -{ - // This assumes no one is using this anymore. The check MAY NOT BE safe. - struct usbi_cond_perthread *pos, *next_pos; - - if(!cond) - return EINVAL; - if (!list_empty(&cond->waiters)) - return EBUSY; // (!see above!) - list_for_each_entry_safe(pos, next_pos, &cond->not_waiting, list, struct usbi_cond_perthread) { - CloseHandle(pos->event); - list_del(&pos->list); - free(pos); - } - return 0; -} - -int usbi_cond_broadcast(usbi_cond_t *cond) -{ - // Assumes mutex is locked; this is not in keeping with POSIX spec, but - // libusb does this anyway, so we simplify by not adding more sync - // primitives to the CV definition! - int fail = 0; - struct usbi_cond_perthread *pos; - - if (!cond) - return EINVAL; - list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread) { - if (!SetEvent(pos->event)) - fail = 1; - } - // The wait function will remove its respective item from the list. - return fail ? EINVAL : 0; -} - -__inline static int usbi_cond_intwait(usbi_cond_t *cond, +static int usbi_cond_intwait(usbi_cond_t *cond, usbi_mutex_t *mutex, DWORD timeout_ms) { struct usbi_cond_perthread *pos; - int r, found = 0; - DWORD r2, tid = GetCurrentThreadId(); + DWORD r; - if (!cond || !mutex) - return EINVAL; - list_for_each_entry(pos, &cond->not_waiting, list, struct usbi_cond_perthread) { - if(tid == pos->tid) { - found = 1; - break; - } - } - - if (!found) { - pos = calloc(1, sizeof(struct usbi_cond_perthread)); - if (!pos) + // Same assumption as usbi_cond_broadcast() holds + if (list_empty(&cond->not_waiting)) { + pos = malloc(sizeof(*pos)); + if (pos == NULL) return ENOMEM; // This errno is not POSIX-allowed. - pos->tid = tid; pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset. - if (!pos->event) { + if (pos->event == NULL) { free(pos); return ENOMEM; } - list_add(&pos->list, &cond->not_waiting); + } else { + pos = list_first_entry(&cond->not_waiting, struct usbi_cond_perthread, list); + list_del(&pos->list); // remove from not_waiting list. + // Ensure the event is clear before waiting + WaitForSingleObject(pos->event, 0); } - list_del(&pos->list); // remove from not_waiting list. list_add(&pos->list, &cond->waiters); - r = usbi_mutex_unlock(mutex); - if (r) - return r; - - r2 = WaitForSingleObject(pos->event, timeout_ms); - r = usbi_mutex_lock(mutex); - if (r) - return r; + LeaveCriticalSection(mutex); + r = WaitForSingleObject(pos->event, timeout_ms); + EnterCriticalSection(mutex); list_del(&pos->list); list_add(&pos->list, &cond->not_waiting); - if (r2 == WAIT_OBJECT_0) + if (r == WAIT_OBJECT_0) return 0; - else if (r2 == WAIT_TIMEOUT) + else if (r == WAIT_TIMEOUT) return ETIMEDOUT; else return EINVAL; } + // N.B.: usbi_cond_*wait() can also return ENOMEM, even though pthread_cond_*wait cannot! int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) { @@ -221,39 +99,28 @@ int usbi_cond_timedwait(usbi_cond_t *cond, return usbi_cond_intwait(cond, mutex, millis); } -int usbi_tls_key_create(usbi_tls_key_t *key) +void usbi_cond_broadcast(usbi_cond_t *cond) { - if (!key) - return EINVAL; - *key = TlsAlloc(); - if (*key == TLS_OUT_OF_INDEXES) - return ENOMEM; - else - return 0; + // Assumes mutex is locked; this is not in keeping with POSIX spec, but + // libusb does this anyway, so we simplify by not adding more sync + // primitives to the CV definition! + struct usbi_cond_perthread *pos; + + list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread) + SetEvent(pos->event); + // The wait function will remove its respective item from the list. } -void *usbi_tls_key_get(usbi_tls_key_t key) +void usbi_cond_destroy(usbi_cond_t *cond) { - return TlsGetValue(key); -} + // This assumes no one is using this anymore. The check MAY NOT BE safe. + struct usbi_cond_perthread *pos, *next; -int usbi_tls_key_set(usbi_tls_key_t key, void *value) -{ - if (TlsSetValue(key, value)) - return 0; - else - return EINVAL; -} - -int usbi_tls_key_delete(usbi_tls_key_t key) -{ - if (TlsFree(key)) - return 0; - else - return EINVAL; -} - -int usbi_get_tid(void) -{ - return (int)GetCurrentThreadId(); + if (!list_empty(&cond->waiters)) + return; // (!see above!) + list_for_each_entry_safe(pos, next, &cond->not_waiting, list, struct usbi_cond_perthread) { + CloseHandle(pos->event); + list_del(&pos->list); + free(pos); + } } diff --git a/Externals/libusb/libusb/os/threads_windows.h b/Externals/libusb/libusb/os/threads_windows.h index e97ee78757..409de2d0e2 100644 --- a/Externals/libusb/libusb/os/threads_windows.h +++ b/Externals/libusb/libusb/os/threads_windows.h @@ -21,17 +21,40 @@ #ifndef LIBUSB_THREADS_WINDOWS_H #define LIBUSB_THREADS_WINDOWS_H -#define usbi_mutex_static_t volatile LONG -#define USBI_MUTEX_INITIALIZER 0 +#define USBI_MUTEX_INITIALIZER 0L +#ifdef _WIN32_WCE +typedef LONG usbi_mutex_static_t; +#else +typedef volatile LONG usbi_mutex_static_t; +#endif +void usbi_mutex_static_lock(usbi_mutex_static_t *mutex); +static inline void usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) +{ + InterlockedExchange(mutex, 0L); +} -#define usbi_mutex_t HANDLE - -typedef struct usbi_cond { - // Every time a thread touches the CV, it winds up in one of these lists. - // It stays there until the CV is destroyed, even if the thread terminates. - struct list_head waiters; - struct list_head not_waiting; -} usbi_cond_t; +typedef CRITICAL_SECTION usbi_mutex_t; +static inline int usbi_mutex_init(usbi_mutex_t *mutex) +{ + InitializeCriticalSection(mutex); + return 0; +} +static inline void usbi_mutex_lock(usbi_mutex_t *mutex) +{ + EnterCriticalSection(mutex); +} +static inline void usbi_mutex_unlock(usbi_mutex_t *mutex) +{ + LeaveCriticalSection(mutex); +} +static inline int usbi_mutex_trylock(usbi_mutex_t *mutex) +{ + return !TryEnterCriticalSection(mutex); +} +static inline void usbi_mutex_destroy(usbi_mutex_t *mutex) +{ + DeleteCriticalSection(mutex); +} // We *were* getting timespec from pthread.h: #if (!defined(HAVE_STRUCT_TIMESPEC) && !defined(_TIMESPEC_DEFINED)) @@ -45,32 +68,44 @@ struct timespec { // We *were* getting ETIMEDOUT from pthread.h: #ifndef ETIMEDOUT -# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ +#define ETIMEDOUT 10060 /* This is the value in winsock.h. */ #endif -#define usbi_tls_key_t DWORD +typedef struct usbi_cond { + // Every time a thread touches the CV, it winds up in one of these lists. + // It stays there until the CV is destroyed, even if the thread terminates. + struct list_head waiters; + struct list_head not_waiting; +} usbi_cond_t; -int usbi_mutex_static_lock(usbi_mutex_static_t *mutex); -int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex); - -int usbi_mutex_init(usbi_mutex_t *mutex); -int usbi_mutex_lock(usbi_mutex_t *mutex); -int usbi_mutex_unlock(usbi_mutex_t *mutex); -int usbi_mutex_trylock(usbi_mutex_t *mutex); -int usbi_mutex_destroy(usbi_mutex_t *mutex); - -int usbi_cond_init(usbi_cond_t *cond); +void usbi_cond_init(usbi_cond_t *cond); int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex); int usbi_cond_timedwait(usbi_cond_t *cond, usbi_mutex_t *mutex, const struct timeval *tv); -int usbi_cond_broadcast(usbi_cond_t *cond); -int usbi_cond_destroy(usbi_cond_t *cond); +void usbi_cond_broadcast(usbi_cond_t *cond); +void usbi_cond_destroy(usbi_cond_t *cond); -int usbi_tls_key_create(usbi_tls_key_t *key); -void *usbi_tls_key_get(usbi_tls_key_t key); -int usbi_tls_key_set(usbi_tls_key_t key, void *value); -int usbi_tls_key_delete(usbi_tls_key_t key); +typedef DWORD usbi_tls_key_t; +static inline void usbi_tls_key_create(usbi_tls_key_t *key) +{ + *key = TlsAlloc(); +} +static inline void *usbi_tls_key_get(usbi_tls_key_t key) +{ + return TlsGetValue(key); +} +static inline void usbi_tls_key_set(usbi_tls_key_t key, void *ptr) +{ + (void)TlsSetValue(key, ptr); +} +static inline void usbi_tls_key_delete(usbi_tls_key_t key) +{ + (void)TlsFree(key); +} -int usbi_get_tid(void); +static inline int usbi_get_tid(void) +{ + return (int)GetCurrentThreadId(); +} #endif /* LIBUSB_THREADS_WINDOWS_H */ diff --git a/Externals/libusb/libusb/os/wince_usb.c b/Externals/libusb/libusb/os/wince_usb.c index 89b5e657c5..a0f35e93e5 100644 --- a/Externals/libusb/libusb/os/wince_usb.c +++ b/Externals/libusb/libusb/os/wince_usb.c @@ -31,8 +31,7 @@ #include "wince_usb.h" // Global variables -const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime -int windows_version = WINDOWS_CE; +int errno = 0; static uint64_t hires_frequency, hires_ticks_to_ps; static HANDLE driver_handle = INVALID_HANDLE_VALUE; static int concurrent_usage = -1; @@ -42,38 +41,39 @@ static int concurrent_usage = -1; * uses retval as errorcode, or, if 0, use GetLastError() */ #if defined(ENABLE_LOGGING) -static const char *windows_error_str(DWORD retval) +static const char *windows_error_str(DWORD error_code) { static TCHAR wErr_string[ERR_BUFFER_SIZE]; static char err_string[ERR_BUFFER_SIZE]; - DWORD error_code, format_error; DWORD size; - size_t i; + int len; - error_code = retval ? retval : GetLastError(); + if (error_code == 0) + error_code = GetLastError(); - safe_stprintf(wErr_string, ERR_BUFFER_SIZE, _T("[%u] "), (unsigned int)error_code); + len = sprintf(err_string, "[%u] ", (unsigned int)error_code); - size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &wErr_string[safe_tcslen(wErr_string)], - ERR_BUFFER_SIZE - (DWORD)safe_tcslen(wErr_string), NULL); + size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + wErr_string, ERR_BUFFER_SIZE, NULL); if (size == 0) { - format_error = GetLastError(); + DWORD format_error = GetLastError(); if (format_error) - safe_stprintf(wErr_string, ERR_BUFFER_SIZE, - _T("Windows error code %u (FormatMessage error code %u)"), + snprintf(err_string, ERR_BUFFER_SIZE, + "Windows error code %u (FormatMessage error code %u)", (unsigned int)error_code, (unsigned int)format_error); else - safe_stprintf(wErr_string, ERR_BUFFER_SIZE, _T("Unknown error code %u"), (unsigned int)error_code); + snprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", (unsigned int)error_code); } else { - // Remove CR/LF terminators - for (i = safe_tcslen(wErr_string) - 1; ((wErr_string[i] == 0x0A) || (wErr_string[i] == 0x0D)); i--) - wErr_string[i] = 0; - } + // Remove CR/LF terminators, if present + size_t pos = size - 2; + if (wErr_string[pos] == 0x0D) + wErr_string[pos] = 0; - if (WideCharToMultiByte(CP_ACP, 0, wErr_string, -1, err_string, ERR_BUFFER_SIZE, NULL, NULL) < 0) - strcpy(err_string, "Unable to convert error string"); + if (!WideCharToMultiByte(CP_ACP, 0, wErr_string, -1, &err_string[len], ERR_BUFFER_SIZE - len, NULL, NULL)) + strcpy(err_string, "Unable to convert error string"); + } return err_string; } @@ -109,7 +109,7 @@ static int translate_driver_error(DWORD error) } } -static int init_dllimports(void) +static BOOL init_dllimports(void) { DLL_GET_HANDLE(ceusbkwrapper); DLL_LOAD_FUNC(ceusbkwrapper, UkwOpenDriver, TRUE); @@ -135,7 +135,7 @@ static int init_dllimports(void) DLL_LOAD_FUNC(ceusbkwrapper, UkwIssueBulkTransfer, TRUE); DLL_LOAD_FUNC(ceusbkwrapper, UkwIsPipeHalted, TRUE); - return LIBUSB_SUCCESS; + return TRUE; } static void exit_dllimports(void) @@ -186,11 +186,8 @@ static int wince_init(struct libusb_context *ctx) // NB: concurrent usage supposes that init calls are equally balanced with // exit calls. If init is called more than exit, we will not exit properly if ( ++concurrent_usage == 0 ) { // First init? - // Initialize pollable file descriptors - init_polling(); - // Load DLL imports - if (init_dllimports() != LIBUSB_SUCCESS) { + if (!init_dllimports()) { usbi_err(ctx, "could not resolve DLL functions"); r = LIBUSB_ERROR_NOT_SUPPORTED; goto init_exit; @@ -223,7 +220,6 @@ static int wince_init(struct libusb_context *ctx) init_exit: // Holds semaphore here. if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? exit_dllimports(); - exit_polling(); if (driver_handle != INVALID_HANDLE_VALUE) { UkwCloseDriver(driver_handle); @@ -239,10 +235,11 @@ init_exit: // Holds semaphore here. return r; } -static void wince_exit(void) +static void wince_exit(struct libusb_context *ctx) { HANDLE semaphore; TCHAR sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' + UNUSED(ctx); _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); semaphore = CreateSemaphore(NULL, 1, 1, sem_name); @@ -259,7 +256,6 @@ static void wince_exit(void) // Only works if exits and inits are balanced exactly if (--concurrent_usage < 0) { // Last exit exit_dllimports(); - exit_polling(); if (driver_handle != INVALID_HANDLE_VALUE) { UkwCloseDriver(driver_handle); @@ -328,19 +324,19 @@ static int wince_get_device_list( } new_devices = discovered_devs_append(new_devices, dev); - if (!discdevs) { + if (!new_devices) { r = LIBUSB_ERROR_NO_MEM; goto err_out; } - safe_unref_device(dev); + libusb_unref_device(dev); } *discdevs = new_devices; return r; err_out: *discdevs = new_devices; - safe_unref_device(dev); + libusb_unref_device(dev); // Release the remainder of the unprocessed device list. // The devices added to new_devices already will still be passed up to libusb, // which can dispose of them at its leisure. @@ -541,12 +537,9 @@ static void wince_destroy_device(struct libusb_device *dev) static void wince_clear_transfer_priv(struct usbi_transfer *itransfer) { struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct winfd wfd = fd_to_winfd(transfer_priv->pollable_fd.fd); - // No need to cancel transfer as it is either complete or abandoned - wfd.itransfer = NULL; - CloseHandle(wfd.handle); - usbi_free_fd(&transfer_priv->pollable_fd); + usbi_close(transfer_priv->pollable_fd.fd); + transfer_priv->pollable_fd = INVALID_WINFD; } static int wince_cancel_transfer(struct usbi_transfer *itransfer) @@ -570,11 +563,10 @@ static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer BOOL direction_in, ret; struct winfd wfd; DWORD flags; - HANDLE eventHandle; PUKW_CONTROL_HEADER setup = NULL; const BOOL control_transfer = transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL; + int r; - transfer_priv->pollable_fd = INVALID_WINFD; if (control_transfer) { setup = (PUKW_CONTROL_HEADER) transfer->buffer; direction_in = setup->bmRequestType & LIBUSB_ENDPOINT_IN; @@ -584,19 +576,18 @@ static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer flags = direction_in ? UKW_TF_IN_TRANSFER : UKW_TF_OUT_TRANSFER; flags |= UKW_TF_SHORT_TRANSFER_OK; - eventHandle = CreateEvent(NULL, FALSE, FALSE, NULL); - if (eventHandle == NULL) { - usbi_err(ctx, "Failed to create event for async transfer"); + wfd = usbi_create_fd(); + if (wfd.fd < 0) return LIBUSB_ERROR_NO_MEM; - } - wfd = usbi_create_fd(eventHandle, direction_in ? RW_READ : RW_WRITE, itransfer, &wince_cancel_transfer); - if (wfd.fd < 0) { - CloseHandle(eventHandle); - return LIBUSB_ERROR_NO_MEM; + r = usbi_add_pollfd(ctx, wfd.fd, direction_in ? POLLIN : POLLOUT); + if (r) { + usbi_close(wfd.fd); + return r; } transfer_priv->pollable_fd = wfd; + if (control_transfer) { // Split out control setup header and data buffer DWORD bufLen = transfer->length - sizeof(UKW_CONTROL_HEADER); @@ -612,19 +603,16 @@ static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer int libusbErr = translate_driver_error(GetLastError()); usbi_err(ctx, "UkwIssue%sTransfer failed: error %u", control_transfer ? "Control" : "Bulk", (unsigned int)GetLastError()); - wince_clear_transfer_priv(itransfer); + usbi_remove_pollfd(ctx, wfd.fd); + usbi_close(wfd.fd); + transfer_priv->pollable_fd = INVALID_WINFD; return libusbErr; } - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, direction_in ? POLLIN : POLLOUT); + return LIBUSB_SUCCESS; } -static int wince_submit_iso_transfer(struct usbi_transfer *itransfer) -{ - return LIBUSB_ERROR_NOT_SUPPORTED; -} - static int wince_submit_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); @@ -635,7 +623,6 @@ static int wince_submit_transfer(struct usbi_transfer *itransfer) case LIBUSB_TRANSFER_TYPE_INTERRUPT: return wince_submit_control_or_bulk_transfer(itransfer); case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return wince_submit_iso_transfer(itransfer); case LIBUSB_TRANSFER_TYPE_BULK_STREAM: return LIBUSB_ERROR_NOT_SUPPORTED; default: @@ -763,7 +750,7 @@ static int wince_handle_events( struct wince_transfer_priv* transfer_priv = NULL; POLL_NFDS_TYPE i = 0; BOOL found = FALSE; - struct usbi_transfer *transfer; + struct usbi_transfer *itransfer; DWORD io_size, io_result; int r = LIBUSB_SUCCESS; @@ -780,8 +767,8 @@ static int wince_handle_events( // Because a Windows OVERLAPPED is used for poll emulation, // a pollable fd is created and stored with each transfer usbi_mutex_lock(&ctx->flying_transfers_lock); - list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { - transfer_priv = usbi_transfer_get_os_priv(transfer); + list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) { + transfer_priv = usbi_transfer_get_os_priv(itransfer); if (transfer_priv->pollable_fd.fd == fds[i].fd) { found = TRUE; break; @@ -796,7 +783,7 @@ static int wince_handle_events( // let handle_callback free the event using the transfer wfd // If you don't use the transfer wfd, you run a risk of trying to free a // newly allocated wfd that took the place of the one from the transfer. - wince_handle_callback(transfer, io_result, io_size); + wince_handle_callback(itransfer, io_result, io_size); } else if (found) { usbi_err(ctx, "matching transfer for fd %d has not completed", fds[i]); r = LIBUSB_ERROR_OTHER; @@ -832,14 +819,14 @@ static int wince_clock_gettime(int clk_id, struct timespec *tp) // Fall through and return real-time if monotonic read failed or was not detected @ init case USBI_CLOCK_REALTIME: // We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx - // with a predef epoch_time to have an epoch that starts at 1970.01.01 00:00 + // with a predef epoch time to have an epoch that starts at 1970.01.01 00:00 // Note however that our resolution is bounded by the Windows system time // functions and is at best of the order of 1 ms (or, usually, worse) GetSystemTime(&st); SystemTimeToFileTime(&st, &filetime); rtime.LowPart = filetime.dwLowDateTime; rtime.HighPart = filetime.dwHighDateTime; - rtime.QuadPart -= epoch_time; + rtime.QuadPart -= EPOCH_TIME; tp->tv_sec = (long)(rtime.QuadPart / 10000000); tp->tv_nsec = (long)((rtime.QuadPart % 10000000)*100); return LIBUSB_SUCCESS; @@ -848,11 +835,12 @@ static int wince_clock_gettime(int clk_id, struct timespec *tp) } } -const struct usbi_os_backend wince_backend = { +const struct usbi_os_backend usbi_backend = { "Windows CE", 0, wince_init, wince_exit, + NULL, /* set_option() */ wince_get_device_list, NULL, /* hotplug_poll */ @@ -893,6 +881,7 @@ const struct usbi_os_backend wince_backend = { NULL, /* handle_transfer_completion() */ wince_clock_gettime, + 0, sizeof(struct wince_device_priv), 0, sizeof(struct wince_transfer_priv), diff --git a/Externals/libusb/libusb/os/windows_common.h b/Externals/libusb/libusb/os/windows_common.h index 17a1923723..b1725c2e32 100644 --- a/Externals/libusb/libusb/os/windows_common.h +++ b/Externals/libusb/libusb/os/windows_common.h @@ -37,38 +37,23 @@ #define false FALSE #endif +#define EPOCH_TIME UINT64_C(116444736000000000) // 1970.01.01 00:00:000 in MS Filetime + #if defined(__CYGWIN__ ) #define _stricmp strcasecmp -#define _snprintf snprintf #define _strdup strdup // _beginthreadex is MSVCRT => unavailable for cygwin. Fallback to using CreateThread #define _beginthreadex(a, b, c, d, e, f) CreateThread(a, b, (LPTHREAD_START_ROUTINE)c, d, e, (LPDWORD)f) #endif -#define safe_free(p) do {if (p != NULL) {free((void*)p); p = NULL;}} while(0) -#define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0) -#define safe_min(a, b) MIN((size_t)(a), (size_t)(b)) -#define safe_strcp(dst, dst_max, src, count) do {memcpy(dst, src, safe_min(count, dst_max)); \ - ((char*)dst)[safe_min(count, dst_max)-1] = 0;} while(0) -#define safe_strcpy(dst, dst_max, src) safe_strcp(dst, dst_max, src, safe_strlen(src)+1) -#define safe_strncat(dst, dst_max, src, count) strncat(dst, src, safe_min(count, dst_max - safe_strlen(dst) - 1)) -#define safe_strcat(dst, dst_max, src) safe_strncat(dst, dst_max, src, safe_strlen(src)+1) -#define safe_strcmp(str1, str2) strcmp(((str1==NULL)?"":str1), ((str2==NULL)?"":str2)) -#define safe_stricmp(str1, str2) _stricmp(((str1==NULL)?"":str1), ((str2==NULL)?"":str2)) -#define safe_strncmp(str1, str2, count) strncmp(((str1==NULL)?"":str1), ((str2==NULL)?"":str2), count) -#define safe_strlen(str) ((str==NULL)?0:strlen(str)) -#define safe_sprintf(dst, count, ...) do {_snprintf(dst, count, __VA_ARGS__); (dst)[(count)-1] = 0; } while(0) -#define safe_stprintf _sntprintf -#define safe_tcslen(str) ((str==NULL)?0:_tcslen(str)) -#define safe_unref_device(dev) do {if (dev != NULL) {libusb_unref_device(dev); dev = NULL;}} while(0) -#define wchar_to_utf8_ms(wstr, str, strlen) WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, strlen, NULL, NULL) +#define safe_free(p) do {if (p != NULL) {free((void *)p); p = NULL;}} while (0) + #ifndef ARRAYSIZE #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) #endif #define ERR_BUFFER_SIZE 256 - /* * API macros - leveraged from libusb-win32 1.x */ @@ -83,31 +68,35 @@ /* * Macros for handling DLL themselves */ +#define DLL_HANDLE_NAME(name) __dll_##name##_handle + #define DLL_DECLARE_HANDLE(name) \ - static HMODULE __dll_##name##_handle = NULL + static HMODULE DLL_HANDLE_NAME(name) = NULL #define DLL_GET_HANDLE(name) \ do { \ - __dll_##name##_handle = DLL_LOAD_LIBRARY(name); \ - if (!__dll_##name##_handle) \ - return LIBUSB_ERROR_OTHER; \ + DLL_HANDLE_NAME(name) = DLL_LOAD_LIBRARY(name); \ + if (!DLL_HANDLE_NAME(name)) \ + return FALSE; \ } while (0) #define DLL_FREE_HANDLE(name) \ do { \ - if (__dll_##name##_handle) { \ - FreeLibrary(__dll_##name##_handle); \ - __dll_##name##_handle = NULL; \ + if (DLL_HANDLE_NAME(name)) { \ + FreeLibrary(DLL_HANDLE_NAME(name)); \ + DLL_HANDLE_NAME(name) = NULL; \ } \ - } while(0) + } while (0) /* * Macros for handling functions within a DLL */ +#define DLL_FUNC_NAME(name) __dll_##name##_func_t + #define DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefixname, name, args) \ - typedef ret (api * __dll_##name##_func_t)args; \ - static __dll_##name##_func_t prefixname = NULL + typedef ret (api * DLL_FUNC_NAME(name))args; \ + static DLL_FUNC_NAME(name) prefixname = NULL #define DLL_DECLARE_FUNC(api, ret, name, args) \ DLL_DECLARE_FUNC_PREFIXNAME(api, ret, name, name, args) @@ -116,22 +105,22 @@ #define DLL_LOAD_FUNC_PREFIXNAME(dll, prefixname, name, ret_on_failure) \ do { \ - HMODULE h = __dll_##dll##_handle; \ - prefixname = (__dll_##name##_func_t)GetProcAddress(h, \ + HMODULE h = DLL_HANDLE_NAME(dll); \ + prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \ DLL_STRINGIFY(name)); \ if (prefixname) \ break; \ - prefixname = (__dll_##name##_func_t)GetProcAddress(h, \ + prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \ DLL_STRINGIFY(name) DLL_STRINGIFY(A)); \ if (prefixname) \ break; \ - prefixname = (__dll_##name##_func_t)GetProcAddress(h, \ + prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \ DLL_STRINGIFY(name) DLL_STRINGIFY(W)); \ if (prefixname) \ break; \ if (ret_on_failure) \ - return LIBUSB_ERROR_NOT_FOUND; \ - } while(0) + return FALSE; \ + } while (0) #define DLL_LOAD_FUNC(dll, name, ret_on_failure) \ DLL_LOAD_FUNC_PREFIXNAME(dll, name, name, ret_on_failure) diff --git a/Externals/libusb/libusb/os/windows_nt_common.c b/Externals/libusb/libusb/os/windows_nt_common.c index 1565a4aba9..7ead83db59 100644 --- a/Externals/libusb/libusb/os/windows_nt_common.c +++ b/Externals/libusb/libusb/os/windows_nt_common.c @@ -32,8 +32,13 @@ #include "windows_common.h" #include "windows_nt_common.h" -// Global variables -const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime +// Public +BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED); +enum windows_version windows_version = WINDOWS_UNDEFINED; + + // Global variables for init/exit +static unsigned int init_count = 0; +static bool usbdk_available = false; // Global variables for clock_gettime mechanism static uint64_t hires_ticks_to_ps; @@ -53,14 +58,17 @@ struct timer_request { static HANDLE timer_thread = NULL; static DWORD timer_thread_id = 0; +/* Kernel32 dependencies */ +DLL_DECLARE_HANDLE(Kernel32); +/* This call is only available from XP SP2 */ +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, IsWow64Process, (HANDLE, PBOOL)); + /* User32 dependencies */ DLL_DECLARE_HANDLE(User32); DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, GetMessageA, (LPMSG, HWND, UINT, UINT)); DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, PeekMessageA, (LPMSG, HWND, UINT, UINT, UINT)); DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, PostThreadMessageA, (DWORD, UINT, WPARAM, LPARAM)); -win_backend backend_func; - static unsigned __stdcall windows_clock_gettime_threaded(void *param); /* @@ -68,17 +76,17 @@ static unsigned __stdcall windows_clock_gettime_threaded(void *param); * uses retval as errorcode, or, if 0, use GetLastError() */ #if defined(ENABLE_LOGGING) -const char *windows_error_str(DWORD retval) +const char *windows_error_str(DWORD error_code) { static char err_string[ERR_BUFFER_SIZE]; - DWORD error_code, format_error; DWORD size; - ssize_t i; + int len; - error_code = retval ? retval : GetLastError(); + if (error_code == 0) + error_code = GetLastError(); - safe_sprintf(err_string, ERR_BUFFER_SIZE, "[%u] ", (unsigned int)error_code); + len = sprintf(err_string, "[%u] ", (unsigned int)error_code); // Translate codes returned by SetupAPI. The ones we are dealing with are either // in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes. @@ -94,33 +102,38 @@ const char *windows_error_str(DWORD retval) break; } - size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &err_string[safe_strlen(err_string)], - ERR_BUFFER_SIZE - (DWORD)safe_strlen(err_string), NULL); + size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + &err_string[len], ERR_BUFFER_SIZE - len, NULL); if (size == 0) { - format_error = GetLastError(); + DWORD format_error = GetLastError(); if (format_error) - safe_sprintf(err_string, ERR_BUFFER_SIZE, - "Windows error code %u (FormatMessage error code %u)", - (unsigned int)error_code, (unsigned int)format_error); + snprintf(err_string, ERR_BUFFER_SIZE, + "Windows error code %u (FormatMessage error code %u)", + (unsigned int)error_code, (unsigned int)format_error); else - safe_sprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", (unsigned int)error_code); - } - else { - // Remove CR/LF terminators - for (i = safe_strlen(err_string) - 1; (i >= 0) && ((err_string[i] == 0x0A) || (err_string[i] == 0x0D)); i--) - err_string[i] = 0; + snprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", (unsigned int)error_code); + } else { + // Remove CRLF from end of message, if present + size_t pos = len + size - 2; + if (err_string[pos] == '\r') + err_string[pos] = '\0'; } return err_string; } #endif +static inline struct windows_context_priv *_context_priv(struct libusb_context *ctx) +{ + return (struct windows_context_priv *)ctx->os_priv; +} + /* Hash table functions - modified From glibc 2.3.2: [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986 [Knuth] The Art of Computer Programming, part 3 (6.4) */ -#define HTAB_SIZE 1021 +#define HTAB_SIZE 1021UL // *MUST* be a prime number!! typedef struct htab_entry { unsigned long used; @@ -128,29 +141,14 @@ typedef struct htab_entry { } htab_entry; static htab_entry *htab_table = NULL; -static usbi_mutex_t htab_write_mutex = NULL; -static unsigned long htab_size, htab_filled; - -/* For the used double hash method the table size has to be a prime. To - correct the user given table size we need a prime test. This trivial - algorithm is adequate because the code is called only during init and - the number is likely to be small */ -static int isprime(unsigned long number) -{ - // no even number will be passed - unsigned int divider = 3; - - while((divider * divider < number) && (number % divider != 0)) - divider += 2; - - return (number % divider != 0); -} +static usbi_mutex_t htab_mutex; +static unsigned long htab_filled; /* Before using the hash table we must allocate memory for it. We allocate one element more as the found prime number says. This is done for more effective indexing as explained in the comment for the hash function. */ -static bool htab_create(struct libusb_context *ctx, unsigned long nel) +static bool htab_create(struct libusb_context *ctx) { if (htab_table != NULL) { usbi_err(ctx, "hash table already allocated"); @@ -158,19 +156,13 @@ static bool htab_create(struct libusb_context *ctx, unsigned long nel) } // Create a mutex - usbi_mutex_init(&htab_write_mutex); + usbi_mutex_init(&htab_mutex); - // Change nel to the first prime number not smaller as nel. - nel |= 1; - while (!isprime(nel)) - nel += 2; - - htab_size = nel; - usbi_dbg("using %lu entries hash table", nel); + usbi_dbg("using %lu entries hash table", HTAB_SIZE); htab_filled = 0; // allocate memory and zero out. - htab_table = calloc(htab_size + 1, sizeof(htab_entry)); + htab_table = calloc(HTAB_SIZE + 1, sizeof(htab_entry)); if (htab_table == NULL) { usbi_err(ctx, "could not allocate space for hash table"); return false; @@ -187,13 +179,12 @@ static void htab_destroy(void) if (htab_table == NULL) return; - for (i = 0; i < htab_size; i++) { - if (htab_table[i].used) - safe_free(htab_table[i].str); - } + for (i = 0; i < HTAB_SIZE; i++) + free(htab_table[i].str); - usbi_mutex_destroy(&htab_write_mutex); safe_free(htab_table); + + usbi_mutex_destroy(&htab_mutex); } /* This is the search function. It uses double hashing with open addressing. @@ -222,26 +213,29 @@ unsigned long htab_hash(const char *str) ++r; // compute table hash: simply take the modulus - hval = r % htab_size; + hval = r % HTAB_SIZE; if (hval == 0) ++hval; // Try the first index idx = hval; + // Mutually exclusive access (R/W lock would be better) + usbi_mutex_lock(&htab_mutex); + if (htab_table[idx].used) { - if ((htab_table[idx].used == hval) && (safe_strcmp(str, htab_table[idx].str) == 0)) - return idx; // existing hash + if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0)) + goto out_unlock; // existing hash usbi_dbg("hash collision ('%s' vs '%s')", str, htab_table[idx].str); // Second hash function, as suggested in [Knuth] - hval2 = 1 + hval % (htab_size - 2); + hval2 = 1 + hval % (HTAB_SIZE - 2); do { // Because size is prime this guarantees to step through all available indexes if (idx <= hval2) - idx = htab_size + idx - hval2; + idx = HTAB_SIZE + idx - hval2; else idx -= hval2; @@ -250,68 +244,76 @@ unsigned long htab_hash(const char *str) break; // If entry is found use it. - if ((htab_table[idx].used == hval) && (safe_strcmp(str, htab_table[idx].str) == 0)) - return idx; + if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0)) + goto out_unlock; } while (htab_table[idx].used); } // Not found => New entry // If the table is full return an error - if (htab_filled >= htab_size) { - usbi_err(NULL, "hash table is full (%d entries)", htab_size); - return 0; + if (htab_filled >= HTAB_SIZE) { + usbi_err(NULL, "hash table is full (%lu entries)", HTAB_SIZE); + idx = 0; + goto out_unlock; } - // Concurrent threads might be storing the same entry at the same time - // (eg. "simultaneous" enums from different threads) => use a mutex - usbi_mutex_lock(&htab_write_mutex); - // Just free any previously allocated string (which should be the same as - // new one). The possibility of concurrent threads storing a collision - // string (same hash, different string) at the same time is extremely low - safe_free(htab_table[idx].str); - htab_table[idx].used = hval; htab_table[idx].str = _strdup(str); if (htab_table[idx].str == NULL) { usbi_err(NULL, "could not duplicate string for hash table"); - usbi_mutex_unlock(&htab_write_mutex); - return 0; + idx = 0; + goto out_unlock; } + + htab_table[idx].used = hval; ++htab_filled; - usbi_mutex_unlock(&htab_write_mutex); + +out_unlock: + usbi_mutex_unlock(&htab_mutex); return idx; } -static int windows_init_dlls(void) +/* +* Make a transfer complete synchronously +*/ +void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size) { + overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; + overlapped->InternalHigh = size; + SetEvent(overlapped->hEvent); +} + +static BOOL windows_init_dlls(void) +{ + DLL_GET_HANDLE(Kernel32); + DLL_LOAD_FUNC_PREFIXED(Kernel32, p, IsWow64Process, FALSE); + pCancelIoEx = (BOOL (WINAPI *)(HANDLE, LPOVERLAPPED)) + GetProcAddress(DLL_HANDLE_NAME(Kernel32), "CancelIoEx"); + usbi_dbg("Will use CancelIo%s for I/O cancellation", pCancelIoEx ? "Ex" : ""); + DLL_GET_HANDLE(User32); DLL_LOAD_FUNC_PREFIXED(User32, p, GetMessageA, TRUE); DLL_LOAD_FUNC_PREFIXED(User32, p, PeekMessageA, TRUE); DLL_LOAD_FUNC_PREFIXED(User32, p, PostThreadMessageA, TRUE); - return LIBUSB_SUCCESS; + return TRUE; } static void windows_exit_dlls(void) { + DLL_FREE_HANDLE(Kernel32); DLL_FREE_HANDLE(User32); } static bool windows_init_clock(struct libusb_context *ctx) { DWORD_PTR affinity, dummy; - HANDLE event = NULL; + HANDLE event; LARGE_INTEGER li_frequency; int i; if (QueryPerformanceFrequency(&li_frequency)) { - // Load DLL imports - if (windows_init_dlls() != LIBUSB_SUCCESS) { - usbi_err(ctx, "could not resolve DLL functions"); - return false; - } - // The hires frequency can go as high as 4 GHz, so we'll use a conversion // to picoseconds to compute the tv_nsecs part in clock_gettime hires_frequency = li_frequency.QuadPart; @@ -367,7 +369,7 @@ static bool windows_init_clock(struct libusb_context *ctx) return true; } -void windows_destroy_clock(void) +static void windows_destroy_clock(void) { if (timer_thread) { // actually the signal to quit the thread. @@ -384,6 +386,110 @@ void windows_destroy_clock(void) } } +/* Windows version detection */ +static BOOL is_x64(void) +{ + BOOL ret = FALSE; + + // Detect if we're running a 32 or 64 bit system + if (sizeof(uintptr_t) < 8) { + if (pIsWow64Process != NULL) + pIsWow64Process(GetCurrentProcess(), &ret); + } else { + ret = TRUE; + } + + return ret; +} + +static void get_windows_version(void) +{ + OSVERSIONINFOEXA vi, vi2; + const char *arch, *w = NULL; + unsigned major, minor, version; + ULONGLONG major_equal, minor_equal; + BOOL ws; + + windows_version = WINDOWS_UNDEFINED; + + memset(&vi, 0, sizeof(vi)); + vi.dwOSVersionInfoSize = sizeof(vi); + if (!GetVersionExA((OSVERSIONINFOA *)&vi)) { + memset(&vi, 0, sizeof(vi)); + vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); + if (!GetVersionExA((OSVERSIONINFOA *)&vi)) + return; + } + + if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT) + return; + + if ((vi.dwMajorVersion > 6) || ((vi.dwMajorVersion == 6) && (vi.dwMinorVersion >= 2))) { + // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version + // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx + + major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); + for (major = vi.dwMajorVersion; major <= 9; major++) { + memset(&vi2, 0, sizeof(vi2)); + vi2.dwOSVersionInfoSize = sizeof(vi2); + vi2.dwMajorVersion = major; + if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal)) + continue; + + if (vi.dwMajorVersion < major) { + vi.dwMajorVersion = major; + vi.dwMinorVersion = 0; + } + + minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL); + for (minor = vi.dwMinorVersion; minor <= 9; minor++) { + memset(&vi2, 0, sizeof(vi2)); + vi2.dwOSVersionInfoSize = sizeof(vi2); + vi2.dwMinorVersion = minor; + if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal)) + continue; + + vi.dwMinorVersion = minor; + break; + } + + break; + } + } + + if ((vi.dwMajorVersion > 0xf) || (vi.dwMinorVersion > 0xf)) + return; + + ws = (vi.wProductType <= VER_NT_WORKSTATION); + version = vi.dwMajorVersion << 4 | vi.dwMinorVersion; + switch (version) { + case 0x50: windows_version = WINDOWS_2000; w = "2000"; break; + case 0x51: windows_version = WINDOWS_XP; w = "XP"; break; + case 0x52: windows_version = WINDOWS_2003; w = "2003"; break; + case 0x60: windows_version = WINDOWS_VISTA; w = (ws ? "Vista" : "2008"); break; + case 0x61: windows_version = WINDOWS_7; w = (ws ? "7" : "2008_R2"); break; + case 0x62: windows_version = WINDOWS_8; w = (ws ? "8" : "2012"); break; + case 0x63: windows_version = WINDOWS_8_1; w = (ws ? "8.1" : "2012_R2"); break; + case 0x64: windows_version = WINDOWS_10; w = (ws ? "10" : "2016"); break; + default: + if (version < 0x50) { + return; + } else { + windows_version = WINDOWS_11_OR_LATER; + w = "11 or later"; + } + } + + arch = is_x64() ? "64-bit" : "32-bit"; + + if (vi.wServicePackMinor) + usbi_dbg("Windows %s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch); + else if (vi.wServicePackMajor) + usbi_dbg("Windows %s SP%u %s", w, vi.wServicePackMajor, arch); + else + usbi_dbg("Windows %s %s", w, arch); +} + /* * Monotonic and real time functions */ @@ -428,11 +534,385 @@ static unsigned __stdcall windows_clock_gettime_threaded(void *param) } } -int windows_clock_gettime(int clk_id, struct timespec *tp) +static void windows_transfer_callback(const struct windows_backend *backend, + struct usbi_transfer *itransfer, DWORD io_result, DWORD io_size) +{ + int status, istatus; + + usbi_dbg("handling I/O completion with errcode %u, size %u", (unsigned int)io_result, (unsigned int)io_size); + + switch (io_result) { + case NO_ERROR: + status = backend->copy_transfer_data(itransfer, (uint32_t)io_size); + break; + case ERROR_GEN_FAILURE: + usbi_dbg("detected endpoint stall"); + status = LIBUSB_TRANSFER_STALL; + break; + case ERROR_SEM_TIMEOUT: + usbi_dbg("detected semaphore timeout"); + status = LIBUSB_TRANSFER_TIMED_OUT; + break; + case ERROR_OPERATION_ABORTED: + istatus = backend->copy_transfer_data(itransfer, (uint32_t)io_size); + if (istatus != LIBUSB_TRANSFER_COMPLETED) + usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus); + + usbi_dbg("detected operation aborted"); + status = LIBUSB_TRANSFER_CANCELLED; + break; + case ERROR_FILE_NOT_FOUND: + usbi_dbg("detected device removed"); + status = LIBUSB_TRANSFER_NO_DEVICE; + break; + default: + usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %u: %s", (unsigned int)io_result, windows_error_str(io_result)); + status = LIBUSB_TRANSFER_ERROR; + break; + } + backend->clear_transfer_priv(itransfer); // Cancel polling + if (status == LIBUSB_TRANSFER_CANCELLED) + usbi_handle_transfer_cancellation(itransfer); + else + usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); +} + +static void windows_handle_callback(const struct windows_backend *backend, + struct usbi_transfer *itransfer, DWORD io_result, DWORD io_size) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + windows_transfer_callback(backend, itransfer, io_result, io_size); + break; + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + usbi_warn(ITRANSFER_CTX(itransfer), "bulk stream transfers are not yet supported on this platform"); + break; + default: + usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); + } +} + +static int windows_init(struct libusb_context *ctx) +{ + struct windows_context_priv *priv = _context_priv(ctx); + HANDLE semaphore; + char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' + int r = LIBUSB_ERROR_OTHER; + bool winusb_backend_init = false; + + sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); + semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name); + if (semaphore == NULL) { + usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_MEM; + } + + // A successful wait brings our semaphore count to 0 (unsignaled) + // => any concurent wait stalls until the semaphore's release + if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { + usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0)); + CloseHandle(semaphore); + return LIBUSB_ERROR_NO_MEM; + } + + // NB: concurrent usage supposes that init calls are equally balanced with + // exit calls. If init is called more than exit, we will not exit properly + if (++init_count == 1) { // First init? + // Load DLL imports + if (!windows_init_dlls()) { + usbi_err(ctx, "could not resolve DLL functions"); + goto init_exit; + } + + get_windows_version(); + + if (windows_version == WINDOWS_UNDEFINED) { + usbi_err(ctx, "failed to detect Windows version"); + r = LIBUSB_ERROR_NOT_SUPPORTED; + goto init_exit; + } + + if (!windows_init_clock(ctx)) + goto init_exit; + + if (!htab_create(ctx)) + goto init_exit; + + r = winusb_backend.init(ctx); + if (r != LIBUSB_SUCCESS) + goto init_exit; + winusb_backend_init = true; + + r = usbdk_backend.init(ctx); + if (r == LIBUSB_SUCCESS) { + usbi_dbg("UsbDk backend is available"); + usbdk_available = true; + } else { + usbi_info(ctx, "UsbDk backend is not available"); + // Do not report this as an error + r = LIBUSB_SUCCESS; + } + } + + // By default, new contexts will use the WinUSB backend + priv->backend = &winusb_backend; + + r = LIBUSB_SUCCESS; + +init_exit: // Holds semaphore here + if ((init_count == 1) && (r != LIBUSB_SUCCESS)) { // First init failed? + if (winusb_backend_init) + winusb_backend.exit(ctx); + htab_destroy(); + windows_destroy_clock(); + windows_exit_dlls(); + --init_count; + } + + ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 + CloseHandle(semaphore); + return r; +} + +static void windows_exit(struct libusb_context *ctx) +{ + HANDLE semaphore; + char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' + UNUSED(ctx); + + sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); + semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name); + if (semaphore == NULL) + return; + + // A successful wait brings our semaphore count to 0 (unsignaled) + // => any concurent wait stalls until the semaphore release + if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { + CloseHandle(semaphore); + return; + } + + // Only works if exits and inits are balanced exactly + if (--init_count == 0) { // Last exit + if (usbdk_available) { + usbdk_backend.exit(ctx); + usbdk_available = false; + } + winusb_backend.exit(ctx); + htab_destroy(); + windows_destroy_clock(); + windows_exit_dlls(); + } + + ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 + CloseHandle(semaphore); +} + +static int windows_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap) +{ + struct windows_context_priv *priv = _context_priv(ctx); + + UNUSED(ap); + + switch (option) { + case LIBUSB_OPTION_USE_USBDK: + if (usbdk_available) { + usbi_dbg("switching context %p to use UsbDk backend", ctx); + priv->backend = &usbdk_backend; + } else { + usbi_err(ctx, "UsbDk backend not available"); + return LIBUSB_ERROR_NOT_FOUND; + } + return LIBUSB_SUCCESS; + default: + return LIBUSB_ERROR_NOT_SUPPORTED; + } + +} + +static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs) +{ + struct windows_context_priv *priv = _context_priv(ctx); + return priv->backend->get_device_list(ctx, discdevs); +} + +static int windows_open(struct libusb_device_handle *dev_handle) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->open(dev_handle); +} + +static void windows_close(struct libusb_device_handle *dev_handle) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + priv->backend->close(dev_handle); +} + +static int windows_get_device_descriptor(struct libusb_device *dev, + unsigned char *buffer, int *host_endian) +{ + struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); + *host_endian = 0; + return priv->backend->get_device_descriptor(dev, buffer); +} + +static int windows_get_active_config_descriptor(struct libusb_device *dev, + unsigned char *buffer, size_t len, int *host_endian) +{ + struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); + *host_endian = 0; + return priv->backend->get_active_config_descriptor(dev, buffer, len); +} + +static int windows_get_config_descriptor(struct libusb_device *dev, + uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) +{ + struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); + *host_endian = 0; + return priv->backend->get_config_descriptor(dev, config_index, buffer, len); +} + +static int windows_get_config_descriptor_by_value(struct libusb_device *dev, + uint8_t bConfigurationValue, unsigned char **buffer, int *host_endian) +{ + struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); + *host_endian = 0; + return priv->backend->get_config_descriptor_by_value(dev, bConfigurationValue, buffer); +} + +static int windows_get_configuration(struct libusb_device_handle *dev_handle, int *config) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->get_configuration(dev_handle, config); +} + +static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->set_configuration(dev_handle, config); +} + +static int windows_claim_interface(struct libusb_device_handle *dev_handle, int interface_number) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->claim_interface(dev_handle, interface_number); +} + +static int windows_release_interface(struct libusb_device_handle *dev_handle, int interface_number) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->release_interface(dev_handle, interface_number); +} + +static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle, + int interface_number, int altsetting) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->set_interface_altsetting(dev_handle, interface_number, altsetting); +} + +static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->clear_halt(dev_handle, endpoint); +} + +static int windows_reset_device(struct libusb_device_handle *dev_handle) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->reset_device(dev_handle); +} + +static void windows_destroy_device(struct libusb_device *dev) +{ + struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); + priv->backend->destroy_device(dev); +} + +static int windows_submit_transfer(struct usbi_transfer *itransfer) +{ + struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer)); + return priv->backend->submit_transfer(itransfer); +} + +static int windows_cancel_transfer(struct usbi_transfer *itransfer) +{ + struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer)); + return priv->backend->cancel_transfer(itransfer); +} + +static void windows_clear_transfer_priv(struct usbi_transfer *itransfer) +{ + struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer)); + priv->backend->clear_transfer_priv(itransfer); +} + +static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) +{ + struct windows_context_priv *priv = _context_priv(ctx); + struct usbi_transfer *itransfer; + DWORD io_size, io_result; + POLL_NFDS_TYPE i; + bool found; + int transfer_fd; + int r = LIBUSB_SUCCESS; + + usbi_mutex_lock(&ctx->open_devs_lock); + for (i = 0; i < nfds && num_ready > 0; i++) { + + usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); + + if (!fds[i].revents) + continue; + + num_ready--; + + // Because a Windows OVERLAPPED is used for poll emulation, + // a pollable fd is created and stored with each transfer + found = false; + transfer_fd = -1; + usbi_mutex_lock(&ctx->flying_transfers_lock); + list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) { + transfer_fd = priv->backend->get_transfer_fd(itransfer); + if (transfer_fd == fds[i].fd) { + found = true; + break; + } + } + usbi_mutex_unlock(&ctx->flying_transfers_lock); + + if (found) { + priv->backend->get_overlapped_result(itransfer, &io_result, &io_size); + + usbi_remove_pollfd(ctx, transfer_fd); + + // let handle_callback free the event using the transfer wfd + // If you don't use the transfer wfd, you run a risk of trying to free a + // newly allocated wfd that took the place of the one from the transfer. + windows_handle_callback(priv->backend, itransfer, io_result, io_size); + } else { + usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i].fd); + r = LIBUSB_ERROR_NOT_FOUND; + break; + } + } + usbi_mutex_unlock(&ctx->open_devs_lock); + + return r; +} + +static int windows_clock_gettime(int clk_id, struct timespec *tp) { struct timer_request request; +#if !defined(_MSC_VER) || (_MSC_VER < 1900) FILETIME filetime; ULARGE_INTEGER rtime; +#endif DWORD r; switch (clk_id) { @@ -465,153 +945,65 @@ int windows_clock_gettime(int clk_id, struct timespec *tp) } // Fall through and return real-time if monotonic was not detected @ timer init case USBI_CLOCK_REALTIME: +#if defined(_MSC_VER) && (_MSC_VER >= 1900) + timespec_get(tp, TIME_UTC); +#else // We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx - // with a predef epoch_time to have an epoch that starts at 1970.01.01 00:00 + // with a predef epoch time to have an epoch that starts at 1970.01.01 00:00 // Note however that our resolution is bounded by the Windows system time // functions and is at best of the order of 1 ms (or, usually, worse) GetSystemTimeAsFileTime(&filetime); rtime.LowPart = filetime.dwLowDateTime; rtime.HighPart = filetime.dwHighDateTime; - rtime.QuadPart -= epoch_time; + rtime.QuadPart -= EPOCH_TIME; tp->tv_sec = (long)(rtime.QuadPart / 10000000); tp->tv_nsec = (long)((rtime.QuadPart % 10000000) * 100); +#endif return LIBUSB_SUCCESS; default: return LIBUSB_ERROR_INVALID_PARAM; } } -static void windows_transfer_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size) -{ - int status, istatus; - - usbi_dbg("handling I/O completion with errcode %u, size %u", io_result, io_size); - - switch (io_result) { - case NO_ERROR: - status = backend_func.copy_transfer_data(itransfer, io_size); - break; - case ERROR_GEN_FAILURE: - usbi_dbg("detected endpoint stall"); - status = LIBUSB_TRANSFER_STALL; - break; - case ERROR_SEM_TIMEOUT: - usbi_dbg("detected semaphore timeout"); - status = LIBUSB_TRANSFER_TIMED_OUT; - break; - case ERROR_OPERATION_ABORTED: - istatus = backend_func.copy_transfer_data(itransfer, io_size); - if (istatus != LIBUSB_TRANSFER_COMPLETED) - usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus); - - usbi_dbg("detected operation aborted"); - status = LIBUSB_TRANSFER_CANCELLED; - break; - default: - usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %u: %s", io_result, windows_error_str(io_result)); - status = LIBUSB_TRANSFER_ERROR; - break; - } - backend_func.clear_transfer_priv(itransfer); // Cancel polling - if (status == LIBUSB_TRANSFER_CANCELLED) - usbi_handle_transfer_cancellation(itransfer); - else - usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); -} - -void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - windows_transfer_callback(itransfer, io_result, io_size); - break; - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - usbi_warn(ITRANSFER_CTX(itransfer), "bulk stream transfers are not yet supported on this platform"); - break; - default: - usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); - } -} - -int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) -{ - POLL_NFDS_TYPE i = 0; - bool found = false; - struct usbi_transfer *transfer; - struct winfd *pollable_fd = NULL; - DWORD io_size, io_result; - int r = LIBUSB_SUCCESS; - - usbi_mutex_lock(&ctx->open_devs_lock); - for (i = 0; i < nfds && num_ready > 0; i++) { - - usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); - - if (!fds[i].revents) - continue; - - num_ready--; - - // Because a Windows OVERLAPPED is used for poll emulation, - // a pollable fd is created and stored with each transfer - usbi_mutex_lock(&ctx->flying_transfers_lock); - found = false; - list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { - pollable_fd = backend_func.get_fd(transfer); - if (pollable_fd->fd == fds[i].fd) { - found = true; - break; - } - } - usbi_mutex_unlock(&ctx->flying_transfers_lock); - - if (found) { - backend_func.get_overlapped_result(transfer, pollable_fd, &io_result, &io_size); - - usbi_remove_pollfd(ctx, pollable_fd->fd); - // let handle_callback free the event using the transfer wfd - // If you don't use the transfer wfd, you run a risk of trying to free a - // newly allocated wfd that took the place of the one from the transfer. - windows_handle_callback(transfer, io_result, io_size); - } else { - usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]); - r = LIBUSB_ERROR_NOT_FOUND; - break; - } - } - usbi_mutex_unlock(&ctx->open_devs_lock); - - return r; -} - -int windows_common_init(struct libusb_context *ctx) -{ - if (!windows_init_clock(ctx)) - goto error_roll_back; - - if (!htab_create(ctx, HTAB_SIZE)) - goto error_roll_back; - - return LIBUSB_SUCCESS; - -error_roll_back: - windows_common_exit(); - return LIBUSB_ERROR_NO_MEM; -} - -void windows_common_exit(void) -{ - htab_destroy(); - windows_destroy_clock(); - windows_exit_dlls(); -} - -void win_nt_init(win_backend *backend) -{ - backend_func = *backend; -} +// NB: MSVC6 does not support named initializers. +const struct usbi_os_backend usbi_backend = { + "Windows", + USBI_CAP_HAS_HID_ACCESS, + windows_init, + windows_exit, + windows_set_option, + windows_get_device_list, + NULL, /* hotplug_poll */ + NULL, /* wrap_sys_device */ + windows_open, + windows_close, + windows_get_device_descriptor, + windows_get_active_config_descriptor, + windows_get_config_descriptor, + windows_get_config_descriptor_by_value, + windows_get_configuration, + windows_set_configuration, + windows_claim_interface, + windows_release_interface, + windows_set_interface_altsetting, + windows_clear_halt, + windows_reset_device, + NULL, /* alloc_streams */ + NULL, /* free_streams */ + NULL, /* dev_mem_alloc */ + NULL, /* dev_mem_free */ + NULL, /* kernel_driver_active */ + NULL, /* detach_kernel_driver */ + NULL, /* attach_kernel_driver */ + windows_destroy_device, + windows_submit_transfer, + windows_cancel_transfer, + windows_clear_transfer_priv, + windows_handle_events, + NULL, /* handle_transfer_completion */ + windows_clock_gettime, + sizeof(struct windows_context_priv), + sizeof(union windows_device_priv), + sizeof(union windows_device_handle_priv), + sizeof(union windows_transfer_priv), +}; diff --git a/Externals/libusb/libusb/os/windows_nt_common.h b/Externals/libusb/libusb/os/windows_nt_common.h index 22d5256aa5..e155b5d3e3 100644 --- a/Externals/libusb/libusb/os/windows_nt_common.h +++ b/Externals/libusb/libusb/os/windows_nt_common.h @@ -26,48 +26,85 @@ #pragma once -// Missing from MinGW -#if !defined(FACILITY_SETUPAPI) -#define FACILITY_SETUPAPI 15 -#endif +#include "windows_nt_shared_types.h" -typedef struct USB_CONFIGURATION_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - USHORT wTotalLength; - UCHAR bNumInterfaces; - UCHAR bConfigurationValue; - UCHAR iConfiguration; - UCHAR bmAttributes; - UCHAR MaxPower; -} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR; + /* Windows versions */ +enum windows_version { + WINDOWS_UNDEFINED, + WINDOWS_2000, + WINDOWS_XP, + WINDOWS_2003, // Also XP x64 + WINDOWS_VISTA, + WINDOWS_7, + WINDOWS_8, + WINDOWS_8_1, + WINDOWS_10, + WINDOWS_11_OR_LATER +}; -typedef struct libusb_device_descriptor USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR; +extern enum windows_version windows_version; -int windows_common_init(struct libusb_context *ctx); -void windows_common_exit(void); +/* This call is only available from Vista */ +extern BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED); + +struct windows_backend { + int (*init)(struct libusb_context *ctx); + void (*exit)(struct libusb_context *ctx); + int (*get_device_list)(struct libusb_context *ctx, + struct discovered_devs **discdevs); + int (*open)(struct libusb_device_handle *dev_handle); + void (*close)(struct libusb_device_handle *dev_handle); + int (*get_device_descriptor)(struct libusb_device *device, unsigned char *buffer); + int (*get_active_config_descriptor)(struct libusb_device *device, + unsigned char *buffer, size_t len); + int (*get_config_descriptor)(struct libusb_device *device, + uint8_t config_index, unsigned char *buffer, size_t len); + int (*get_config_descriptor_by_value)(struct libusb_device *device, + uint8_t bConfigurationValue, unsigned char **buffer); + int (*get_configuration)(struct libusb_device_handle *dev_handle, int *config); + int (*set_configuration)(struct libusb_device_handle *dev_handle, int config); + int (*claim_interface)(struct libusb_device_handle *dev_handle, int interface_number); + int (*release_interface)(struct libusb_device_handle *dev_handle, int interface_number); + int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle, + int interface_number, int altsetting); + int (*clear_halt)(struct libusb_device_handle *dev_handle, + unsigned char endpoint); + int (*reset_device)(struct libusb_device_handle *dev_handle); + void (*destroy_device)(struct libusb_device *dev); + int (*submit_transfer)(struct usbi_transfer *itransfer); + int (*cancel_transfer)(struct usbi_transfer *itransfer); + void (*clear_transfer_priv)(struct usbi_transfer *itransfer); + int (*copy_transfer_data)(struct usbi_transfer *itransfer, uint32_t io_size); + int (*get_transfer_fd)(struct usbi_transfer *itransfer); + void (*get_overlapped_result)(struct usbi_transfer *itransfer, + DWORD *io_result, DWORD *io_size); +}; + +struct windows_context_priv { + const struct windows_backend *backend; +}; + +union windows_device_priv { + struct usbdk_device_priv usbdk_priv; + struct winusb_device_priv winusb_priv; +}; + +union windows_device_handle_priv { + struct usbdk_device_handle_priv usbdk_priv; + struct winusb_device_handle_priv winusb_priv; +}; + +union windows_transfer_priv { + struct usbdk_transfer_priv usbdk_priv; + struct winusb_transfer_priv winusb_priv; +}; + +extern const struct windows_backend usbdk_backend; +extern const struct windows_backend winusb_backend; unsigned long htab_hash(const char *str); -int windows_clock_gettime(int clk_id, struct timespec *tp); - -typedef void(*CLEAR_TRANSFER_PRIV)(struct usbi_transfer *itransfer); -typedef int(*COPY_TRANSFER_DATA)(struct usbi_transfer *itransfer, uint32_t io_size); -typedef struct winfd *(*GET_FD)(struct usbi_transfer *transfer); -typedef void(*GET_OVERLAPPED_RESULT)(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size); - -typedef struct win_backend -{ - CLEAR_TRANSFER_PRIV clear_transfer_priv; - COPY_TRANSFER_DATA copy_transfer_data; - GET_FD get_fd; - GET_OVERLAPPED_RESULT get_overlapped_result; -} win_backend; - -void win_nt_init(win_backend *backend); - -void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size); -int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready); +void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size); #if defined(ENABLE_LOGGING) -const char *windows_error_str(DWORD retval); +const char *windows_error_str(DWORD error_code); #endif diff --git a/Externals/libusb/libusb/os/windows_nt_shared_types.h b/Externals/libusb/libusb/os/windows_nt_shared_types.h new file mode 100644 index 0000000000..d809bfd7d9 --- /dev/null +++ b/Externals/libusb/libusb/os/windows_nt_shared_types.h @@ -0,0 +1,147 @@ +#pragma once + +#include "windows_common.h" + +#include + +typedef struct USB_DEVICE_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + USHORT bcdUSB; + UCHAR bDeviceClass; + UCHAR bDeviceSubClass; + UCHAR bDeviceProtocol; + UCHAR bMaxPacketSize0; + USHORT idVendor; + USHORT idProduct; + USHORT bcdDevice; + UCHAR iManufacturer; + UCHAR iProduct; + UCHAR iSerialNumber; + UCHAR bNumConfigurations; +} USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR; + +typedef struct USB_CONFIGURATION_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + USHORT wTotalLength; + UCHAR bNumInterfaces; + UCHAR bConfigurationValue; + UCHAR iConfiguration; + UCHAR bmAttributes; + UCHAR MaxPower; +} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR; + +#include + +#define MAX_DEVICE_ID_LEN 200 + +typedef struct USB_DK_DEVICE_ID { + WCHAR DeviceID[MAX_DEVICE_ID_LEN]; + WCHAR InstanceID[MAX_DEVICE_ID_LEN]; +} USB_DK_DEVICE_ID, *PUSB_DK_DEVICE_ID; + +typedef struct USB_DK_DEVICE_INFO { + USB_DK_DEVICE_ID ID; + ULONG64 FilterID; + ULONG64 Port; + ULONG64 Speed; + USB_DEVICE_DESCRIPTOR DeviceDescriptor; +} USB_DK_DEVICE_INFO, *PUSB_DK_DEVICE_INFO; + +typedef struct USB_DK_ISO_TRANSFER_RESULT { + ULONG64 ActualLength; + ULONG64 TransferResult; +} USB_DK_ISO_TRANSFER_RESULT, *PUSB_DK_ISO_TRANSFER_RESULT; + +typedef struct USB_DK_GEN_TRANSFER_RESULT { + ULONG64 BytesTransferred; + ULONG64 UsbdStatus; // USBD_STATUS code +} USB_DK_GEN_TRANSFER_RESULT, *PUSB_DK_GEN_TRANSFER_RESULT; + +typedef struct USB_DK_TRANSFER_RESULT { + USB_DK_GEN_TRANSFER_RESULT GenResult; + PVOID64 IsochronousResultsArray; // array of USB_DK_ISO_TRANSFER_RESULT +} USB_DK_TRANSFER_RESULT, *PUSB_DK_TRANSFER_RESULT; + +typedef struct USB_DK_TRANSFER_REQUEST { + ULONG64 EndpointAddress; + PVOID64 Buffer; + ULONG64 BufferLength; + ULONG64 TransferType; + ULONG64 IsochronousPacketsArraySize; + PVOID64 IsochronousPacketsArray; + USB_DK_TRANSFER_RESULT Result; +} USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST; + +struct usbdk_device_priv { + USB_DK_DEVICE_INFO info; + PUSB_CONFIGURATION_DESCRIPTOR *config_descriptors; + HANDLE redirector_handle; + HANDLE system_handle; + uint8_t active_configuration; +}; + +struct winusb_device_priv { + bool initialized; + bool root_hub; + uint8_t active_config; + uint8_t depth; // distance to HCD + const struct windows_usb_api_backend *apib; + char *dev_id; + char *path; // device interface path + int sub_api; // for WinUSB-like APIs + struct { + char *path; // each interface needs a device interface path, + const struct windows_usb_api_backend *apib; // an API backend (multiple drivers support), + int sub_api; + int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS) + uint8_t *endpoint; + int current_altsetting; + 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]; + struct hid_device_priv *hid; + USB_DEVICE_DESCRIPTOR dev_descriptor; + PUSB_CONFIGURATION_DESCRIPTOR *config_descriptor; // list of pointers to the cached config descriptors +}; + +struct usbdk_device_handle_priv { + // Not currently used + char dummy; +}; + +struct winusb_device_handle_priv { + int active_interface; + struct { + HANDLE dev_handle; // WinUSB needs an extra handle for the file + HANDLE api_handle; // used by the API to communicate with the device + } interface_handle[USB_MAXINTERFACES]; + int autoclaim_count[USB_MAXINTERFACES]; // For auto-release +}; + +struct usbdk_transfer_priv { + USB_DK_TRANSFER_REQUEST request; + struct winfd pollable_fd; + HANDLE system_handle; + PULONG64 IsochronousPacketsArray; + PUSB_DK_ISO_TRANSFER_RESULT IsochronousResultsArray; +}; + +struct winusb_transfer_priv { + struct winfd pollable_fd; + HANDLE handle; + 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; + + // For isochronous transfers with LibUSBk driver: + void *iso_context; + + // For isochronous transfers with Microsoft WinUSB driver: + void *isoch_buffer_handle; // The isoch_buffer_handle to free at the end of the transfer + BOOL iso_break_stream; // Whether the isoch. stream was to be continued in the last call of libusb_submit_transfer. + // As we this structure is zeroed out upon initialization, we need to use inverse logic here. + libusb_transfer_cb_fn iso_user_callback; // Original transfer callback of the user. Might be used for isochronous transfers. +}; diff --git a/Externals/libusb/libusb/os/windows_usbdk.c b/Externals/libusb/libusb/os/windows_usbdk.c index a588e51e82..fbccbd5cff 100644 --- a/Externals/libusb/libusb/os/windows_usbdk.c +++ b/Externals/libusb/libusb/os/windows_usbdk.c @@ -24,19 +24,11 @@ #include #include -#include #include #include "libusbi.h" #include "windows_common.h" #include "windows_nt_common.h" - -#define ULONG64 uint64_t -#define PVOID64 uint64_t - -typedef CONST WCHAR *PCWCHAR; -#define wcsncpy_s wcsncpy - #include "windows_usbdk.h" #if !defined(STATUS_SUCCESS) @@ -53,7 +45,7 @@ typedef LONG NTSTATUS; #endif #if !defined(USBD_SUCCESS) -typedef int32_t USBD_STATUS; +typedef LONG USBD_STATUS; #define USBD_SUCCESS(Status) ((USBD_STATUS) (Status) >= 0) #define USBD_PENDING(Status) ((ULONG) (Status) >> 30 == 1) #define USBD_ERROR(Status) ((USBD_STATUS) (Status) < 0) @@ -64,24 +56,6 @@ typedef int32_t USBD_STATUS; #define USBD_STATUS_CANCELED ((USBD_STATUS) 0xc0010000) #endif -static void backend_init(void); - -static int concurrent_usage = -1; - -struct usbdk_device_priv { - USB_DK_DEVICE_INFO info; - PUSB_CONFIGURATION_DESCRIPTOR *config_descriptors; - HANDLE redirector_handle; - uint8_t active_configuration; -}; - -struct usbdk_transfer_priv { - USB_DK_TRANSFER_REQUEST request; - struct winfd pollable_fd; - PULONG64 IsochronousPacketsArray; - PUSB_DK_ISO_TRANSFER_RESULT IsochronousResultsArray; -}; - static inline struct usbdk_device_priv *_usbdk_device_priv(struct libusb_device *dev) { return (struct usbdk_device_priv *)dev->os_priv; @@ -115,7 +89,7 @@ static FARPROC get_usbdk_proc_addr(struct libusb_context *ctx, LPCSTR api_name) FARPROC api_ptr = GetProcAddress(usbdk_helper.module, api_name); if (api_ptr == NULL) - usbi_err(ctx, "UsbDkHelper API %s not found, error %d", api_name, GetLastError()); + usbi_err(ctx, "UsbDkHelper API %s not found: %s", api_name, windows_error_str(0)); return api_ptr; } @@ -132,7 +106,7 @@ static int load_usbdk_helper_dll(struct libusb_context *ctx) { usbdk_helper.module = LoadLibraryA("UsbDkHelper"); if (usbdk_helper.module == NULL) { - usbi_err(ctx, "Failed to load UsbDkHelper.dll, error %d", GetLastError()); + usbi_err(ctx, "Failed to load UsbDkHelper.dll: %s", windows_error_str(0)); return LIBUSB_ERROR_NOT_FOUND; } @@ -198,44 +172,41 @@ error_unload: static int usbdk_init(struct libusb_context *ctx) { - int r; + SC_HANDLE managerHandle; + SC_HANDLE serviceHandle; - if (++concurrent_usage == 0) { // First init? - - backend_init(); - - r = load_usbdk_helper_dll(ctx); - if (r) - goto init_exit; - - init_polling(); - - r = windows_common_init(ctx); - if (r) - goto init_exit; - } - // At this stage, either we went through full init successfully, or didn't need to - r = LIBUSB_SUCCESS; - -init_exit: - if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? - exit_polling(); - windows_common_exit(); - unload_usbdk_helper_dll(); + managerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); + if (managerHandle == NULL) { + usbi_warn(ctx, "failed to open service control manager: %s", windows_error_str(0)); + return LIBUSB_ERROR_OTHER; } - if (r != LIBUSB_SUCCESS) - --concurrent_usage; // Not expected to call libusb_exit if we failed. + serviceHandle = OpenServiceA(managerHandle, "UsbDk", GENERIC_READ); + CloseServiceHandle(managerHandle); - return r; + if (serviceHandle == NULL) { + if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST) + usbi_warn(ctx, "failed to open UsbDk service: %s", windows_error_str(0)); + return LIBUSB_ERROR_NOT_FOUND; + } + + CloseServiceHandle(serviceHandle); + + return load_usbdk_helper_dll(ctx); +} + +static void usbdk_exit(struct libusb_context *ctx) +{ + UNUSED(ctx); + unload_usbdk_helper_dll(); } static int usbdk_get_session_id_for_device(struct libusb_context *ctx, PUSB_DK_DEVICE_ID id, unsigned long *session_id) { - char dev_identity[ARRAYSIZE(id->DeviceID) + ARRAYSIZE(id->InstanceID)]; + char dev_identity[ARRAYSIZE(id->DeviceID) + ARRAYSIZE(id->InstanceID) + 1]; - if (sprintf(dev_identity, "%S%S", id->DeviceID, id->InstanceID) == -1) { + if (snprintf(dev_identity, sizeof(dev_identity), "%S%S", id->DeviceID, id->InstanceID) == -1) { usbi_warn(ctx, "cannot form device identity", id->DeviceID); return LIBUSB_ERROR_NOT_SUPPORTED; } @@ -299,11 +270,11 @@ static void usbdk_device_init(libusb_device *dev, PUSB_DK_DEVICE_INFO info) dev->port_number = (uint8_t)info->Port; dev->parent_dev = NULL; - //Addresses in libusb are 1-based + // Addresses in libusb are 1-based dev->device_address = (uint8_t)(info->Port + 1); dev->num_configurations = info->DeviceDescriptor.bNumConfigurations; - dev->device_descriptor = info->DeviceDescriptor; + memcpy(&dev->device_descriptor, &info->DeviceDescriptor, LIBUSB_DT_DEVICE_SIZE); switch (info->Speed) { case LowSpeed: @@ -333,7 +304,7 @@ static int usbdk_get_device_list(struct libusb_context *ctx, struct discovered_d ULONG dev_number; PUSB_DK_DEVICE_INFO devices; - if(!usbdk_helper.GetDevicesList(&devices, &dev_number)) + if (!usbdk_helper.GetDevicesList(&devices, &dev_number)) return LIBUSB_ERROR_OTHER; for (i = 0; i < dev_number; i++) { @@ -374,26 +345,16 @@ func_exit: return r; } -static void usbdk_exit(void) -{ - if (--concurrent_usage < 0) { - windows_common_exit(); - exit_polling(); - unload_usbdk_helper_dll(); - } -} - -static int usbdk_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian) +static int usbdk_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer) { struct usbdk_device_priv *priv = _usbdk_device_priv(dev); memcpy(buffer, &priv->info.DeviceDescriptor, DEVICE_DESC_LENGTH); - *host_endian = 0; return LIBUSB_SUCCESS; } -static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) +static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len) { struct usbdk_device_priv *priv = _usbdk_device_priv(dev); PUSB_CONFIGURATION_DESCRIPTOR config_header; @@ -406,15 +367,31 @@ static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config size = min(config_header->wTotalLength, len); memcpy(buffer, config_header, size); - *host_endian = 0; - return (int)size; } -static inline int usbdk_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian) +static int usbdk_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue, + unsigned char **buffer) +{ + struct usbdk_device_priv *priv = _usbdk_device_priv(dev); + PUSB_CONFIGURATION_DESCRIPTOR config_header; + uint8_t index; + + for (index = 0; index < dev->num_configurations; index++) { + config_header = priv->config_descriptors[index]; + if (config_header->bConfigurationValue == bConfigurationValue) { + *buffer = (unsigned char *)priv->config_descriptors[index]; + return (int)config_header->wTotalLength; + } + } + + return LIBUSB_ERROR_NOT_FOUND; +} + +static int usbdk_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len) { return usbdk_get_config_descriptor(dev, _usbdk_device_priv(dev)->active_configuration, - buffer, len, host_endian); + buffer, len); } static int usbdk_open(struct libusb_device_handle *dev_handle) @@ -427,6 +404,8 @@ static int usbdk_open(struct libusb_device_handle *dev_handle) return LIBUSB_ERROR_OTHER; } + priv->system_handle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); + return LIBUSB_SUCCESS; } @@ -434,10 +413,8 @@ static void usbdk_close(struct libusb_device_handle *dev_handle) { struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); - if (!usbdk_helper.StopRedirect(priv->redirector_handle)) { - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - usbi_err(ctx, "Redirector shutdown failed"); - } + if (!usbdk_helper.StopRedirect(priv->redirector_handle)) + usbi_err(HANDLE_CTX(dev_handle), "Redirector shutdown failed"); } static int usbdk_get_configuration(struct libusb_device_handle *dev_handle, int *config) @@ -463,7 +440,7 @@ static int usbdk_claim_interface(struct libusb_device_handle *dev_handle, int if static int usbdk_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) { - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct libusb_context *ctx = HANDLE_CTX(dev_handle); struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); if (!usbdk_helper.SetAltsetting(priv->redirector_handle, iface, altsetting)) { @@ -483,7 +460,7 @@ static int usbdk_release_interface(struct libusb_device_handle *dev_handle, int static int usbdk_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) { - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct libusb_context *ctx = HANDLE_CTX(dev_handle); struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); if (!usbdk_helper.ResetPipe(priv->redirector_handle, endpoint)) { @@ -496,7 +473,7 @@ static int usbdk_clear_halt(struct libusb_device_handle *dev_handle, unsigned ch static int usbdk_reset_device(struct libusb_device_handle *dev_handle) { - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct libusb_context *ctx = HANDLE_CTX(dev_handle); struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); if (!usbdk_helper.ResetDevice(priv->redirector_handle)) { @@ -507,27 +484,6 @@ static int usbdk_reset_device(struct libusb_device_handle *dev_handle) return LIBUSB_SUCCESS; } -static int usbdk_kernel_driver_active(struct libusb_device_handle *dev_handle, int iface) -{ - UNUSED(dev_handle); - UNUSED(iface); - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static int usbdk_attach_kernel_driver(struct libusb_device_handle *dev_handle, int iface) -{ - UNUSED(dev_handle); - UNUSED(iface); - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static int usbdk_detach_kernel_driver(struct libusb_device_handle *dev_handle, int iface) -{ - UNUSED(dev_handle); - UNUSED(iface); - return LIBUSB_ERROR_NOT_SUPPORTED; -} - static void usbdk_destroy_device(struct libusb_device *dev) { struct usbdk_device_priv* p = _usbdk_device_priv(dev); @@ -536,12 +492,14 @@ static void usbdk_destroy_device(struct libusb_device *dev) usbdk_release_config_descriptors(p, p->info.DeviceDescriptor.bNumConfigurations); } -static void windows_clear_transfer_priv(struct usbi_transfer *itransfer) +static void usbdk_clear_transfer_priv(struct usbi_transfer *itransfer) { struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - usbi_free_fd(&transfer_priv->pollable_fd); + usbi_close(transfer_priv->pollable_fd.fd); + transfer_priv->pollable_fd = INVALID_WINFD; + transfer_priv->system_handle = NULL; if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { safe_free(transfer_priv->IsochronousPacketsArray); @@ -554,47 +512,30 @@ static int usbdk_do_control_transfer(struct usbi_transfer *itransfer) struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winfd wfd; - ULONG Length; + struct libusb_context *ctx = TRANSFER_CTX(transfer); + OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped; TransferResult transResult; - HANDLE sysHandle; - sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); - - wfd = usbi_create_fd(sysHandle, RW_READ, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) - return LIBUSB_ERROR_NO_MEM; - - transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; + transfer_priv->request.Buffer = (PVOID64)transfer->buffer; transfer_priv->request.BufferLength = transfer->length; transfer_priv->request.TransferType = ControlTransferType; - transfer_priv->pollable_fd = INVALID_WINFD; - Length = (ULONG)transfer->length; - if (IS_XFERIN(transfer)) - transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + if (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) + transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped); else - transResult = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + transResult = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped); switch (transResult) { case TransferSuccess: - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - wfd.overlapped->InternalHigh = (DWORD)Length; + windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred); break; case TransferSuccessAsync: break; case TransferFailure: usbi_err(ctx, "ControlTransfer failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); return LIBUSB_ERROR_IO; } - // Use priv_transfer to store data needed for async polling - transfer_priv->pollable_fd = wfd; - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN); - return LIBUSB_SUCCESS; } @@ -603,12 +544,11 @@ static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer) struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winfd wfd; + struct libusb_context *ctx = TRANSFER_CTX(transfer); + OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped; TransferResult transferRes; - HANDLE sysHandle; - transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; + transfer_priv->request.Buffer = (PVOID64)transfer->buffer; transfer_priv->request.BufferLength = transfer->length; transfer_priv->request.EndpointAddress = transfer->endpoint; @@ -617,42 +557,29 @@ static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer) transfer_priv->request.TransferType = BulkTransferType; break; case LIBUSB_TRANSFER_TYPE_INTERRUPT: - transfer_priv->request.TransferType = IntertuptTransferType; + transfer_priv->request.TransferType = InterruptTransferType; break; default: - usbi_err(ctx, "Wrong transfer type (%d) in usbdk_do_bulk_transfer. %s", transfer->type, windows_error_str(0)); + usbi_err(ctx, "Wrong transfer type (%d) in usbdk_do_bulk_transfer", transfer->type); return LIBUSB_ERROR_INVALID_PARAM; } - transfer_priv->pollable_fd = INVALID_WINFD; - - sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); - - wfd = usbi_create_fd(sysHandle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) - return LIBUSB_ERROR_NO_MEM; - if (IS_XFERIN(transfer)) - transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped); else - transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped); switch (transferRes) { case TransferSuccess: - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; + windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred); break; case TransferSuccessAsync: break; case TransferFailure: usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); return LIBUSB_ERROR_IO; } - transfer_priv->pollable_fd = wfd; - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, IS_XFERIN(transfer) ? POLLIN : POLLOUT); - return LIBUSB_SUCCESS; } @@ -661,68 +588,81 @@ static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer) struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winfd wfd; + struct libusb_context *ctx = TRANSFER_CTX(transfer); + OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped; TransferResult transferRes; int i; - HANDLE sysHandle; - transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; + transfer_priv->request.Buffer = (PVOID64)transfer->buffer; transfer_priv->request.BufferLength = transfer->length; transfer_priv->request.EndpointAddress = transfer->endpoint; transfer_priv->request.TransferType = IsochronousTransferType; transfer_priv->request.IsochronousPacketsArraySize = transfer->num_iso_packets; transfer_priv->IsochronousPacketsArray = malloc(transfer->num_iso_packets * sizeof(ULONG64)); - transfer_priv->request.IsochronousPacketsArray = (PVOID64)(uintptr_t)transfer_priv->IsochronousPacketsArray; + transfer_priv->request.IsochronousPacketsArray = (PVOID64)transfer_priv->IsochronousPacketsArray; if (!transfer_priv->IsochronousPacketsArray) { - usbi_err(ctx, "Allocation of IsochronousPacketsArray is failed, %s", windows_error_str(0)); - return LIBUSB_ERROR_IO; + usbi_err(ctx, "Allocation of IsochronousPacketsArray failed"); + return LIBUSB_ERROR_NO_MEM; } transfer_priv->IsochronousResultsArray = malloc(transfer->num_iso_packets * sizeof(USB_DK_ISO_TRANSFER_RESULT)); - transfer_priv->request.Result.IsochronousResultsArray = (PVOID64)(uintptr_t)transfer_priv->IsochronousResultsArray; + transfer_priv->request.Result.IsochronousResultsArray = (PVOID64)transfer_priv->IsochronousResultsArray; if (!transfer_priv->IsochronousResultsArray) { - usbi_err(ctx, "Allocation of isochronousResultsArray is failed, %s", windows_error_str(0)); - free(transfer_priv->IsochronousPacketsArray); - return LIBUSB_ERROR_IO; + usbi_err(ctx, "Allocation of isochronousResultsArray failed"); + return LIBUSB_ERROR_NO_MEM; } for (i = 0; i < transfer->num_iso_packets; i++) transfer_priv->IsochronousPacketsArray[i] = transfer->iso_packet_desc[i].length; - transfer_priv->pollable_fd = INVALID_WINFD; - - sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); - - wfd = usbi_create_fd(sysHandle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) { - free(transfer_priv->IsochronousPacketsArray); - free(transfer_priv->IsochronousResultsArray); - return LIBUSB_ERROR_NO_MEM; - } - if (IS_XFERIN(transfer)) - transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped); else - transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped); switch (transferRes) { case TransferSuccess: - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; + windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred); break; case TransferSuccessAsync: break; case TransferFailure: - usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); - free(transfer_priv->IsochronousPacketsArray); - free(transfer_priv->IsochronousResultsArray); return LIBUSB_ERROR_IO; } + return LIBUSB_SUCCESS; +} + +static int usbdk_do_submit_transfer(struct usbi_transfer *itransfer, + short events, int (*transfer_fn)(struct usbi_transfer *)) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = TRANSFER_CTX(transfer); + struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct winfd wfd; + int r; + + wfd = usbi_create_fd(); + if (wfd.fd < 0) + return LIBUSB_ERROR_NO_MEM; + + r = usbi_add_pollfd(ctx, wfd.fd, events); + if (r) { + usbi_close(wfd.fd); + return r; + } + + // Use transfer_priv to store data needed for async polling transfer_priv->pollable_fd = wfd; - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, IS_XFERIN(transfer) ? POLLIN : POLLOUT); + transfer_priv->system_handle = priv->system_handle; + + r = transfer_fn(itransfer); + if (r != LIBUSB_SUCCESS) { + usbi_remove_pollfd(ctx, wfd.fd); + usbdk_clear_transfer_priv(itransfer); + return r; + } return LIBUSB_SUCCESS; } @@ -730,33 +670,52 @@ static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer) static int usbdk_submit_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + int (*transfer_fn)(struct usbi_transfer *); + short events; switch (transfer->type) { case LIBUSB_TRANSFER_TYPE_CONTROL: - return usbdk_do_control_transfer(itransfer); + events = (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) ? POLLIN : POLLOUT; + transfer_fn = usbdk_do_control_transfer; + break; case LIBUSB_TRANSFER_TYPE_BULK: case LIBUSB_TRANSFER_TYPE_INTERRUPT: if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)) return LIBUSB_ERROR_NOT_SUPPORTED; //TODO: Check whether we can support this in UsbDk - else - return usbdk_do_bulk_transfer(itransfer); + events = IS_XFERIN(transfer) ? POLLIN : POLLOUT; + transfer_fn = usbdk_do_bulk_transfer; + break; case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return usbdk_do_iso_transfer(itransfer); + events = IS_XFERIN(transfer) ? POLLIN : POLLOUT; + transfer_fn = usbdk_do_iso_transfer; + break; default: usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); return LIBUSB_ERROR_INVALID_PARAM; } + + return usbdk_do_submit_transfer(itransfer, events, transfer_fn); } static int usbdk_abort_transfers(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct libusb_context *ctx = TRANSFER_CTX(transfer); struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct winfd *pollable_fd = &transfer_priv->pollable_fd; - if (!usbdk_helper.AbortPipe(priv->redirector_handle, transfer->endpoint)) { - usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; + if (pCancelIoEx != NULL) { + // Use CancelIoEx if available to cancel just a single transfer + if (!pCancelIoEx(priv->system_handle, pollable_fd->overlapped)) { + usbi_err(ctx, "CancelIoEx failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } + } else { + if (!usbdk_helper.AbortPipe(priv->redirector_handle, transfer->endpoint)) { + usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } } return LIBUSB_SUCCESS; @@ -781,16 +740,16 @@ static int usbdk_cancel_transfer(struct usbi_transfer *itransfer) } } -static int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size) +static int usbdk_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size) { itransfer->transferred += io_size; return LIBUSB_TRANSFER_COMPLETED; } -static struct winfd *windows_get_fd(struct usbi_transfer *transfer) +static int usbdk_get_transfer_fd(struct usbi_transfer *itransfer) { - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer); - return &transfer_priv->pollable_fd; + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + return transfer_priv->pollable_fd.fd; } static DWORD usbdk_translate_usbd_status(USBD_STATUS UsbdStatus) @@ -799,30 +758,28 @@ static DWORD usbdk_translate_usbd_status(USBD_STATUS UsbdStatus) return NO_ERROR; switch (UsbdStatus) { - case USBD_STATUS_STALL_PID: - case USBD_STATUS_ENDPOINT_HALTED: - case USBD_STATUS_BAD_START_FRAME: - return ERROR_GEN_FAILURE; case USBD_STATUS_TIMEOUT: return ERROR_SEM_TIMEOUT; case USBD_STATUS_CANCELED: return ERROR_OPERATION_ABORTED; default: - return ERROR_FUNCTION_FAILED; + return ERROR_GEN_FAILURE; } } -static void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size) +static void usbdk_get_overlapped_result(struct usbi_transfer *itransfer, DWORD *io_result, DWORD *io_size) { - if (HasOverlappedIoCompletedSync(pollable_fd->overlapped) // Handle async requests that completed synchronously first - || GetOverlappedResult(pollable_fd->handle, pollable_fd->overlapped, io_size, false)) { // Regular async overlapped - struct libusb_transfer *ltransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer); - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct winfd *pollable_fd = &transfer_priv->pollable_fd; - if (ltransfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { - int i; + if (HasOverlappedIoCompletedSync(pollable_fd->overlapped) // Handle async requests that completed synchronously first + || GetOverlappedResult(transfer_priv->system_handle, pollable_fd->overlapped, io_size, FALSE)) { // Regular async overlapped + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { + ULONG64 i; for (i = 0; i < transfer_priv->request.IsochronousPacketsArraySize; i++) { - struct libusb_iso_packet_descriptor *lib_desc = <ransfer->iso_packet_desc[i]; + struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i]; switch (transfer_priv->IsochronousResultsArray[i].TransferResult) { case STATUS_SUCCESS: @@ -839,78 +796,35 @@ static void windows_get_overlapped_result(struct usbi_transfer *transfer, struct } } - *io_size = (DWORD) transfer_priv->request.Result.GenResult.BytesTransferred; - *io_result = usbdk_translate_usbd_status((USBD_STATUS) transfer_priv->request.Result.GenResult.UsbdStatus); - } - else { + *io_size = (DWORD)transfer_priv->request.Result.GenResult.BytesTransferred; + *io_result = usbdk_translate_usbd_status((USBD_STATUS)transfer_priv->request.Result.GenResult.UsbdStatus); + } else { *io_result = GetLastError(); } } -static int usbdk_clock_gettime(int clk_id, struct timespec *tp) -{ - return windows_clock_gettime(clk_id, tp); -} - -const struct usbi_os_backend usbdk_backend = { - "Windows", - USBI_CAP_HAS_HID_ACCESS, +const struct windows_backend usbdk_backend = { usbdk_init, usbdk_exit, - usbdk_get_device_list, - NULL, usbdk_open, usbdk_close, - usbdk_get_device_descriptor, usbdk_get_active_config_descriptor, usbdk_get_config_descriptor, - NULL, - + usbdk_get_config_descriptor_by_value, usbdk_get_configuration, usbdk_set_configuration, usbdk_claim_interface, usbdk_release_interface, - usbdk_set_interface_altsetting, usbdk_clear_halt, usbdk_reset_device, - - NULL, - NULL, - - NULL, // dev_mem_alloc() - NULL, // dev_mem_free() - - usbdk_kernel_driver_active, - usbdk_detach_kernel_driver, - usbdk_attach_kernel_driver, - usbdk_destroy_device, - usbdk_submit_transfer, usbdk_cancel_transfer, - windows_clear_transfer_priv, - - windows_handle_events, - NULL, - - usbdk_clock_gettime, -#if defined(USBI_TIMERFD_AVAILABLE) - NULL, -#endif - sizeof(struct usbdk_device_priv), - 0, - sizeof(struct usbdk_transfer_priv), + usbdk_clear_transfer_priv, + usbdk_copy_transfer_data, + usbdk_get_transfer_fd, + usbdk_get_overlapped_result, }; - -static void backend_init(void) -{ - win_backend backend; - backend.clear_transfer_priv = windows_clear_transfer_priv; - backend.copy_transfer_data = windows_copy_transfer_data; - backend.get_fd = windows_get_fd; - backend.get_overlapped_result = windows_get_overlapped_result; - win_nt_init(&backend); -} diff --git a/Externals/libusb/libusb/os/windows_usbdk.h b/Externals/libusb/libusb/os/windows_usbdk.h index 04a9787f2d..77660ae97f 100644 --- a/Externals/libusb/libusb/os/windows_usbdk.h +++ b/Externals/libusb/libusb/os/windows_usbdk.h @@ -23,56 +23,13 @@ #pragma once -typedef struct tag_USB_DK_DEVICE_ID { - WCHAR DeviceID[MAX_DEVICE_ID_LEN]; - WCHAR InstanceID[MAX_DEVICE_ID_LEN]; -} USB_DK_DEVICE_ID, *PUSB_DK_DEVICE_ID; +#include "windows_nt_common.h" -static inline void UsbDkFillIDStruct(USB_DK_DEVICE_ID *ID, PCWCHAR DeviceID, PCWCHAR InstanceID) -{ - wcsncpy_s(ID->DeviceID, DeviceID, MAX_DEVICE_ID_LEN); - wcsncpy_s(ID->InstanceID, InstanceID, MAX_DEVICE_ID_LEN); -} - -typedef struct tag_USB_DK_DEVICE_INFO { - USB_DK_DEVICE_ID ID; - ULONG64 FilterID; - ULONG64 Port; - ULONG64 Speed; - USB_DEVICE_DESCRIPTOR DeviceDescriptor; -} USB_DK_DEVICE_INFO, *PUSB_DK_DEVICE_INFO; - -typedef struct tag_USB_DK_CONFIG_DESCRIPTOR_REQUEST { +typedef struct USB_DK_CONFIG_DESCRIPTOR_REQUEST { USB_DK_DEVICE_ID ID; ULONG64 Index; } USB_DK_CONFIG_DESCRIPTOR_REQUEST, *PUSB_DK_CONFIG_DESCRIPTOR_REQUEST; -typedef struct tag_USB_DK_ISO_TRANSFER_RESULT { - ULONG64 ActualLength; - ULONG64 TransferResult; -} USB_DK_ISO_TRANSFER_RESULT, *PUSB_DK_ISO_TRANSFER_RESULT; - -typedef struct tag_USB_DK_GEN_TRANSFER_RESULT { - ULONG64 BytesTransferred; - ULONG64 UsbdStatus; // USBD_STATUS code -} USB_DK_GEN_TRANSFER_RESULT, *PUSB_DK_GEN_TRANSFER_RESULT; - -typedef struct tag_USB_DK_TRANSFER_RESULT { - USB_DK_GEN_TRANSFER_RESULT GenResult; - PVOID64 IsochronousResultsArray; // array of USB_DK_ISO_TRANSFER_RESULT -} USB_DK_TRANSFER_RESULT, *PUSB_DK_TRANSFER_RESULT; - -typedef struct tag_USB_DK_TRANSFER_REQUEST { - ULONG64 EndpointAddress; - PVOID64 Buffer; - ULONG64 BufferLength; - ULONG64 TransferType; - ULONG64 IsochronousPacketsArraySize; - PVOID64 IsochronousPacketsArray; - - USB_DK_TRANSFER_RESULT Result; -} USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST; - typedef enum { TransferFailure = 0, TransferSuccess, @@ -90,7 +47,7 @@ typedef enum { typedef enum { ControlTransferType, BulkTransferType, - IntertuptTransferType, + InterruptTransferType, IsochronousTransferType } USB_DK_TRANSFER_TYPE; diff --git a/Externals/libusb/libusb/os/windows_winusb.c b/Externals/libusb/libusb/os/windows_winusb.c index 99e866e159..19b605a6d5 100644 --- a/Externals/libusb/libusb/os/windows_winusb.c +++ b/Externals/libusb/libusb/os/windows_winusb.c @@ -1,6 +1,7 @@ /* * windows backend for libusb 1.0 * Copyright © 2009-2012 Pete Batard + * Copyright © 2016-2018 Chris Dickens * 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 @@ -36,10 +37,11 @@ #include #include "libusbi.h" -#include "poll_windows.h" +#include "windows_common.h" +#include "windows_nt_common.h" #include "windows_winusb.h" -#define HANDLE_VALID(h) (((h) != 0) && ((h) != INVALID_HANDLE_VALUE)) +#define HANDLE_VALID(h) (((h) != NULL) && ((h) != INVALID_HANDLE_VALUE)) // The 2 macros below are used in conjunction with safe loops. #define LOOP_CHECK(fcall) \ @@ -55,8 +57,8 @@ } // WinUSB-like API prototypes -static int winusbx_init(int sub_api, struct libusb_context *ctx); -static int winusbx_exit(int sub_api); +static int winusbx_init(struct libusb_context *ctx); +static void winusbx_exit(void); static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle); static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle); static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface); @@ -64,6 +66,7 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer); static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting); +static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer); static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer); static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint); static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer); @@ -71,8 +74,8 @@ static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer); static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle); static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size); // HID API prototypes -static int hid_init(int sub_api, struct libusb_context *ctx); -static int hid_exit(int sub_api); +static int hid_init(struct libusb_context *ctx); +static void hid_exit(void); static int hid_open(int sub_api, struct libusb_device_handle *dev_handle); static void hid_close(int sub_api, struct libusb_device_handle *dev_handle); static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); @@ -85,8 +88,6 @@ static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer); static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle); static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size); // Composite API prototypes -static int composite_init(int sub_api, struct libusb_context *ctx); -static int composite_exit(int sub_api); static int composite_open(int sub_api, struct libusb_device_handle *dev_handle); static void composite_close(int sub_api, struct libusb_device_handle *dev_handle); static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); @@ -101,26 +102,18 @@ static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer) static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle); static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size); -static void backend_init(void); - -// Global variables -int windows_version = WINDOWS_UNDEFINED; -static char windows_version_str[128] = "Windows Undefined"; -// Concurrency -static int concurrent_usage = -1; static usbi_mutex_t autoclaim_lock; + // API globals +static HMODULE WinUSBX_handle = NULL; +static struct winusb_interface WinUSBX[SUB_API_MAX]; #define CHECK_WINUSBX_AVAILABLE(sub_api) \ do { \ if (sub_api == SUB_API_NOTSET) \ sub_api = priv->sub_api; \ if (!WinUSBX[sub_api].initialized) \ return LIBUSB_ERROR_ACCESS; \ - } while(0) - -static HMODULE WinUSBX_handle = NULL; -static struct winusb_interface WinUSBX[SUB_API_MAX]; -static const char *sub_api_name[SUB_API_MAX] = WINUSBX_DRV_NAMES; + } while (0) static bool api_hid_available = false; #define CHECK_HID_AVAILABLE \ @@ -129,21 +122,13 @@ static bool api_hid_available = false; return LIBUSB_ERROR_ACCESS; \ } while (0) -static inline BOOLEAN guid_eq(const GUID *guid1, const GUID *guid2) -{ - if ((guid1 != NULL) && (guid2 != NULL)) - return (memcmp(guid1, guid2, sizeof(GUID)) == 0); - - return false; -} - #if defined(ENABLE_LOGGING) -static char *guid_to_string(const GUID *guid) +static const char *guid_to_string(const GUID *guid) { static char guid_string[MAX_GUID_STRING_LENGTH]; if (guid == NULL) - return NULL; + return ""; sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", (unsigned int)guid->Data1, guid->Data2, guid->Data3, @@ -160,36 +145,34 @@ static char *guid_to_string(const GUID *guid) */ static char *sanitize_path(const char *path) { - const char root_prefix[] = "\\\\.\\"; - size_t j, size, root_size; - char *ret_path = NULL; + const char root_prefix[] = {'\\', '\\', '.', '\\'}; + size_t j, size; + char *ret_path; size_t add_root = 0; if (path == NULL) return NULL; - size = safe_strlen(path) + 1; - root_size = sizeof(root_prefix) - 1; + size = strlen(path) + 1; // Microsoft indiscriminately uses '\\?\', '\\.\', '##?#" or "##.#" for root prefixes. if (!((size > 3) && (((path[0] == '\\') && (path[1] == '\\') && (path[3] == '\\')) || ((path[0] == '#') && (path[1] == '#') && (path[3] == '#'))))) { - add_root = root_size; + add_root = sizeof(root_prefix); size += add_root; } - ret_path = calloc(1, size); + ret_path = malloc(size); if (ret_path == NULL) return NULL; - safe_strcpy(&ret_path[add_root], size-add_root, path); + strcpy(&ret_path[add_root], path); // Ensure consistency with root prefix - for (j = 0; j < root_size; j++) - ret_path[j] = root_prefix[j]; + memcpy(ret_path, root_prefix, sizeof(root_prefix)); // Same goes for '\' and '#' after the root prefix. Ensure '#' is used - for (j = root_size; j < size; j++) { + for (j = sizeof(root_prefix); j < size; j++) { ret_path[j] = (char)toupper((int)ret_path[j]); // Fix case too if (ret_path[j] == '\\') ret_path[j] = '#'; @@ -199,45 +182,40 @@ static char *sanitize_path(const char *path) } /* - * Cfgmgr32, OLE32 and SetupAPI DLL functions + * Cfgmgr32, AdvAPI32, OLE32 and SetupAPI DLL functions */ -static int init_dlls(void) +static BOOL init_dlls(void) { DLL_GET_HANDLE(Cfgmgr32); DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Parent, TRUE); DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Child, TRUE); - DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Sibling, TRUE); - DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Device_IDA, TRUE); // Prefixed to avoid conflict with header files DLL_GET_HANDLE(AdvAPI32); DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExW, TRUE); DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegCloseKey, TRUE); - DLL_GET_HANDLE(Kernel32); - DLL_LOAD_FUNC_PREFIXED(Kernel32, p, IsWow64Process, FALSE); - DLL_GET_HANDLE(OLE32); - DLL_LOAD_FUNC_PREFIXED(OLE32, p, CLSIDFromString, TRUE); + DLL_LOAD_FUNC_PREFIXED(OLE32, p, IIDFromString, TRUE); DLL_GET_HANDLE(SetupAPI); DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetClassDevsA, TRUE); DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInfo, TRUE); DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInterfaces, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInstanceIdA, TRUE); DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInterfaceDetailA, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceRegistryPropertyA, TRUE); DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiDestroyDeviceInfoList, TRUE); DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDevRegKey, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceRegistryPropertyA, TRUE); DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDeviceInterfaceRegKey, TRUE); - return LIBUSB_SUCCESS; + return TRUE; } static void exit_dlls(void) { DLL_FREE_HANDLE(Cfgmgr32); DLL_FREE_HANDLE(AdvAPI32); - DLL_FREE_HANDLE(Kernel32); DLL_FREE_HANDLE(OLE32); DLL_FREE_HANDLE(SetupAPI); } @@ -248,7 +226,7 @@ static void exit_dlls(void) * Parameters: * dev_info: a pointer to a dev_info list * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed) - * usb_class: the generic USB class for which to retrieve interface details + * enumerator: the generic USB class for which to retrieve interface details * index: zero based index of the interface in the device info list * * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA @@ -256,19 +234,22 @@ static void exit_dlls(void) * incremented index starting at zero) until all interfaces have been returned. */ static bool get_devinfo_data(struct libusb_context *ctx, - HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const char *usb_class, unsigned _index) + HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const char *enumerator, unsigned _index) { - if (_index <= 0) { - *dev_info = pSetupDiGetClassDevsA(NULL, usb_class, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES); - if (*dev_info == INVALID_HANDLE_VALUE) + if (_index == 0) { + *dev_info = pSetupDiGetClassDevsA(NULL, enumerator, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES); + if (*dev_info == INVALID_HANDLE_VALUE) { + usbi_err(ctx, "could not obtain device info set for PnP enumerator '%s': %s", + enumerator, windows_error_str(0)); return false; + } } dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) { if (GetLastError() != ERROR_NO_MORE_ITEMS) - usbi_err(ctx, "Could not obtain device info data for index %u: %s", - _index, windows_error_str(0)); + usbi_err(ctx, "could not obtain device info data for PnP enumerator '%s' index %u: %s", + enumerator, _index, windows_error_str(0)); pSetupDiDestroyDeviceInfoList(*dev_info); *dev_info = INVALID_HANDLE_VALUE; @@ -290,72 +271,81 @@ static bool get_devinfo_data(struct libusb_context *ctx, * structure returned and call this function repeatedly using the same guid (with an * incremented index starting at zero) until all interfaces have been returned. */ -static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details(struct libusb_context *ctx, - HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID *guid, unsigned _index) +static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info, + PSP_DEVINFO_DATA dev_info_data, LPCGUID guid, DWORD *_index, char **dev_interface_path) { SP_DEVICE_INTERFACE_DATA dev_interface_data; - SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL; + PSP_DEVICE_INTERFACE_DETAIL_DATA_A dev_interface_details; DWORD size; - if (_index <= 0) - *dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); - - if (dev_info_data != NULL) { - dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); - if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) - usbi_err(ctx, "Could not obtain device info data for index %u: %s", - _index, windows_error_str(0)); - - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return NULL; - } - } - + dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, guid, _index, &dev_interface_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) - usbi_err(ctx, "Could not obtain interface data for index %u: %s", - _index, windows_error_str(0)); + for (;;) { + if (!pSetupDiEnumDeviceInfo(dev_info, *_index, dev_info_data)) { + if (GetLastError() != ERROR_NO_MORE_ITEMS) { + usbi_err(ctx, "Could not obtain device info data for %s index %u: %s", + guid_to_string(guid), *_index, windows_error_str(0)); + return LIBUSB_ERROR_OTHER; + } - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return NULL; + // No more devices + return LIBUSB_SUCCESS; + } + + // Always advance the index for the next iteration + (*_index)++; + + if (pSetupDiEnumDeviceInterfaces(dev_info, dev_info_data, guid, 0, &dev_interface_data)) + break; + + if (GetLastError() != ERROR_NO_MORE_ITEMS) { + usbi_err(ctx, "Could not obtain interface data for %s devInst %X: %s", + guid_to_string(guid), dev_info_data->DevInst, windows_error_str(0)); + return LIBUSB_ERROR_OTHER; + } + + // Device does not have an interface matching this GUID, skip } // Read interface data (dummy + actual) to access the device path - if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, NULL, 0, &size, NULL)) { + if (!pSetupDiGetDeviceInterfaceDetailA(dev_info, &dev_interface_data, NULL, 0, &size, NULL)) { // The dummy call should fail with ERROR_INSUFFICIENT_BUFFER if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - usbi_err(ctx, "could not access interface data (dummy) for index %u: %s", - _index, windows_error_str(0)); - goto err_exit; + usbi_err(ctx, "could not access interface data (dummy) for %s devInst %X: %s", + guid_to_string(guid), dev_info_data->DevInst, windows_error_str(0)); + return LIBUSB_ERROR_OTHER; } } else { - usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong."); - goto err_exit; + usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong"); + return LIBUSB_ERROR_OTHER; } - dev_interface_details = calloc(1, size); + dev_interface_details = malloc(size); if (dev_interface_details == NULL) { - usbi_err(ctx, "could not allocate interface data for index %u.", _index); - goto err_exit; + usbi_err(ctx, "could not allocate interface data for %s devInst %X", + guid_to_string(guid), dev_info_data->DevInst); + return LIBUSB_ERROR_NO_MEM; } dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); - if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, - dev_interface_details, size, &size, NULL)) { - usbi_err(ctx, "could not access interface data (actual) for index %u: %s", - _index, windows_error_str(0)); + if (!pSetupDiGetDeviceInterfaceDetailA(dev_info, &dev_interface_data, + dev_interface_details, size, NULL, NULL)) { + usbi_err(ctx, "could not access interface data (actual) for %s devInst %X: %s", + guid_to_string(guid), dev_info_data->DevInst, windows_error_str(0)); + free(dev_interface_details); + return LIBUSB_ERROR_OTHER; } - return dev_interface_details; + *dev_interface_path = sanitize_path(dev_interface_details->DevicePath); + free(dev_interface_details); -err_exit: - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return NULL; + if (*dev_interface_path == NULL) { + usbi_err(ctx, "could not allocate interface path for %s devInst %X", + guid_to_string(guid), dev_info_data->DevInst); + return LIBUSB_ERROR_NO_MEM; + } + + return LIBUSB_SUCCESS; } /* For libusb0 filter */ @@ -363,10 +353,10 @@ static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details_filter(struct li HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID *guid, unsigned _index, char *filter_path) { SP_DEVICE_INTERFACE_DATA dev_interface_data; - SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL; + SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details; DWORD size; - if (_index <= 0) + if (_index == 0) *dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); if (dev_info_data != NULL) { @@ -432,7 +422,7 @@ static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details_filter(struct li if (libusb0_symboliclink_index < 256) { // libusb0.sys is connected to this device instance. // If the the device interface guid is {F9F3FF14-AE21-48A0-8A25-8011A7A931D9} then it's a filter. - safe_sprintf(filter_path, sizeof("\\\\.\\libusb0-0000"), "\\\\.\\libusb0-%04u", (unsigned int)libusb0_symboliclink_index); + sprintf(filter_path, "\\\\.\\libusb0-%04u", (unsigned int)libusb0_symboliclink_index); usbi_dbg("assigned libusb0 symbolic link %s", filter_path); } else { // libusb0.sys was connected to this device instance at one time; but not anymore. @@ -451,37 +441,25 @@ err_exit: } /* - * Returns the session ID of a device's nth level ancestor - * If there's no device at the nth level, return 0 + * Returns the first known ancestor of a device */ -static unsigned long get_ancestor_session_id(DWORD devinst, unsigned level) +static struct libusb_device *get_ancestor(struct libusb_context *ctx, + DEVINST devinst, PDEVINST _parent_devinst) { - DWORD parent_devinst; - unsigned long session_id = 0; - char *sanitized_path = NULL; - char path[MAX_PATH_LENGTH]; - unsigned i; + struct libusb_device *dev = NULL; + DEVINST parent_devinst; - if (level < 1) - return 0; - - for (i = 0; i < level; i++) { + while (dev == NULL) { if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS) - return 0; + break; devinst = parent_devinst; + dev = usbi_get_device_by_session_id(ctx, (unsigned long)devinst); } - if (CM_Get_Device_IDA(devinst, path, MAX_PATH_LENGTH, 0) != CR_SUCCESS) - return 0; + if ((dev != NULL) && (_parent_devinst != NULL)) + *_parent_devinst = devinst; - // TODO: (post hotplug): try without sanitizing - sanitized_path = sanitize_path(path); - if (sanitized_path == NULL) - return 0; - - session_id = htab_hash(sanitized_path); - safe_free(sanitized_path); - return session_id; + return dev; } /* @@ -516,7 +494,7 @@ static int get_interface_by_endpoint(struct libusb_config_descriptor *conf_desc, static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int iface, int altsetting) { int i, r; - struct windows_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); struct libusb_config_descriptor *conf_desc; const struct libusb_interface_descriptor *if_desc; struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); @@ -533,6 +511,7 @@ static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int if (if_desc->bNumEndpoints == 0) { usbi_dbg("no endpoints found for interface %d", iface); libusb_free_config_descriptor(conf_desc); + priv->usb_interface[iface].current_altsetting = altsetting; return LIBUSB_SUCCESS; } @@ -550,7 +529,13 @@ static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int libusb_free_config_descriptor(conf_desc); // Extra init may be required to configure endpoints - return priv->apib->configure_endpoints(SUB_API_NOTSET, dev_handle, iface); + if (priv->apib->configure_endpoints) + r = priv->apib->configure_endpoints(SUB_API_NOTSET, dev_handle, iface); + + if (r == LIBUSB_SUCCESS) + priv->usb_interface[iface].current_altsetting = altsetting; + + return r; } // Lookup for a match in the list of API driver names @@ -560,7 +545,7 @@ static int get_sub_api(char *driver, int api) int i; const char sep_str[2] = {LIST_SEPARATOR, 0}; char *tok, *tmp_str; - size_t len = safe_strlen(driver); + size_t len = strlen(driver); if (len == 0) return SUB_API_NOTSET; @@ -572,7 +557,7 @@ static int get_sub_api(char *driver, int api) tok = strtok(tmp_str, sep_str); while (tok != NULL) { for (i = 0; i < usb_api_backend[api].nb_driver_names; i++) { - if (safe_stricmp(tok, usb_api_backend[api].driver_name_list[i]) == 0) { + if (_stricmp(tok, usb_api_backend[api].driver_name_list[i]) == 0) { free(tmp_str); return i; } @@ -590,13 +575,13 @@ static int get_sub_api(char *driver, int api) static int auto_claim(struct libusb_transfer *transfer, int *interface_number, int api_type) { struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv( + struct winusb_device_handle_priv *handle_priv = _device_handle_priv( transfer->dev_handle); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); int current_interface = *interface_number; int r = LIBUSB_SUCCESS; - switch(api_type) { + switch (api_type) { case USB_API_WINUSBX: case USB_API_HID: break; @@ -635,10 +620,10 @@ static int auto_claim(struct libusb_transfer *transfer, int *interface_number, i static void auto_release(struct usbi_transfer *itransfer) { - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); libusb_device_handle *dev_handle = transfer->dev_handle; - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); int r; usbi_mutex_lock(&autoclaim_lock); @@ -656,461 +641,285 @@ static void auto_release(struct usbi_transfer *itransfer) usbi_mutex_unlock(&autoclaim_lock); } -/* Windows version dtection */ -static BOOL is_x64(void) -{ - BOOL ret = FALSE; - - // Detect if we're running a 32 or 64 bit system - if (sizeof(uintptr_t) < 8) { - if (pIsWow64Process != NULL) - pIsWow64Process(GetCurrentProcess(), &ret); - } else { - ret = TRUE; - } - - return ret; -} - -static void get_windows_version(void) -{ - OSVERSIONINFOEXA vi, vi2; - const char *w = 0; - const char *w64 = "32 bit"; - char *vptr; - size_t vlen; - unsigned major, minor; - ULONGLONG major_equal, minor_equal; - BOOL ws; - - memset(&vi, 0, sizeof(vi)); - vi.dwOSVersionInfoSize = sizeof(vi); - if (!GetVersionExA((OSVERSIONINFOA *)&vi)) { - memset(&vi, 0, sizeof(vi)); - vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); - if (!GetVersionExA((OSVERSIONINFOA *)&vi)) - return; - } - - if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) { - if (vi.dwMajorVersion > 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion >= 2)) { - // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version - // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx - - major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); - for (major = vi.dwMajorVersion; major <= 9; major++) { - memset(&vi2, 0, sizeof(vi2)); - vi2.dwOSVersionInfoSize = sizeof(vi2); - vi2.dwMajorVersion = major; - if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal)) - continue; - - if (vi.dwMajorVersion < major) { - vi.dwMajorVersion = major; - vi.dwMinorVersion = 0; - } - - minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL); - for (minor = vi.dwMinorVersion; minor <= 9; minor++) { - memset(&vi2, 0, sizeof(vi2)); - vi2.dwOSVersionInfoSize = sizeof(vi2); - vi2.dwMinorVersion = minor; - if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal)) - continue; - - vi.dwMinorVersion = minor; - break; - } - - break; - } - } - - if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) { - ws = (vi.wProductType <= VER_NT_WORKSTATION); - windows_version = vi.dwMajorVersion << 4 | vi.dwMinorVersion; - switch (windows_version) { - case 0x50: w = "2000"; break; - case 0x51: w = "XP"; break; - case 0x52: w = ("2003"); break; - case 0x60: w = (ws ? "Vista" : "2008"); break; - case 0x61: w = (ws ? "7" : "2008_R2"); break; - case 0x62: w = (ws ? "8" : "2012"); break; - case 0x63: w = (ws ? "8.1": "2012_R2"); break; - case 0x64: w = (ws ? "10": "2015"); break; - default: - if (windows_version < 0x50) - windows_version = WINDOWS_UNSUPPORTED; - else - w = "11 or later"; - break; - } - } - } - - if (is_x64()) - w64 = "64-bit"; - - vptr = &windows_version_str[sizeof("Windows ") - 1]; - vlen = sizeof(windows_version_str) - sizeof("Windows ") - 1; - if (!w) - safe_sprintf(vptr, vlen, "%s %u.%u %s", (vi.dwPlatformId == VER_PLATFORM_WIN32_NT ? "NT" : "??"), - (unsigned int)vi.dwMajorVersion, (unsigned int)vi.dwMinorVersion, w64); - else if (vi.wServicePackMinor) - safe_sprintf(vptr, vlen, "%s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, w64); - else if (vi.wServicePackMajor) - safe_sprintf(vptr, vlen, "%s SP%u %s", w, vi.wServicePackMajor, w64); - else - safe_sprintf(vptr, vlen, "%s %s", w, w64); -} - /* * init: libusb backend init function - * - * This function enumerates the HCDs (Host Controller Drivers) and populates our private HCD list - * In our implementation, we equate Windows' "HCD" to libusb's "bus". Note that bus is zero indexed. - * HCDs are not expected to change after init (might not hold true for hot pluggable USB PCI card?) */ -static int windows_init(struct libusb_context *ctx) +static int winusb_init(struct libusb_context *ctx) { - int i, r = LIBUSB_ERROR_OTHER; - HANDLE semaphore; - char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' + int i; - sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); - semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name); - if (semaphore == NULL) { - usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_MEM; + // We need a lock for proper auto-release + usbi_mutex_init(&autoclaim_lock); + + // Load DLL imports + if (!init_dlls()) { + usbi_err(ctx, "could not resolve DLL functions"); + return LIBUSB_ERROR_OTHER; } - // A successful wait brings our semaphore count to 0 (unsignaled) - // => any concurent wait stalls until the semaphore's release - if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { - usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0)); - CloseHandle(semaphore); - return LIBUSB_ERROR_NO_MEM; - } - - // NB: concurrent usage supposes that init calls are equally balanced with - // exit calls. If init is called more than exit, we will not exit properly - if (++concurrent_usage == 0) { // First init? - get_windows_version(); - usbi_dbg(windows_version_str); - - if (windows_version == WINDOWS_UNSUPPORTED) { - usbi_err(ctx, "This version of Windows is NOT supported"); - r = LIBUSB_ERROR_NOT_SUPPORTED; - goto init_exit; - } - - backend_init(); - - // We need a lock for proper auto-release - usbi_mutex_init(&autoclaim_lock); - - // Initialize pollable file descriptors - init_polling(); - - // Load DLL imports - if (init_dlls() != LIBUSB_SUCCESS) { - usbi_err(ctx, "could not resolve DLL functions"); - goto init_exit; - } - - // Initialize the low level APIs (we don't care about errors at this stage) - for (i = 0; i < USB_API_MAX; i++) - usb_api_backend[i].init(SUB_API_NOTSET, ctx); - - r = windows_common_init(ctx); - if (r) - goto init_exit; - } - // At this stage, either we went through full init successfully, or didn't need to - r = LIBUSB_SUCCESS; - -init_exit: // Holds semaphore here. - if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? - for (i = 0; i < USB_API_MAX; i++) - usb_api_backend[i].exit(SUB_API_NOTSET); - exit_dlls(); - exit_polling(); - windows_common_exit(); - usbi_mutex_destroy(&autoclaim_lock); - } - - if (r != LIBUSB_SUCCESS) - --concurrent_usage; // Not expected to call libusb_exit if we failed. - - ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 - CloseHandle(semaphore); - return r; -} - -/* - * HCD (root) hubs need to have their device descriptor manually populated - * - * Note that, like Microsoft does in the device manager, we populate the - * Vendor and Device ID for HCD hubs with the ones from the PCI HCD device. - */ -static int force_hcd_device_descriptor(struct libusb_device *dev) -{ - struct windows_device_priv *parent_priv, *priv = _device_priv(dev); - struct libusb_context *ctx = DEVICE_CTX(dev); - int vid, pid; - - dev->num_configurations = 1; - priv->dev_descriptor.bLength = sizeof(USB_DEVICE_DESCRIPTOR); - priv->dev_descriptor.bDescriptorType = USB_DEVICE_DESCRIPTOR_TYPE; - priv->dev_descriptor.bNumConfigurations = 1; - priv->active_config = 1; - - if (dev->parent_dev == NULL) { - usbi_err(ctx, "program assertion failed - HCD hub has no parent"); - return LIBUSB_ERROR_NO_DEVICE; - } - - parent_priv = _device_priv(dev->parent_dev); - if (sscanf(parent_priv->path, "\\\\.\\PCI#VEN_%04x&DEV_%04x%*s", &vid, &pid) == 2) { - priv->dev_descriptor.idVendor = (uint16_t)vid; - priv->dev_descriptor.idProduct = (uint16_t)pid; - } else { - usbi_warn(ctx, "could not infer VID/PID of HCD hub from '%s'", parent_priv->path); - priv->dev_descriptor.idVendor = 0x1d6b; // Linux Foundation root hub - priv->dev_descriptor.idProduct = 1; + // Initialize the low level APIs (we don't care about errors at this stage) + for (i = 0; i < USB_API_MAX; i++) { + if (usb_api_backend[i].init && usb_api_backend[i].init(ctx)) + usbi_warn(ctx, "error initializing %s backend", + usb_api_backend[i].designation); } return LIBUSB_SUCCESS; } +/* +* exit: libusb backend deinitialization function +*/ +static void winusb_exit(struct libusb_context *ctx) +{ + int i; + + for (i = 0; i < USB_API_MAX; i++) { + if (usb_api_backend[i].exit) + usb_api_backend[i].exit(); + } + + exit_dlls(); + usbi_mutex_destroy(&autoclaim_lock); +} + /* * fetch and cache all the config descriptors through I/O */ -static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle, char *device_id) +static void cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle) { - DWORD size, ret_size; struct libusb_context *ctx = DEVICE_CTX(dev); - struct windows_device_priv *priv = _device_priv(dev); - int r; + struct winusb_device_priv *priv = _device_priv(dev); + DWORD size, ret_size; uint8_t i; USB_CONFIGURATION_DESCRIPTOR_SHORT cd_buf_short; // dummy request PUSB_DESCRIPTOR_REQUEST cd_buf_actual = NULL; // actual request - PUSB_CONFIGURATION_DESCRIPTOR cd_data = NULL; + PUSB_CONFIGURATION_DESCRIPTOR cd_data; if (dev->num_configurations == 0) - return LIBUSB_ERROR_INVALID_PARAM; + return; - priv->config_descriptor = calloc(dev->num_configurations, sizeof(unsigned char *)); - if (priv->config_descriptor == NULL) - return LIBUSB_ERROR_NO_MEM; + priv->config_descriptor = calloc(dev->num_configurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR)); + if (priv->config_descriptor == NULL) { + usbi_err(ctx, "could not allocate configuration descriptor array for '%s'", priv->dev_id); + return; + } - for (i = 0; i < dev->num_configurations; i++) - priv->config_descriptor[i] = NULL; - - for (i = 0, r = LIBUSB_SUCCESS; ; i++) { - // safe loop: release all dynamic resources + for (i = 0; i <= dev->num_configurations; i++) { safe_free(cd_buf_actual); - // safe loop: end of loop condition - if ((i >= dev->num_configurations) || (r != LIBUSB_SUCCESS)) + if (i == dev->num_configurations) break; - size = sizeof(USB_CONFIGURATION_DESCRIPTOR_SHORT); + size = sizeof(cd_buf_short); memset(&cd_buf_short, 0, size); - cd_buf_short.req.ConnectionIndex = (ULONG)priv->port; + cd_buf_short.req.ConnectionIndex = (ULONG)dev->port_number; cd_buf_short.req.SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN; - cd_buf_short.req.SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; - cd_buf_short.req.SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | i; + cd_buf_short.req.SetupPacket.bRequest = LIBUSB_REQUEST_GET_DESCRIPTOR; + cd_buf_short.req.SetupPacket.wValue = (LIBUSB_DT_CONFIG << 8) | i; cd_buf_short.req.SetupPacket.wIndex = 0; - cd_buf_short.req.SetupPacket.wLength = (USHORT)(size - sizeof(USB_DESCRIPTOR_REQUEST)); + cd_buf_short.req.SetupPacket.wLength = (USHORT)sizeof(USB_CONFIGURATION_DESCRIPTOR); // Dummy call to get the required data size. Initial failures are reported as info rather // than error as they can occur for non-penalizing situations, such as with some hubs. // coverity[tainted_data_argument] if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, &cd_buf_short, size, &cd_buf_short, size, &ret_size, NULL)) { - usbi_info(ctx, "could not access configuration descriptor (dummy) for '%s': %s", device_id, windows_error_str(0)); - LOOP_BREAK(LIBUSB_ERROR_IO); + usbi_info(ctx, "could not access configuration descriptor %u (dummy) for '%s': %s", i, priv->dev_id, windows_error_str(0)); + continue; } - if ((ret_size != size) || (cd_buf_short.data.wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))) { - usbi_info(ctx, "unexpected configuration descriptor size (dummy) for '%s'.", device_id); - LOOP_BREAK(LIBUSB_ERROR_IO); + if ((ret_size != size) || (cd_buf_short.desc.wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))) { + usbi_info(ctx, "unexpected configuration descriptor %u size (dummy) for '%s'", i, priv->dev_id); + continue; } - size = sizeof(USB_DESCRIPTOR_REQUEST) + cd_buf_short.data.wTotalLength; - cd_buf_actual = calloc(1, size); + size = sizeof(USB_DESCRIPTOR_REQUEST) + cd_buf_short.desc.wTotalLength; + cd_buf_actual = malloc(size); if (cd_buf_actual == NULL) { - usbi_err(ctx, "could not allocate configuration descriptor buffer for '%s'.", device_id); - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + usbi_err(ctx, "could not allocate configuration descriptor %u buffer for '%s'", i, priv->dev_id); + continue; } // Actual call - cd_buf_actual->ConnectionIndex = (ULONG)priv->port; + cd_buf_actual->ConnectionIndex = (ULONG)dev->port_number; cd_buf_actual->SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN; - cd_buf_actual->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; - cd_buf_actual->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | i; + cd_buf_actual->SetupPacket.bRequest = LIBUSB_REQUEST_GET_DESCRIPTOR; + cd_buf_actual->SetupPacket.wValue = (LIBUSB_DT_CONFIG << 8) | i; cd_buf_actual->SetupPacket.wIndex = 0; - cd_buf_actual->SetupPacket.wLength = (USHORT)(size - sizeof(USB_DESCRIPTOR_REQUEST)); + cd_buf_actual->SetupPacket.wLength = cd_buf_short.desc.wTotalLength; if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, cd_buf_actual, size, cd_buf_actual, size, &ret_size, NULL)) { - usbi_err(ctx, "could not access configuration descriptor (actual) for '%s': %s", device_id, windows_error_str(0)); - LOOP_BREAK(LIBUSB_ERROR_IO); + usbi_err(ctx, "could not access configuration descriptor %u (actual) for '%s': %s", i, priv->dev_id, windows_error_str(0)); + continue; } cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR *)cd_buf_actual + sizeof(USB_DESCRIPTOR_REQUEST)); - if ((size != ret_size) || (cd_data->wTotalLength != cd_buf_short.data.wTotalLength)) { - usbi_err(ctx, "unexpected configuration descriptor size (actual) for '%s'.", device_id); - LOOP_BREAK(LIBUSB_ERROR_IO); + if ((size != ret_size) || (cd_data->wTotalLength != cd_buf_short.desc.wTotalLength)) { + usbi_err(ctx, "unexpected configuration descriptor %u size (actual) for '%s'", i, priv->dev_id); + continue; } - if (cd_data->bDescriptorType != USB_CONFIGURATION_DESCRIPTOR_TYPE) { - usbi_err(ctx, "not a configuration descriptor for '%s'", device_id); - LOOP_BREAK(LIBUSB_ERROR_IO); + if (cd_data->bDescriptorType != LIBUSB_DT_CONFIG) { + usbi_err(ctx, "descriptor %u not a configuration descriptor for '%s'", i, priv->dev_id); + continue; } - usbi_dbg("cached config descriptor %d (bConfigurationValue=%u, %u bytes)", + usbi_dbg("cached config descriptor %u (bConfigurationValue=%u, %u bytes)", i, cd_data->bConfigurationValue, cd_data->wTotalLength); // Cache the descriptor priv->config_descriptor[i] = malloc(cd_data->wTotalLength); - if (priv->config_descriptor[i] == NULL) - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - memcpy(priv->config_descriptor[i], cd_data, cd_data->wTotalLength); + if (priv->config_descriptor[i] != NULL) { + memcpy(priv->config_descriptor[i], cd_data, cd_data->wTotalLength); + } else { + usbi_err(ctx, "could not allocate configuration descriptor %u buffer for '%s'", i, priv->dev_id); + } } - return LIBUSB_SUCCESS; } /* * Populate a libusb device structure */ static int init_device(struct libusb_device *dev, struct libusb_device *parent_dev, - uint8_t port_number, char *device_id, DWORD devinst) + uint8_t port_number, DEVINST devinst) { - HANDLE handle; - DWORD size; - USB_NODE_CONNECTION_INFORMATION_EX conn_info; - USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2; - struct windows_device_priv *priv, *parent_priv; struct libusb_context *ctx; struct libusb_device *tmp_dev; - unsigned long tmp_id; - unsigned i; + struct winusb_device_priv *priv, *parent_priv; + USB_NODE_CONNECTION_INFORMATION_EX conn_info; + USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2; + HANDLE hub_handle; + DWORD size; + uint8_t bus_number, depth; + int r; + int ginfotimeout; - if ((dev == NULL) || (parent_dev == NULL)) - return LIBUSB_ERROR_NOT_FOUND; - - ctx = DEVICE_CTX(dev); priv = _device_priv(dev); - parent_priv = _device_priv(parent_dev); - if (parent_priv->apib->id != USB_API_HUB) { - usbi_warn(ctx, "parent for device '%s' is not a hub", device_id); - return LIBUSB_ERROR_NOT_FOUND; - } - // It is possible for the parent hub not to have been initialized yet - // If that's the case, lookup the ancestors to set the bus number - if (parent_dev->bus_number == 0) { - for (i = 2; ; i++) { - tmp_id = get_ancestor_session_id(devinst, i); - if (tmp_id == 0) - break; - - tmp_dev = usbi_get_device_by_session_id(ctx, tmp_id); - if (tmp_dev == NULL) - continue; - - if (tmp_dev->bus_number != 0) { - usbi_dbg("got bus number from ancestor #%u", i); - parent_dev->bus_number = tmp_dev->bus_number; - libusb_unref_device(tmp_dev); - break; - } - - libusb_unref_device(tmp_dev); - } - } - - if (parent_dev->bus_number == 0) { - usbi_err(ctx, "program assertion failed: unable to find ancestor bus number for '%s'", device_id); - return LIBUSB_ERROR_NOT_FOUND; - } - - dev->bus_number = parent_dev->bus_number; - priv->port = port_number; - dev->port_number = port_number; - priv->depth = parent_priv->depth + 1; - dev->parent_dev = parent_dev; - - // If the device address is already set, we can stop here - if (dev->device_address != 0) + // If the device is already initialized, we can stop here + if (priv->initialized) 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); - if (handle == INVALID_HANDLE_VALUE) { + if (parent_dev != NULL) { // Not a HCD root hub + ctx = DEVICE_CTX(dev); + parent_priv = _device_priv(parent_dev); + if (parent_priv->apib->id != USB_API_HUB) { + usbi_warn(ctx, "parent for device '%s' is not a hub", priv->dev_id); + return LIBUSB_ERROR_NOT_FOUND; + } + + // Calculate depth and fetch bus number + bus_number = parent_dev->bus_number; + if (bus_number == 0) { + tmp_dev = get_ancestor(ctx, devinst, &devinst); + if (tmp_dev != parent_dev) { + usbi_err(ctx, "program assertion failed - first ancestor is not parent"); + return LIBUSB_ERROR_NOT_FOUND; + } + libusb_unref_device(tmp_dev); + + for (depth = 1; bus_number == 0; depth++) { + tmp_dev = get_ancestor(ctx, devinst, &devinst); + if (tmp_dev->bus_number != 0) { + bus_number = tmp_dev->bus_number; + depth += _device_priv(tmp_dev)->depth; + } + libusb_unref_device(tmp_dev); + } + } else { + depth = parent_priv->depth + 1; + } + + if (bus_number == 0) { + usbi_err(ctx, "program assertion failed - bus number not found for '%s'", priv->dev_id); + return LIBUSB_ERROR_NOT_FOUND; + } + + dev->bus_number = bus_number; + dev->port_number = port_number; + dev->parent_dev = parent_dev; + priv->depth = depth; + + hub_handle = CreateFileA(parent_priv->path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + 0, NULL); + if (hub_handle == INVALID_HANDLE_VALUE) { usbi_warn(ctx, "could not open hub %s: %s", parent_priv->path, windows_error_str(0)); return LIBUSB_ERROR_ACCESS; } - size = sizeof(conn_info); + memset(&conn_info, 0, sizeof(conn_info)); conn_info.ConnectionIndex = (ULONG)port_number; // coverity[tainted_data_argument] - if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, &conn_info, size, - &conn_info, size, &size, NULL)) { - usbi_warn(ctx, "could not get node connection information for device '%s': %s", - device_id, windows_error_str(0)); - safe_closehandle(handle); - return LIBUSB_ERROR_NO_DEVICE; + ginfotimeout = 20; + do { + if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, &conn_info, sizeof(conn_info), + &conn_info, sizeof(conn_info), &size, NULL)) { + usbi_warn(ctx, "could not get node connection information for device '%s': %s", + priv->dev_id, windows_error_str(0)); + CloseHandle(hub_handle); + return LIBUSB_ERROR_NO_DEVICE; + } + + if (conn_info.ConnectionStatus == NoDeviceConnected) { + usbi_err(ctx, "device '%s' is no longer connected!", priv->dev_id); + CloseHandle(hub_handle); + return LIBUSB_ERROR_NO_DEVICE; + } + + memcpy(&priv->dev_descriptor, &(conn_info.DeviceDescriptor), sizeof(USB_DEVICE_DESCRIPTOR)); + dev->num_configurations = priv->dev_descriptor.bNumConfigurations; + priv->active_config = conn_info.CurrentConfigurationValue; + if (priv->active_config == 0) { + usbi_dbg("0x%x:0x%x found %u configurations (active conf: %u) \n", + priv->dev_descriptor.idVendor, + priv->dev_descriptor.idProduct, + dev->num_configurations, + priv->active_config); + } + if (priv->active_config == 0) + Sleep(50); + } while (priv->active_config == 0 && --ginfotimeout >= 0); + + if (priv->active_config == 0) { + usbi_dbg("after try 0x%x:0x%x found %u configurations (active conf: %u) \n", + priv->dev_descriptor.idVendor, + priv->dev_descriptor.idProduct, + dev->num_configurations, + priv->active_config); + usbi_dbg("Force this device active config to 1 in libusb! \nNOTICE: Should not reach this place!!!!!! \n"); + priv->active_config = 1; } - if (conn_info.ConnectionStatus == NoDeviceConnected) { - usbi_err(ctx, "device '%s' is no longer connected!", device_id); - safe_closehandle(handle); - return LIBUSB_ERROR_NO_DEVICE; - } - - memcpy(&priv->dev_descriptor, &(conn_info.DeviceDescriptor), sizeof(USB_DEVICE_DESCRIPTOR)); - dev->num_configurations = priv->dev_descriptor.bNumConfigurations; - priv->active_config = conn_info.CurrentConfigurationValue; usbi_dbg("found %u configurations (active conf: %u)", dev->num_configurations, priv->active_config); - // If we can't read the config descriptors, just set the number of confs to zero - if (cache_config_descriptors(dev, handle, device_id) != LIBUSB_SUCCESS) { - dev->num_configurations = 0; - priv->dev_descriptor.bNumConfigurations = 0; - } + // Cache as many config descriptors as we can + cache_config_descriptors(dev, hub_handle); // In their great wisdom, Microsoft decided to BREAK the USB speed report between Windows 7 and Windows 8 if (windows_version >= WINDOWS_8) { - memset(&conn_info_v2, 0, sizeof(conn_info_v2)); - size = sizeof(conn_info_v2); conn_info_v2.ConnectionIndex = (ULONG)port_number; - conn_info_v2.Length = size; + conn_info_v2.Length = sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2); conn_info_v2.SupportedUsbProtocols.Usb300 = 1; - if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, - &conn_info_v2, size, &conn_info_v2, size, &size, NULL)) { + if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, + &conn_info_v2, sizeof(conn_info_v2), &conn_info_v2, sizeof(conn_info_v2), &size, NULL)) { usbi_warn(ctx, "could not get node connection information (V2) for device '%s': %s", - device_id, windows_error_str(0)); + priv->dev_id, windows_error_str(0)); } else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedOrHigher) { conn_info.Speed = 3; } } - safe_closehandle(handle); + CloseHandle(hub_handle); if (conn_info.DeviceAddress > UINT8_MAX) - usbi_err(ctx, "program assertion failed: device address overflow"); + usbi_err(ctx, "program assertion failed - device address overflow"); - dev->device_address = (uint8_t)conn_info.DeviceAddress + 1; - if (dev->device_address == 1) - usbi_err(ctx, "program assertion failed: device address collision with root hub"); + dev->device_address = (uint8_t)conn_info.DeviceAddress; switch (conn_info.Speed) { case 0: dev->speed = LIBUSB_SPEED_LOW; break; @@ -1118,22 +927,66 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d case 2: dev->speed = LIBUSB_SPEED_HIGH; break; case 3: dev->speed = LIBUSB_SPEED_SUPER; break; default: - usbi_warn(ctx, "Got unknown device speed %u", conn_info.Speed); + usbi_warn(ctx, "unknown device speed %u", conn_info.Speed); break; } - } else { - dev->device_address = 1; // root hubs are set to use device number 1 - force_hcd_device_descriptor(dev); } - usbi_sanitize_device(dev); + r = usbi_sanitize_device(dev); + if (r) + return r; + + priv->initialized = true; usbi_dbg("(bus: %u, addr: %u, depth: %u, port: %u): '%s'", - dev->bus_number, dev->device_address, priv->depth, priv->port, device_id); + dev->bus_number, dev->device_address, priv->depth, dev->port_number, priv->dev_id); return LIBUSB_SUCCESS; } +static int enumerate_hcd_root_hub(struct libusb_context *ctx, const char *dev_id, + uint8_t bus_number, DEVINST devinst) +{ + struct libusb_device *dev; + struct winusb_device_priv *priv; + unsigned long session_id; + DEVINST child_devinst; + + if (CM_Get_Child(&child_devinst, devinst, 0) != CR_SUCCESS) { + usbi_err(ctx, "could not get child devinst for '%s'", dev_id); + return LIBUSB_ERROR_OTHER; + } + + session_id = (unsigned long)child_devinst; + dev = usbi_get_device_by_session_id(ctx, session_id); + if (dev == NULL) { + usbi_err(ctx, "program assertion failed - HCD '%s' child not found", dev_id); + return LIBUSB_ERROR_NO_DEVICE; + } + + if (dev->bus_number == 0) { + // Only do this once + usbi_dbg("assigning HCD '%s' bus number %u", dev_id, bus_number); + priv = _device_priv(dev); + dev->bus_number = bus_number; + dev->num_configurations = 1; + priv->dev_descriptor.bLength = LIBUSB_DT_DEVICE_SIZE; + priv->dev_descriptor.bDescriptorType = LIBUSB_DT_DEVICE; + priv->dev_descriptor.bDeviceClass = LIBUSB_CLASS_HUB; + priv->dev_descriptor.bNumConfigurations = 1; + priv->active_config = 1; + priv->root_hub = true; + if (sscanf(dev_id, "PCI\\VEN_%04hx&DEV_%04hx%*s", &priv->dev_descriptor.idVendor, &priv->dev_descriptor.idProduct) != 2) { + usbi_warn(ctx, "could not infer VID/PID of HCD root hub from '%s'", dev_id); + priv->dev_descriptor.idVendor = 0x1d6b; // Linux Foundation root hub + priv->dev_descriptor.idProduct = 1; + } + } + + libusb_unref_device(dev); + return LIBUSB_SUCCESS; +} + // Returns the api type, or 0 if not found/unsupported static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, int *api, int *sub_api) @@ -1148,17 +1001,14 @@ static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info, unsigned k, l; int i, j; - *api = USB_API_UNSUPPORTED; - *sub_api = SUB_API_NOTSET; - // Check the service & filter names to know the API we should use for (k = 0; k < 3; k++) { if (pSetupDiGetDeviceRegistryPropertyA(*dev_info, dev_info_data, lookup[k].reg_prop, - ®_type, (BYTE *)lookup[k].list, MAX_KEY_LENGTH, &size)) { + ®_type, (PBYTE)lookup[k].list, MAX_KEY_LENGTH, &size)) { // Turn the REG_SZ SPDRP_SERVICE into REG_MULTI_SZ if (lookup[k].reg_prop == SPDRP_SERVICE) // our buffers are MAX_KEY_LENGTH + 1 so we can overflow if needed - lookup[k].list[safe_strlen(lookup[k].list) + 1] = 0; + lookup[k].list[strlen(lookup[k].list) + 1] = 0; // MULTI_SZ is a pain to work with. Turn it into something much more manageable // NB: none of the driver names we check against contain LIST_SEPARATOR, @@ -1175,12 +1025,12 @@ static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info, } } - for (i = 1; i < USB_API_MAX; i++) { + for (i = 2; i < USB_API_MAX; i++) { for (k = 0; k < 3; k++) { j = get_sub_api(lookup[k].list, i); if (j >= 0) { usbi_dbg("matched %s name against %s", lookup[k].designation, - (i != USB_API_WINUSBX) ? usb_api_backend[i].designation : sub_api_name[j]); + (i != USB_API_WINUSBX) ? usb_api_backend[i].designation : usb_api_backend[i].driver_name_list[j]); *api = i; *sub_api = j; return; @@ -1192,31 +1042,25 @@ static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info, static int set_composite_interface(struct libusb_context *ctx, struct libusb_device *dev, char *dev_interface_path, char *device_id, int api, int sub_api) { - unsigned i; - struct windows_device_priv *priv = _device_priv(dev); + struct winusb_device_priv *priv = _device_priv(dev); int interface_number; - - if (priv->apib->id != USB_API_COMPOSITE) { - usbi_err(ctx, "program assertion failed: '%s' is not composite", device_id); - return LIBUSB_ERROR_NO_DEVICE; - } + const char *mi_str; // 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; - for (i = 0; device_id[i] != 0; ) { - if ((device_id[i++] == 'M') && (device_id[i++] == 'I') - && (device_id[i++] == '_')) { - interface_number = (device_id[i++] - '0') * 10; - interface_number += device_id[i] - '0'; - break; - } + mi_str = strstr(device_id, "MI_"); + if ((mi_str != NULL) && isdigit(mi_str[3]) && isdigit(mi_str[4])) { + interface_number = ((mi_str[3] - '0') * 10) + (mi_str[4] - '0'); + } else { + usbi_warn(ctx, "failure to read interface number for %s, using default value", device_id); + interface_number = 0; } - if (device_id[i] == 0) - usbi_warn(ctx, "failure to read interface number for %s. Using default value %d", - device_id, interface_number); + if (interface_number >= USB_MAXINTERFACES) { + usbi_warn(ctx, "interface %d too large - ignoring interface path %s", interface_number, dev_interface_path); + return LIBUSB_ERROR_ACCESS; + } if (priv->usb_interface[interface_number].path != NULL) { if (api == USB_API_HID) { @@ -1246,7 +1090,7 @@ static int set_hid_interface(struct libusb_context *ctx, struct libusb_device *d char *dev_interface_path) { int i; - struct windows_device_priv *priv = _device_priv(dev); + struct winusb_device_priv *priv = _device_priv(dev); if (priv->hid == NULL) { usbi_err(ctx, "program assertion failed: parent is not HID"); @@ -1257,7 +1101,7 @@ static int set_hid_interface(struct libusb_context *ctx, struct libusb_device *d } for (i = 0; i < priv->hid->nb_interfaces; i++) { - if (safe_strcmp(priv->usb_interface[i].path, dev_interface_path) == 0) { + if ((priv->usb_interface[i].path != NULL) && strcmp(priv->usb_interface[i].path, dev_interface_path) == 0) { usbi_dbg("interface[%d] already set to %s", i, dev_interface_path); return LIBUSB_ERROR_ACCESS; } @@ -1273,40 +1117,46 @@ static int set_hid_interface(struct libusb_context *ctx, struct libusb_device *d /* * get_device_list: libusb backend device enumeration function */ -static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs) +static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs) { struct discovered_devs *discdevs; - HDEVINFO dev_info = { 0 }; - const char *usb_class[] = {"USB", "NUSB3", "IUSB3", "IARUSB3"}; - SP_DEVINFO_DATA dev_info_data = { 0 }; - SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL; + HDEVINFO *dev_info, dev_info_intf, dev_info_enum; + SP_DEVINFO_DATA dev_info_data; + DWORD _index = 0; 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; int api, sub_api; - size_t class_index = 0; - unsigned int nb_guids, pass, i, j, ancestor; - char path[MAX_PATH_LENGTH]; - char strbuf[MAX_PATH_LENGTH]; + unsigned int pass, i, j; + char enumerator[16]; + char dev_id[MAX_PATH_LENGTH]; struct libusb_device *dev, *parent_dev; - struct windows_device_priv *priv, *parent_priv; + struct winusb_device_priv *priv, *parent_priv; char *dev_interface_path = NULL; - char *dev_id_path = NULL; unsigned long session_id; - DWORD size, reg_type, port_nr, install_state; + DWORD size, port_nr, reg_type, install_state; HKEY key; WCHAR guid_string_w[MAX_GUID_STRING_LENGTH]; GUID *if_guid; LONG s; +#define HUB_PASS 0 +#define DEV_PASS 1 +#define HCD_PASS 2 +#define GEN_PASS 3 +#define HID_PASS 4 +#define EXT_PASS 5 + // Keep a list of guids that will be enumerated +#define GUID_SIZE_STEP 8 + const GUID **guid_list, **new_guid_list; + unsigned int guid_size = GUID_SIZE_STEP; + unsigned int nb_guids; + // Keep a list of PnP enumerator strings that are found + char *usb_enumerator[8] = { "USB" }; + unsigned int nb_usb_enumerators = 1; + unsigned int usb_enum_index = 0; // Keep a list of newly allocated devs to unref +#define UNREF_SIZE_STEP 16 libusb_device **unref_list, **new_unref_list; - unsigned int unref_size = 64; + unsigned int unref_size = UNREF_SIZE_STEP; unsigned int unref_cur = 0; // PASS 1 : (re)enumerate HCDs (allows for HCD hotplug) @@ -1318,31 +1168,54 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered // 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; - - unref_list = calloc(unref_size, sizeof(libusb_device *)); - if (unref_list == NULL) + guid_list = malloc(guid_size * sizeof(void *)); + if (guid_list == NULL) { + usbi_err(ctx, "failed to alloc guid list"); return LIBUSB_ERROR_NO_MEM; + } + + guid_list[HUB_PASS] = &GUID_DEVINTERFACE_USB_HUB; + guid_list[DEV_PASS] = &GUID_DEVINTERFACE_USB_DEVICE; + guid_list[HCD_PASS] = &GUID_DEVINTERFACE_USB_HOST_CONTROLLER; + guid_list[GEN_PASS] = NULL; + if (api_hid_available) { + HidD_GetHidGuid(&hid_guid); + guid_list[HID_PASS] = &hid_guid; + } else { + guid_list[HID_PASS] = NULL; + } + nb_guids = EXT_PASS; + + unref_list = malloc(unref_size * sizeof(void *)); + if (unref_list == NULL) { + usbi_err(ctx, "failed to alloc unref list"); + free((void *)guid_list); + return LIBUSB_ERROR_NO_MEM; + } + + dev_info_intf = pSetupDiGetClassDevsA(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + if (dev_info_intf == INVALID_HANDLE_VALUE) { + usbi_err(ctx, "failed to obtain device info list: %s", windows_error_str(0)); + free(unref_list); + free((void *)guid_list); + return LIBUSB_ERROR_OTHER; + } for (pass = 0; ((pass < nb_guids) && (r == LIBUSB_SUCCESS)); pass++) { //#define ENUM_DEBUG #if defined(ENABLE_LOGGING) && defined(ENUM_DEBUG) - const char *passname[] = { "HCD", "HUB", "GEN", "DEV", "HID", "EXT" }; - usbi_dbg("#### PROCESSING %ss %s", passname[(pass <= HID_PASS) ? pass : (HID_PASS + 1)], - (pass != GEN_PASS) ? guid_to_string(guid[pass]) : ""); + const char * const passname[] = {"HUB", "DEV", "HCD", "GEN", "HID", "EXT"}; + usbi_dbg("#### PROCESSING %ss %s", passname[MIN(pass, EXT_PASS)], guid_to_string(guid_list[pass])); #endif + if ((pass == HID_PASS) && (guid_list[HID_PASS] == NULL)) + continue; + + dev_info = (pass != GEN_PASS) ? &dev_info_intf : &dev_info_enum; + for (i = 0; ; i++) { // safe loop: free up any (unprotected) dynamic resource // NB: this is always executed before breaking the loop - safe_free(dev_interface_details); safe_free(dev_interface_path); - safe_free(dev_id_path); priv = parent_priv = NULL; dev = parent_dev = NULL; @@ -1351,139 +1224,165 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered break; if ((pass == HCD_PASS) && (i == UINT8_MAX)) { - usbi_warn(ctx, "program assertion failed - found more than %d buses, skipping the rest.", UINT8_MAX); + usbi_warn(ctx, "program assertion failed - found more than %u buses, skipping the rest.", UINT8_MAX); break; } if (pass != GEN_PASS) { // Except for GEN, all passes deal with device interfaces - dev_interface_details = get_interface_details(ctx, &dev_info, &dev_info_data, guid[pass], i); - if (dev_interface_details == NULL) + r = get_interface_details(ctx, *dev_info, &dev_info_data, guid_list[pass], &_index, &dev_interface_path); + if ((r != LIBUSB_SUCCESS) || (dev_interface_path == NULL)) { + _index = 0; break; - - dev_interface_path = sanitize_path(dev_interface_details->DevicePath); - if (dev_interface_path == NULL) { - usbi_warn(ctx, "could not sanitize device interface path for '%s'", dev_interface_details->DevicePath); - continue; } } else { // Workaround for a Nec/Renesas USB 3.0 driver bug where root hubs are // being listed under the "NUSB3" PnP Symbolic Name rather than "USB". // The Intel USB 3.0 driver behaves similar, but uses "IUSB3" // The Intel Alpine Ridge USB 3.1 driver uses "IARUSB3" - for (; class_index < ARRAYSIZE(usb_class); class_index++) { - if (get_devinfo_data(ctx, &dev_info, &dev_info_data, usb_class[class_index], i)) + for (; usb_enum_index < nb_usb_enumerators; usb_enum_index++) { + if (get_devinfo_data(ctx, dev_info, &dev_info_data, usb_enumerator[usb_enum_index], i)) break; i = 0; } - if (class_index >= ARRAYSIZE(usb_class)) + if (usb_enum_index == nb_usb_enumerators) break; } - // Read the Device ID path. This is what we'll use as UID - // Note that if the device is plugged in a different port or hub, the Device ID changes - if (CM_Get_Device_IDA(dev_info_data.DevInst, path, sizeof(path), 0) != CR_SUCCESS) { - usbi_warn(ctx, "could not read the device id path for devinst %X, skipping", - (unsigned int)dev_info_data.DevInst); + // Read the Device ID path + if (!pSetupDiGetDeviceInstanceIdA(*dev_info, &dev_info_data, dev_id, sizeof(dev_id), NULL)) { + usbi_warn(ctx, "could not read the device instance ID for devInst %X, skipping", + dev_info_data.DevInst); continue; } - dev_id_path = sanitize_path(path); - if (dev_id_path == NULL) { - usbi_warn(ctx, "could not sanitize device id path for devinst %X, skipping", - (unsigned int)dev_info_data.DevInst); - continue; - } #ifdef ENUM_DEBUG - usbi_dbg("PRO: %s", dev_id_path); + usbi_dbg("PRO: %s", dev_id); #endif - // The SPDRP_ADDRESS for USB devices is the device port number on the hub - port_nr = 0; - if ((pass >= HUB_PASS) && (pass <= GEN_PASS)) { - if ((!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_ADDRESS, - ®_type, (BYTE *)&port_nr, 4, &size)) || (size != 4)) { - usbi_warn(ctx, "could not retrieve port number for device '%s', skipping: %s", - dev_id_path, windows_error_str(0)); - continue; - } - } - // Set API to use or get additional data from generic pass api = USB_API_UNSUPPORTED; sub_api = SUB_API_NOTSET; switch (pass) { case HCD_PASS: break; - case GEN_PASS: - // We use the GEN pass to detect driverless devices... - size = sizeof(strbuf); - if (!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_DRIVER, - ®_type, (BYTE *)strbuf, size, &size)) { - usbi_info(ctx, "The following device has no driver: '%s'", dev_id_path); - usbi_info(ctx, "libusb will not be able to access it."); + case HUB_PASS: + api = USB_API_HUB; + // Fetch the PnP enumerator class for this hub + // This will allow us to enumerate all classes during the GEN pass + if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_ENUMERATOR_NAME, + NULL, (PBYTE)enumerator, sizeof(enumerator), NULL)) { + usbi_err(ctx, "could not read enumerator string for device '%s': %s", dev_id, windows_error_str(0)); + LOOP_BREAK(LIBUSB_ERROR_OTHER); } - // ...and to add the additional device interface GUIDs - key = pSetupDiOpenDevRegKey(dev_info, &dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); - if (key != INVALID_HANDLE_VALUE) { - size = sizeof(guid_string_w); - s = pRegQueryValueExW(key, L"DeviceInterfaceGUIDs", NULL, ®_type, - (BYTE *)guid_string_w, &size); - pRegCloseKey(key); - if (s == ERROR_SUCCESS) { - if (nb_guids >= MAX_ENUM_GUIDS) { - // If this assert is ever reported, grow a GUID table dynamically - usbi_err(ctx, "program assertion failed: too many GUIDs"); - LOOP_BREAK(LIBUSB_ERROR_OVERFLOW); - } - if_guid = calloc(1, sizeof(GUID)); - if (if_guid == NULL) { - usbi_err(ctx, "could not calloc for if_guid: not enough memory"); + for (j = 0; j < nb_usb_enumerators; j++) { + if (strcmp(usb_enumerator[j], enumerator) == 0) + break; + } + if (j == nb_usb_enumerators) { + usbi_dbg("found new PnP enumerator string '%s'", enumerator); + if (nb_usb_enumerators < ARRAYSIZE(usb_enumerator)) { + usb_enumerator[nb_usb_enumerators] = _strdup(enumerator); + if (usb_enumerator[nb_usb_enumerators] != NULL) { + nb_usb_enumerators++; + } else { + usbi_err(ctx, "could not allocate enumerator string '%s'", enumerator); LOOP_BREAK(LIBUSB_ERROR_NO_MEM); } - pCLSIDFromString(guid_string_w, if_guid); - guid[nb_guids++] = if_guid; - usbi_dbg("extra GUID: %s", guid_to_string(if_guid)); + } else { + usbi_warn(ctx, "too many enumerator strings, some devices may not be accessible"); } } break; + case GEN_PASS: + // We use the GEN pass to detect driverless devices... + if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_DRIVER, + NULL, NULL, 0, NULL) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) { + usbi_info(ctx, "The following device has no driver: '%s'", dev_id); + usbi_info(ctx, "libusb will not be able to access it"); + } + // ...and to add the additional device interface GUIDs + key = pSetupDiOpenDevRegKey(*dev_info, &dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); + if (key == INVALID_HANDLE_VALUE) + break; + // Look for both DeviceInterfaceGUIDs *and* DeviceInterfaceGUID, in that order + size = sizeof(guid_string_w); + s = pRegQueryValueExW(key, L"DeviceInterfaceGUIDs", NULL, ®_type, + (LPBYTE)guid_string_w, &size); + if (s == ERROR_FILE_NOT_FOUND) + s = pRegQueryValueExW(key, L"DeviceInterfaceGUID", NULL, ®_type, + (LPBYTE)guid_string_w, &size); + pRegCloseKey(key); + if ((s == ERROR_SUCCESS) && + (((reg_type == REG_SZ) && (size == (sizeof(guid_string_w) - sizeof(WCHAR)))) || + ((reg_type == REG_MULTI_SZ) && (size == sizeof(guid_string_w))))) { + if (nb_guids == guid_size) { + new_guid_list = realloc((void *)guid_list, (guid_size + GUID_SIZE_STEP) * sizeof(void *)); + if (new_guid_list == NULL) { + usbi_err(ctx, "failed to realloc guid list"); + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + } + guid_list = new_guid_list; + guid_size += GUID_SIZE_STEP; + } + if_guid = malloc(sizeof(*if_guid)); + if (if_guid == NULL) { + usbi_err(ctx, "failed to alloc if_guid"); + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + } + if (pIIDFromString(guid_string_w, if_guid) != 0) { + usbi_warn(ctx, "device '%s' has malformed DeviceInterfaceGUID string, skipping", dev_id); + free(if_guid); + } else { + // Check if we've already seen this GUID + for (j = EXT_PASS; j < nb_guids; j++) { + if (memcmp(guid_list[j], if_guid, sizeof(*if_guid)) == 0) + break; + } + if (j == nb_guids) { + usbi_dbg("extra GUID: %s", guid_to_string(if_guid)); + guid_list[nb_guids++] = if_guid; + } else { + // Duplicate, ignore + free(if_guid); + } + } + } else if (s == ERROR_SUCCESS) { + usbi_warn(ctx, "unexpected type/size of DeviceInterfaceGUID for '%s'", dev_id); + } + 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, - ®_type, (BYTE *)&install_state, 4, &size)) || (size != 4)) { + if ((!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_INSTALL_STATE, + NULL, (PBYTE)&install_state, sizeof(install_state), &size)) || (size != sizeof(install_state))) { usbi_warn(ctx, "could not detect installation state of driver for '%s': %s", - dev_id_path, windows_error_str(0)); + dev_id, windows_error_str(0)); } else if (install_state != 0) { usbi_warn(ctx, "driver for device '%s' is reporting an issue (code: %u) - skipping", - dev_id_path, (unsigned int)install_state); + dev_id, (unsigned int)install_state); continue; } - get_api_type(ctx, &dev_info, &dev_info_data, &api, &sub_api); + get_api_type(ctx, dev_info, &dev_info_data, &api, &sub_api); break; } // Find parent device (for the passes that need it) - switch (pass) { - case HCD_PASS: - case DEV_PASS: - case HUB_PASS: - break; - default: - // Go through the ancestors until we see a face we recognize - parent_dev = NULL; - for (ancestor = 1; parent_dev == NULL; ancestor++) { - session_id = get_ancestor_session_id(dev_info_data.DevInst, ancestor); - if (session_id == 0) - break; - - parent_dev = usbi_get_device_by_session_id(ctx, session_id); - } - + if (pass >= GEN_PASS) { + parent_dev = get_ancestor(ctx, dev_info_data.DevInst, NULL); if (parent_dev == NULL) { - usbi_dbg("unlisted ancestor for '%s' (non USB HID, newly connected, etc.) - ignoring", dev_id_path); + // Root hubs will not have a parent + dev = usbi_get_device_by_session_id(ctx, (unsigned long)dev_info_data.DevInst); + if (dev != NULL) { + priv = _device_priv(dev); + if (priv->root_hub) + goto track_unref; + libusb_unref_device(dev); + } + + usbi_dbg("unlisted ancestor for '%s' (non USB HID, newly connected, etc.) - ignoring", dev_id); continue; } @@ -1493,81 +1392,54 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered libusb_unref_device(parent_dev); continue; } - - break; } - // Create new or match existing device, using the (hashed) device_id as session id - if (pass <= DEV_PASS) { // For subsequent passes, we'll lookup the parent + // Create new or match existing device, using the devInst as session id + if ((pass <= GEN_PASS) && (pass != HCD_PASS)) { // For subsequent passes, we'll lookup the parent // These are the passes that create "new" devices - session_id = htab_hash(dev_id_path); + session_id = (unsigned long)dev_info_data.DevInst; dev = usbi_get_device_by_session_id(ctx, session_id); if (dev == NULL) { - if (pass == DEV_PASS) { - // This can occur if the OS only reports a newly plugged device after we started enum - usbi_warn(ctx, "'%s' was only detected in late pass (newly connected device?)" - " - ignoring", dev_id_path); - continue; - } - + alloc_device: usbi_dbg("allocating new device for session [%lX]", session_id); dev = usbi_alloc_device(ctx, session_id); if (dev == NULL) LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - priv = windows_device_priv_init(dev); + priv = winusb_device_priv_init(dev); + priv->dev_id = _strdup(dev_id); + if (priv->dev_id == NULL) { + libusb_unref_device(dev); + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + } } else { - usbi_dbg("found existing device for session [%lX] (%u.%u)", - session_id, dev->bus_number, dev->device_address); + usbi_dbg("found existing device for session [%lX]", session_id); priv = _device_priv(dev); - if ((parent_dev != NULL) && (dev->parent_dev != NULL)) { - if (dev->parent_dev != parent_dev) { - // It is possible for the actual parent device to not have existed at the - // time of enumeration, so the currently assigned parent may in fact be a - // grandparent. If the devices differ, we assume the "new" parent device - // is in fact closer to the device. - usbi_dbg("updating parent device [session %lX -> %lX]", - dev->parent_dev->session_data, parent_dev->session_data); - libusb_unref_device(dev->parent_dev); - dev->parent_dev = parent_dev; - } else { - // We hold a reference to parent_dev instance, but this device already - // has a parent_dev reference (only one per child) - libusb_unref_device(parent_dev); - } + if (strcmp(priv->dev_id, dev_id) != 0) { + usbi_dbg("device instance ID for session [%lX] changed", session_id); + usbi_disconnect_device(dev); + libusb_unref_device(dev); + goto alloc_device; } } + track_unref: // Keep track of devices that need unref - unref_list[unref_cur++] = dev; - if (unref_cur >= unref_size) { - unref_size += 64; - new_unref_list = usbi_reallocf(unref_list, unref_size * sizeof(libusb_device *)); + if (unref_cur == unref_size) { + new_unref_list = realloc(unref_list, (unref_size + UNREF_SIZE_STEP) * sizeof(void *)); if (new_unref_list == NULL) { - usbi_err(ctx, "could not realloc list for unref - aborting."); + usbi_err(ctx, "could not realloc list for unref - aborting"); LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - } else { - unref_list = new_unref_list; } + unref_list = new_unref_list; + unref_size += UNREF_SIZE_STEP; } + unref_list[unref_cur++] = dev; } // Setup device switch (pass) { - case HCD_PASS: - // If the hcd has already been setup, don't do it again - if (priv->path != NULL) - break; - dev->bus_number = (uint8_t)(i + 1); // bus 0 is reserved for disconnected - dev->device_address = 0; - dev->num_configurations = 0; - priv->apib = &usb_api_backend[USB_API_HUB]; - priv->sub_api = SUB_API_NOTSET; - priv->depth = UINT8_MAX; // Overflow to 0 for HCD Hubs - priv->path = dev_interface_path; - dev_interface_path = NULL; - break; case HUB_PASS: case DEV_PASS: // If the device has already been setup, don't do it again @@ -1578,7 +1450,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered dev_interface_path = NULL; priv->apib = &usb_api_backend[api]; priv->sub_api = sub_api; - switch(api) { + switch (api) { case USB_API_COMPOSITE: case USB_API_HUB: break; @@ -1586,24 +1458,29 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered 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 = _strdup(priv->path); if (priv->usb_interface[0].path == NULL) - usbi_warn(ctx, "could not duplicate interface path '%s'", priv->path); + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); // The following is needed if we want API calls to work for both simple // and composite devices. - for(j = 0; j < USB_MAXINTERFACES; j++) + for (j = 0; j < USB_MAXINTERFACES; j++) priv->usb_interface[j].apib = &usb_api_backend[api]; - break; } break; + case HCD_PASS: + r = enumerate_hcd_root_hub(ctx, dev_id, (uint8_t)(i + 1), dev_info_data.DevInst); + break; case GEN_PASS: - r = init_device(dev, parent_dev, (uint8_t)port_nr, dev_id_path, dev_info_data.DevInst); + // The SPDRP_ADDRESS for USB devices is the device port number on the hub + port_nr = 0; + if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_ADDRESS, + NULL, (PBYTE)&port_nr, sizeof(port_nr), &size) || (size != sizeof(port_nr))) + usbi_warn(ctx, "could not retrieve port number for device '%s': %s", dev_id, windows_error_str(0)); + r = init_device(dev, parent_dev, (uint8_t)port_nr, dev_info_data.DevInst); if (r == LIBUSB_SUCCESS) { // Append device to the list of discovered devices discdevs = discovered_devs_append(*_discdevs, dev); @@ -1624,7 +1501,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered r = set_hid_interface(ctx, parent_dev, dev_interface_path); } else { usbi_dbg("setting composite interface for [%lX]:", parent_dev->session_data); - r = set_composite_interface(ctx, parent_dev, dev_interface_path, dev_id_path, api, sub_api); + r = set_composite_interface(ctx, parent_dev, dev_interface_path, dev_id, api, sub_api); } switch (r) { case LIBUSB_SUCCESS: @@ -1645,66 +1522,36 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered } } + pSetupDiDestroyDeviceInfoList(dev_info_intf); + // Free any additional GUIDs - for (pass = HID_PASS + 1; pass < nb_guids; pass++) - safe_free(guid[pass]); + for (pass = EXT_PASS; pass < nb_guids; pass++) + free((void *)guid_list[pass]); + free((void *)guid_list); + + // Free any PnP enumerator strings + for (i = 1; i < nb_usb_enumerators; i++) + free(usb_enumerator[i]); // Unref newly allocated devs for (i = 0; i < unref_cur; i++) - safe_unref_device(unref_list[i]); + libusb_unref_device(unref_list[i]); free(unref_list); return r; } -/* - * exit: libusb backend deinitialization function - */ -static void windows_exit(void) +static int winusb_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer) { - int i; - HANDLE semaphore; - char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' - - sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); - semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name); - if (semaphore == NULL) - return; - - // A successful wait brings our semaphore count to 0 (unsignaled) - // => any concurent wait stalls until the semaphore release - if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { - CloseHandle(semaphore); - return; - } - - // Only works if exits and inits are balanced exactly - if (--concurrent_usage < 0) { // Last exit - for (i = 0; i < USB_API_MAX; i++) - usb_api_backend[i].exit(SUB_API_NOTSET); - exit_dlls(); - exit_polling(); - windows_common_exit(); - usbi_mutex_destroy(&autoclaim_lock); - } - - ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 - CloseHandle(semaphore); -} - -static int windows_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian) -{ - struct windows_device_priv *priv = _device_priv(dev); + struct winusb_device_priv *priv = _device_priv(dev); memcpy(buffer, &priv->dev_descriptor, DEVICE_DESC_LENGTH); - *host_endian = 0; - return LIBUSB_SUCCESS; } -static int windows_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) +static int winusb_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len) { - struct windows_device_priv *priv = _device_priv(dev); + struct winusb_device_priv *priv = _device_priv(dev); PUSB_CONFIGURATION_DESCRIPTOR config_header; size_t size; @@ -1715,32 +1562,29 @@ static int windows_get_config_descriptor(struct libusb_device *dev, uint8_t conf if ((priv->config_descriptor == NULL) || (priv->config_descriptor[config_index] == NULL)) return LIBUSB_ERROR_NOT_FOUND; - config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptor[config_index]; + config_header = priv->config_descriptor[config_index]; size = MIN(config_header->wTotalLength, len); memcpy(buffer, priv->config_descriptor[config_index], size); - *host_endian = 0; - return (int)size; } -static int windows_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue, - unsigned char **buffer, int *host_endian) +static int winusb_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue, + unsigned char **buffer) { - struct windows_device_priv *priv = _device_priv(dev); + struct winusb_device_priv *priv = _device_priv(dev); PUSB_CONFIGURATION_DESCRIPTOR config_header; uint8_t index; - *buffer = NULL; - *host_endian = 0; - if (priv->config_descriptor == NULL) return LIBUSB_ERROR_NOT_FOUND; for (index = 0; index < dev->num_configurations; index++) { - config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptor[index]; + config_header = priv->config_descriptor[index]; + if (config_header == NULL) + continue; if (config_header->bConfigurationValue == bConfigurationValue) { - *buffer = priv->config_descriptor[index]; + *buffer = (unsigned char *)priv->config_descriptor[index]; return (int)config_header->wTotalLength; } } @@ -1751,16 +1595,16 @@ static int windows_get_config_descriptor_by_value(struct libusb_device *dev, uin /* * return the cached copy of the active config descriptor */ -static int windows_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian) +static int winusb_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len) { - struct windows_device_priv *priv = _device_priv(dev); + struct winusb_device_priv *priv = _device_priv(dev); unsigned char *config_desc; int r; if (priv->active_config == 0) return LIBUSB_ERROR_NOT_FOUND; - r = windows_get_config_descriptor_by_value(dev, priv->active_config, &config_desc, host_endian); + r = winusb_get_config_descriptor_by_value(dev, priv->active_config, &config_desc); if (r < 0) return r; @@ -1769,29 +1613,26 @@ static int windows_get_active_config_descriptor(struct libusb_device *dev, unsig return (int)len; } -static int windows_open(struct libusb_device_handle *dev_handle) +static int winusb_open(struct libusb_device_handle *dev_handle) { - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - if (priv->apib == NULL) { - usbi_err(ctx, "program assertion failed - device is not initialized"); - return LIBUSB_ERROR_NO_DEVICE; - } + CHECK_SUPPORTED_API(priv->apib, open); return priv->apib->open(SUB_API_NOTSET, dev_handle); } -static void windows_close(struct libusb_device_handle *dev_handle) +static void winusb_close(struct libusb_device_handle *dev_handle) { - struct windows_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); - priv->apib->close(SUB_API_NOTSET, dev_handle); + if (priv->apib->close) + priv->apib->close(SUB_API_NOTSET, dev_handle); } -static int windows_get_configuration(struct libusb_device_handle *dev_handle, int *config) +static int winusb_get_configuration(struct libusb_device_handle *dev_handle, int *config) { - struct windows_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); if (priv->active_config == 0) { *config = 0; @@ -1807,9 +1648,9 @@ static int windows_get_configuration(struct libusb_device_handle *dev_handle, in * does not currently expose a service that allows higher-level drivers to set * the configuration." */ -static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config) +static int winusb_set_configuration(struct libusb_device_handle *dev_handle, int config) { - struct windows_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); int r = LIBUSB_SUCCESS; if (config >= USB_MAXCONFIG) @@ -1826,10 +1667,12 @@ static int windows_set_configuration(struct libusb_device_handle *dev_handle, in return r; } -static int windows_claim_interface(struct libusb_device_handle *dev_handle, int iface) +static int winusb_claim_interface(struct libusb_device_handle *dev_handle, int iface) { - int r = LIBUSB_SUCCESS; - struct windows_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + int r; + + CHECK_SUPPORTED_API(priv->apib, claim_interface); safe_free(priv->usb_interface[iface].endpoint); priv->usb_interface[iface].nb_endpoints = 0; @@ -1842,10 +1685,12 @@ static int windows_claim_interface(struct libusb_device_handle *dev_handle, int return r; } -static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) +static int winusb_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) { - int r = LIBUSB_SUCCESS; - struct windows_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + int r; + + CHECK_SUPPORTED_API(priv->apib, set_interface_altsetting); safe_free(priv->usb_interface[iface].endpoint); priv->usb_interface[iface].nb_endpoints = 0; @@ -1858,135 +1703,144 @@ static int windows_set_interface_altsetting(struct libusb_device_handle *dev_han return r; } -static int windows_release_interface(struct libusb_device_handle *dev_handle, int iface) +static int winusb_release_interface(struct libusb_device_handle *dev_handle, int iface) { - struct windows_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->apib, release_interface); return priv->apib->release_interface(SUB_API_NOTSET, dev_handle, iface); } -static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) +static int winusb_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) { - struct windows_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->apib, clear_halt); + return priv->apib->clear_halt(SUB_API_NOTSET, dev_handle, endpoint); } -static int windows_reset_device(struct libusb_device_handle *dev_handle) +static int winusb_reset_device(struct libusb_device_handle *dev_handle) { - struct windows_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->apib, reset_device); + return priv->apib->reset_device(SUB_API_NOTSET, dev_handle); } -// The 3 functions below are unlikely to ever get supported on Windows -static int windows_kernel_driver_active(struct libusb_device_handle *dev_handle, int iface) +static void winusb_destroy_device(struct libusb_device *dev) { - return LIBUSB_ERROR_NOT_SUPPORTED; + winusb_device_priv_release(dev); } -static int windows_attach_kernel_driver(struct libusb_device_handle *dev_handle, int iface) +static void winusb_clear_transfer_priv(struct usbi_transfer *itransfer) { - return LIBUSB_ERROR_NOT_SUPPORTED; -} + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int sub_api = priv->sub_api; -static int windows_detach_kernel_driver(struct libusb_device_handle *dev_handle, int iface) -{ - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static void windows_destroy_device(struct libusb_device *dev) -{ - windows_device_priv_release(dev); -} - -static void windows_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - - usbi_free_fd(&transfer_priv->pollable_fd); + usbi_close(transfer_priv->pollable_fd.fd); + transfer_priv->pollable_fd = INVALID_WINFD; + transfer_priv->handle = NULL; safe_free(transfer_priv->hid_buffer); + + if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS && sub_api == SUB_API_WINUSB) { + if (transfer_priv->isoch_buffer_handle != NULL) { + if (WinUSBX[sub_api].UnregisterIsochBuffer(transfer_priv->isoch_buffer_handle)) { + transfer_priv->isoch_buffer_handle = NULL; + } else { + usbi_dbg("Couldn't unregister isoch buffer!"); + } + } + } + + safe_free(transfer_priv->iso_context); + // When auto claim is in use, attempt to release the auto-claimed interface auto_release(itransfer); } -static int submit_bulk_transfer(struct usbi_transfer *itransfer) +static int do_submit_transfer(struct usbi_transfer *itransfer, short events, + int (*transfer_fn)(int, struct usbi_transfer *)) { - 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); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); + struct libusb_context *ctx = ITRANSFER_CTX(itransfer); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winfd wfd; int r; - r = priv->apib->submit_bulk_transfer(SUB_API_NOTSET, itransfer); - if (r != LIBUSB_SUCCESS) + wfd = usbi_create_fd(); + if (wfd.fd < 0) + return LIBUSB_ERROR_NO_MEM; + + r = usbi_add_pollfd(ctx, wfd.fd, events); + if (r) { + usbi_close(wfd.fd); return r; + } - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, - (short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT)); + // Use transfer_priv to store data needed for async polling + transfer_priv->pollable_fd = wfd; - return LIBUSB_SUCCESS; + r = transfer_fn(SUB_API_NOTSET, itransfer); + + if ((r != LIBUSB_SUCCESS) && (r != LIBUSB_ERROR_OVERFLOW)) { + usbi_remove_pollfd(ctx, wfd.fd); + usbi_close(wfd.fd); + transfer_priv->pollable_fd = INVALID_WINFD; + } + + return r; } -static int submit_iso_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int r; - - r = priv->apib->submit_iso_transfer(SUB_API_NOTSET, itransfer); - if (r != LIBUSB_SUCCESS) - return r; - - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, - (short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT)); - - return LIBUSB_SUCCESS; -} - -static int submit_control_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int r; - - r = priv->apib->submit_control_transfer(SUB_API_NOTSET, itransfer); - if (r != LIBUSB_SUCCESS) - return r; - - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN); - - return LIBUSB_SUCCESS; -} - -static int windows_submit_transfer(struct usbi_transfer *itransfer) +static int winusb_submit_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int (*transfer_fn)(int, struct usbi_transfer *); + short events; switch (transfer->type) { case LIBUSB_TRANSFER_TYPE_CONTROL: - return submit_control_transfer(itransfer); + events = (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) ? POLLIN : POLLOUT; + transfer_fn = priv->apib->submit_control_transfer; + break; case LIBUSB_TRANSFER_TYPE_BULK: case LIBUSB_TRANSFER_TYPE_INTERRUPT: if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)) return LIBUSB_ERROR_NOT_SUPPORTED; - return submit_bulk_transfer(itransfer); + events = IS_XFERIN(transfer) ? POLLIN : POLLOUT; + transfer_fn = priv->apib->submit_bulk_transfer; + break; case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return submit_iso_transfer(itransfer); + events = IS_XFERIN(transfer) ? POLLIN : POLLOUT; + transfer_fn = priv->apib->submit_iso_transfer; + break; case LIBUSB_TRANSFER_TYPE_BULK_STREAM: return LIBUSB_ERROR_NOT_SUPPORTED; default: usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); return LIBUSB_ERROR_INVALID_PARAM; } + + if (transfer_fn == NULL) { + usbi_warn(TRANSFER_CTX(transfer), + "unsupported transfer type %d (unrecognized device driver)", + transfer->type); + return LIBUSB_ERROR_NOT_SUPPORTED; + } + + return do_submit_transfer(itransfer, events, transfer_fn); } static int windows_abort_control(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + + CHECK_SUPPORTED_API(priv->apib, abort_control); return priv->apib->abort_control(SUB_API_NOTSET, itransfer); } @@ -1994,12 +1848,14 @@ static int windows_abort_control(struct usbi_transfer *itransfer) static int windows_abort_transfers(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + + CHECK_SUPPORTED_API(priv->apib, abort_transfers); return priv->apib->abort_transfers(SUB_API_NOTSET, itransfer); } -static int windows_cancel_transfer(struct usbi_transfer *itransfer) +static int winusb_cancel_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); @@ -2018,237 +1874,91 @@ static int windows_cancel_transfer(struct usbi_transfer *itransfer) } } -static int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size) +static int winusb_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); return priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, io_size); } -static struct winfd *windows_get_fd(struct usbi_transfer *transfer) +static int winusb_get_transfer_fd(struct usbi_transfer *itransfer) { - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(transfer); - return &transfer_priv->pollable_fd; + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + return transfer_priv->pollable_fd.fd; } -static void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size) +static void winusb_get_overlapped_result(struct usbi_transfer *itransfer, + DWORD *io_result, DWORD *io_size) { + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winfd *pollable_fd = &transfer_priv->pollable_fd; + if (HasOverlappedIoCompletedSync(pollable_fd->overlapped)) { *io_result = NO_ERROR; *io_size = (DWORD)pollable_fd->overlapped->InternalHigh; - } - else if (GetOverlappedResult(pollable_fd->handle, pollable_fd->overlapped, io_size, false)) { + } else if (GetOverlappedResult(transfer_priv->handle, pollable_fd->overlapped, io_size, FALSE)) { // Regular async overlapped *io_result = NO_ERROR; - } - else { + } else { *io_result = GetLastError(); } } // NB: MSVC6 does not support named initializers. -const struct usbi_os_backend windows_backend = { - "Windows", - USBI_CAP_HAS_HID_ACCESS, - windows_init, - windows_exit, - - windows_get_device_list, - NULL, /* hotplug_poll */ - windows_open, - windows_close, - - windows_get_device_descriptor, - windows_get_active_config_descriptor, - windows_get_config_descriptor, - windows_get_config_descriptor_by_value, - - windows_get_configuration, - windows_set_configuration, - windows_claim_interface, - windows_release_interface, - - windows_set_interface_altsetting, - windows_clear_halt, - windows_reset_device, - - NULL, /* alloc_streams */ - NULL, /* free_streams */ - - NULL, /* dev_mem_alloc */ - NULL, /* dev_mem_free */ - - windows_kernel_driver_active, - windows_detach_kernel_driver, - windows_attach_kernel_driver, - - windows_destroy_device, - - windows_submit_transfer, - windows_cancel_transfer, - windows_clear_transfer_priv, - - windows_handle_events, - NULL, - - windows_clock_gettime, -#if defined(USBI_TIMERFD_AVAILABLE) - NULL, -#endif - sizeof(struct windows_device_priv), - sizeof(struct windows_device_handle_priv), - sizeof(struct windows_transfer_priv), +const struct windows_backend winusb_backend = { + winusb_init, + winusb_exit, + winusb_get_device_list, + winusb_open, + winusb_close, + winusb_get_device_descriptor, + winusb_get_active_config_descriptor, + winusb_get_config_descriptor, + winusb_get_config_descriptor_by_value, + winusb_get_configuration, + winusb_set_configuration, + winusb_claim_interface, + winusb_release_interface, + winusb_set_interface_altsetting, + winusb_clear_halt, + winusb_reset_device, + winusb_destroy_device, + winusb_submit_transfer, + winusb_cancel_transfer, + winusb_clear_transfer_priv, + winusb_copy_transfer_data, + winusb_get_transfer_fd, + winusb_get_overlapped_result, }; - /* * USB API backends */ -static int unsupported_init(int sub_api, struct libusb_context *ctx) -{ - return LIBUSB_SUCCESS; -} -static int unsupported_exit(int sub_api) -{ - return LIBUSB_SUCCESS; -} - -static int unsupported_open(int sub_api, struct libusb_device_handle *dev_handle) -{ - PRINT_UNSUPPORTED_API(open); -} - -static void unsupported_close(int sub_api, struct libusb_device_handle *dev_handle) -{ - usbi_dbg("unsupported API call for 'close'"); -} - -static int unsupported_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - PRINT_UNSUPPORTED_API(configure_endpoints); -} - -static int unsupported_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - PRINT_UNSUPPORTED_API(claim_interface); -} - -static int unsupported_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - PRINT_UNSUPPORTED_API(set_interface_altsetting); -} - -static int unsupported_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - PRINT_UNSUPPORTED_API(release_interface); -} - -static int unsupported_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) -{ - PRINT_UNSUPPORTED_API(clear_halt); -} - -static int unsupported_reset_device(int sub_api, struct libusb_device_handle *dev_handle) -{ - PRINT_UNSUPPORTED_API(reset_device); -} - -static int unsupported_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - PRINT_UNSUPPORTED_API(submit_bulk_transfer); -} - -static int unsupported_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - PRINT_UNSUPPORTED_API(submit_iso_transfer); -} - -static int unsupported_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - PRINT_UNSUPPORTED_API(submit_control_transfer); -} - -static int unsupported_abort_control(int sub_api, struct usbi_transfer *itransfer) -{ - PRINT_UNSUPPORTED_API(abort_control); -} - -static int unsupported_abort_transfers(int sub_api, struct usbi_transfer *itransfer) -{ - PRINT_UNSUPPORTED_API(abort_transfers); -} - -static int unsupported_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) -{ - PRINT_UNSUPPORTED_API(copy_transfer_data); -} - -static int common_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - return LIBUSB_SUCCESS; -} - -// These names must be uppercase -static const char *hub_driver_names[] = {"USBHUB", "USBHUB3", "USB3HUB", "NUSB3HUB", "RUSB3HUB", "FLXHCIH", "TIHUB3", "ETRONHUB3", "VIAHUB3", "ASMTHUB3", "IUSB3HUB", "VUSB3HUB", "AMDHUB30", "VHHUB", "AUSB3HUB"}; -static const char *composite_driver_names[] = {"USBCCGP"}; -static const char *winusbx_driver_names[] = WINUSBX_DRV_NAMES; -static const char *hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"}; +static const char * const composite_driver_names[] = {"USBCCGP"}; +static const char * const winusbx_driver_names[] = {"libusbK", "libusb0", "WinUSB"}; +static const char * const hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"}; const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { { USB_API_UNSUPPORTED, "Unsupported API", - NULL, - 0, - unsupported_init, - unsupported_exit, - unsupported_open, - unsupported_close, - unsupported_configure_endpoints, - unsupported_claim_interface, - unsupported_set_interface_altsetting, - unsupported_release_interface, - unsupported_clear_halt, - unsupported_reset_device, - unsupported_submit_bulk_transfer, - unsupported_submit_iso_transfer, - unsupported_submit_control_transfer, - unsupported_abort_control, - unsupported_abort_transfers, - unsupported_copy_transfer_data, + // No supported operations }, { USB_API_HUB, "HUB API", - hub_driver_names, - ARRAYSIZE(hub_driver_names), - unsupported_init, - unsupported_exit, - unsupported_open, - unsupported_close, - unsupported_configure_endpoints, - unsupported_claim_interface, - unsupported_set_interface_altsetting, - unsupported_release_interface, - unsupported_clear_halt, - unsupported_reset_device, - unsupported_submit_bulk_transfer, - unsupported_submit_iso_transfer, - unsupported_submit_control_transfer, - unsupported_abort_control, - unsupported_abort_transfers, - unsupported_copy_transfer_data, + // No supported operations }, { USB_API_COMPOSITE, "Composite API", composite_driver_names, ARRAYSIZE(composite_driver_names), - composite_init, - composite_exit, + NULL, /* init */ + NULL, /* exit */ composite_open, composite_close, - common_configure_endpoints, + NULL, /* configure_endpoints */ composite_claim_interface, composite_set_interface_altsetting, composite_release_interface, @@ -2277,7 +1987,7 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { winusbx_clear_halt, winusbx_reset_device, winusbx_submit_bulk_transfer, - unsupported_submit_iso_transfer, + winusbx_submit_iso_transfer, winusbx_submit_control_transfer, winusbx_abort_control, winusbx_abort_transfers, @@ -2292,14 +2002,14 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { hid_exit, hid_open, hid_close, - common_configure_endpoints, + NULL, /* 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, + NULL, /* submit_iso_transfer */ hid_submit_control_transfer, hid_abort_transfers, hid_abort_transfers, @@ -2319,7 +2029,15 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { pLibK_GetProcAddress((PVOID *)&WinUSBX[i].fn, i, KUSB_FNID_##fn); \ } while (0) -static int winusbx_init(int sub_api, struct libusb_context *ctx) +#define NativeWinUSBOnly_Set(fn) \ + do { \ + if (native_winusb) \ + WinUSBX[i].fn = (WinUsb_##fn##_t)GetProcAddress(h, "WinUsb_" #fn); \ + else \ + WinUSBX[i].fn = NULL; \ + } while (0) + +static int winusbx_init(struct libusb_context *ctx) { HMODULE h; bool native_winusb; @@ -2356,35 +2074,35 @@ static int winusbx_init(int sub_api, struct libusb_context *ctx) } native_winusb = (pLibK_GetProcAddress == NULL); - for (i = SUB_API_LIBUSBK; i < SUB_API_MAX; i++) { + for (i = 0; i < SUB_API_MAX; i++) { WinUSBX_Set(AbortPipe); WinUSBX_Set(ControlTransfer); WinUSBX_Set(FlushPipe); WinUSBX_Set(Free); WinUSBX_Set(GetAssociatedInterface); - WinUSBX_Set(GetCurrentAlternateSetting); - WinUSBX_Set(GetDescriptor); - WinUSBX_Set(GetOverlappedResult); - WinUSBX_Set(GetPipePolicy); - WinUSBX_Set(GetPowerPolicy); WinUSBX_Set(Initialize); - WinUSBX_Set(QueryDeviceInformation); - WinUSBX_Set(QueryInterfaceSettings); - WinUSBX_Set(QueryPipe); WinUSBX_Set(ReadPipe); + if (!native_winusb) + WinUSBX_Set(ResetDevice); WinUSBX_Set(ResetPipe); WinUSBX_Set(SetCurrentAlternateSetting); WinUSBX_Set(SetPipePolicy); - WinUSBX_Set(SetPowerPolicy); WinUSBX_Set(WritePipe); - if (!native_winusb) - WinUSBX_Set(ResetDevice); + WinUSBX_Set(IsoReadPipe); + WinUSBX_Set(IsoWritePipe); + NativeWinUSBOnly_Set(RegisterIsochBuffer); + NativeWinUSBOnly_Set(UnregisterIsochBuffer); + NativeWinUSBOnly_Set(WriteIsochPipeAsap); + NativeWinUSBOnly_Set(ReadIsochPipeAsap); + NativeWinUSBOnly_Set(QueryPipeEx); if (WinUSBX[i].Initialize != NULL) { WinUSBX[i].initialized = true; - usbi_dbg("initalized sub API %s", sub_api_name[i]); + // Assume driver supports CancelIoEx() if it is available + WinUSBX[i].CancelIoEx_supported = (pCancelIoEx != NULL); + usbi_dbg("initalized sub API %s", winusbx_driver_names[i]); } else { - usbi_warn(ctx, "Failed to initalize sub API %s", sub_api_name[i]); + usbi_warn(ctx, "Failed to initalize sub API %s", winusbx_driver_names[i]); WinUSBX[i].initialized = false; } } @@ -2393,7 +2111,7 @@ static int winusbx_init(int sub_api, struct libusb_context *ctx) return LIBUSB_SUCCESS; } -static int winusbx_exit(int sub_api) +static void winusbx_exit(void) { if (WinUSBX_handle != NULL) { FreeLibrary(WinUSBX_handle); @@ -2402,8 +2120,6 @@ static int winusbx_exit(int sub_api) /* Reset the WinUSBX API structures */ memset(&WinUSBX, 0, sizeof(WinUSBX)); } - - return LIBUSB_SUCCESS; } // NB: open and close must ensure that they only handle interface of @@ -2412,9 +2128,8 @@ static int winusbx_exit(int sub_api) static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle) { struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); HANDLE file_handle; int i; @@ -2428,7 +2143,7 @@ static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle) NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (file_handle == INVALID_HANDLE_VALUE) { usbi_err(ctx, "could not open device %s (interface %d): %s", priv->usb_interface[i].path, i, windows_error_str(0)); - switch(GetLastError()) { + switch (GetLastError()) { case ERROR_FILE_NOT_FOUND: // The device was disconnected return LIBUSB_ERROR_NO_DEVICE; case ERROR_ACCESS_DENIED: @@ -2446,8 +2161,8 @@ static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle) static void winusbx_close(int sub_api, 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); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); HANDLE handle; int i; @@ -2471,8 +2186,7 @@ static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle) CloseHandle(handle); } } - } - else { + } else { // If this is a WinUSB device, free all interfaces above interface 0, // then free and close interface 0 last for (i = 1; i < USB_MAXINTERFACES; i++) { @@ -2492,8 +2206,8 @@ static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle) static int winusbx_configure_endpoints(int sub_api, 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); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); HANDLE winusb_handle = handle_priv->interface_handle[iface].api_handle; UCHAR policy; ULONG timeout = 0; @@ -2532,6 +2246,12 @@ static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, AUTO_CLEAR_STALL, sizeof(UCHAR), &policy)) usbi_dbg("failed to enable AUTO_CLEAR_STALL for endpoint %02X", endpoint_address); + + if (sub_api == SUB_API_LIBUSBK) { + if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, + ISO_ALWAYS_START_ASAP, sizeof(UCHAR), &policy)) + usbi_dbg("failed to enable ISO_ALWAYS_START_ASAP for endpoint %02X", endpoint_address); + } } return LIBUSB_SUCCESS; @@ -2540,8 +2260,8 @@ static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) { 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); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE); SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL; HDEVINFO dev_info = INVALID_HANDLE_VALUE; @@ -2566,7 +2286,7 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev if (!WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; err = GetLastError(); - switch(err) { + switch (err) { case ERROR_BAD_COMMAND: // The device was disconnected usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(0)); @@ -2577,26 +2297,35 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev for (i = 0; ; i++) { safe_free(dev_interface_details); safe_free(dev_path_no_guid); + dev_interface_details = get_interface_details_filter(ctx, &dev_info, &dev_info_data, &GUID_DEVINTERFACE_LIBUSB0_FILTER, i, filter_path); if ((found_filter) || (dev_interface_details == NULL)) break; // ignore GUID part dev_path_no_guid = sanitize_path(strtok(dev_interface_details->DevicePath, "{")); - if (safe_strncmp(dev_path_no_guid, priv->usb_interface[iface].path, safe_strlen(dev_path_no_guid)) == 0) { + if (dev_path_no_guid == NULL) + continue; + + if (strncmp(dev_path_no_guid, priv->usb_interface[iface].path, strlen(dev_path_no_guid)) == 0) { file_handle = CreateFileA(filter_path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); - if (file_handle == INVALID_HANDLE_VALUE) { - usbi_err(ctx, "could not open device %s: %s", filter_path, windows_error_str(0)); - } else { - WinUSBX[sub_api].Free(winusb_handle); - if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) + if (file_handle != INVALID_HANDLE_VALUE) { + if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { + // Replace the existing file handle with the working one + CloseHandle(handle_priv->interface_handle[iface].dev_handle); + handle_priv->interface_handle[iface].dev_handle = file_handle; found_filter = true; - else + } else { usbi_err(ctx, "could not initialize filter driver for %s", filter_path); + CloseHandle(file_handle); + } + } else { + usbi_err(ctx, "could not open device %s: %s", filter_path, windows_error_str(0)); } } } + free(dev_interface_details); if (!found_filter) { usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(err)); return LIBUSB_ERROR_ACCESS; @@ -2622,7 +2351,7 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev if (!WinUSBX[sub_api].GetAssociatedInterface(winusb_handle, (UCHAR)(iface - 1), &handle_priv->interface_handle[iface].api_handle)) { handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; - switch(GetLastError()) { + switch (GetLastError()) { case ERROR_NO_MORE_ITEMS: // invalid iface return LIBUSB_ERROR_NOT_FOUND; case ERROR_BAD_COMMAND: // The device was disconnected @@ -2634,6 +2363,7 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev return LIBUSB_ERROR_ACCESS; } } + handle_priv->interface_handle[iface].dev_handle = handle_priv->interface_handle[0].dev_handle; } usbi_dbg("claimed interface %d", iface); handle_priv->active_interface = iface; @@ -2643,8 +2373,8 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev static int winusbx_release_interface(int sub_api, 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); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); HANDLE winusb_handle; CHECK_WINUSBX_AVAILABLE(sub_api); @@ -2664,8 +2394,8 @@ static int winusbx_release_interface(int sub_api, struct libusb_device_handle *d */ static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_id) { - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); int i; if ((api_id < USB_API_WINUSBX) || (api_id > USB_API_HID)) { @@ -2674,20 +2404,45 @@ static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_ } for (i = 0; i < USB_MAXINTERFACES; i++) { - if (HANDLE_VALID(handle_priv->interface_handle[i].dev_handle) - && HANDLE_VALID(handle_priv->interface_handle[i].api_handle) - && (priv->usb_interface[i].apib->id == api_id)) - return i; + if (HANDLE_VALID(handle_priv->interface_handle[i].dev_handle) + && HANDLE_VALID(handle_priv->interface_handle[i].api_handle) + && (priv->usb_interface[i].apib->id == api_id)) + return i; } return -1; } +/* +* Check a specific interface is valid (of the same API type), for control transfers +*/ +static int check_valid_interface(struct libusb_device_handle *dev_handle, unsigned short interface, int api_id) +{ + if (interface >= USB_MAXINTERFACES) + return -1; + + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + if ((api_id < USB_API_WINUSBX) || (api_id > USB_API_HID)) { + usbi_dbg("unsupported API ID"); + return -1; + } + + // try the requested interface + if (HANDLE_VALID(handle_priv->interface_handle[interface].dev_handle) + && HANDLE_VALID(handle_priv->interface_handle[interface].api_handle) + && (priv->usb_interface[interface].apib->id == api_id)) + return interface; + + return -1; +} + /* * Lookup interface by endpoint address. -1 if not found */ -static int interface_by_endpoint(struct windows_device_priv *priv, - struct windows_device_handle_priv *handle_priv, uint8_t endpoint_address) +static int interface_by_endpoint(struct winusb_device_priv *priv, + struct winusb_device_handle_priv *handle_priv, uint8_t endpoint_address) { int i, j; @@ -2709,18 +2464,17 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer; + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + PWINUSB_SETUP_PACKET setup = (PWINUSB_SETUP_PACKET)transfer->buffer; ULONG size; HANDLE winusb_handle; + OVERLAPPED *overlapped; int current_interface; - struct winfd wfd; CHECK_WINUSBX_AVAILABLE(sub_api); - transfer_priv->pollable_fd = INVALID_WINFD; size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; // Windows places upper limits on the control transfer size @@ -2728,45 +2482,40 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it if (size > MAX_CTRL_BUFFER_LENGTH) return LIBUSB_ERROR_INVALID_PARAM; - current_interface = get_valid_interface(transfer->dev_handle, USB_API_WINUSBX); + if ((setup->RequestType & 0x1F) == LIBUSB_RECIPIENT_INTERFACE) + current_interface = check_valid_interface(transfer->dev_handle, setup->Index & 0xff, USB_API_WINUSBX); + else + current_interface = get_valid_interface(transfer->dev_handle, USB_API_WINUSBX); if (current_interface < 0) { if (auto_claim(transfer, ¤t_interface, USB_API_WINUSBX) != LIBUSB_SUCCESS) return LIBUSB_ERROR_NOT_FOUND; } usbi_dbg("will use interface %d", current_interface); - winusb_handle = handle_priv->interface_handle[current_interface].api_handle; - wfd = usbi_create_fd(winusb_handle, RW_READ, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) - return LIBUSB_ERROR_NO_MEM; + transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle; + overlapped = transfer_priv->pollable_fd.overlapped; - // Sending of set configuration control requests from WinUSB creates issues - if (((setup->request_type & (0x03 << 5)) == LIBUSB_REQUEST_TYPE_STANDARD) - && (setup->request == LIBUSB_REQUEST_SET_CONFIGURATION)) { - if (setup->value != priv->active_config) { + // Sending of set configuration control requests from WinUSB creates issues, except when using libusb0.sys + if (sub_api != SUB_API_LIBUSB0 + && (LIBUSB_REQ_TYPE(setup->RequestType) == LIBUSB_REQUEST_TYPE_STANDARD) + && (setup->Request == LIBUSB_REQUEST_SET_CONFIGURATION)) { + if (setup->Value != priv->active_config) { usbi_warn(ctx, "cannot set configuration other than the default one"); - usbi_free_fd(&wfd); return LIBUSB_ERROR_INVALID_PARAM; } - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - wfd.overlapped->InternalHigh = 0; + windows_force_sync_completion(overlapped, 0); } else { - if (!WinUSBX[sub_api].ControlTransfer(wfd.handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, wfd.overlapped)) { + if (!WinUSBX[sub_api].ControlTransfer(winusb_handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, overlapped)) { if (GetLastError() != ERROR_IO_PENDING) { usbi_warn(ctx, "ControlTransfer failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); return LIBUSB_ERROR_IO; } } else { - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - wfd.overlapped->InternalHigh = (DWORD)size; + windows_force_sync_completion(overlapped, size); } } - // Use priv_transfer to store data needed for async polling - transfer_priv->pollable_fd = wfd; transfer_priv->interface_number = (uint8_t)current_interface; return LIBUSB_SUCCESS; @@ -2775,8 +2524,8 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) { 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); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); HANDLE winusb_handle; CHECK_WINUSBX_AVAILABLE(sub_api); @@ -2798,22 +2547,295 @@ static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_ha return LIBUSB_SUCCESS; } +static enum libusb_transfer_status usbd_status_to_libusb_transfer_status(USBD_STATUS status) +{ + /* Based on https://msdn.microsoft.com/en-us/library/windows/hardware/ff539136(v=vs.85).aspx : + * USBD_STATUS have the most significant 4 bits indicating overall status and the rest gives the details. */ + switch (status >> 28) { + case 0x00: /* USBD_STATUS_SUCCESS */ + return LIBUSB_TRANSFER_COMPLETED; + case 0x01: /* USBD_STATUS_PENDING */ + return LIBUSB_TRANSFER_COMPLETED; + default: /* USBD_STATUS_ERROR */ + switch (status & 0x0fffffff) { + case 0xC0006000: /* USBD_STATUS_TIMEOUT */ + return LIBUSB_TRANSFER_TIMED_OUT; + case 0xC0010000: /* USBD_STATUS_CANCELED */ + return LIBUSB_TRANSFER_CANCELLED; + case 0xC0000030: /* USBD_STATUS_ENDPOINT_HALTED */ + return LIBUSB_TRANSFER_STALL; + case 0xC0007000: /* USBD_STATUS_DEVICE_GONE */ + return LIBUSB_TRANSFER_NO_DEVICE; + default: + usbi_dbg("USBD_STATUS 0x%08x translated to LIBUSB_TRANSFER_ERROR", status); + return LIBUSB_TRANSFER_ERROR; + } + } +} + +static void WINAPI winusbx_native_iso_transfer_continue_stream_callback(struct libusb_transfer *transfer) +{ + // If this callback is invoked, this means that we attempted to set ContinueStream + // to TRUE when calling Read/WriteIsochPipeAsap in winusbx_do_iso_transfer. + // The role of this callback is to fallback to ContinueStream = FALSE if the transfer + // did not succeed. + + struct winusb_transfer_priv *transfer_priv = (struct winusb_transfer_priv *) + usbi_transfer_get_os_priv(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)); + BOOL fallback = (transfer->status != LIBUSB_TRANSFER_COMPLETED); + int idx; + + // Restore the user callback + transfer->callback = transfer_priv->iso_user_callback; + + for (idx = 0; idx < transfer->num_iso_packets && !fallback; ++idx) { + if (transfer->iso_packet_desc[idx].status != LIBUSB_TRANSFER_COMPLETED) { + fallback = TRUE; + } + } + + if (!fallback) { + // If the transfer was successful, we restore the user callback and call it. + if (transfer->callback) { + transfer->callback(transfer); + } + } + else { + // If the transfer wasn't successful we reschedule the transfer while forcing it + // not to continue the stream. This might results in a 5-ms delay. + transfer_priv->iso_break_stream = TRUE; + libusb_submit_transfer(transfer); + } +} +static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + HANDLE winusb_handle; + OVERLAPPED *overlapped; + bool ret; + int current_interface; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + 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; + } else { + usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface); + } + + transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle; + overlapped = transfer_priv->pollable_fd.overlapped; + + if ((sub_api == SUB_API_LIBUSBK) || (sub_api == SUB_API_LIBUSB0)) { + int i; + UINT offset; + size_t iso_ctx_size; + PKISO_CONTEXT iso_context; + + iso_ctx_size = sizeof(KISO_CONTEXT) + (transfer->num_iso_packets * sizeof(KISO_PACKET)); + transfer_priv->iso_context = iso_context = calloc(1, iso_ctx_size); + if (transfer_priv->iso_context == NULL) + return LIBUSB_ERROR_NO_MEM; + + // start ASAP + iso_context->StartFrame = 0; + iso_context->NumberOfPackets = (SHORT)transfer->num_iso_packets; + + // convert the transfer packet lengths to iso_packet offsets + offset = 0; + for (i = 0; i < transfer->num_iso_packets; i++) { + iso_context->IsoPackets[i].offset = offset; + offset += transfer->iso_packet_desc[i].length; + } + + if (IS_XFERIN(transfer)) { + usbi_dbg("reading %d iso packets", transfer->num_iso_packets); + ret = WinUSBX[sub_api].IsoReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, overlapped, iso_context); + } else { + usbi_dbg("writing %d iso packets", transfer->num_iso_packets); + ret = WinUSBX[sub_api].IsoWritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, overlapped, iso_context); + } + + if (!ret) { + if (GetLastError() != ERROR_IO_PENDING) { + usbi_err(ctx, "IsoReadPipe/IsoWritePipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_IO; + } + } else { + windows_force_sync_completion(overlapped, (ULONG)transfer->length); + } + + transfer_priv->interface_number = (uint8_t)current_interface; + + return LIBUSB_SUCCESS; + } + else if (sub_api == SUB_API_WINUSB) { + WINUSB_PIPE_INFORMATION_EX pipe_info_ex = { 0 }; + WINUSB_ISOCH_BUFFER_HANDLE buffer_handle; + ULONG iso_transfer_size_multiple; + int out_transfer_length = 0; + int idx; + +# define WINUSBX_CHECK_API_SUPPORTED(API) \ + if (WinUSBX[sub_api].API == NULL) \ + { \ + usbi_dbg(#API " isn't available"); \ + return LIBUSB_ERROR_NOT_SUPPORTED; \ + } + + // Depending on the version of Microsoft WinUSB, isochronous transfers may not be supported. + WINUSBX_CHECK_API_SUPPORTED(RegisterIsochBuffer); + WINUSBX_CHECK_API_SUPPORTED(ReadIsochPipeAsap); + WINUSBX_CHECK_API_SUPPORTED(WriteIsochPipeAsap); + WINUSBX_CHECK_API_SUPPORTED(UnregisterIsochBuffer); + WINUSBX_CHECK_API_SUPPORTED(QueryPipeEx); + + if (sizeof(struct libusb_iso_packet_descriptor) != sizeof(USBD_ISO_PACKET_DESCRIPTOR)) { + usbi_dbg("The size of Microsoft WinUsb and libusb isochronous packet descriptor doesn't match."); + return LIBUSB_ERROR_NOT_SUPPORTED; + } + + // Query the pipe extended information to find the pipe index corresponding to the endpoint. + for (idx = 0; idx < priv->usb_interface[current_interface].nb_endpoints; ++idx) { + ret = WinUSBX[sub_api].QueryPipeEx(winusb_handle, (UINT8)priv->usb_interface[current_interface].current_altsetting, (UCHAR)idx, &pipe_info_ex); + if (!ret) { + usbi_dbg("Couldn't query interface settings for USB pipe with index %d. Error: %s", idx, windows_error_str(0)); + return LIBUSB_ERROR_NOT_FOUND; + } + + if (pipe_info_ex.PipeId == transfer->endpoint && pipe_info_ex.PipeType == UsbdPipeTypeIsochronous) { + break; + } + } + + // Make sure we found the index. + if (idx >= priv->usb_interface[current_interface].nb_endpoints) { + usbi_dbg("Couldn't find the isochronous endpoint %02x.", transfer->endpoint); + return LIBUSB_ERROR_NOT_FOUND; + } + + if (IS_XFERIN(transfer)) { + int interval = pipe_info_ex.Interval; + + // For high-speed and SuperSpeed device, the interval is 2**(bInterval-1). + if (libusb_get_device_speed(libusb_get_device(transfer->dev_handle)) >= LIBUSB_SPEED_HIGH) { + interval = (1 << (pipe_info_ex.Interval - 1)); + } + + // WinUSB only supports isochronous transfers spanning a full USB frames. Later, we might be smarter about this + // and allocate a temporary buffer. However, this is harder than it seems as its destruction would depend on overlapped + // IO... + iso_transfer_size_multiple = (pipe_info_ex.MaximumBytesPerInterval * 8) / interval; + if (transfer->length % iso_transfer_size_multiple != 0) { + usbi_dbg("The length of isochronous buffer must be a multiple of the MaximumBytesPerInterval * 8 / Interval"); + return LIBUSB_ERROR_INVALID_PARAM; + } + } + else { + // If this is an OUT transfer, we make sure the isochronous packets are contiguous as this isn't supported otherwise. + BOOL size_should_be_zero = FALSE; + out_transfer_length = 0; + for (idx = 0; idx < transfer->num_iso_packets; ++idx) { + if ((size_should_be_zero && transfer->iso_packet_desc[idx].length != 0) || + (transfer->iso_packet_desc[idx].length != pipe_info_ex.MaximumBytesPerInterval && idx + 1 < transfer->num_iso_packets && transfer->iso_packet_desc[idx + 1].length > 0)) { + usbi_dbg("Isochronous packets for OUT transfer with Microsoft WinUSB must be contiguous in memory."); + return LIBUSB_ERROR_INVALID_PARAM; + } + + size_should_be_zero = (transfer->iso_packet_desc[idx].length == 0); + out_transfer_length += transfer->iso_packet_desc[idx].length; + } + } + + if (transfer_priv->isoch_buffer_handle != NULL) { + if (WinUSBX[sub_api].UnregisterIsochBuffer(transfer_priv->isoch_buffer_handle)) { + transfer_priv->isoch_buffer_handle = NULL; + } else { + usbi_dbg("Couldn't unregister the Microsoft WinUSB isochronous buffer: %s", windows_error_str(0)); + return LIBUSB_ERROR_OTHER; + } + } + + // Register the isochronous buffer to the operating system. + ret = WinUSBX[sub_api].RegisterIsochBuffer(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, &buffer_handle); + if (!ret) { + usbi_dbg("Microsoft WinUSB refused to allocate an isochronous buffer."); + return LIBUSB_ERROR_NO_MEM; + } + + // Important note: the WinUSB_Read/WriteIsochPipeAsap API requires a ContinueStream parameter that tells whether the isochronous + // stream must be continued or if the WinUSB driver can schedule the transfer at its conveniance. Profiling subsequent transfers + // with ContinueStream = FALSE showed that 5 frames, i.e. about 5 milliseconds, were left empty between each transfer. This + // is critical as this greatly diminish the achievable isochronous bandwidth. We solved the problem using the following strategy: + // - Transfers are first scheduled with ContinueStream = TRUE and with winusbx_iso_transfer_continue_stream_callback as user callback. + // - If the transfer succeeds, winusbx_iso_transfer_continue_stream_callback restore the user callback and calls its. + // - If the transfer fails, winusbx_iso_transfer_continue_stream_callback reschedule the transfer and force ContinueStream = FALSE. + if (!transfer_priv->iso_break_stream) { + transfer_priv->iso_user_callback = transfer->callback; + transfer->callback = winusbx_native_iso_transfer_continue_stream_callback; + } + + // Initiate the transfers. + if (IS_XFERIN(transfer)) { + ret = WinUSBX[sub_api].ReadIsochPipeAsap(buffer_handle, 0, transfer->length, !transfer_priv->iso_break_stream, transfer->num_iso_packets, (PUSBD_ISO_PACKET_DESCRIPTOR)transfer->iso_packet_desc, overlapped); + } + else { + ret = WinUSBX[sub_api].WriteIsochPipeAsap(buffer_handle, 0, out_transfer_length, !transfer_priv->iso_break_stream, overlapped); + } + + // Restore the ContinueStream parameter to TRUE. + transfer_priv->iso_break_stream = FALSE; + + if (!ret) { + if (GetLastError() == ERROR_IO_PENDING) { + transfer_priv->isoch_buffer_handle = buffer_handle; + } else { + usbi_err(ctx, "ReadIsochPipeAsap/WriteIsochPipeAsap failed: %s", windows_error_str(0)); + if (WinUSBX[sub_api].UnregisterIsochBuffer(buffer_handle)) { + transfer_priv->isoch_buffer_handle = NULL; + return LIBUSB_ERROR_IO; + } else { + usbi_dbg("Couldn't unregister the Microsoft WinUSB isochronous buffer: %s", windows_error_str(0)); + return LIBUSB_ERROR_OTHER; + } + } + } else { + windows_force_sync_completion(overlapped, (ULONG)transfer->length); + if (!WinUSBX[sub_api].UnregisterIsochBuffer(buffer_handle)) { + usbi_dbg("Couldn't unregister the Microsoft WinUSB isochronous buffer: %s", windows_error_str(0)); + return LIBUSB_ERROR_OTHER; + } + } + + transfer_priv->interface_number = (uint8_t)current_interface; + + return LIBUSB_SUCCESS; + } else { + PRINT_UNSUPPORTED_API(winusbx_submit_iso_transfer); + return LIBUSB_ERROR_NOT_SUPPORTED; + } +} + static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); HANDLE winusb_handle; + OVERLAPPED *overlapped; bool ret; int current_interface; - struct winfd wfd; CHECK_WINUSBX_AVAILABLE(sub_api); - transfer_priv->pollable_fd = INVALID_WINFD; - 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"); @@ -2822,33 +2844,26 @@ static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itran usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface); - winusb_handle = handle_priv->interface_handle[current_interface].api_handle; - - wfd = usbi_create_fd(winusb_handle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) - return LIBUSB_ERROR_NO_MEM; + transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle; + overlapped = transfer_priv->pollable_fd.overlapped; if (IS_XFERIN(transfer)) { usbi_dbg("reading %d bytes", transfer->length); - ret = WinUSBX[sub_api].ReadPipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped); + ret = WinUSBX[sub_api].ReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped); } else { usbi_dbg("writing %d bytes", transfer->length); - ret = WinUSBX[sub_api].WritePipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped); + ret = WinUSBX[sub_api].WritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped); } if (!ret) { if (GetLastError() != ERROR_IO_PENDING) { usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); return LIBUSB_ERROR_IO; } } else { - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - wfd.overlapped->InternalHigh = (DWORD)transfer->length; + windows_force_sync_completion(overlapped, (ULONG)transfer->length); } - transfer_priv->pollable_fd = wfd; transfer_priv->interface_number = (uint8_t)current_interface; return LIBUSB_SUCCESS; @@ -2857,8 +2872,8 @@ static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itran static int winusbx_clear_halt(int sub_api, 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); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); HANDLE winusb_handle; int current_interface; @@ -2897,10 +2912,10 @@ static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - HANDLE winusb_handle; + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + HANDLE handle; int current_interface; CHECK_WINUSBX_AVAILABLE(sub_api); @@ -2912,9 +2927,21 @@ static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer) } usbi_dbg("will use interface %d", current_interface); - winusb_handle = handle_priv->interface_handle[current_interface].api_handle; + if (WinUSBX[sub_api].CancelIoEx_supported) { + // Try to use CancelIoEx if available to cancel just a single transfer + handle = handle_priv->interface_handle[current_interface].dev_handle; + if (pCancelIoEx(handle, transfer_priv->pollable_fd.overlapped)) + return LIBUSB_SUCCESS; + else if (GetLastError() == ERROR_NOT_FOUND) + return LIBUSB_ERROR_NOT_FOUND; - if (!WinUSBX[sub_api].AbortPipe(winusb_handle, transfer->endpoint)) { + // Not every driver implements the necessary functionality for CancelIoEx + usbi_warn(ctx, "CancelIoEx not supported for sub API %s", winusbx_driver_names[sub_api]); + WinUSBX[sub_api].CancelIoEx_supported = false; + } + + handle = handle_priv->interface_handle[current_interface].api_handle; + if (!WinUSBX[sub_api].AbortPipe(handle, transfer->endpoint)) { usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); return LIBUSB_ERROR_NO_DEVICE; } @@ -2934,9 +2961,8 @@ static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer) static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle) { 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); - struct winfd wfd; + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); HANDLE winusb_handle; int i, j; @@ -2945,13 +2971,6 @@ static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_ha // Reset any available pipe (except control) for (i = 0; i < USB_MAXINTERFACES; i++) { winusb_handle = handle_priv->interface_handle[i].api_handle; - for (wfd = handle_to_winfd(winusb_handle); wfd.fd > 0; ) { - // Cancel any pollable I/O - usbi_remove_pollfd(ctx, wfd.fd); - usbi_free_fd(&wfd); - wfd = handle_to_winfd(winusb_handle); - } - if (HANDLE_VALID(winusb_handle)) { for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) { usbi_dbg("resetting ep %02X", priv->usb_interface[i].endpoint[j]); @@ -2984,6 +3003,53 @@ static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_ha static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) { + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + PKISO_CONTEXT iso_context; + int i; + + if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { + CHECK_WINUSBX_AVAILABLE(sub_api); + + // for isochronous, need to copy the individual iso packet actual_lengths and statuses + if ((sub_api == SUB_API_LIBUSBK) || (sub_api == SUB_API_LIBUSB0)) { + // iso only supported on libusbk-based backends for now + iso_context = transfer_priv->iso_context; + for (i = 0; i < transfer->num_iso_packets; i++) { + transfer->iso_packet_desc[i].actual_length = iso_context->IsoPackets[i].actual_length; + // TODO translate USDB_STATUS codes http://msdn.microsoft.com/en-us/library/ff539136(VS.85).aspx to libusb_transfer_status + //transfer->iso_packet_desc[i].status = transfer_priv->iso_context->IsoPackets[i].status; + } + } else if (sub_api == SUB_API_WINUSB) { + if (IS_XFERIN(transfer)) { + /* Convert isochronous packet descriptor between Windows and libusb representation. + * Both representation are guaranteed to have the same length in bytes.*/ + PUSBD_ISO_PACKET_DESCRIPTOR usbd_iso_packet_desc = (PUSBD_ISO_PACKET_DESCRIPTOR)transfer->iso_packet_desc; + for (i = 0; i < transfer->num_iso_packets; ++i) + { + int length = (i < transfer->num_iso_packets - 1) ? (usbd_iso_packet_desc[i + 1].Offset - usbd_iso_packet_desc[i].Offset) : usbd_iso_packet_desc[i].Length; + int actual_length = usbd_iso_packet_desc[i].Length; + USBD_STATUS status = usbd_iso_packet_desc[i].Status; + + transfer->iso_packet_desc[i].length = length; + transfer->iso_packet_desc[i].actual_length = actual_length; + transfer->iso_packet_desc[i].status = usbd_status_to_libusb_transfer_status(status); + } + } + else { + for (i = 0; i < transfer->num_iso_packets; ++i) + { + transfer->iso_packet_desc[i].status = LIBUSB_TRANSFER_COMPLETED; + } + } + } else { + // This should only occur if backend is not set correctly or other backend isoc is partially implemented + PRINT_UNSUPPORTED_API(copy_transfer_data); + return LIBUSB_ERROR_NOT_SUPPORTED; + } + } + itransfer->transferred += io_size; return LIBUSB_TRANSFER_COMPLETED; } @@ -3108,9 +3174,10 @@ static int _hid_get_config_descriptor(struct hid_device_priv *dev, void *data, s } static int _hid_get_string_descriptor(struct hid_device_priv *dev, int _index, - void *data, size_t *size) + void *data, size_t *size, HANDLE hid_handle) { void *tmp = NULL; + WCHAR string[MAX_USB_STRING_LENGTH]; size_t tmp_size = 0; int i; @@ -3132,8 +3199,12 @@ static int _hid_get_string_descriptor(struct hid_device_priv *dev, int _index, } } - if (i == 3) // not found - return LIBUSB_ERROR_INVALID_PARAM; + if (i == 3) { + if (!HidD_GetIndexedString(hid_handle, _index, string, sizeof(string))) + return LIBUSB_ERROR_INVALID_PARAM; + tmp = string; + tmp_size = (_hid_wcslen(string) + 1) * sizeof(WCHAR); + } } if (!tmp_size) @@ -3178,10 +3249,10 @@ static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, s 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; + /* usage page */ + d[i++] = 0x06; d[i++] = dev->usagePage & 0xFF; d[i++] = dev->usagePage >> 8; + /* usage */ + d[i++] = 0x09; d[i++] = (uint8_t)dev->usage; /* start collection (application) */ d[i++] = 0xA1; d[i++] = 0x01; /* input report */ @@ -3243,7 +3314,7 @@ static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, s 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) { + switch (type) { case LIBUSB_DT_DEVICE: usbi_dbg("LIBUSB_DT_DEVICE"); return _hid_get_device_descriptor(dev, data, size); @@ -3254,7 +3325,7 @@ static int _hid_get_descriptor(struct hid_device_priv *dev, HANDLE hid_handle, i return LIBUSB_ERROR_INVALID_PARAM; case LIBUSB_DT_STRING: usbi_dbg("LIBUSB_DT_STRING"); - return _hid_get_string_descriptor(dev, _index, data, size); + return _hid_get_string_descriptor(dev, _index, data, size, hid_handle); case LIBUSB_DT_HID: usbi_dbg("LIBUSB_DT_HID"); if (!_index) @@ -3277,7 +3348,7 @@ static int _hid_get_descriptor(struct hid_device_priv *dev, HANDLE hid_handle, i } 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) + struct winusb_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type) { uint8_t *buf; DWORD ioctl_code, read_size, expected_size = (DWORD)*size; @@ -3319,7 +3390,7 @@ static int _hid_get_report(struct hid_device_priv *dev, HANDLE hid_handle, int i 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); + free(buf); return LIBUSB_ERROR_IO; } // Asynchronous wait @@ -3350,20 +3421,22 @@ static int _hid_get_report(struct hid_device_priv *dev, HANDLE hid_handle, int i memcpy(data, buf, *size); } - safe_free(buf); + 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) + struct winusb_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type) { uint8_t *buf = NULL; DWORD ioctl_code, write_size = (DWORD)*size; + // If an id is reported, we must allow MAX_HID_REPORT_SIZE + 1 + size_t max_report_size = MAX_HID_REPORT_SIZE + (id ? 1 : 0); if (tp->hid_buffer != NULL) usbi_dbg("program assertion failed: hid_buffer is not NULL"); - if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) { + if ((*size == 0) || (*size > max_report_size)) { usbi_dbg("invalid size (%u)", *size); return LIBUSB_ERROR_INVALID_PARAM; } @@ -3406,7 +3479,7 @@ static int _hid_set_report(struct hid_device_priv *dev, HANDLE hid_handle, int i 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); + free(buf); return LIBUSB_ERROR_IO; } tp->hid_buffer = buf; @@ -3419,12 +3492,12 @@ static int _hid_set_report(struct hid_device_priv *dev, HANDLE hid_handle, int i if (write_size == 0) usbi_dbg("program assertion failed - write completed synchronously, but no data was written"); - safe_free(buf); + 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, + int request, int value, int _index, void *data, struct winusb_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped) { int report_type = (value >> 8) & 0xFF; @@ -3447,9 +3520,10 @@ static int _hid_class_request(struct hid_device_priv *dev, HANDLE hid_handle, in /* * HID API functions */ -static int hid_init(int sub_api, struct libusb_context *ctx) +static int hid_init(struct libusb_context *ctx) { DLL_GET_HANDLE(hid); + DLL_LOAD_FUNC(hid, HidD_GetAttributes, TRUE); DLL_LOAD_FUNC(hid, HidD_GetHidGuid, TRUE); DLL_LOAD_FUNC(hid, HidD_GetPreparsedData, TRUE); @@ -3457,13 +3531,10 @@ static int hid_init(int sub_api, struct libusb_context *ctx) DLL_LOAD_FUNC(hid, HidD_GetManufacturerString, TRUE); DLL_LOAD_FUNC(hid, HidD_GetProductString, TRUE); DLL_LOAD_FUNC(hid, HidD_GetSerialNumberString, TRUE); + DLL_LOAD_FUNC(hid, HidD_GetIndexedString, TRUE); DLL_LOAD_FUNC(hid, HidP_GetCaps, TRUE); DLL_LOAD_FUNC(hid, HidD_SetNumInputBuffers, TRUE); - DLL_LOAD_FUNC(hid, HidD_SetFeature, TRUE); - DLL_LOAD_FUNC(hid, HidD_GetFeature, TRUE); DLL_LOAD_FUNC(hid, HidD_GetPhysicalDescriptor, TRUE); - DLL_LOAD_FUNC(hid, HidD_GetInputReport, FALSE); - DLL_LOAD_FUNC(hid, HidD_SetOutputReport, FALSE); DLL_LOAD_FUNC(hid, HidD_FlushQueue, TRUE); DLL_LOAD_FUNC(hid, HidP_GetValueCaps, TRUE); @@ -3471,11 +3542,9 @@ static int hid_init(int sub_api, struct libusb_context *ctx) return LIBUSB_SUCCESS; } -static int hid_exit(int sub_api) +static void hid_exit(void) { DLL_FREE_HANDLE(hid); - - return LIBUSB_SUCCESS; } // NB: open and close must ensure that they only handle interface of @@ -3484,8 +3553,8 @@ static int hid_exit(int sub_api) static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) { struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); HIDD_ATTRIBUTES hid_attributes; PHIDP_PREPARSED_DATA preparsed_data = NULL; HIDP_CAPS capabilities; @@ -3496,7 +3565,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) ULONG size[3]; int nb_ids[2]; // zero and nonzero report IDs #if defined(ENABLE_LOGGING) - const char *type[3] = {"input", "output", "feature"}; + const char * const type[3] = {"input", "output", "feature"}; #endif CHECK_HID_AVAILABLE; @@ -3524,7 +3593,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) 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()) { + switch (GetLastError()) { case ERROR_FILE_NOT_FOUND: // The device was disconnected return LIBUSB_ERROR_NO_DEVICE; case ERROR_ACCESS_DENIED: @@ -3593,7 +3662,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) } else { usbi_warn(ctx, " could not process %s report IDs", type[j]); } - safe_free(value_caps); + free(value_caps); } } @@ -3602,6 +3671,10 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) priv->hid->output_report_size = capabilities.OutputReportByteLength; priv->hid->feature_report_size = capabilities.FeatureReportByteLength; + // Store usage and usagePage values + priv->hid->usage = capabilities.Usage; + priv->hid->usagePage = capabilities.UsagePage; + // Fetch string descriptors priv->hid->string_index[0] = priv->dev_descriptor.iManufacturer; if (priv->hid->string_index[0] != 0) @@ -3620,7 +3693,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) HidD_GetSerialNumberString(hid_handle, priv->hid->string[2], sizeof(priv->hid->string[2])); else priv->hid->string[2][0] = 0; - } while(0); + } while (0); if (preparsed_data) HidD_FreePreparsedData(preparsed_data); @@ -3630,8 +3703,8 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) static void hid_close(int sub_api, 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); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); HANDLE file_handle; int i; @@ -3649,8 +3722,8 @@ static void hid_close(int sub_api, struct libusb_device_handle *dev_handle) static int hid_claim_interface(int sub_api, 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); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); CHECK_HID_AVAILABLE; @@ -3662,7 +3735,6 @@ static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_han 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); @@ -3673,8 +3745,8 @@ static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_han static int hid_release_interface(int sub_api, 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); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); CHECK_HID_AVAILABLE; @@ -3709,20 +3781,19 @@ static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = 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 winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + struct winusb_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; + OVERLAPPED *overlapped; 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; @@ -3737,21 +3808,19 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans } usbi_dbg("will use interface %d", current_interface); - hid_handle = handle_priv->interface_handle[current_interface].api_handle; - // Always use the handle returned from usbi_create_fd (wfd.handle) - wfd = usbi_create_fd(hid_handle, RW_READ, NULL, NULL); - if (wfd.fd < 0) - return LIBUSB_ERROR_NOT_FOUND; - switch(LIBUSB_REQ_TYPE(setup->request_type)) { + hid_handle = handle_priv->interface_handle[current_interface].api_handle; + overlapped = transfer_priv->pollable_fd.overlapped; + + switch (LIBUSB_REQ_TYPE(setup->RequestType)) { case LIBUSB_REQUEST_TYPE_STANDARD: - switch(setup->request) { + 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); + r = _hid_get_descriptor(priv->hid, hid_handle, LIBUSB_REQ_RECIPIENT(setup->RequestType), + (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); + r = winusb_get_configuration(transfer->dev_handle, &config); if (r == LIBUSB_SUCCESS) { size = 1; ((uint8_t *)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = (uint8_t)config; @@ -3759,7 +3828,7 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans } break; case LIBUSB_REQUEST_SET_CONFIGURATION: - if (setup->value == priv->active_config) { + if (setup->Value == priv->active_config) { r = LIBUSB_COMPLETED; } else { usbi_warn(ctx, "cannot set configuration other than the default one"); @@ -3772,56 +3841,48 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans r = LIBUSB_COMPLETED; break; case LIBUSB_REQUEST_SET_INTERFACE: - r = hid_set_interface_altsetting(0, transfer->dev_handle, setup->index, setup->value); + r = hid_set_interface_altsetting(0, 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_NOT_SUPPORTED; - break; + return LIBUSB_ERROR_NOT_SUPPORTED; } 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); + r = _hid_class_request(priv->hid, hid_handle, setup->RequestType, setup->Request, setup->Value, + setup->Index, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, transfer_priv, + &size, overlapped); break; default: usbi_warn(ctx, "unsupported HID control request"); - r = LIBUSB_ERROR_NOT_SUPPORTED; - break; + return LIBUSB_ERROR_NOT_SUPPORTED; } + if (r < 0) + return r; + 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; + windows_force_sync_completion(overlapped, (ULONG)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); - } + transfer_priv->interface_number = (uint8_t)current_interface; - return r; + return LIBUSB_SUCCESS; } static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - struct winfd wfd; + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); HANDLE hid_handle; + OVERLAPPED *overlapped; bool direction_in, ret; int current_interface, length; DWORD size; @@ -3829,7 +3890,6 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer CHECK_HID_AVAILABLE; - transfer_priv->pollable_fd = INVALID_WINFD; transfer_priv->hid_dest = NULL; safe_free(transfer_priv->hid_buffer); @@ -3841,13 +3901,9 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer 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?RW_READ:RW_WRITE, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) - return LIBUSB_ERROR_NO_MEM; + transfer_priv->handle = hid_handle = handle_priv->interface_handle[current_interface].api_handle; + overlapped = transfer_priv->pollable_fd.overlapped; + direction_in = IS_XFERIN(transfer); // If report IDs are not in use, an extra prefix byte must be added if (((direction_in) && (!priv->hid->uses_report_ids[0])) @@ -3866,7 +3922,7 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer if (direction_in) { transfer_priv->hid_dest = transfer->buffer; usbi_dbg("reading %d bytes (report ID: 0x00)", length); - ret = ReadFile(wfd.handle, transfer_priv->hid_buffer, length + 1, &size, wfd.overlapped); + ret = ReadFile(hid_handle, transfer_priv->hid_buffer, length + 1, &size, overlapped); } else { if (!priv->hid->uses_report_ids[1]) memcpy(transfer_priv->hid_buffer + 1, transfer->buffer, transfer->length); @@ -3875,13 +3931,12 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer 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); + ret = WriteFile(hid_handle, transfer_priv->hid_buffer, length, &size, overlapped); } if (!ret) { if (GetLastError() != ERROR_IO_PENDING) { usbi_err(ctx, "HID transfer failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); safe_free(transfer_priv->hid_buffer); return LIBUSB_ERROR_IO; } @@ -3899,11 +3954,9 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer usbi_err(ctx, "OVERFLOW!"); r = LIBUSB_ERROR_OVERFLOW; } - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - wfd.overlapped->InternalHigh = size; + windows_force_sync_completion(overlapped, (ULONG)size); } - transfer_priv->pollable_fd = wfd; transfer_priv->interface_number = (uint8_t)current_interface; return r; @@ -3911,24 +3964,40 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer) { + struct libusb_context *ctx = ITRANSFER_CTX(itransfer); struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_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); + if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) { + usbi_err(ctx, "program assertion failed: invalid interface_number"); + return LIBUSB_ERROR_NOT_FOUND; + } + usbi_dbg("will use interface %d", current_interface); - return LIBUSB_SUCCESS; + hid_handle = handle_priv->interface_handle[current_interface].api_handle; + + if (pCancelIoEx != NULL) { + // Use CancelIoEx if available to cancel just a single transfer + if (pCancelIoEx(hid_handle, transfer_priv->pollable_fd.overlapped)) + return LIBUSB_SUCCESS; + } else { + if (CancelIo(hid_handle)) + return LIBUSB_SUCCESS; + } + + usbi_warn(ctx, "cancel failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NOT_FOUND; } static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle) { - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); HANDLE hid_handle; int current_interface; @@ -3947,8 +4016,8 @@ static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle static int hid_clear_halt(int sub_api, 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); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); HANDLE hid_handle; int current_interface; @@ -3979,7 +4048,7 @@ static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); int r = LIBUSB_TRANSFER_COMPLETED; uint32_t corrected_size = io_size; @@ -4016,19 +4085,9 @@ static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, /* * Composite API functions */ -static int composite_init(int sub_api, struct libusb_context *ctx) -{ - return LIBUSB_SUCCESS; -} - -static int composite_exit(int sub_api) -{ - return LIBUSB_SUCCESS; -} - static int composite_open(int sub_api, struct libusb_device_handle *dev_handle) { - struct windows_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); int r = LIBUSB_ERROR_NOT_FOUND; uint8_t i; // SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID @@ -4064,7 +4123,7 @@ static int composite_open(int sub_api, struct libusb_device_handle *dev_handle) static void composite_close(int sub_api, struct libusb_device_handle *dev_handle) { - struct windows_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); uint8_t i; // SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID bool available[SUB_API_MAX + 1] = { 0 }; @@ -4094,7 +4153,9 @@ static void composite_close(int sub_api, struct libusb_device_handle *dev_handle static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) { - struct windows_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, claim_interface); return priv->usb_interface[iface].apib-> claim_interface(priv->usb_interface[iface].sub_api, dev_handle, iface); @@ -4102,7 +4163,9 @@ static int composite_claim_interface(int sub_api, struct libusb_device_handle *d static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) { - struct windows_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, set_interface_altsetting); return priv->usb_interface[iface].apib-> set_interface_altsetting(priv->usb_interface[iface].sub_api, dev_handle, iface, altsetting); @@ -4110,7 +4173,9 @@ static int composite_set_interface_altsetting(int sub_api, struct libusb_device_ static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) { - struct windows_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, release_interface); return priv->usb_interface[iface].apib-> release_interface(priv->usb_interface[iface].sub_api, dev_handle, iface); @@ -4120,7 +4185,7 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer * { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); struct libusb_config_descriptor *conf_desc; WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer; int iface, pass, r; @@ -4128,14 +4193,14 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer * // Interface shouldn't matter for control, but it does in practice, with Windows' // restrictions with regards to accessing HID keyboards and mice. Try to target // a specific interface first, if possible. - switch (LIBUSB_REQ_RECIPIENT(setup->request_type)) { + switch (LIBUSB_REQ_RECIPIENT(setup->RequestType)) { case LIBUSB_RECIPIENT_INTERFACE: - iface = setup->index & 0xFF; + iface = setup->Index & 0xFF; break; case LIBUSB_RECIPIENT_ENDPOINT: r = libusb_get_active_config_descriptor(transfer->dev_handle->dev, &conf_desc); if (r == LIBUSB_SUCCESS) { - iface = get_interface_by_endpoint(conf_desc, (setup->index & 0xFF)); + iface = get_interface_by_endpoint(conf_desc, (setup->Index & 0xFF)); libusb_free_config_descriptor(conf_desc); break; } @@ -4148,7 +4213,8 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer * // Try and target a specific interface if the control setup indicates such if ((iface >= 0) && (iface < USB_MAXINTERFACES)) { usbi_dbg("attempting control transfer targeted to interface %d", iface); - if (priv->usb_interface[iface].path != NULL) { + if ((priv->usb_interface[iface].path != NULL) + && (priv->usb_interface[iface].apib->submit_control_transfer != NULL)) { r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer); if (r == LIBUSB_SUCCESS) return r; @@ -4159,7 +4225,8 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer * // Try a 2 pass approach with all interfaces. for (pass = 0; pass < 2; pass++) { for (iface = 0; iface < USB_MAXINTERFACES; iface++) { - if (priv->usb_interface[iface].path != NULL) { + if ((priv->usb_interface[iface].path != NULL) + && (priv->usb_interface[iface].apib->submit_control_transfer != NULL)) { if ((pass == 0) && (priv->usb_interface[iface].restricted_functionality)) { usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)", iface); continue; @@ -4181,8 +4248,8 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer * static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); int current_interface; current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); @@ -4191,6 +4258,8 @@ static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itr return LIBUSB_ERROR_NOT_FOUND; } + CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, submit_bulk_transfer); + return priv->usb_interface[current_interface].apib-> submit_bulk_transfer(priv->usb_interface[current_interface].sub_api, itransfer); } @@ -4198,8 +4267,8 @@ static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itr static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); int current_interface; current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); @@ -4208,6 +4277,8 @@ static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itra return LIBUSB_ERROR_NOT_FOUND; } + CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, submit_iso_transfer); + return priv->usb_interface[current_interface].apib-> submit_iso_transfer(priv->usb_interface[current_interface].sub_api, itransfer); } @@ -4215,8 +4286,8 @@ static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itra static int composite_clear_halt(int sub_api, 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); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); int current_interface; current_interface = interface_by_endpoint(priv, handle_priv, endpoint); @@ -4225,6 +4296,8 @@ static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_ha return LIBUSB_ERROR_NOT_FOUND; } + CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, clear_halt); + return priv->usb_interface[current_interface].apib-> clear_halt(priv->usb_interface[current_interface].sub_api, dev_handle, endpoint); } @@ -4232,26 +4305,42 @@ static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_ha static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int current_interface = transfer_priv->interface_number; - return priv->usb_interface[transfer_priv->interface_number].apib-> - abort_control(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer); + if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) { + usbi_err(TRANSFER_CTX(transfer), "program assertion failed: invalid interface_number"); + return LIBUSB_ERROR_NOT_FOUND; + } + + CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, abort_control); + + return priv->usb_interface[current_interface].apib-> + abort_control(priv->usb_interface[current_interface].sub_api, itransfer); } static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int current_interface = transfer_priv->interface_number; - return priv->usb_interface[transfer_priv->interface_number].apib-> - abort_transfers(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer); + if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) { + usbi_err(TRANSFER_CTX(transfer), "program assertion failed: invalid interface_number"); + return LIBUSB_ERROR_NOT_FOUND; + } + + CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, abort_transfers); + + return priv->usb_interface[current_interface].apib-> + abort_transfers(priv->usb_interface[current_interface].sub_api, itransfer); } static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle) { - struct windows_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); int r; uint8_t i; bool available[SUB_API_MAX]; @@ -4279,19 +4368,12 @@ static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_ static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int current_interface = transfer_priv->interface_number; - return priv->usb_interface[transfer_priv->interface_number].apib-> - copy_transfer_data(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer, io_size); -} + CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, copy_transfer_data); -static void backend_init(void) -{ - win_backend backend; - backend.clear_transfer_priv = windows_clear_transfer_priv; - backend.copy_transfer_data = windows_copy_transfer_data; - backend.get_fd = windows_get_fd; - backend.get_overlapped_result = windows_get_overlapped_result; - win_nt_init(&backend); + return priv->usb_interface[current_interface].apib-> + copy_transfer_data(priv->usb_interface[current_interface].sub_api, itransfer, io_size); } diff --git a/Externals/libusb/libusb/os/windows_winusb.h b/Externals/libusb/libusb/os/windows_winusb.h index a259374b1d..3a911d55f1 100644 --- a/Externals/libusb/libusb/os/windows_winusb.h +++ b/Externals/libusb/libusb/os/windows_winusb.h @@ -36,15 +36,14 @@ #endif // Missing from MSVC6 setupapi.h -#if !defined(SPDRP_ADDRESS) +#ifndef SPDRP_ADDRESS #define SPDRP_ADDRESS 28 #endif -#if !defined(SPDRP_INSTALL_STATE) +#ifndef SPDRP_INSTALL_STATE #define SPDRP_INSTALL_STATE 34 #endif #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 @@ -61,17 +60,17 @@ // 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 -#if !defined(GUID_DEVINTERFACE_USB_HOST_CONTROLLER) -const GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = { 0x3ABF6F2D, 0x71C4, 0x462A, {0x8A, 0x92, 0x1E, 0x68, 0x61, 0xE6, 0xAF, 0x27} }; +#ifndef GUID_DEVINTERFACE_USB_HOST_CONTROLLER +const GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = {0x3ABF6F2D, 0x71C4, 0x462A, {0x8A, 0x92, 0x1E, 0x68, 0x61, 0xE6, 0xAF, 0x27}}; #endif -#if !defined(GUID_DEVINTERFACE_USB_DEVICE) -const GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED} }; +#ifndef GUID_DEVINTERFACE_USB_DEVICE +const GUID GUID_DEVINTERFACE_USB_DEVICE = {0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED}}; #endif -#if !defined(GUID_DEVINTERFACE_USB_HUB) -const GUID GUID_DEVINTERFACE_USB_HUB = { 0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8} }; +#ifndef GUID_DEVINTERFACE_USB_HUB +const GUID GUID_DEVINTERFACE_USB_HUB = {0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8}}; #endif -#if !defined(GUID_DEVINTERFACE_LIBUSB0_FILTER) -const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = { 0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9} }; +#ifndef GUID_DEVINTERFACE_LIBUSB0_FILTER +const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = {0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9}}; #endif @@ -84,8 +83,6 @@ const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = { 0xF9F3FF14, 0xAE21, 0x48A0, {0x8 #define USB_API_WINUSBX 3 #define USB_API_HID 4 #define USB_API_MAX 5 -// The following is used to indicate if the HID or composite extra props have already been set. -#define USB_API_SET (1 << USB_API_MAX) // Sub-APIs for WinUSB-like driver APIs (WinUSB, libusbK, libusb-win32 through the libusbK DLL) // Must have the same values as the KUSB_DRVID enum from libusbk.h @@ -95,15 +92,13 @@ const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = { 0xF9F3FF14, 0xAE21, 0x48A0, {0x8 #define SUB_API_WINUSB 2 #define SUB_API_MAX 3 -#define WINUSBX_DRV_NAMES {"libusbK", "libusb0", "WinUSB"} - struct windows_usb_api_backend { const uint8_t id; - const char *designation; - const char **driver_name_list; // Driver name, without .sys, e.g. "usbccgp" + const char * const designation; + const char * const * const driver_name_list; // Driver name, without .sys, e.g. "usbccgp" const uint8_t nb_driver_names; - int (*init)(int sub_api, struct libusb_context *ctx); - int (*exit)(int sub_api); + int (*init)(struct libusb_context *ctx); + void (*exit)(void); int (*open)(int sub_api, struct libusb_device_handle *dev_handle); void (*close)(int sub_api, struct libusb_device_handle *dev_handle); int (*configure_endpoints)(int sub_api, struct libusb_device_handle *dev_handle, int iface); @@ -123,9 +118,16 @@ struct windows_usb_api_backend { extern const struct windows_usb_api_backend usb_api_backend[USB_API_MAX]; #define PRINT_UNSUPPORTED_API(fname) \ - usbi_dbg("unsupported API call for '" \ - #fname "' (unrecognized device driver)"); \ - return LIBUSB_ERROR_NOT_SUPPORTED; + usbi_dbg("unsupported API call for '%s' " \ + "(unrecognized device driver)", #fname) + +#define CHECK_SUPPORTED_API(apip, fname) \ + do { \ + if ((apip)->fname == NULL) { \ + PRINT_UNSUPPORTED_API(fname); \ + return LIBUSB_ERROR_NOT_SUPPORTED; \ + } \ + } while (0) /* * private structures definition @@ -154,15 +156,16 @@ struct libusb_hid_descriptor { #define LIBUSB_REQ_IN(request_type) ((request_type) & LIBUSB_ENDPOINT_IN) #define LIBUSB_REQ_OUT(request_type) (!LIBUSB_REQ_IN(request_type)) +#ifndef CTL_CODE +#define CTL_CODE(DeviceType, Function, Method, Access) \ + (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) +#endif + // 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) + 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) + 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) @@ -193,106 +196,57 @@ struct hid_device_priv { uint16_t input_report_size; uint16_t output_report_size; uint16_t feature_report_size; + uint16_t usage; + uint16_t usagePage; WCHAR string[3][MAX_USB_STRING_LENGTH]; uint8_t string_index[3]; // man, prod, ser }; -struct windows_device_priv { - uint8_t depth; // distance to HCD - uint8_t port; // port number on the hub - uint8_t active_config; - struct windows_usb_api_backend const *apib; - char *path; // device interface path - int sub_api; // for WinUSB-like APIs - struct { - char *path; // each interface needs a device interface path, - struct windows_usb_api_backend const *apib; // an API backend (multiple drivers support), - int sub_api; - 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]; - struct hid_device_priv *hid; - USB_DEVICE_DESCRIPTOR dev_descriptor; - unsigned char **config_descriptor; // list of pointers to the cached config descriptors -}; - -static inline struct windows_device_priv *_device_priv(struct libusb_device *dev) +static inline struct winusb_device_priv *_device_priv(struct libusb_device *dev) { - return (struct windows_device_priv *)dev->os_priv; + return (struct winusb_device_priv *)dev->os_priv; } -static inline struct windows_device_priv *windows_device_priv_init(struct libusb_device *dev) +static inline struct winusb_device_priv *winusb_device_priv_init(struct libusb_device *dev) { - struct windows_device_priv *p = _device_priv(dev); + struct winusb_device_priv *p = _device_priv(dev); int i; - p->depth = 0; - p->port = 0; - p->path = NULL; p->apib = &usb_api_backend[USB_API_UNSUPPORTED]; p->sub_api = SUB_API_NOTSET; - p->hid = NULL; - p->active_config = 0; - p->config_descriptor = NULL; - memset(&p->dev_descriptor, 0, sizeof(USB_DEVICE_DESCRIPTOR)); for (i = 0; i < USB_MAXINTERFACES; i++) { - p->usb_interface[i].path = NULL; p->usb_interface[i].apib = &usb_api_backend[USB_API_UNSUPPORTED]; p->usb_interface[i].sub_api = SUB_API_NOTSET; - p->usb_interface[i].nb_endpoints = 0; - p->usb_interface[i].endpoint = NULL; - p->usb_interface[i].restricted_functionality = false; } return p; } -static inline void windows_device_priv_release(struct libusb_device *dev) +static inline void winusb_device_priv_release(struct libusb_device *dev) { - struct windows_device_priv *p = _device_priv(dev); + struct winusb_device_priv *p = _device_priv(dev); int i; - safe_free(p->path); + free(p->dev_id); + free(p->path); if ((dev->num_configurations > 0) && (p->config_descriptor != NULL)) { for (i = 0; i < dev->num_configurations; i++) - safe_free(p->config_descriptor[i]); + free(p->config_descriptor[i]); } - safe_free(p->config_descriptor); - safe_free(p->hid); + free(p->config_descriptor); + free(p->hid); for (i = 0; i < USB_MAXINTERFACES; i++) { - safe_free(p->usb_interface[i].path); - safe_free(p->usb_interface[i].endpoint); + free(p->usb_interface[i].path); + free(p->usb_interface[i].endpoint); } } -struct interface_handle_t { - HANDLE dev_handle; // WinUSB needs an extra handle for the file - HANDLE api_handle; // used by the API to communicate with the device -}; - -struct windows_device_handle_priv { - int active_interface; - struct interface_handle_t interface_handle[USB_MAXINTERFACES]; - int autoclaim_count[USB_MAXINTERFACES]; // For auto-release -}; - -static inline struct windows_device_handle_priv *_device_handle_priv( +static inline struct winusb_device_handle_priv *_device_handle_priv( struct libusb_device_handle *handle) { - return (struct windows_device_handle_priv *)handle->os_priv; + return (struct winusb_device_handle_priv *)handle->os_priv; } -// used for async polling functions -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 struct driver_lookup { char list[MAX_KEY_LENGTH + 1]; // REG_MULTI_SZ list of services (driver) names @@ -300,34 +254,6 @@ struct driver_lookup { const char* designation; // internal designation (for debug output) }; -/* OLE32 dependency */ -DLL_DECLARE_HANDLE(OLE32); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, HRESULT, p, CLSIDFromString, (LPCOLESTR, LPCLSID)); - -/* Kernel32 dependencies */ -DLL_DECLARE_HANDLE(Kernel32); -/* This call is only available from XP SP2 */ -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, IsWow64Process, (HANDLE, PBOOL)); - -/* SetupAPI dependencies */ -DLL_DECLARE_HANDLE(SetupAPI); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, HDEVINFO, p, SetupDiGetClassDevsA, (const GUID*, PCSTR, HWND, DWORD)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInfo, (HDEVINFO, DWORD, PSP_DEVINFO_DATA)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInterfaces, (HDEVINFO, PSP_DEVINFO_DATA, - const GUID*, DWORD, PSP_DEVICE_INTERFACE_DATA)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInterfaceDetailA, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, - PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDevRegKey, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO, - PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDeviceInterfaceRegKey, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, DWORD)); - -/* AdvAPI32 dependencies */ -DLL_DECLARE_HANDLE(AdvAPI32); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY)); - /* * Windows DDK API definitions. Most of it copied from MinGW's includes */ @@ -336,58 +262,64 @@ typedef DEVNODE *PDEVNODE, *PDEVINST; typedef DWORD RETURN_TYPE; typedef RETURN_TYPE CONFIGRET; -#define CR_SUCCESS 0x00000000 -#define CR_NO_SUCH_DEVNODE 0x0000000D +#define CR_SUCCESS 0x00000000 -#define USB_DEVICE_DESCRIPTOR_TYPE LIBUSB_DT_DEVICE -#define USB_CONFIGURATION_DESCRIPTOR_TYPE LIBUSB_DT_CONFIG -#define USB_STRING_DESCRIPTOR_TYPE LIBUSB_DT_STRING -#define USB_INTERFACE_DESCRIPTOR_TYPE LIBUSB_DT_INTERFACE -#define USB_ENDPOINT_DESCRIPTOR_TYPE LIBUSB_DT_ENDPOINT +/* Cfgmgr32 dependencies */ +DLL_DECLARE_HANDLE(Cfgmgr32); +DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG)); +DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG)); -#define USB_REQUEST_GET_STATUS LIBUSB_REQUEST_GET_STATUS -#define USB_REQUEST_CLEAR_FEATURE LIBUSB_REQUEST_CLEAR_FEATURE -#define USB_REQUEST_SET_FEATURE LIBUSB_REQUEST_SET_FEATURE -#define USB_REQUEST_SET_ADDRESS LIBUSB_REQUEST_SET_ADDRESS -#define USB_REQUEST_GET_DESCRIPTOR LIBUSB_REQUEST_GET_DESCRIPTOR -#define USB_REQUEST_SET_DESCRIPTOR LIBUSB_REQUEST_SET_DESCRIPTOR -#define USB_REQUEST_GET_CONFIGURATION LIBUSB_REQUEST_GET_CONFIGURATION -#define USB_REQUEST_SET_CONFIGURATION LIBUSB_REQUEST_SET_CONFIGURATION -#define USB_REQUEST_GET_INTERFACE LIBUSB_REQUEST_GET_INTERFACE -#define USB_REQUEST_SET_INTERFACE LIBUSB_REQUEST_SET_INTERFACE -#define USB_REQUEST_SYNC_FRAME LIBUSB_REQUEST_SYNCH_FRAME +/* AdvAPI32 dependencies */ +DLL_DECLARE_HANDLE(AdvAPI32); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY)); -#define USB_GET_NODE_INFORMATION 258 -#define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 260 -#define USB_GET_NODE_CONNECTION_NAME 261 -#define USB_GET_HUB_CAPABILITIES 271 -#if !defined(USB_GET_NODE_CONNECTION_INFORMATION_EX) -#define USB_GET_NODE_CONNECTION_INFORMATION_EX 274 +/* OLE32 dependency */ +DLL_DECLARE_HANDLE(OLE32); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, HRESULT, p, IIDFromString, (LPCOLESTR, LPIID)); + +/* SetupAPI dependencies */ +DLL_DECLARE_HANDLE(SetupAPI); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, HDEVINFO, p, SetupDiGetClassDevsA, (LPCGUID, PCSTR, HWND, DWORD)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInfo, (HDEVINFO, DWORD, PSP_DEVINFO_DATA)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInterfaces, (HDEVINFO, PSP_DEVINFO_DATA, + LPCGUID, DWORD, PSP_DEVICE_INTERFACE_DATA)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInstanceIdA, (HDEVINFO, PSP_DEVINFO_DATA, + PCSTR, DWORD, PDWORD)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInterfaceDetailA, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, + PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO, + PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDevRegKey, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDeviceInterfaceRegKey, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, DWORD)); + + +#ifndef USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION +#define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 260 #endif -#if !defined(USB_GET_HUB_CAPABILITIES_EX) -#define USB_GET_HUB_CAPABILITIES_EX 276 +#ifndef USB_GET_NODE_CONNECTION_INFORMATION_EX +#define USB_GET_NODE_CONNECTION_INFORMATION_EX 274 #endif -#if !defined(USB_GET_NODE_CONNECTION_INFORMATION_EX_V2) +#ifndef USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 #define USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 279 #endif -#ifndef METHOD_BUFFERED -#define METHOD_BUFFERED 0 -#endif -#ifndef FILE_ANY_ACCESS -#define FILE_ANY_ACCESS 0x00000000 -#endif -#ifndef FILE_DEVICE_UNKNOWN -#define FILE_DEVICE_UNKNOWN 0x00000022 -#endif #ifndef FILE_DEVICE_USB -#define FILE_DEVICE_USB FILE_DEVICE_UNKNOWN +#define FILE_DEVICE_USB FILE_DEVICE_UNKNOWN #endif -#ifndef CTL_CODE -#define CTL_CODE(DeviceType, Function, Method, Access) \ - (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) -#endif +#define USB_CTL_CODE(id) \ + CTL_CODE(FILE_DEVICE_USB, (id), METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION \ + USB_CTL_CODE(USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION) + +#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX \ + USB_CTL_CODE(USB_GET_NODE_CONNECTION_INFORMATION_EX) + +#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 \ + USB_CTL_CODE(USB_GET_NODE_CONNECTION_INFORMATION_EX_V2) typedef enum USB_CONNECTION_STATUS { NoDeviceConnected, @@ -406,42 +338,25 @@ typedef enum USB_HUB_NODE { UsbMIParent } USB_HUB_NODE; -/* Cfgmgr32.dll interface */ -DLL_DECLARE_HANDLE(Cfgmgr32); -DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG)); -DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG)); -DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Sibling, (PDEVINST, DEVINST, ULONG)); -DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Device_IDA, (DEVINST, PCHAR, ULONG, ULONG)); - -#define IOCTL_USB_GET_HUB_CAPABILITIES_EX \ - CTL_CODE( FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES_EX, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_HUB_CAPABILITIES \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_ROOT_HUB_NAME \ - CTL_CODE(FILE_DEVICE_USB, HCD_GET_ROOT_HUB_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_NODE_INFORMATION \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_INFORMATION, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_ATTRIBUTES, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_NODE_CONNECTION_NAME \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS) - // Most of the structures below need to be packed -#pragma pack(push, 1) +#include + +typedef struct _USB_DESCRIPTOR_REQUEST { + ULONG ConnectionIndex; + struct { + UCHAR bmRequest; + UCHAR bRequest; + USHORT wValue; + USHORT wIndex; + USHORT wLength; + } SetupPacket; +// UCHAR Data[0]; +} USB_DESCRIPTOR_REQUEST, *PUSB_DESCRIPTOR_REQUEST; + +typedef struct _USB_CONFIGURATION_DESCRIPTOR_SHORT { + USB_DESCRIPTOR_REQUEST req; + USB_CONFIGURATION_DESCRIPTOR desc; +} USB_CONFIGURATION_DESCRIPTOR_SHORT; typedef struct USB_INTERFACE_DESCRIPTOR { UCHAR bLength; @@ -455,103 +370,7 @@ typedef struct USB_INTERFACE_DESCRIPTOR { UCHAR iInterface; } USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR; -typedef struct USB_CONFIGURATION_DESCRIPTOR_SHORT { - struct { - ULONG ConnectionIndex; - struct { - UCHAR bmRequest; - UCHAR bRequest; - USHORT wValue; - USHORT wIndex; - USHORT wLength; - } SetupPacket; - } req; - USB_CONFIGURATION_DESCRIPTOR data; -} USB_CONFIGURATION_DESCRIPTOR_SHORT; - -typedef struct USB_ENDPOINT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bEndpointAddress; - UCHAR bmAttributes; - USHORT wMaxPacketSize; - UCHAR bInterval; -} USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR; - -typedef struct USB_DESCRIPTOR_REQUEST { - ULONG ConnectionIndex; - struct { - UCHAR bmRequest; - UCHAR bRequest; - USHORT wValue; - USHORT wIndex; - USHORT wLength; - } SetupPacket; -// UCHAR Data[0]; -} USB_DESCRIPTOR_REQUEST, *PUSB_DESCRIPTOR_REQUEST; - -typedef struct USB_HUB_DESCRIPTOR { - UCHAR bDescriptorLength; - UCHAR bDescriptorType; - UCHAR bNumberOfPorts; - USHORT wHubCharacteristics; - UCHAR bPowerOnToPowerGood; - UCHAR bHubControlCurrent; - UCHAR bRemoveAndPowerMask[64]; -} USB_HUB_DESCRIPTOR, *PUSB_HUB_DESCRIPTOR; - -typedef struct USB_ROOT_HUB_NAME { - ULONG ActualLength; - WCHAR RootHubName[1]; -} USB_ROOT_HUB_NAME, *PUSB_ROOT_HUB_NAME; - -typedef struct USB_ROOT_HUB_NAME_FIXED { - ULONG ActualLength; - WCHAR RootHubName[MAX_PATH_LENGTH]; -} USB_ROOT_HUB_NAME_FIXED; - -typedef struct USB_NODE_CONNECTION_NAME { - ULONG ConnectionIndex; - ULONG ActualLength; - WCHAR NodeName[1]; -} USB_NODE_CONNECTION_NAME, *PUSB_NODE_CONNECTION_NAME; - -typedef struct USB_NODE_CONNECTION_NAME_FIXED { - ULONG ConnectionIndex; - ULONG ActualLength; - WCHAR NodeName[MAX_PATH_LENGTH]; -} USB_NODE_CONNECTION_NAME_FIXED; - -typedef struct USB_HUB_NAME_FIXED { - union { - USB_ROOT_HUB_NAME_FIXED root; - USB_NODE_CONNECTION_NAME_FIXED node; - } u; -} USB_HUB_NAME_FIXED; - -typedef struct USB_HUB_INFORMATION { - USB_HUB_DESCRIPTOR HubDescriptor; - BOOLEAN HubIsBusPowered; -} USB_HUB_INFORMATION, *PUSB_HUB_INFORMATION; - -typedef struct USB_MI_PARENT_INFORMATION { - ULONG NumberOfInterfaces; -} USB_MI_PARENT_INFORMATION, *PUSB_MI_PARENT_INFORMATION; - -typedef struct USB_NODE_INFORMATION { - USB_HUB_NODE NodeType; - union { - USB_HUB_INFORMATION HubInformation; - USB_MI_PARENT_INFORMATION MiParentInformation; - } u; -} USB_NODE_INFORMATION, *PUSB_NODE_INFORMATION; - -typedef struct USB_PIPE_INFO { - USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; - ULONG ScheduleOffset; -} USB_PIPE_INFO, *PUSB_PIPE_INFO; - -typedef struct USB_NODE_CONNECTION_INFORMATION_EX { +typedef struct _USB_NODE_CONNECTION_INFORMATION_EX { ULONG ConnectionIndex; USB_DEVICE_DESCRIPTOR DeviceDescriptor; UCHAR CurrentConfigurationValue; @@ -589,28 +408,11 @@ typedef struct _USB_NODE_CONNECTION_INFORMATION_EX_V2 { USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS Flags; } USB_NODE_CONNECTION_INFORMATION_EX_V2, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2; -typedef struct USB_HUB_CAP_FLAGS { - ULONG HubIsHighSpeedCapable:1; - ULONG HubIsHighSpeed:1; - ULONG HubIsMultiTtCapable:1; - ULONG HubIsMultiTt:1; - ULONG HubIsRoot:1; - ULONG HubIsArmedWakeOnConnect:1; - ULONG ReservedMBZ:26; -} USB_HUB_CAP_FLAGS, *PUSB_HUB_CAP_FLAGS; - -typedef struct USB_HUB_CAPABILITIES { - ULONG HubIs2xCapable:1; -} USB_HUB_CAPABILITIES, *PUSB_HUB_CAPABILITIES; - -typedef struct USB_HUB_CAPABILITIES_EX { - USB_HUB_CAP_FLAGS CapabilityFlags; -} USB_HUB_CAPABILITIES_EX, *PUSB_HUB_CAPABILITIES_EX; - -#pragma pack(pop) +#include /* winusb.dll interface */ +/* pipe policies */ #define SHORT_PACKET_TERMINATE 0x01 #define AUTO_CLEAR_STALL 0x02 #define PIPE_TRANSFER_TIMEOUT 0x03 @@ -619,36 +421,27 @@ typedef struct USB_HUB_CAPABILITIES_EX { #define AUTO_FLUSH 0x06 #define RAW_IO 0x07 #define MAXIMUM_TRANSFER_SIZE 0x08 -#define AUTO_SUSPEND 0x81 -#define SUSPEND_DELAY 0x83 -#define DEVICE_SPEED 0x01 -#define LowSpeed 0x01 -#define FullSpeed 0x02 -#define HighSpeed 0x03 +/* libusbK */ +#define ISO_ALWAYS_START_ASAP 0x21 -typedef enum USBD_PIPE_TYPE { +typedef enum _USBD_PIPE_TYPE { UsbdPipeTypeControl, UsbdPipeTypeIsochronous, UsbdPipeTypeBulk, UsbdPipeTypeInterrupt } USBD_PIPE_TYPE; -typedef struct { - USBD_PIPE_TYPE PipeType; - UCHAR PipeId; - USHORT MaximumPacketSize; - UCHAR Interval; -} WINUSB_PIPE_INFORMATION, *PWINUSB_PIPE_INFORMATION; +#include -#pragma pack(1) -typedef struct { - UCHAR request_type; - UCHAR request; - USHORT value; - USHORT index; - USHORT length; +typedef struct _WINUSB_SETUP_PACKET { + UCHAR RequestType; + UCHAR Request; + USHORT Value; + USHORT Index; + USHORT Length; } WINUSB_SETUP_PACKET, *PWINUSB_SETUP_PACKET; -#pragma pack() + +#include typedef void *WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE; @@ -676,59 +469,10 @@ typedef BOOL (WINAPI *WinUsb_GetAssociatedInterface_t)( UCHAR AssociatedInterfaceIndex, PWINUSB_INTERFACE_HANDLE AssociatedInterfaceHandle ); -typedef BOOL (WINAPI *WinUsb_GetCurrentAlternateSetting_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - PUCHAR AlternateSetting -); -typedef BOOL (WINAPI *WinUsb_GetDescriptor_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR DescriptorType, - UCHAR Index, - USHORT LanguageID, - PUCHAR Buffer, - ULONG BufferLength, - PULONG LengthTransferred -); -typedef BOOL (WINAPI *WinUsb_GetOverlappedResult_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - LPOVERLAPPED lpOverlapped, - LPDWORD lpNumberOfBytesTransferred, - BOOL bWait -); -typedef BOOL (WINAPI *WinUsb_GetPipePolicy_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR PipeID, - ULONG PolicyType, - PULONG ValueLength, - PVOID Value -); -typedef BOOL (WINAPI *WinUsb_GetPowerPolicy_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - ULONG PolicyType, - PULONG ValueLength, - PVOID Value -); typedef BOOL (WINAPI *WinUsb_Initialize_t)( HANDLE DeviceHandle, PWINUSB_INTERFACE_HANDLE InterfaceHandle ); -typedef BOOL (WINAPI *WinUsb_QueryDeviceInformation_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - ULONG InformationType, - PULONG BufferLength, - PVOID Buffer -); -typedef BOOL (WINAPI *WinUsb_QueryInterfaceSettings_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR AlternateSettingNumber, - PUSB_INTERFACE_DESCRIPTOR UsbAltInterfaceDescriptor -); -typedef BOOL (WINAPI *WinUsb_QueryPipe_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR AlternateInterfaceNumber, - UCHAR PipeIndex, - PWINUSB_PIPE_INFORMATION PipeInformation -); typedef BOOL (WINAPI *WinUsb_ReadPipe_t)( WINUSB_INTERFACE_HANDLE InterfaceHandle, UCHAR PipeID, @@ -737,6 +481,9 @@ typedef BOOL (WINAPI *WinUsb_ReadPipe_t)( PULONG LengthTransferred, LPOVERLAPPED Overlapped ); +typedef BOOL (WINAPI *WinUsb_ResetDevice_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle +); typedef BOOL (WINAPI *WinUsb_ResetPipe_t)( WINUSB_INTERFACE_HANDLE InterfaceHandle, UCHAR PipeID @@ -752,12 +499,6 @@ typedef BOOL (WINAPI *WinUsb_SetPipePolicy_t)( ULONG ValueLength, PVOID Value ); -typedef BOOL (WINAPI *WinUsb_SetPowerPolicy_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - ULONG PolicyType, - ULONG ValueLength, - PVOID Value -); typedef BOOL (WINAPI *WinUsb_WritePipe_t)( WINUSB_INTERFACE_HANDLE InterfaceHandle, UCHAR PipeID, @@ -766,8 +507,59 @@ typedef BOOL (WINAPI *WinUsb_WritePipe_t)( PULONG LengthTransferred, LPOVERLAPPED Overlapped ); -typedef BOOL (WINAPI *WinUsb_ResetDevice_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle + +typedef PVOID WINUSB_ISOCH_BUFFER_HANDLE, *PWINUSB_ISOCH_BUFFER_HANDLE; + +typedef BOOL (WINAPI *WinUsb_RegisterIsochBuffer_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle, + UCHAR PipeID, + PVOID Buffer, + ULONG BufferLength, + PWINUSB_ISOCH_BUFFER_HANDLE BufferHandle +); + +typedef BOOL (WINAPI *WinUsb_UnregisterIsochBuffer_t)( + WINUSB_ISOCH_BUFFER_HANDLE BufferHandle +); + +typedef BOOL (WINAPI *WinUsb_WriteIsochPipeAsap_t)( + WINUSB_ISOCH_BUFFER_HANDLE BufferHandle, + ULONG Offset, + ULONG Length, + BOOL ContinueStream, + LPOVERLAPPED Overlapped +); + +typedef LONG USBD_STATUS; +typedef struct { + ULONG Offset; + ULONG Length; + USBD_STATUS Status; +} USBD_ISO_PACKET_DESCRIPTOR, *PUSBD_ISO_PACKET_DESCRIPTOR; + +typedef BOOL (WINAPI *WinUsb_ReadIsochPipeAsap_t)( + PWINUSB_ISOCH_BUFFER_HANDLE BufferHandle, + ULONG Offset, + ULONG Length, + BOOL ContinueStream, + ULONG NumberOfPackets, + PUSBD_ISO_PACKET_DESCRIPTOR IsoPacketDescriptors, + LPOVERLAPPED Overlapped +); + +typedef struct { + USBD_PIPE_TYPE PipeType; + UCHAR PipeId; + USHORT MaximumPacketSize; + UCHAR Interval; + ULONG MaximumBytesPerInterval; +} WINUSB_PIPE_INFORMATION_EX, *PWINUSB_PIPE_INFORMATION_EX; + +typedef BOOL (WINAPI *WinUsb_QueryPipeEx_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle, + UCHAR AlternateInterfaceHandle, + UCHAR PipeIndex, + PWINUSB_PIPE_INFORMATION_EX PipeInformationEx ); /* /!\ These must match the ones from the official libusbk.h */ @@ -814,8 +606,7 @@ typedef struct _KLIB_VERSION { INT Minor; INT Micro; INT Nano; -} KLIB_VERSION; -typedef KLIB_VERSION* PKLIB_VERSION; +} KLIB_VERSION, *PKLIB_VERSION; typedef BOOL (WINAPI *LibK_GetProcAddress_t)( PVOID *ProcAddress, @@ -827,29 +618,72 @@ typedef VOID (WINAPI *LibK_GetVersion_t)( PKLIB_VERSION Version ); +//KISO_PACKET is equivalent of libusb_iso_packet_descriptor except uses absolute "offset" field instead of sequential Lengths +typedef struct _KISO_PACKET { + UINT offset; + USHORT actual_length; //changed from libusbk_shared.h "Length" for clarity + USHORT status; +} KISO_PACKET, *PKISO_PACKET; + +typedef enum _KISO_FLAG { + KISO_FLAG_NONE = 0, + KISO_FLAG_SET_START_FRAME = 0x00000001, +} KISO_FLAG; + +//KISO_CONTEXT is the conceptual equivalent of libusb_transfer except is isochronous-specific and must match libusbk's version +typedef struct _KISO_CONTEXT { + KISO_FLAG Flags; + UINT StartFrame; + SHORT ErrorCount; + SHORT NumberOfPackets; + UINT UrbHdrStatus; + KISO_PACKET IsoPackets[0]; +} KISO_CONTEXT, *PKISO_CONTEXT; + +typedef BOOL(WINAPI *WinUsb_IsoReadPipe_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle, + UCHAR PipeID, + PUCHAR Buffer, + ULONG BufferLength, + LPOVERLAPPED Overlapped, + PKISO_CONTEXT IsoContext +); + +typedef BOOL(WINAPI *WinUsb_IsoWritePipe_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle, + UCHAR PipeID, + PUCHAR Buffer, + ULONG BufferLength, + LPOVERLAPPED Overlapped, + PKISO_CONTEXT IsoContext +); + struct winusb_interface { bool initialized; + bool CancelIoEx_supported; WinUsb_AbortPipe_t AbortPipe; WinUsb_ControlTransfer_t ControlTransfer; WinUsb_FlushPipe_t FlushPipe; WinUsb_Free_t Free; WinUsb_GetAssociatedInterface_t GetAssociatedInterface; - WinUsb_GetCurrentAlternateSetting_t GetCurrentAlternateSetting; - WinUsb_GetDescriptor_t GetDescriptor; - WinUsb_GetOverlappedResult_t GetOverlappedResult; - WinUsb_GetPipePolicy_t GetPipePolicy; - WinUsb_GetPowerPolicy_t GetPowerPolicy; WinUsb_Initialize_t Initialize; - WinUsb_QueryDeviceInformation_t QueryDeviceInformation; - WinUsb_QueryInterfaceSettings_t QueryInterfaceSettings; - WinUsb_QueryPipe_t QueryPipe; WinUsb_ReadPipe_t ReadPipe; + WinUsb_ResetDevice_t ResetDevice; WinUsb_ResetPipe_t ResetPipe; WinUsb_SetCurrentAlternateSetting_t SetCurrentAlternateSetting; WinUsb_SetPipePolicy_t SetPipePolicy; - WinUsb_SetPowerPolicy_t SetPowerPolicy; WinUsb_WritePipe_t WritePipe; - WinUsb_ResetDevice_t ResetDevice; + + // Isochoronous functions for LibUSBk sub api: + WinUsb_IsoReadPipe_t IsoReadPipe; + WinUsb_IsoWritePipe_t IsoWritePipe; + + // Isochronous functions for Microsoft WinUSB sub api (native WinUSB): + WinUsb_RegisterIsochBuffer_t RegisterIsochBuffer; + WinUsb_UnregisterIsochBuffer_t UnregisterIsochBuffer; + WinUsb_WriteIsochPipeAsap_t WriteIsochPipeAsap; + WinUsb_ReadIsochPipeAsap_t ReadIsochPipeAsap; + WinUsb_QueryPipeEx_t QueryPipeEx; }; /* hid.dll interface */ @@ -857,17 +691,19 @@ struct winusb_interface { #define HIDP_STATUS_SUCCESS 0x110000 typedef void * PHIDP_PREPARSED_DATA; -#pragma pack(1) -typedef struct { +#include + +typedef struct _HIDD_ATTIRBUTES { ULONG Size; USHORT VendorID; USHORT ProductID; USHORT VersionNumber; } HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; -#pragma pack() + +#include typedef USHORT USAGE; -typedef struct { +typedef struct _HIDP_CAPS { USAGE Usage; USAGE UsagePage; USHORT InputReportByteLength; @@ -930,19 +766,16 @@ typedef struct _HIDP_VALUE_CAPS { } HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS; DLL_DECLARE_HANDLE(hid); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetAttributes, (HANDLE, PHIDD_ATTRIBUTES)); DLL_DECLARE_FUNC(WINAPI, VOID, HidD_GetHidGuid, (LPGUID)); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetAttributes, (HANDLE, PHIDD_ATTRIBUTES)); DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetPreparsedData, (HANDLE, PHIDP_PREPARSED_DATA *)); DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_FreePreparsedData, (PHIDP_PREPARSED_DATA)); DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetManufacturerString, (HANDLE, PVOID, ULONG)); DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetProductString, (HANDLE, PVOID, ULONG)); DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetSerialNumberString, (HANDLE, PVOID, ULONG)); +DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetIndexedString, (HANDLE, ULONG, PVOID, ULONG)); DLL_DECLARE_FUNC(WINAPI, LONG, HidP_GetCaps, (PHIDP_PREPARSED_DATA, PHIDP_CAPS)); DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetNumInputBuffers, (HANDLE, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetFeature, (HANDLE, PVOID, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetFeature, (HANDLE, PVOID, ULONG)); DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetPhysicalDescriptor, (HANDLE, PVOID, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetInputReport, (HANDLE, PVOID, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetOutputReport, (HANDLE, PVOID, ULONG)); DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_FlushQueue, (HANDLE)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidP_GetValueCaps, (HIDP_REPORT_TYPE, PHIDP_VALUE_CAPS, PULONG, PHIDP_PREPARSED_DATA)); \ No newline at end of file +DLL_DECLARE_FUNC(WINAPI, BOOL, HidP_GetValueCaps, (HIDP_REPORT_TYPE, PHIDP_VALUE_CAPS, PULONG, PHIDP_PREPARSED_DATA)); diff --git a/Externals/libusb/libusb/strerror.c b/Externals/libusb/libusb/strerror.c index d2be0e2a00..a1b474e94b 100644 --- a/Externals/libusb/libusb/strerror.c +++ b/Externals/libusb/libusb/strerror.c @@ -38,7 +38,7 @@ static size_t usbi_locale = 0; * How to add a new \ref libusb_strerror() translation: *
    *
  1. Download the latest \c strerror.c from:
    - * https://raw.github.com/libusb/libusb/master/libusb/sterror.c
  2. + * https://raw.github.com/libusb/libusb/master/libusb/strerror.c *
  3. Open the file in an UTF-8 capable editor
  4. *
  5. Add the 2 letter ISO 639-1 * code for your locale at the end of \c usbi_locale_supported[]
    @@ -60,7 +60,7 @@ static size_t usbi_locale = 0; *
*/ -static const char* usbi_locale_supported[] = { "en", "nl", "fr", "ru" }; +static const char* usbi_locale_supported[] = { "en", "nl", "fr", "ru", "de", "hu" }; static const char* usbi_localized_errors[ARRAYSIZE(usbi_locale_supported)][LIBUSB_ERROR_COUNT] = { { /* English (en) */ "Success", @@ -122,6 +122,37 @@ static const char* usbi_localized_errors[ARRAYSIZE(usbi_locale_supported)][LIBUS "Память исчерпана", "Операция не поддерживается данной платформой", "Неизвестная ошибка" + + }, { /* German (de) */ + "Erfolgreich", + "Eingabe-/Ausgabefehler", + "Ungültiger Parameter", + "Keine Berechtigung (Zugriffsrechte fehlen)", + "Kein passendes Gerät gefunden (es könnte entfernt worden sein)", + "Entität nicht gefunden", + "Die Ressource ist belegt", + "Die Wartezeit für die Operation ist abgelaufen", + "Mehr Daten empfangen als erwartet", + "Datenübergabe unterbrochen (broken pipe)", + "Unterbrechung während des Betriebssystemaufrufs", + "Nicht genügend Hauptspeicher verfügbar", + "Die Operation wird nicht unterstützt oder ist auf dieser Platform nicht implementiert", + "Allgemeiner Fehler", + }, { /* Hungarian (hu) */ + "Sikeres", + "Be-/kimeneti hiba", + "Érvénytelen paraméter", + "Hozzáférés megtagadva", + "Az eszköz nem található (eltávolították?)", + "Nem található", + "Az erőforrás foglalt", + "Időtúllépés", + "Túlcsordulás", + "Törött adatcsatorna", + "Rendszerhívás megszakítva", + "Nincs elég memória", + "A művelet nem támogatott ezen a rendszeren", + "Általános hiba", } }; diff --git a/Externals/libusb/libusb/version.h b/Externals/libusb/libusb/version.h index 6ce48a7d01..a7550b0a65 100644 --- a/Externals/libusb/libusb/version.h +++ b/Externals/libusb/libusb/version.h @@ -7,12 +7,12 @@ #define LIBUSB_MINOR 0 #endif #ifndef LIBUSB_MICRO -#define LIBUSB_MICRO 21 +#define LIBUSB_MICRO 23 #endif #ifndef LIBUSB_NANO #define LIBUSB_NANO 0 #endif /* LIBUSB_RC is the release candidate suffix. Should normally be empty. */ #ifndef LIBUSB_RC -#define LIBUSB_RC "" +#define LIBUSB_RC "-rc1" #endif diff --git a/Externals/libusb/libusb/version_nano.h b/Externals/libusb/libusb/version_nano.h index 58cb0fbf89..e549eee730 100644 --- a/Externals/libusb/libusb/version_nano.h +++ b/Externals/libusb/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11156 +#define LIBUSB_NANO 11367 diff --git a/Externals/libusb/libusb_static_2013.vcxproj b/Externals/libusb/libusb_static_2013.vcxproj index 23e817fa98..f9e2ea4442 100644 --- a/Externals/libusb/libusb_static_2013.vcxproj +++ b/Externals/libusb/libusb_static_2013.vcxproj @@ -67,10 +67,11 @@ + - \ No newline at end of file + diff --git a/Externals/libusb/msvc/appveyor.bat b/Externals/libusb/msvc/appveyor.bat deleted file mode 100644 index 779af59d9f..0000000000 --- a/Externals/libusb/msvc/appveyor.bat +++ /dev/null @@ -1,28 +0,0 @@ -echo on -SetLocal EnableDelayedExpansion - -if [%Configuration%] NEQ [Debug] goto releasex64 -if [%Configuration%] NEQ [Release] goto debugx64 - -:debugx64 -if [%Platform%] NEQ [x64] goto debugWin32 -if [%Configuration%] NEQ [Debug] exit 0 -call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /Debug /x64 -msbuild %libusb_2010% /p:Configuration=Debug,Platform=x64 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - -:releasex64 -if [%Platform%] NEQ [x64] goto releaseWin32 -if [%Configuration%] NEQ [Release] exit 0 -call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /Release /x64 -msbuild %libusb_2010% /p:Configuration=Release,Platform=x64 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - -:debugWin32 -if [%Platform%] NEQ [Win32] exit 0 -if [%Configuration%] NEQ [Debug] exit 0 -msbuild %libusb_2010% /p:Configuration=Debug,Platform=Win32 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - -:releaseWin32 -if [%Platform%] NEQ [Win32] exit 0 -if [%Configuration%] NEQ [Release] exit 0 -msbuild %libusb_2010% /p:Configuration=Release,Platform=Win32 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - diff --git a/Externals/libusb/msvc/config.h b/Externals/libusb/msvc/config.h index 4f39d78ca5..b20d99ba71 100644 --- a/Externals/libusb/msvc/config.h +++ b/Externals/libusb/msvc/config.h @@ -6,16 +6,18 @@ #endif /* Visual Studio 2015 and later defines timespec */ -#if defined(_MSC_VER) && (_MSC_VER >= 1900) +#if (_MSC_VER >= 1900) #define _TIMESPEC_DEFINED 1 #endif /* Disable: warning C4200: nonstandard extension used : zero-sized array in struct/union */ #pragma warning(disable:4200) +/* Disable: warning C4324: structure was padded due to __declspec(align()) */ +#pragma warning(disable:4324) /* Disable: warning C6258: Using TerminateThread does not allow proper thread clean up */ -#pragma warning(disable: 6258) +#pragma warning(disable:6258) /* Disable: warning C4996: 'GetVersionA': was declared deprecated */ -#pragma warning(disable: 4996) +#pragma warning(disable:4996) #if defined(_PREFAST_) /* Disable "Banned API" errors when using the MS's WDK OACR/Prefast */ @@ -45,6 +47,5 @@ #define HAVE_MISSING_H #else #define OS_WINDOWS 1 -#define HAVE_SIGNAL_H 1 #define HAVE_SYS_TYPES_H 1 #endif diff --git a/Externals/libusb/msvc/ddk_build.cmd b/Externals/libusb/msvc/ddk_build.cmd deleted file mode 100644 index c0b905abdd..0000000000 --- a/Externals/libusb/msvc/ddk_build.cmd +++ /dev/null @@ -1,184 +0,0 @@ -@echo off -::# default builds static library. -::# you can pass the following arguments (case insensitive): -::# - "DLL" to build a DLL instead of a static library -::# - "/MT" to build a static library compatible with MSVC's /MT option (LIBCMT vs MSVCRT) -::# - "USBDK" to build with UsbDk backend - -if Test%BUILD_ALT_DIR%==Test goto usage - -::# process commandline parameters -set TARGET=LIBRARY -set STATIC_LIBC= -set WITH_USBDK= -set version=1.0 -set PWD=%~dp0 -set BUILD_CMD=build -bcwgZ -M2 - -:more_args - -if "%1" == "" goto no_more_args -::# /I for case insensitive -if /I Test%1==TestDLL set TARGET=DYNLINK -if /I Test%1==Test/MT set STATIC_LIBC=1 -if /I Test%1==TestUSBDK set WITH_USBDK=1 - -shift -goto more_args - -:no_more_args - -cd ..\libusb\os -echo TARGETTYPE=%TARGET% > target -copy target+..\..\msvc\libusb_sources sources >NUL 2>&1 -del target -@echo on -%BUILD_CMD% -@echo off -if errorlevel 1 goto builderror -cd ..\.. - -set cpudir=i386 -set destType=Win32 -if %_BUILDARCH%==x86 goto isI386 -set cpudir=amd64 -set destType=x64 -:isI386 - -set srcPath=libusb\os\obj%BUILD_ALT_DIR%\%cpudir% - -set dstPath=%destType%\Debug -if %DDKBUILDENV%==chk goto isDebug -set dstPath=%destType%\Release -:isDebug - -if exist %destType% goto md2 -mkdir %destType% -:md2 -if exist %dstPath% goto md3 -mkdir %dstPath% -:md3 -if exist %dstPath%\dll goto md4 -mkdir %dstPath%\dll -:md4 -if exist %dstPath%\lib goto md5 -md %dstPath%\lib -:md5 -if exist %dstPath%\examples goto md6 -md %dstPath%\examples -:md6 -@echo on - -@if /I NOT Test%1==TestDLL goto copylib -copy %srcPath%\libusb-%version%.dll %dstPath%\dll -copy %srcPath%\libusb-%version%.pdb %dstPath%\dll -:copylib -copy %srcPath%\libusb-%version%.lib %dstPath%\lib - -@echo off - -if exist examples\listdevs_ddkbuild goto md7 -md examples\listdevs_ddkbuild -:md7 - -cd examples\listdevs_ddkbuild -copy ..\..\msvc\listdevs_sources sources >NUL 2>&1 -@echo on -%BUILD_CMD% -@echo off -if errorlevel 1 goto builderror -cd ..\.. - -set srcPath=examples\listdevs_ddkbuild\obj%BUILD_ALT_DIR%\%cpudir% -@echo on - -copy %srcPath%\listdevs.exe %dstPath%\examples -copy %srcPath%\listdevs.pdb %dstPath%\examples - -@echo off - -if exist examples\xusb_ddkbuild goto md8 -md examples\xusb_ddkbuild -:md8 - -cd examples\xusb_ddkbuild -copy ..\..\msvc\xusb_sources sources >NUL 2>&1 -@echo on -%BUILD_CMD% -@echo off -if errorlevel 1 goto builderror -cd ..\.. - -set srcPath=examples\xusb_ddkbuild\obj%BUILD_ALT_DIR%\%cpudir% -@echo on - -copy %srcPath%\xusb.exe %dstPath%\examples -copy %srcPath%\xusb.pdb %dstPath%\examples - -@echo off - -if exist examples\getopt\getopt_ddkbuild goto md9 -md examples\getopt\getopt_ddkbuild -:md9 - -cd examples\getopt\getopt_ddkbuild -copy ..\..\..\msvc\getopt_sources sources >NUL 2>&1 -@echo on -%BUILD_CMD% -@echo off -if errorlevel 1 goto builderror -cd ..\..\.. - -if exist examples\fxload_ddkbuild goto md10 -md examples\fxload_ddkbuild -:md10 - -cd examples\fxload_ddkbuild -copy ..\..\msvc\fxload_sources sources >NUL 2>&1 -@echo on -%BUILD_CMD% -@echo off -if errorlevel 1 goto builderror -cd ..\.. - -set srcPath=examples\fxload_ddkbuild\obj%BUILD_ALT_DIR%\%cpudir% -@echo on - -copy %srcPath%\fxload.exe %dstPath%\examples -copy %srcPath%\fxload.pdb %dstPath%\examples - -@echo off - -if exist examples\hotplugtest_ddkbuild goto md11 -md examples\hotplugtest_ddkbuild -:md11 - -cd examples\hotplugtest_ddkbuild -copy ..\..\msvc\hotplugtest_sources sources >NUL 2>&1 -@echo on -%BUILD_CMD% -@echo off -if errorlevel 1 goto builderror -cd ..\.. - -set srcPath=examples\hotplugtest_ddkbuild\obj%BUILD_ALT_DIR%\%cpudir% -@echo on - -copy %srcPath%\hotplugtest.exe %dstPath%\examples -copy %srcPath%\hotplugtest.pdb %dstPath%\examples - -@echo off - -cd msvc -goto done - -:usage -echo ddk_build must be run in a WDK build environment -pause -goto done - -:builderror -echo Build failed - -:done -cd %PWD% diff --git a/Externals/libusb/msvc/errno.h b/Externals/libusb/msvc/errno.h deleted file mode 100644 index 07d15e3d44..0000000000 --- a/Externals/libusb/msvc/errno.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * errno.h - * This file has no copyright assigned and is placed in the Public Domain. - * This file is a part of the mingw-runtime package. - * No warranty is given; refer to the file DISCLAIMER within the package. - * - * Error numbers and access to error reporting. - * - */ - -#ifndef _ERRNO_H_ -#define _ERRNO_H_ - -#include - -/* - * Error numbers. - * TODO: Can't be sure of some of these assignments, I guessed from the - * names given by strerror and the defines in the Cygnus errno.h. A lot - * of the names from the Cygnus errno.h are not represented, and a few - * of the descriptions returned by strerror do not obviously match - * their error naming. - */ -#define EPERM 1 /* Operation not permitted */ -#define ENOFILE 2 /* No such file or directory */ -#define ENOENT 2 -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted function call */ -#define EIO 5 /* Input/output error */ -#define ENXIO 6 /* No such device or address */ -#define E2BIG 7 /* Arg list too long */ -#define ENOEXEC 8 /* Exec format error */ -#define EBADF 9 /* Bad file descriptor */ -#define ECHILD 10 /* No child processes */ -#define EAGAIN 11 /* Resource temporarily unavailable */ -#define ENOMEM 12 /* Not enough space */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -/* 15 - Unknown Error */ -#define EBUSY 16 /* strerror reports "Resource device" */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Improper link (cross-device link?) */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENFILE 23 /* Too many open files in system */ -#define EMFILE 24 /* Too many open files */ -#define ENOTTY 25 /* Inappropriate I/O control operation */ -/* 26 - Unknown Error */ -#define EFBIG 27 /* File too large */ -#define ENOSPC 28 /* No space left on device */ -#define ESPIPE 29 /* Invalid seek (seek on a pipe?) */ -#define EROFS 30 /* Read-only file system */ -#define EMLINK 31 /* Too many links */ -#define EPIPE 32 /* Broken pipe */ -#define EDOM 33 /* Domain error (math functions) */ -#define ERANGE 34 /* Result too large (possibly too small) */ -/* 35 - Unknown Error */ -#define EDEADLOCK 36 /* Resource deadlock avoided (non-Cyg) */ -#define EDEADLK 36 -#if 0 -/* 37 - Unknown Error */ -#define ENAMETOOLONG 38 /* Filename too long (91 in Cyg?) */ -#define ENOLCK 39 /* No locks available (46 in Cyg?) */ -#define ENOSYS 40 /* Function not implemented (88 in Cyg?) */ -#define ENOTEMPTY 41 /* Directory not empty (90 in Cyg?) */ -#define EILSEQ 42 /* Illegal byte sequence */ -#endif - -/* - * NOTE: ENAMETOOLONG and ENOTEMPTY conflict with definitions in the - * sockets.h header provided with windows32api-0.1.2. - * You should go and put an #if 0 ... #endif around the whole block - * of errors (look at the comment above them). - */ - -#ifndef RC_INVOKED - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Definitions of errno. For _doserrno, sys_nerr and * sys_errlist, see - * stdlib.h. - */ -#if defined(_UWIN) || defined(_WIN32_WCE) -#undef errno -extern int errno; -#else -_CRTIMP int* __cdecl _errno(void); -#define errno (*_errno()) -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* Not RC_INVOKED */ - -#endif /* Not _ERRNO_H_ */ \ No newline at end of file diff --git a/Externals/libusb/msvc/fxload_2010.vcxproj b/Externals/libusb/msvc/fxload_2010.vcxproj deleted file mode 100644 index 56e585303c..0000000000 --- a/Externals/libusb/msvc/fxload_2010.vcxproj +++ /dev/null @@ -1,170 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - fxload - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88} - examples - Win32Proj - - - - Application - Unicode - true - - - Application - Unicode - - - Application - Unicode - true - - - Application - Unicode - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - .;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories) - WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - .;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories) - WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - .;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories) - WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - .;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories) - WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - {ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e} - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/fxload_2010.vcxproj.filters b/Externals/libusb/msvc/fxload_2010.vcxproj.filters deleted file mode 100644 index 824ae40362..0000000000 --- a/Externals/libusb/msvc/fxload_2010.vcxproj.filters +++ /dev/null @@ -1,25 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {651ff73d-037b-4903-8dd3-56e9950be25c} - - - - - Source Files - - - Source Files - - - - - Header Files - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/fxload_2012.vcxproj b/Externals/libusb/msvc/fxload_2012.vcxproj deleted file mode 100644 index fb53a43d55..0000000000 --- a/Externals/libusb/msvc/fxload_2012.vcxproj +++ /dev/null @@ -1,174 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - fxload - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88} - examples - Win32Proj - - - - Application - Unicode - true - v110 - - - Application - Unicode - v110 - - - Application - Unicode - true - v110 - - - Application - Unicode - v110 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - .;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories) - WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - .;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories) - WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - .;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories) - WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - .;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories) - WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - {ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e} - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/fxload_2012.vcxproj.filters b/Externals/libusb/msvc/fxload_2012.vcxproj.filters deleted file mode 100644 index 824ae40362..0000000000 --- a/Externals/libusb/msvc/fxload_2012.vcxproj.filters +++ /dev/null @@ -1,25 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {651ff73d-037b-4903-8dd3-56e9950be25c} - - - - - Source Files - - - Source Files - - - - - Header Files - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/fxload_2013.vcxproj b/Externals/libusb/msvc/fxload_2013.vcxproj deleted file mode 100644 index 74a0d28247..0000000000 --- a/Externals/libusb/msvc/fxload_2013.vcxproj +++ /dev/null @@ -1,174 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - fxload - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88} - examples - Win32Proj - - - - Application - Unicode - true - v120 - - - Application - Unicode - v120 - - - Application - Unicode - true - v120 - - - Application - Unicode - v120 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - .;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories) - WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - .;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories) - WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - .;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories) - WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - .;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories) - WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - {ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e} - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/fxload_2015.vcxproj b/Externals/libusb/msvc/fxload_2015.vcxproj deleted file mode 100644 index 1ef31d3a96..0000000000 --- a/Externals/libusb/msvc/fxload_2015.vcxproj +++ /dev/null @@ -1,174 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - fxload - {9E166F7A-A793-9FB6-0A67-F0AED8AE8C88} - examples - Win32Proj - - - - Application - Unicode - true - v140 - - - Application - Unicode - v140 - - - Application - Unicode - true - v140 - - - Application - Unicode - v140 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - .;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories) - WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - .;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories) - WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - .;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories) - WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - .;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories) - WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - {ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e} - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/fxload_sources b/Externals/libusb/msvc/fxload_sources deleted file mode 100644 index d6e31d691b..0000000000 --- a/Externals/libusb/msvc/fxload_sources +++ /dev/null @@ -1,23 +0,0 @@ -TARGETNAME=fxload -TARGETTYPE=PROGRAM -386_STDCALL=0 - -_NT_TARGET_VERSION= $(_NT_TARGET_VERSION_WINXP) - -!IFNDEF MSC_WARNING_LEVEL -MSC_WARNING_LEVEL=/W3 -!ENDIF - -!IFDEF STATIC_LIBC -USE_LIBCMT=1 -!ELSE -USE_MSVCRT=1 -!ENDIF - -UMTYPE=console -INCLUDES=..\..\msvc;..\..\libusb;..\getopt;$(DDK_INC_PATH) -C_DEFINES=$(C_DEFINES) /D__GNU_LIBRARY__ -UMLIBS=..\..\libusb\os\obj$(BUILD_ALT_DIR)\*\libusb-1.0.lib \ - ..\getopt\getopt_ddkbuild\obj$(BUILD_ALT_DIR)\*\getopt.lib -SOURCES=..\ezusb.c \ - ..\fxload.c diff --git a/Externals/libusb/msvc/getopt_2005.vcproj b/Externals/libusb/msvc/getopt_2005.vcproj deleted file mode 100644 index a98a0a805f..0000000000 --- a/Externals/libusb/msvc/getopt_2005.vcproj +++ /dev/null @@ -1,288 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Externals/libusb/msvc/getopt_2010.vcxproj b/Externals/libusb/msvc/getopt_2010.vcxproj deleted file mode 100644 index 66c5e44144..0000000000 --- a/Externals/libusb/msvc/getopt_2010.vcxproj +++ /dev/null @@ -1,131 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E} - getopt - - - - StaticLibrary - Unicode - true - - - StaticLibrary - Unicode - - - StaticLibrary - Unicode - true - - - StaticLibrary - Unicode - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\ - - - - HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - true - - - - - X64 - - - HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebug - Level3 - ProgramDatabase - - - true - - - - - MaxSpeed - HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - true - - - - - X64 - - - HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - true - - - - - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/getopt_2010.vcxproj.filters b/Externals/libusb/msvc/getopt_2010.vcxproj.filters deleted file mode 100644 index 7cf095b2ce..0000000000 --- a/Externals/libusb/msvc/getopt_2010.vcxproj.filters +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Source Files - - - Source Files - - - - - Header Files - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/getopt_2012.vcxproj b/Externals/libusb/msvc/getopt_2012.vcxproj deleted file mode 100644 index 01b792832e..0000000000 --- a/Externals/libusb/msvc/getopt_2012.vcxproj +++ /dev/null @@ -1,136 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E} - getopt - getopt - - - - StaticLibrary - Unicode - true - v110 - - - StaticLibrary - Unicode - v110 - - - StaticLibrary - Unicode - true - v110 - - - StaticLibrary - Unicode - v110 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\ - - - - HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - true - - - - - X64 - - - HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebug - Level3 - ProgramDatabase - - - true - - - - - MaxSpeed - HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - true - - - - - X64 - - - HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - true - - - - - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/getopt_2012.vcxproj.filters b/Externals/libusb/msvc/getopt_2012.vcxproj.filters deleted file mode 100644 index 7cf095b2ce..0000000000 --- a/Externals/libusb/msvc/getopt_2012.vcxproj.filters +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Source Files - - - Source Files - - - - - Header Files - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/getopt_2013.vcxproj b/Externals/libusb/msvc/getopt_2013.vcxproj deleted file mode 100644 index ee36fd405d..0000000000 --- a/Externals/libusb/msvc/getopt_2013.vcxproj +++ /dev/null @@ -1,136 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E} - getopt - getopt - - - - StaticLibrary - Unicode - true - v120 - - - StaticLibrary - Unicode - v120 - - - StaticLibrary - Unicode - true - v120 - - - StaticLibrary - Unicode - v120 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\ - - - - HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - true - - - - - X64 - - - HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebug - Level3 - ProgramDatabase - - - true - - - - - MaxSpeed - HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - true - - - - - X64 - - - HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - true - - - - - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/getopt_2015.vcxproj b/Externals/libusb/msvc/getopt_2015.vcxproj deleted file mode 100644 index d1c81a0881..0000000000 --- a/Externals/libusb/msvc/getopt_2015.vcxproj +++ /dev/null @@ -1,136 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E} - getopt - getopt - - - - StaticLibrary - Unicode - true - v140 - - - StaticLibrary - Unicode - v140 - - - StaticLibrary - Unicode - true - v140 - - - StaticLibrary - Unicode - v140 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\getopt\ - - - - HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - true - - - - - X64 - - - HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebug - Level3 - ProgramDatabase - - - true - - - - - MaxSpeed - HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - true - - - - - X64 - - - HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - true - - - - - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/getopt_sources b/Externals/libusb/msvc/getopt_sources deleted file mode 100644 index b9adc1b75a..0000000000 --- a/Externals/libusb/msvc/getopt_sources +++ /dev/null @@ -1,20 +0,0 @@ -TARGETTYPE=LIBRARY -TARGETNAME=getopt -386_STDCALL=0 - -_NT_TARGET_VERSION= $(_NT_TARGET_VERSION_WINXP) - -!IFNDEF MSC_WARNING_LEVEL -MSC_WARNING_LEVEL=/W3 -!ENDIF - -USE_MSVCRT=1 - -INCLUDES=$(DDK_INC_PATH) -C_DEFINES = $(C_DEFINES) /DDDKBUILD /DHAVE_STRING_H - -TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ - $(SDK_LIB_PATH)\user32.lib - -SOURCES=..\getopt1.c \ - ..\getopt.c diff --git a/Externals/libusb/msvc/hotplugtest_2010.vcxproj b/Externals/libusb/msvc/hotplugtest_2010.vcxproj deleted file mode 100644 index ae4afeb336..0000000000 --- a/Externals/libusb/msvc/hotplugtest_2010.vcxproj +++ /dev/null @@ -1,163 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - hotplugtest - {99D2AC64-DC66-4422-91CE-6715C403C9E5} - examples - Win32Proj - - - - Application - Unicode - true - - - Application - Unicode - - - Application - Unicode - true - - - Application - Unicode - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/hotplugtest_2010.vcxproj.filters b/Externals/libusb/msvc/hotplugtest_2010.vcxproj.filters deleted file mode 100644 index 125ac1be48..0000000000 --- a/Externals/libusb/msvc/hotplugtest_2010.vcxproj.filters +++ /dev/null @@ -1,14 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Source Files - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/hotplugtest_2012.vcxproj b/Externals/libusb/msvc/hotplugtest_2012.vcxproj deleted file mode 100644 index 4460e364e1..0000000000 --- a/Externals/libusb/msvc/hotplugtest_2012.vcxproj +++ /dev/null @@ -1,167 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - hotplugtest - {99D2AC64-DC66-4422-91CE-6715C403C9E5} - examples - Win32Proj - - - - Application - Unicode - true - v110 - - - Application - Unicode - v110 - - - Application - Unicode - true - v110 - - - Application - Unicode - v110 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/hotplugtest_2012.vcxproj.filters b/Externals/libusb/msvc/hotplugtest_2012.vcxproj.filters deleted file mode 100644 index 125ac1be48..0000000000 --- a/Externals/libusb/msvc/hotplugtest_2012.vcxproj.filters +++ /dev/null @@ -1,14 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Source Files - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/hotplugtest_2013.vcxproj b/Externals/libusb/msvc/hotplugtest_2013.vcxproj deleted file mode 100644 index 578c6fff34..0000000000 --- a/Externals/libusb/msvc/hotplugtest_2013.vcxproj +++ /dev/null @@ -1,167 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - hotplugtest - {99D2AC64-DC66-4422-91CE-6715C403C9E5} - examples - Win32Proj - - - - Application - Unicode - true - v120 - - - Application - Unicode - v120 - - - Application - Unicode - true - v120 - - - Application - Unicode - v120 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/hotplugtest_2015.vcxproj b/Externals/libusb/msvc/hotplugtest_2015.vcxproj deleted file mode 100644 index 377e1c5f2b..0000000000 --- a/Externals/libusb/msvc/hotplugtest_2015.vcxproj +++ /dev/null @@ -1,167 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - hotplugtest - {99D2AC64-DC66-4422-91CE-6715C403C9E5} - examples - Win32Proj - - - - Application - Unicode - true - v140 - - - Application - Unicode - v140 - - - Application - Unicode - true - v140 - - - Application - Unicode - v140 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/hotplugtest_sources b/Externals/libusb/msvc/hotplugtest_sources deleted file mode 100644 index 1b27cad913..0000000000 --- a/Externals/libusb/msvc/hotplugtest_sources +++ /dev/null @@ -1,20 +0,0 @@ -TARGETNAME=hotplugtest -TARGETTYPE=PROGRAM -386_STDCALL=0 - -_NT_TARGET_VERSION= $(_NT_TARGET_VERSION_WINXP) - -!IFNDEF MSC_WARNING_LEVEL -MSC_WARNING_LEVEL=/W3 -!ENDIF - -!IFDEF STATIC_LIBC -USE_LIBCMT=1 -!ELSE -USE_MSVCRT=1 -!ENDIF - -UMTYPE=console -INCLUDES=..\..\msvc;..\..\libusb;$(DDK_INC_PATH) -UMLIBS=..\..\libusb\os\obj$(BUILD_ALT_DIR)\*\libusb-1.0.lib -SOURCES=..\hotplugtest.c diff --git a/Externals/libusb/msvc/inttypes.h b/Externals/libusb/msvc/inttypes.h deleted file mode 100644 index 289bb50b4d..0000000000 --- a/Externals/libusb/msvc/inttypes.h +++ /dev/null @@ -1,295 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file was original part of the w64 mingw-runtime package. - */ - -/* - * THIS SOFTWARE IS NOT COPYRIGHTED - * - * Modified for libusb/MSVC: Pete Batard - * - * This source code is offered for use in the public domain. You may - * use, modify or distribute it freely. - * - * This code is distributed in the hope that it will be useful but - * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY - * DISCLAIMED. This includes but is not limited to warranties of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Date: 2010-04-02 - */ - -#ifndef _MSC_VER -#error This header should only be used with Microsoft compilers -#endif - -/* 7.8 Format conversion of integer types */ - -#ifndef _INTTYPES_H_ -#define _INTTYPES_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - intmax_t quot; - intmax_t rem; - } imaxdiv_t; - - -/* 7.8.1 Macros for format specifiers - * - * MS runtime does not yet understand C9x standard "ll" - * length specifier. It appears to treat "ll" as "l". - * The non-standard I64 length specifier causes warning in GCC, - * but understood by MS runtime functions. - */ - -/* fprintf macros for signed types */ -#define PRId8 "d" -#define PRId16 "d" -#define PRId32 "d" -#define PRId64 "I64d" - -#define PRIdLEAST8 "d" -#define PRIdLEAST16 "d" -#define PRIdLEAST32 "d" -#define PRIdLEAST64 "I64d" - -#define PRIdFAST8 "d" -#define PRIdFAST16 "d" -#define PRIdFAST32 "d" -#define PRIdFAST64 "I64d" - -#define PRIdMAX "I64d" - -#define PRIi8 "i" -#define PRIi16 "i" -#define PRIi32 "i" -#define PRIi64 "I64i" - -#define PRIiLEAST8 "i" -#define PRIiLEAST16 "i" -#define PRIiLEAST32 "i" -#define PRIiLEAST64 "I64i" - -#define PRIiFAST8 "i" -#define PRIiFAST16 "i" -#define PRIiFAST32 "i" -#define PRIiFAST64 "I64i" - -#define PRIiMAX "I64i" - -#define PRIo8 "o" -#define PRIo16 "o" -#define PRIo32 "o" -#define PRIo64 "I64o" - -#define PRIoLEAST8 "o" -#define PRIoLEAST16 "o" -#define PRIoLEAST32 "o" -#define PRIoLEAST64 "I64o" - -#define PRIoFAST8 "o" -#define PRIoFAST16 "o" -#define PRIoFAST32 "o" -#define PRIoFAST64 "I64o" - -#define PRIoMAX "I64o" - -/* fprintf macros for unsigned types */ -#define PRIu8 "u" -#define PRIu16 "u" -#define PRIu32 "u" -#define PRIu64 "I64u" - - -#define PRIuLEAST8 "u" -#define PRIuLEAST16 "u" -#define PRIuLEAST32 "u" -#define PRIuLEAST64 "I64u" - -#define PRIuFAST8 "u" -#define PRIuFAST16 "u" -#define PRIuFAST32 "u" -#define PRIuFAST64 "I64u" - -#define PRIuMAX "I64u" - -#define PRIx8 "x" -#define PRIx16 "x" -#define PRIx32 "x" -#define PRIx64 "I64x" - -#define PRIxLEAST8 "x" -#define PRIxLEAST16 "x" -#define PRIxLEAST32 "x" -#define PRIxLEAST64 "I64x" - -#define PRIxFAST8 "x" -#define PRIxFAST16 "x" -#define PRIxFAST32 "x" -#define PRIxFAST64 "I64x" - -#define PRIxMAX "I64x" - -#define PRIX8 "X" -#define PRIX16 "X" -#define PRIX32 "X" -#define PRIX64 "I64X" - -#define PRIXLEAST8 "X" -#define PRIXLEAST16 "X" -#define PRIXLEAST32 "X" -#define PRIXLEAST64 "I64X" - -#define PRIXFAST8 "X" -#define PRIXFAST16 "X" -#define PRIXFAST32 "X" -#define PRIXFAST64 "I64X" - -#define PRIXMAX "I64X" - -/* - * fscanf macros for signed int types - * NOTE: if 32-bit int is used for int_fast8_t and int_fast16_t - * (see stdint.h, 7.18.1.3), FAST8 and FAST16 should have - * no length identifiers - */ - -#define SCNd16 "hd" -#define SCNd32 "d" -#define SCNd64 "I64d" - -#define SCNdLEAST16 "hd" -#define SCNdLEAST32 "d" -#define SCNdLEAST64 "I64d" - -#define SCNdFAST16 "hd" -#define SCNdFAST32 "d" -#define SCNdFAST64 "I64d" - -#define SCNdMAX "I64d" - -#define SCNi16 "hi" -#define SCNi32 "i" -#define SCNi64 "I64i" - -#define SCNiLEAST16 "hi" -#define SCNiLEAST32 "i" -#define SCNiLEAST64 "I64i" - -#define SCNiFAST16 "hi" -#define SCNiFAST32 "i" -#define SCNiFAST64 "I64i" - -#define SCNiMAX "I64i" - -#define SCNo16 "ho" -#define SCNo32 "o" -#define SCNo64 "I64o" - -#define SCNoLEAST16 "ho" -#define SCNoLEAST32 "o" -#define SCNoLEAST64 "I64o" - -#define SCNoFAST16 "ho" -#define SCNoFAST32 "o" -#define SCNoFAST64 "I64o" - -#define SCNoMAX "I64o" - -#define SCNx16 "hx" -#define SCNx32 "x" -#define SCNx64 "I64x" - -#define SCNxLEAST16 "hx" -#define SCNxLEAST32 "x" -#define SCNxLEAST64 "I64x" - -#define SCNxFAST16 "hx" -#define SCNxFAST32 "x" -#define SCNxFAST64 "I64x" - -#define SCNxMAX "I64x" - -/* fscanf macros for unsigned int types */ - -#define SCNu16 "hu" -#define SCNu32 "u" -#define SCNu64 "I64u" - -#define SCNuLEAST16 "hu" -#define SCNuLEAST32 "u" -#define SCNuLEAST64 "I64u" - -#define SCNuFAST16 "hu" -#define SCNuFAST32 "u" -#define SCNuFAST64 "I64u" - -#define SCNuMAX "I64u" - -#ifdef _WIN64 -#define PRIdPTR "I64d" -#define PRIiPTR "I64i" -#define PRIoPTR "I64o" -#define PRIuPTR "I64u" -#define PRIxPTR "I64x" -#define PRIXPTR "I64X" -#define SCNdPTR "I64d" -#define SCNiPTR "I64i" -#define SCNoPTR "I64o" -#define SCNxPTR "I64x" -#define SCNuPTR "I64u" -#else -#define PRIdPTR "d" -#define PRIiPTR "i" -#define PRIoPTR "o" -#define PRIuPTR "u" -#define PRIxPTR "x" -#define PRIXPTR "X" -#define SCNdPTR "d" -#define SCNiPTR "i" -#define SCNoPTR "o" -#define SCNxPTR "x" - #define SCNuPTR "u" -#endif - -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -/* - * no length modifier for char types prior to C9x - * MS runtime scanf appears to treat "hh" as "h" - */ - -/* signed char */ -#define SCNd8 "hhd" -#define SCNdLEAST8 "hhd" -#define SCNdFAST8 "hhd" - -#define SCNi8 "hhi" -#define SCNiLEAST8 "hhi" -#define SCNiFAST8 "hhi" - -#define SCNo8 "hho" -#define SCNoLEAST8 "hho" -#define SCNoFAST8 "hho" - -#define SCNx8 "hhx" -#define SCNxLEAST8 "hhx" -#define SCNxFAST8 "hhx" - -/* unsigned char */ -#define SCNu8 "hhu" -#define SCNuLEAST8 "hhu" -#define SCNuFAST8 "hhu" -#endif /* __STDC_VERSION__ >= 199901 */ - - -#ifdef __cplusplus -} -#endif - -#endif /* ndef _INTTYPES_H */ diff --git a/Externals/libusb/msvc/libusb.dsw b/Externals/libusb/msvc/libusb.dsw deleted file mode 100644 index 4e2652e3d4..0000000000 --- a/Externals/libusb/msvc/libusb.dsw +++ /dev/null @@ -1,71 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "libusb_dll"=".\libusb_dll.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "libusb_static"=".\libusb_static.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "listdevs"=".\listdevs.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name libusb_static - End Project Dependency -}}} - -############################################################################### - -Project: "xusb"=".\xusb.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name libusb_static - End Project Dependency -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/Externals/libusb/msvc/libusb_dll.dsp b/Externals/libusb/msvc/libusb_dll.dsp deleted file mode 100644 index f6a894566a..0000000000 --- a/Externals/libusb/msvc/libusb_dll.dsp +++ /dev/null @@ -1,194 +0,0 @@ -# Microsoft Developer Studio Project File - Name="libusb_dll" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=libusb_dll - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "libusb_dll.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "libusb_dll.mak" CFG="libusb_dll - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "libusb_dll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "libusb_dll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "libusb_dll - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "../Win32/Release/dll" -# PROP Intermediate_Dir "../Win32/Release/dll" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "LIBUSB_DLL_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../libusb" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /U "_MBCS" /D "_USRDLL" /FR /FD /EHsc /c -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"Win32/Release/dll/libusb-1.0.dll" - -!ELSEIF "$(CFG)" == "libusb_dll - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "../Win32/Debug/dll" -# PROP Intermediate_Dir "../Win32/Debug/dll" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "LIBUSB_DLL_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "../libusb" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /U "_MBCS" /D "_USRDLL" /FR /FD /EHsc /c -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo /n -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"Win32/Debug/dll/libusb-1.0.dll" -# SUBTRACT LINK32 /pdb:none /incremental:no - -!ENDIF - -# Begin Target - -# Name "libusb_dll - Win32 Release" -# Name "libusb_dll - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\libusb\core.c -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\darwin_usb.c -# PROP Exclude_From_Build 1 -# End Source File -# Begin Source File - -SOURCE=..\libusb\descriptor.c -# End Source File -# Begin Source File - -SOURCE=..\libusb\io.c -# End Source File -# Begin Source File - -SOURCE="..\libusb\libusb-1.0.rc" -# End Source File -# Begin Source File - -SOURCE="..\libusb\libusb-1.0.def" -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\linux_usbfs.c -# PROP Exclude_From_Build 1 -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\poll_windows.c -# End Source File -# Begin Source File - -SOURCE=..\libusb\sync.c -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\threads_windows.c -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\windows_winusb.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\config.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\darwin_usb.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\libusb.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\libusbi.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\linux_usbfs.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\poll_posix.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\poll_windows.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\threads_posix.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\threads_windows.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\windows_winusb.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\windows_common.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/Externals/libusb/msvc/libusb_dll_2005.vcproj b/Externals/libusb/msvc/libusb_dll_2005.vcproj deleted file mode 100644 index 2801f7fd0a..0000000000 --- a/Externals/libusb/msvc/libusb_dll_2005.vcproj +++ /dev/null @@ -1,436 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Externals/libusb/msvc/libusb_dll_2010.vcxproj b/Externals/libusb/msvc/libusb_dll_2010.vcxproj deleted file mode 100644 index a1f03181a5..0000000000 --- a/Externals/libusb/msvc/libusb_dll_2010.vcxproj +++ /dev/null @@ -1,174 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - libusb-1.0 (dll) - {349EE8FA-7D25-4909-AAF5-FF3FADE72187} - libusbdll - - - - DynamicLibrary - Unicode - true - - - DynamicLibrary - Unicode - - - DynamicLibrary - Unicode - true - - - DynamicLibrary - Unicode - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\ - libusb-1.0 - libusb-1.0 - libusb-1.0 - libusb-1.0 - - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - $(OutDir)libusb-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - true - - - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - $(OutDir)libusb-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - true - - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDLL - Level4 - - - $(OutDir)libusb-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - - - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDLL - Level4 - - - $(OutDir)libusb-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/libusb_dll_2010.vcxproj.filters b/Externals/libusb/msvc/libusb_dll_2010.vcxproj.filters deleted file mode 100644 index 4e1ccab5c1..0000000000 --- a/Externals/libusb/msvc/libusb_dll_2010.vcxproj.filters +++ /dev/null @@ -1,81 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {d81e81ca-b13e-4a15-b54b-b12b41361e6b} - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Resource Files - - - - - Resource Files - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/libusb_dll_2012.vcxproj b/Externals/libusb/msvc/libusb_dll_2012.vcxproj deleted file mode 100644 index 004bf112cc..0000000000 --- a/Externals/libusb/msvc/libusb_dll_2012.vcxproj +++ /dev/null @@ -1,178 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - libusb-1.0 (dll) - {349EE8FA-7D25-4909-AAF5-FF3FADE72187} - libusbdll - - - - DynamicLibrary - Unicode - true - v110 - - - DynamicLibrary - Unicode - v110 - - - DynamicLibrary - Unicode - true - v110 - - - DynamicLibrary - Unicode - v110 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\ - libusb-1.0 - libusb-1.0 - libusb-1.0 - libusb-1.0 - - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - $(OutDir)libusb-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - true - - - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - $(OutDir)libusb-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - true - - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDLL - Level4 - - - $(OutDir)libusb-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - - - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDLL - Level4 - - - $(OutDir)libusb-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/libusb_dll_2012.vcxproj.filters b/Externals/libusb/msvc/libusb_dll_2012.vcxproj.filters deleted file mode 100644 index 65e44f96a3..0000000000 --- a/Externals/libusb/msvc/libusb_dll_2012.vcxproj.filters +++ /dev/null @@ -1,84 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {d81e81ca-b13e-4a15-b54b-b12b41361e6b} - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Resource Files - - - - - Resource Files - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/libusb_dll_2013.vcxproj b/Externals/libusb/msvc/libusb_dll_2013.vcxproj deleted file mode 100644 index 80d1a29391..0000000000 --- a/Externals/libusb/msvc/libusb_dll_2013.vcxproj +++ /dev/null @@ -1,178 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - libusb-1.0 (dll) - {349EE8FA-7D25-4909-AAF5-FF3FADE72187} - libusbdll - - - - DynamicLibrary - Unicode - true - v120 - - - DynamicLibrary - Unicode - v120 - - - DynamicLibrary - Unicode - true - v120 - - - DynamicLibrary - Unicode - v120 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\ - libusb-1.0 - libusb-1.0 - libusb-1.0 - libusb-1.0 - - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - $(OutDir)libusb-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - true - - - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - $(OutDir)libusb-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - true - - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDLL - Level4 - - - $(OutDir)libusb-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - - - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDLL - Level4 - - - $(OutDir)libusb-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/libusb_dll_2015.vcxproj b/Externals/libusb/msvc/libusb_dll_2015.vcxproj deleted file mode 100644 index 202f6c0a0f..0000000000 --- a/Externals/libusb/msvc/libusb_dll_2015.vcxproj +++ /dev/null @@ -1,178 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - libusb-1.0 (dll) - {349EE8FA-7D25-4909-AAF5-FF3FADE72187} - libusbdll - - - - DynamicLibrary - Unicode - true - v140 - - - DynamicLibrary - Unicode - v140 - - - DynamicLibrary - Unicode - true - v140 - - - DynamicLibrary - Unicode - v140 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0\ - libusb-1.0 - libusb-1.0 - libusb-1.0 - libusb-1.0 - - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - $(OutDir)libusb-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - true - - - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - $(OutDir)libusb-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - true - - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDLL - Level4 - - - $(OutDir)libusb-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - - - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDLL - Level4 - - - $(OutDir)libusb-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/libusb_dll_wince.vcproj b/Externals/libusb/msvc/libusb_dll_wince.vcproj deleted file mode 100644 index 77b1858b03..0000000000 --- a/Externals/libusb/msvc/libusb_dll_wince.vcproj +++ /dev/null @@ -1,1243 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Externals/libusb/msvc/libusb_sources b/Externals/libusb/msvc/libusb_sources deleted file mode 100644 index c527ac7341..0000000000 --- a/Externals/libusb/msvc/libusb_sources +++ /dev/null @@ -1,45 +0,0 @@ -#TARGETTYPE is not defined, to allow selection between static lib or DLL with ddk_build -TARGETNAME=libusb-1.0 -DLLDEF=..\libusb-1.0.def - -!IFNDEF MSC_WARNING_LEVEL -MSC_WARNING_LEVEL=/W3 -!ENDIF - -!IFDEF STATIC_LIBC -USE_LIBCMT=1 -!ELSE -USE_MSVCRT=1 -!ENDIF - -!IFDEF WITH_USBDK -BACKEND_DEFINES="/DUSE_USBDK" -!ENDIF - -INCLUDES=..;..\..\msvc;$(DDK_INC_PATH) -C_DEFINES= $(C_DEFINES) $(LIBUSB_DEFINES) $(BACKEND_DEFINES) /DDDKBUILD - -# http://jpassing.com/2009/10/21/ltcg-issues-with-the-win7amd64-environment-of-wdk-7600/ -# prevents the following error when using the 64 bit static lib with Visual Studio 2010: -# "fatal error C1001: An internal error has occurred in the compiler. -# (compiler file 'f:\dd\vctools\compiler\utc\src\p2\p2symtab.c', line 1823)" -# and the following with Visual Studio 2010: -# "fatal error C1047: The object or library file 'libusb-1.0.lib' was created with -# an older compiler than other objects; rebuild old objects and libraries" -USER_C_FLAGS=/GL- - -TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib - -SOURCES=..\core.c \ - ..\descriptor.c \ - ..\io.c \ - ..\strerror.c \ - ..\sync.c \ - ..\hotplug.c \ - threads_windows.c \ - poll_windows.c \ - windows_usbdk.c \ - windows_winusb.c \ - windows_usbdk.c \ - windows_nt_common.c \ - ..\libusb-1.0.rc diff --git a/Externals/libusb/msvc/libusb_static.dsp b/Externals/libusb/msvc/libusb_static.dsp deleted file mode 100644 index b138cd0ebe..0000000000 --- a/Externals/libusb/msvc/libusb_static.dsp +++ /dev/null @@ -1,174 +0,0 @@ -# Microsoft Developer Studio Project File - Name="libusb_static" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -CFG=libusb_static - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "libusb_static.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "libusb_static.mak" CFG="libusb_static - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "libusb_static - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "libusb_static - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "libusb_static - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "../Win32/Release/lib" -# PROP Intermediate_Dir "../Win32/Release/lib" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../libusb" /D "WIN32" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /U "_MBCS" /D "_LIB" /FR /FD /EHsc /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"../Win32/Release/lib/libusb-1.0.lib" - -!ELSEIF "$(CFG)" == "libusb_static - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "../Win32/Debug/lib" -# PROP Intermediate_Dir "../Win32/Debug/lib" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "../libusb" /D "WIN32" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /U "_MBCS" /D "_LIB" /FR /FD /GZ /EHsc /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo /n -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"../Win32/Debug/lib/libusb-1.0.lib" - -!ENDIF - -# Begin Target - -# Name "libusb_static - Win32 Release" -# Name "libusb_static - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\libusb\core.c -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\darwin_usb.c -# PROP Exclude_From_Build 1 -# End Source File -# Begin Source File - -SOURCE=..\libusb\descriptor.c -# End Source File -# Begin Source File - -SOURCE=..\libusb\io.c -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\linux_usbfs.c -# PROP Exclude_From_Build 1 -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\poll_windows.c -# End Source File -# Begin Source File - -SOURCE=..\libusb\sync.c -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\threads_windows.c -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\windows_winusb.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\config.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\darwin_usb.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\libusb.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\libusbi.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\linux_usbfs.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\poll_posix.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\poll_windows.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\threads_posix.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\threads_windows.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\windows_winusb.h -# End Source File -# Begin Source File - -SOURCE=..\libusb\os\windows_common.h -# End Source File -# End Group -# End Target -# End Project diff --git a/Externals/libusb/msvc/libusb_static_2005.vcproj b/Externals/libusb/msvc/libusb_static_2005.vcproj deleted file mode 100644 index a649db3d5f..0000000000 --- a/Externals/libusb/msvc/libusb_static_2005.vcproj +++ /dev/null @@ -1,362 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Externals/libusb/msvc/libusb_static_2010.vcxproj b/Externals/libusb/msvc/libusb_static_2010.vcxproj deleted file mode 100644 index 76f40e767a..0000000000 --- a/Externals/libusb/msvc/libusb_static_2010.vcxproj +++ /dev/null @@ -1,158 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - libusb-1.0 (static) - {349EE8F9-7D25-4909-AAF5-FF3FADE72187} - libusb - - - - StaticLibrary - Unicode - true - - - StaticLibrary - Unicode - - - StaticLibrary - Unicode - true - - - StaticLibrary - Unicode - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\ - libusb-1.0 - libusb-1.0 - libusb-1.0 - libusb-1.0 - - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebug - Level4 - ProgramDatabase - - - $(OutDir)libusb-1.0.lib - - - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebug - Level4 - ProgramDatabase - - - $(OutDir)libusb-1.0.lib - - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level4 - - - $(OutDir)libusb-1.0.lib - - - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level4 - - - $(OutDir)libusb-1.0.lib - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/libusb_static_2010.vcxproj.filters b/Externals/libusb/msvc/libusb_static_2010.vcxproj.filters deleted file mode 100644 index 2c396e34cc..0000000000 --- a/Externals/libusb/msvc/libusb_static_2010.vcxproj.filters +++ /dev/null @@ -1,74 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/libusb_static_2012.vcxproj b/Externals/libusb/msvc/libusb_static_2012.vcxproj deleted file mode 100644 index 896794f3d7..0000000000 --- a/Externals/libusb/msvc/libusb_static_2012.vcxproj +++ /dev/null @@ -1,162 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - libusb-1.0 (static) - {349EE8F9-7D25-4909-AAF5-FF3FADE72187} - libusb - - - - StaticLibrary - Unicode - true - v110 - - - StaticLibrary - Unicode - v110 - - - StaticLibrary - Unicode - true - v110 - - - StaticLibrary - Unicode - v110 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\ - libusb-1.0 - libusb-1.0 - libusb-1.0 - libusb-1.0 - - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebug - Level4 - ProgramDatabase - - - $(OutDir)libusb-1.0.lib - - - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebug - Level4 - ProgramDatabase - - - $(OutDir)libusb-1.0.lib - - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level4 - - - $(OutDir)libusb-1.0.lib - - - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level4 - - - $(OutDir)libusb-1.0.lib - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/libusb_static_2012.vcxproj.filters b/Externals/libusb/msvc/libusb_static_2012.vcxproj.filters deleted file mode 100644 index 2c396e34cc..0000000000 --- a/Externals/libusb/msvc/libusb_static_2012.vcxproj.filters +++ /dev/null @@ -1,74 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/libusb_static_2013.vcxproj b/Externals/libusb/msvc/libusb_static_2013.vcxproj deleted file mode 100644 index 74833e810c..0000000000 --- a/Externals/libusb/msvc/libusb_static_2013.vcxproj +++ /dev/null @@ -1,162 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - libusb-1.0 (static) - {349EE8F9-7D25-4909-AAF5-FF3FADE72187} - libusb - - - - StaticLibrary - Unicode - true - v120 - - - StaticLibrary - Unicode - v120 - - - StaticLibrary - Unicode - true - v120 - - - StaticLibrary - Unicode - v120 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\ - libusb-1.0 - libusb-1.0 - libusb-1.0 - libusb-1.0 - - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebug - Level4 - ProgramDatabase - - - $(OutDir)libusb-1.0.lib - - - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebug - Level4 - ProgramDatabase - - - $(OutDir)libusb-1.0.lib - - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level4 - - - $(OutDir)libusb-1.0.lib - - - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level4 - - - $(OutDir)libusb-1.0.lib - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/libusb_static_2015.vcxproj b/Externals/libusb/msvc/libusb_static_2015.vcxproj deleted file mode 100644 index 275cd72f43..0000000000 --- a/Externals/libusb/msvc/libusb_static_2015.vcxproj +++ /dev/null @@ -1,162 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - libusb-1.0 (static) - {349EE8F9-7D25-4909-AAF5-FF3FADE72187} - libusb - - - - StaticLibrary - Unicode - true - v140 - - - StaticLibrary - Unicode - v140 - - - StaticLibrary - Unicode - true - v140 - - - StaticLibrary - Unicode - v140 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-1.0\ - libusb-1.0 - libusb-1.0 - libusb-1.0 - libusb-1.0 - - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level4 - ProgramDatabase - $(IntDir)$(TargetName).pdb - - - $(OutDir)libusb-1.0.lib - - - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level4 - ProgramDatabase - $(IntDir)$(TargetName).pdb - - - $(OutDir)libusb-1.0.lib - - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level4 - $(IntDir)$(TargetName).pdb - - - $(OutDir)libusb-1.0.lib - - - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level4 - $(IntDir)$(TargetName).pdb - - - $(OutDir)libusb-1.0.lib - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Externals/libusb/msvc/libusb_static_wince.vcproj b/Externals/libusb/msvc/libusb_static_wince.vcproj deleted file mode 100644 index 57db8cd40b..0000000000 --- a/Externals/libusb/msvc/libusb_static_wince.vcproj +++ /dev/null @@ -1,1185 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Externals/libusb/msvc/libusb_usbdk_dll_2013.vcxproj b/Externals/libusb/msvc/libusb_usbdk_dll_2013.vcxproj deleted file mode 100644 index 8695556e86..0000000000 --- a/Externals/libusb/msvc/libusb_usbdk_dll_2013.vcxproj +++ /dev/null @@ -1,178 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - libusb-usbdk-1.0 (dll) - {F53A5974-2319-48EB-A67B-27933AEDF14A} - libusbdll - - - - DynamicLibrary - Unicode - true - v120 - - - DynamicLibrary - Unicode - v120 - - - DynamicLibrary - Unicode - true - v120 - - - DynamicLibrary - Unicode - v120 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\ - libusb-usbdk-1.0 - libusb-usbdk-1.0 - libusb-usbdk-1.0 - libusb-usbdk-1.0 - - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - $(OutDir)libusb-usbdk-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - true - - - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_DEBUG;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - $(OutDir)libusb-usbdk-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - true - - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) - MultiThreadedDLL - Level4 - - - $(OutDir)libusb-usbdk-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - - - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) - MultiThreadedDLL - Level4 - - - $(OutDir)libusb-usbdk-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/libusb_usbdk_dll_2015.vcxproj b/Externals/libusb/msvc/libusb_usbdk_dll_2015.vcxproj deleted file mode 100644 index 5408fd458f..0000000000 --- a/Externals/libusb/msvc/libusb_usbdk_dll_2015.vcxproj +++ /dev/null @@ -1,178 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - libusb-usbdk-1.0 (dll) - {F53A5974-2319-48EB-A67B-27933AEDF14A} - libusbdll - - - - DynamicLibrary - Unicode - true - v140 - - - DynamicLibrary - Unicode - v140 - - - DynamicLibrary - Unicode - true - v140 - - - DynamicLibrary - Unicode - v140 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\ - $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-usbdk-1.0\ - libusb-usbdk-1.0 - libusb-usbdk-1.0 - libusb-usbdk-1.0 - libusb-usbdk-1.0 - - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - $(OutDir)libusb-usbdk-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - true - - - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_DEBUG;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - $(OutDir)libusb-usbdk-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - true - - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) - MultiThreadedDLL - Level4 - - - $(OutDir)libusb-usbdk-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - - - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) - MultiThreadedDLL - Level4 - - - $(OutDir)libusb-usbdk-1.0.dll - ..\libusb\libusb-1.0.def - libusb-1.0.rc;%(EmbedManagedResourceFile) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/libusb_usbdk_static_2013.vcxproj b/Externals/libusb/msvc/libusb_usbdk_static_2013.vcxproj deleted file mode 100644 index c9af0e9016..0000000000 --- a/Externals/libusb/msvc/libusb_usbdk_static_2013.vcxproj +++ /dev/null @@ -1,162 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - libusb-usbdk-1.0 (static) - {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED} - libusb - - - - StaticLibrary - Unicode - true - v120 - - - StaticLibrary - Unicode - v120 - - - StaticLibrary - Unicode - true - v120 - - - StaticLibrary - Unicode - v120 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\ - libusb-usbdk-1.0 - libusb-usbdk-1.0 - libusb-usbdk-1.0 - libusb-usbdk-1.0 - - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) - MultiThreadedDebug - Level4 - ProgramDatabase - - - $(OutDir)libusb-usbdk-1.0.lib - - - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) - MultiThreadedDebug - Level4 - ProgramDatabase - - - $(OutDir)libusb-usbdk-1.0.lib - - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) - MultiThreaded - Level4 - - - $(OutDir)libusb-usbdk-1.0.lib - - - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) - MultiThreaded - Level4 - - - $(OutDir)libusb-usbdk-1.0.lib - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/libusb_usbdk_static_2015.vcxproj b/Externals/libusb/msvc/libusb_usbdk_static_2015.vcxproj deleted file mode 100644 index b02ad158f6..0000000000 --- a/Externals/libusb/msvc/libusb_usbdk_static_2015.vcxproj +++ /dev/null @@ -1,162 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - libusb-usbdk-1.0 (static) - {0B3D86CF-5D70-41A9-B391-A2E7C5C969ED} - libusb - - - - StaticLibrary - Unicode - true - v140 - - - StaticLibrary - Unicode - v140 - - - StaticLibrary - Unicode - true - v140 - - - StaticLibrary - Unicode - v140 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\ - $(SolutionDir)..\$(Platform)\$(Configuration)\lib\libusb-usbdk-1.0\ - libusb-usbdk-1.0 - libusb-usbdk-1.0 - libusb-usbdk-1.0 - libusb-usbdk-1.0 - - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) - MultiThreadedDebug - Level4 - ProgramDatabase - - - $(OutDir)libusb-usbdk-1.0.lib - - - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) - MultiThreadedDebug - Level4 - ProgramDatabase - - - $(OutDir)libusb-usbdk-1.0.lib - - - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) - MultiThreaded - Level4 - - - $(OutDir)libusb-usbdk-1.0.lib - - - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;USE_USBDK;%(PreprocessorDefinitions) - MultiThreaded - Level4 - - - $(OutDir)libusb-usbdk-1.0.lib - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Externals/libusb/msvc/listdevs.dsp b/Externals/libusb/msvc/listdevs.dsp deleted file mode 100644 index 2ed8aec31a..0000000000 --- a/Externals/libusb/msvc/listdevs.dsp +++ /dev/null @@ -1,103 +0,0 @@ -# Microsoft Developer Studio Project File - Name="listdevs" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=listdevs - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "listdevs.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "listdevs.mak" CFG="listdevs - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "listdevs - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "listdevs - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "listdevs - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "../Win32/Release/examples" -# PROP Intermediate_Dir "../Win32/Release/examples/listdevs" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /I "../libusb" /I "." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /U "_MBCS" /FR /FD /EHsc /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "listdevs - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "../Win32/Debug/examples" -# PROP Intermediate_Dir "../Win32/Debug/examples/listdevs" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../libusb" /I "." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /U "_MBCS" /FR /FD /GZ /EHsc /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo /n "../Win32/Debug/dll/core.sbr" "../Win32/Debug/dll/descriptor.sbr" "../Win32/Debug/dll/io.sbr" "../Win32/Debug/dll/sync.sbr" "../Win32/Debug/dll/poll_windows.sbr" "../Win32/Debug/dll/threads_windows.sbr" "../Win32/Debug/dll/windows_usb.sbr" -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 -# SUBTRACT LINK32 /pdb:none - -!ENDIF - -# Begin Target - -# Name "listdevs - Win32 Release" -# Name "listdevs - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\examples\listdevs.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/Externals/libusb/msvc/listdevs_2005.vcproj b/Externals/libusb/msvc/listdevs_2005.vcproj deleted file mode 100644 index cff754e0e3..0000000000 --- a/Externals/libusb/msvc/listdevs_2005.vcproj +++ /dev/null @@ -1,360 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Externals/libusb/msvc/listdevs_2010.vcxproj b/Externals/libusb/msvc/listdevs_2010.vcxproj deleted file mode 100644 index 173af38dd1..0000000000 --- a/Externals/libusb/msvc/listdevs_2010.vcxproj +++ /dev/null @@ -1,165 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - listdevs - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87} - examples - Win32Proj - - - - Application - Unicode - true - - - Application - Unicode - - - Application - Unicode - true - - - Application - Unicode - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - ..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - $(TargetDir)$(ProjectName).pdb - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - ..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - $(TargetDir)$(ProjectName).pdb - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - ..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - $(TargetDir)$(ProjectName).pdb - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - ..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - $(TargetDir)$(ProjectName).pdb - Console - MachineX64 - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/listdevs_2010.vcxproj.filters b/Externals/libusb/msvc/listdevs_2010.vcxproj.filters deleted file mode 100644 index 1378e296c8..0000000000 --- a/Externals/libusb/msvc/listdevs_2010.vcxproj.filters +++ /dev/null @@ -1,14 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Source Files - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/listdevs_2012.vcxproj b/Externals/libusb/msvc/listdevs_2012.vcxproj deleted file mode 100644 index 4ecc865e4f..0000000000 --- a/Externals/libusb/msvc/listdevs_2012.vcxproj +++ /dev/null @@ -1,169 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - listdevs - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87} - examples - Win32Proj - - - - Application - Unicode - true - v110 - - - Application - Unicode - v110 - - - Application - Unicode - true - v110 - - - Application - Unicode - v110 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - ..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - $(TargetDir)$(ProjectName).pdb - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - ..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - $(TargetDir)$(ProjectName).pdb - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - ..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - $(TargetDir)$(ProjectName).pdb - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - ..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - $(TargetDir)$(ProjectName).pdb - Console - MachineX64 - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/listdevs_2012.vcxproj.filters b/Externals/libusb/msvc/listdevs_2012.vcxproj.filters deleted file mode 100644 index 1378e296c8..0000000000 --- a/Externals/libusb/msvc/listdevs_2012.vcxproj.filters +++ /dev/null @@ -1,14 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Source Files - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/listdevs_2013.vcxproj b/Externals/libusb/msvc/listdevs_2013.vcxproj deleted file mode 100644 index 7289504c9d..0000000000 --- a/Externals/libusb/msvc/listdevs_2013.vcxproj +++ /dev/null @@ -1,169 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - listdevs - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87} - examples - Win32Proj - - - - Application - Unicode - true - v120 - - - Application - Unicode - v120 - - - Application - Unicode - true - v120 - - - Application - Unicode - v120 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - ..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - $(TargetDir)$(ProjectName).pdb - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - ..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - $(TargetDir)$(ProjectName).pdb - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - ..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - $(TargetDir)$(ProjectName).pdb - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - ..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - $(TargetDir)$(ProjectName).pdb - Console - MachineX64 - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/listdevs_2015.vcxproj b/Externals/libusb/msvc/listdevs_2015.vcxproj deleted file mode 100644 index 9224d8bddc..0000000000 --- a/Externals/libusb/msvc/listdevs_2015.vcxproj +++ /dev/null @@ -1,169 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - listdevs - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87} - examples - Win32Proj - - - - Application - Unicode - true - v140 - - - Application - Unicode - v140 - - - Application - Unicode - true - v140 - - - Application - Unicode - v140 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - ..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - $(TargetDir)$(ProjectName).pdb - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - ..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - $(TargetDir)$(ProjectName).pdb - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - ..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - $(TargetDir)$(ProjectName).pdb - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - ..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - $(TargetDir)$(ProjectName).pdb - Console - MachineX64 - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/listdevs_sources b/Externals/libusb/msvc/listdevs_sources deleted file mode 100644 index 97a5723e4c..0000000000 --- a/Externals/libusb/msvc/listdevs_sources +++ /dev/null @@ -1,19 +0,0 @@ -TARGETNAME=listdevs -TARGETTYPE=PROGRAM -386_STDCALL=0 - -_NT_TARGET_VERSION= $(_NT_TARGET_VERSION_WINXP) -!IFNDEF MSC_WARNING_LEVEL -MSC_WARNING_LEVEL=/W3 -!ENDIF - -!IFDEF STATIC_LIBC -USE_LIBCMT=1 -!ELSE -USE_MSVCRT=1 -!ENDIF - -UMTYPE=console -INCLUDES=..\..\libusb;$(DDK_INC_PATH) -UMLIBS=..\..\libusb\os\obj$(BUILD_ALT_DIR)\*\libusb-1.0.lib -SOURCES=..\listdevs.c diff --git a/Externals/libusb/msvc/listdevs_wince.vcproj b/Externals/libusb/msvc/listdevs_wince.vcproj deleted file mode 100644 index 1bb6c6dca7..0000000000 --- a/Externals/libusb/msvc/listdevs_wince.vcproj +++ /dev/null @@ -1,1120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Externals/libusb/msvc/missing.c b/Externals/libusb/msvc/missing.c deleted file mode 100644 index 85d9d6f344..0000000000 --- a/Externals/libusb/msvc/missing.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Source file for missing WinCE functionality - * Copyright © 2012 RealVNC Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "missing.h" - -#include -#include - -#include - -// The registry path to store environment variables -#define ENVIRONMENT_REG_PATH _T("Software\\libusb\\environment") - -/* Workaround getenv not being available on WinCE. - * Instead look in HKLM\Software\libusb\environment */ -char *getenv(const char *name) -{ - static char value[MAX_PATH]; - TCHAR wValue[MAX_PATH]; - WCHAR wName[MAX_PATH]; - DWORD dwType, dwData; - HKEY hkey; - LONG rc; - - if (!name) - return NULL; - - if (MultiByteToWideChar(CP_UTF8, 0, name, -1, wName, MAX_PATH) <= 0) { - usbi_dbg("Failed to convert environment variable name to wide string"); - return NULL; - } - wName[MAX_PATH - 1] = 0; // Be sure it's NUL terminated - - rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ENVIRONMENT_REG_PATH, 0, KEY_QUERY_VALUE, &hkey); - if (rc != ERROR_SUCCESS) { - usbi_dbg("Failed to open registry key for getenv with error %d", rc); - return NULL; - } - - // Attempt to read the key - dwData = sizeof(wValue); - rc = RegQueryValueEx(hkey, wName, NULL, &dwType, - (LPBYTE)&wValue, &dwData); - RegCloseKey(hkey); - if (rc != ERROR_SUCCESS) { - usbi_dbg("Failed to read registry key value for getenv with error %d", rc); - return NULL; - } - if (dwType != REG_SZ) { - usbi_dbg("Registry value was of type %d instead of REG_SZ", dwType); - return NULL; - } - - // Success in reading the key, convert from WCHAR to char - if (WideCharToMultiByte(CP_UTF8, 0, - wValue, dwData / sizeof(*wValue), - value, MAX_PATH, - NULL, NULL) <= 0) { - usbi_dbg("Failed to convert environment variable value to narrow string"); - return NULL; - } - value[MAX_PATH - 1] = 0; // Be sure it's NUL terminated - return value; -} diff --git a/Externals/libusb/msvc/missing.h b/Externals/libusb/msvc/missing.h deleted file mode 100644 index 183b9d35a2..0000000000 --- a/Externals/libusb/msvc/missing.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Header file for missing WinCE functionality - * Copyright © 2012-2013 RealVNC Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef MISSING_H -#define MISSING_H - -/* Windows CE doesn't have SleepEx() - Fallback to Sleep() */ -#define SleepEx(m, a) Sleep(m) - -/* Windows CE doesn't have any APIs to query environment variables. - * - * This contains a registry based implementation of getenv. - */ -char *getenv(const char *name); - -#endif diff --git a/Externals/libusb/msvc/stdint.h b/Externals/libusb/msvc/stdint.h deleted file mode 100644 index 00988d9bba..0000000000 --- a/Externals/libusb/msvc/stdint.h +++ /dev/null @@ -1,256 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file was originally part of the w64 mingw-runtime package. - */ - -/* ISO C9x 7.18 Integer types - * Based on ISO/IEC SC22/WG14 9899 Committee draft (SC22 N2794) - * - * THIS SOFTWARE IS NOT COPYRIGHTED - * - * Contributor: Danny Smith - * Modified for libusb/MSVC: Pete Batard - * - * This source code is offered for use in the public domain. You may - * use, modify or distribute it freely. - * - * This code is distributed in the hope that it will be useful but - * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY - * DISCLAIMED. This includes but is not limited to warranties of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Date: 2010-04-02 - */ - -#ifndef _MSC_VER -#error This header should only be used with Microsoft compilers -#endif - -#ifndef _STDINT_H -#define _STDINT_H - -#ifndef _INTPTR_T_DEFINED -#define _INTPTR_T_DEFINED -#ifndef __intptr_t_defined -#define __intptr_t_defined -#undef intptr_t -#ifdef _WIN64 - typedef __int64 intptr_t; -#else - typedef int intptr_t; -#endif /* _WIN64 */ -#endif /* __intptr_t_defined */ -#endif /* _INTPTR_T_DEFINED */ - -#ifndef _UINTPTR_T_DEFINED -#define _UINTPTR_T_DEFINED -#ifndef __uintptr_t_defined -#define __uintptr_t_defined -#undef uintptr_t -#ifdef _WIN64 - typedef unsigned __int64 uintptr_t; -#else - typedef unsigned int uintptr_t; -#endif /* _WIN64 */ -#endif /* __uintptr_t_defined */ -#endif /* _UINTPTR_T_DEFINED */ - -#ifndef _PTRDIFF_T_DEFINED -#define _PTRDIFF_T_DEFINED -#ifndef _PTRDIFF_T_ -#define _PTRDIFF_T_ -#undef ptrdiff_t -#ifdef _WIN64 - typedef __int64 ptrdiff_t; -#else - typedef int ptrdiff_t; -#endif /* _WIN64 */ -#endif /* _PTRDIFF_T_ */ -#endif /* _PTRDIFF_T_DEFINED */ - -#ifndef _WCHAR_T_DEFINED -#define _WCHAR_T_DEFINED -#ifndef __cplusplus - typedef unsigned short wchar_t; -#endif /* C++ */ -#endif /* _WCHAR_T_DEFINED */ - -#ifndef _WCTYPE_T_DEFINED -#define _WCTYPE_T_DEFINED -#ifndef _WINT_T -#define _WINT_T - typedef unsigned short wint_t; - typedef unsigned short wctype_t; -#endif /* _WINT_T */ -#endif /* _WCTYPE_T_DEFINED */ - -/* 7.18.1.1 Exact-width integer types */ -typedef __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; - -/* 7.18.1.2 Minimum-width integer types */ -typedef signed char int_least8_t; -typedef unsigned char uint_least8_t; -typedef short int_least16_t; -typedef unsigned short uint_least16_t; -typedef int int_least32_t; -typedef unsigned uint_least32_t; -typedef __int64 int_least64_t; -typedef unsigned __int64 uint_least64_t; - -/* 7.18.1.3 Fastest minimum-width integer types - * Not actually guaranteed to be fastest for all purposes - * Here we use the exact-width types for 8 and 16-bit ints. - */ -typedef __int8 int_fast8_t; -typedef unsigned __int8 uint_fast8_t; -typedef __int16 int_fast16_t; -typedef unsigned __int16 uint_fast16_t; -typedef __int32 int_fast32_t; -typedef unsigned __int32 uint_fast32_t; -typedef __int64 int_fast64_t; -typedef unsigned __int64 uint_fast64_t; - -/* 7.18.1.5 Greatest-width integer types */ -typedef __int64 intmax_t; -typedef unsigned __int64 uintmax_t; - -/* 7.18.2 Limits of specified-width integer types */ - -/* 7.18.2.1 Limits of exact-width integer types */ -#define INT8_MIN (-128) -#define INT16_MIN (-32768) -#define INT32_MIN (-2147483647 - 1) -#define INT64_MIN (-9223372036854775807LL - 1) - -#define INT8_MAX 127 -#define INT16_MAX 32767 -#define INT32_MAX 2147483647 -#define INT64_MAX 9223372036854775807LL - -#define UINT8_MAX 255 -#define UINT16_MAX 65535 -#define UINT32_MAX 0xffffffffU /* 4294967295U */ -#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */ - -/* 7.18.2.2 Limits of minimum-width integer types */ -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST64_MIN INT64_MIN - -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MAX INT64_MAX - -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -/* 7.18.2.3 Limits of fastest minimum-width integer types */ -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST64_MIN INT64_MIN - -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MAX INT16_MAX -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MAX INT64_MAX - -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT16_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -/* 7.18.2.4 Limits of integer types capable of holding - object pointers */ -#ifdef _WIN64 -#define INTPTR_MIN INT64_MIN -#define INTPTR_MAX INT64_MAX -#define UINTPTR_MAX UINT64_MAX -#else -#define INTPTR_MIN INT32_MIN -#define INTPTR_MAX INT32_MAX -#define UINTPTR_MAX UINT32_MAX -#endif - -/* 7.18.2.5 Limits of greatest-width integer types */ -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -/* 7.18.3 Limits of other integer types */ -#ifdef _WIN64 -#define PTRDIFF_MIN INT64_MIN -#define PTRDIFF_MAX INT64_MAX -#else -#define PTRDIFF_MIN INT32_MIN -#define PTRDIFF_MAX INT32_MAX -#endif - -#define SIG_ATOMIC_MIN INT32_MIN -#define SIG_ATOMIC_MAX INT32_MAX - -#ifndef SIZE_MAX -#ifdef _WIN64 -#define SIZE_MAX UINT64_MAX -#else -#define SIZE_MAX UINT32_MAX -#endif -#endif - -#ifndef WCHAR_MIN /* also in wchar.h */ -#define WCHAR_MIN 0U -#define WCHAR_MAX 0xffffU -#endif - -/* - * wint_t is unsigned short for compatibility with MS runtime - */ -#define WINT_MIN 0U -#define WINT_MAX 0xffffU - - -/* 7.18.4 Macros for integer constants */ - -/* 7.18.4.1 Macros for minimum-width integer constants - - Accoding to Douglas Gwyn : - "This spec was changed in ISO/IEC 9899:1999 TC1; in ISO/IEC - 9899:1999 as initially published, the expansion was required - to be an integer constant of precisely matching type, which - is impossible to accomplish for the shorter types on most - platforms, because C99 provides no standard way to designate - an integer constant with width less than that of type int. - TC1 changed this to require just an integer constant - *expression* with *promoted* type." - - The trick used here is from Clive D W Feather. -*/ - -#define INT8_C(val) (INT_LEAST8_MAX-INT_LEAST8_MAX+(val)) -#define INT16_C(val) (INT_LEAST16_MAX-INT_LEAST16_MAX+(val)) -#define INT32_C(val) (INT_LEAST32_MAX-INT_LEAST32_MAX+(val)) -/* The 'trick' doesn't work in C89 for long long because, without - suffix, (val) will be evaluated as int, not intmax_t */ -#define INT64_C(val) val##i64 - -#define UINT8_C(val) (val) -#define UINT16_C(val) (val) -#define UINT32_C(val) (val##i32) -#define UINT64_C(val) val##ui64 - -/* 7.18.4.2 Macros for greatest-width integer constants */ -#define INTMAX_C(val) val##i64 -#define UINTMAX_C(val) val##ui64 - -#endif diff --git a/Externals/libusb/msvc/stress_2005.vcproj b/Externals/libusb/msvc/stress_2005.vcproj deleted file mode 100644 index ca59d1b97a..0000000000 --- a/Externals/libusb/msvc/stress_2005.vcproj +++ /dev/null @@ -1,390 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Externals/libusb/msvc/stress_2010.vcxproj b/Externals/libusb/msvc/stress_2010.vcxproj deleted file mode 100644 index b6d6b85125..0000000000 --- a/Externals/libusb/msvc/stress_2010.vcxproj +++ /dev/null @@ -1,167 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - stress - {53942EFF-C810-458D-B3CB-EE5CE9F1E781} - tests - Win32Proj - - - - Application - Unicode - true - - - Application - Unicode - - - Application - Unicode - true - - - Application - Unicode - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/stress_2010.vcxproj.filters b/Externals/libusb/msvc/stress_2010.vcxproj.filters deleted file mode 100644 index fca1eb6352..0000000000 --- a/Externals/libusb/msvc/stress_2010.vcxproj.filters +++ /dev/null @@ -1,25 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {28b6220e-d087-4f48-bd69-ffe0ac5bcc7a} - - - - - Source Files - - - Source Files - - - - - Header Files - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/stress_2012.vcxproj b/Externals/libusb/msvc/stress_2012.vcxproj deleted file mode 100644 index c3cdea1bea..0000000000 --- a/Externals/libusb/msvc/stress_2012.vcxproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - stress - {53942EFF-C810-458D-B3CB-EE5CE9F1E781} - tests - Win32Proj - - - - Application - Unicode - true - v110 - - - Application - Unicode - v110 - - - Application - Unicode - true - v110 - - - Application - Unicode - v110 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/stress_2012.vcxproj.filters b/Externals/libusb/msvc/stress_2012.vcxproj.filters deleted file mode 100644 index fca1eb6352..0000000000 --- a/Externals/libusb/msvc/stress_2012.vcxproj.filters +++ /dev/null @@ -1,25 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {28b6220e-d087-4f48-bd69-ffe0ac5bcc7a} - - - - - Source Files - - - Source Files - - - - - Header Files - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/stress_2013.vcxproj b/Externals/libusb/msvc/stress_2013.vcxproj deleted file mode 100644 index df1b586360..0000000000 --- a/Externals/libusb/msvc/stress_2013.vcxproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - stress - {53942EFF-C810-458D-B3CB-EE5CE9F1E781} - tests - Win32Proj - - - - Application - Unicode - true - v120 - - - Application - Unicode - v120 - - - Application - Unicode - true - v120 - - - Application - Unicode - v120 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/stress_2015.vcxproj b/Externals/libusb/msvc/stress_2015.vcxproj deleted file mode 100644 index 18733c833b..0000000000 --- a/Externals/libusb/msvc/stress_2015.vcxproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - stress - {53942EFF-C810-458D-B3CB-EE5CE9F1E781} - tests - Win32Proj - - - - Application - Unicode - true - v140 - - - Application - Unicode - v140 - - - Application - Unicode - true - v140 - - - Application - Unicode - v140 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\ - $(SolutionDir)..\$(Platform)\$(Configuration)\tests\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/stress_wince.vcproj b/Externals/libusb/msvc/stress_wince.vcproj deleted file mode 100644 index a0bf46905b..0000000000 --- a/Externals/libusb/msvc/stress_wince.vcproj +++ /dev/null @@ -1,1128 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Externals/libusb/msvc/xusb.dsp b/Externals/libusb/msvc/xusb.dsp deleted file mode 100644 index a99178ccd7..0000000000 --- a/Externals/libusb/msvc/xusb.dsp +++ /dev/null @@ -1,102 +0,0 @@ -# Microsoft Developer Studio Project File - Name="xusb" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=xusb - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "xusb.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "xusb.mak" CFG="xusb - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "xusb - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "xusb - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "xusb - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "../Win32/Release/examples" -# PROP Intermediate_Dir "../Win32/Release/examples/xusb" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../libusb" /I "." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /U "_MBCS" /FR /FD /EHsc /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "xusb - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "xusb___Win32_Debug" -# PROP BASE Intermediate_Dir "xusb___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "../Win32/Debug/examples" -# PROP Intermediate_Dir "../Win32/Debug/examples/xusb" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "../libusb" /I "." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /U "_MBCS" /FR /FD /GZ /EHsc /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo /n "../Win32/Debug/dll/core.sbr" "../Win32/Debug/dll/descriptor.sbr" "../Win32/Debug/dll/io.sbr" "../Win32/Debug/dll/sync.sbr" "../Win32/Debug/dll/poll_windows.sbr" "../Win32/Debug/dll/threads_windows.sbr" "../Win32/Debug/dll/windows_usb.sbr" -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 - -!ENDIF - -# Begin Target - -# Name "xusb - Win32 Release" -# Name "xusb - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\examples\xusb.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/Externals/libusb/msvc/xusb_2005.vcproj b/Externals/libusb/msvc/xusb_2005.vcproj deleted file mode 100644 index b12f5c13df..0000000000 --- a/Externals/libusb/msvc/xusb_2005.vcproj +++ /dev/null @@ -1,344 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Externals/libusb/msvc/xusb_2010.vcxproj b/Externals/libusb/msvc/xusb_2010.vcxproj deleted file mode 100644 index 7c4811d9f7..0000000000 --- a/Externals/libusb/msvc/xusb_2010.vcxproj +++ /dev/null @@ -1,163 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - xusb - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11} - examples - Win32Proj - - - - Application - Unicode - true - - - Application - Unicode - - - Application - Unicode - true - - - Application - Unicode - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/xusb_2010.vcxproj.filters b/Externals/libusb/msvc/xusb_2010.vcxproj.filters deleted file mode 100644 index f71902f455..0000000000 --- a/Externals/libusb/msvc/xusb_2010.vcxproj.filters +++ /dev/null @@ -1,14 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Source Files - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/xusb_2012.vcxproj b/Externals/libusb/msvc/xusb_2012.vcxproj deleted file mode 100644 index 7d64df51d9..0000000000 --- a/Externals/libusb/msvc/xusb_2012.vcxproj +++ /dev/null @@ -1,167 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - xusb - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11} - examples - Win32Proj - - - - Application - Unicode - true - v110 - - - Application - Unicode - v110 - - - Application - Unicode - true - v110 - - - Application - Unicode - v110 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/xusb_2012.vcxproj.filters b/Externals/libusb/msvc/xusb_2012.vcxproj.filters deleted file mode 100644 index f71902f455..0000000000 --- a/Externals/libusb/msvc/xusb_2012.vcxproj.filters +++ /dev/null @@ -1,14 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Source Files - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/xusb_2013.vcxproj b/Externals/libusb/msvc/xusb_2013.vcxproj deleted file mode 100644 index 3fd53ad69b..0000000000 --- a/Externals/libusb/msvc/xusb_2013.vcxproj +++ /dev/null @@ -1,167 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - xusb - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11} - examples - Win32Proj - - - - Application - Unicode - true - v120 - - - Application - Unicode - v120 - - - Application - Unicode - true - v120 - - - Application - Unicode - v120 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/xusb_2015.vcxproj b/Externals/libusb/msvc/xusb_2015.vcxproj deleted file mode 100644 index e63663892f..0000000000 --- a/Externals/libusb/msvc/xusb_2015.vcxproj +++ /dev/null @@ -1,167 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - xusb - {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11} - examples - Win32Proj - - - - Application - Unicode - true - v140 - - - Application - Unicode - v140 - - - Application - Unicode - true - v140 - - - Application - Unicode - v140 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\ - $(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - Disabled - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreadedDebug - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - .;..\libusb;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - Level3 - - - %(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - - - - {349ee8f9-7d25-4909-aaf5-ff3fade72187} - false - - - - - - \ No newline at end of file diff --git a/Externals/libusb/msvc/xusb_sources b/Externals/libusb/msvc/xusb_sources deleted file mode 100644 index b43f94f683..0000000000 --- a/Externals/libusb/msvc/xusb_sources +++ /dev/null @@ -1,20 +0,0 @@ -TARGETNAME=xusb -TARGETTYPE=PROGRAM -386_STDCALL=0 - -_NT_TARGET_VERSION= $(_NT_TARGET_VERSION_WINXP) - -!IFNDEF MSC_WARNING_LEVEL -MSC_WARNING_LEVEL=/W3 -!ENDIF - -!IFDEF STATIC_LIBC -USE_LIBCMT=1 -!ELSE -USE_MSVCRT=1 -!ENDIF - -UMTYPE=console -INCLUDES=..\..\msvc;..\..\libusb;$(DDK_INC_PATH) -UMLIBS=..\..\libusb\os\obj$(BUILD_ALT_DIR)\*\libusb-1.0.lib -SOURCES=..\xusb.c diff --git a/Externals/libusb/msvc/xusb_wince.vcproj b/Externals/libusb/msvc/xusb_wince.vcproj deleted file mode 100644 index f994678013..0000000000 --- a/Externals/libusb/msvc/xusb_wince.vcproj +++ /dev/null @@ -1,1120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Externals/libusb/travis-autogen.sh b/Externals/libusb/travis-autogen.sh new file mode 100755 index 0000000000..cdd8781de8 --- /dev/null +++ b/Externals/libusb/travis-autogen.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# Warnings enabled +CFLAGS="-Wall -Wextra" + +CFLAGS+=" -Wbad-function-cast" +#CFLAGS+=" -Wcast-align" +CFLAGS+=" -Wchar-subscripts" +CFLAGS+=" -Wempty-body" +CFLAGS+=" -Wformat" +CFLAGS+=" -Wformat-security" +CFLAGS+=" -Winit-self" +CFLAGS+=" -Winline" +CFLAGS+=" -Wmissing-declarations" +CFLAGS+=" -Wmissing-include-dirs" +CFLAGS+=" -Wmissing-prototypes" +CFLAGS+=" -Wnested-externs" +CFLAGS+=" -Wold-style-definition" +CFLAGS+=" -Wpointer-arith" +CFLAGS+=" -Wredundant-decls" +CFLAGS+=" -Wshadow" +CFLAGS+=" -Wstrict-prototypes" +CFLAGS+=" -Wswitch-enum" +CFLAGS+=" -Wundef" +CFLAGS+=" -Wuninitialized" +CFLAGS+=" -Wunused" +CFLAGS+=" -Wwrite-strings" + +# warnings disabled on purpose +CFLAGS+=" -Wno-unused-parameter" +CFLAGS+=" -Wno-unused-function" +CFLAGS+=" -Wno-deprecated-declarations" + +# should be removed and the code fixed +CFLAGS+=" -Wno-incompatible-pointer-types-discards-qualifiers" + +export CFLAGS + +./autogen.sh "$@" diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 498b430d71..78701af198 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -10,6 +10,7 @@ add_library(core GeckoCodeConfig.cpp GeckoCode.cpp HotkeyManager.cpp + LibusbUtils.cpp MemTools.cpp Movie.cpp NetPlayClient.cpp diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index 62b00d0f70..a08761f0d9 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -231,6 +231,9 @@ 4200;%(DisableSpecificWarnings) + + 4200;%(DisableSpecificWarnings) + 4200;%(DisableSpecificWarnings) @@ -497,6 +500,7 @@ + diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index 68a8141f87..3064754798 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -173,6 +173,7 @@ + @@ -939,6 +940,7 @@ + diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp index becd2032c8..7ccd5c4fac 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp @@ -24,11 +24,11 @@ #include "Common/Network.h" #include "Common/StringUtil.h" #include "Common/Swap.h" -#include "Common/Thread.h" #include "Core/ConfigManager.h" #include "Core/Core.h" #include "Core/HW/Memmap.h" #include "Core/IOS/Device.h" +#include "Core/LibusbUtils.h" #include "VideoCommon/OnScreenDisplay.h" namespace IOS::HLE::Device @@ -57,11 +57,6 @@ static bool IsBluetoothDevice(const libusb_interface_descriptor& descriptor) BluetoothReal::BluetoothReal(Kernel& ios, const std::string& device_name) : BluetoothBase(ios, device_name) { - const int ret = libusb_init(&m_libusb_context); - if (ret < 0) - { - PanicAlertT("Couldn't initialise libusb for Bluetooth passthrough: %s", libusb_error_name(ret)); - } LoadLinkKeys(); } @@ -72,42 +67,27 @@ BluetoothReal::~BluetoothReal() SendHCIResetCommand(); WaitForHCICommandComplete(HCI_CMD_RESET); libusb_release_interface(m_handle, 0); - // libusb_handle_events() may block the libusb thread indefinitely, so we need to - // call libusb_close() first then immediately stop the thread in StopTransferThread. - StopTransferThread(); + libusb_close(m_handle); libusb_unref_device(m_device); } - - libusb_exit(m_libusb_context); SaveLinkKeys(); } IPCCommandResult BluetoothReal::Open(const OpenRequest& request) { - if (!m_libusb_context) + auto& context = LibusbUtils::GetContext(); + if (!context.IsValid()) return GetDefaultReply(IPC_EACCES); - libusb_device** list; - const ssize_t cnt = libusb_get_device_list(m_libusb_context, &list); - if (cnt < 0) - { - ERROR_LOG(IOS_WIIMOTE, "Couldn't get device list: %s", - libusb_error_name(static_cast(cnt))); - return GetDefaultReply(IPC_ENOENT); - } - - for (ssize_t i = 0; i < cnt; ++i) - { - libusb_device* device = list[i]; + context.GetDeviceList([this](libusb_device* device) { libusb_device_descriptor device_descriptor; - libusb_config_descriptor* config_descriptor; libusb_get_device_descriptor(device, &device_descriptor); - const int ret = libusb_get_config_descriptor(device, 0, &config_descriptor); - if (ret != 0) + auto config_descriptor = LibusbUtils::MakeConfigDescriptor(device); + if (!config_descriptor) { - ERROR_LOG(IOS_WIIMOTE, "Failed to get config descriptor for device %04x:%04x: %s", - device_descriptor.idVendor, device_descriptor.idProduct, libusb_error_name(ret)); - continue; + ERROR_LOG(IOS_WIIMOTE, "Failed to get config descriptor for device %04x:%04x", + device_descriptor.idVendor, device_descriptor.idProduct); + return true; } const libusb_interface& interface = config_descriptor->interface[INTERFACE]; @@ -126,12 +106,10 @@ IPCCommandResult BluetoothReal::Open(const OpenRequest& request) device_descriptor.bcdDevice, manufacturer, product, serial_number); m_is_wii_bt_module = device_descriptor.idVendor == 0x57e && device_descriptor.idProduct == 0x305; - libusb_free_config_descriptor(config_descriptor); - break; + return false; } - libusb_free_config_descriptor(config_descriptor); - } - libusb_free_device_list(list, 1); + return true; + }); if (m_handle == nullptr) { @@ -141,8 +119,6 @@ IPCCommandResult BluetoothReal::Open(const OpenRequest& request) return GetDefaultReply(IPC_ENOENT); } - StartTransferThread(); - return Device::Open(request); } @@ -151,7 +127,7 @@ IPCCommandResult BluetoothReal::Close(u32 fd) if (m_handle) { libusb_release_interface(m_handle, 0); - StopTransferThread(); + libusb_close(m_handle); libusb_unref_device(m_device); m_handle = nullptr; } @@ -595,32 +571,6 @@ bool BluetoothReal::OpenDevice(libusb_device* device) return true; } -void BluetoothReal::StartTransferThread() -{ - if (m_thread_running.IsSet()) - return; - m_thread_running.Set(); - m_thread = std::thread(&BluetoothReal::TransferThread, this); -} - -void BluetoothReal::StopTransferThread() -{ - if (m_thread_running.TestAndClear()) - { - libusb_close(m_handle); - m_thread.join(); - } -} - -void BluetoothReal::TransferThread() -{ - Common::SetCurrentThreadName("BT USB Thread"); - while (m_thread_running.IsSet()) - { - libusb_handle_events_completed(m_libusb_context, nullptr); - } -} - // The callbacks are called from libusb code on a separate thread. void BluetoothReal::HandleCtrlTransfer(libusb_transfer* tr) { diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.h b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.h index 63f4fcc9ef..5070cbee75 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.h +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.h @@ -11,7 +11,6 @@ #include #include #include -#include #include "Common/CommonTypes.h" #include "Common/Flag.h" @@ -22,7 +21,6 @@ #include "Core/IOS/USB/USBV0.h" class PointerWrap; -struct libusb_context; struct libusb_device; struct libusb_device_handle; struct libusb_transfer; @@ -74,10 +72,6 @@ private: libusb_device* m_device = nullptr; libusb_device_handle* m_handle = nullptr; - libusb_context* m_libusb_context = nullptr; - - Common::Flag m_thread_running; - std::thread m_thread; std::mutex m_transfers_mutex; struct PendingTransfer @@ -122,9 +116,6 @@ private: void SaveLinkKeys(); bool OpenDevice(libusb_device* device); - void StartTransferThread(); - void StopTransferThread(); - void TransferThread(); }; } // namespace Device } // namespace IOS::HLE diff --git a/Source/Core/Core/IOS/USB/Host.cpp b/Source/Core/Core/IOS/USB/Host.cpp index 03b9c30c62..15308d2b4e 100644 --- a/Source/Core/Core/IOS/USB/Host.cpp +++ b/Source/Core/Core/IOS/USB/Host.cpp @@ -24,24 +24,15 @@ #include "Core/Core.h" #include "Core/IOS/USB/Common.h" #include "Core/IOS/USB/LibusbDevice.h" +#include "Core/LibusbUtils.h" namespace IOS::HLE::Device { USBHost::USBHost(Kernel& ios, const std::string& device_name) : Device(ios, device_name) { -#ifdef __LIBUSB__ - const int ret = libusb_init(&m_libusb_context); - DEBUG_ASSERT_MSG(IOS_USB, ret == 0, "Failed to init libusb for USB passthrough."); -#endif } -USBHost::~USBHost() -{ -#ifdef __LIBUSB__ - if (m_libusb_context) - libusb_exit(m_libusb_context); -#endif -} +USBHost::~USBHost() = default; IPCCommandResult USBHost::Open(const OpenRequest& request) { @@ -130,43 +121,26 @@ bool USBHost::AddNewDevices(std::set& new_devices, DeviceChangeHooks& hooks if (SConfig::GetInstance().m_usb_passthrough_devices.empty()) return true; - if (m_libusb_context) + auto& context = LibusbUtils::GetContext(); + if (context.IsValid()) { - libusb_device** list; - const ssize_t count = libusb_get_device_list(m_libusb_context, &list); - if (count < 0) - { - WARN_LOG(IOS_USB, "Failed to get device list: %s", - libusb_error_name(static_cast(count))); - return false; - } - - for (ssize_t i = 0; i < count; ++i) - { - libusb_device* device = list[i]; + context.GetDeviceList([&](libusb_device* device) { libusb_device_descriptor descriptor; libusb_get_device_descriptor(device, &descriptor); - if (!SConfig::GetInstance().IsUSBDeviceWhitelisted( - {descriptor.idVendor, descriptor.idProduct})) - { - libusb_unref_device(device); - continue; - } + const std::pair vid_pid = {descriptor.idVendor, descriptor.idProduct}; + if (!SConfig::GetInstance().IsUSBDeviceWhitelisted(vid_pid)) + return true; auto usb_device = std::make_unique(m_ios, device, descriptor); if (!ShouldAddDevice(*usb_device)) - { - libusb_unref_device(device); - continue; - } + return true; + const u64 id = usb_device->GetId(); new_devices.insert(id); if (AddDevice(std::move(usb_device)) || always_add_hooks) hooks.emplace(GetDeviceById(id), ChangeEvent::Inserted); - else - libusb_unref_device(device); - } - libusb_free_device_list(list, 0); + return true; + }); } #endif return true; @@ -219,27 +193,6 @@ void USBHost::StartThreads() } }); } - -#ifdef __LIBUSB__ - if (!m_event_thread_running.IsSet() && m_libusb_context) - { - m_event_thread_running.Set(); - m_event_thread = std::thread([this] { - Common::SetCurrentThreadName("USB Passthrough Thread"); - while (m_event_thread_running.IsSet()) - { - if (SConfig::GetInstance().m_usb_passthrough_devices.empty()) - { - Common::SleepCurrentThread(50); - continue; - } - - static timeval tv = {0, 50000}; - libusb_handle_events_timeout_completed(m_libusb_context, &tv, nullptr); - } - }); - } -#endif } void USBHost::StopThreads() @@ -251,10 +204,6 @@ void USBHost::StopThreads() DeviceChangeHooks hooks; DetectRemovedDevices(std::set(), hooks); DispatchHooks(hooks); -#ifdef __LIBUSB__ - if (m_event_thread_running.TestAndClear()) - m_event_thread.join(); -#endif } IPCCommandResult USBHost::HandleTransfer(std::shared_ptr device, u32 request, diff --git a/Source/Core/Core/IOS/USB/Host.h b/Source/Core/Core/IOS/USB/Host.h index dc37efe4c6..40e42193d2 100644 --- a/Source/Core/Core/IOS/USB/Host.h +++ b/Source/Core/Core/IOS/USB/Host.h @@ -22,7 +22,6 @@ #include "Core/IOS/USB/Common.h" class PointerWrap; -struct libusb_context; namespace IOS::HLE::Device { @@ -67,13 +66,6 @@ private: void DetectRemovedDevices(const std::set& plugged_devices, DeviceChangeHooks& hooks); void DispatchHooks(const DeviceChangeHooks& hooks); -#ifdef __LIBUSB__ - libusb_context* m_libusb_context = nullptr; - - // Event thread for libusb - Common::Flag m_event_thread_running; - std::thread m_event_thread; -#endif // Device scanning thread Common::Flag m_scan_thread_running; std::thread m_scan_thread; diff --git a/Source/Core/Core/IOS/USB/LibusbDevice.cpp b/Source/Core/Core/IOS/USB/LibusbDevice.cpp index df346ae95b..a1a9dba531 100644 --- a/Source/Core/Core/IOS/USB/LibusbDevice.cpp +++ b/Source/Core/Core/IOS/USB/LibusbDevice.cpp @@ -37,7 +37,7 @@ LibusbDevice::LibusbDevice(Kernel& ios, libusb_device* device, static_cast(libusb_get_device_address(device))); for (u8 i = 0; i < descriptor.bNumConfigurations; ++i) - m_config_descriptors.emplace_back(std::make_unique(m_device, i)); + m_config_descriptors.emplace_back(LibusbUtils::MakeConfigDescriptor(m_device, i)); } LibusbDevice::~LibusbDevice() @@ -65,13 +65,13 @@ std::vector LibusbDevice::GetConfigurations() const std::vector descriptors; for (const auto& config_descriptor : m_config_descriptors) { - if (!config_descriptor->IsValid()) + if (!config_descriptor) { ERROR_LOG(IOS_USB, "Ignoring invalid config descriptor for %04x:%04x", m_vid, m_pid); continue; } ConfigDescriptor descriptor; - std::memcpy(&descriptor, config_descriptor->Get(), sizeof(descriptor)); + std::memcpy(&descriptor, config_descriptor.get(), sizeof(descriptor)); descriptors.push_back(descriptor); } return descriptors; @@ -80,14 +80,14 @@ std::vector LibusbDevice::GetConfigurations() const std::vector LibusbDevice::GetInterfaces(const u8 config) const { std::vector descriptors; - if (config >= m_config_descriptors.size() || !m_config_descriptors[config]->IsValid()) + if (config >= m_config_descriptors.size() || !m_config_descriptors[config]) { ERROR_LOG(IOS_USB, "Invalid config descriptor %u for %04x:%04x", config, m_vid, m_pid); return descriptors; } - for (u8 i = 0; i < m_config_descriptors[config]->Get()->bNumInterfaces; ++i) + for (u8 i = 0; i < m_config_descriptors[config]->bNumInterfaces; ++i) { - const libusb_interface& interface = m_config_descriptors[config]->Get()->interface[i]; + const libusb_interface& interface = m_config_descriptors[config]->interface[i]; for (u8 a = 0; a < interface.num_altsetting; ++a) { InterfaceDescriptor descriptor; @@ -102,13 +102,13 @@ std::vector LibusbDevice::GetEndpoints(const u8 config, const u8 interface_number, const u8 alt_setting) const { std::vector descriptors; - if (config >= m_config_descriptors.size() || !m_config_descriptors[config]->IsValid()) + if (config >= m_config_descriptors.size() || !m_config_descriptors[config]) { ERROR_LOG(IOS_USB, "Invalid config descriptor %u for %04x:%04x", config, m_vid, m_pid); return descriptors; } - ASSERT(interface_number < m_config_descriptors[config]->Get()->bNumInterfaces); - const auto& interface = m_config_descriptors[config]->Get()->interface[interface_number]; + ASSERT(interface_number < m_config_descriptors[config]->bNumInterfaces); + const auto& interface = m_config_descriptors[config]->interface[interface_number]; ASSERT(alt_setting < interface.num_altsetting); const libusb_interface_descriptor& interface_descriptor = interface.altsetting[alt_setting]; for (u8 i = 0; i < interface_descriptor.bNumEndpoints; ++i) @@ -403,16 +403,16 @@ void LibusbDevice::TransferEndpoint::CancelTransfers() int LibusbDevice::GetNumberOfAltSettings(const u8 interface_number) { - return m_config_descriptors[0]->Get()->interface[interface_number].num_altsetting; + return m_config_descriptors[0]->interface[interface_number].num_altsetting; } template static int DoForEachInterface(const Configs& configs, u8 config_num, Function action) { int ret = LIBUSB_ERROR_NOT_FOUND; - if (configs.size() <= config_num || !configs[config_num]->IsValid()) + if (configs.size() <= config_num || !configs[config_num]) return ret; - for (u8 i = 0; i < configs[config_num]->Get()->bNumInterfaces; ++i) + for (u8 i = 0; i < configs[config_num]->bNumInterfaces; ++i) { ret = action(i); if (ret < 0) @@ -462,16 +462,4 @@ int LibusbDevice::ReleaseAllInterfacesForCurrentConfig() const return get_config_ret; return ReleaseAllInterfaces(config_num); } - -LibusbConfigDescriptor::LibusbConfigDescriptor(libusb_device* device, const u8 config_num) -{ - if (libusb_get_config_descriptor(device, config_num, &m_descriptor) != LIBUSB_SUCCESS) - m_descriptor = nullptr; -} - -LibusbConfigDescriptor::~LibusbConfigDescriptor() -{ - if (m_descriptor != nullptr) - libusb_free_config_descriptor(m_descriptor); -} } // namespace IOS::HLE::USB diff --git a/Source/Core/Core/IOS/USB/LibusbDevice.h b/Source/Core/Core/IOS/USB/LibusbDevice.h index a068a6c9e4..5a9700922f 100644 --- a/Source/Core/Core/IOS/USB/LibusbDevice.h +++ b/Source/Core/Core/IOS/USB/LibusbDevice.h @@ -15,8 +15,8 @@ #include "Common/CommonTypes.h" #include "Core/IOS/USB/Common.h" +#include "Core/LibusbUtils.h" -struct libusb_config_descriptor; struct libusb_device; struct libusb_device_descriptor; struct libusb_device_handle; @@ -24,19 +24,6 @@ struct libusb_transfer; namespace IOS::HLE::USB { -// Simple wrapper around libusb_get_config_descriptor and libusb_free_config_descriptor. -class LibusbConfigDescriptor final -{ -public: - explicit LibusbConfigDescriptor(libusb_device* device, u8 config_num = 0); - ~LibusbConfigDescriptor(); - libusb_config_descriptor* Get() const { return m_descriptor; } - bool IsValid() const { return m_descriptor != nullptr; } - -private: - libusb_config_descriptor* m_descriptor = nullptr; -}; - class LibusbDevice final : public Device { public: @@ -62,7 +49,7 @@ public: private: Kernel& m_ios; - std::vector> m_config_descriptors; + std::vector m_config_descriptors; u16 m_vid = 0; u16 m_pid = 0; u8 m_active_interface = 0; diff --git a/Source/Core/Core/LibusbUtils.cpp b/Source/Core/Core/LibusbUtils.cpp new file mode 100644 index 0000000000..2ee7838c33 --- /dev/null +++ b/Source/Core/Core/LibusbUtils.cpp @@ -0,0 +1,127 @@ +// Copyright 2019 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include + +#if defined(__LIBUSB__) +#include +#endif + +#include "Common/Assert.h" +#include "Common/Flag.h" +#include "Common/Thread.h" +#include "Core/LibusbUtils.h" + +namespace LibusbUtils +{ +#if defined(__LIBUSB__) +class Context::Impl +{ +public: + Impl() + { + const int ret = libusb_init(&m_context); + ASSERT_MSG(IOS_USB, ret == LIBUSB_SUCCESS, "Failed to init libusb: %s", libusb_error_name(ret)); + if (ret != LIBUSB_SUCCESS) + return; + +#ifdef _WIN32 + libusb_set_option(m_context, LIBUSB_OPTION_USE_USBDK); +#endif + m_event_thread_running.Set(); + m_event_thread = std::thread(&Impl::EventThread, this); + } + + ~Impl() + { + if (!m_context || !m_event_thread_running.TestAndClear()) + return; +#if defined(LIBUSB_API_VERSION) && LIBUSB_API_VERSION >= 0x01000105 + libusb_interrupt_event_handler(m_context); +#endif + m_event_thread.join(); + libusb_exit(m_context); + } + + libusb_context* GetContext() { return m_context; } + + bool GetDeviceList(GetDeviceListCallback callback) + { + std::lock_guard lock{m_device_list_mutex}; + + libusb_device** list; + ssize_t count = libusb_get_device_list(m_context, &list); + if (count < 0) + return false; + + for (ssize_t i = 0; i < count; ++i) + { + if (!callback(list[i])) + break; + } + libusb_free_device_list(list, 1); + return true; + } + +private: + void EventThread() + { + Common::SetCurrentThreadName("libusb thread"); + timeval tv{5, 0}; + while (m_event_thread_running.IsSet()) + libusb_handle_events_timeout_completed(m_context, &tv, nullptr); + } + + libusb_context* m_context = nullptr; + std::mutex m_device_list_mutex; + Common::Flag m_event_thread_running; + std::thread m_event_thread; +}; +#else +class Context::Impl +{ +public: + libusb_context* GetContext() { return nullptr; } + bool GetDeviceList(GetDeviceListCallback callback) { return false; } +}; +#endif + +Context::Context() : m_impl{std::make_unique()} +{ +} + +Context::~Context() = default; + +Context::operator libusb_context*() const +{ + return m_impl->GetContext(); +} + +bool Context::IsValid() const +{ + return m_impl->GetContext() != nullptr; +} + +bool Context::GetDeviceList(GetDeviceListCallback callback) +{ + return m_impl->GetDeviceList(std::move(callback)); +} + +Context& GetContext() +{ + static Context s_context; + return s_context; +} + +ConfigDescriptor MakeConfigDescriptor(libusb_device* device, u8 config_num) +{ +#if defined(__LIBUSB__) + libusb_config_descriptor* descriptor = nullptr; + if (libusb_get_config_descriptor(device, config_num, &descriptor) == LIBUSB_SUCCESS) + return {descriptor, libusb_free_config_descriptor}; +#endif + return {nullptr, [](auto) {}}; +} +} // namespace LibusbUtils diff --git a/Source/Core/Core/LibusbUtils.h b/Source/Core/Core/LibusbUtils.h new file mode 100644 index 0000000000..ded3bd9940 --- /dev/null +++ b/Source/Core/Core/LibusbUtils.h @@ -0,0 +1,48 @@ +// Copyright 2019 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +#include "Common/CommonTypes.h" + +struct libusb_config_descriptor; +struct libusb_context; +struct libusb_device; + +namespace LibusbUtils +{ +template +using UniquePtr = std::unique_ptr; + +// Return false to stop iterating the device list. +using GetDeviceListCallback = std::function; + +class Context +{ +public: + Context(); + ~Context(); + + operator libusb_context*() const; + bool IsValid() const; + + // Only valid if the context is valid. + bool GetDeviceList(GetDeviceListCallback callback); + +private: + class Impl; + std::unique_ptr m_impl; +}; + +// Use this to get a libusb context. Do *not* use any other context +// because some libusb backends such as UsbDk only work properly with a single context. +// Additionally, device lists must be retrieved using GetDeviceList for thread safety reasons. +Context& GetContext(); + +using ConfigDescriptor = UniquePtr; +ConfigDescriptor MakeConfigDescriptor(libusb_device* device, u8 config_num = 0); +} // namespace LibusbUtils diff --git a/Source/Core/InputCommon/GCAdapter.cpp b/Source/Core/InputCommon/GCAdapter.cpp index 196f693b07..4e008317df 100644 --- a/Source/Core/InputCommon/GCAdapter.cpp +++ b/Source/Core/InputCommon/GCAdapter.cpp @@ -15,6 +15,7 @@ #include "Core/CoreTiming.h" #include "Core/HW/SI/SI.h" #include "Core/HW/SystemTimers.h" +#include "Core/LibusbUtils.h" #include "Core/NetPlayProto.h" #include "InputCommon/GCAdapter.h" @@ -54,7 +55,6 @@ static Common::Flag s_adapter_detect_thread_running; static std::function s_detect_callback; static bool s_libusb_driver_not_supported = false; -static libusb_context* s_libusb_context; #if defined(__FreeBSD__) && __FreeBSD__ >= 11 static bool s_libusb_hotplug_enabled = true; #else @@ -127,6 +127,7 @@ static int HotplugCallback(libusb_context* ctx, libusb_device* dev, libusb_hotpl static void ScanThreadFunc() { + auto& context = LibusbUtils::GetContext(); Common::SetCurrentThreadName("GC Adapter Scanning Thread"); NOTICE_LOG(SERIALINTERFACE, "GC Adapter scanning thread started"); @@ -137,7 +138,7 @@ static void ScanThreadFunc() if (s_libusb_hotplug_enabled) { if (libusb_hotplug_register_callback( - s_libusb_context, + context, (libusb_hotplug_event)(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT), LIBUSB_HOTPLUG_ENUMERATE, 0x057e, 0x0337, LIBUSB_HOTPLUG_MATCH_ANY, HotplugCallback, @@ -148,24 +149,19 @@ static void ScanThreadFunc() } #endif + if (s_libusb_hotplug_enabled) + return; + while (s_adapter_detect_thread_running.IsSet()) { - if (s_libusb_hotplug_enabled) + if (s_handle == nullptr) { - static timeval tv = {0, 500000}; - libusb_handle_events_timeout(s_libusb_context, &tv); - } - else - { - if (s_handle == nullptr) - { - std::lock_guard lk(s_init_mutex); - Setup(); - if (s_detected && s_detect_callback != nullptr) - s_detect_callback(); - } - Common::SleepCurrentThread(500); + std::lock_guard lk(s_init_mutex); + Setup(); + if (s_detected && s_detect_callback != nullptr) + s_detect_callback(); } + Common::SleepCurrentThread(500); } NOTICE_LOG(SERIALINTERFACE, "GC Adapter scanning thread stopped"); } @@ -198,13 +194,8 @@ void StartScanThread() { if (s_adapter_detect_thread_running.IsSet()) return; - - const int ret = libusb_init(&s_libusb_context); - if (ret < 0) - { - ERROR_LOG(SERIALINTERFACE, "libusb_init failed with error: %d", ret); + if (!LibusbUtils::GetContext().IsValid()) return; - } s_adapter_detect_thread_running.Set(true); s_adapter_detect_thread = std::thread(ScanThreadFunc); } @@ -219,27 +210,21 @@ void StopScanThread() static void Setup() { - libusb_device** list; - ssize_t cnt = libusb_get_device_list(s_libusb_context, &list); - for (int i = 0; i < SerialInterface::MAX_SI_CHANNELS; i++) { s_controller_type[i] = ControllerTypes::CONTROLLER_NONE; s_controller_rumble[i] = 0; } - for (int d = 0; d < cnt; d++) - { - libusb_device* device = list[d]; + LibusbUtils::GetContext().GetDeviceList([](libusb_device* device) { if (CheckDeviceAccess(device)) { // Only connect to a single adapter in case the user has multiple connected AddGCAdapter(device); - break; + return false; } - } - - libusb_free_device_list(list, 1); + return true; + }); } static bool CheckDeviceAccess(libusb_device* device) @@ -342,16 +327,11 @@ void Shutdown() { StopScanThread(); #if defined(LIBUSB_API_VERSION) && LIBUSB_API_VERSION >= 0x01000102 - if (s_libusb_context && s_libusb_hotplug_enabled) - libusb_hotplug_deregister_callback(s_libusb_context, s_hotplug_handle); + if (LibusbUtils::GetContext().IsValid() && s_libusb_hotplug_enabled) + libusb_hotplug_deregister_callback(LibusbUtils::GetContext(), s_hotplug_handle); #endif Reset(); - if (s_libusb_context) - { - libusb_exit(s_libusb_context); - s_libusb_context = nullptr; - } s_libusb_driver_not_supported = false; } diff --git a/Source/Core/UICommon/USBUtils.cpp b/Source/Core/UICommon/USBUtils.cpp index 001e1dbbb1..42cf815a12 100644 --- a/Source/Core/UICommon/USBUtils.cpp +++ b/Source/Core/UICommon/USBUtils.cpp @@ -8,6 +8,7 @@ #include "Common/CommonTypes.h" #include "Common/StringUtil.h" +#include "Core/LibusbUtils.h" #include "UICommon/USBUtils.h" // Because opening and getting the device name from devices is slow, especially on Windows @@ -34,21 +35,17 @@ std::map, std::string> GetInsertedDevices() std::map, std::string> devices; #ifdef __LIBUSB__ - libusb_context* context = nullptr; - if (libusb_init(&context) < 0) + auto& context = LibusbUtils::GetContext(); + if (!context.IsValid()) return devices; - libusb_device** list; - const ssize_t cnt = libusb_get_device_list(context, &list); - for (ssize_t i = 0; i < cnt; ++i) - { + context.GetDeviceList([&](libusb_device* device) { libusb_device_descriptor descr; - libusb_get_device_descriptor(list[i], &descr); + libusb_get_device_descriptor(device, &descr); const std::pair vid_pid{descr.idVendor, descr.idProduct}; devices[vid_pid] = GetDeviceName(vid_pid); - } - libusb_free_device_list(list, 1); - libusb_exit(context); + return true; + }); #endif return devices;