Externals: Update libusb to 1.0.23-rc1

Now has support for isochronous transfers in the WinUSB backend,
which may or may not work better than the UsbDk backend.
This commit is contained in:
Léo Lam 2019-05-01 11:47:48 +02:00
parent 42de5b9a10
commit 1b9617c85c
163 changed files with 19633 additions and 7732 deletions

49
Externals/libusb/.travis.yml vendored Normal file
View File

@ -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

View File

@ -8,14 +8,19 @@ Copyright © 2010-2012 Michael Plante <michael.plante@gmail.com>
Copyright © 2011-2013 Hans de Goede <hdegoede@redhat.com> Copyright © 2011-2013 Hans de Goede <hdegoede@redhat.com>
Copyright © 2012-2013 Martin Pieuchot <mpi@openbsd.org> Copyright © 2012-2013 Martin Pieuchot <mpi@openbsd.org>
Copyright © 2012-2013 Toby Gray <toby.gray@realvnc.com> Copyright © 2012-2013 Toby Gray <toby.gray@realvnc.com>
Copyright © 2013-2015 Chris Dickens <christopher.a.dickens@gmail.com> Copyright © 2013-2018 Chris Dickens <christopher.a.dickens@gmail.com>
Other contributors: Other contributors:
Adrian Bunk
Akshay Jaggi Akshay Jaggi
Alan Ott Alan Ott
Alan Stern Alan Stern
Alex Vatchenko Alex Vatchenko
Andrew Fernandes Andrew Fernandes
Andy Chunyu
Andy McFadden
Angus Gratton
Anil Nair
Anthony Clay Anthony Clay
Antonio Ospite Antonio Ospite
Artem Egorkine Artem Egorkine
@ -23,12 +28,17 @@ Aurelien Jarno
Bastien Nocera Bastien Nocera
Bei Zhang Bei Zhang
Benjamin Dobell Benjamin Dobell
Brent Rector
Carl Karsten Carl Karsten
Christophe Zeitouny
Colin Walters Colin Walters
Dave Camarillo Dave Camarillo
David Engraf David Engraf
David Moore David Moore
Davidlohr Bueso Davidlohr Bueso
Dmitry Fleytman
Doug Johnston
Evan Hunter
Federico Manzan Federico Manzan
Felipe Balbi Felipe Balbi
Florian Albrechtskirchinger Florian Albrechtskirchinger
@ -41,23 +51,34 @@ Hans Ulrich Niedermann
Hector Martin Hector Martin
Hoi-Ho Chan Hoi-Ho Chan
Ilya Konstantinov Ilya Konstantinov
Jakub Klama
James Hanko James Hanko
Jeffrey Nichols
Johann Richard
John Sheu John Sheu
Jonathon Jongsma
Joost Muller
Josh Gao
Joshua Blake Joshua Blake
Justin Bischoff Justin Bischoff
KIMURA Masaru
Karsten Koenig Karsten Koenig
Konrad Rzepecki Konrad Rzepecki
Kuangye Guo Kuangye Guo
Lars Kanis Lars Kanis
Lars Wirzenius Lars Wirzenius
Lei Chen
Luca Longinotti Luca Longinotti
Marcus Meissner Marcus Meissner
Markus Heidelberg Markus Heidelberg
Martin Ettl Martin Ettl
Martin Koegler Martin Koegler
Matthew Stapleton
Matthias Bolte Matthias Bolte
Michel Zou
Mike Frysinger Mike Frysinger
Mikhail Gusarov Mikhail Gusarov
Morgan Leborgne
Moritz Fischer Moritz Fischer
Ларионов Даниил Ларионов Даниил
Nicholas Corgan Nicholas Corgan
@ -66,10 +87,17 @@ Orin Eman
Paul Fertser Paul Fertser
Pekka Nikander Pekka Nikander
Rob Walker Rob Walker
Romain Vimont
Roman Kalashnikov
Sameeh Jubran
Sean McBride Sean McBride
Sebastian Pipping Sebastian Pipping
Sergey Serb
Simon Haggett Simon Haggett
Simon Newton Simon Newton
Stefan Agner
Stefan Tauner
Steinar H. Gunderson
Thomas Röfer Thomas Röfer
Tim Hutt Tim Hutt
Tim Roberts Tim Roberts
@ -81,9 +109,11 @@ Uri Lublin
Vasily Khoruzhick Vasily Khoruzhick
Vegard Storheil Eriksen Vegard Storheil Eriksen
Venkatesh Shukla Venkatesh Shukla
Vianney le Clément de Saint-Marcq
Victor Toso
Vitali Lovich Vitali Lovich
William Skellenger
Xiaofan Chen Xiaofan Chen
Zoltán Kovács Zoltán Kovács
Роман Донченко Роман Донченко
parafin parafin
xantares

4
Externals/libusb/Brewfile vendored Normal file
View File

@ -0,0 +1,4 @@
brew 'automake'
brew 'libtool'
brew 'autoconf'
brew 'm4'

View File

@ -1,6 +1,41 @@
For detailed information about the changes below, please see the git log or For detailed information about the changes below, please see the git log or
visit: http://log.libusb.info 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: 2016-10-01: v1.0.21:
* Core: Refactor code related to transfer flags and timeout handling * Core: Refactor code related to transfer flags and timeout handling
* Darwin: Ignore root hub simulation devices * Darwin: Ignore root hub simulation devices

View File

@ -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

73
Externals/libusb/INSTALL_WIN.txt vendored Normal file
View File

@ -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

28
Externals/libusb/Makefile.am vendored Normal file
View File

@ -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)

View File

@ -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 <pete@akeo.ie>
- Hans de Goede <hdegoede@redhat.com>
- Xiaofan Chen <xiaofanc@gmail.com>
- Ludovic Rousseau <ludovic.rousseau@gmail.com>
- Nathan Hjelm <hjelmn@cs.unm.edu>
- Chris Dickens <christopher.a.dickens@gmail.com>
(Please use the mailing list rather than mailing developers directly)

1
Externals/libusb/README vendored Symbolic link
View File

@ -0,0 +1 @@
README.md

41
Externals/libusb/README.git vendored Normal file
View File

@ -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.

32
Externals/libusb/README.md vendored Normal file
View File

@ -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 <hdegoede@redhat.com>
- Xiaofan Chen <xiaofanc@gmail.com>
- Ludovic Rousseau <ludovic.rousseau@gmail.com>
- Nathan Hjelm <hjelmn@cs.unm.edu>
- Chris Dickens <christopher.a.dickens@gmail.com>
(Please use the mailing list rather than mailing developers directly)

61
Externals/libusb/Xcode/common.xcconfig vendored Normal file
View File

@ -0,0 +1,61 @@
//
// libusb Xcode configuration file
// Copyright © 2012 Pete Batard <pete@akeo.ie>
// For more information, please visit: <http://libusb.info>
//
// 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
// libusb does not follow C99 strict aliasing rules, so disable it.
GCC_STRICT_ALIASING = NO
// Use C99 dialect.
GCC_C_LANGUAGE_STANDARD = c99
// Don't search user paths with <> style #includes.
ALWAYS_SEARCH_USER_PATHS = NO
// Compiler warnings.
GCC_WARN_64_TO_32_BIT_CONVERSION = YES
GCC_WARN_ABOUT_RETURN_TYPE = YES
GCC_WARN_UNINITIALIZED_AUTOS = YES
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES
GCC_WARN_SHADOW = YES
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES
GCC_WARN_ABOUT_MISSING_NEWLINE = YES
GCC_WARN_UNKNOWN_PRAGMAS = YES
GCC_WARN_UNUSED_FUNCTION = YES
GCC_WARN_UNUSED_LABEL = YES
GCC_WARN_UNUSED_VARIABLE = YES
GCC_WARN_UNUSED_PARAMETER = YES
CLANG_WARN_EMPTY_BODY = YES
CLANG_WARN_CONSTANT_CONVERSION = YES
CLANG_WARN_ENUM_CONVERSION = YES
CLANG_WARN_INT_CONVERSION = YES
CLANG_WARN_DOCUMENTATION_COMMENTS = YES
CLANG_WARN_BOOL_CONVERSION = YES
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES
CLANG_WARN_FLOAT_CONVERSION = YES
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES
CLANG_WARN_INFINITE_RECURSION = YES
CLANG_WARN_ASSIGN_ENUM = YES
CLANG_WARN_STRICT_PROTOTYPES = YES
CLANG_WARN_COMMA = YES
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES
// Static analyzer warnings.
CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES
CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES

25
Externals/libusb/Xcode/config.h vendored Normal file
View File

@ -0,0 +1,25 @@
/* config.h. Manually generated for Xcode. */
/* Default visibility */
#define DEFAULT_VISIBILITY /**/
/* Message logging */
#define ENABLE_LOGGING 1
/* Define to 1 if you have the <poll.h> header file. */
#define HAVE_POLL_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Darwin backend */
#define OS_DARWIN 1
/* type of second poll() argument */
#define POLL_NFDS_TYPE nfds_t
/* Use POSIX Threads */
#define THREADS_POSIX 1
/* Use GNU extensions */
#define _GNU_SOURCE 1

29
Externals/libusb/Xcode/debug.xcconfig vendored Normal file
View File

@ -0,0 +1,29 @@
//
// libusb Xcode configuration file
// Copyright © 2012 Pete Batard <pete@akeo.ie>
// For more information, please visit: <http://libusb.info>
//
// 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 "common.xcconfig"
// Embed debug symbols in binary itself.
DEBUG_INFORMATION_FORMAT = dwarf
// No optimizations in debug.
GCC_OPTIMIZATION_LEVEL = 0
//
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) DEBUG=1

21
Externals/libusb/Xcode/libusb.xcconfig vendored Normal file
View File

@ -0,0 +1,21 @@
//
// libusb Xcode configuration file
// Copyright © 2012 Pete Batard <pete@akeo.ie>
// For more information, please visit: <http://libusb.info>
//
// 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
PRODUCT_NAME = libusb-1.0.0
LD_DYLIB_INSTALL_NAME = @rpath/libusb-1.0.0.dylib

View File

@ -0,0 +1,959 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 45;
objects = {
/* Begin PBXAggregateTarget section */
008FC0321628BC9400BC5BE2 /* all */ = {
isa = PBXAggregateTarget;
buildConfigurationList = 008FC0331628BC9400BC5BE2 /* Build configuration list for PBXAggregateTarget "all" */;
buildPhases = (
);
dependencies = (
006AD4281C8C5BBC007F8C6A /* PBXTargetDependency */,
008FC0371628BC9A00BC5BE2 /* PBXTargetDependency */,
008FC0391628BC9A00BC5BE2 /* PBXTargetDependency */,
008FC03B1628BC9A00BC5BE2 /* PBXTargetDependency */,
008FC03D1628BC9A00BC5BE2 /* PBXTargetDependency */,
008FC03F1628BC9A00BC5BE2 /* PBXTargetDependency */,
008FC0411628BC9A00BC5BE2 /* PBXTargetDependency */,
);
name = all;
productName = all;
};
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
006AD4241C8C5AAE007F8C6A /* hotplugtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 006AD4231C8C5AAE007F8C6A /* hotplugtest.c */; };
006AD4251C8C5AC4007F8C6A /* hotplugtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 006AD4231C8C5AAE007F8C6A /* hotplugtest.c */; };
006AD4261C8C5AD9007F8C6A /* libusb-1.0.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */; };
008FBF861628B7E800BC5BE2 /* core.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBF541628B7E800BC5BE2 /* core.c */; };
008FBF871628B7E800BC5BE2 /* descriptor.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBF551628B7E800BC5BE2 /* descriptor.c */; };
008FBF881628B7E800BC5BE2 /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBF561628B7E800BC5BE2 /* io.c */; };
008FBF891628B7E800BC5BE2 /* libusb.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBF5A1628B7E800BC5BE2 /* libusb.h */; };
008FBF901628B7E800BC5BE2 /* libusbi.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBF671628B7E800BC5BE2 /* libusbi.h */; };
008FBF921628B7E800BC5BE2 /* darwin_usb.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBF6C1628B7E800BC5BE2 /* darwin_usb.c */; };
008FBF931628B7E800BC5BE2 /* darwin_usb.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBF6D1628B7E800BC5BE2 /* darwin_usb.h */; };
008FBF971628B7E800BC5BE2 /* poll_posix.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBF711628B7E800BC5BE2 /* poll_posix.h */; };
008FBF9A1628B7E800BC5BE2 /* threads_posix.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBF741628B7E800BC5BE2 /* threads_posix.c */; };
008FBF9B1628B7E800BC5BE2 /* threads_posix.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBF751628B7E800BC5BE2 /* threads_posix.h */; };
008FBFA01628B7E800BC5BE2 /* sync.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBF7A1628B7E800BC5BE2 /* sync.c */; };
008FBFA11628B7E800BC5BE2 /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBF7B1628B7E800BC5BE2 /* version.h */; };
008FBFA21628B7E800BC5BE2 /* version_nano.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBF7C1628B7E800BC5BE2 /* version_nano.h */; };
008FBFA51628B84200BC5BE2 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 008FBFA41628B84200BC5BE2 /* config.h */; };
008FBFA71628B87000BC5BE2 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBFA61628B87000BC5BE2 /* CoreFoundation.framework */; };
008FBFA91628B88000BC5BE2 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBFA81628B88000BC5BE2 /* IOKit.framework */; };
008FBFAB1628B8CB00BC5BE2 /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBFAA1628B8CB00BC5BE2 /* libobjc.dylib */; };
008FBFEF1628BA3500BC5BE2 /* xusb.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBFED1628BA0E00BC5BE2 /* xusb.c */; };
008FBFF01628BA3A00BC5BE2 /* libusb-1.0.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */; };
008FBFFF1628BB9600BC5BE2 /* dpfp.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBFD71628BA0E00BC5BE2 /* dpfp.c */; };
008FC0001628BBCD00BC5BE2 /* libusb-1.0.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */; };
008FC00F1628BBE400BC5BE2 /* dpfp_threaded.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBFDB1628BA0E00BC5BE2 /* dpfp_threaded.c */; };
008FC0101628BBE900BC5BE2 /* libusb-1.0.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */; };
008FC01F1628BC1500BC5BE2 /* fxload.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBFE11628BA0E00BC5BE2 /* fxload.c */; };
008FC0201628BC1B00BC5BE2 /* libusb-1.0.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */; };
008FC0211628BC5200BC5BE2 /* ezusb.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBFDC1628BA0E00BC5BE2 /* ezusb.c */; };
008FC0301628BC7400BC5BE2 /* listdevs.c in Sources */ = {isa = PBXBuildFile; fileRef = 008FBFE71628BA0E00BC5BE2 /* listdevs.c */; };
008FC0311628BC7800BC5BE2 /* libusb-1.0.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */; };
1438D77A17A2ED9F00166101 /* hotplug.c in Sources */ = {isa = PBXBuildFile; fileRef = 1438D77817A2ED9F00166101 /* hotplug.c */; };
1438D77B17A2ED9F00166101 /* hotplug.h in Headers */ = {isa = PBXBuildFile; fileRef = 1438D77917A2ED9F00166101 /* hotplug.h */; };
1438D77D17A2EDCD00166101 /* poll_posix.c in Sources */ = {isa = PBXBuildFile; fileRef = 1438D77C17A2EDCD00166101 /* poll_posix.c */; };
1438D77F17A2F0EA00166101 /* strerror.c in Sources */ = {isa = PBXBuildFile; fileRef = 1438D77E17A2F0EA00166101 /* strerror.c */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
006AD4271C8C5BBC007F8C6A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 006AD41B1C8C5A90007F8C6A;
remoteInfo = hotplugtest;
};
008FC0361628BC9A00BC5BE2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 008FBF301628B79300BC5BE2;
remoteInfo = libusb;
};
008FC0381628BC9A00BC5BE2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 008FBFBC1628B9FE00BC5BE2;
remoteInfo = xusb;
};
008FC03A1628BC9A00BC5BE2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 008FBFF41628BB8B00BC5BE2;
remoteInfo = dpfp;
};
008FC03C1628BC9A00BC5BE2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 008FC0041628BBDB00BC5BE2;
remoteInfo = dpfp_threaded;
};
008FC03E1628BC9A00BC5BE2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 008FC0141628BC0300BC5BE2;
remoteInfo = fxload;
};
008FC0401628BC9A00BC5BE2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 008FC0251628BC6B00BC5BE2;
remoteInfo = listdevs;
};
1443EE8B1641926D007E0579 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 008FBF301628B79300BC5BE2;
remoteInfo = libusb;
};
1443EE8D16419273007E0579 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 008FBF301628B79300BC5BE2;
remoteInfo = libusb;
};
1443EE8F16419276007E0579 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 008FBF301628B79300BC5BE2;
remoteInfo = libusb;
};
1443EE911641927A007E0579 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 008FBF301628B79300BC5BE2;
remoteInfo = libusb;
};
1443EE931641927D007E0579 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 008FBF281628B79300BC5BE2 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 008FBF301628B79300BC5BE2;
remoteInfo = libusb;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
006AD41A1C8C5A90007F8C6A /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
008FBFBB1628B9FE00BC5BE2 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
008FBFF31628BB8B00BC5BE2 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
008FC0031628BBDB00BC5BE2 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
008FC0131628BC0300BC5BE2 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
008FC0241628BC6B00BC5BE2 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
006AD41C1C8C5A90007F8C6A /* hotplugtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = hotplugtest; sourceTree = BUILT_PRODUCTS_DIR; };
006AD4231C8C5AAE007F8C6A /* hotplugtest.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = hotplugtest.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = "libusb-1.0.0.dylib"; sourceTree = BUILT_PRODUCTS_DIR; };
008FBF541628B7E800BC5BE2 /* core.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = core.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBF551628B7E800BC5BE2 /* descriptor.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = descriptor.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBF561628B7E800BC5BE2 /* io.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = io.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBF5A1628B7E800BC5BE2 /* libusb.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = libusb.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBF671628B7E800BC5BE2 /* libusbi.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = libusbi.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBF6C1628B7E800BC5BE2 /* darwin_usb.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = darwin_usb.c; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
008FBF6D1628B7E800BC5BE2 /* darwin_usb.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = darwin_usb.h; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
008FBF711628B7E800BC5BE2 /* poll_posix.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = poll_posix.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBF741628B7E800BC5BE2 /* threads_posix.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = threads_posix.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBF751628B7E800BC5BE2 /* threads_posix.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = threads_posix.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBF7A1628B7E800BC5BE2 /* sync.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = sync.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBF7B1628B7E800BC5BE2 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBF7C1628B7E800BC5BE2 /* version_nano.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = version_nano.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBFA41628B84200BC5BE2 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBFA61628B87000BC5BE2 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
008FBFA81628B88000BC5BE2 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
008FBFAA1628B8CB00BC5BE2 /* libobjc.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libobjc.dylib; path = usr/lib/libobjc.dylib; sourceTree = SDKROOT; };
008FBFBD1628B9FE00BC5BE2 /* xusb */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xusb; sourceTree = BUILT_PRODUCTS_DIR; };
008FBFD71628BA0E00BC5BE2 /* dpfp.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = dpfp.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBFDB1628BA0E00BC5BE2 /* dpfp_threaded.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = dpfp_threaded.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBFDC1628BA0E00BC5BE2 /* ezusb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = ezusb.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBFDD1628BA0E00BC5BE2 /* ezusb.h */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = ezusb.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBFE11628BA0E00BC5BE2 /* fxload.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = fxload.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBFE71628BA0E00BC5BE2 /* listdevs.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = listdevs.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBFED1628BA0E00BC5BE2 /* xusb.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = xusb.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
008FBFF51628BB8B00BC5BE2 /* dpfp */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dpfp; sourceTree = BUILT_PRODUCTS_DIR; };
008FC0051628BBDB00BC5BE2 /* dpfp_threaded */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dpfp_threaded; sourceTree = BUILT_PRODUCTS_DIR; };
008FC0151628BC0300BC5BE2 /* fxload */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fxload; sourceTree = BUILT_PRODUCTS_DIR; };
008FC0261628BC6B00BC5BE2 /* listdevs */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = listdevs; sourceTree = BUILT_PRODUCTS_DIR; };
1438D77817A2ED9F00166101 /* hotplug.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = hotplug.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
1438D77917A2ED9F00166101 /* hotplug.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = hotplug.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
1438D77C17A2EDCD00166101 /* poll_posix.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = poll_posix.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
1438D77E17A2F0EA00166101 /* strerror.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = strerror.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
1443EE8416417E63007E0579 /* common.xcconfig */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.xcconfig; path = common.xcconfig; sourceTree = SOURCE_ROOT; tabWidth = 4; usesTabs = 1; };
1443EE8516417E63007E0579 /* debug.xcconfig */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = SOURCE_ROOT; tabWidth = 4; usesTabs = 1; };
1443EE8616417E63007E0579 /* libusb_debug.xcconfig */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.xcconfig; path = libusb_debug.xcconfig; sourceTree = SOURCE_ROOT; tabWidth = 4; usesTabs = 1; };
1443EE8716417E63007E0579 /* libusb.xcconfig */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.xcconfig; path = libusb.xcconfig; sourceTree = SOURCE_ROOT; tabWidth = 4; usesTabs = 1; };
1443EE8816417E63007E0579 /* release.xcconfig */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = SOURCE_ROOT; tabWidth = 4; usesTabs = 1; };
1443EE8916417EA6007E0579 /* libusb_release.xcconfig */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.xcconfig; path = libusb_release.xcconfig; sourceTree = SOURCE_ROOT; tabWidth = 4; usesTabs = 1; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
006AD4191C8C5A90007F8C6A /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
006AD4261C8C5AD9007F8C6A /* libusb-1.0.0.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
008FBF2E1628B79300BC5BE2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
008FBFAB1628B8CB00BC5BE2 /* libobjc.dylib in Frameworks */,
008FBFA91628B88000BC5BE2 /* IOKit.framework in Frameworks */,
008FBFA71628B87000BC5BE2 /* CoreFoundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
008FBFBA1628B9FE00BC5BE2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
008FBFF01628BA3A00BC5BE2 /* libusb-1.0.0.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
008FBFF21628BB8B00BC5BE2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
008FC0001628BBCD00BC5BE2 /* libusb-1.0.0.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
008FC0021628BBDB00BC5BE2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
008FC0101628BBE900BC5BE2 /* libusb-1.0.0.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
008FC0121628BC0300BC5BE2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
008FC0201628BC1B00BC5BE2 /* libusb-1.0.0.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
008FC0231628BC6B00BC5BE2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
008FC0311628BC7800BC5BE2 /* libusb-1.0.0.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
008FBF261628B79300BC5BE2 = {
isa = PBXGroup;
children = (
1443EE8316417DE3007E0579 /* xcconfig */,
008FBFA41628B84200BC5BE2 /* config.h */,
008FBF3B1628B7E800BC5BE2 /* libusb */,
008FBFC81628BA0E00BC5BE2 /* examples */,
1443EE8A16419057007E0579 /* Apple */,
008FBF321628B79300BC5BE2 /* Products */,
);
sourceTree = "<group>";
};
008FBF321628B79300BC5BE2 /* Products */ = {
isa = PBXGroup;
children = (
008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */,
008FBFBD1628B9FE00BC5BE2 /* xusb */,
008FBFF51628BB8B00BC5BE2 /* dpfp */,
008FC0051628BBDB00BC5BE2 /* dpfp_threaded */,
008FC0151628BC0300BC5BE2 /* fxload */,
008FC0261628BC6B00BC5BE2 /* listdevs */,
006AD41C1C8C5A90007F8C6A /* hotplugtest */,
);
name = Products;
sourceTree = "<group>";
};
008FBF3B1628B7E800BC5BE2 /* libusb */ = {
isa = PBXGroup;
children = (
008FBF541628B7E800BC5BE2 /* core.c */,
008FBF551628B7E800BC5BE2 /* descriptor.c */,
1438D77817A2ED9F00166101 /* hotplug.c */,
1438D77917A2ED9F00166101 /* hotplug.h */,
008FBF561628B7E800BC5BE2 /* io.c */,
008FBF5A1628B7E800BC5BE2 /* libusb.h */,
008FBF671628B7E800BC5BE2 /* libusbi.h */,
008FBF6B1628B7E800BC5BE2 /* os */,
1438D77E17A2F0EA00166101 /* strerror.c */,
008FBF7A1628B7E800BC5BE2 /* sync.c */,
008FBF7B1628B7E800BC5BE2 /* version.h */,
008FBF7C1628B7E800BC5BE2 /* version_nano.h */,
);
name = libusb;
path = ../libusb;
sourceTree = "<group>";
};
008FBF6B1628B7E800BC5BE2 /* os */ = {
isa = PBXGroup;
children = (
008FBF6C1628B7E800BC5BE2 /* darwin_usb.c */,
008FBF6D1628B7E800BC5BE2 /* darwin_usb.h */,
1438D77C17A2EDCD00166101 /* poll_posix.c */,
008FBF711628B7E800BC5BE2 /* poll_posix.h */,
008FBF741628B7E800BC5BE2 /* threads_posix.c */,
008FBF751628B7E800BC5BE2 /* threads_posix.h */,
);
path = os;
sourceTree = "<group>";
};
008FBFC81628BA0E00BC5BE2 /* examples */ = {
isa = PBXGroup;
children = (
008FBFDB1628BA0E00BC5BE2 /* dpfp_threaded.c */,
008FBFD71628BA0E00BC5BE2 /* dpfp.c */,
008FBFDC1628BA0E00BC5BE2 /* ezusb.c */,
008FBFDD1628BA0E00BC5BE2 /* ezusb.h */,
008FBFE11628BA0E00BC5BE2 /* fxload.c */,
006AD4231C8C5AAE007F8C6A /* hotplugtest.c */,
008FBFE71628BA0E00BC5BE2 /* listdevs.c */,
008FBFED1628BA0E00BC5BE2 /* xusb.c */,
);
name = examples;
path = ../examples;
sourceTree = "<group>";
};
1443EE8316417DE3007E0579 /* xcconfig */ = {
isa = PBXGroup;
children = (
1443EE8416417E63007E0579 /* common.xcconfig */,
1443EE8516417E63007E0579 /* debug.xcconfig */,
1443EE8816417E63007E0579 /* release.xcconfig */,
1443EE8716417E63007E0579 /* libusb.xcconfig */,
1443EE8616417E63007E0579 /* libusb_debug.xcconfig */,
1443EE8916417EA6007E0579 /* libusb_release.xcconfig */,
);
name = xcconfig;
path = ../libusb;
sourceTree = "<group>";
};
1443EE8A16419057007E0579 /* Apple */ = {
isa = PBXGroup;
children = (
008FBFAA1628B8CB00BC5BE2 /* libobjc.dylib */,
008FBFA81628B88000BC5BE2 /* IOKit.framework */,
008FBFA61628B87000BC5BE2 /* CoreFoundation.framework */,
);
name = Apple;
path = ../libusb;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
008FBF2F1628B79300BC5BE2 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
008FBF891628B7E800BC5BE2 /* libusb.h in Headers */,
008FBF901628B7E800BC5BE2 /* libusbi.h in Headers */,
008FBF931628B7E800BC5BE2 /* darwin_usb.h in Headers */,
008FBF971628B7E800BC5BE2 /* poll_posix.h in Headers */,
008FBF9B1628B7E800BC5BE2 /* threads_posix.h in Headers */,
008FBFA11628B7E800BC5BE2 /* version.h in Headers */,
008FBFA21628B7E800BC5BE2 /* version_nano.h in Headers */,
008FBFA51628B84200BC5BE2 /* config.h in Headers */,
1438D77B17A2ED9F00166101 /* hotplug.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
006AD41B1C8C5A90007F8C6A /* hotplugtest */ = {
isa = PBXNativeTarget;
buildConfigurationList = 006AD4221C8C5A90007F8C6A /* Build configuration list for PBXNativeTarget "hotplugtest" */;
buildPhases = (
006AD4181C8C5A90007F8C6A /* Sources */,
006AD4191C8C5A90007F8C6A /* Frameworks */,
006AD41A1C8C5A90007F8C6A /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = hotplugtest;
productName = hotplugtest;
productReference = 006AD41C1C8C5A90007F8C6A /* hotplugtest */;
productType = "com.apple.product-type.tool";
};
008FBF301628B79300BC5BE2 /* libusb */ = {
isa = PBXNativeTarget;
buildConfigurationList = 008FBF351628B79300BC5BE2 /* Build configuration list for PBXNativeTarget "libusb" */;
buildPhases = (
008FBF2D1628B79300BC5BE2 /* Sources */,
008FBF2E1628B79300BC5BE2 /* Frameworks */,
008FBF2F1628B79300BC5BE2 /* Headers */,
);
buildRules = (
);
dependencies = (
);
name = libusb;
productName = libusb;
productReference = 008FBF311628B79300BC5BE2 /* libusb-1.0.0.dylib */;
productType = "com.apple.product-type.library.dynamic";
};
008FBFBC1628B9FE00BC5BE2 /* xusb */ = {
isa = PBXNativeTarget;
buildConfigurationList = 008FBFC61628B9FE00BC5BE2 /* Build configuration list for PBXNativeTarget "xusb" */;
buildPhases = (
008FBFB91628B9FE00BC5BE2 /* Sources */,
008FBFBA1628B9FE00BC5BE2 /* Frameworks */,
008FBFBB1628B9FE00BC5BE2 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
1443EE941641927D007E0579 /* PBXTargetDependency */,
);
name = xusb;
productName = xusb;
productReference = 008FBFBD1628B9FE00BC5BE2 /* xusb */;
productType = "com.apple.product-type.tool";
};
008FBFF41628BB8B00BC5BE2 /* dpfp */ = {
isa = PBXNativeTarget;
buildConfigurationList = 008FBFFC1628BB8C00BC5BE2 /* Build configuration list for PBXNativeTarget "dpfp" */;
buildPhases = (
008FBFF11628BB8B00BC5BE2 /* Sources */,
008FBFF21628BB8B00BC5BE2 /* Frameworks */,
008FBFF31628BB8B00BC5BE2 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
1443EE921641927A007E0579 /* PBXTargetDependency */,
);
name = dpfp;
productName = dpfp;
productReference = 008FBFF51628BB8B00BC5BE2 /* dpfp */;
productType = "com.apple.product-type.tool";
};
008FC0041628BBDB00BC5BE2 /* dpfp_threaded */ = {
isa = PBXNativeTarget;
buildConfigurationList = 008FC00C1628BBDB00BC5BE2 /* Build configuration list for PBXNativeTarget "dpfp_threaded" */;
buildPhases = (
008FC0011628BBDB00BC5BE2 /* Sources */,
008FC0021628BBDB00BC5BE2 /* Frameworks */,
008FC0031628BBDB00BC5BE2 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
1443EE9016419276007E0579 /* PBXTargetDependency */,
);
name = dpfp_threaded;
productName = dpfp_threaded;
productReference = 008FC0051628BBDB00BC5BE2 /* dpfp_threaded */;
productType = "com.apple.product-type.tool";
};
008FC0141628BC0300BC5BE2 /* fxload */ = {
isa = PBXNativeTarget;
buildConfigurationList = 008FC01C1628BC0300BC5BE2 /* Build configuration list for PBXNativeTarget "fxload" */;
buildPhases = (
008FC0111628BC0300BC5BE2 /* Sources */,
008FC0121628BC0300BC5BE2 /* Frameworks */,
008FC0131628BC0300BC5BE2 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
1443EE8E16419273007E0579 /* PBXTargetDependency */,
);
name = fxload;
productName = fxload;
productReference = 008FC0151628BC0300BC5BE2 /* fxload */;
productType = "com.apple.product-type.tool";
};
008FC0251628BC6B00BC5BE2 /* listdevs */ = {
isa = PBXNativeTarget;
buildConfigurationList = 008FC02D1628BC6B00BC5BE2 /* Build configuration list for PBXNativeTarget "listdevs" */;
buildPhases = (
008FC0221628BC6B00BC5BE2 /* Sources */,
008FC0231628BC6B00BC5BE2 /* Frameworks */,
008FC0241628BC6B00BC5BE2 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
1443EE8C1641926D007E0579 /* PBXTargetDependency */,
);
name = listdevs;
productName = listdevs;
productReference = 008FC0261628BC6B00BC5BE2 /* listdevs */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
008FBF281628B79300BC5BE2 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0450;
ORGANIZATIONNAME = libusb;
TargetAttributes = {
006AD41B1C8C5A90007F8C6A = {
CreatedOnToolsVersion = 7.2.1;
};
};
};
buildConfigurationList = 008FBF2B1628B79300BC5BE2 /* Build configuration list for PBXProject "libusb" */;
compatibilityVersion = "Xcode 3.1";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 008FBF261628B79300BC5BE2;
productRefGroup = 008FBF321628B79300BC5BE2 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
008FBF301628B79300BC5BE2 /* libusb */,
008FBFBC1628B9FE00BC5BE2 /* xusb */,
008FBFF41628BB8B00BC5BE2 /* dpfp */,
008FC0041628BBDB00BC5BE2 /* dpfp_threaded */,
008FC0141628BC0300BC5BE2 /* fxload */,
008FC0251628BC6B00BC5BE2 /* listdevs */,
006AD41B1C8C5A90007F8C6A /* hotplugtest */,
008FC0321628BC9400BC5BE2 /* all */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
006AD4181C8C5A90007F8C6A /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
006AD4251C8C5AC4007F8C6A /* hotplugtest.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
008FBF2D1628B79300BC5BE2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
008FBF861628B7E800BC5BE2 /* core.c in Sources */,
008FBF871628B7E800BC5BE2 /* descriptor.c in Sources */,
008FBF881628B7E800BC5BE2 /* io.c in Sources */,
008FBF921628B7E800BC5BE2 /* darwin_usb.c in Sources */,
008FBF9A1628B7E800BC5BE2 /* threads_posix.c in Sources */,
008FBFA01628B7E800BC5BE2 /* sync.c in Sources */,
1438D77A17A2ED9F00166101 /* hotplug.c in Sources */,
1438D77D17A2EDCD00166101 /* poll_posix.c in Sources */,
1438D77F17A2F0EA00166101 /* strerror.c in Sources */,
006AD4241C8C5AAE007F8C6A /* hotplugtest.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
008FBFB91628B9FE00BC5BE2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
008FBFEF1628BA3500BC5BE2 /* xusb.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
008FBFF11628BB8B00BC5BE2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
008FBFFF1628BB9600BC5BE2 /* dpfp.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
008FC0011628BBDB00BC5BE2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
008FC00F1628BBE400BC5BE2 /* dpfp_threaded.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
008FC0111628BC0300BC5BE2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
008FC0211628BC5200BC5BE2 /* ezusb.c in Sources */,
008FC01F1628BC1500BC5BE2 /* fxload.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
008FC0221628BC6B00BC5BE2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
008FC0301628BC7400BC5BE2 /* listdevs.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
006AD4281C8C5BBC007F8C6A /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 006AD41B1C8C5A90007F8C6A /* hotplugtest */;
targetProxy = 006AD4271C8C5BBC007F8C6A /* PBXContainerItemProxy */;
};
008FC0371628BC9A00BC5BE2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 008FBF301628B79300BC5BE2 /* libusb */;
targetProxy = 008FC0361628BC9A00BC5BE2 /* PBXContainerItemProxy */;
};
008FC0391628BC9A00BC5BE2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 008FBFBC1628B9FE00BC5BE2 /* xusb */;
targetProxy = 008FC0381628BC9A00BC5BE2 /* PBXContainerItemProxy */;
};
008FC03B1628BC9A00BC5BE2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 008FBFF41628BB8B00BC5BE2 /* dpfp */;
targetProxy = 008FC03A1628BC9A00BC5BE2 /* PBXContainerItemProxy */;
};
008FC03D1628BC9A00BC5BE2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 008FC0041628BBDB00BC5BE2 /* dpfp_threaded */;
targetProxy = 008FC03C1628BC9A00BC5BE2 /* PBXContainerItemProxy */;
};
008FC03F1628BC9A00BC5BE2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 008FC0141628BC0300BC5BE2 /* fxload */;
targetProxy = 008FC03E1628BC9A00BC5BE2 /* PBXContainerItemProxy */;
};
008FC0411628BC9A00BC5BE2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 008FC0251628BC6B00BC5BE2 /* listdevs */;
targetProxy = 008FC0401628BC9A00BC5BE2 /* PBXContainerItemProxy */;
};
1443EE8C1641926D007E0579 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 008FBF301628B79300BC5BE2 /* libusb */;
targetProxy = 1443EE8B1641926D007E0579 /* PBXContainerItemProxy */;
};
1443EE8E16419273007E0579 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 008FBF301628B79300BC5BE2 /* libusb */;
targetProxy = 1443EE8D16419273007E0579 /* PBXContainerItemProxy */;
};
1443EE9016419276007E0579 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 008FBF301628B79300BC5BE2 /* libusb */;
targetProxy = 1443EE8F16419276007E0579 /* PBXContainerItemProxy */;
};
1443EE921641927A007E0579 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 008FBF301628B79300BC5BE2 /* libusb */;
targetProxy = 1443EE911641927A007E0579 /* PBXContainerItemProxy */;
};
1443EE941641927D007E0579 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 008FBF301628B79300BC5BE2 /* libusb */;
targetProxy = 1443EE931641927D007E0579 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
006AD4201C8C5A90007F8C6A /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
006AD4211C8C5A90007F8C6A /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
008FBF331628B79300BC5BE2 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
buildSettings = {
};
name = Debug;
};
008FBF341628B79300BC5BE2 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
buildSettings = {
};
name = Release;
};
008FBF361628B79300BC5BE2 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1443EE8616417E63007E0579 /* libusb_debug.xcconfig */;
buildSettings = {
};
name = Debug;
};
008FBF371628B79300BC5BE2 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1443EE8916417EA6007E0579 /* libusb_release.xcconfig */;
buildSettings = {
};
name = Release;
};
008FBFC41628B9FE00BC5BE2 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
008FBFC51628B9FE00BC5BE2 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
008FBFFD1628BB8C00BC5BE2 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
008FBFFE1628BB8C00BC5BE2 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
008FC00D1628BBDB00BC5BE2 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
008FC00E1628BBDB00BC5BE2 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
008FC01D1628BC0300BC5BE2 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
008FC01E1628BC0300BC5BE2 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
008FC02E1628BC6B00BC5BE2 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1443EE8516417E63007E0579 /* debug.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
008FC02F1628BC6B00BC5BE2 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1443EE8816417E63007E0579 /* release.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
008FC0341628BC9400BC5BE2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
008FC0351628BC9400BC5BE2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
006AD4221C8C5A90007F8C6A /* Build configuration list for PBXNativeTarget "hotplugtest" */ = {
isa = XCConfigurationList;
buildConfigurations = (
006AD4201C8C5A90007F8C6A /* Debug */,
006AD4211C8C5A90007F8C6A /* Release */,
);
defaultConfigurationIsVisible = 0;
};
008FBF2B1628B79300BC5BE2 /* Build configuration list for PBXProject "libusb" */ = {
isa = XCConfigurationList;
buildConfigurations = (
008FBF331628B79300BC5BE2 /* Debug */,
008FBF341628B79300BC5BE2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
008FBF351628B79300BC5BE2 /* Build configuration list for PBXNativeTarget "libusb" */ = {
isa = XCConfigurationList;
buildConfigurations = (
008FBF361628B79300BC5BE2 /* Debug */,
008FBF371628B79300BC5BE2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
008FBFC61628B9FE00BC5BE2 /* Build configuration list for PBXNativeTarget "xusb" */ = {
isa = XCConfigurationList;
buildConfigurations = (
008FBFC41628B9FE00BC5BE2 /* Debug */,
008FBFC51628B9FE00BC5BE2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
008FBFFC1628BB8C00BC5BE2 /* Build configuration list for PBXNativeTarget "dpfp" */ = {
isa = XCConfigurationList;
buildConfigurations = (
008FBFFD1628BB8C00BC5BE2 /* Debug */,
008FBFFE1628BB8C00BC5BE2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
008FC00C1628BBDB00BC5BE2 /* Build configuration list for PBXNativeTarget "dpfp_threaded" */ = {
isa = XCConfigurationList;
buildConfigurations = (
008FC00D1628BBDB00BC5BE2 /* Debug */,
008FC00E1628BBDB00BC5BE2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
008FC01C1628BC0300BC5BE2 /* Build configuration list for PBXNativeTarget "fxload" */ = {
isa = XCConfigurationList;
buildConfigurations = (
008FC01D1628BC0300BC5BE2 /* Debug */,
008FC01E1628BC0300BC5BE2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
008FC02D1628BC6B00BC5BE2 /* Build configuration list for PBXNativeTarget "listdevs" */ = {
isa = XCConfigurationList;
buildConfigurations = (
008FC02E1628BC6B00BC5BE2 /* Debug */,
008FC02F1628BC6B00BC5BE2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
008FC0331628BC9400BC5BE2 /* Build configuration list for PBXAggregateTarget "all" */ = {
isa = XCConfigurationList;
buildConfigurations = (
008FC0341628BC9400BC5BE2 /* Debug */,
008FC0351628BC9400BC5BE2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 008FBF281628B79300BC5BE2 /* Project object */;
}

View File

@ -0,0 +1,21 @@
//
// libusb Xcode configuration file
// Copyright © 2012 Pete Batard <pete@akeo.ie>
// For more information, please visit: <http://libusb.info>
//
// 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 "debug.xcconfig"
#include "libusb.xcconfig"

View File

@ -0,0 +1,21 @@
//
// libusb Xcode configuration file
// Copyright © 2012 Pete Batard <pete@akeo.ie>
// For more information, please visit: <http://libusb.info>
//
// 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 "release.xcconfig"
#include "libusb.xcconfig"

30
Externals/libusb/Xcode/release.xcconfig vendored Normal file
View File

@ -0,0 +1,30 @@
//
// libusb Xcode configuration file
// Copyright © 2012 Pete Batard <pete@akeo.ie>
// For more information, please visit: <http://libusb.info>
//
// 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 "common.xcconfig"
// Put debug symbols in separate .dym file.
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
// Optimizations in release.
GCC_OPTIMIZATION_LEVEL = s
LLVM_LTO = YES
// Define NDEBUG so asserts go away in release.
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) NDEBUG=1

116
Externals/libusb/android/README vendored Normal file
View File

@ -0,0 +1,116 @@
libusb for Android
==================
Building:
---------
To build libusb for Android do the following:
1. Download the latest NDK from:
http://developer.android.com/tools/sdk/ndk/index.html
2. Extract the NDK.
3. Open a shell and make sure there exist an NDK global variable
set to the directory where you extracted the NDK.
4. Change directory to libusb's "android/jni"
5. Run "$NDK/ndk-build".
The libusb library, examples and tests can then be found in:
"android/libs/$ARCH"
Where $ARCH is one of:
armeabi
armeabi-v7a
mips
mips64
x86
x86_64
Installing:
-----------
If you wish to use libusb from native code in own Android application
then you should add the following line to your Android.mk file:
include $(PATH_TO_LIBUSB_SRC)/android/jni/libusb.mk
You will then need to add the following lines to the build
configuration for each native binary which uses libusb:
LOCAL_C_INCLUDES += $(LIBUSB_ROOT_ABS)
LOCAL_SHARED_LIBRARIES += libusb1.0
The Android build system will then correctly include libusb in the
application package (APK) file, provided ndk-build is invoked before
the package is built.
For a rooted device it is possible to install libusb into the system
image of a running device:
1. Enable ADB on the device.
2. Connect the device to a machine running ADB.
3. Execute the following commands on the machine
running ADB:
# Make the system partition writable
adb shell su -c "mount -o remount,rw /system"
# Install libusb
adb push obj/local/armeabi/libusb1.0.so /sdcard/
adb shell su -c "cat > /system/lib/libusb1.0.so < /sdcard/libusb1.0.so"
adb shell rm /sdcard/libusb1.0.so
# Install the samples and tests
for B in listdevs fxload xusb sam3u_benchmark hotplugtest stress
do
adb push "obj/local/armeabi/$B" /sdcard/
adb shell su -c "cat > /system/bin/$B < /sdcard/$B"
adb shell su -c "chmod 0755 /system/bin/$B"
adb shell rm "/sdcard/$B"
done
# Make the system partition read only again
adb shell su -c "mount -o remount,ro /system"
# Run listdevs to
adb shell su -c "listdevs"
4. If your device only has a single OTG port then ADB can generally
be switched to using Wifi with the following commands when connected
via USB:
adb shell netcfg
# Note the wifi IP address of the phone
adb tcpip 5555
# Use the IP address from netcfg
adb connect 192.168.1.123:5555
Runtime Permissions:
--------------------
The default system configuration on most Android device will not allow
access to USB devices. There are several options for changing this.
If you have control of the system image then you can modify the
ueventd.rc used in the image to change the permissions on
/dev/bus/usb/*/*. If using this approach then it is advisable to
create a new Android permission to protect access to these files.
It is not advisable to give all applications read and write permissions
to these files.
For rooted devices the code using libusb could be executed as root
using the "su" command. An alternative would be to use the "su" command
to change the permissions on the appropriate /dev/bus/usb/ files.
Users have reported success in using android.hardware.usb.UsbManager
to request permission to use the UsbDevice and then opening the
device. The difficulties in this method is that there is no guarantee
that it will continue to work in the future Android versions, it
requires invoking Java APIs and running code to match each
android.hardware.usb.UsbDevice to a libusb_device.

75
Externals/libusb/android/config.h vendored Normal file
View File

@ -0,0 +1,75 @@
/*
* Android build config for libusb
* Copyright © 2012-2013 RealVNC Ltd. <toby.gray@realvnc.com>
*
* 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
*/
/* Start with debug message logging enabled */
/* #undef ENABLE_DEBUG_LOGGING */
/* Message logging */
#define ENABLE_LOGGING
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Linux backend */
#define OS_LINUX 1
/* Enable output to system log */
#define USE_SYSTEM_LOGGING_FACILITY 1
/* type of second poll() argument */
#define POLL_NFDS_TYPE nfds_t
/* Use POSIX Threads */
#define THREADS_POSIX 1
/* Default visibility */
#define DEFAULT_VISIBILITY __attribute__((visibility("default")))
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the <poll.h> header file. */
#define HAVE_POLL_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the <linux/filter.h> header file. */
#define HAVE_LINUX_FILTER_H 1
/* Define to 1 if you have the <linux/netlink.h> header file. */
#define HAVE_LINUX_NETLINK_H 1
/* Define to 1 if you have the <asm/types.h> header file. */
#define HAVE_ASM_TYPES_H 1
/* Define to 1 if you have the <sys/socket.h> header file. */
#define HAVE_SYS_SOCKET_H 1

23
Externals/libusb/android/jni/Android.mk vendored Normal file
View File

@ -0,0 +1,23 @@
# Android build config for libusb, examples and tests
# Copyright © 2012-2013 RealVNC Ltd. <toby.gray@realvnc.com>
#
# 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
#
LOCAL_PATH:= $(call my-dir)
include $(LOCAL_PATH)/libusb.mk
include $(LOCAL_PATH)/examples.mk
include $(LOCAL_PATH)/tests.mk

View File

@ -0,0 +1,24 @@
# Android application build config for libusb
# Copyright © 2012-2013 RealVNC Ltd. <toby.gray@realvnc.com>
#
# 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
#
APP_ABI := all
# Workaround for MIPS toolchain linker being unable to find liblog dependency
# of shared object in NDK versions at least up to r9.
#
APP_LDFLAGS := -llog

134
Externals/libusb/android/jni/examples.mk vendored Normal file
View File

@ -0,0 +1,134 @@
# Android build config for libusb examples
# Copyright © 2012-2013 RealVNC Ltd. <toby.gray@realvnc.com>
#
# 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
#
LOCAL_PATH:= $(call my-dir)
LIBUSB_ROOT_REL:= ../..
LIBUSB_ROOT_ABS:= $(LOCAL_PATH)/../..
# listdevs
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
$(LIBUSB_ROOT_REL)/examples/listdevs.c
LOCAL_C_INCLUDES += \
$(LIBUSB_ROOT_ABS)
LOCAL_SHARED_LIBRARIES += libusb1.0
LOCAL_MODULE:= listdevs
include $(BUILD_EXECUTABLE)
# xusb
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
$(LIBUSB_ROOT_REL)/examples/xusb.c
LOCAL_C_INCLUDES += \
$(LIBUSB_ROOT_ABS)
LOCAL_SHARED_LIBRARIES += libusb1.0
LOCAL_MODULE:= xusb
include $(BUILD_EXECUTABLE)
# hotplugtest
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
$(LIBUSB_ROOT_REL)/examples/hotplugtest.c
LOCAL_C_INCLUDES += \
$(LIBUSB_ROOT_ABS)
LOCAL_SHARED_LIBRARIES += libusb1.0
LOCAL_MODULE:= hotplugtest
include $(BUILD_EXECUTABLE)
# fxload
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
$(LIBUSB_ROOT_REL)/examples/fxload.c \
$(LIBUSB_ROOT_REL)/examples/ezusb.c
LOCAL_C_INCLUDES += \
$(LIBUSB_ROOT_ABS)
LOCAL_SHARED_LIBRARIES += libusb1.0
LOCAL_MODULE:= fxload
include $(BUILD_EXECUTABLE)
# sam3u_benchmake
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
$(LIBUSB_ROOT_REL)/examples/sam3u_benchmark.c
LOCAL_C_INCLUDES += \
$(LIBUSB_ROOT_ABS)
LOCAL_SHARED_LIBRARIES += libusb1.0
LOCAL_MODULE:= sam3u_benchmark
include $(BUILD_EXECUTABLE)
# dpfp
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
$(LIBUSB_ROOT_REL)/examples/dpfp.c
LOCAL_C_INCLUDES += \
$(LIBUSB_ROOT_ABS)
LOCAL_SHARED_LIBRARIES += libusb1.0
LOCAL_MODULE:= dpfp
include $(BUILD_EXECUTABLE)
# dpfp_threaded
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
$(LIBUSB_ROOT_REL)/examples/dpfp_threaded.c
LOCAL_C_INCLUDES += \
$(LIBUSB_ROOT_ABS)
LOCAL_SHARED_LIBRARIES += libusb1.0
LOCAL_MODULE:= dpfp_threaded
include $(BUILD_EXECUTABLE)

54
Externals/libusb/android/jni/libusb.mk vendored Normal file
View File

@ -0,0 +1,54 @@
# Android build config for libusb
# Copyright © 2012-2013 RealVNC Ltd. <toby.gray@realvnc.com>
#
# 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
#
LOCAL_PATH:= $(call my-dir)
LIBUSB_ROOT_REL:= ../..
LIBUSB_ROOT_ABS:= $(LOCAL_PATH)/../..
# libusb
include $(CLEAR_VARS)
LIBUSB_ROOT_REL:= ../..
LIBUSB_ROOT_ABS:= $(LOCAL_PATH)/../..
LOCAL_SRC_FILES := \
$(LIBUSB_ROOT_REL)/libusb/core.c \
$(LIBUSB_ROOT_REL)/libusb/descriptor.c \
$(LIBUSB_ROOT_REL)/libusb/hotplug.c \
$(LIBUSB_ROOT_REL)/libusb/io.c \
$(LIBUSB_ROOT_REL)/libusb/sync.c \
$(LIBUSB_ROOT_REL)/libusb/strerror.c \
$(LIBUSB_ROOT_REL)/libusb/os/linux_usbfs.c \
$(LIBUSB_ROOT_REL)/libusb/os/poll_posix.c \
$(LIBUSB_ROOT_REL)/libusb/os/threads_posix.c \
$(LIBUSB_ROOT_REL)/libusb/os/linux_netlink.c
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/.. \
$(LIBUSB_ROOT_ABS)/libusb \
$(LIBUSB_ROOT_ABS)/libusb/os
LOCAL_EXPORT_C_INCLUDES := \
$(LIBUSB_ROOT_ABS)/libusb
LOCAL_LDLIBS := -llog
LOCAL_MODULE := libusb1.0
include $(BUILD_SHARED_LIBRARY)

56
Externals/libusb/android/jni/tests.mk vendored Normal file
View File

@ -0,0 +1,56 @@
# Android build config for libusb tests
# Copyright © 2012-2013 RealVNC Ltd. <toby.gray@realvnc.com>
#
# 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
#
LOCAL_PATH:= $(call my-dir)
LIBUSB_ROOT_REL:= ../..
LIBUSB_ROOT_ABS:= $(LOCAL_PATH)/../..
# testlib
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
$(LIBUSB_ROOT_REL)/tests/testlib.c
LOCAL_C_INCLUDES += \
$(LIBUSB_ROOT_ABS)/tests
LOCAL_EXPORT_C_INCLUDES := \
$(LIBUSB_ROOT_ABS)/tests
LOCAL_MODULE := testlib
include $(BUILD_STATIC_LIBRARY)
# stress
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
$(LIBUSB_ROOT_REL)/tests/stress.c
LOCAL_C_INCLUDES += \
$(LIBUSB_ROOT_ABS)
LOCAL_SHARED_LIBRARIES += libusb1.0
LOCAL_STATIC_LIBRARIES += testlib
LOCAL_MODULE:= stress
include $(BUILD_EXECUTABLE)

41
Externals/libusb/appveyor.yml vendored Normal file
View File

@ -0,0 +1,41 @@
version: 1.0.{build}
configuration:
- Debug
- Release
platform:
- x64
- Win32
build:
project: msvc\libusb_2013.sln
parallel: true
verbosity: detailed
environment:
matrix:
- libusb_2015: msvc\libusb_2015.sln
libusb_2013: msvc\libusb_2013.sln
libusb_2012: msvc\libusb_2012.sln
libusb_2010: msvc\libusb_2010.sln
install:
- cmd: >-
rem Copying libusb to cygwin home directory
xcopy /S C:\projects\libusb C:\cygwin\home\appveyor\
rem Copying libusb to MinGW home directory
xcopy /S C:\projects\libusb C:\msys64\home\appveyor\
build_script:
- cmd: >-
msbuild %libusb_2015% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
msbuild %libusb_2013% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
msbuild %libusb_2012% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
msvc/appveyor.bat
appveyor_minGW.bat
appveyor_cygwin.bat

11
Externals/libusb/appveyor_cygwin.bat vendored Normal file
View File

@ -0,0 +1,11 @@
echo on
SetLocal EnableDelayedExpansion
if [%Configuration%] NEQ [Release] exit 0
if [%Platform%] NEQ [Win32] exit 0
C:\cygwin\bin\bash -e -l -c "./bootstrap.sh" || exit /B
C:\cygwin\bin\bash -e -l -c "mkdir build-Win32-cygwin" || exit /B
C:\cygwin\bin\bash -e -l -c "cd build-Win32-cygwin && ../configure --enable-examples-build --enable-tests-build" || exit /B
C:\cygwin\bin\bash -e -l -c "cd build-Win32-cygwin && make -j4" || exit /B
C:\cygwin\bin\bash -e -l -c "cd build-Win32-cygwin && make install" || exit /B

19
Externals/libusb/appveyor_minGW.bat vendored Normal file
View File

@ -0,0 +1,19 @@
echo on
SetLocal EnableDelayedExpansion
if [%Configuration%] NEQ [Release] exit 0
if [%Platform%] NEQ [x64] goto Win32
C:\msys64\usr\bin\bash -e -l -c "./bootstrap.sh" || exit /B
C:\msys64\usr\bin\bash -e -l -c "mkdir build-x64" || exit /B
C:\msys64\usr\bin\bash -e -l -c "cd build-x64 && ../configure --prefix=/mingw64 --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32" || exit /B
C:\msys64\usr\bin\bash -e -l -c "cd build-x64 && make -j4" || exit /B
C:\msys64\usr\bin\bash -e -l -c "cd build-x64 && make install" || exit /B
:Win32
if [%Platform%] NEQ [Win32] exit 0
C:\msys64\usr\bin\bash -e -l -c "./bootstrap.sh" || exit /B
C:\msys64\usr\bin\bash -e -l -c "mkdir build-Win32" || exit /B
C:\msys64\usr\bin\bash -e -l -c "cd build-Win32 && ../configure --prefix=/mingw32 --build=i686-w64-mingw32 --host=i686-w64-mingw32" || exit /B
C:\msys64\usr\bin\bash -e -l -c "cd build-Win32 && make -j4" || exit /B
C:\msys64\usr\bin\bash -e -l -c "cd build-Win32 && make install" || exit /B

8
Externals/libusb/autogen.sh vendored Executable file
View File

@ -0,0 +1,8 @@
#!/bin/sh
set -e
./bootstrap.sh
if test -z "$NOCONFIGURE"; then
exec ./configure --enable-examples-build --enable-tests-build "$@"
fi

6
Externals/libusb/bootstrap.sh vendored Executable file
View File

@ -0,0 +1,6 @@
#!/bin/sh
if ! test -d m4 ; then
mkdir m4
fi
autoreconf -ivf || exit 1

332
Externals/libusb/configure.ac vendored Normal file
View File

@ -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 <asm/types.h>
#endif
#include <sys/socket.h>
])
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 <poll.h>])
;;
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 <sys/timerfd.h>])
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

9
Externals/libusb/doc/Makefile.am vendored Normal file
View File

@ -0,0 +1,9 @@
EXTRA_DIST = doxygen.cfg.in
docs: doxygen.cfg
doxygen $^
docs-upload: docs
ln -s html api-1.0
scp -r api-1.0 pbatard@web.sourceforge.net:/home/project-web/libusb/htdocs
rm -f api-1.0

2334
Externals/libusb/doc/doxygen.cfg.in vendored Normal file

File diff suppressed because it is too large Load Diff

BIN
Externals/libusb/doc/libusb.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

19
Externals/libusb/examples/Makefile.am vendored Normal file
View File

@ -0,0 +1,19 @@
AM_CPPFLAGS = -I$(top_srcdir)/libusb
LDADD = ../libusb/libusb-1.0.la
noinst_PROGRAMS = listdevs xusb fxload hotplugtest testlibusb
if HAVE_SIGACTION
noinst_PROGRAMS += dpfp
if THREADS_POSIX
dpfp_threaded_CFLAGS = $(AM_CFLAGS)
noinst_PROGRAMS += dpfp_threaded
endif
sam3u_benchmark_SOURCES = sam3u_benchmark.c
noinst_PROGRAMS += sam3u_benchmark
endif
fxload_SOURCES = ezusb.c ezusb.h fxload.c
fxload_CFLAGS = $(THREAD_CFLAGS) $(AM_CFLAGS)

508
Externals/libusb/examples/dpfp.c vendored Normal file
View File

@ -0,0 +1,508 @@
/*
* libusb example program to manipulate U.are.U 4000B fingerprint scanner.
* Copyright © 2007 Daniel Drake <dsd@gentoo.org>
*
* Basic image capture program only, does not consider the powerup quirks or
* the fact that image encryption may be enabled. Not expected to work
* flawlessly all of the time.
*
* 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 <errno.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "libusb.h"
#define EP_INTR (1 | LIBUSB_ENDPOINT_IN)
#define EP_DATA (2 | LIBUSB_ENDPOINT_IN)
#define CTRL_IN (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN)
#define CTRL_OUT (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT)
#define USB_RQ 0x04
#define INTR_LENGTH 64
enum {
MODE_INIT = 0x00,
MODE_AWAIT_FINGER_ON = 0x10,
MODE_AWAIT_FINGER_OFF = 0x12,
MODE_CAPTURE = 0x20,
MODE_SHUT_UP = 0x30,
MODE_READY = 0x80,
};
static int next_state(void);
enum {
STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON = 1,
STATE_AWAIT_IRQ_FINGER_DETECTED,
STATE_AWAIT_MODE_CHANGE_CAPTURE,
STATE_AWAIT_IMAGE,
STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF,
STATE_AWAIT_IRQ_FINGER_REMOVED,
};
static int state = 0;
static struct libusb_device_handle *devh = NULL;
static unsigned char imgbuf[0x1b340];
static unsigned char irqbuf[INTR_LENGTH];
static struct libusb_transfer *img_transfer = NULL;
static struct libusb_transfer *irq_transfer = NULL;
static int img_idx = 0;
static int do_exit = 0;
static int find_dpfp_device(void)
{
devh = libusb_open_device_with_vid_pid(NULL, 0x05ba, 0x000a);
return devh ? 0 : -EIO;
}
static int print_f0_data(void)
{
unsigned char data[0x10];
int r;
unsigned int i;
r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0xf0, 0, data,
sizeof(data), 0);
if (r < 0) {
fprintf(stderr, "F0 error %d\n", r);
return r;
}
if ((unsigned int) r < sizeof(data)) {
fprintf(stderr, "short read (%d)\n", r);
return -1;
}
printf("F0 data:");
for (i = 0; i < sizeof(data); i++)
printf("%02x ", data[i]);
printf("\n");
return 0;
}
static int get_hwstat(unsigned char *status)
{
int r;
r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0x07, 0, status, 1, 0);
if (r < 0) {
fprintf(stderr, "read hwstat error %d\n", r);
return r;
}
if ((unsigned int) r < 1) {
fprintf(stderr, "short read (%d)\n", r);
return -1;
}
printf("hwstat reads %02x\n", *status);
return 0;
}
static int set_hwstat(unsigned char data)
{
int r;
printf("set hwstat to %02x\n", data);
r = libusb_control_transfer(devh, CTRL_OUT, USB_RQ, 0x07, 0, &data, 1, 0);
if (r < 0) {
fprintf(stderr, "set hwstat error %d\n", r);
return r;
}
if ((unsigned int) r < 1) {
fprintf(stderr, "short write (%d)", r);
return -1;
}
return 0;
}
static int set_mode(unsigned char data)
{
int r;
printf("set mode %02x\n", data);
r = libusb_control_transfer(devh, CTRL_OUT, USB_RQ, 0x4e, 0, &data, 1, 0);
if (r < 0) {
fprintf(stderr, "set mode error %d\n", r);
return r;
}
if ((unsigned int) r < 1) {
fprintf(stderr, "short write (%d)", r);
return -1;
}
return 0;
}
static void LIBUSB_CALL cb_mode_changed(struct libusb_transfer *transfer)
{
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fprintf(stderr, "mode change transfer not completed!\n");
do_exit = 2;
}
printf("async cb_mode_changed length=%d actual_length=%d\n",
transfer->length, transfer->actual_length);
if (next_state() < 0)
do_exit = 2;
}
static int set_mode_async(unsigned char data)
{
unsigned char *buf = (unsigned char*) malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
struct libusb_transfer *transfer;
if (!buf)
return -ENOMEM;
transfer = libusb_alloc_transfer(0);
if (!transfer) {
free(buf);
return -ENOMEM;
}
printf("async set mode %02x\n", data);
libusb_fill_control_setup(buf, CTRL_OUT, USB_RQ, 0x4e, 0, 1);
buf[LIBUSB_CONTROL_SETUP_SIZE] = data;
libusb_fill_control_transfer(transfer, devh, buf, cb_mode_changed, NULL,
1000);
transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK
| LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER;
return libusb_submit_transfer(transfer);
}
static int do_sync_intr(unsigned char *data)
{
int r;
int transferred;
r = libusb_interrupt_transfer(devh, EP_INTR, data, INTR_LENGTH,
&transferred, 1000);
if (r < 0) {
fprintf(stderr, "intr error %d\n", r);
return r;
}
if (transferred < INTR_LENGTH) {
fprintf(stderr, "short read (%d)\n", r);
return -1;
}
printf("recv interrupt %04x\n", *((uint16_t *) data));
return 0;
}
static int sync_intr(unsigned char type)
{
int r;
unsigned char data[INTR_LENGTH];
while (1) {
r = do_sync_intr(data);
if (r < 0)
return r;
if (data[0] == type)
return 0;
}
}
static int save_to_file(unsigned char *data)
{
FILE *fd;
char filename[64];
snprintf(filename, sizeof(filename), "finger%d.pgm", img_idx++);
fd = fopen(filename, "w");
if (!fd)
return -1;
fputs("P5 384 289 255 ", fd);
(void) fwrite(data + 64, 1, 384*289, fd);
fclose(fd);
printf("saved image to %s\n", filename);
return 0;
}
static int next_state(void)
{
int r = 0;
printf("old state: %d\n", state);
switch (state) {
case STATE_AWAIT_IRQ_FINGER_REMOVED:
state = STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON;
r = set_mode_async(MODE_AWAIT_FINGER_ON);
break;
case STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON:
state = STATE_AWAIT_IRQ_FINGER_DETECTED;
break;
case STATE_AWAIT_IRQ_FINGER_DETECTED:
state = STATE_AWAIT_MODE_CHANGE_CAPTURE;
r = set_mode_async(MODE_CAPTURE);
break;
case STATE_AWAIT_MODE_CHANGE_CAPTURE:
state = STATE_AWAIT_IMAGE;
break;
case STATE_AWAIT_IMAGE:
state = STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF;
r = set_mode_async(MODE_AWAIT_FINGER_OFF);
break;
case STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF:
state = STATE_AWAIT_IRQ_FINGER_REMOVED;
break;
default:
printf("unrecognised state %d\n", state);
}
if (r < 0) {
fprintf(stderr, "error detected changing state\n");
return r;
}
printf("new state: %d\n", state);
return 0;
}
static void LIBUSB_CALL cb_irq(struct libusb_transfer *transfer)
{
unsigned char irqtype = transfer->buffer[0];
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fprintf(stderr, "irq transfer status %d?\n", transfer->status);
do_exit = 2;
libusb_free_transfer(transfer);
irq_transfer = NULL;
return;
}
printf("IRQ callback %02x\n", irqtype);
switch (state) {
case STATE_AWAIT_IRQ_FINGER_DETECTED:
if (irqtype == 0x01) {
if (next_state() < 0) {
do_exit = 2;
return;
}
} else {
printf("finger-on-sensor detected in wrong state!\n");
}
break;
case STATE_AWAIT_IRQ_FINGER_REMOVED:
if (irqtype == 0x02) {
if (next_state() < 0) {
do_exit = 2;
return;
}
} else {
printf("finger-on-sensor detected in wrong state!\n");
}
break;
}
if (libusb_submit_transfer(irq_transfer) < 0)
do_exit = 2;
}
static void LIBUSB_CALL cb_img(struct libusb_transfer *transfer)
{
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fprintf(stderr, "img transfer status %d?\n", transfer->status);
do_exit = 2;
libusb_free_transfer(transfer);
img_transfer = NULL;
return;
}
printf("Image callback\n");
save_to_file(imgbuf);
if (next_state() < 0) {
do_exit = 2;
return;
}
if (libusb_submit_transfer(img_transfer) < 0)
do_exit = 2;
}
static int init_capture(void)
{
int r;
r = libusb_submit_transfer(irq_transfer);
if (r < 0)
return r;
r = libusb_submit_transfer(img_transfer);
if (r < 0) {
libusb_cancel_transfer(irq_transfer);
while (irq_transfer)
if (libusb_handle_events(NULL) < 0)
break;
return r;
}
/* start state machine */
state = STATE_AWAIT_IRQ_FINGER_REMOVED;
return next_state();
}
static int do_init(void)
{
unsigned char status;
int r;
r = get_hwstat(&status);
if (r < 0)
return r;
if (!(status & 0x80)) {
r = set_hwstat(status | 0x80);
if (r < 0)
return r;
r = get_hwstat(&status);
if (r < 0)
return r;
}
status &= ~0x80;
r = set_hwstat(status);
if (r < 0)
return r;
r = get_hwstat(&status);
if (r < 0)
return r;
r = sync_intr(0x56);
if (r < 0)
return r;
return 0;
}
static int alloc_transfers(void)
{
img_transfer = libusb_alloc_transfer(0);
if (!img_transfer)
return -ENOMEM;
irq_transfer = libusb_alloc_transfer(0);
if (!irq_transfer)
return -ENOMEM;
libusb_fill_bulk_transfer(img_transfer, devh, EP_DATA, imgbuf,
sizeof(imgbuf), cb_img, NULL, 0);
libusb_fill_interrupt_transfer(irq_transfer, devh, EP_INTR, irqbuf,
sizeof(irqbuf), cb_irq, NULL, 0);
return 0;
}
static void sighandler(int signum)
{
(void)signum;
do_exit = 1;
}
int main(void)
{
struct sigaction sigact;
int r;
r = libusb_init(NULL);
if (r < 0) {
fprintf(stderr, "failed to initialise libusb\n");
exit(1);
}
r = find_dpfp_device();
if (r < 0) {
fprintf(stderr, "Could not find/open device\n");
goto out;
}
r = libusb_claim_interface(devh, 0);
if (r < 0) {
fprintf(stderr, "usb_claim_interface error %d\n", r);
goto out;
}
printf("claimed interface\n");
r = print_f0_data();
if (r < 0)
goto out_release;
r = do_init();
if (r < 0)
goto out_deinit;
/* async from here onwards */
r = alloc_transfers();
if (r < 0)
goto out_deinit;
r = init_capture();
if (r < 0)
goto out_deinit;
sigact.sa_handler = sighandler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
sigaction(SIGINT, &sigact, NULL);
sigaction(SIGTERM, &sigact, NULL);
sigaction(SIGQUIT, &sigact, NULL);
while (!do_exit) {
r = libusb_handle_events(NULL);
if (r < 0)
goto out_deinit;
}
printf("shutting down...\n");
if (irq_transfer) {
r = libusb_cancel_transfer(irq_transfer);
if (r < 0)
goto out_deinit;
}
if (img_transfer) {
r = libusb_cancel_transfer(img_transfer);
if (r < 0)
goto out_deinit;
}
while (irq_transfer || img_transfer)
if (libusb_handle_events(NULL) < 0)
break;
if (do_exit == 1)
r = 0;
else
r = 1;
out_deinit:
libusb_free_transfer(img_transfer);
libusb_free_transfer(irq_transfer);
set_mode(0);
set_hwstat(0x80);
out_release:
libusb_release_interface(devh, 0);
out:
libusb_close(devh);
libusb_exit(NULL);
return r >= 0 ? r : -r;
}

View File

@ -0,0 +1,557 @@
/*
* libusb example program to manipulate U.are.U 4000B fingerprint scanner.
* Copyright © 2007 Daniel Drake <dsd@gentoo.org>
* Copyright © 2016 Nathan Hjelm <hjelmn@mac.com>
*
* Basic image capture program only, does not consider the powerup quirks or
* the fact that image encryption may be enabled. Not expected to work
* flawlessly all of the time.
*
* 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 <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include "libusb.h"
#define EP_INTR (1 | LIBUSB_ENDPOINT_IN)
#define EP_DATA (2 | LIBUSB_ENDPOINT_IN)
#define CTRL_IN (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN)
#define CTRL_OUT (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT)
#define USB_RQ 0x04
#define INTR_LENGTH 64
#define SEM_NAME "/org.libusb.example.dpfp_threaded"
enum {
MODE_INIT = 0x00,
MODE_AWAIT_FINGER_ON = 0x10,
MODE_AWAIT_FINGER_OFF = 0x12,
MODE_CAPTURE = 0x20,
MODE_SHUT_UP = 0x30,
MODE_READY = 0x80,
};
static int next_state(void);
enum {
STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON = 1,
STATE_AWAIT_IRQ_FINGER_DETECTED,
STATE_AWAIT_MODE_CHANGE_CAPTURE,
STATE_AWAIT_IMAGE,
STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF,
STATE_AWAIT_IRQ_FINGER_REMOVED,
};
static int state = 0;
static struct libusb_device_handle *devh = NULL;
static unsigned char imgbuf[0x1b340];
static unsigned char irqbuf[INTR_LENGTH];
static struct libusb_transfer *img_transfer = NULL;
static struct libusb_transfer *irq_transfer = NULL;
static int img_idx = 0;
static volatile sig_atomic_t do_exit = 0;
static pthread_t poll_thread;
static sem_t *exit_sem;
static void request_exit(sig_atomic_t code)
{
do_exit = code;
sem_post(exit_sem);
}
static void *poll_thread_main(void *arg)
{
int r = 0;
printf("poll thread running\n");
(void)arg;
while (!do_exit) {
struct timeval tv = { 1, 0 };
r = libusb_handle_events_timeout(NULL, &tv);
if (r < 0) {
request_exit(2);
break;
}
}
printf("poll thread shutting down\n");
return NULL;
}
static int find_dpfp_device(void)
{
devh = libusb_open_device_with_vid_pid(NULL, 0x05ba, 0x000a);
return devh ? 0 : -EIO;
}
static int print_f0_data(void)
{
unsigned char data[0x10];
int r;
unsigned int i;
r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0xf0, 0, data,
sizeof(data), 0);
if (r < 0) {
fprintf(stderr, "F0 error %d\n", r);
return r;
}
if ((unsigned int) r < sizeof(data)) {
fprintf(stderr, "short read (%d)\n", r);
return -1;
}
printf("F0 data:");
for (i = 0; i < sizeof(data); i++)
printf("%02x ", data[i]);
printf("\n");
return 0;
}
static int get_hwstat(unsigned char *status)
{
int r;
r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0x07, 0, status, 1, 0);
if (r < 0) {
fprintf(stderr, "read hwstat error %d\n", r);
return r;
}
if ((unsigned int) r < 1) {
fprintf(stderr, "short read (%d)\n", r);
return -1;
}
printf("hwstat reads %02x\n", *status);
return 0;
}
static int set_hwstat(unsigned char data)
{
int r;
printf("set hwstat to %02x\n", data);
r = libusb_control_transfer(devh, CTRL_OUT, USB_RQ, 0x07, 0, &data, 1, 0);
if (r < 0) {
fprintf(stderr, "set hwstat error %d\n", r);
return r;
}
if ((unsigned int) r < 1) {
fprintf(stderr, "short write (%d)", r);
return -1;
}
return 0;
}
static int set_mode(unsigned char data)
{
int r;
printf("set mode %02x\n", data);
r = libusb_control_transfer(devh, CTRL_OUT, USB_RQ, 0x4e, 0, &data, 1, 0);
if (r < 0) {
fprintf(stderr, "set mode error %d\n", r);
return r;
}
if ((unsigned int) r < 1) {
fprintf(stderr, "short write (%d)", r);
return -1;
}
return 0;
}
static void LIBUSB_CALL cb_mode_changed(struct libusb_transfer *transfer)
{
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fprintf(stderr, "mode change transfer not completed!\n");
request_exit(2);
}
printf("async cb_mode_changed length=%d actual_length=%d\n",
transfer->length, transfer->actual_length);
if (next_state() < 0)
request_exit(2);
}
static int set_mode_async(unsigned char data)
{
unsigned char *buf = (unsigned char*) malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
struct libusb_transfer *transfer;
if (!buf)
return -ENOMEM;
transfer = libusb_alloc_transfer(0);
if (!transfer) {
free(buf);
return -ENOMEM;
}
printf("async set mode %02x\n", data);
libusb_fill_control_setup(buf, CTRL_OUT, USB_RQ, 0x4e, 0, 1);
buf[LIBUSB_CONTROL_SETUP_SIZE] = data;
libusb_fill_control_transfer(transfer, devh, buf, cb_mode_changed, NULL,
1000);
transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK
| LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER;
return libusb_submit_transfer(transfer);
}
static int do_sync_intr(unsigned char *data)
{
int r;
int transferred;
r = libusb_interrupt_transfer(devh, EP_INTR, data, INTR_LENGTH,
&transferred, 1000);
if (r < 0) {
fprintf(stderr, "intr error %d\n", r);
return r;
}
if (transferred < INTR_LENGTH) {
fprintf(stderr, "short read (%d)\n", r);
return -1;
}
printf("recv interrupt %04x\n", *((uint16_t *) data));
return 0;
}
static int sync_intr(unsigned char type)
{
int r;
unsigned char data[INTR_LENGTH];
while (1) {
r = do_sync_intr(data);
if (r < 0)
return r;
if (data[0] == type)
return 0;
}
}
static int save_to_file(unsigned char *data)
{
FILE *fd;
char filename[64];
snprintf(filename, sizeof(filename), "finger%d.pgm", img_idx++);
fd = fopen(filename, "w");
if (!fd)
return -1;
fputs("P5 384 289 255 ", fd);
(void) fwrite(data + 64, 1, 384*289, fd);
fclose(fd);
printf("saved image to %s\n", filename);
return 0;
}
static int next_state(void)
{
int r = 0;
printf("old state: %d\n", state);
switch (state) {
case STATE_AWAIT_IRQ_FINGER_REMOVED:
state = STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON;
r = set_mode_async(MODE_AWAIT_FINGER_ON);
break;
case STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON:
state = STATE_AWAIT_IRQ_FINGER_DETECTED;
break;
case STATE_AWAIT_IRQ_FINGER_DETECTED:
state = STATE_AWAIT_MODE_CHANGE_CAPTURE;
r = set_mode_async(MODE_CAPTURE);
break;
case STATE_AWAIT_MODE_CHANGE_CAPTURE:
state = STATE_AWAIT_IMAGE;
break;
case STATE_AWAIT_IMAGE:
state = STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF;
r = set_mode_async(MODE_AWAIT_FINGER_OFF);
break;
case STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF:
state = STATE_AWAIT_IRQ_FINGER_REMOVED;
break;
default:
printf("unrecognised state %d\n", state);
}
if (r < 0) {
fprintf(stderr, "error detected changing state\n");
return r;
}
printf("new state: %d\n", state);
return 0;
}
static void LIBUSB_CALL cb_irq(struct libusb_transfer *transfer)
{
unsigned char irqtype = transfer->buffer[0];
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fprintf(stderr, "irq transfer status %d?\n", transfer->status);
irq_transfer = NULL;
request_exit(2);
return;
}
printf("IRQ callback %02x\n", irqtype);
switch (state) {
case STATE_AWAIT_IRQ_FINGER_DETECTED:
if (irqtype == 0x01) {
if (next_state() < 0) {
request_exit(2);
return;
}
} else {
printf("finger-on-sensor detected in wrong state!\n");
}
break;
case STATE_AWAIT_IRQ_FINGER_REMOVED:
if (irqtype == 0x02) {
if (next_state() < 0) {
request_exit(2);
return;
}
} else {
printf("finger-on-sensor detected in wrong state!\n");
}
break;
}
if (libusb_submit_transfer(irq_transfer) < 0)
request_exit(2);
}
static void LIBUSB_CALL cb_img(struct libusb_transfer *transfer)
{
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fprintf(stderr, "img transfer status %d?\n", transfer->status);
img_transfer = NULL;
request_exit(2);
return;
}
printf("Image callback\n");
save_to_file(imgbuf);
if (next_state() < 0) {
request_exit(2);
return;
}
if (libusb_submit_transfer(img_transfer) < 0)
request_exit(2);
}
static int init_capture(void)
{
int r;
r = libusb_submit_transfer(irq_transfer);
if (r < 0)
return r;
r = libusb_submit_transfer(img_transfer);
if (r < 0) {
libusb_cancel_transfer(irq_transfer);
while (irq_transfer)
if (libusb_handle_events(NULL) < 0)
break;
return r;
}
/* start state machine */
state = STATE_AWAIT_IRQ_FINGER_REMOVED;
return next_state();
}
static int do_init(void)
{
unsigned char status;
int r;
r = get_hwstat(&status);
if (r < 0)
return r;
if (!(status & 0x80)) {
r = set_hwstat(status | 0x80);
if (r < 0)
return r;
r = get_hwstat(&status);
if (r < 0)
return r;
}
status &= ~0x80;
r = set_hwstat(status);
if (r < 0)
return r;
r = get_hwstat(&status);
if (r < 0)
return r;
r = sync_intr(0x56);
if (r < 0)
return r;
return 0;
}
static int alloc_transfers(void)
{
img_transfer = libusb_alloc_transfer(0);
if (!img_transfer)
return -ENOMEM;
irq_transfer = libusb_alloc_transfer(0);
if (!irq_transfer)
return -ENOMEM;
libusb_fill_bulk_transfer(img_transfer, devh, EP_DATA, imgbuf,
sizeof(imgbuf), cb_img, NULL, 0);
libusb_fill_interrupt_transfer(irq_transfer, devh, EP_INTR, irqbuf,
sizeof(irqbuf), cb_irq, NULL, 0);
return 0;
}
static void sighandler(int signum)
{
(void)signum;
request_exit(1);
}
int main(void)
{
struct sigaction sigact;
int r = 1;
exit_sem = sem_open (SEM_NAME, O_CREAT, 0);
if (!exit_sem) {
fprintf(stderr, "failed to initialise semaphore error %d", errno);
exit(1);
}
/* only using this semaphore in this process so go ahead and unlink it now */
sem_unlink (SEM_NAME);
r = libusb_init(NULL);
if (r < 0) {
fprintf(stderr, "failed to initialise libusb\n");
exit(1);
}
r = find_dpfp_device();
if (r < 0) {
fprintf(stderr, "Could not find/open device\n");
goto out;
}
r = libusb_claim_interface(devh, 0);
if (r < 0) {
fprintf(stderr, "usb_claim_interface error %d %s\n", r, strerror(-r));
goto out;
}
printf("claimed interface\n");
r = print_f0_data();
if (r < 0)
goto out_release;
r = do_init();
if (r < 0)
goto out_deinit;
/* async from here onwards */
sigact.sa_handler = sighandler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
sigaction(SIGINT, &sigact, NULL);
sigaction(SIGTERM, &sigact, NULL);
sigaction(SIGQUIT, &sigact, NULL);
r = pthread_create(&poll_thread, NULL, poll_thread_main, NULL);
if (r)
goto out_deinit;
r = alloc_transfers();
if (r < 0) {
request_exit(1);
pthread_join(poll_thread, NULL);
goto out_deinit;
}
r = init_capture();
if (r < 0) {
request_exit(1);
pthread_join(poll_thread, NULL);
goto out_deinit;
}
while (!do_exit)
sem_wait(exit_sem);
printf("shutting down...\n");
pthread_join(poll_thread, NULL);
r = libusb_cancel_transfer(irq_transfer);
if (r < 0) {
request_exit(1);
goto out_deinit;
}
r = libusb_cancel_transfer(img_transfer);
if (r < 0) {
request_exit(1);
goto out_deinit;
}
while (img_transfer || irq_transfer)
if (libusb_handle_events(NULL) < 0)
break;
if (do_exit == 1)
r = 0;
else
r = 1;
out_deinit:
libusb_free_transfer(img_transfer);
libusb_free_transfer(irq_transfer);
set_mode(0);
set_hwstat(0x80);
out_release:
libusb_release_interface(devh, 0);
out:
libusb_close(devh);
libusb_exit(NULL);
return r >= 0 ? r : -r;
}

831
Externals/libusb/examples/ezusb.c vendored Normal file
View File

@ -0,0 +1,831 @@
/*
* Copyright © 2001 Stephen Williams (steve@icarus.com)
* Copyright © 2001-2002 David Brownell (dbrownell@users.sourceforge.net)
* Copyright © 2008 Roger Williams (rawqux@users.sourceforge.net)
* Copyright © 2012 Pete Batard (pete@akeo.ie)
* Copyright © 2013 Federico Manzan (f.manzan@gmail.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "libusb.h"
#include "ezusb.h"
extern void logerror(const char *format, ...)
__attribute__ ((format(printf, 1, 2)));
/*
* This file contains functions for uploading firmware into Cypress
* EZ-USB microcontrollers. These chips use control endpoint 0 and vendor
* specific commands to support writing into the on-chip SRAM. They also
* support writing into the CPUCS register, which is how we reset the
* processor after loading firmware (including the reset vector).
*
* These Cypress devices are 8-bit 8051 based microcontrollers with
* special support for USB I/O. They come in several packages, and
* some can be set up with external memory when device costs allow.
* Note that the design was originally by AnchorChips, so you may find
* references to that vendor (which was later merged into Cypress).
* The Cypress FX parts are largely compatible with the Anchorhip ones.
*/
int verbose = 1;
/*
* return true if [addr,addr+len] includes external RAM
* for Anchorchips EZ-USB or Cypress EZ-USB FX
*/
static bool fx_is_external(uint32_t addr, size_t len)
{
/* with 8KB RAM, 0x0000-0x1b3f can be written
* we can't tell if it's a 4KB device here
*/
if (addr <= 0x1b3f)
return ((addr + len) > 0x1b40);
/* there may be more RAM; unclear if we can write it.
* some bulk buffers may be unused, 0x1b3f-0x1f3f
* firmware can set ISODISAB for 2KB at 0x2000-0x27ff
*/
return true;
}
/*
* return true if [addr,addr+len] includes external RAM
* for Cypress EZ-USB FX2
*/
static bool fx2_is_external(uint32_t addr, size_t len)
{
/* 1st 8KB for data/code, 0x0000-0x1fff */
if (addr <= 0x1fff)
return ((addr + len) > 0x2000);
/* and 512 for data, 0xe000-0xe1ff */
else if (addr >= 0xe000 && addr <= 0xe1ff)
return ((addr + len) > 0xe200);
/* otherwise, it's certainly external */
else
return true;
}
/*
* return true if [addr,addr+len] includes external RAM
* for Cypress EZ-USB FX2LP
*/
static bool fx2lp_is_external(uint32_t addr, size_t len)
{
/* 1st 16KB for data/code, 0x0000-0x3fff */
if (addr <= 0x3fff)
return ((addr + len) > 0x4000);
/* and 512 for data, 0xe000-0xe1ff */
else if (addr >= 0xe000 && addr <= 0xe1ff)
return ((addr + len) > 0xe200);
/* otherwise, it's certainly external */
else
return true;
}
/*****************************************************************************/
/*
* These are the requests (bRequest) that the bootstrap loader is expected
* to recognize. The codes are reserved by Cypress, and these values match
* what EZ-USB hardware, or "Vend_Ax" firmware (2nd stage loader) uses.
* Cypress' "a3load" is nice because it supports both FX and FX2, although
* it doesn't have the EEPROM support (subset of "Vend_Ax").
*/
#define RW_INTERNAL 0xA0 /* hardware implements this one */
#define RW_MEMORY 0xA3
/*
* Issues the specified vendor-specific write request.
*/
static int ezusb_write(libusb_device_handle *device, const char *label,
uint8_t opcode, uint32_t addr, const unsigned char *data, size_t len)
{
int status;
if (verbose > 1)
logerror("%s, addr 0x%08x len %4u (0x%04x)\n", label, addr, (unsigned)len, (unsigned)len);
status = libusb_control_transfer(device,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
opcode, addr & 0xFFFF, addr >> 16,
(unsigned char*)data, (uint16_t)len, 1000);
if (status != (signed)len) {
if (status < 0)
logerror("%s: %s\n", label, libusb_error_name(status));
else
logerror("%s ==> %d\n", label, status);
}
return (status < 0) ? -EIO : 0;
}
/*
* Issues the specified vendor-specific read request.
*/
static int ezusb_read(libusb_device_handle *device, const char *label,
uint8_t opcode, uint32_t addr, const unsigned char *data, size_t len)
{
int status;
if (verbose > 1)
logerror("%s, addr 0x%08x len %4u (0x%04x)\n", label, addr, (unsigned)len, (unsigned)len);
status = libusb_control_transfer(device,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
opcode, addr & 0xFFFF, addr >> 16,
(unsigned char*)data, (uint16_t)len, 1000);
if (status != (signed)len) {
if (status < 0)
logerror("%s: %s\n", label, libusb_error_name(status));
else
logerror("%s ==> %d\n", label, status);
}
return (status < 0) ? -EIO : 0;
}
/*
* Modifies the CPUCS register to stop or reset the CPU.
* Returns false on error.
*/
static bool ezusb_cpucs(libusb_device_handle *device, uint32_t addr, bool doRun)
{
int status;
uint8_t data = doRun ? 0x00 : 0x01;
if (verbose)
logerror("%s\n", data ? "stop CPU" : "reset CPU");
status = libusb_control_transfer(device,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
RW_INTERNAL, addr & 0xFFFF, addr >> 16,
&data, 1, 1000);
if ((status != 1) &&
/* We may get an I/O error from libusb as the device disappears */
((!doRun) || (status != LIBUSB_ERROR_IO)))
{
const char *mesg = "can't modify CPUCS";
if (status < 0)
logerror("%s: %s\n", mesg, libusb_error_name(status));
else
logerror("%s\n", mesg);
return false;
} else
return true;
}
/*
* Send an FX3 jumpt to address command
* Returns false on error.
*/
static bool ezusb_fx3_jump(libusb_device_handle *device, uint32_t addr)
{
int status;
if (verbose)
logerror("transfer execution to Program Entry at 0x%08x\n", addr);
status = libusb_control_transfer(device,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
RW_INTERNAL, addr & 0xFFFF, addr >> 16,
NULL, 0, 1000);
/* We may get an I/O error from libusb as the device disappears */
if ((status != 0) && (status != LIBUSB_ERROR_IO))
{
const char *mesg = "failed to send jump command";
if (status < 0)
logerror("%s: %s\n", mesg, libusb_error_name(status));
else
logerror("%s\n", mesg);
return false;
} else
return true;
}
/*****************************************************************************/
/*
* Parse an Intel HEX image file and invoke the poke() function on the
* various segments to implement policies such as writing to RAM (with
* a one or two stage loader setup, depending on the firmware) or to
* EEPROM (two stages required).
*
* image - the hex image file
* context - for use by poke()
* is_external - if non-null, used to check which segments go into
* external memory (writable only by software loader)
* poke - called with each memory segment; errors indicated
* by returning negative values.
*
* Caller is responsible for halting CPU as needed, such as when
* overwriting a second stage loader.
*/
static int parse_ihex(FILE *image, void *context,
bool (*is_external)(uint32_t addr, size_t len),
int (*poke) (void *context, uint32_t addr, bool external,
const unsigned char *data, size_t len))
{
unsigned char data[1023];
uint32_t data_addr = 0;
size_t data_len = 0;
int rc;
int first_line = 1;
bool external = false;
/* Read the input file as an IHEX file, and report the memory segments
* as we go. Each line holds a max of 16 bytes, but uploading is
* faster (and EEPROM space smaller) if we merge those lines into larger
* chunks. Most hex files keep memory segments together, which makes
* such merging all but free. (But it may still be worth sorting the
* hex files to make up for undesirable behavior from tools.)
*
* Note that EEPROM segments max out at 1023 bytes; the upload protocol
* allows segments of up to 64 KBytes (more than a loader could handle).
*/
for (;;) {
char buf[512], *cp;
char tmp, type;
size_t len;
unsigned idx, off;
cp = fgets(buf, sizeof(buf), image);
if (cp == NULL) {
logerror("EOF without EOF record!\n");
break;
}
/* EXTENSION: "# comment-till-end-of-line", for copyrights etc */
if (buf[0] == '#')
continue;
if (buf[0] != ':') {
logerror("not an ihex record: %s", buf);
return -2;
}
/* ignore any newline */
cp = strchr(buf, '\n');
if (cp)
*cp = 0;
if (verbose >= 3)
logerror("** LINE: %s\n", buf);
/* Read the length field (up to 16 bytes) */
tmp = buf[3];
buf[3] = 0;
len = strtoul(buf+1, NULL, 16);
buf[3] = tmp;
/* Read the target offset (address up to 64KB) */
tmp = buf[7];
buf[7] = 0;
off = (unsigned int)strtoul(buf+3, NULL, 16);
buf[7] = tmp;
/* Initialize data_addr */
if (first_line) {
data_addr = off;
first_line = 0;
}
/* Read the record type */
tmp = buf[9];
buf[9] = 0;
type = (char)strtoul(buf+7, NULL, 16);
buf[9] = tmp;
/* If this is an EOF record, then make it so. */
if (type == 1) {
if (verbose >= 2)
logerror("EOF on hexfile\n");
break;
}
if (type != 0) {
logerror("unsupported record type: %u\n", type);
return -3;
}
if ((len * 2) + 11 > strlen(buf)) {
logerror("record too short?\n");
return -4;
}
/* FIXME check for _physically_ contiguous not just virtually
* e.g. on FX2 0x1f00-0x2100 includes both on-chip and external
* memory so it's not really contiguous */
/* flush the saved data if it's not contiguous,
* or when we've buffered as much as we can.
*/
if (data_len != 0
&& (off != (data_addr + data_len)
/* || !merge */
|| (data_len + len) > sizeof(data))) {
if (is_external)
external = is_external(data_addr, data_len);
rc = poke(context, data_addr, external, data, data_len);
if (rc < 0)
return -1;
data_addr = off;
data_len = 0;
}
/* append to saved data, flush later */
for (idx = 0, cp = buf+9 ; idx < len ; idx += 1, cp += 2) {
tmp = cp[2];
cp[2] = 0;
data[data_len + idx] = (uint8_t)strtoul(cp, NULL, 16);
cp[2] = tmp;
}
data_len += len;
}
/* flush any data remaining */
if (data_len != 0) {
if (is_external)
external = is_external(data_addr, data_len);
rc = poke(context, data_addr, external, data, data_len);
if (rc < 0)
return -1;
}
return 0;
}
/*
* Parse a binary image file and write it as is to the target.
* Applies to Cypress BIX images for RAM or Cypress IIC images
* for EEPROM.
*
* image - the BIX image file
* context - for use by poke()
* is_external - if non-null, used to check which segments go into
* external memory (writable only by software loader)
* poke - called with each memory segment; errors indicated
* by returning negative values.
*
* Caller is responsible for halting CPU as needed, such as when
* overwriting a second stage loader.
*/
static int parse_bin(FILE *image, void *context,
bool (*is_external)(uint32_t addr, size_t len), int (*poke)(void *context,
uint32_t addr, bool external, const unsigned char *data, size_t len))
{
unsigned char data[4096];
uint32_t data_addr = 0;
size_t data_len = 0;
int rc;
bool external = false;
for (;;) {
data_len = fread(data, 1, 4096, image);
if (data_len == 0)
break;
if (is_external)
external = is_external(data_addr, data_len);
rc = poke(context, data_addr, external, data, data_len);
if (rc < 0)
return -1;
data_addr += (uint32_t)data_len;
}
return feof(image)?0:-1;
}
/*
* Parse a Cypress IIC image file and invoke the poke() function on the
* various segments for writing to RAM
*
* image - the IIC image file
* context - for use by poke()
* is_external - if non-null, used to check which segments go into
* external memory (writable only by software loader)
* poke - called with each memory segment; errors indicated
* by returning negative values.
*
* Caller is responsible for halting CPU as needed, such as when
* overwriting a second stage loader.
*/
static int parse_iic(FILE *image, void *context,
bool (*is_external)(uint32_t addr, size_t len),
int (*poke)(void *context, uint32_t addr, bool external, const unsigned char *data, size_t len))
{
unsigned char data[4096];
uint32_t data_addr = 0;
size_t data_len = 0, read_len;
uint8_t block_header[4];
int rc;
bool external = false;
long file_size, initial_pos;
initial_pos = ftell(image);
if (initial_pos < 0)
return -1;
if (fseek(image, 0L, SEEK_END) != 0)
return -1;
file_size = ftell(image);
if (fseek(image, initial_pos, SEEK_SET) != 0)
return -1;
for (;;) {
/* Ignore the trailing reset IIC data (5 bytes) */
if (ftell(image) >= (file_size - 5))
break;
if (fread(&block_header, 1, sizeof(block_header), image) != 4) {
logerror("unable to read IIC block header\n");
return -1;
}
data_len = (block_header[0] << 8) + block_header[1];
data_addr = (block_header[2] << 8) + block_header[3];
if (data_len > sizeof(data)) {
/* If this is ever reported as an error, switch to using malloc/realloc */
logerror("IIC data block too small - please report this error to libusb.info\n");
return -1;
}
read_len = fread(data, 1, data_len, image);
if (read_len != data_len) {
logerror("read error\n");
return -1;
}
if (is_external)
external = is_external(data_addr, data_len);
rc = poke(context, data_addr, external, data, data_len);
if (rc < 0)
return -1;
}
return 0;
}
/* the parse call will be selected according to the image type */
static int (*parse[IMG_TYPE_MAX])(FILE *image, void *context, bool (*is_external)(uint32_t addr, size_t len),
int (*poke)(void *context, uint32_t addr, bool external, const unsigned char *data, size_t len))
= { parse_ihex, parse_iic, parse_bin };
/*****************************************************************************/
/*
* For writing to RAM using a first (hardware) or second (software)
* stage loader and 0xA0 or 0xA3 vendor requests
*/
typedef enum {
_undef = 0,
internal_only, /* hardware first-stage loader */
skip_internal, /* first phase, second-stage loader */
skip_external /* second phase, second-stage loader */
} ram_mode;
struct ram_poke_context {
libusb_device_handle *device;
ram_mode mode;
size_t total, count;
};
#define RETRY_LIMIT 5
static int ram_poke(void *context, uint32_t addr, bool external,
const unsigned char *data, size_t len)
{
struct ram_poke_context *ctx = (struct ram_poke_context*)context;
int rc;
unsigned retry = 0;
switch (ctx->mode) {
case internal_only: /* CPU should be stopped */
if (external) {
logerror("can't write %u bytes external memory at 0x%08x\n",
(unsigned)len, addr);
return -EINVAL;
}
break;
case skip_internal: /* CPU must be running */
if (!external) {
if (verbose >= 2) {
logerror("SKIP on-chip RAM, %u bytes at 0x%08x\n",
(unsigned)len, addr);
}
return 0;
}
break;
case skip_external: /* CPU should be stopped */
if (external) {
if (verbose >= 2) {
logerror("SKIP external RAM, %u bytes at 0x%08x\n",
(unsigned)len, addr);
}
return 0;
}
break;
case _undef:
default:
logerror("bug\n");
return -EDOM;
}
ctx->total += len;
ctx->count++;
/* Retry this till we get a real error. Control messages are not
* NAKed (just dropped) so time out means is a real problem.
*/
while ((rc = ezusb_write(ctx->device,
external ? "write external" : "write on-chip",
external ? RW_MEMORY : RW_INTERNAL,
addr, data, len)) < 0
&& retry < RETRY_LIMIT) {
if (rc != LIBUSB_ERROR_TIMEOUT)
break;
retry += 1;
}
return rc;
}
/*
* Load a Cypress Image file into target RAM.
* See http://www.cypress.com/?docID=41351 (AN76405 PDF) for more info.
*/
static int fx3_load_ram(libusb_device_handle *device, const char *path)
{
uint32_t dCheckSum, dExpectedCheckSum, dAddress, i, dLen, dLength;
uint32_t* dImageBuf;
unsigned char *bBuf, hBuf[4], blBuf[4], rBuf[4096];
FILE *image;
int ret = 0;
image = fopen(path, "rb");
if (image == NULL) {
logerror("unable to open '%s' for input\n", path);
return -2;
} else if (verbose)
logerror("open firmware image %s for RAM upload\n", path);
// Read header
if (fread(hBuf, sizeof(char), sizeof(hBuf), image) != sizeof(hBuf)) {
logerror("could not read image header");
ret = -3;
goto exit;
}
// check "CY" signature byte and format
if ((hBuf[0] != 'C') || (hBuf[1] != 'Y')) {
logerror("image doesn't have a CYpress signature\n");
ret = -3;
goto exit;
}
// Check bImageType
switch(hBuf[3]) {
case 0xB0:
if (verbose)
logerror("normal FW binary %s image with checksum\n", (hBuf[2]&0x01)?"data":"executable");
break;
case 0xB1:
logerror("security binary image is not currently supported\n");
ret = -3;
goto exit;
case 0xB2:
logerror("VID:PID image is not currently supported\n");
ret = -3;
goto exit;
default:
logerror("invalid image type 0x%02X\n", hBuf[3]);
ret = -3;
goto exit;
}
// Read the bootloader version
if (verbose) {
if ((ezusb_read(device, "read bootloader version", RW_INTERNAL, 0xFFFF0020, blBuf, 4) < 0)) {
logerror("Could not read bootloader version\n");
ret = -8;
goto exit;
}
logerror("FX3 bootloader version: 0x%02X%02X%02X%02X\n", blBuf[3], blBuf[2], blBuf[1], blBuf[0]);
}
dCheckSum = 0;
if (verbose)
logerror("writing image...\n");
while (1) {
if ((fread(&dLength, sizeof(uint32_t), 1, image) != 1) || // read dLength
(fread(&dAddress, sizeof(uint32_t), 1, image) != 1)) { // read dAddress
logerror("could not read image");
ret = -3;
goto exit;
}
if (dLength == 0)
break; // done
// coverity[tainted_data]
dImageBuf = (uint32_t*)calloc(dLength, sizeof(uint32_t));
if (dImageBuf == NULL) {
logerror("could not allocate buffer for image chunk\n");
ret = -4;
goto exit;
}
// read sections
if (fread(dImageBuf, sizeof(uint32_t), dLength, image) != dLength) {
logerror("could not read image");
free(dImageBuf);
ret = -3;
goto exit;
}
for (i = 0; i < dLength; i++)
dCheckSum += dImageBuf[i];
dLength <<= 2; // convert to Byte length
bBuf = (unsigned char*) dImageBuf;
while (dLength > 0) {
dLen = 4096; // 4K max
if (dLen > dLength)
dLen = dLength;
if ((ezusb_write(device, "write firmware", RW_INTERNAL, dAddress, bBuf, dLen) < 0) ||
(ezusb_read(device, "read firmware", RW_INTERNAL, dAddress, rBuf, dLen) < 0)) {
logerror("R/W error\n");
free(dImageBuf);
ret = -5;
goto exit;
}
// Verify data: rBuf with bBuf
for (i = 0; i < dLen; i++) {
if (rBuf[i] != bBuf[i]) {
logerror("verify error");
free(dImageBuf);
ret = -6;
goto exit;
}
}
dLength -= dLen;
bBuf += dLen;
dAddress += dLen;
}
free(dImageBuf);
}
// read pre-computed checksum data
if ((fread(&dExpectedCheckSum, sizeof(uint32_t), 1, image) != 1) ||
(dCheckSum != dExpectedCheckSum)) {
logerror("checksum error\n");
ret = -7;
goto exit;
}
// transfer execution to Program Entry
if (!ezusb_fx3_jump(device, dAddress)) {
ret = -6;
}
exit:
fclose(image);
return ret;
}
/*
* Load a firmware file into target RAM. device is the open libusb
* device, and the path is the name of the source file. Open the file,
* parse the bytes, and write them in one or two phases.
*
* If stage == 0, this uses the first stage loader, built into EZ-USB
* hardware but limited to writing on-chip memory or CPUCS. Everything
* is written during one stage, unless there's an error such as the image
* holding data that needs to be written to external memory.
*
* Otherwise, things are written in two stages. First the external
* memory is written, expecting a second stage loader to have already
* been loaded. Then file is re-parsed and on-chip memory is written.
*/
int ezusb_load_ram(libusb_device_handle *device, const char *path, int fx_type, int img_type, int stage)
{
FILE *image;
uint32_t cpucs_addr;
bool (*is_external)(uint32_t off, size_t len);
struct ram_poke_context ctx;
int status;
uint8_t iic_header[8] = { 0 };
int ret = 0;
if (fx_type == FX_TYPE_FX3)
return fx3_load_ram(device, path);
image = fopen(path, "rb");
if (image == NULL) {
logerror("%s: unable to open for input.\n", path);
return -2;
} else if (verbose > 1)
logerror("open firmware image %s for RAM upload\n", path);
if (img_type == IMG_TYPE_IIC) {
if ( (fread(iic_header, 1, sizeof(iic_header), image) != sizeof(iic_header))
|| (((fx_type == FX_TYPE_FX2LP) || (fx_type == FX_TYPE_FX2)) && (iic_header[0] != 0xC2))
|| ((fx_type == FX_TYPE_AN21) && (iic_header[0] != 0xB2))
|| ((fx_type == FX_TYPE_FX1) && (iic_header[0] != 0xB6)) ) {
logerror("IIC image does not contain executable code - cannot load to RAM.\n");
ret = -1;
goto exit;
}
}
/* EZ-USB original/FX and FX2 devices differ, apart from the 8051 core */
switch(fx_type) {
case FX_TYPE_FX2LP:
cpucs_addr = 0xe600;
is_external = fx2lp_is_external;
break;
case FX_TYPE_FX2:
cpucs_addr = 0xe600;
is_external = fx2_is_external;
break;
default:
cpucs_addr = 0x7f92;
is_external = fx_is_external;
break;
}
/* use only first stage loader? */
if (stage == 0) {
ctx.mode = internal_only;
/* if required, halt the CPU while we overwrite its code/data */
if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, false))
{
ret = -1;
goto exit;
}
/* 2nd stage, first part? loader was already uploaded */
} else {
ctx.mode = skip_internal;
/* let CPU run; overwrite the 2nd stage loader later */
if (verbose)
logerror("2nd stage: write external memory\n");
}
/* scan the image, first (maybe only) time */
ctx.device = device;
ctx.total = ctx.count = 0;
status = parse[img_type](image, &ctx, is_external, ram_poke);
if (status < 0) {
logerror("unable to upload %s\n", path);
ret = status;
goto exit;
}
/* second part of 2nd stage: rescan */
// TODO: what should we do for non HEX images there?
if (stage) {
ctx.mode = skip_external;
/* if needed, halt the CPU while we overwrite the 1st stage loader */
if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, false))
{
ret = -1;
goto exit;
}
/* at least write the interrupt vectors (at 0x0000) for reset! */
rewind(image);
if (verbose)
logerror("2nd stage: write on-chip memory\n");
status = parse_ihex(image, &ctx, is_external, ram_poke);
if (status < 0) {
logerror("unable to completely upload %s\n", path);
ret = status;
goto exit;
}
}
if (verbose && (ctx.count != 0)) {
logerror("... WROTE: %d bytes, %d segments, avg %d\n",
(int)ctx.total, (int)ctx.count, (int)(ctx.total/ctx.count));
}
/* if required, reset the CPU so it runs what we just uploaded */
if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, true))
ret = -1;
exit:
fclose(image);
return ret;
}

120
Externals/libusb/examples/ezusb.h vendored Normal file
View File

@ -0,0 +1,120 @@
#ifndef ezusb_H
#define ezusb_H
/*
* Copyright © 2001 Stephen Williams (steve@icarus.com)
* Copyright © 2002 David Brownell (dbrownell@users.sourceforge.net)
* Copyright © 2013 Federico Manzan (f.manzan@gmail.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(_MSC_VER)
#include <stdbool.h>
#else
#define __attribute__(x)
#if !defined(bool)
#define bool int
#endif
#if !defined(true)
#define true (1 == 1)
#endif
#if !defined(false)
#define false (!true)
#endif
#if defined(_PREFAST_)
#pragma warning(disable:28193)
#endif
#endif
#define FX_TYPE_UNDEFINED -1
#define FX_TYPE_AN21 0 /* Original AnchorChips parts */
#define FX_TYPE_FX1 1 /* Updated Cypress versions */
#define FX_TYPE_FX2 2 /* USB 2.0 versions */
#define FX_TYPE_FX2LP 3 /* Updated FX2 */
#define FX_TYPE_FX3 4 /* USB 3.0 versions */
#define FX_TYPE_MAX 5
#define FX_TYPE_NAMES { "an21", "fx", "fx2", "fx2lp", "fx3" }
#define IMG_TYPE_UNDEFINED -1
#define IMG_TYPE_HEX 0 /* Intel HEX */
#define IMG_TYPE_IIC 1 /* Cypress 8051 IIC */
#define IMG_TYPE_BIX 2 /* Cypress 8051 BIX */
#define IMG_TYPE_IMG 3 /* Cypress IMG format */
#define IMG_TYPE_MAX 4
#define IMG_TYPE_NAMES { "Intel HEX", "Cypress 8051 IIC", "Cypress 8051 BIX", "Cypress IMG format" }
#ifdef __cplusplus
extern "C" {
#endif
/*
* Automatically identified devices (VID, PID, type, designation).
* TODO: Could use some validation. Also where's the FX2?
*/
typedef struct {
uint16_t vid;
uint16_t pid;
int type;
const char* designation;
} fx_known_device;
#define FX_KNOWN_DEVICES { \
{ 0x0547, 0x2122, FX_TYPE_AN21, "Cypress EZ-USB (2122S)" },\
{ 0x0547, 0x2125, FX_TYPE_AN21, "Cypress EZ-USB (2121S/2125S)" },\
{ 0x0547, 0x2126, FX_TYPE_AN21, "Cypress EZ-USB (2126S)" },\
{ 0x0547, 0x2131, FX_TYPE_AN21, "Cypress EZ-USB (2131Q/2131S/2135S)" },\
{ 0x0547, 0x2136, FX_TYPE_AN21, "Cypress EZ-USB (2136S)" },\
{ 0x0547, 0x2225, FX_TYPE_AN21, "Cypress EZ-USB (2225)" },\
{ 0x0547, 0x2226, FX_TYPE_AN21, "Cypress EZ-USB (2226)" },\
{ 0x0547, 0x2235, FX_TYPE_AN21, "Cypress EZ-USB (2235)" },\
{ 0x0547, 0x2236, FX_TYPE_AN21, "Cypress EZ-USB (2236)" },\
{ 0x04b4, 0x6473, FX_TYPE_FX1, "Cypress EZ-USB FX1" },\
{ 0x04b4, 0x8613, FX_TYPE_FX2LP, "Cypress EZ-USB FX2LP (68013A/68014A/68015A/68016A)" }, \
{ 0x04b4, 0x00f3, FX_TYPE_FX3, "Cypress FX3" },\
}
/*
* This function uploads the firmware from the given file into RAM.
* Stage == 0 means this is a single stage load (or the first of
* two stages). Otherwise it's the second of two stages; the
* caller having preloaded the second stage loader.
*
* The target processor is reset at the end of this upload.
*/
extern int ezusb_load_ram(libusb_device_handle *device,
const char *path, int fx_type, int img_type, int stage);
/*
* This function uploads the firmware from the given file into EEPROM.
* This uses the right CPUCS address to terminate the EEPROM load with
* a reset command where FX parts behave differently than FX2 ones.
* The configuration byte is as provided here (zero for an21xx parts)
* and the EEPROM type is set so that the microcontroller will boot
* from it.
*
* The caller must have preloaded a second stage loader that knows
* how to respond to the EEPROM write request.
*/
extern int ezusb_load_eeprom(libusb_device_handle *device,
const char *path, int fx_type, int img_type, int config);
/* Verbosity level (default 1). Can be increased or decreased with options v/q */
extern int verbose;
#ifdef __cplusplus
}
#endif
#endif

309
Externals/libusb/examples/fxload.c vendored Normal file
View File

@ -0,0 +1,309 @@
/*
* Copyright © 2001 Stephen Williams (steve@icarus.com)
* Copyright © 2001-2002 David Brownell (dbrownell@users.sourceforge.net)
* Copyright © 2008 Roger Williams (rawqux@users.sourceforge.net)
* Copyright © 2012 Pete Batard (pete@akeo.ie)
* Copyright © 2013 Federico Manzan (f.manzan@gmail.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <sys/types.h>
#include <getopt.h>
#include "libusb.h"
#include "ezusb.h"
#if !defined(_WIN32) || defined(__CYGWIN__ )
#include <syslog.h>
static bool dosyslog = false;
#include <strings.h>
#define _stricmp strcasecmp
#endif
#ifndef FXLOAD_VERSION
#define FXLOAD_VERSION (__DATE__ " (libusb)")
#endif
#ifndef ARRAYSIZE
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
void logerror(const char *format, ...)
__attribute__ ((format (__printf__, 1, 2)));
void logerror(const char *format, ...)
{
va_list ap;
va_start(ap, format);
#if !defined(_WIN32) || defined(__CYGWIN__ )
if (dosyslog)
vsyslog(LOG_ERR, format, ap);
else
#endif
vfprintf(stderr, format, ap);
va_end(ap);
}
static int print_usage(int error_code) {
fprintf(stderr, "\nUsage: fxload [-v] [-V] [-t type] [-d vid:pid] [-p bus,addr] [-s loader] -i firmware\n");
fprintf(stderr, " -i <path> -- Firmware to upload\n");
fprintf(stderr, " -s <path> -- Second stage loader\n");
fprintf(stderr, " -t <type> -- Target type: an21, fx, fx2, fx2lp, fx3\n");
fprintf(stderr, " -d <vid:pid> -- Target device, as an USB VID:PID\n");
fprintf(stderr, " -p <bus,addr> -- Target device, as a libusb bus number and device address path\n");
fprintf(stderr, " -v -- Increase verbosity\n");
fprintf(stderr, " -q -- Decrease verbosity (silent mode)\n");
fprintf(stderr, " -V -- Print program version\n");
return error_code;
}
#define FIRMWARE 0
#define LOADER 1
int main(int argc, char*argv[])
{
fx_known_device known_device[] = FX_KNOWN_DEVICES;
const char *path[] = { NULL, NULL };
const char *device_id = NULL;
const char *device_path = getenv("DEVICE");
const char *type = NULL;
const char *fx_name[FX_TYPE_MAX] = FX_TYPE_NAMES;
const char *ext, *img_name[] = IMG_TYPE_NAMES;
int fx_type = FX_TYPE_UNDEFINED, img_type[ARRAYSIZE(path)];
int opt, status;
unsigned int i, j;
unsigned vid = 0, pid = 0;
unsigned busnum = 0, devaddr = 0, _busnum, _devaddr;
libusb_device *dev, **devs;
libusb_device_handle *device = NULL;
struct libusb_device_descriptor desc;
while ((opt = getopt(argc, argv, "qvV?hd:p:i:I:s:S:t:")) != EOF)
switch (opt) {
case 'd':
device_id = optarg;
if (sscanf(device_id, "%x:%x" , &vid, &pid) != 2 ) {
fputs ("please specify VID & PID as \"vid:pid\" in hexadecimal format\n", stderr);
return -1;
}
break;
case 'p':
device_path = optarg;
if (sscanf(device_path, "%u,%u", &busnum, &devaddr) != 2 ) {
fputs ("please specify bus number & device number as \"bus,dev\" in decimal format\n", stderr);
return -1;
}
break;
case 'i':
case 'I':
path[FIRMWARE] = optarg;
break;
case 's':
case 'S':
path[LOADER] = optarg;
break;
case 'V':
puts(FXLOAD_VERSION);
return 0;
case 't':
type = optarg;
break;
case 'v':
verbose++;
break;
case 'q':
verbose--;
break;
case '?':
case 'h':
default:
return print_usage(-1);
}
if (path[FIRMWARE] == NULL) {
logerror("no firmware specified!\n");
return print_usage(-1);
}
if ((device_id != NULL) && (device_path != NULL)) {
logerror("only one of -d or -p can be specified\n");
return print_usage(-1);
}
/* determine the target type */
if (type != NULL) {
for (i=0; i<FX_TYPE_MAX; i++) {
if (strcmp(type, fx_name[i]) == 0) {
fx_type = i;
break;
}
}
if (i >= FX_TYPE_MAX) {
logerror("illegal microcontroller type: %s\n", type);
return print_usage(-1);
}
}
/* open the device using libusb */
status = libusb_init(NULL);
if (status < 0) {
logerror("libusb_init() failed: %s\n", libusb_error_name(status));
return -1;
}
libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, verbose);
/* try to pick up missing parameters from known devices */
if ((type == NULL) || (device_id == NULL) || (device_path != NULL)) {
if (libusb_get_device_list(NULL, &devs) < 0) {
logerror("libusb_get_device_list() failed: %s\n", libusb_error_name(status));
goto err;
}
for (i=0; (dev=devs[i]) != NULL; i++) {
_busnum = libusb_get_bus_number(dev);
_devaddr = libusb_get_device_address(dev);
if ((type != NULL) && (device_path != NULL)) {
// if both a type and bus,addr were specified, we just need to find our match
if ((libusb_get_bus_number(dev) == busnum) && (libusb_get_device_address(dev) == devaddr))
break;
} else {
status = libusb_get_device_descriptor(dev, &desc);
if (status >= 0) {
if (verbose >= 3) {
logerror("examining %04x:%04x (%d,%d)\n",
desc.idVendor, desc.idProduct, _busnum, _devaddr);
}
for (j=0; j<ARRAYSIZE(known_device); j++) {
if ((desc.idVendor == known_device[j].vid)
&& (desc.idProduct == known_device[j].pid)) {
if (// nothing was specified
((type == NULL) && (device_id == NULL) && (device_path == NULL)) ||
// vid:pid was specified and we have a match
((type == NULL) && (device_id != NULL) && (vid == desc.idVendor) && (pid == desc.idProduct)) ||
// bus,addr was specified and we have a match
((type == NULL) && (device_path != NULL) && (busnum == _busnum) && (devaddr == _devaddr)) ||
// type was specified and we have a match
((type != NULL) && (device_id == NULL) && (device_path == NULL) && (fx_type == known_device[j].type)) ) {
fx_type = known_device[j].type;
vid = desc.idVendor;
pid = desc.idProduct;
busnum = _busnum;
devaddr = _devaddr;
break;
}
}
}
if (j < ARRAYSIZE(known_device)) {
if (verbose)
logerror("found device '%s' [%04x:%04x] (%d,%d)\n",
known_device[j].designation, vid, pid, busnum, devaddr);
break;
}
}
}
}
if (dev == NULL) {
libusb_free_device_list(devs, 1);
libusb_exit(NULL);
logerror("could not find a known device - please specify type and/or vid:pid and/or bus,dev\n");
return print_usage(-1);
}
status = libusb_open(dev, &device);
libusb_free_device_list(devs, 1);
if (status < 0) {
logerror("libusb_open() failed: %s\n", libusb_error_name(status));
goto err;
}
} else if (device_id != NULL) {
device = libusb_open_device_with_vid_pid(NULL, (uint16_t)vid, (uint16_t)pid);
if (device == NULL) {
logerror("libusb_open() failed\n");
goto err;
}
}
/* We need to claim the first interface */
libusb_set_auto_detach_kernel_driver(device, 1);
status = libusb_claim_interface(device, 0);
if (status != LIBUSB_SUCCESS) {
libusb_close(device);
logerror("libusb_claim_interface failed: %s\n", libusb_error_name(status));
goto err;
}
if (verbose)
logerror("microcontroller type: %s\n", fx_name[fx_type]);
for (i=0; i<ARRAYSIZE(path); i++) {
if (path[i] != NULL) {
ext = path[i] + strlen(path[i]) - 4;
if ((_stricmp(ext, ".hex") == 0) || (strcmp(ext, ".ihx") == 0))
img_type[i] = IMG_TYPE_HEX;
else if (_stricmp(ext, ".iic") == 0)
img_type[i] = IMG_TYPE_IIC;
else if (_stricmp(ext, ".bix") == 0)
img_type[i] = IMG_TYPE_BIX;
else if (_stricmp(ext, ".img") == 0)
img_type[i] = IMG_TYPE_IMG;
else {
logerror("%s is not a recognized image type\n", path[i]);
goto err;
}
}
if (verbose && path[i] != NULL)
logerror("%s: type %s\n", path[i], img_name[img_type[i]]);
}
if (path[LOADER] == NULL) {
/* single stage, put into internal memory */
if (verbose > 1)
logerror("single stage: load on-chip memory\n");
status = ezusb_load_ram(device, path[FIRMWARE], fx_type, img_type[FIRMWARE], 0);
} else {
/* two-stage, put loader into internal memory */
if (verbose > 1)
logerror("1st stage: load 2nd stage loader\n");
status = ezusb_load_ram(device, path[LOADER], fx_type, img_type[LOADER], 0);
if (status == 0) {
/* two-stage, put firmware into internal memory */
if (verbose > 1)
logerror("2nd state: load on-chip memory\n");
status = ezusb_load_ram(device, path[FIRMWARE], fx_type, img_type[FIRMWARE], 1);
}
}
libusb_release_interface(device, 0);
libusb_close(device);
libusb_exit(NULL);
return status;
err:
libusb_exit(NULL);
return -1;
}

1060
Externals/libusb/examples/getopt/getopt.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,180 @@
/* Declarations for getopt.
Copyright (C) 1989-1994, 1996-1999, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C 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.
The GNU C 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 the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _GETOPT_H
#ifndef __need_getopt
# define _GETOPT_H 1
#endif
/* If __GNU_LIBRARY__ is not already defined, either we are being used
standalone, or this is the first header included in the source file.
If we are being used with glibc, we need to include <features.h>, but
that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
not defined, include <ctype.h>, which will pull in <features.h> for us
if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
doesn't flood the namespace with stuff the way some other headers do.) */
#if !defined __GNU_LIBRARY__
# include <ctype.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
#ifndef __need_getopt
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
# if (defined __STDC__ && __STDC__) || defined __cplusplus
const char *name;
# else
char *name;
# endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
# define no_argument 0
# define required_argument 1
# define optional_argument 2
#endif /* need getopt */
/* Get definitions and prototypes for functions to process the
arguments in ARGV (ARGC of them, minus the program name) for
options given in OPTS.
Return the option character from OPTS just read. Return -1 when
there are no more options. For unrecognized options, or options
missing arguments, `optopt' is set to the option letter, and '?' is
returned.
The OPTS string is a list of characters which are recognized option
letters, optionally followed by colons, specifying that that letter
takes an argument, to be placed in `optarg'.
If a letter in OPTS is followed by two colons, its argument is
optional. This behavior is specific to the GNU `getopt'.
The argument `--' causes premature termination of argument
scanning, explicitly telling `getopt' that there are no more
options.
If OPTS begins with `--', then non-option arguments are treated as
arguments to the option '\0'. This behavior is specific to the GNU
`getopt'. */
#if (defined __STDC__ && __STDC__) || defined __cplusplus
# ifdef __GNU_LIBRARY__
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
# else /* not __GNU_LIBRARY__ */
extern int getopt ();
# endif /* __GNU_LIBRARY__ */
# ifndef __need_getopt
extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
const struct option *__longopts, int *__longind);
extern int getopt_long_only (int __argc, char *const *__argv,
const char *__shortopts,
const struct option *__longopts, int *__longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int __argc, char *const *__argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only);
# endif
#else /* not __STDC__ */
extern int getopt ();
# ifndef __need_getopt
extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal ();
# endif
#endif /* __STDC__ */
#ifdef __cplusplus
}
#endif
/* Make sure we later can get all the definitions and declarations. */
#undef __need_getopt
#endif /* getopt.h */

View File

@ -0,0 +1,188 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C 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.
The GNU C 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 the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "getopt.h"
#if !defined __STDC__ || !__STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
#define const
#endif
#endif
#include <stdio.h>
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#define GETOPT_INTERFACE_VERSION 2
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
#include <gnu-versions.h>
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
#define ELIDE_CODE
#endif
#endif
#ifndef ELIDE_CODE
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
#include <stdlib.h>
#endif
#ifndef NULL
#define NULL 0
#endif
int
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
If an option that starts with '-' (not '--') doesn't match a long option,
but does match a short option, it is parsed as a short option
instead. */
int
getopt_long_only (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
}
#endif /* Not ELIDE_CODE. */
#ifdef TEST
#include <stdio.h>
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] =
{
{"add", 1, 0, 0},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 0, 0, 0},
{"file", 1, 0, 0},
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "abc:d:0123456789",
long_options, &option_index);
if (c == -1)
break;
switch (c)
{
case 0:
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case 'd':
printf ("option d with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */

132
Externals/libusb/examples/hotplugtest.c vendored Normal file
View File

@ -0,0 +1,132 @@
/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
/*
* libusb example program for hotplug API
* Copyright © 2012-2013 Nathan Hjelm <hjelmn@mac.com>
*
* 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 <stdlib.h>
#include <stdio.h>
#include "libusb.h"
int done = 0;
libusb_device_handle *handle = NULL;
static int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
struct libusb_device_descriptor desc;
int rc;
(void)ctx;
(void)dev;
(void)event;
(void)user_data;
rc = libusb_get_device_descriptor(dev, &desc);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error getting device descriptor\n");
}
printf ("Device attached: %04x:%04x\n", desc.idVendor, desc.idProduct);
if (handle) {
libusb_close (handle);
handle = NULL;
}
rc = libusb_open (dev, &handle);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error opening device\n");
}
done++;
return 0;
}
static int LIBUSB_CALL hotplug_callback_detach(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
(void)ctx;
(void)dev;
(void)event;
(void)user_data;
printf ("Device detached\n");
if (handle) {
libusb_close (handle);
handle = NULL;
}
done++;
return 0;
}
int main(int argc, char *argv[])
{
libusb_hotplug_callback_handle hp[2];
int product_id, vendor_id, class_id;
int rc;
vendor_id = (argc > 1) ? (int)strtol (argv[1], NULL, 0) : 0x045a;
product_id = (argc > 2) ? (int)strtol (argv[2], NULL, 0) : 0x5005;
class_id = (argc > 3) ? (int)strtol (argv[3], NULL, 0) : LIBUSB_HOTPLUG_MATCH_ANY;
rc = libusb_init (NULL);
if (rc < 0)
{
printf("failed to initialise libusb: %s\n", libusb_error_name(rc));
return EXIT_FAILURE;
}
if (!libusb_has_capability (LIBUSB_CAP_HAS_HOTPLUG)) {
printf ("Hotplug capabilites are not supported on this platform\n");
libusb_exit (NULL);
return EXIT_FAILURE;
}
rc = libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, 0, vendor_id,
product_id, class_id, hotplug_callback, NULL, &hp[0]);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error registering callback 0\n");
libusb_exit (NULL);
return EXIT_FAILURE;
}
rc = libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, vendor_id,
product_id,class_id, hotplug_callback_detach, NULL, &hp[1]);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error registering callback 1\n");
libusb_exit (NULL);
return EXIT_FAILURE;
}
while (done < 2) {
rc = libusb_handle_events (NULL);
if (rc < 0)
printf("libusb_handle_events() failed: %s\n", libusb_error_name(rc));
}
if (handle) {
libusb_close (handle);
}
libusb_exit (NULL);
return EXIT_SUCCESS;
}

73
Externals/libusb/examples/listdevs.c vendored Normal file
View File

@ -0,0 +1,73 @@
/*
* libusb example program to list devices on the bus
* Copyright © 2007 Daniel Drake <dsd@gentoo.org>
*
* 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 <stdio.h>
#include "libusb.h"
static void print_devs(libusb_device **devs)
{
libusb_device *dev;
int i = 0, j = 0;
uint8_t path[8];
while ((dev = devs[i++]) != NULL) {
struct libusb_device_descriptor desc;
int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0) {
fprintf(stderr, "failed to get device descriptor");
return;
}
printf("%04x:%04x (bus %d, device %d)",
desc.idVendor, desc.idProduct,
libusb_get_bus_number(dev), libusb_get_device_address(dev));
r = libusb_get_port_numbers(dev, path, sizeof(path));
if (r > 0) {
printf(" path: %d", path[0]);
for (j = 1; j < r; j++)
printf(".%d", path[j]);
}
printf("\n");
}
}
int main(void)
{
libusb_device **devs;
int r;
ssize_t cnt;
r = libusb_init(NULL);
if (r < 0)
return r;
cnt = libusb_get_device_list(NULL, &devs);
if (cnt < 0){
libusb_exit(NULL);
return (int) cnt;
}
print_devs(devs);
libusb_free_device_list(devs, 1);
libusb_exit(NULL);
return 0;
}

View File

@ -0,0 +1,193 @@
/*
* libusb example program to measure Atmel SAM3U isochronous performance
* Copyright (C) 2012 Harald Welte <laforge@gnumonks.org>
*
* Copied with the author's permission under LGPL-2.1 from
* http://git.gnumonks.org/cgi-bin/gitweb.cgi?p=sam3u-tests.git;a=blob;f=usb-benchmark-project/host/benchmark.c;h=74959f7ee88f1597286cd435f312a8ff52c56b7e
*
* An Atmel SAM3U test firmware is also available in the above repository.
*
* 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 <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <libusb.h>
#define EP_DATA_IN 0x82
#define EP_ISO_IN 0x86
static int do_exit = 0;
static struct libusb_device_handle *devh = NULL;
static unsigned long num_bytes = 0, num_xfer = 0;
static struct timeval tv_start;
static void LIBUSB_CALL cb_xfr(struct libusb_transfer *xfr)
{
int i;
if (xfr->status != LIBUSB_TRANSFER_COMPLETED) {
fprintf(stderr, "transfer status %d\n", xfr->status);
libusb_free_transfer(xfr);
exit(3);
}
if (xfr->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
for (i = 0; i < xfr->num_iso_packets; i++) {
struct libusb_iso_packet_descriptor *pack = &xfr->iso_packet_desc[i];
if (pack->status != LIBUSB_TRANSFER_COMPLETED) {
fprintf(stderr, "Error: pack %d status %d\n", i, pack->status);
exit(5);
}
printf("pack%d length:%u, actual_length:%u\n", i, pack->length, pack->actual_length);
}
}
printf("length:%u, actual_length:%u\n", xfr->length, xfr->actual_length);
for (i = 0; i < xfr->actual_length; i++) {
printf("%02x", xfr->buffer[i]);
if (i % 16)
printf("\n");
else if (i % 8)
printf(" ");
else
printf(" ");
}
num_bytes += xfr->actual_length;
num_xfer++;
if (libusb_submit_transfer(xfr) < 0) {
fprintf(stderr, "error re-submitting URB\n");
exit(1);
}
}
static int benchmark_in(uint8_t ep)
{
static uint8_t buf[2048];
static struct libusb_transfer *xfr;
int num_iso_pack = 0;
if (ep == EP_ISO_IN)
num_iso_pack = 16;
xfr = libusb_alloc_transfer(num_iso_pack);
if (!xfr)
return -ENOMEM;
if (ep == EP_ISO_IN) {
libusb_fill_iso_transfer(xfr, devh, ep, buf,
sizeof(buf), num_iso_pack, cb_xfr, NULL, 0);
libusb_set_iso_packet_lengths(xfr, sizeof(buf)/num_iso_pack);
} else
libusb_fill_bulk_transfer(xfr, devh, ep, buf,
sizeof(buf), cb_xfr, NULL, 0);
gettimeofday(&tv_start, NULL);
/* NOTE: To reach maximum possible performance the program must
* submit *multiple* transfers here, not just one.
*
* When only one transfer is submitted there is a gap in the bus
* schedule from when the transfer completes until a new transfer
* is submitted by the callback. This causes some jitter for
* isochronous transfers and loss of throughput for bulk transfers.
*
* This is avoided by queueing multiple transfers in advance, so
* that the host controller is always kept busy, and will schedule
* more transfers on the bus while the callback is running for
* transfers which have completed on the bus.
*/
return libusb_submit_transfer(xfr);
}
static void measure(void)
{
struct timeval tv_stop;
unsigned int diff_msec;
gettimeofday(&tv_stop, NULL);
diff_msec = (tv_stop.tv_sec - tv_start.tv_sec)*1000;
diff_msec += (tv_stop.tv_usec - tv_start.tv_usec)/1000;
printf("%lu transfers (total %lu bytes) in %u miliseconds => %lu bytes/sec\n",
num_xfer, num_bytes, diff_msec, (num_bytes*1000)/diff_msec);
}
static void sig_hdlr(int signum)
{
switch (signum) {
case SIGINT:
measure();
do_exit = 1;
break;
}
}
int main(int argc, char **argv)
{
int rc;
struct sigaction sigact;
sigact.sa_handler = sig_hdlr;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
sigaction(SIGINT, &sigact, NULL);
rc = libusb_init(NULL);
if (rc < 0) {
fprintf(stderr, "Error initializing libusb: %s\n", libusb_error_name(rc));
exit(1);
}
devh = libusb_open_device_with_vid_pid(NULL, 0x16c0, 0x0763);
if (!devh) {
fprintf(stderr, "Error finding USB device\n");
goto out;
}
rc = libusb_claim_interface(devh, 2);
if (rc < 0) {
fprintf(stderr, "Error claiming interface: %s\n", libusb_error_name(rc));
goto out;
}
benchmark_in(EP_ISO_IN);
while (!do_exit) {
rc = libusb_handle_events(NULL);
if (rc != LIBUSB_SUCCESS)
break;
}
/* Measurement has already been done by the signal handler. */
libusb_release_interface(devh, 0);
out:
if (devh)
libusb_close(devh);
libusb_exit(NULL);
return rc;
}

277
Externals/libusb/examples/testlibusb.c vendored Executable file
View File

@ -0,0 +1,277 @@
/*
* Test suite program based of libusb-0.1-compat testlibusb
* Copyright (c) 2013 Nathan Hjelm <hjelmn@mac.ccom>
*
* 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 <stdio.h>
#include <string.h>
#include "libusb.h"
#if defined(_MSC_VER) && (_MSC_VER < 1900)
#define snprintf _snprintf
#endif
int verbose = 0;
static void print_endpoint_comp(const struct libusb_ss_endpoint_companion_descriptor *ep_comp)
{
printf(" USB 3.0 Endpoint Companion:\n");
printf(" bMaxBurst: %d\n", ep_comp->bMaxBurst);
printf(" bmAttributes: 0x%02x\n", ep_comp->bmAttributes);
printf(" wBytesPerInterval: %d\n", ep_comp->wBytesPerInterval);
}
static void print_endpoint(const struct libusb_endpoint_descriptor *endpoint)
{
int i, ret;
printf(" Endpoint:\n");
printf(" bEndpointAddress: %02xh\n", endpoint->bEndpointAddress);
printf(" bmAttributes: %02xh\n", endpoint->bmAttributes);
printf(" wMaxPacketSize: %d\n", endpoint->wMaxPacketSize);
printf(" bInterval: %d\n", endpoint->bInterval);
printf(" bRefresh: %d\n", endpoint->bRefresh);
printf(" bSynchAddress: %d\n", endpoint->bSynchAddress);
for (i = 0; i < endpoint->extra_length;) {
if (LIBUSB_DT_SS_ENDPOINT_COMPANION == endpoint->extra[i + 1]) {
struct libusb_ss_endpoint_companion_descriptor *ep_comp;
ret = libusb_get_ss_endpoint_companion_descriptor(NULL, endpoint, &ep_comp);
if (LIBUSB_SUCCESS != ret) {
continue;
}
print_endpoint_comp(ep_comp);
libusb_free_ss_endpoint_companion_descriptor(ep_comp);
}
i += endpoint->extra[i];
}
}
static void print_altsetting(const struct libusb_interface_descriptor *interface)
{
uint8_t i;
printf(" Interface:\n");
printf(" bInterfaceNumber: %d\n", interface->bInterfaceNumber);
printf(" bAlternateSetting: %d\n", interface->bAlternateSetting);
printf(" bNumEndpoints: %d\n", interface->bNumEndpoints);
printf(" bInterfaceClass: %d\n", interface->bInterfaceClass);
printf(" bInterfaceSubClass: %d\n", interface->bInterfaceSubClass);
printf(" bInterfaceProtocol: %d\n", interface->bInterfaceProtocol);
printf(" iInterface: %d\n", interface->iInterface);
for (i = 0; i < interface->bNumEndpoints; i++)
print_endpoint(&interface->endpoint[i]);
}
static void print_2_0_ext_cap(struct libusb_usb_2_0_extension_descriptor *usb_2_0_ext_cap)
{
printf(" USB 2.0 Extension Capabilities:\n");
printf(" bDevCapabilityType: %d\n", usb_2_0_ext_cap->bDevCapabilityType);
printf(" bmAttributes: 0x%x\n", usb_2_0_ext_cap->bmAttributes);
}
static void print_ss_usb_cap(struct libusb_ss_usb_device_capability_descriptor *ss_usb_cap)
{
printf(" USB 3.0 Capabilities:\n");
printf(" bDevCapabilityType: %d\n", ss_usb_cap->bDevCapabilityType);
printf(" bmAttributes: 0x%x\n", ss_usb_cap->bmAttributes);
printf(" wSpeedSupported: 0x%x\n", ss_usb_cap->wSpeedSupported);
printf(" bFunctionalitySupport: %d\n", ss_usb_cap->bFunctionalitySupport);
printf(" bU1devExitLat: %d\n", ss_usb_cap->bU1DevExitLat);
printf(" bU2devExitLat: %d\n", ss_usb_cap->bU2DevExitLat);
}
static void print_bos(libusb_device_handle *handle)
{
struct libusb_bos_descriptor *bos;
int ret;
ret = libusb_get_bos_descriptor(handle, &bos);
if (0 > ret) {
return;
}
printf(" Binary Object Store (BOS):\n");
printf(" wTotalLength: %d\n", bos->wTotalLength);
printf(" bNumDeviceCaps: %d\n", bos->bNumDeviceCaps);
if(bos->dev_capability[0]->bDevCapabilityType == LIBUSB_BT_USB_2_0_EXTENSION) {
struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension;
ret = libusb_get_usb_2_0_extension_descriptor(NULL, bos->dev_capability[0],&usb_2_0_extension);
if (0 > ret) {
return;
}
print_2_0_ext_cap(usb_2_0_extension);
libusb_free_usb_2_0_extension_descriptor(usb_2_0_extension);
}
if(bos->dev_capability[0]->bDevCapabilityType == LIBUSB_BT_SS_USB_DEVICE_CAPABILITY) {
struct libusb_ss_usb_device_capability_descriptor *dev_cap;
ret = libusb_get_ss_usb_device_capability_descriptor(NULL, bos->dev_capability[0],&dev_cap);
if (0 > ret) {
return;
}
print_ss_usb_cap(dev_cap);
libusb_free_ss_usb_device_capability_descriptor(dev_cap);
}
libusb_free_bos_descriptor(bos);
}
static void print_interface(const struct libusb_interface *interface)
{
int i;
for (i = 0; i < interface->num_altsetting; i++)
print_altsetting(&interface->altsetting[i]);
}
static void print_configuration(struct libusb_config_descriptor *config)
{
uint8_t i;
printf(" Configuration:\n");
printf(" wTotalLength: %d\n", config->wTotalLength);
printf(" bNumInterfaces: %d\n", config->bNumInterfaces);
printf(" bConfigurationValue: %d\n", config->bConfigurationValue);
printf(" iConfiguration: %d\n", config->iConfiguration);
printf(" bmAttributes: %02xh\n", config->bmAttributes);
printf(" MaxPower: %d\n", config->MaxPower);
for (i = 0; i < config->bNumInterfaces; i++)
print_interface(&config->interface[i]);
}
static int print_device(libusb_device *dev, int level)
{
struct libusb_device_descriptor desc;
libusb_device_handle *handle = NULL;
char description[260];
char string[256];
int ret;
uint8_t i;
ret = libusb_get_device_descriptor(dev, &desc);
if (ret < 0) {
fprintf(stderr, "failed to get device descriptor");
return -1;
}
ret = libusb_open(dev, &handle);
if (LIBUSB_SUCCESS == ret) {
if (desc.iManufacturer) {
ret = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, string, sizeof(string));
if (ret > 0)
snprintf(description, sizeof(description), "%s - ", string);
else
snprintf(description, sizeof(description), "%04X - ",
desc.idVendor);
}
else
snprintf(description, sizeof(description), "%04X - ",
desc.idVendor);
if (desc.iProduct) {
ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct, string, sizeof(string));
if (ret > 0)
snprintf(description + strlen(description), sizeof(description) -
strlen(description), "%s", string);
else
snprintf(description + strlen(description), sizeof(description) -
strlen(description), "%04X", desc.idProduct);
}
else
snprintf(description + strlen(description), sizeof(description) -
strlen(description), "%04X", desc.idProduct);
}
else {
snprintf(description, sizeof(description), "%04X - %04X",
desc.idVendor, desc.idProduct);
}
printf("%.*sDev (bus %d, device %d): %s\n", level * 2, " ",
libusb_get_bus_number(dev), libusb_get_device_address(dev), description);
if (handle && verbose) {
if (desc.iSerialNumber) {
ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, string, sizeof(string));
if (ret > 0)
printf("%.*s - Serial Number: %s\n", level * 2,
" ", string);
}
}
if (verbose) {
for (i = 0; i < desc.bNumConfigurations; i++) {
struct libusb_config_descriptor *config;
ret = libusb_get_config_descriptor(dev, i, &config);
if (LIBUSB_SUCCESS != ret) {
printf(" Couldn't retrieve descriptors\n");
continue;
}
print_configuration(config);
libusb_free_config_descriptor(config);
}
if (handle && desc.bcdUSB >= 0x0201) {
print_bos(handle);
}
}
if (handle)
libusb_close(handle);
return 0;
}
int main(int argc, char *argv[])
{
libusb_device **devs;
ssize_t cnt;
int r, i;
if (argc > 1 && !strcmp(argv[1], "-v"))
verbose = 1;
r = libusb_init(NULL);
if (r < 0)
return r;
cnt = libusb_get_device_list(NULL, &devs);
if (cnt < 0)
return (int)cnt;
for (i = 0; devs[i]; ++i) {
print_device(devs[i], 0);
}
libusb_free_device_list(devs, 1);
libusb_exit(NULL);
return 0;
}

1135
Externals/libusb/examples/xusb.c vendored Normal file

File diff suppressed because it is too large Load Diff

11
Externals/libusb/libusb-1.0.pc.in vendored Normal file
View File

@ -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

View File

@ -13,10 +13,12 @@ DARWIN_USB_SRC = os/darwin_usb.h os/darwin_usb.c
OPENBSD_USB_SRC = os/openbsd_usb.c OPENBSD_USB_SRC = os/openbsd_usb.c
NETBSD_USB_SRC = os/netbsd_usb.c NETBSD_USB_SRC = os/netbsd_usb.c
SUNOS_USB_SRC = os/sunos_usb.c os/sunos_usb.h SUNOS_USB_SRC = os/sunos_usb.c os/sunos_usb.h
WINDOWS_COMMON_SRC = os/windows_nt_common.h os/windows_nt_common.c \ WINDOWS_USB_SRC = libusb-1.0.def libusb-1.0.rc \
os/windows_common.h libusb-1.0.rc libusb-1.0.def os/windows_common.h \
WINDOWS_USB_SRC = os/windows_winusb.h os/windows_winusb.c os/windows_usbdk.h \ os/windows_nt_common.h os/windows_nt_common.c \
os/windows_usbdk.c $(COMMON_WINDOWS_SRC) 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 WINCE_USB_SRC = os/wince_usb.h os/wince_usb.c
HAIKU_USB_SRC = os/haiku_usb.h os/haiku_usb_backend.cpp \ 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 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) \ $(WINDOWS_POLL_SRC) $(WINDOWS_THREADS_SRC) \
$(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) \ $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) \
$(OPENBSD_USB_SRC) $(NETBSD_USB_SRC) \ $(OPENBSD_USB_SRC) $(NETBSD_USB_SRC) \
$(WINDOWS_COMMON_SRC) $(WINDOWS_USB_SRC) $(WINDOWS_USBDK_SRC) \ $(WINDOWS_USB_SRC) $(WINCE_USB_SRC) \
$(WINCE_USB_SRC) $(HAIKU_USB_SRC) \ $(HAIKU_USB_SRC) \
os/linux_udev.c os/linux_netlink.c os/linux_udev.c os/linux_netlink.c
if OS_LINUX if OS_LINUX
@ -63,7 +65,7 @@ libusb_1_0_la_LIBADD = libusb_haiku.la
endif endif
if OS_WINDOWS if OS_WINDOWS
OS_SRC = $(WINDOWS_USB_SRC) $(WINDOWS_COMMON_SRC) OS_SRC = $(WINDOWS_USB_SRC)
.rc.lo: .rc.lo:
$(AM_V_GEN)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(RCFLAGS) -i $< -o $@ $(AM_V_GEN)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(RCFLAGS) -i $< -o $@

File diff suppressed because it is too large Load Diff

View File

@ -62,7 +62,7 @@ int usbi_parse_descriptor(const unsigned char *source, const char *descriptor,
if (host_endian) { if (host_endian) {
memcpy(dp, sp, 2); memcpy(dp, sp, 2);
} else { } else {
w = (sp[1] << 8) | sp[0]; w = (uint16_t)((sp[1] << 8) | sp[0]);
*((uint16_t *)dp) = w; *((uint16_t *)dp) = w;
} }
sp += 2; sp += 2;
@ -74,8 +74,8 @@ int usbi_parse_descriptor(const unsigned char *source, const char *descriptor,
if (host_endian) { if (host_endian) {
memcpy(dp, sp, 4); memcpy(dp, sp, 4);
} else { } else {
d = (sp[3] << 24) | (sp[2] << 16) | d = (uint32_t)((sp[3] << 24) | (sp[2] << 16) |
(sp[1] << 8) | sp[0]; (sp[1] << 8) | sp[0]);
*((uint32_t *)dp) = d; *((uint32_t *)dp) = d;
} }
sp += 4; sp += 4;
@ -168,13 +168,13 @@ static int parse_endpoint(struct libusb_context *ctx,
/* Copy any unknown descriptors into a storage area for drivers */ /* Copy any unknown descriptors into a storage area for drivers */
/* to later parse */ /* to later parse */
len = (int)(buffer - begin); len = (int)(buffer - begin);
if (!len) { if (len <= 0) {
endpoint->extra = NULL; endpoint->extra = NULL;
endpoint->extra_length = 0; endpoint->extra_length = 0;
return parsed; return parsed;
} }
extra = malloc(len); extra = malloc((size_t)len);
endpoint->extra = extra; endpoint->extra = extra;
if (!extra) { if (!extra) {
endpoint->extra_length = 0; endpoint->extra_length = 0;
@ -230,7 +230,7 @@ static int parse_interface(libusb_context *ctx,
(struct libusb_interface_descriptor *) usb_interface->altsetting; (struct libusb_interface_descriptor *) usb_interface->altsetting;
altsetting = usbi_reallocf(altsetting, altsetting = usbi_reallocf(altsetting,
sizeof(struct libusb_interface_descriptor) * sizeof(struct libusb_interface_descriptor) *
(usb_interface->num_altsetting + 1)); ((size_t)usb_interface->num_altsetting + 1));
if (!altsetting) { if (!altsetting) {
r = LIBUSB_ERROR_NO_MEM; r = LIBUSB_ERROR_NO_MEM;
goto err; goto err;
@ -307,8 +307,8 @@ static int parse_interface(libusb_context *ctx,
/* Copy any unknown descriptors into a storage area for */ /* Copy any unknown descriptors into a storage area for */
/* drivers to later parse */ /* drivers to later parse */
len = (int)(buffer - begin); len = (int)(buffer - begin);
if (len) { if (len > 0) {
ifp->extra = malloc(len); ifp->extra = malloc((size_t)len);
if (!ifp->extra) { if (!ifp->extra) {
r = LIBUSB_ERROR_NO_MEM; r = LIBUSB_ERROR_NO_MEM;
goto err; goto err;
@ -333,7 +333,7 @@ static int parse_interface(libusb_context *ctx,
goto err; goto err;
if (r == 0) { if (r == 0) {
ifp->bNumEndpoints = (uint8_t)i; ifp->bNumEndpoints = (uint8_t)i;
break;; break;
} }
buffer += r; buffer += r;
@ -453,10 +453,10 @@ static int parse_configuration(struct libusb_context *ctx,
/* Copy any unknown descriptors into a storage area for */ /* Copy any unknown descriptors into a storage area for */
/* drivers to later parse */ /* drivers to later parse */
len = (int)(buffer - begin); len = (int)(buffer - begin);
if (len) { if (len > 0) {
/* FIXME: We should realloc and append here */ /* FIXME: We should realloc and append here */
if (!config->extra_length) { if (!config->extra_length) {
config->extra = malloc(len); config->extra = malloc((size_t)len);
if (!config->extra) { if (!config->extra) {
r = LIBUSB_ERROR_NO_MEM; r = LIBUSB_ERROR_NO_MEM;
goto err; goto err;
@ -513,7 +513,7 @@ int usbi_device_cache_descriptor(libusb_device *dev)
{ {
int r, host_endian = 0; 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); &host_endian);
if (r < 0) if (r < 0)
return r; return r;
@ -572,7 +572,7 @@ int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev,
int host_endian = 0; int host_endian = 0;
int r; 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); LIBUSB_DT_CONFIG_SIZE, &host_endian);
if (r < 0) if (r < 0)
return r; return r;
@ -587,7 +587,7 @@ int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev,
if (!buf) if (!buf)
return LIBUSB_ERROR_NO_MEM; 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); _config.wTotalLength, &host_endian);
if (r >= 0) if (r >= 0)
r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config); 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) if (config_index >= dev->num_configurations)
return LIBUSB_ERROR_NOT_FOUND; 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); LIBUSB_DT_CONFIG_SIZE, &host_endian);
if (r < 0) if (r < 0)
return r; return r;
@ -640,7 +640,7 @@ int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev,
if (!buf) if (!buf)
return LIBUSB_ERROR_NO_MEM; 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); _config.wTotalLength, &host_endian);
if (r >= 0) if (r >= 0)
r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config); 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++) { for (i = 0; i < dev->num_configurations; i++) {
unsigned char tmp[6]; unsigned char tmp[6];
int host_endian; 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); &host_endian);
if (r < 0) { if (r < 0) {
*idx = -1; *idx = -1;
@ -702,8 +702,8 @@ int API_EXPORTED libusb_get_config_descriptor_by_value(libusb_device *dev,
int r, idx, host_endian; int r, idx, host_endian;
unsigned char *buf = NULL; unsigned char *buf = NULL;
if (usbi_backend->get_config_descriptor_by_value) { if (usbi_backend.get_config_descriptor_by_value) {
r = usbi_backend->get_config_descriptor_by_value(dev, r = usbi_backend.get_config_descriptor_by_value(dev,
bConfigurationValue, &buf, &host_endian); bConfigurationValue, &buf, &host_endian);
if (r < 0) if (r < 0)
return r; 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 * It is safe to call this function with a NULL ss_usb_device_cap
* parameter, in which case the function simply returns. * 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( void API_EXPORTED libusb_free_ss_usb_device_capability_descriptor(
struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap) 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, * It is safe to call this function with a NULL container_id parameter,
* in which case the function simply returns. * 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( void API_EXPORTED libusb_free_container_id_descriptor(
struct libusb_container_id_descriptor *container_id) 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) if (r < 4)
return LIBUSB_ERROR_IO; 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, r = libusb_get_string_descriptor(dev_handle, desc_index, langid, tbuf,
sizeof(tbuf)); sizeof(tbuf));
@ -1176,7 +1177,8 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_ha
if (tbuf[0] > r) if (tbuf[0] > r)
return LIBUSB_ERROR_IO; 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)) if (di >= (length - 1))
break; break;

View File

@ -154,36 +154,30 @@ int main (void) {
\endcode \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_device *dev, libusb_hotplug_event event,
struct libusb_hotplug_callback *hotplug_cb) struct libusb_hotplug_callback *hotplug_cb)
{ {
/* Handle lazy deregistration of callback */ if (!(hotplug_cb->flags & event)) {
if (hotplug_cb->needs_free) {
/* Free callback */
return 1;
}
if (!(hotplug_cb->events & event)) {
return 0; 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) { hotplug_cb->vendor_id != dev->device_descriptor.idVendor) {
return 0; 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) { hotplug_cb->product_id != dev->device_descriptor.idProduct) {
return 0; 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) { hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) {
return 0; 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, 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); usbi_mutex_lock(&ctx->hotplug_cbs_lock);
list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) { 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); 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); usbi_mutex_lock(&ctx->hotplug_cbs_lock);
if (ret) { 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); 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, void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev,
libusb_hotplug_event event) libusb_hotplug_event event)
{ {
int pending_events; int pending_events;
libusb_hotplug_message *message = calloc(1, sizeof(*message)); struct libusb_hotplug_message *message = calloc(1, sizeof(*message));
if (!message) { if (!message) {
usbi_err(ctx, "error allocating hotplug 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_fn cb_fn, void *user_data,
libusb_hotplug_callback_handle *callback_handle) libusb_hotplug_callback_handle *callback_handle)
{ {
libusb_hotplug_callback *new_callback; struct 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;
}
/* check for sane values */ /* 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 != product_id && (~0xffff & product_id)) ||
(LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) || (LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) ||
!cb_fn) { !cb_fn) {
return LIBUSB_ERROR_INVALID_PARAM; 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); USBI_GET_CONTEXT(ctx);
new_callback = (libusb_hotplug_callback *)calloc(1, sizeof (*new_callback)); new_callback = calloc(1, sizeof(*new_callback));
if (!new_callback) { if (!new_callback) {
return LIBUSB_ERROR_NO_MEM; return LIBUSB_ERROR_NO_MEM;
} }
new_callback->ctx = ctx; new_callback->flags = (uint8_t)events;
new_callback->vendor_id = vendor_id; if (LIBUSB_HOTPLUG_MATCH_ANY != vendor_id) {
new_callback->product_id = product_id; new_callback->flags |= USBI_HOTPLUG_VENDOR_ID_VALID;
new_callback->dev_class = dev_class; new_callback->vendor_id = (uint16_t)vendor_id;
new_callback->flags = flags; }
new_callback->events = events; 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->cb = cb_fn;
new_callback->user_data = user_data; new_callback->user_data = user_data;
new_callback->needs_free = 0;
usbi_mutex_lock(&ctx->hotplug_cbs_lock); usbi_mutex_lock(&ctx->hotplug_cbs_lock);
/* protect the handle by the context hotplug lock. it doesn't matter if the same handle /* protect the handle by the context hotplug lock */
* is used for different contexts only that the handle is unique for this context */ new_callback->handle = ctx->next_hotplug_cb_handle++;
new_callback->handle = handle_id++;
/* 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); list_add(&new_callback->list, &ctx->hotplug_cbs);
usbi_mutex_unlock(&ctx->hotplug_cbs_lock); 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) { if ((flags & LIBUSB_HOTPLUG_ENUMERATE) && (events & LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)) {
int i, len; ssize_t i, len;
struct libusb_device **devs; struct libusb_device **devs;
len = (int) libusb_get_device_list(ctx, &devs); len = libusb_get_device_list(ctx, &devs);
if (len < 0) { if (len < 0) {
libusb_hotplug_deregister_callback(ctx, libusb_hotplug_deregister_callback(ctx,
new_callback->handle); new_callback->handle);
return len; return (int)len;
} }
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
@ -311,10 +319,11 @@ int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
return LIBUSB_SUCCESS; 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) libusb_hotplug_callback_handle callback_handle)
{ {
struct libusb_hotplug_callback *hotplug_cb; struct libusb_hotplug_callback *hotplug_cb;
int deregistered = 0;
/* check for hotplug support */ /* check for hotplug support */
if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { 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_GET_CONTEXT(ctx);
usbi_dbg("deregister hotplug cb %d", callback_handle);
usbi_mutex_lock(&ctx->hotplug_cbs_lock); usbi_mutex_lock(&ctx->hotplug_cbs_lock);
list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list, list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
struct libusb_hotplug_callback) {
if (callback_handle == hotplug_cb->handle) { if (callback_handle == hotplug_cb->handle) {
/* Mark this callback for deregistration */ /* 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_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; struct libusb_hotplug_callback *hotplug_cb, *next;
usbi_mutex_lock(&ctx->hotplug_cbs_lock); usbi_mutex_lock(&ctx->hotplug_cbs_lock);
list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
struct libusb_hotplug_callback) { if (forced || (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE)) {
list_del(&hotplug_cb->list); usbi_dbg("freeing hotplug cb %p with handle %d", hotplug_cb,
free(hotplug_cb); hotplug_cb->handle);
list_del(&hotplug_cb->list);
free(hotplug_cb);
}
} }
usbi_mutex_unlock(&ctx->hotplug_cbs_lock); usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
} }

View File

@ -19,12 +19,34 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 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 #define USBI_HOTPLUG_H
#ifndef LIBUSBI_H
#include "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 /** \ingroup hotplug
* The hotplug callback structure. The user populates this structure with * The hotplug callback structure. The user populates this structure with
@ -32,23 +54,17 @@
* to receive notification of hotplug events. * to receive notification of hotplug events.
*/ */
struct libusb_hotplug_callback { struct libusb_hotplug_callback {
/** Context this callback is associated with */ /** Flags that control how this callback behaves */
struct libusb_context *ctx; uint8_t flags;
/** Vendor ID to match or LIBUSB_HOTPLUG_MATCH_ANY */ /** Vendor ID to match (if flags says this is valid) */
int vendor_id; uint16_t vendor_id;
/** Product ID to match or LIBUSB_HOTPLUG_MATCH_ANY */ /** Product ID to match (if flags says this is valid) */
int product_id; uint16_t product_id;
/** Device class to match or LIBUSB_HOTPLUG_MATCH_ANY */ /** Device class to match (if flags says this is valid) */
int dev_class; uint8_t dev_class;
/** Hotplug callback flags */
libusb_hotplug_flag flags;
/** Event(s) that will trigger this callback */
libusb_hotplug_event events;
/** Callback function to invoke for matching event/device */ /** Callback function to invoke for matching event/device */
libusb_hotplug_callback_fn cb; libusb_hotplug_callback_fn cb;
@ -59,15 +75,10 @@ struct libusb_hotplug_callback {
/** User data that will be passed to the callback function */ /** User data that will be passed to the callback function */
void *user_data; void *user_data;
/** Callback is marked for deletion */
int needs_free;
/** List this callback is registered in (ctx->hotplug_cbs) */ /** List this callback is registered in (ctx->hotplug_cbs) */
struct list_head list; struct list_head list;
}; };
typedef struct libusb_hotplug_callback libusb_hotplug_callback;
struct libusb_hotplug_message { struct libusb_hotplug_message {
/** The hotplug event that occurred */ /** The hotplug event that occurred */
libusb_hotplug_event event; libusb_hotplug_event event;
@ -79,9 +90,7 @@ struct libusb_hotplug_message {
struct list_head list; struct list_head list;
}; };
typedef struct libusb_hotplug_message libusb_hotplug_message; void usbi_hotplug_deregister(struct libusb_context *ctx, int forced);
void usbi_hotplug_deregister_all(struct libusb_context *ctx);
void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
libusb_hotplug_event event); libusb_hotplug_event event);
void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev, void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev,

View File

@ -27,9 +27,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#ifdef HAVE_SYS_TIME_H #ifdef HAVE_SYS_TIME_H
#include <sys/time.h> #include <sys/time.h>
#endif #endif
@ -1147,8 +1144,8 @@ int usbi_io_init(struct libusb_context *ctx)
goto err_close_pipe; goto err_close_pipe;
#ifdef USBI_TIMERFD_AVAILABLE #ifdef USBI_TIMERFD_AVAILABLE
ctx->timerfd = timerfd_create(usbi_backend->get_timerfd_clockid(), ctx->timerfd = timerfd_create(usbi_backend.get_timerfd_clockid(),
TFD_NONBLOCK); TFD_NONBLOCK | TFD_CLOEXEC);
if (ctx->timerfd >= 0) { if (ctx->timerfd >= 0) {
usbi_dbg("using timerfd for timeouts"); usbi_dbg("using timerfd for timeouts");
r = usbi_add_pollfd(ctx, ctx->timerfd, POLLIN); 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_cond_destroy(&ctx->event_waiters_cond);
usbi_mutex_destroy(&ctx->event_data_lock); usbi_mutex_destroy(&ctx->event_data_lock);
usbi_tls_key_delete(ctx->event_handling_key); 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) static int calculate_timeout(struct usbi_transfer *transfer)
@ -1208,10 +1204,12 @@ static int calculate_timeout(struct usbi_transfer *transfer)
unsigned int timeout = unsigned int timeout =
USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout; USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout;
if (!timeout) if (!timeout) {
timerclear(&transfer->timeout);
return 0; return 0;
}
r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &current_time); r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, &current_time);
if (r < 0) { if (r < 0) {
usbi_err(ITRANSFER_CTX(transfer), usbi_err(ITRANSFER_CTX(transfer),
"failed to read monotonic clock, errno=%d", errno); "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 * 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. * 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 * \returns a newly allocated transfer, or NULL on error
*/ */
DEFAULT_VISIBILITY DEFAULT_VISIBILITY
@ -1258,12 +1256,18 @@ struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(
int iso_packets) int iso_packets)
{ {
struct libusb_transfer *transfer; struct libusb_transfer *transfer;
size_t os_alloc_size = usbi_backend->transfer_priv_size; size_t os_alloc_size;
size_t alloc_size = sizeof(struct usbi_transfer) 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_transfer)
+ (sizeof(struct libusb_iso_packet_descriptor) * iso_packets) + (sizeof(struct libusb_iso_packet_descriptor) * (size_t)iso_packets)
+ os_alloc_size; + os_alloc_size;
struct usbi_transfer *itransfer = calloc(1, alloc_size); itransfer = calloc(1, alloc_size);
if (!itransfer) if (!itransfer)
return NULL; return NULL;
@ -1298,7 +1302,7 @@ void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer)
return; return;
usbi_dbg("transfer %p", transfer); usbi_dbg("transfer %p", transfer);
if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER && transfer->buffer) if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER)
free(transfer->buffer); free(transfer->buffer);
itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); 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); usbi_mutex_unlock(&ctx->flying_transfers_lock);
r = usbi_backend->submit_transfer(itransfer); r = usbi_backend.submit_transfer(itransfer);
if (r == LIBUSB_SUCCESS) { if (r == LIBUSB_SUCCESS) {
itransfer->state_flags |= USBI_TRANSFER_IN_FLIGHT; itransfer->state_flags |= USBI_TRANSFER_IN_FLIGHT;
/* keep a reference to this device */ /* 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; r = LIBUSB_ERROR_NOT_FOUND;
goto out; goto out;
} }
r = usbi_backend->cancel_transfer(itransfer); r = usbi_backend.cancel_transfer(itransfer);
if (r < 0) { if (r < 0) {
if (r != LIBUSB_ERROR_NOT_FOUND && if (r != LIBUSB_ERROR_NOT_FOUND &&
r != LIBUSB_ERROR_NO_DEVICE) 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. */ * function will be called the next time an event handler runs. */
void usbi_signal_transfer_completion(struct usbi_transfer *transfer) void usbi_signal_transfer_completion(struct usbi_transfer *transfer)
{ {
struct libusb_context *ctx = ITRANSFER_CTX(transfer); libusb_device_handle *dev_handle = USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->dev_handle;
int pending_events;
usbi_mutex_lock(&ctx->event_data_lock); if (dev_handle) {
pending_events = usbi_pending_events(ctx); struct libusb_context *ctx = HANDLE_CTX(dev_handle);
list_add_tail(&transfer->completed_list, &ctx->completed_transfers); int pending_events;
if (!pending_events)
usbi_signal_event(ctx); usbi_mutex_lock(&ctx->event_data_lock);
usbi_mutex_unlock(&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 /** \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) void API_EXPORTED libusb_interrupt_event_handler(libusb_context *ctx)
{ {
int pending_events;
USBI_GET_CONTEXT(ctx); USBI_GET_CONTEXT(ctx);
usbi_dbg(""); usbi_dbg("");
usbi_mutex_lock(&ctx->event_data_lock); 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_signal_event(ctx);
}
usbi_mutex_unlock(&ctx->event_data_lock); usbi_mutex_unlock(&ctx->event_data_lock);
} }
@ -2004,7 +2015,7 @@ static int handle_timeouts_locked(struct libusb_context *ctx)
return 0; return 0;
/* get current time */ /* 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) if (r < 0)
return r; return r;
@ -2077,13 +2088,19 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv)
struct pollfd *fds = NULL; struct pollfd *fds = NULL;
int i = -1; int i = -1;
int timeout_ms; int timeout_ms;
int special_event;
/* prevent attempts to recursively handle events (e.g. calling into /* prevent attempts to recursively handle events (e.g. calling into
* libusb_handle_events() from within a hotplug or transfer callback) */ * libusb_handle_events() from within a hotplug or transfer callback) */
usbi_mutex_lock(&ctx->event_data_lock);
r = 0;
if (usbi_handling_events(ctx)) if (usbi_handling_events(ctx))
return LIBUSB_ERROR_BUSY; r = LIBUSB_ERROR_BUSY;
usbi_start_event_handling(ctx); 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: /* 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) { if (ctx->event_flags & USBI_EVENT_POLLFDS_MODIFIED) {
usbi_dbg("poll fds modified, reallocating"); usbi_dbg("poll fds modified, reallocating");
if (ctx->pollfds) { free(ctx->pollfds);
free(ctx->pollfds); ctx->pollfds = NULL;
ctx->pollfds = NULL;
}
/* sanity check - it is invalid for a context to have fewer than the /* sanity check - it is invalid for a context to have fewer than the
* required internal fds (memory corruption?) */ * required internal fds (memory corruption?) */
@ -2138,6 +2153,7 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv)
} }
fds = ctx->pollfds; fds = ctx->pollfds;
nfds = ctx->pollfds_cnt; nfds = ctx->pollfds_cnt;
usbi_inc_fds_ref(fds, nfds);
usbi_mutex_unlock(&ctx->event_data_lock); usbi_mutex_unlock(&ctx->event_data_lock);
timeout_ms = (int)(tv->tv_sec * 1000) + (tv->tv_usec / 1000); 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) if (tv->tv_usec % 1000)
timeout_ms++; timeout_ms++;
redo_poll:
usbi_dbg("poll() %d fds with timeout in %dms", nfds, timeout_ms); usbi_dbg("poll() %d fds with timeout in %dms", nfds, timeout_ms);
r = usbi_poll(fds, nfds, timeout_ms); r = usbi_poll(fds, nfds, timeout_ms);
usbi_dbg("poll() returned %d", r); usbi_dbg("poll() returned %d", r);
if (r == 0) { if (r == 0) {
r = handle_timeouts(ctx); r = handle_timeouts(ctx);
goto done; goto done;
} } else if (r == -1 && errno == EINTR) {
else if (r == -1 && errno == EINTR) {
r = LIBUSB_ERROR_INTERRUPTED; r = LIBUSB_ERROR_INTERRUPTED;
goto done; goto done;
} } else if (r < 0) {
else if (r < 0) {
usbi_err(ctx, "poll failed %d err=%d", r, errno); usbi_err(ctx, "poll failed %d err=%d", r, errno);
r = LIBUSB_ERROR_IO; r = LIBUSB_ERROR_IO;
goto done; goto done;
} }
special_event = 0;
/* fds[0] is always the event pipe */ /* fds[0] is always the event pipe */
if (fds[0].revents) { if (fds[0].revents) {
libusb_hotplug_message *message = NULL; struct list_head hotplug_msgs;
struct usbi_transfer *itransfer; struct usbi_transfer *itransfer;
int hotplug_cb_deregistered = 0;
int ret = 0; int ret = 0;
list_init(&hotplug_msgs);
usbi_dbg("caught a fish on the event pipe"); usbi_dbg("caught a fish on the event pipe");
/* take the the event data lock while processing events */ /* take the the event data lock while processing events */
@ -2186,6 +2200,12 @@ redo_poll:
ctx->event_flags &= ~USBI_EVENT_USER_INTERRUPT; 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 */ /* check if someone is closing a device */
if (ctx->device_close) if (ctx->device_close)
usbi_dbg("someone is closing a device"); usbi_dbg("someone is closing a device");
@ -2193,9 +2213,7 @@ redo_poll:
/* check for any pending hotplug messages */ /* check for any pending hotplug messages */
if (!list_empty(&ctx->hotplug_msgs)) { if (!list_empty(&ctx->hotplug_msgs)) {
usbi_dbg("hotplug message received"); usbi_dbg("hotplug message received");
special_event = 1; list_cut(&hotplug_msgs, &ctx->hotplug_msgs);
message = list_first_entry(&ctx->hotplug_msgs, libusb_hotplug_message, list);
list_del(&message->list);
} }
/* complete any pending transfers */ /* complete any pending transfers */
@ -2203,7 +2221,7 @@ redo_poll:
itransfer = list_first_entry(&ctx->completed_transfers, struct usbi_transfer, completed_list); itransfer = list_first_entry(&ctx->completed_transfers, struct usbi_transfer, completed_list);
list_del(&itransfer->completed_list); list_del(&itransfer->completed_list);
usbi_mutex_unlock(&ctx->event_data_lock); usbi_mutex_unlock(&ctx->event_data_lock);
ret = usbi_backend->handle_transfer_completion(itransfer); ret = usbi_backend.handle_transfer_completion(itransfer);
if (ret) if (ret)
usbi_err(ctx, "backend handle_transfer_completion failed with error %d", ret); usbi_err(ctx, "backend handle_transfer_completion failed with error %d", ret);
usbi_mutex_lock(&ctx->event_data_lock); usbi_mutex_lock(&ctx->event_data_lock);
@ -2215,14 +2233,21 @@ redo_poll:
usbi_mutex_unlock(&ctx->event_data_lock); usbi_mutex_unlock(&ctx->event_data_lock);
/* process the hotplug message, if any */ if (hotplug_cb_deregistered)
if (message) { 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); usbi_hotplug_match(ctx, message->device, message->event);
/* the device left, dereference the device */ /* the device left, dereference the device */
if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == message->event) if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == message->event)
libusb_unref_device(message->device); libusb_unref_device(message->device);
list_del(&message->list);
free(message); free(message);
} }
@ -2233,7 +2258,7 @@ redo_poll:
} }
if (0 == --r) if (0 == --r)
goto handled; goto done;
} }
#ifdef USBI_TIMERFD_AVAILABLE #ifdef USBI_TIMERFD_AVAILABLE
@ -2242,7 +2267,6 @@ redo_poll:
/* timerfd indicates that a timeout has expired */ /* timerfd indicates that a timeout has expired */
int ret; int ret;
usbi_dbg("timerfd triggered"); usbi_dbg("timerfd triggered");
special_event = 1;
ret = handle_timerfd_trigger(ctx); ret = handle_timerfd_trigger(ctx);
if (ret < 0) { if (ret < 0) {
@ -2252,22 +2276,17 @@ redo_poll:
} }
if (0 == --r) if (0 == --r)
goto handled; goto done;
} }
#endif #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) if (r)
usbi_err(ctx, "backend handle_events failed with error %d", 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: done:
usbi_end_event_handling(ctx); usbi_end_event_handling(ctx);
usbi_dec_fds_ref(fds, nfds);
return r; return r;
} }
@ -2583,7 +2602,7 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx,
return 0; 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) { if (r < 0) {
usbi_err(ctx, "failed to read monotonic clock, errno=%d", errno); usbi_err(ctx, "failed to read monotonic clock, errno=%d", errno);
return 0; return 0;
@ -2595,7 +2614,7 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx,
timerclear(tv); timerclear(tv);
} else { } else {
timersub(&next_timeout, &cur_tv, tv); 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; return 1;
@ -2752,15 +2771,12 @@ out:
* Since version 1.0.20, \ref LIBUSB_API_VERSION >= 0x01000104 * 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, * 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 * \param pollfds the list of libusb_pollfd structures to free
*/ */
void API_EXPORTED libusb_free_pollfds(const struct libusb_pollfd **pollfds) void API_EXPORTED libusb_free_pollfds(const struct libusb_pollfd **pollfds)
{ {
if (!pollfds)
return;
free((void *)pollfds); 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_TRANSFER_TO_LIBUSB_TRANSFER(to_cancel));
usbi_mutex_lock(&to_cancel->lock); 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_mutex_unlock(&to_cancel->lock);
usbi_handle_transfer_completion(to_cancel, LIBUSB_TRANSFER_NO_DEVICE); usbi_handle_transfer_completion(to_cancel, LIBUSB_TRANSFER_NO_DEVICE);
} }

View File

@ -126,10 +126,10 @@ EXPORTS
libusb_interrupt_transfer@24 = libusb_interrupt_transfer libusb_interrupt_transfer@24 = libusb_interrupt_transfer
libusb_kernel_driver_active libusb_kernel_driver_active
libusb_kernel_driver_active@8 = 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
libusb_lock_event_waiters@4 = 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
libusb_open@8 = libusb_open libusb_open@8 = libusb_open
libusb_open_device_with_vid_pid libusb_open_device_with_vid_pid
@ -148,12 +148,16 @@ EXPORTS
libusb_set_configuration@8 = libusb_set_configuration libusb_set_configuration@8 = libusb_set_configuration
libusb_set_debug libusb_set_debug
libusb_set_debug@8 = 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
libusb_set_interface_alt_setting@12 = libusb_set_interface_alt_setting libusb_set_interface_alt_setting@12 = libusb_set_interface_alt_setting
libusb_setlocale libusb_set_option
libusb_setlocale@4 = libusb_setlocale _libusb_set_option = libusb_set_option
libusb_set_pollfd_notifiers libusb_set_pollfd_notifiers
libusb_set_pollfd_notifiers@16 = libusb_set_pollfd_notifiers libusb_set_pollfd_notifiers@16 = libusb_set_pollfd_notifiers
libusb_setlocale
libusb_setlocale@4 = libusb_setlocale
libusb_strerror libusb_strerror
libusb_strerror@4 = libusb_strerror libusb_strerror@4 = libusb_strerror
libusb_submit_transfer libusb_submit_transfer
@ -164,10 +168,10 @@ EXPORTS
libusb_transfer_set_stream_id@8 = libusb_transfer_set_stream_id libusb_transfer_set_stream_id@8 = libusb_transfer_set_stream_id
libusb_try_lock_events libusb_try_lock_events
libusb_try_lock_events@4 = 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
libusb_unlock_event_waiters@4 = 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
libusb_unref_device@4 = libusb_unref_device libusb_unref_device@4 = libusb_unref_device
libusb_wait_for_event libusb_wait_for_event

View File

@ -3,7 +3,7 @@
* Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com> * Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com>
* Copyright © 2007-2008 Daniel Drake <dsd@gentoo.org> * Copyright © 2007-2008 Daniel Drake <dsd@gentoo.org>
* Copyright © 2012 Pete Batard <pete@akeo.ie> * Copyright © 2012 Pete Batard <pete@akeo.ie>
* Copyright © 2012 Nathan Hjelm <hjelmn@cs.unm.edu> * Copyright © 2012-2018 Nathan Hjelm <hjelmn@cs.unm.edu>
* For more information, please visit: http://libusb.info * For more information, please visit: http://libusb.info
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
@ -54,13 +54,19 @@ typedef unsigned __int32 uint32_t;
#include <sys/types.h> #include <sys/types.h>
#endif #endif
#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__) #if defined(__linux__) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__)
#include <sys/time.h> #include <sys/time.h>
#endif #endif
#include <time.h> #include <time.h>
#include <limits.h> #include <limits.h>
#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 /* '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 * undefine it so as not to break the current libusb API, because
* libusb_config_descriptor has an 'interface' member * libusb_config_descriptor has an 'interface' member
@ -79,6 +85,8 @@ typedef unsigned __int32 uint32_t;
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
#define LIBUSB_DEPRECATED_FOR(f) \ #define LIBUSB_DEPRECATED_FOR(f) \
__attribute__((deprecated("Use " #f " instead"))) __attribute__((deprecated("Use " #f " instead")))
#elif __GNUC__ >= 3
#define LIBUSB_DEPRECATED_FOR(f) __attribute__((deprecated))
#else #else
#define LIBUSB_DEPRECATED_FOR(f) #define LIBUSB_DEPRECATED_FOR(f)
#endif /* __GNUC__ */ #endif /* __GNUC__ */
@ -141,7 +149,7 @@ typedef unsigned __int32 uint32_t;
* Internally, LIBUSB_API_VERSION is defined as follows: * Internally, LIBUSB_API_VERSION is defined as follows:
* (libusb major << 24) | (libusb minor << 16) | (16 bit incremental) * (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 */ /* The following is kept for compatibility, but will be deprecated in the future */
#define LIBUSBX_API_VERSION LIBUSB_API_VERSION #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. */ * it will store them here, should you wish to parse them. */
const unsigned char *extra; 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; int extra_length;
}; };
@ -619,7 +627,7 @@ struct libusb_interface_descriptor {
* it will store them here, should you wish to parse them. */ * it will store them here, should you wish to parse them. */
const unsigned char *extra; 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; int extra_length;
}; };
@ -631,7 +639,8 @@ struct libusb_interface {
* by the num_altsetting field. */ * by the num_altsetting field. */
const struct libusb_interface_descriptor *altsetting; 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; int num_altsetting;
}; };
@ -678,7 +687,7 @@ struct libusb_config_descriptor {
* descriptors, it will store them here, should you wish to parse them. */ * descriptors, it will store them here, should you wish to parse them. */
const unsigned char *extra; 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; int extra_length;
}; };
@ -729,13 +738,7 @@ struct libusb_bos_dev_capability_descriptor {
/** Device Capability type */ /** Device Capability type */
uint8_t bDevCapabilityType; uint8_t bDevCapabilityType;
/** Device Capability data (bLength - 3 bytes) */ /** Device Capability data (bLength - 3 bytes) */
uint8_t dev_capability_data uint8_t dev_capability_data[ZERO_SIZED_ARRAY];
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
[] /* valid C99 code */
#else
[0] /* non-standard, but usually working code */
#endif
;
}; };
/** \ingroup libusb_desc /** \ingroup libusb_desc
@ -760,13 +763,7 @@ struct libusb_bos_descriptor {
uint8_t bNumDeviceCaps; uint8_t bNumDeviceCaps;
/** bNumDeviceCap Device Capability Descriptors */ /** bNumDeviceCap Device Capability Descriptors */
struct libusb_bos_dev_capability_descriptor *dev_capability struct libusb_bos_dev_capability_descriptor *dev_capability[ZERO_SIZED_ARRAY];
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
[] /* valid C99 code */
#else
[0] /* non-standard, but usually working code */
#endif
;
}; };
/** \ingroup libusb_desc /** \ingroup libusb_desc
@ -927,7 +924,7 @@ struct libusb_version {
* sessions allows for your program to use two libraries (or dynamically * sessions allows for your program to use two libraries (or dynamically
* load two modules) which both independently use libusb. This will prevent * load two modules) which both independently use libusb. This will prevent
* interference between the individual libusb users - for example * 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 * libusb_exit() will not destroy resources that the other user is still
* using. * using.
* *
@ -987,6 +984,9 @@ enum libusb_speed {
/** The device is operating at super speed (5000MBit/s). */ /** The device is operating at super speed (5000MBit/s). */
LIBUSB_SPEED_SUPER = 4, LIBUSB_SPEED_SUPER = 4,
/** The device is operating at super speed plus (10000MBit/s). */
LIBUSB_SPEED_SUPER_PLUS = 5,
}; };
/** \ingroup libusb_dev /** \ingroup libusb_dev
@ -1135,19 +1135,19 @@ enum libusb_transfer_status {
* libusb_transfer.flags values */ * libusb_transfer.flags values */
enum libusb_transfer_flags { enum libusb_transfer_flags {
/** Report short frames as errors */ /** 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(). /** Automatically free() transfer buffer during libusb_free_transfer().
* Note that buffers allocated with libusb_dev_mem_alloc() should not * Note that buffers allocated with libusb_dev_mem_alloc() should not
* be attempted freed in this way, since free() is not an appropriate * be attempted freed in this way, since free() is not an appropriate
* way to release such memory. */ * 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. /** Automatically call libusb_free_transfer() after callback returns.
* If this flag is set, it is illegal to call libusb_free_transfer() * 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 * from your transfer callback, as this will result in a double-free
* when this flag is acted upon. */ * 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 /** Terminate transfers that are a multiple of the endpoint's
* wMaxPacketSize with an extra zero length packet. This is useful * wMaxPacketSize with an extra zero length packet. This is useful
@ -1172,7 +1172,7 @@ enum libusb_transfer_flags {
* *
* Available since libusb-1.0.9. * Available since libusb-1.0.9.
*/ */
LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1 << 3, LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1U << 3,
}; };
/** \ingroup libusb_asyncio /** \ingroup libusb_asyncio
@ -1220,7 +1220,7 @@ struct libusb_transfer {
/** Type of the endpoint from \ref libusb_transfer_type */ /** Type of the endpoint from \ref libusb_transfer_type */
unsigned char 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. */ * timeout. */
unsigned int timeout; unsigned int timeout;
@ -1233,7 +1233,7 @@ struct libusb_transfer {
* to determine if errors occurred. */ * to determine if errors occurred. */
enum libusb_transfer_status status; enum libusb_transfer_status status;
/** Length of the data buffer */ /** Length of the data buffer. Must be non-negative. */
int length; int length;
/** Actual length of data that was transferred. Read-only, and only for /** Actual length of data that was transferred. Read-only, and only for
@ -1252,17 +1252,11 @@ struct libusb_transfer {
unsigned char *buffer; unsigned char *buffer;
/** Number of isochronous packets. Only used for I/O with isochronous /** Number of isochronous packets. Only used for I/O with isochronous
* endpoints. */ * endpoints. Must be non-negative. */
int num_iso_packets; int num_iso_packets;
/** Isochronous packet descriptors, for isochronous transfers only. */ /** Isochronous packet descriptors, for isochronous transfers only. */
struct libusb_iso_packet_descriptor iso_packet_desc struct libusb_iso_packet_descriptor iso_packet_desc[ZERO_SIZED_ARRAY];
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
[] /* valid C99 code */
#else
[0] /* non-standard, but usually working code */
#endif
;
}; };
/** \ingroup libusb_misc /** \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_NONE (0) : no messages ever printed by the library (default)
* - LIBUSB_LOG_LEVEL_ERROR (1) : error messages are printed to stderr * - 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_WARNING (2) : warning and error messages are printed to stderr
* - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stdout, warning * - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stderr
* and error messages are printed to stderr * - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stderr
* - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stdout,
* warnings and errors to stderr
*/ */
enum libusb_log_level { enum libusb_log_level {
LIBUSB_LOG_LEVEL_NONE = 0, LIBUSB_LOG_LEVEL_NONE = 0,
LIBUSB_LOG_LEVEL_ERROR, LIBUSB_LOG_LEVEL_ERROR = 1,
LIBUSB_LOG_LEVEL_WARNING, LIBUSB_LOG_LEVEL_WARNING = 2,
LIBUSB_LOG_LEVEL_INFO, LIBUSB_LOG_LEVEL_INFO = 3,
LIBUSB_LOG_LEVEL_DEBUG, 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); int LIBUSB_CALL libusb_init(libusb_context **ctx);
void LIBUSB_CALL libusb_exit(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_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); const struct libusb_version * LIBUSB_CALL libusb_get_version(void);
int LIBUSB_CALL libusb_has_capability(uint32_t capability); int LIBUSB_CALL libusb_has_capability(uint32_t capability);
const char * LIBUSB_CALL libusb_error_name(int errcode); 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, int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev,
unsigned char endpoint); 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); int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **dev_handle);
void LIBUSB_CALL libusb_close(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); 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 */ * Flags for hotplug events */
typedef enum { typedef enum {
/** Default value when not using any flags. */ /** 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. */ /** 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; } libusb_hotplug_flag;
/** \ingroup libusb_hotplug /** \ingroup libusb_hotplug
@ -1905,12 +1924,12 @@ typedef enum {
* Hotplug events */ * Hotplug events */
typedef enum { typedef enum {
/** A device has been plugged in and is ready to use */ /** 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. /** 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 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 */ * 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; } libusb_hotplug_event;
/** \ingroup libusb_hotplug /** \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, void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx,
libusb_hotplug_callback_handle callback_handle); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -24,7 +24,7 @@
#include <config.h> #include <config.h>
#include <stdlib.h> #include <stdlib.h>
#include <assert.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <time.h> #include <time.h>
@ -39,6 +39,20 @@
#include "libusb.h" #include "libusb.h"
#include "version.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: /* Inside the libusb code, mark all public functions as follows:
* return_type API_EXPORTED function_name(params) { ... } * return_type API_EXPORTED function_name(params) { ... }
* But if the function returns a pointer, mark it as follows: * But if the function returns a pointer, mark it as follows:
@ -48,6 +62,16 @@
*/ */
#define API_EXPORTED LIBUSB_CALL DEFAULT_VISIBILITY #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 #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -139,6 +163,19 @@ static inline void list_del(struct list_head *entry)
entry->next = entry->prev = NULL; 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) static inline void *usbi_reallocf(void *ptr, size_t size)
{ {
void *ret = realloc(ptr, 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); \ const typeof( ((type *)0)->member ) *mptr = (ptr); \
(type *)( (char *)mptr - offsetof(type,member) );}) (type *)( (char *)mptr - offsetof(type,member) );})
#ifndef CLAMP
#define CLAMP(val, min, max) ((val) < (min) ? (min) : ((val) > (max) ? (max) : (val)))
#endif
#ifndef MIN #ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif #endif
@ -175,29 +215,33 @@ static inline void *usbi_reallocf(void *ptr, size_t size)
} while (0) } while (0)
#endif #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, 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, 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_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_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) \ #define LOG_BODY(ctxt, level) \
{ \ { \
va_list args; \ 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); \ usbi_log_v(ctxt, level, "", format, args); \
va_end(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, ...) static inline void usbi_err(struct libusb_context *ctx, const char *format, ...)
LOG_BODY(ctx, LIBUSB_LOG_LEVEL_ERROR) 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, ...) static inline void usbi_dbg(const char *format, ...)
LOG_BODY(NULL, LIBUSB_LOG_LEVEL_DEBUG) LOG_BODY(NULL, LIBUSB_LOG_LEVEL_DEBUG)
#endif /* !defined(_MSC_VER) || _MSC_VER >= 1400 */ #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) \ #define USBI_GET_CONTEXT(ctx) \
do { \ do { \
@ -254,8 +300,11 @@ extern struct libusb_context *usbi_default_context;
struct pollfd; struct pollfd;
struct libusb_context { struct libusb_context {
int debug; #if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
enum libusb_log_level debug;
int debug_fixed; int debug_fixed;
libusb_log_cb log_handler;
#endif
/* internal event pipe, used for signalling occurrence of an internal event. */ /* internal event pipe, used for signalling occurrence of an internal event. */
int event_pipe[2]; int event_pipe[2];
@ -270,6 +319,7 @@ struct libusb_context {
/* A list of registered hotplug callbacks */ /* A list of registered hotplug callbacks */
struct list_head hotplug_cbs; struct list_head hotplug_cbs;
libusb_hotplug_callback_handle next_hotplug_cb_handle;
usbi_mutex_t hotplug_cbs_lock; usbi_mutex_t hotplug_cbs_lock;
/* this is a list of in-flight transfer handles, sorted by timeout /* this is a list of in-flight transfer handles, sorted by timeout
@ -331,14 +381,19 @@ struct libusb_context {
#endif #endif
struct list_head list; struct list_head list;
PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY];
}; };
enum usbi_event_flags { enum usbi_event_flags {
/* The list of pollfds has been modified */ /* 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 */ /* 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 */ /* Macros for managing event handling state */
@ -383,17 +438,7 @@ struct libusb_device {
struct libusb_device_descriptor device_descriptor; struct libusb_device_descriptor device_descriptor;
int attached; int attached;
unsigned char os_priv PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY];
#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
}; };
struct libusb_device_handle { struct libusb_device_handle {
@ -404,17 +449,8 @@ struct libusb_device_handle {
struct list_head list; struct list_head list;
struct libusb_device *dev; struct libusb_device *dev;
int auto_detach_kernel_driver; int auto_detach_kernel_driver;
unsigned char os_priv
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY];
[] /* valid C99 code */
#else
[0] /* non-standard, but usually working code */
#endif
#if defined(OS_SUNOS)
__attribute__ ((aligned (8)));
#else
;
#endif
}; };
enum { enum {
@ -459,24 +495,24 @@ struct usbi_transfer {
enum usbi_transfer_state_flags { enum usbi_transfer_state_flags {
/* Transfer successfully submitted by backend */ /* Transfer successfully submitted by backend */
USBI_TRANSFER_IN_FLIGHT = 1 << 0, USBI_TRANSFER_IN_FLIGHT = 1U << 0,
/* Cancellation was requested via libusb_cancel_transfer() */ /* 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 */ /* 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 { enum usbi_transfer_timeout_flags {
/* Set by backend submit_transfer() if the OS handles timeout */ /* 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 */ /* The transfer timeout has been handled */
USBI_TRANSFER_TIMEOUT_HANDLED = 1 << 1, USBI_TRANSFER_TIMEOUT_HANDLED = 1U << 1,
/* The transfer timeout was successfully processed */ /* 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) \ #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) 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) return ((unsigned char *)transfer) + sizeof(struct usbi_transfer)
+ sizeof(struct libusb_transfer) + sizeof(struct libusb_transfer)
+ (transfer->num_iso_packets + ((size_t)transfer->num_iso_packets
* sizeof(struct libusb_iso_packet_descriptor)); * sizeof(struct libusb_iso_packet_descriptor));
} }
@ -540,19 +577,6 @@ int usbi_clear_event(struct libusb_context *ctx);
#include "os/poll_windows.h" #include "os/poll_windows.h"
#endif #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 { struct usbi_pollfd {
/* must come first */ /* must come first */
struct libusb_pollfd pollfd; struct libusb_pollfd pollfd;
@ -573,13 +597,7 @@ void usbi_remove_pollfd(struct libusb_context *ctx, int fd);
struct discovered_devs { struct discovered_devs {
size_t len; size_t len;
size_t capacity; size_t capacity;
struct libusb_device *devices struct libusb_device *devices[ZERO_SIZED_ARRAY];
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
[] /* valid C99 code */
#else
[0] /* non-standard, but usually working code */
#endif
;
}; };
struct discovered_devs *discovered_devs_append( struct discovered_devs *discovered_devs_append(
@ -612,7 +630,17 @@ struct usbi_os_backend {
* *
* This function is called when the user deinitializes the library. * 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 /* Enumerate all the USB devices on the system, returning them in a list
* of discovered devices. * of discovered devices.
@ -685,6 +713,34 @@ struct usbi_os_backend {
*/ */
void (*hotplug_poll)(void); 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 /* Open a device for I/O and other USB operations. The device handle
* is preallocated for you, you can retrieve the device in question * is preallocated for you, you can retrieve the device in question
* through handle->dev. * through handle->dev.
@ -1115,6 +1171,11 @@ struct usbi_os_backend {
clockid_t (*get_timerfd_clockid)(void); clockid_t (*get_timerfd_clockid)(void);
#endif #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. /* Number of bytes to reserve for per-device private backend data.
* This private data area is accessible through the "os_priv" field of * This private data area is accessible through the "os_priv" field of
* struct libusb_device. */ * struct libusb_device. */
@ -1132,21 +1193,7 @@ struct usbi_os_backend {
size_t transfer_priv_size; size_t transfer_priv_size;
}; };
#if defined(OS_WINDOWS) extern const struct usbi_os_backend usbi_backend;
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 struct list_head active_contexts_list; extern struct list_head active_contexts_list;
extern usbi_mutex_static_t active_contexts_lock; extern usbi_mutex_static_t active_contexts_lock;

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
/* /*
* darwin backend for libusb 1.0 * darwin backend for libusb 1.0
* Copyright © 2008-2015 Nathan Hjelm <hjelmn@users.sourceforge.net> * Copyright © 2008-2019 Nathan Hjelm <hjelmn@users.sourceforge.net>
* Copyright © 2019 Google LLC. All rights reserved.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -20,6 +21,8 @@
#if !defined(LIBUSB_DARWIN_H) #if !defined(LIBUSB_DARWIN_H)
#define LIBUSB_DARWIN_H #define LIBUSB_DARWIN_H
#include <stdbool.h>
#include "libusbi.h" #include "libusbi.h"
#include <IOKit/IOTypes.h> #include <IOKit/IOTypes.h>
@ -28,37 +31,58 @@
#include <IOKit/IOCFPlugIn.h> #include <IOKit/IOCFPlugIn.h>
/* IOUSBInterfaceInferface */ /* 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 usb_interface_t IOUSBInterfaceInterface700
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID700 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID700
#define InterfaceVersion 700 #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 usb_interface_t IOUSBInterfaceInterface550
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID550 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID550
#define InterfaceVersion 550 #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 usb_interface_t IOUSBInterfaceInterface500
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID500 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID500
#define InterfaceVersion 500 #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 usb_interface_t IOUSBInterfaceInterface300
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID300 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID300
#define InterfaceVersion 300 #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 usb_interface_t IOUSBInterfaceInterface245
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID245 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID245
#define InterfaceVersion 245 #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 usb_interface_t IOUSBInterfaceInterface220
#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220
@ -66,43 +90,57 @@
#else #else
#error "IOUSBFamily is too old. Please upgrade your OS" #error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target"
#endif #endif
/* IOUSBDeviceInterface */ /* 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 usb_device_t IOUSBDeviceInterface500
#define DeviceInterfaceID kIOUSBDeviceInterfaceID500 #define DeviceInterfaceID kIOUSBDeviceInterfaceID500
#define DeviceVersion 500 #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 usb_device_t IOUSBDeviceInterface320
#define DeviceInterfaceID kIOUSBDeviceInterfaceID320 #define DeviceInterfaceID kIOUSBDeviceInterfaceID320
#define DeviceVersion 320 #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 usb_device_t IOUSBDeviceInterface300
#define DeviceInterfaceID kIOUSBDeviceInterfaceID300 #define DeviceInterfaceID kIOUSBDeviceInterfaceID300
#define DeviceVersion 300 #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 usb_device_t IOUSBDeviceInterface245
#define DeviceInterfaceID kIOUSBDeviceInterfaceID245 #define DeviceInterfaceID kIOUSBDeviceInterfaceID245
#define DeviceVersion 245 #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 usb_device_t IOUSBDeviceInterface197
#define DeviceInterfaceID kIOUSBDeviceInterfaceID197 #define DeviceInterfaceID kIOUSBDeviceInterfaceID197
#define DeviceVersion 197 #define DeviceVersion 197
#else #else
#error "IOUSBFamily is too old. Please upgrade your OS" #error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target"
#endif #endif
@ -120,13 +158,14 @@ struct darwin_cached_device {
UInt32 location; UInt32 location;
UInt64 parent_session; UInt64 parent_session;
UInt64 session; UInt64 session;
UInt16 address; USBDeviceAddress address;
char sys_path[21]; char sys_path[21];
usb_device_t **device; usb_device_t **device;
int open_count; int open_count;
UInt8 first_config, active_config, port; UInt8 first_config, active_config, port;
int can_enumerate; int can_enumerate;
int refcount; int refcount;
bool in_reenumerate;
}; };
struct darwin_device_priv { struct darwin_device_priv {
@ -134,7 +173,7 @@ struct darwin_device_priv {
}; };
struct darwin_device_handle_priv { struct darwin_device_handle_priv {
int is_open; bool is_open;
CFRunLoopSourceRef cfSource; CFRunLoopSourceRef cfSource;
struct darwin_interface { struct darwin_interface {

View File

@ -243,7 +243,7 @@ USBDeviceHandle::~USBDeviceHandle()
if (fRawFD > 0) if (fRawFD > 0)
close(fRawFD); close(fRawFD);
for(int i = 0; i < 32; i++) { for(int i = 0; i < 32; i++) {
if (fClaimedInterfaces & (1 << i)) if (fClaimedInterfaces & (1U << i))
ReleaseInterface(i); ReleaseInterface(i);
} }
delete_sem(fTransfersSem); delete_sem(fTransfersSem);
@ -256,7 +256,7 @@ USBDeviceHandle::ClaimInterface(int inumber)
{ {
int status = fUSBDevice->ClaimInterface(inumber); int status = fUSBDevice->ClaimInterface(inumber);
if (status == LIBUSB_SUCCESS) if (status == LIBUSB_SUCCESS)
fClaimedInterfaces |= (1 << inumber); fClaimedInterfaces |= (1U << inumber);
return status; return status;
} }
@ -264,7 +264,7 @@ int
USBDeviceHandle::ReleaseInterface(int inumber) USBDeviceHandle::ReleaseInterface(int inumber)
{ {
fUSBDevice->ReleaseInterface(inumber); fUSBDevice->ReleaseInterface(inumber);
fClaimedInterfaces &= ~(1 << inumber); fClaimedInterfaces &= ~(1U << inumber);
return LIBUSB_SUCCESS; return LIBUSB_SUCCESS;
} }
@ -388,15 +388,15 @@ int USBDevice::ClaimInterface(int interface)
{ {
if (interface > ActiveConfiguration()->number_interfaces) if (interface > ActiveConfiguration()->number_interfaces)
return LIBUSB_ERROR_NOT_FOUND; return LIBUSB_ERROR_NOT_FOUND;
if (fClaimedInterfaces & (1 << interface)) if (fClaimedInterfaces & (1U << interface))
return LIBUSB_ERROR_BUSY; return LIBUSB_ERROR_BUSY;
fClaimedInterfaces |= (1 << interface); fClaimedInterfaces |= (1U << interface);
return LIBUSB_SUCCESS; return LIBUSB_SUCCESS;
} }
int USBDevice::ReleaseInterface(int interface) int USBDevice::ReleaseInterface(int interface)
{ {
fClaimedInterfaces &= ~(1 << interface); fClaimedInterfaces &= ~(1U << interface);
return LIBUSB_SUCCESS; return LIBUSB_SUCCESS;
} }

View File

@ -29,6 +29,9 @@
USBRoster gUsbRoster; USBRoster gUsbRoster;
int32 gInitCount = 0; int32 gInitCount = 0;
static int haiku_get_config_descriptor(struct libusb_device *, uint8_t,
unsigned char *, size_t, int *);
static int static int
haiku_init(struct libusb_context *ctx) haiku_init(struct libusb_context *ctx)
{ {
@ -38,8 +41,9 @@ haiku_init(struct libusb_context *ctx)
} }
static void static void
haiku_exit(void) haiku_exit(struct libusb_context *ctx)
{ {
UNUSED(ctx);
if (atomic_add(&gInitCount, -1) == 1) if (atomic_add(&gInitCount, -1) == 1)
gUsbRoster.Stop(); 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) haiku_get_active_config_descriptor(struct libusb_device *device, unsigned char *buffer, size_t len, int *host_endian)
{ {
USBDevice *dev = *((USBDevice **)device->os_priv); USBDevice *dev = *((USBDevice **)device->os_priv);
const usb_configuration_descriptor *act_config = dev->ActiveConfiguration(); return haiku_get_config_descriptor(device, dev->ActiveConfigurationIndex(), buffer, len, host_endian);
if (len > act_config->total_length)
return LIBUSB_ERROR_OVERFLOW;
memcpy(buffer, act_config, len);
*host_endian = 0;
return LIBUSB_SUCCESS;
} }
static int 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"); usbi_err(DEVICE_CTX(device), "failed getting configuration descriptor");
return LIBUSB_ERROR_INVALID_PARAM; return LIBUSB_ERROR_INVALID_PARAM;
} }
if (len > config->total_length) if (len > config->total_length) {
len = config->total_length; len = config->total_length;
}
memcpy(buffer, config, len); memcpy(buffer, config, len);
*host_endian = 0; *host_endian = 0;
return len; return len;
@ -195,56 +195,59 @@ haiku_clock_gettime(int clkid, struct timespec *tp)
return LIBUSB_ERROR_INVALID_PARAM; return LIBUSB_ERROR_INVALID_PARAM;
} }
const struct usbi_os_backend haiku_usb_raw_backend = { const struct usbi_os_backend usbi_backend = {
/*.name =*/ "Haiku usbfs", .name = "Haiku usbfs",
/*.caps =*/ 0, .caps = 0,
/*.init =*/ haiku_init, .init = haiku_init,
/*.exit =*/ haiku_exit, .exit = haiku_exit,
/*.get_device_list =*/ NULL, .set_option = NULL,
/*.hotplug_poll =*/ NULL, .get_device_list = NULL,
/*.open =*/ haiku_open, .hotplug_poll = NULL,
/*.close =*/ haiku_close, .wrap_sys_device = NULL,
/*.get_device_descriptor =*/ haiku_get_device_descriptor, .open = haiku_open,
/*.get_active_config_descriptor =*/ haiku_get_active_config_descriptor, .close = haiku_close,
/*.get_config_descriptor =*/ haiku_get_config_descriptor, .get_device_descriptor = haiku_get_device_descriptor,
/*.get_config_descriptor_by_value =*/ NULL, .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, .get_configuration = NULL,
/*.set_configuration =*/ haiku_set_configuration, .set_configuration = haiku_set_configuration,
/*.claim_interface =*/ haiku_claim_interface, .claim_interface = haiku_claim_interface,
/*.release_interface =*/ haiku_release_interface, .release_interface = haiku_release_interface,
/*.set_interface_altsetting =*/ haiku_set_altsetting, .set_interface_altsetting = haiku_set_altsetting,
/*.clear_halt =*/ NULL, .clear_halt = NULL,
/*.reset_device =*/ NULL, .reset_device = NULL,
/*.alloc_streams =*/ NULL, .alloc_streams = NULL,
/*.free_streams =*/ NULL, .free_streams = NULL,
/*.dev_mem_alloc =*/ NULL, .dev_mem_alloc = NULL,
/*.dev_mem_free =*/ NULL, .dev_mem_free = NULL,
/*.kernel_driver_active =*/ NULL, .kernel_driver_active = NULL,
/*.detach_kernel_driver =*/ NULL, .detach_kernel_driver = NULL,
/*.attach_kernel_driver =*/ NULL, .attach_kernel_driver = NULL,
/*.destroy_device =*/ NULL, .destroy_device = NULL,
/*.submit_transfer =*/ haiku_submit_transfer, .submit_transfer = haiku_submit_transfer,
/*.cancel_transfer =*/ haiku_cancel_transfer, .cancel_transfer = haiku_cancel_transfer,
/*.clear_transfer_priv =*/ haiku_clear_transfer_priv, .clear_transfer_priv = haiku_clear_transfer_priv,
/*.handle_events =*/ NULL, .handle_events = NULL,
/*.handle_transfer_completion =*/ haiku_handle_transfer_completion, .handle_transfer_completion = haiku_handle_transfer_completion,
/*.clock_gettime =*/ haiku_clock_gettime, .clock_gettime = haiku_clock_gettime,
#ifdef USBI_TIMERFD_AVAILABLE #ifdef USBI_TIMERFD_AVAILABLE
/*.get_timerfd_clockid =*/ NULL, .get_timerfd_clockid = NULL,
#endif #endif
/*.device_priv_size =*/ sizeof(USBDevice *), .context_priv_size = 0,
/*.device_handle_priv_size =*/ sizeof(USBDeviceHandle *), .device_priv_size = sizeof(USBDevice *),
/*.transfer_priv_size =*/ sizeof(USBTransfer *), .device_handle_priv_size = sizeof(USBDeviceHandle *),
.transfer_priv_size = sizeof(USBTransfer *),
}; };

View File

@ -45,24 +45,33 @@
#define NL_GROUP_KERNEL 1 #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 linux_netlink_socket = -1;
static int netlink_control_pipe[2] = { -1, -1 }; static int netlink_control_pipe[2] = { -1, -1 };
static pthread_t libusb_linux_event_thread; static pthread_t libusb_linux_event_thread;
static void *linux_netlink_event_thread_main(void *arg); 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; int flags;
#if defined(FD_CLOEXEC) #if defined(FD_CLOEXEC)
flags = fcntl(fd, F_GETFD); /* Make sure the netlink socket file descriptor is marked as CLOEXEC */
if (flags == -1) { if (!(socktype & SOCK_CLOEXEC)) {
usbi_err(NULL, "failed to get netlink fd flags (%d)", errno); flags = fcntl(fd, F_GETFD);
return -1; 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) { if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
usbi_err(NULL, "failed to set netlink fd flags (%d)", errno); usbi_err(NULL, "failed to set netlink fd flags (%d)", errno);
return -1; return -1;
@ -70,13 +79,14 @@ static int set_fd_cloexec_nb(int fd)
} }
#endif #endif
flags = fcntl(fd, F_GETFL); /* Make sure the netlink socket is non-blocking */
if (flags == -1) { if (!(socktype & SOCK_NONBLOCK)) {
usbi_err(NULL, "failed to get netlink fd status flags (%d)", errno); flags = fcntl(fd, F_GETFL);
return -1; 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) { if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
usbi_err(NULL, "failed to set netlink fd status flags (%d)", errno); usbi_err(NULL, "failed to set netlink fd status flags (%d)", errno);
return -1; return -1;
@ -89,21 +99,15 @@ static int set_fd_cloexec_nb(int fd)
int linux_netlink_start_event_monitor(void) int linux_netlink_start_event_monitor(void)
{ {
struct sockaddr_nl sa_nl = { .nl_family = AF_NETLINK, .nl_groups = NL_GROUP_KERNEL }; 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 opt = 1;
int ret; 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); linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT);
if (linux_netlink_socket == -1 && errno == EINVAL) { if (linux_netlink_socket == -1 && errno == EINVAL) {
usbi_dbg("failed to create netlink socket of type %d, attempting SOCK_RAW", socktype); 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) { if (linux_netlink_socket == -1) {
@ -111,7 +115,7 @@ int linux_netlink_start_event_monitor(void)
goto err; goto err;
} }
ret = set_fd_cloexec_nb(linux_netlink_socket); ret = set_fd_cloexec_nb(linux_netlink_socket, socktype);
if (ret == -1) if (ret == -1)
goto err_close_socket; goto err_close_socket;
@ -162,7 +166,7 @@ int linux_netlink_stop_event_monitor(void)
/* Write some dummy data to the control pipe and /* Write some dummy data to the control pipe and
* wait for the thread to exit */ * 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) if (r <= 0)
usbi_warn(NULL, "netlink control pipe signal failed"); 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) static void *linux_netlink_event_thread_main(void *arg)
{ {
char dummy; char dummy;
ssize_t r; int r;
ssize_t nb;
struct pollfd fds[] = { struct pollfd fds[] = {
{ .fd = netlink_control_pipe[0], { .fd = netlink_control_pipe[0],
.events = POLLIN }, .events = POLLIN },
@ -368,11 +373,15 @@ static void *linux_netlink_event_thread_main(void *arg)
usbi_dbg("netlink event thread entering"); 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) { if (fds[0].revents & POLLIN) {
/* activity on control pipe, read the byte and exit */ /* activity on control pipe, read the byte and exit */
r = usbi_read(netlink_control_pipe[0], &dummy, sizeof(dummy)); nb = read(netlink_control_pipe[0], &dummy, sizeof(dummy));
if (r <= 0) if (nb <= 0)
usbi_warn(NULL, "netlink control pipe read failed"); usbi_warn(NULL, "netlink control pipe read failed");
break; break;
} }

View File

@ -82,17 +82,33 @@ int linux_udev_start_event_monitor(void)
udev_monitor_fd = udev_monitor_get_fd(udev_monitor); 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, /* Some older versions of udev are not non-blocking by default,
* so make sure this is set */ * so make sure this is set */
r = fcntl(udev_monitor_fd, F_GETFL); r = fcntl(udev_monitor_fd, F_GETFL);
if (r == -1) { 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; goto err_free_monitor;
} }
r = fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK); if (!(r & O_NONBLOCK)) {
if (r) { if (fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK) == -1) {
usbi_err(NULL, "setting udev monitor fd flags (%d)", errno); usbi_err(NULL, "setting udev monitor fd status flags (%d)", errno);
goto err_free_monitor; goto err_free_monitor;
}
} }
r = usbi_pipe(udev_control_pipe); 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 /* Write some dummy data to the control pipe and
* wait for the thread to exit */ * 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) { if (r <= 0) {
usbi_warn(NULL, "udev control pipe signal failed"); usbi_warn(NULL, "udev control pipe signal failed");
} }
@ -162,6 +178,7 @@ static void *linux_udev_event_thread_main(void *arg)
{ {
char dummy; char dummy;
int r; int r;
ssize_t nb;
struct udev_device* udev_dev; struct udev_device* udev_dev;
struct pollfd fds[] = { struct pollfd fds[] = {
{.fd = udev_control_pipe[0], {.fd = udev_control_pipe[0],
@ -172,11 +189,15 @@ static void *linux_udev_event_thread_main(void *arg)
usbi_dbg("udev event thread entering."); 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) { if (fds[0].revents & POLLIN) {
/* activity on control pipe, read the byte and exit */ /* activity on control pipe, read the byte and exit */
r = usbi_read(udev_control_pipe[0], &dummy, sizeof(dummy)); nb = read(udev_control_pipe[0], &dummy, sizeof(dummy));
if (r <= 0) { if (nb <= 0) {
usbi_warn(NULL, "udev control pipe read failed"); usbi_warn(NULL, "udev control pipe read failed");
} }
break; 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, 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) 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); udev_enumerate_scan_devices(enumerator);
devices = udev_enumerate_get_list_entry(enumerator); devices = udev_enumerate_get_list_entry(enumerator);
entry = NULL;
udev_list_entry_foreach(entry, devices) { udev_list_entry_foreach(entry, devices) {
const char *path = udev_list_entry_get_name(entry); const char *path = udev_list_entry_get_name(entry);
uint8_t busnum = 0, devaddr = 0; uint8_t busnum = 0, devaddr = 0;

View File

@ -81,6 +81,19 @@ static const char *usbfs_path = NULL;
/* use usbdev*.* device names in /dev instead of the usbfs bus directories */ /* use usbdev*.* device names in /dev instead of the usbfs bus directories */
static int usbdev_names = 0; 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 /* 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 * 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 * 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); static int linux_default_scan_devices (struct libusb_context *ctx);
#endif #endif
struct kernel_version {
int major;
int minor;
int sublevel;
};
struct linux_device_priv { struct linux_device_priv {
char *sysfs_dir; char *sysfs_dir;
unsigned char *descriptors; unsigned char *descriptors;
@ -146,6 +165,7 @@ struct linux_device_priv {
struct linux_device_handle_priv { struct linux_device_handle_priv {
int fd; int fd;
int fd_removed; int fd_removed;
int fd_keep;
uint32_t caps; uint32_t caps;
}; };
@ -180,6 +200,16 @@ struct linux_transfer_priv {
int iso_packet_offset; 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) static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
{ {
struct libusb_context *ctx = DEVICE_CTX(dev); 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", snprintf(path, PATH_MAX, "%s/%03d/%03d",
usbfs_path, dev->bus_number, dev->device_address); usbfs_path, dev->bus_number, dev->device_address);
fd = open(path, mode); fd = _open(path, mode);
if (fd != -1) if (fd != -1)
return fd; /* Success */ 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.*/ /* Wait 10ms for USB device path creation.*/
nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL); nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL);
fd = open(path, mode); fd = _open(path, mode);
if (fd != -1) if (fd != -1)
return fd; /* Success */ 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 /* 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 * 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. */ * simply assume /dev/bus/usb rather then making libusb_init fail.
#if defined(USE_UDEV) * 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) if (ret == NULL)
ret = "/dev/bus/usb"; ret = "/dev/bus/usb";
#endif #endif
@ -342,39 +374,59 @@ static clockid_t find_monotonic_clock(void)
return CLOCK_REALTIME; 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; struct utsname uts;
int atoms, kmajor, kminor, ksublevel; int atoms;
if (uname(&uts) < 0) if (uname(&uts) < 0) {
return -1; usbi_err(ctx, "uname failed, errno %d", errno);
atoms = sscanf(uts.release, "%d.%d.%d", &kmajor, &kminor, &ksublevel);
if (atoms < 1)
return -1; 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; return 1;
if (kmajor < major) else if (ver->major < major)
return 0; return 0;
/* kmajor == major */ /* kmajor == major */
if (atoms < 2) if (ver->minor == -1 && ver->sublevel == -1)
return 0 == minor && 0 == sublevel; return 0 == minor && 0 == sublevel;
if (kminor > minor) else if (ver->minor > minor)
return 1; return 1;
if (kminor < minor) else if (ver->minor < minor)
return 0; return 0;
/* kminor == minor */ /* kminor == minor */
if (atoms < 3) if (ver->sublevel == -1)
return 0 == sublevel; return 0 == sublevel;
return ksublevel >= sublevel; return ver->sublevel >= sublevel;
} }
static int op_init(struct libusb_context *ctx) static int op_init(struct libusb_context *ctx)
{ {
struct kernel_version kversion;
struct stat statbuf; struct stat statbuf;
int r; int r;
@ -387,13 +439,17 @@ static int op_init(struct libusb_context *ctx)
if (monotonic_clkid == -1) if (monotonic_clkid == -1)
monotonic_clkid = find_monotonic_clock(); 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) { if (supports_flag_bulk_continuation == -1) {
/* bulk continuation URB flag available from Linux 2.6.32 */ /* bulk continuation URB flag available from Linux 2.6.32 */
supports_flag_bulk_continuation = kernel_version_ge(2,6,32); supports_flag_bulk_continuation = kernel_version_ge(&kversion,2,6,32);
if (supports_flag_bulk_continuation == -1) {
usbi_err(ctx, "error checking for bulk continuation support");
return LIBUSB_ERROR_OTHER;
}
} }
if (supports_flag_bulk_continuation) if (supports_flag_bulk_continuation)
@ -401,32 +457,31 @@ static int op_init(struct libusb_context *ctx)
if (-1 == supports_flag_zero_packet) { if (-1 == supports_flag_zero_packet) {
/* zero length packet URB flag fixed since Linux 2.6.31 */ /* zero length packet URB flag fixed since Linux 2.6.31 */
supports_flag_zero_packet = kernel_version_ge(2,6,31); supports_flag_zero_packet = kernel_version_ge(&kversion,2,6,31);
if (-1 == supports_flag_zero_packet) {
usbi_err(ctx, "error checking for zero length packet support");
return LIBUSB_ERROR_OTHER;
}
} }
if (supports_flag_zero_packet) if (supports_flag_zero_packet)
usbi_dbg("zero length packet flag supported"); 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) { if (-1 == sysfs_has_descriptors) {
/* sysfs descriptors has all descriptors since Linux 2.6.26 */ /* sysfs descriptors has all descriptors since Linux 2.6.26 */
sysfs_has_descriptors = kernel_version_ge(2,6,26); sysfs_has_descriptors = kernel_version_ge(&kversion,2,6,26);
if (-1 == sysfs_has_descriptors) {
usbi_err(ctx, "error checking for sysfs descriptors");
return LIBUSB_ERROR_OTHER;
}
} }
if (-1 == sysfs_can_relate_devices) { if (-1 == sysfs_can_relate_devices) {
/* sysfs has busnum since Linux 2.6.22 */ /* sysfs has busnum since Linux 2.6.22 */
sysfs_can_relate_devices = kernel_version_ge(2,6,22); sysfs_can_relate_devices = kernel_version_ge(&kversion,2,6,22);
if (-1 == sysfs_can_relate_devices) {
usbi_err(ctx, "error checking for sysfs busnum");
return LIBUSB_ERROR_OTHER;
}
} }
if (sysfs_can_relate_devices || sysfs_has_descriptors) { if (sysfs_can_relate_devices || sysfs_has_descriptors) {
@ -463,8 +518,9 @@ static int op_init(struct libusb_context *ctx)
return r; 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); usbi_mutex_static_lock(&linux_hotplug_startstop_lock);
assert(init_count != 0); assert(init_count != 0);
if (!--init_count) { if (!--init_count) {
@ -478,8 +534,10 @@ static int linux_start_event_monitor(void)
{ {
#if defined(USE_UDEV) #if defined(USE_UDEV)
return linux_udev_start_event_monitor(); return linux_udev_start_event_monitor();
#else #elif !defined(__ANDROID__)
return linux_netlink_start_event_monitor(); return linux_netlink_start_event_monitor();
#else
return LIBUSB_SUCCESS;
#endif #endif
} }
@ -487,20 +545,22 @@ static int linux_stop_event_monitor(void)
{ {
#if defined(USE_UDEV) #if defined(USE_UDEV)
return linux_udev_stop_event_monitor(); return linux_udev_stop_event_monitor();
#else #elif !defined(__ANDROID__)
return linux_netlink_stop_event_monitor(); return linux_netlink_stop_event_monitor();
#else
return LIBUSB_SUCCESS;
#endif #endif
} }
static int linux_scan_devices(struct libusb_context *ctx) static int linux_scan_devices(struct libusb_context *ctx)
{ {
int ret; int ret = 0;
usbi_mutex_static_lock(&linux_hotplug_lock); usbi_mutex_static_lock(&linux_hotplug_lock);
#if defined(USE_UDEV) #if defined(USE_UDEV)
ret = linux_udev_scan_devices(ctx); ret = linux_udev_scan_devices(ctx);
#else #elif !defined(__ANDROID__)
ret = linux_default_scan_devices(ctx); ret = linux_default_scan_devices(ctx);
#endif #endif
@ -513,7 +573,7 @@ static void op_hotplug_poll(void)
{ {
#if defined(USE_UDEV) #if defined(USE_UDEV)
linux_udev_hotplug_poll(); linux_udev_hotplug_poll();
#else #elif !defined(__ANDROID__)
linux_netlink_hotplug_poll(); linux_netlink_hotplug_poll();
#endif #endif
} }
@ -526,7 +586,7 @@ static int _open_sysfs_attr(struct libusb_device *dev, const char *attr)
snprintf(filename, PATH_MAX, "%s/%s/%s", snprintf(filename, PATH_MAX, "%s/%s/%s",
SYSFS_DEVICE_PATH, priv->sysfs_dir, attr); SYSFS_DEVICE_PATH, priv->sysfs_dir, attr);
fd = open(filename, O_RDONLY); fd = _open(filename, O_RDONLY);
if (fd < 0) { if (fd < 0) {
usbi_err(DEVICE_CTX(dev), usbi_err(DEVICE_CTX(dev),
"open %s failed ret=%d errno=%d", filename, fd, errno); "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]; char filename[PATH_MAX];
FILE *f; FILE *f;
int r, value; int fd, r, value;
snprintf(filename, PATH_MAX, "%s/%s/%s", SYSFS_DEVICE_PATH, snprintf(filename, PATH_MAX, "%s/%s/%s", SYSFS_DEVICE_PATH,
devname, attr); devname, attr);
f = fopen(filename, "r"); fd = _open(filename, O_RDONLY);
if (f == NULL) { if (fd == -1) {
if (errno == ENOENT) { if (errno == ENOENT) {
/* File doesn't exist. Assume the device has been /* File doesn't exist. Assume the device has been
disconnected (see trac ticket #70). */ disconnected (see trac ticket #70). */
@ -557,6 +617,13 @@ static int __read_sysfs_attr(struct libusb_context *ctx,
return LIBUSB_ERROR_IO; 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); r = fscanf(f, "%d", &value);
fclose(f); fclose(f);
if (r != 1) { 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); 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); memcpy(buffer, priv->descriptors, DEVICE_DESC_LENGTH);
return 0; 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, int linux_get_device_address (struct libusb_context *ctx, int detached,
uint8_t *busnum, uint8_t *devaddr,const char *dev_node, 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; int sysfs_attr;
ssize_t r;
usbi_dbg("getting address for device: %s detached: %d", sys_name, detached); 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 /* can't use sysfs to read the bus and device number if the
* device has been detached */ * device has been detached */
if (!sysfs_can_relate_devices || detached || NULL == sys_name) { 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) { if (NULL == dev_node) {
return LIBUSB_ERROR_OTHER; 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); sscanf (dev_node, "/dev/bus/usb/%hhu/%hhu", busnum, devaddr);
} else if (!strncmp(dev_node, "/proc/bus/usb", 13)) { } else if (!strncmp(dev_node, "/proc/bus/usb", 13)) {
sscanf (dev_node, "/proc/bus/usb/%hhu/%hhu", busnum, devaddr); sscanf (dev_node, "/proc/bus/usb/%hhu/%hhu", busnum, devaddr);
} else {
return LIBUSB_ERROR_OTHER;
} }
return LIBUSB_SUCCESS; return LIBUSB_SUCCESS;
@ -696,9 +774,11 @@ static int seek_to_next_descriptor(struct libusb_context *ctx,
} }
/* Return offset to next config */ /* 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) 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; struct libusb_config_descriptor config;
if (size == 0) 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 * config descriptor with verified bLength fields, with descriptors
* with an invalid bLength removed. * 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, int next = seek_to_next_descriptor(ctx, LIBUSB_DT_CONFIG,
buffer, size); buffer, size);
if (next == LIBUSB_ERROR_NOT_FOUND) 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, static int op_get_config_descriptor_by_value(struct libusb_device *dev,
uint8_t value, unsigned char **buffer, int *host_endian) uint8_t value, unsigned char **buffer, int *host_endian)
{ {
struct libusb_context *ctx = DEVICE_CTX(dev);
struct linux_device_priv *priv = _device_priv(dev); struct linux_device_priv *priv = _device_priv(dev);
unsigned char *descriptors = priv->descriptors; unsigned char *descriptors = priv->descriptors;
int size = priv->descriptors_len; 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" */ /* Seek till the config is found, or till "EOF" */
while (1) { while (1) {
int next = seek_to_next_config(ctx, descriptors, size); int next = seek_to_next_config(dev, descriptors, size);
if (next < 0) if (next < 0)
return next; return next;
config = (struct libusb_config_descriptor *)descriptors; 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, static int op_get_active_config_descriptor(struct libusb_device *dev,
unsigned char *buffer, size_t len, int *host_endian) unsigned char *buffer, size_t len, int *host_endian)
{ {
struct linux_device_priv *priv = _device_priv(dev);
int r, config; int r, config;
unsigned char *config_desc; unsigned char *config_desc;
if (sysfs_can_relate_devices) { if (priv->sysfs_dir && sysfs_can_relate_devices) {
r = sysfs_get_active_config(dev, &config); r = sysfs_get_active_config(dev, &config);
if (r < 0) if (r < 0)
return r; return r;
} else { } else {
/* Use cached bConfigurationValue */ /* Use cached bConfigurationValue */
struct linux_device_priv *priv = _device_priv(dev);
config = priv->active_config; config = priv->active_config;
} }
if (config == -1) if (config == -1)
@ -806,7 +885,7 @@ static int op_get_active_config_descriptor(struct libusb_device *dev,
if (r < 0) if (r < 0)
return r; return r;
len = MIN(len, r); len = MIN(len, (size_t)r);
memcpy(buffer, config_desc, len); memcpy(buffer, config_desc, len);
return 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" */ /* Seek till the config is found, or till "EOF" */
for (i = 0; ; i++) { 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) if (r < 0)
return r; return r;
if (i == config_index) if (i == config_index)
@ -836,7 +915,7 @@ static int op_get_config_descriptor(struct libusb_device *dev,
descriptors += r; descriptors += r;
} }
len = MIN(len, r); len = MIN(len, (size_t)r);
memcpy(buffer, descriptors, len); memcpy(buffer, descriptors, len);
return 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, 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 linux_device_priv *priv = _device_priv(dev);
struct libusb_context *ctx = DEVICE_CTX(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 12: dev->speed = LIBUSB_SPEED_FULL; break;
case 480: dev->speed = LIBUSB_SPEED_HIGH; break; case 480: dev->speed = LIBUSB_SPEED_HIGH; break;
case 5000: dev->speed = LIBUSB_SPEED_SUPER; break; case 5000: dev->speed = LIBUSB_SPEED_SUPER; break;
case 10000: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break;
default: default:
usbi_warn(DEVICE_CTX(dev), "Unknown device speed: %d Mbps", speed); 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 */ /* cache descriptors in memory */
if (sysfs_has_descriptors) if (sysfs_dir && sysfs_has_descriptors) {
fd = _open_sysfs_attr(dev, "descriptors"); fd = _open_sysfs_attr(dev, "descriptors");
else } else if (wrapped_fd < 0) {
fd = _get_usbfs_fd(dev, O_RDONLY, 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) if (fd < 0)
return fd; return fd;
@ -930,11 +1018,12 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum,
priv->descriptors = usbi_reallocf(priv->descriptors, priv->descriptors = usbi_reallocf(priv->descriptors,
descriptors_size); descriptors_size);
if (!priv->descriptors) { if (!priv->descriptors) {
close(fd); if (fd != wrapped_fd)
close(fd);
return LIBUSB_ERROR_NO_MEM; return LIBUSB_ERROR_NO_MEM;
} }
/* usbfs has holes in the file */ /* usbfs has holes in the file */
if (!sysfs_has_descriptors) { if (!(sysfs_dir && sysfs_has_descriptors)) {
memset(priv->descriptors + priv->descriptors_len, memset(priv->descriptors + priv->descriptors_len,
0, descriptors_size - 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) { if (r < 0) {
usbi_err(ctx, "read descriptor failed ret=%d errno=%d", usbi_err(ctx, "read descriptor failed ret=%d errno=%d",
fd, errno); fd, errno);
close(fd); if (fd != wrapped_fd)
close(fd);
return LIBUSB_ERROR_IO; return LIBUSB_ERROR_IO;
} }
priv->descriptors_len += r; priv->descriptors_len += r;
} while (priv->descriptors_len == descriptors_size); } while (priv->descriptors_len == descriptors_size);
close(fd); if (fd != wrapped_fd)
close(fd);
if (priv->descriptors_len < DEVICE_DESC_LENGTH) { if (priv->descriptors_len < DEVICE_DESC_LENGTH) {
usbi_err(ctx, "short descriptor read (%d)", 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; return LIBUSB_ERROR_IO;
} }
if (sysfs_can_relate_devices) if (sysfs_dir && sysfs_can_relate_devices)
return LIBUSB_SUCCESS; return LIBUSB_SUCCESS;
/* cache active config */ /* 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) { if (fd < 0) {
/* cannot send a control message to determine the active /* cannot send a control message to determine the active
* config. just assume the first one is 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); r = usbfs_get_active_config(dev, fd);
close(fd); if (wrapped_fd < 0)
close(fd);
return r; return r;
} }
@ -1029,9 +1124,11 @@ retry:
usbi_mutex_lock(&ctx->usb_devs_lock); usbi_mutex_lock(&ctx->usb_devs_lock);
list_for_each_entry(it, &ctx->usb_devs, list, struct libusb_device) { list_for_each_entry(it, &ctx->usb_devs, list, struct libusb_device) {
struct linux_device_priv *priv = _device_priv(it); struct linux_device_priv *priv = _device_priv(it);
if (0 == strcmp (priv->sysfs_dir, parent_sysfs_dir)) { if (priv->sysfs_dir) {
dev->parent_dev = libusb_ref_device(it); if (0 == strcmp (priv->sysfs_dir, parent_sysfs_dir)) {
break; dev->parent_dev = libusb_ref_device(it);
break;
}
} }
} }
usbi_mutex_unlock(&ctx->usb_devs_lock); usbi_mutex_unlock(&ctx->usb_devs_lock);
@ -1080,7 +1177,7 @@ int linux_enumerate_device(struct libusb_context *ctx,
if (!dev) if (!dev)
return LIBUSB_ERROR_NO_MEM; 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) if (r < 0)
goto out; goto out;
r = usbi_sanitize_device(dev); 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; uint8_t busnum, devaddr;
int ret; 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) { if (LIBUSB_SUCCESS != ret) {
return ret; return ret;
} }
@ -1237,11 +1334,12 @@ static int sysfs_get_device_list(struct libusb_context *ctx)
{ {
DIR *devices = opendir(SYSFS_DEVICE_PATH); DIR *devices = opendir(SYSFS_DEVICE_PATH);
struct dirent *entry; struct dirent *entry;
int r = LIBUSB_ERROR_IO; int num_devices = 0;
int num_enumerated = 0;
if (!devices) { if (!devices) {
usbi_err(ctx, "opendir devices failed errno=%d", errno); usbi_err(ctx, "opendir devices failed errno=%d", errno);
return r; return LIBUSB_ERROR_IO;
} }
while ((entry = readdir(devices))) { while ((entry = readdir(devices))) {
@ -1249,16 +1347,23 @@ static int sysfs_get_device_list(struct libusb_context *ctx)
|| strchr(entry->d_name, ':')) || strchr(entry->d_name, ':'))
continue; continue;
num_devices++;
if (sysfs_scan_device(ctx, entry->d_name)) { if (sysfs_scan_device(ctx, entry->d_name)) {
usbi_dbg("failed to enumerate dir entry %s", entry->d_name); usbi_dbg("failed to enumerate dir entry %s", entry->d_name);
continue; continue;
} }
r = 0; num_enumerated++;
} }
closedir(devices); 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) 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 #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); struct linux_device_handle_priv *hpriv = _device_handle_priv(handle);
int r; int r;
hpriv->fd = _get_usbfs_fd(handle->dev, O_RDWR, 0); hpriv->fd = fd;
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;
}
r = ioctl(hpriv->fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps); r = ioctl(fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps);
if (r < 0) { if (r < 0) {
if (errno == ENOTTY) if (errno == ENOTTY)
usbi_dbg("getcap not available"); usbi_dbg("getcap not available");
@ -1314,9 +1405,82 @@ static int op_open(struct libusb_device_handle *handle)
hpriv->caps |= USBFS_CAP_BULK_CONTINUATION; 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) 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; 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() */ /* fd may have already been removed by POLLERR condition in op_handle_events() */
if (!hpriv->fd_removed) if (!hpriv->fd_removed)
usbi_remove_pollfd(HANDLE_CTX(dev_handle), hpriv->fd); 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, static int op_get_configuration(struct libusb_device_handle *handle,
int *config) int *config)
{ {
struct linux_device_priv *priv = _device_priv(handle->dev);
int r; int r;
if (sysfs_can_relate_devices) { if (priv->sysfs_dir && sysfs_can_relate_devices) {
r = sysfs_get_active_config(handle->dev, config); r = sysfs_get_active_config(handle->dev, config);
} else { } else {
r = usbfs_get_active_config(handle->dev, r = usbfs_get_active_config(handle->dev,
_device_handle_priv(handle)->fd); _device_handle_priv(handle)->fd);
if (r == LIBUSB_SUCCESS) if (r == LIBUSB_SUCCESS)
*config = _device_priv(handle->dev)->active_config; *config = priv->active_config;
} }
if (r < 0) if (r < 0)
return r; return r;
@ -1683,10 +1849,7 @@ static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle,
strcpy(dc.driver, "usbfs"); strcpy(dc.driver, "usbfs");
dc.flags = USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER; dc.flags = USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER;
r = ioctl(fd, IOCTL_USBFS_DISCONNECT_CLAIM, &dc); r = ioctl(fd, IOCTL_USBFS_DISCONNECT_CLAIM, &dc);
if (r == 0 || (r != 0 && errno != ENOTTY)) { if (r != 0 && errno != ENOTTY) {
if (r == 0)
return 0;
switch (errno) { switch (errno) {
case EBUSY: case EBUSY:
return LIBUSB_ERROR_BUSY; 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), usbi_err(HANDLE_CTX(handle),
"disconnect-and-claim failed errno %d", errno); "disconnect-and-claim failed errno %d", errno);
return LIBUSB_ERROR_OTHER; return LIBUSB_ERROR_OTHER;
} } else if (r == 0)
return 0;
/* Fallback code for kernels which don't support the /* Fallback code for kernels which don't support the
disconnect-and-claim ioctl */ disconnect-and-claim ioctl */
@ -1971,38 +2135,43 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
struct linux_device_handle_priv *dpriv = struct linux_device_handle_priv *dpriv =
_device_handle_priv(transfer->dev_handle); _device_handle_priv(transfer->dev_handle);
struct usbfs_urb **urbs; struct usbfs_urb **urbs;
size_t alloc_size;
int num_packets = transfer->num_iso_packets; int num_packets = transfer->num_iso_packets;
int i; int num_packets_remaining;
int this_urb_len = 0; int i, j;
int num_urbs = 1; int num_urbs;
int packet_offset = 0;
unsigned int packet_len; unsigned int packet_len;
unsigned int total_len = 0;
unsigned char *urb_buffer = transfer->buffer; unsigned char *urb_buffer = transfer->buffer;
/* usbfs places arbitrary limits on iso URBs. this limit has changed if (num_packets < 1)
* at least three times, and it's difficult to accurately detect which return LIBUSB_ERROR_INVALID_PARAM;
* 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.
*/
/* 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++) { 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; packet_len = transfer->iso_packet_desc[i].length;
if (packet_len > space_remaining) { if (packet_len > max_iso_packet_len) {
num_urbs++; usbi_warn(TRANSFER_CTX(transfer),
this_urb_len = packet_len; "iso packet length of %u bytes exceeds maximum of %u bytes",
/* check that we can actually support this packet length */ packet_len, max_iso_packet_len);
if (this_urb_len > MAX_ISO_BUFFER_LENGTH) return LIBUSB_ERROR_INVALID_PARAM;
return LIBUSB_ERROR_INVALID_PARAM;
} else {
this_urb_len += packet_len;
} }
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)); urbs = calloc(num_urbs, sizeof(*urbs));
if (!urbs) if (!urbs)
@ -2015,31 +2184,15 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
tpriv->iso_packet_offset = 0; tpriv->iso_packet_offset = 0;
/* allocate + initialize each URB with the correct number of packets */ /* 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; struct usbfs_urb *urb;
unsigned int space_remaining_in_urb = MAX_ISO_BUFFER_LENGTH; size_t alloc_size;
int urb_packet_offset = 0;
unsigned char *urb_buffer_orig = urb_buffer;
int j;
int k; 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) 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); urb = calloc(1, alloc_size);
if (!urb) { if (!urb) {
free_iso_urbs(tpriv); free_iso_urbs(tpriv);
@ -2048,10 +2201,10 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
urbs[i] = urb; urbs[i] = urb;
/* populate packet lengths */ /* populate packet lengths */
for (j = 0, k = packet_offset - urb_packet_offset; for (k = 0; k < num_packets_in_urb; j++, k++) {
k < packet_offset; k++, j++) { packet_len = transfer->iso_packet_desc[j].length;
packet_len = transfer->iso_packet_desc[k].length; urb->buffer_length += packet_len;
urb->iso_frame_desc[j].length = packet_len; urb->iso_frame_desc[k].length = packet_len;
} }
urb->usercontext = itransfer; urb->usercontext = itransfer;
@ -2059,8 +2212,11 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
/* FIXME: interface for non-ASAP data? */ /* FIXME: interface for non-ASAP data? */
urb->flags = USBFS_URB_ISO_ASAP; urb->flags = USBFS_URB_ISO_ASAP;
urb->endpoint = transfer->endpoint; urb->endpoint = transfer->endpoint;
urb->number_of_packets = urb_packet_offset; urb->number_of_packets = num_packets_in_urb;
urb->buffer = urb_buffer_orig; urb->buffer = urb_buffer;
urb_buffer += urb->buffer_length;
num_packets_remaining -= num_packets_in_urb;
} }
/* submit URBs */ /* submit URBs */
@ -2073,6 +2229,10 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
usbi_warn(TRANSFER_CTX(transfer), usbi_warn(TRANSFER_CTX(transfer),
"submiturb failed, transfer too large"); "submiturb failed, transfer too large");
r = LIBUSB_ERROR_INVALID_PARAM; 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 { } else {
usbi_err(TRANSFER_CTX(transfer), usbi_err(TRANSFER_CTX(transfer),
"submiturb failed error %d errno=%d", r, errno); "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); USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(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) { switch (transfer->type) {
case LIBUSB_TRANSFER_TYPE_CONTROL: case LIBUSB_TRANSFER_TYPE_CONTROL:
case LIBUSB_TRANSFER_TYPE_BULK: 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); struct linux_device_handle_priv *hpriv = _device_handle_priv(handle);
int r; int r;
struct usbfs_urb *urb; struct usbfs_urb *urb = NULL;
struct usbi_transfer *itransfer; struct usbi_transfer *itransfer;
struct libusb_transfer *transfer; struct libusb_transfer *transfer;
@ -2683,7 +2842,7 @@ static clockid_t op_get_timerfd_clockid(void)
} }
#endif #endif
const struct usbi_os_backend linux_usbfs_backend = { const struct usbi_os_backend usbi_backend = {
.name = "Linux usbfs", .name = "Linux usbfs",
.caps = USBI_CAP_HAS_HID_ACCESS|USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER, .caps = USBI_CAP_HAS_HID_ACCESS|USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER,
.init = op_init, .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 = op_get_config_descriptor,
.get_config_descriptor_by_value = op_get_config_descriptor_by_value, .get_config_descriptor_by_value = op_get_config_descriptor_by_value,
.wrap_sys_device = op_wrap_sys_device,
.open = op_open, .open = op_open,
.close = op_close, .close = op_close,
.get_configuration = op_get_configuration, .get_configuration = op_get_configuration,

View File

@ -81,10 +81,11 @@ struct usbfs_iso_packet_desc {
unsigned int status; unsigned int status;
}; };
#define MAX_ISO_BUFFER_LENGTH 49152 * 128
#define MAX_BULK_BUFFER_LENGTH 16384 #define MAX_BULK_BUFFER_LENGTH 16384
#define MAX_CTRL_BUFFER_LENGTH 4096 #define MAX_CTRL_BUFFER_LENGTH 4096
#define MAX_ISO_PACKETS_PER_URB 128
struct usbfs_urb { struct usbfs_urb {
unsigned char type; unsigned char type;
unsigned char endpoint; 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, int linux_get_device_address (struct libusb_context *ctx, int detached,
uint8_t *busnum, uint8_t *devaddr, const char *dev_node, 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, int linux_enumerate_device(struct libusb_context *ctx,
uint8_t busnum, uint8_t devaddr, const char *sysfs_dir); uint8_t busnum, uint8_t devaddr, const char *sysfs_dir);

View File

@ -86,11 +86,12 @@ static int _sync_control_transfer(struct usbi_transfer *);
static int _sync_gen_transfer(struct usbi_transfer *); static int _sync_gen_transfer(struct usbi_transfer *);
static int _access_endpoint(struct libusb_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", "Synchronous NetBSD backend",
0, 0,
NULL, /* init() */ NULL, /* init() */
NULL, /* exit() */ NULL, /* exit() */
NULL, /* set_option() */
netbsd_get_device_list, netbsd_get_device_list,
NULL, /* hotplug_poll */ NULL, /* hotplug_poll */
netbsd_open, netbsd_open,
@ -131,6 +132,7 @@ const struct usbi_os_backend netbsd_backend = {
netbsd_handle_transfer_completion, netbsd_handle_transfer_completion,
netbsd_clock_gettime, netbsd_clock_gettime,
0, /* context_priv_size */
sizeof(struct device_priv), sizeof(struct device_priv),
sizeof(struct handle_priv), sizeof(struct handle_priv),
0, /* transfer_priv_size */ 0, /* transfer_priv_size */
@ -212,8 +214,9 @@ error:
int int
netbsd_open(struct libusb_device_handle *handle) 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 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); dpriv->fd = open(dpriv->devnode, O_RDWR);
if (dpriv->fd < 0) { if (dpriv->fd < 0) {
@ -222,6 +225,9 @@ netbsd_open(struct libusb_device_handle *handle)
return _errno_to_libusb(errno); 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); usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd);
return (LIBUSB_SUCCESS); return (LIBUSB_SUCCESS);
@ -230,7 +236,6 @@ netbsd_open(struct libusb_device_handle *handle)
void void
netbsd_close(struct libusb_device_handle *handle) 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; struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
usbi_dbg("close: fd %d", dpriv->fd); usbi_dbg("close: fd %d", dpriv->fd);

View File

@ -89,11 +89,12 @@ static int _access_endpoint(struct libusb_transfer *);
static int _bus_open(int); static int _bus_open(int);
const struct usbi_os_backend openbsd_backend = { const struct usbi_os_backend usbi_backend = {
"Synchronous OpenBSD backend", "Synchronous OpenBSD backend",
0, 0,
NULL, /* init() */ NULL, /* init() */
NULL, /* exit() */ NULL, /* exit() */
NULL, /* set_option() */
obsd_get_device_list, obsd_get_device_list,
NULL, /* hotplug_poll */ NULL, /* hotplug_poll */
obsd_open, obsd_open,
@ -134,6 +135,7 @@ const struct usbi_os_backend openbsd_backend = {
obsd_handle_transfer_completion, obsd_handle_transfer_completion,
obsd_clock_gettime, obsd_clock_gettime,
0, /* context_priv_size */
sizeof(struct device_priv), sizeof(struct device_priv),
sizeof(struct handle_priv), sizeof(struct handle_priv),
0, /* transfer_priv_size */ 0, /* transfer_priv_size */
@ -246,7 +248,6 @@ obsd_get_device_list(struct libusb_context * ctx,
int int
obsd_open(struct libusb_device_handle *handle) 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; struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
char devnode[16]; char devnode[16];
@ -270,7 +271,6 @@ obsd_open(struct libusb_device_handle *handle)
void void
obsd_close(struct libusb_device_handle *handle) 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; struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
if (dpriv->devname) { if (dpriv->devname) {

View File

@ -29,25 +29,56 @@
int usbi_pipe(int pipefd[2]) int usbi_pipe(int pipefd[2])
{ {
#if defined(HAVE_PIPE2)
int ret = pipe2(pipefd, O_CLOEXEC);
#else
int ret = pipe(pipefd); int ret = pipe(pipefd);
#endif
if (ret != 0) { if (ret != 0) {
usbi_err(NULL, "failed to create pipe (%d)", errno);
return ret; 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); ret = fcntl(pipefd[1], F_GETFL);
if (ret == -1) { 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; goto err_close_pipe;
} }
ret = fcntl(pipefd[1], F_SETFL, ret | O_NONBLOCK); ret = fcntl(pipefd[1], F_SETFL, ret | O_NONBLOCK);
if (ret != 0) { if (ret == -1) {
usbi_dbg("Failed to set non-blocking on new pipe: %d", errno); usbi_err(NULL, "failed to set pipe fd status flags (%d)", errno);
goto err_close_pipe; goto err_close_pipe;
} }
return 0; return 0;
err_close_pipe: err_close_pipe:
usbi_close(pipefd[0]); close(pipefd[0]);
usbi_close(pipefd[1]); close(pipefd[1]);
return ret; return ret;
} }

View File

@ -8,4 +8,7 @@
int usbi_pipe(int pipefd[2]); 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 */ #endif /* LIBUSB_POLL_POSIX_H */

View File

@ -1,9 +1,6 @@
/* /*
* poll_windows: poll compatibility wrapper for Windows * poll_windows: poll compatibility wrapper for Windows
* Copyright © 2012-2013 RealVNC Ltd. * Copyright © 2017 Chris Dickens <christopher.a.dickens@gmail.com>
* Copyright © 2009-2010 Pete Batard <pete@akeo.ie>
* With contributions from Michael Plante, Orin Eman et al.
* Parts of poll implementation from libusb-win32, by Stephan Meyer et al.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * 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 * - obtain a Windows HANDLE to a file or device that has been opened in
* OVERLAPPED mode * OVERLAPPED mode
* - call usbi_create_fd with this handle to obtain a custom fd. * - 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 * - leave the core functions call the poll routine and flag POLLIN/POLLOUT
* *
* The pipe pollable synchronous I/O works using the overlapped event associated * The pipe pollable synchronous I/O works using the overlapped event associated
@ -42,465 +36,176 @@
*/ */
#include <config.h> #include <config.h>
#include <assert.h>
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "libusbi.h" #include "libusbi.h"
#include "windows_common.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)
// public fd data // public fd data
const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, NULL, NULL, RW_NONE}; const struct winfd INVALID_WINFD = { -1, NULL };
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];
// globals // private data
BOOLEAN is_polling_set = FALSE; struct file_descriptor {
LONG pipe_number = 0; enum fd_type { FD_TYPE_PIPE, FD_TYPE_TRANSFER } type;
static volatile LONG compat_spinlock = 0; OVERLAPPED overlapped;
int refcount;
};
#if !defined(_WIN32_WCE) static usbi_mutex_static_t fd_table_lock = USBI_MUTEX_INITIALIZER;
// CancelIoEx, available on Vista and later only, provides the ability to cancel static struct file_descriptor *fd_table[MAX_FDS];
// 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 inline void setup_cancel_io(void) static struct file_descriptor *create_fd(enum fd_type type)
{ {
HMODULE hKernel32 = GetModuleHandleA("KERNEL32"); struct file_descriptor *fd = calloc(1, sizeof(*fd));
if (hKernel32 != NULL) { if (fd == NULL)
pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED)) return NULL;
GetProcAddress(hKernel32, "CancelIoEx"); fd->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
} if (fd->overlapped.hEvent == NULL) {
usbi_dbg("Will use CancelIo%s for I/O cancellation", free(fd);
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; i<MAX_FDS; i++) {
poll_fd[i] = INVALID_WINFD;
_poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
_poll_fd[i].thread_id = 0;
InitializeCriticalSection(&_poll_fd[i].mutex);
}
is_polling_set = TRUE;
}
InterlockedExchange((LONG *)&compat_spinlock, 0);
}
// Internal function to retrieve the table index (and lock the fd mutex)
static int _fd_to_index_and_lock(int fd)
{
int i;
if (fd < 0)
return -1;
for (i=0; i<MAX_FDS; i++) {
if (poll_fd[i].fd == fd) {
EnterCriticalSection(&_poll_fd[i].mutex);
// fd might have changed before we got to critical
if (poll_fd[i].fd != fd) {
LeaveCriticalSection(&_poll_fd[i].mutex);
continue;
}
return i;
}
}
return -1;
}
static OVERLAPPED *create_overlapped(void)
{
OVERLAPPED *overlapped = (OVERLAPPED*) calloc(1, sizeof(OVERLAPPED));
if (overlapped == NULL) {
return NULL; return NULL;
} }
overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); fd->type = type;
if(overlapped->hEvent == NULL) { fd->refcount = 1;
free (overlapped); return fd;
return NULL;
}
return overlapped;
} }
static void free_overlapped(OVERLAPPED *overlapped) static void free_fd(struct file_descriptor *fd)
{ {
if (overlapped == NULL) CloseHandle(fd->overlapped.hEvent);
return; free(fd);
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; i<MAX_FDS; i++) {
// Cancel any async I/O (handle can be invalid)
cancel_io(i);
// If anything was pending on that I/O, it should be
// terminating, and we should be able to access the fd
// mutex lock before too long
EnterCriticalSection(&_poll_fd[i].mutex);
free_overlapped(poll_fd[i].overlapped);
if (Use_Duplicate_Handles) {
// Close duplicate handle
if (_poll_fd[i].original_handle != INVALID_HANDLE_VALUE) {
CloseHandle(poll_fd[i].handle);
}
}
poll_fd[i] = INVALID_WINFD;
LeaveCriticalSection(&_poll_fd[i].mutex);
DeleteCriticalSection(&_poll_fd[i].mutex);
}
}
InterlockedExchange((LONG *)&compat_spinlock, 0);
} }
/* /*
* Create a fake pipe. * Create both an fd and an OVERLAPPED, so that it can be used with our
* As libusb only uses pipes for signaling, all we need from a pipe is an * polling function
* 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<MAX_FDS; i++) {
if (poll_fd[i].fd < 0) {
EnterCriticalSection(&_poll_fd[i].mutex);
// fd might have been allocated before we got to critical
if (poll_fd[i].fd >= 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
* The handle MUST support overlapped transfers (usually requires CreateFile * The handle MUST support overlapped transfers (usually requires CreateFile
* with FILE_FLAG_OVERLAPPED) * with FILE_FLAG_OVERLAPPED)
* Return a pollable file descriptor struct, or INVALID_WINFD on error * 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 * 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 * 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 * 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 * read and one for write. Using a single R/W fd is unsupported and will
* produce unexpected results * 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 file_descriptor *fd;
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<MAX_FDS; i++) {
if (poll_fd[i].fd < 0) {
EnterCriticalSection(&_poll_fd[i].mutex);
// fd might have been removed before we got to critical
if (poll_fd[i].fd >= 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 winfd wfd; struct winfd wfd;
CHECK_INIT_POLLING; fd = create_fd(FD_TYPE_TRANSFER);
if (fd == NULL)
if (fd < 0)
return INVALID_WINFD; return INVALID_WINFD;
for (i=0; i<MAX_FDS; i++) { usbi_mutex_static_lock(&fd_table_lock);
if (poll_fd[i].fd == fd) { for (wfd.fd = 0; wfd.fd < MAX_FDS; wfd.fd++) {
EnterCriticalSection(&_poll_fd[i].mutex); if (fd_table[wfd.fd] != NULL)
// fd might have been deleted before we got to critical continue;
if (poll_fd[i].fd != fd) { fd_table[wfd.fd] = fd;
LeaveCriticalSection(&_poll_fd[i].mutex); break;
continue;
}
memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
LeaveCriticalSection(&_poll_fd[i].mutex);
return wfd;
}
} }
return INVALID_WINFD; usbi_mutex_static_unlock(&fd_table_lock);
if (wfd.fd == MAX_FDS) {
free_fd(fd);
return INVALID_WINFD;
}
wfd.overlapped = &fd->overlapped;
return wfd;
} }
struct winfd handle_to_winfd(HANDLE handle) int usbi_inc_fds_ref(struct pollfd *fds, unsigned int nfds)
{ {
int i; int n;
struct winfd wfd; usbi_mutex_static_lock(&fd_table_lock);
for (n = 0; n < nfds; ++n) {
CHECK_INIT_POLLING; fd_table[fds[n].fd]->refcount++;
if ((handle == 0) || (handle == INVALID_HANDLE_VALUE))
return INVALID_WINFD;
for (i=0; i<MAX_FDS; i++) {
if (poll_fd[i].handle == handle) {
EnterCriticalSection(&_poll_fd[i].mutex);
// fd might have been deleted before we got to critical
if (poll_fd[i].handle != handle) {
LeaveCriticalSection(&_poll_fd[i].mutex);
continue;
}
memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
LeaveCriticalSection(&_poll_fd[i].mutex);
return wfd;
}
} }
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; int n;
struct winfd wfd; struct file_descriptor *fd;
CHECK_INIT_POLLING; usbi_mutex_static_lock(&fd_table_lock);
for (n = 0; n < nfds; ++n) {
if (overlapped == NULL) fd = fd_table[fds[n].fd];
return INVALID_WINFD; fd->refcount--;
if (fd->refcount == 0)
for (i=0; i<MAX_FDS; i++) { {
if (poll_fd[i].overlapped == overlapped) { if (fd->type == FD_TYPE_PIPE) {
EnterCriticalSection(&_poll_fd[i].mutex); // InternalHigh is our reference count
// fd might have been deleted before we got to critical fd->overlapped.InternalHigh--;
if (poll_fd[i].overlapped != overlapped) { if (fd->overlapped.InternalHigh == 0)
LeaveCriticalSection(&_poll_fd[i].mutex); free_fd(fd);
continue;
} }
memcpy(&wfd, &poll_fd[i], sizeof(struct winfd)); else {
LeaveCriticalSection(&_poll_fd[i].mutex); free_fd(fd);
return wfd; }
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 * POSIX poll equivalent, using Windows OVERLAPPED
* Currently, this function only accepts one of POLLIN or POLLOUT per fd * 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) int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
{ {
unsigned i; HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
int _index, object_index, triggered; DWORD nb_wait_handles = 0;
HANDLE *handles_to_wait_on;
int *handle_to_index;
DWORD nb_handles_to_wait_on = 0;
DWORD ret; DWORD ret;
int nready;
CHECK_INIT_POLLING; nready = check_pollfds(fds, nfds, wait_handles, &nb_wait_handles);
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);
}
// If nothing was triggered, wait on all fds that require it // If nothing was triggered, wait on all fds that require it
if ((timeout != 0) && (triggered == 0) && (nb_handles_to_wait_on != 0)) { if ((nready == 0) && (nb_wait_handles != 0) && (timeout != 0)) {
if (timeout < 0) { ret = WaitForMultipleObjects(nb_wait_handles, wait_handles,
poll_dbg("starting infinite wait for %u handles...", (unsigned int)nb_handles_to_wait_on); FALSE, (timeout < 0) ? INFINITE : (DWORD)timeout);
} else { if (ret < (WAIT_OBJECT_0 + nb_wait_handles)) {
poll_dbg("starting %d ms wait for %u handles...", timeout, (unsigned int)nb_handles_to_wait_on); nready = check_pollfds(fds, nfds, NULL, NULL);
} } else if (ret != WAIT_TIMEOUT) {
ret = WaitForMultipleObjects(nb_handles_to_wait_on, handles_to_wait_on, if (ret == WAIT_FAILED)
FALSE, (timeout<0)?INFINITE:(DWORD)timeout); usbi_err(NULL, "WaitForMultipleObjects failed: %u", (unsigned int)GetLastError());
object_index = ret-WAIT_OBJECT_0; nready = -1;
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
} }
} }
poll_exit: return nready;
if (handles_to_wait_on != NULL) {
free(handles_to_wait_on);
}
if (handle_to_index != NULL) {
free(handle_to_index);
}
return triggered;
} }
/* /*
* close a fake pipe fd * close a fake file descriptor
*/ */
int usbi_close(int fd) int usbi_close(int _fd)
{ {
int _index; struct file_descriptor *fd;
int r = -1;
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) { if (fd->type == FD_TYPE_PIPE) {
errno = EBADF; // InternalHigh is our reference count
} else { fd->overlapped.InternalHigh--;
free_overlapped(poll_fd[_index].overlapped); if (fd->overlapped.InternalHigh == 0)
poll_fd[_index] = INVALID_WINFD; free_fd(fd);
LeaveCriticalSection(&_poll_fd[_index].mutex); }
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) ssize_t usbi_write(int fd, const void *buf, size_t count)
{ {
int _index; int error = EBADF;
UNUSED(buf); UNUSED(buf);
CHECK_INIT_POLLING; if (fd < 0 || fd >= MAX_FDS)
goto err_out;
if (count != sizeof(unsigned char)) { if (count != sizeof(unsigned char)) {
usbi_err(NULL, "this function should only used for signaling"); usbi_err(NULL, "this function should only used for signaling");
return -1; error = EINVAL;
goto err_out;
} }
_index = _fd_to_index_and_lock(fd); usbi_mutex_static_lock(&fd_table_lock);
if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) {
if ( (_index < 0) || (poll_fd[_index].overlapped == NULL) ) { assert(fd_table[fd]->overlapped.Internal == STATUS_PENDING);
errno = EBADF; assert(fd_table[fd]->overlapped.InternalHigh == 2);
if (_index >= 0) { fd_table[fd]->overlapped.Internal = STATUS_WAIT_0;
LeaveCriticalSection(&_poll_fd[_index].mutex); SetEvent(fd_table[fd]->overlapped.hEvent);
} error = 0;
return -1;
} }
usbi_mutex_static_unlock(&fd_table_lock);
poll_dbg("set pipe event (fd = %d, thread = %08X)", _index, (unsigned int)GetCurrentThreadId()); if (error)
SetEvent(poll_fd[_index].overlapped->hEvent); goto err_out;
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++;
LeaveCriticalSection(&_poll_fd[_index].mutex);
return sizeof(unsigned char); 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) ssize_t usbi_read(int fd, void *buf, size_t count)
{ {
int _index; int error = EBADF;
ssize_t r = -1;
UNUSED(buf); UNUSED(buf);
CHECK_INIT_POLLING; if (fd < 0 || fd >= MAX_FDS)
goto err_out;
if (count != sizeof(unsigned char)) { if (count != sizeof(unsigned char)) {
usbi_err(NULL, "this function should only used for signaling"); usbi_err(NULL, "this function should only used for signaling");
return -1; error = EINVAL;
goto err_out;
} }
_index = _fd_to_index_and_lock(fd); usbi_mutex_static_lock(&fd_table_lock);
if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) {
if (_index < 0) { assert(fd_table[fd]->overlapped.Internal == STATUS_WAIT_0);
errno = EBADF; assert(fd_table[fd]->overlapped.InternalHigh == 2);
return -1; 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) { if (error)
usbi_warn(NULL, "waiting for event failed: %u", (unsigned int)GetLastError()); goto err_out;
errno = EIO;
goto out;
}
poll_dbg("clr pipe event (fd = %d, thread = %08X)", _index, (unsigned int)GetCurrentThreadId()); return sizeof(unsigned char);
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;
}
r = sizeof(unsigned char); err_out:
errno = error;
out: return -1;
LeaveCriticalSection(&_poll_fd[_index].mutex);
return r;
} }

View File

@ -2,6 +2,7 @@
* Windows compat: POSIX compatibility wrapper * Windows compat: POSIX compatibility wrapper
* Copyright © 2012-2013 RealVNC Ltd. * Copyright © 2012-2013 RealVNC Ltd.
* Copyright © 2009-2010 Pete Batard <pete@akeo.ie> * Copyright © 2009-2010 Pete Batard <pete@akeo.ie>
* Copyright © 2016-2018 Chris Dickens <christopher.a.dickens@gmail.com>
* With contributions from Michael Plante, Orin Eman et al. * With contributions from Michael Plante, Orin Eman et al.
* Parts of poll implementation from libusb-win32, by Stephan Meyer 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) #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 MAX_FDS 256
#define POLLIN 0x0001 /* There is data to read */ #define POLLIN 0x0001 /* There is data to read */
@ -65,45 +51,28 @@ extern int windows_version;
#define POLLNVAL 0x0020 /* Invalid request: fd not open */ #define POLLNVAL 0x0020 /* Invalid request: fd not open */
struct pollfd { struct pollfd {
int fd; /* file descriptor */ int fd; /* file descriptor */
short events; /* requested events */ short events; /* requested events */
short revents; /* returned 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 { struct winfd {
int fd; // what's exposed to libusb core 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
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)
}; };
extern const struct winfd INVALID_WINFD; extern const struct winfd INVALID_WINFD;
struct winfd usbi_create_fd(void);
int usbi_pipe(int pipefd[2]); int usbi_pipe(int pipefd[2]);
int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout); 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_write(int fd, const void *buf, size_t count);
ssize_t usbi_read(int fd, void *buf, size_t count); ssize_t usbi_read(int fd, void *buf, size_t count);
int usbi_close(int fd); int usbi_close(int fd);
void init_polling(void); int usbi_inc_fds_ref(struct pollfd *fds, unsigned int nfds);
void exit_polling(void); int usbi_dec_fds_ref(struct pollfd *fds, unsigned int nfds);
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);
/* /*
* Timeval operations * Timeval operations

View File

@ -21,6 +21,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/list.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <strings.h> #include <strings.h>
#include <errno.h> #include <errno.h>
@ -28,21 +29,34 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <wait.h>
#include <unistd.h> #include <unistd.h>
#include <aio.h> #include <aio.h>
#include <libdevinfo.h> #include <libdevinfo.h>
#include <sys/nvpair.h>
#include <sys/devctl.h>
#include <sys/usb/clients/ugen/usb_ugen.h> #include <sys/usb/clients/ugen/usb_ugen.h>
#include <errno.h>
#include <sys/usb/usba.h> #include <sys/usb/usba.h>
#include <sys/pci.h> #include <sys/pci.h>
#include "libusbi.h" #include "libusbi.h"
#include "sunos_usb.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 * Backend functions
*/ */
static int sunos_init(struct libusb_context *); 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 *, static int sunos_get_device_list(struct libusb_context *,
struct discovered_devs **); struct discovered_devs **);
static int sunos_open(struct libusb_device_handle *); 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 void sunos_clear_transfer_priv(struct usbi_transfer *);
static int sunos_handle_transfer_completion(struct usbi_transfer *); static int sunos_handle_transfer_completion(struct usbi_transfer *);
static int sunos_clock_gettime(int, struct timespec *); 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 * Private functions
@ -79,20 +249,239 @@ static int sunos_init(struct libusb_context *ctx)
return (LIBUSB_SUCCESS); return (LIBUSB_SUCCESS);
} }
static void sunos_exit(void) static void sunos_exit(struct libusb_context *ctx)
{ {
usbi_dbg(""); 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 static int
sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev) sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev)
{ {
int proplen; int proplen;
int n, *addr, *port_prop; int *i, n, *addr, *port_prop;
char *phypath; char *phypath;
uint8_t *rdata; uint8_t *rdata;
struct libusb_device_descriptor *descr; struct libusb_device_descriptor *descr;
sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv;
char match_str[PATH_MAX];
/* Device descriptors */ /* Device descriptors */
proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, 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); phypath = di_devfs_path(node);
if (phypath) { if (phypath) {
dpriv->phypath = strdup(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); di_devfs_path_free(phypath);
} else { } else {
free(dpriv->raw_cfgdescr); free(dpriv->raw_cfgdescr);
@ -153,13 +546,13 @@ sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev)
} }
/* speed */ /* 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; 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; 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; 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; 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); return (LIBUSB_SUCCESS);
} }
static int static int
sunos_add_devices(di_devlink_t link, void *arg) sunos_add_devices(di_devlink_t link, void *arg)
{ {
struct devlink_cbarg *largs = (struct devlink_cbarg *)arg; struct devlink_cbarg *largs = (struct devlink_cbarg *)arg;
struct node_args *nargs; struct node_args *nargs;
di_node_t myself, pnode; di_node_t myself, dn;
uint64_t session_id = 0; uint64_t session_id = 0;
uint16_t bdf = 0; uint64_t sid = 0;
uint64_t bdf = 0;
struct libusb_device *dev; struct libusb_device *dev;
sunos_dev_priv_t *devpriv; sunos_dev_priv_t *devpriv;
const char *path, *newpath; int n, *j;
int n, i; int i = 0;
int *addr_prop; int *addr_prop;
uint8_t bus_number = 0; uint8_t bus_number = 0;
uint32_t * regbuf = NULL;
uint32_t reg;
nargs = (struct node_args *)largs->nargs; nargs = (struct node_args *)largs->nargs;
myself = largs->myself; myself = largs->myself;
if (nargs->last_ugenpath) {
/* the same node's links */
return (DI_WALK_CONTINUE);
}
/* /*
* Construct session ID. * 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; if (myself == DI_NODE_NIL)
i = 0; return (DI_WALK_CONTINUE);
while (pnode != DI_NODE_NIL) {
if (di_prop_exists(DDI_DEV_T_ANY, pnode, "root-hub") == 1) {
/* walk to root */
uint32_t *regbuf = NULL;
uint32_t reg;
n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode, "reg", dn = myself;
(int **)&regbuf); /* find the root hub */
reg = regbuf[0]; while (di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "root-hub", &j) != 0) {
bdf = (PCI_REG_BUS_G(reg) << 8) | usbi_dbg("find_root_hub:%s", di_devfs_path(dn));
(PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn,
session_id |= (bdf << i * 8); "assigned-address", &addr_prop);
session_id |= ((addr_prop[0] & 0xff) << i++ * 8);
dn = di_parent_node(dn);
}
/* same as 'unit-address' property */ /* dn is the root hub node */
bus_number = n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "reg", (int **)&regbuf);
(PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); 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", usbi_dbg("device bus address=%s:%x, name:%s",
di_bus_addr(pnode), bus_number); di_bus_addr(myself), bus_number, di_node_name(dn));
usbi_dbg("session id org:%lx", session_id);
break;
}
/* 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 */ /* 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); "assigned-address", &addr_prop);
if ((n != 1) || (addr_prop[0] == 0)) { if ((n != 1) || (addr_prop[0] == 0)) {
usbi_dbg("cannot get valid usb_addr"); usbi_dbg("cannot get valid usb_addr");
continue;
return (DI_WALK_CONTINUE);
} }
session_id |= ((addr_prop[0] & 0xff) << i * 8); sid = (session_id << 8) | (addr_prop[0] & 0xff) ;
if (++i > 7) usbi_dbg("session id %lx", sid);
break;
pnode = di_parent_node(pnode); dev = usbi_get_device_by_session_id(nargs->ctx, sid);
}
path = di_devlink_path(link);
dev = usbi_get_device_by_session_id(nargs->ctx, session_id);
if (dev == NULL) {
dev = usbi_alloc_device(nargs->ctx, session_id);
if (dev == NULL) { 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) { if (discovered_devs_append(*(nargs->discdevs), dev) == NULL) {
usbi_dbg("cannot append device"); 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. * hereafter. Front end or app should take care of their ref.
*/ */
libusb_unref_device(dev); libusb_unref_device(dev);
}
usbi_dbg("Device %s %s id=0x%llx, devcount:%d, bdf=%x", usbi_dbg("Device %s %s id=0x%llx, devcount:%d, bdf=%x",
devpriv->ugenpath, path, (uint64_t)session_id, devpriv->ugenpath, di_devfs_path(dn), (uint64_t)sid,
(*nargs->discdevs)->len, bdf); (*nargs->discdevs)->len, bdf);
}
return (DI_WALK_CONTINUE); 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; struct node_args *nargs = (struct node_args *)args;
di_devlink_handle_t devlink_hdl = nargs->dlink_hdl; 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) { while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
minor_path = di_devfs_minor_path(minor); minor_path = di_devfs_minor_path(minor);
arg.nargs = args; arg.nargs = args;
arg.myself = node; arg.myself = node;
arg.minor = minor; arg.minor = minor;
(void) di_devlink_walk(devlink_hdl, (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_PRIMARY_LINK, (void *)&arg, sunos_add_devices);
di_devfs_path_free(minor_path); 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", usbi_dbg("can't find interface for endpoint 0x%02x",
ep_addr); ep_addr);
return (LIBUSB_ERROR_ACCESS); return (EACCES);
} }
/* create filename */ /* create filename */
@ -603,6 +983,11 @@ sunos_open(struct libusb_device_handle *handle)
hpriv->eps[i].statfd = -1; 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) { if ((ret = sunos_usb_open_ep0(hpriv, dpriv)) != LIBUSB_SUCCESS) {
usbi_dbg("fail: %d", ret); usbi_dbg("fail: %d", ret);
return (ret); return (ret);
@ -811,26 +1196,32 @@ sunos_async_callback(union sigval arg)
int ret; int ret;
sunos_dev_handle_priv_t *hpriv; sunos_dev_handle_priv_t *hpriv;
uint8_t ep; uint8_t ep;
libusb_device_handle *dev_handle;
hpriv = (sunos_dev_handle_priv_t *)xfer->dev_handle->os_priv; dev_handle = xfer->dev_handle;
ep = sunos_usb_ep_index(xfer->endpoint);
ret = aio_error(aiocb); /* libusb can forcibly interrupt transfer in do_close() */
if (ret != 0) { if (dev_handle != NULL) {
xfer->status = sunos_usb_get_status(hpriv->eps[ep].statfd); hpriv = (sunos_dev_handle_priv_t *)dev_handle->os_priv;
} else { ep = sunos_usb_ep_index(xfer->endpoint);
xfer->actual_length =
LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)->transferred = ret = aio_error(aiocb);
aio_return(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 static int
@ -975,9 +1366,15 @@ solaris_submit_ctrl_on_default(struct libusb_transfer *transfer)
} }
usbi_dbg("Done: ctrl data bytes %d", ret); 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), ret = usbi_handle_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer),
transfer->status); transfer->status);
usbi_mutex_lock(&LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)->lock);
return (ret); return (ret);
} }
@ -1010,9 +1407,7 @@ void
sunos_destroy_device(struct libusb_device *dev) sunos_destroy_device(struct libusb_device *dev)
{ {
sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv;
usbi_dbg("destroy everyting");
usbi_dbg("");
free(dpriv->raw_cfgdescr); free(dpriv->raw_cfgdescr);
free(dpriv->ugenpath); free(dpriv->ugenpath);
free(dpriv->phypath); free(dpriv->phypath);
@ -1120,8 +1515,6 @@ sunos_handle_transfer_completion(struct usbi_transfer *itransfer)
int int
sunos_clock_gettime(int clkid, struct timespec *tp) sunos_clock_gettime(int clkid, struct timespec *tp)
{ {
usbi_dbg("clock %d", clkid);
if (clkid == USBI_CLOCK_REALTIME) if (clkid == USBI_CLOCK_REALTIME)
return clock_gettime(CLOCK_REALTIME, tp); return clock_gettime(CLOCK_REALTIME, tp);
@ -1254,7 +1647,14 @@ sunos_usb_get_status(int fd)
return (status); 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", .name = "Solaris",
.caps = 0, .caps = 0,
.init = sunos_init, .init = sunos_init,
@ -1276,9 +1676,9 @@ const struct usbi_os_backend sunos_backend = {
.reset_device = sunos_reset_device, /* TODO */ .reset_device = sunos_reset_device, /* TODO */
.alloc_streams = NULL, .alloc_streams = NULL,
.free_streams = NULL, .free_streams = NULL,
.kernel_driver_active = NULL, .kernel_driver_active = sunos_kernel_driver_active,
.detach_kernel_driver = NULL, .detach_kernel_driver = sunos_detach_kernel_driver,
.attach_kernel_driver = NULL, .attach_kernel_driver = sunos_attach_kernel_driver,
.destroy_device = sunos_destroy_device, .destroy_device = sunos_destroy_device,
.submit_transfer = sunos_submit_transfer, .submit_transfer = sunos_submit_transfer,
.cancel_transfer = sunos_cancel_transfer, .cancel_transfer = sunos_cancel_transfer,
@ -1286,6 +1686,9 @@ const struct usbi_os_backend sunos_backend = {
.clear_transfer_priv = sunos_clear_transfer_priv, .clear_transfer_priv = sunos_clear_transfer_priv,
.handle_transfer_completion = sunos_handle_transfer_completion, .handle_transfer_completion = sunos_handle_transfer_completion,
.clock_gettime = sunos_clock_gettime, .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_priv_size = sizeof(sunos_dev_priv_t),
.device_handle_priv_size = sizeof(sunos_dev_handle_priv_t), .device_handle_priv_size = sizeof(sunos_dev_handle_priv_t),
.transfer_priv_size = sizeof(sunos_xfer_priv_t), .transfer_priv_size = sizeof(sunos_xfer_priv_t),

View File

@ -65,6 +65,12 @@ struct devlink_cbarg {
di_minor_t minor; di_minor_t minor;
}; };
typedef struct walk_link {
char *path;
int len;
char **linkpp;
} walk_link_t;
/* AIO callback args */ /* AIO callback args */
struct aio_callback_args{ struct aio_callback_args{
struct libusb_transfer *transfer; struct libusb_transfer *transfer;

View File

@ -29,7 +29,7 @@
# include <unistd.h> # include <unistd.h>
# include <sys/syscall.h> # include <sys/syscall.h>
#elif defined(__APPLE__) #elif defined(__APPLE__)
# include <mach/mach.h> # include <pthread.h>
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
# include <windows.h> # include <windows.h>
#endif #endif
@ -43,7 +43,7 @@ int usbi_cond_timedwait(pthread_cond_t *cond,
struct timespec timeout; struct timespec timeout;
int r; int r;
r = usbi_backend->clock_gettime(USBI_CLOCK_REALTIME, &timeout); r = usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, &timeout);
if (r < 0) if (r < 0)
return r; return r;
@ -59,7 +59,7 @@ int usbi_cond_timedwait(pthread_cond_t *cond,
int usbi_get_tid(void) int usbi_get_tid(void)
{ {
int ret = -1; int ret;
#if defined(__ANDROID__) #if defined(__ANDROID__)
ret = gettid(); ret = gettid();
#elif defined(__linux__) #elif defined(__linux__)
@ -69,10 +69,11 @@ int usbi_get_tid(void)
real thread support. For 5.1 and earlier, -1 is returned. */ real thread support. For 5.1 and earlier, -1 is returned. */
ret = syscall(SYS_getthrid); ret = syscall(SYS_getthrid);
#elif defined(__APPLE__) #elif defined(__APPLE__)
ret = mach_thread_self(); ret = (int)pthread_mach_thread_np(pthread_self());
mach_port_deallocate(mach_task_self(), ret);
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
ret = GetCurrentThreadId(); ret = GetCurrentThreadId();
#else
ret = -1;
#endif #endif
/* TODO: NetBSD thread ID support */ /* TODO: NetBSD thread ID support */
return ret; return ret;

View File

@ -26,32 +26,76 @@
#include <sys/time.h> #include <sys/time.h>
#endif #endif
#define usbi_mutex_static_t pthread_mutex_t #define USBI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
#define USBI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER typedef pthread_mutex_t usbi_mutex_static_t;
#define usbi_mutex_static_lock pthread_mutex_lock static inline void usbi_mutex_static_lock(usbi_mutex_static_t *mutex)
#define usbi_mutex_static_unlock pthread_mutex_unlock {
(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 typedef pthread_mutex_t usbi_mutex_t;
#define usbi_mutex_init(mutex) pthread_mutex_init((mutex), NULL) static inline int usbi_mutex_init(usbi_mutex_t *mutex)
#define usbi_mutex_lock pthread_mutex_lock {
#define usbi_mutex_unlock pthread_mutex_unlock return pthread_mutex_init(mutex, NULL);
#define usbi_mutex_trylock pthread_mutex_trylock }
#define usbi_mutex_destroy pthread_mutex_destroy 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 typedef pthread_cond_t usbi_cond_t;
#define usbi_cond_init(cond) pthread_cond_init((cond), NULL) static inline void usbi_cond_init(pthread_cond_t *cond)
#define usbi_cond_wait pthread_cond_wait {
#define usbi_cond_broadcast pthread_cond_broadcast (void)pthread_cond_init(cond, NULL);
#define usbi_cond_destroy pthread_cond_destroy }
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 typedef pthread_key_t usbi_tls_key_t;
#define usbi_tls_key_create(key) pthread_key_create((key), NULL) static inline void usbi_tls_key_create(usbi_tls_key_t *key)
#define usbi_tls_key_get pthread_getspecific {
#define usbi_tls_key_set pthread_setspecific (void)pthread_key_create(key, NULL);
#define usbi_tls_key_delete pthread_key_delete }
static inline void *usbi_tls_key_get(usbi_tls_key_t key)
int usbi_cond_timedwait(pthread_cond_t *cond, {
pthread_mutex_t *mutex, const struct timeval *tv); 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); int usbi_get_tid(void);

View File

@ -20,189 +20,67 @@
#include <config.h> #include <config.h>
#include <objbase.h>
#include <errno.h> #include <errno.h>
#include "libusbi.h" #include "libusbi.h"
struct usbi_cond_perthread { struct usbi_cond_perthread {
struct list_head list; struct list_head list;
DWORD tid;
HANDLE event; HANDLE event;
}; };
int usbi_mutex_static_lock(usbi_mutex_static_t *mutex) void usbi_mutex_static_lock(usbi_mutex_static_t *mutex)
{ {
if (!mutex) while (InterlockedExchange(mutex, 1L) == 1L)
return EINVAL;
while (InterlockedExchange(mutex, 1) == 1)
SleepEx(0, TRUE); 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->waiters);
list_init(&cond->not_waiting); list_init(&cond->not_waiting);
return 0;
} }
int usbi_cond_destroy(usbi_cond_t *cond) static int usbi_cond_intwait(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,
usbi_mutex_t *mutex, DWORD timeout_ms) usbi_mutex_t *mutex, DWORD timeout_ms)
{ {
struct usbi_cond_perthread *pos; struct usbi_cond_perthread *pos;
int r, found = 0; DWORD r;
DWORD r2, tid = GetCurrentThreadId();
if (!cond || !mutex) // Same assumption as usbi_cond_broadcast() holds
return EINVAL; if (list_empty(&cond->not_waiting)) {
list_for_each_entry(pos, &cond->not_waiting, list, struct usbi_cond_perthread) { pos = malloc(sizeof(*pos));
if(tid == pos->tid) { if (pos == NULL)
found = 1;
break;
}
}
if (!found) {
pos = calloc(1, sizeof(struct usbi_cond_perthread));
if (!pos)
return ENOMEM; // This errno is not POSIX-allowed. return ENOMEM; // This errno is not POSIX-allowed.
pos->tid = tid;
pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset. pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset.
if (!pos->event) { if (pos->event == NULL) {
free(pos); free(pos);
return ENOMEM; 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); list_add(&pos->list, &cond->waiters);
r = usbi_mutex_unlock(mutex); LeaveCriticalSection(mutex);
if (r) r = WaitForSingleObject(pos->event, timeout_ms);
return r; EnterCriticalSection(mutex);
r2 = WaitForSingleObject(pos->event, timeout_ms);
r = usbi_mutex_lock(mutex);
if (r)
return r;
list_del(&pos->list); list_del(&pos->list);
list_add(&pos->list, &cond->not_waiting); list_add(&pos->list, &cond->not_waiting);
if (r2 == WAIT_OBJECT_0) if (r == WAIT_OBJECT_0)
return 0; return 0;
else if (r2 == WAIT_TIMEOUT) else if (r == WAIT_TIMEOUT)
return ETIMEDOUT; return ETIMEDOUT;
else else
return EINVAL; return EINVAL;
} }
// N.B.: usbi_cond_*wait() can also return ENOMEM, even though pthread_cond_*wait cannot! // N.B.: usbi_cond_*wait() can also return ENOMEM, even though pthread_cond_*wait cannot!
int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex)
{ {
@ -221,39 +99,28 @@ int usbi_cond_timedwait(usbi_cond_t *cond,
return usbi_cond_intwait(cond, mutex, millis); 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) // Assumes mutex is locked; this is not in keeping with POSIX spec, but
return EINVAL; // libusb does this anyway, so we simplify by not adding more sync
*key = TlsAlloc(); // primitives to the CV definition!
if (*key == TLS_OUT_OF_INDEXES) struct usbi_cond_perthread *pos;
return ENOMEM;
else list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread)
return 0; 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 (!list_empty(&cond->waiters))
{ return; // (!see above!)
if (TlsSetValue(key, value)) list_for_each_entry_safe(pos, next, &cond->not_waiting, list, struct usbi_cond_perthread) {
return 0; CloseHandle(pos->event);
else list_del(&pos->list);
return EINVAL; free(pos);
} }
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();
} }

View File

@ -21,17 +21,40 @@
#ifndef LIBUSB_THREADS_WINDOWS_H #ifndef LIBUSB_THREADS_WINDOWS_H
#define LIBUSB_THREADS_WINDOWS_H #define LIBUSB_THREADS_WINDOWS_H
#define usbi_mutex_static_t volatile LONG #define USBI_MUTEX_INITIALIZER 0L
#define USBI_MUTEX_INITIALIZER 0 #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 CRITICAL_SECTION usbi_mutex_t;
static inline int usbi_mutex_init(usbi_mutex_t *mutex)
typedef struct usbi_cond { {
// Every time a thread touches the CV, it winds up in one of these lists. InitializeCriticalSection(mutex);
// It stays there until the CV is destroyed, even if the thread terminates. return 0;
struct list_head waiters; }
struct list_head not_waiting; static inline void usbi_mutex_lock(usbi_mutex_t *mutex)
} usbi_cond_t; {
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: // We *were* getting timespec from pthread.h:
#if (!defined(HAVE_STRUCT_TIMESPEC) && !defined(_TIMESPEC_DEFINED)) #if (!defined(HAVE_STRUCT_TIMESPEC) && !defined(_TIMESPEC_DEFINED))
@ -45,32 +68,44 @@ struct timespec {
// We *were* getting ETIMEDOUT from pthread.h: // We *were* getting ETIMEDOUT from pthread.h:
#ifndef ETIMEDOUT #ifndef ETIMEDOUT
# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ #define ETIMEDOUT 10060 /* This is the value in winsock.h. */
#endif #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); void usbi_cond_init(usbi_cond_t *cond);
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);
int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex); int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex);
int usbi_cond_timedwait(usbi_cond_t *cond, int usbi_cond_timedwait(usbi_cond_t *cond,
usbi_mutex_t *mutex, const struct timeval *tv); usbi_mutex_t *mutex, const struct timeval *tv);
int usbi_cond_broadcast(usbi_cond_t *cond); void usbi_cond_broadcast(usbi_cond_t *cond);
int usbi_cond_destroy(usbi_cond_t *cond); void usbi_cond_destroy(usbi_cond_t *cond);
int usbi_tls_key_create(usbi_tls_key_t *key); typedef DWORD usbi_tls_key_t;
void *usbi_tls_key_get(usbi_tls_key_t key); static inline void usbi_tls_key_create(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); *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 */ #endif /* LIBUSB_THREADS_WINDOWS_H */

View File

@ -31,8 +31,7 @@
#include "wince_usb.h" #include "wince_usb.h"
// Global variables // Global variables
const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime int errno = 0;
int windows_version = WINDOWS_CE;
static uint64_t hires_frequency, hires_ticks_to_ps; static uint64_t hires_frequency, hires_ticks_to_ps;
static HANDLE driver_handle = INVALID_HANDLE_VALUE; static HANDLE driver_handle = INVALID_HANDLE_VALUE;
static int concurrent_usage = -1; static int concurrent_usage = -1;
@ -42,38 +41,39 @@ static int concurrent_usage = -1;
* uses retval as errorcode, or, if 0, use GetLastError() * uses retval as errorcode, or, if 0, use GetLastError()
*/ */
#if defined(ENABLE_LOGGING) #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 TCHAR wErr_string[ERR_BUFFER_SIZE];
static char err_string[ERR_BUFFER_SIZE]; static char err_string[ERR_BUFFER_SIZE];
DWORD error_code, format_error;
DWORD size; 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, size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &wErr_string[safe_tcslen(wErr_string)], NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
ERR_BUFFER_SIZE - (DWORD)safe_tcslen(wErr_string), NULL); wErr_string, ERR_BUFFER_SIZE, NULL);
if (size == 0) { if (size == 0) {
format_error = GetLastError(); DWORD format_error = GetLastError();
if (format_error) if (format_error)
safe_stprintf(wErr_string, ERR_BUFFER_SIZE, snprintf(err_string, ERR_BUFFER_SIZE,
_T("Windows error code %u (FormatMessage error code %u)"), "Windows error code %u (FormatMessage error code %u)",
(unsigned int)error_code, (unsigned int)format_error); (unsigned int)error_code, (unsigned int)format_error);
else 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 { } else {
// Remove CR/LF terminators // Remove CR/LF terminators, if present
for (i = safe_tcslen(wErr_string) - 1; ((wErr_string[i] == 0x0A) || (wErr_string[i] == 0x0D)); i--) size_t pos = size - 2;
wErr_string[i] = 0; 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) 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"); strcpy(err_string, "Unable to convert error string");
}
return err_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_GET_HANDLE(ceusbkwrapper);
DLL_LOAD_FUNC(ceusbkwrapper, UkwOpenDriver, TRUE); 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, UkwIssueBulkTransfer, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwIsPipeHalted, TRUE); DLL_LOAD_FUNC(ceusbkwrapper, UkwIsPipeHalted, TRUE);
return LIBUSB_SUCCESS; return TRUE;
} }
static void exit_dllimports(void) 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 // 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 // exit calls. If init is called more than exit, we will not exit properly
if ( ++concurrent_usage == 0 ) { // First init? if ( ++concurrent_usage == 0 ) { // First init?
// Initialize pollable file descriptors
init_polling();
// Load DLL imports // Load DLL imports
if (init_dllimports() != LIBUSB_SUCCESS) { if (!init_dllimports()) {
usbi_err(ctx, "could not resolve DLL functions"); usbi_err(ctx, "could not resolve DLL functions");
r = LIBUSB_ERROR_NOT_SUPPORTED; r = LIBUSB_ERROR_NOT_SUPPORTED;
goto init_exit; goto init_exit;
@ -223,7 +220,6 @@ static int wince_init(struct libusb_context *ctx)
init_exit: // Holds semaphore here. init_exit: // Holds semaphore here.
if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed?
exit_dllimports(); exit_dllimports();
exit_polling();
if (driver_handle != INVALID_HANDLE_VALUE) { if (driver_handle != INVALID_HANDLE_VALUE) {
UkwCloseDriver(driver_handle); UkwCloseDriver(driver_handle);
@ -239,10 +235,11 @@ init_exit: // Holds semaphore here.
return r; return r;
} }
static void wince_exit(void) static void wince_exit(struct libusb_context *ctx)
{ {
HANDLE semaphore; HANDLE semaphore;
TCHAR sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' 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)); _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF));
semaphore = CreateSemaphore(NULL, 1, 1, sem_name); 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 // Only works if exits and inits are balanced exactly
if (--concurrent_usage < 0) { // Last exit if (--concurrent_usage < 0) { // Last exit
exit_dllimports(); exit_dllimports();
exit_polling();
if (driver_handle != INVALID_HANDLE_VALUE) { if (driver_handle != INVALID_HANDLE_VALUE) {
UkwCloseDriver(driver_handle); UkwCloseDriver(driver_handle);
@ -328,19 +324,19 @@ static int wince_get_device_list(
} }
new_devices = discovered_devs_append(new_devices, dev); new_devices = discovered_devs_append(new_devices, dev);
if (!discdevs) { if (!new_devices) {
r = LIBUSB_ERROR_NO_MEM; r = LIBUSB_ERROR_NO_MEM;
goto err_out; goto err_out;
} }
safe_unref_device(dev); libusb_unref_device(dev);
} }
*discdevs = new_devices; *discdevs = new_devices;
return r; return r;
err_out: err_out:
*discdevs = new_devices; *discdevs = new_devices;
safe_unref_device(dev); libusb_unref_device(dev);
// Release the remainder of the unprocessed device list. // Release the remainder of the unprocessed device list.
// The devices added to new_devices already will still be passed up to libusb, // The devices added to new_devices already will still be passed up to libusb,
// which can dispose of them at its leisure. // 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) static void wince_clear_transfer_priv(struct usbi_transfer *itransfer)
{ {
struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
struct winfd wfd = fd_to_winfd(transfer_priv->pollable_fd.fd);
// No need to cancel transfer as it is either complete or abandoned usbi_close(transfer_priv->pollable_fd.fd);
wfd.itransfer = NULL; transfer_priv->pollable_fd = INVALID_WINFD;
CloseHandle(wfd.handle);
usbi_free_fd(&transfer_priv->pollable_fd);
} }
static int wince_cancel_transfer(struct usbi_transfer *itransfer) 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; BOOL direction_in, ret;
struct winfd wfd; struct winfd wfd;
DWORD flags; DWORD flags;
HANDLE eventHandle;
PUKW_CONTROL_HEADER setup = NULL; PUKW_CONTROL_HEADER setup = NULL;
const BOOL control_transfer = transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL; const BOOL control_transfer = transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL;
int r;
transfer_priv->pollable_fd = INVALID_WINFD;
if (control_transfer) { if (control_transfer) {
setup = (PUKW_CONTROL_HEADER) transfer->buffer; setup = (PUKW_CONTROL_HEADER) transfer->buffer;
direction_in = setup->bmRequestType & LIBUSB_ENDPOINT_IN; 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 = direction_in ? UKW_TF_IN_TRANSFER : UKW_TF_OUT_TRANSFER;
flags |= UKW_TF_SHORT_TRANSFER_OK; flags |= UKW_TF_SHORT_TRANSFER_OK;
eventHandle = CreateEvent(NULL, FALSE, FALSE, NULL); wfd = usbi_create_fd();
if (eventHandle == NULL) { if (wfd.fd < 0)
usbi_err(ctx, "Failed to create event for async transfer");
return LIBUSB_ERROR_NO_MEM; return LIBUSB_ERROR_NO_MEM;
}
wfd = usbi_create_fd(eventHandle, direction_in ? RW_READ : RW_WRITE, itransfer, &wince_cancel_transfer); r = usbi_add_pollfd(ctx, wfd.fd, direction_in ? POLLIN : POLLOUT);
if (wfd.fd < 0) { if (r) {
CloseHandle(eventHandle); usbi_close(wfd.fd);
return LIBUSB_ERROR_NO_MEM; return r;
} }
transfer_priv->pollable_fd = wfd; transfer_priv->pollable_fd = wfd;
if (control_transfer) { if (control_transfer) {
// Split out control setup header and data buffer // Split out control setup header and data buffer
DWORD bufLen = transfer->length - sizeof(UKW_CONTROL_HEADER); 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()); int libusbErr = translate_driver_error(GetLastError());
usbi_err(ctx, "UkwIssue%sTransfer failed: error %u", usbi_err(ctx, "UkwIssue%sTransfer failed: error %u",
control_transfer ? "Control" : "Bulk", (unsigned int)GetLastError()); 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; return libusbErr;
} }
usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, direction_in ? POLLIN : POLLOUT);
return LIBUSB_SUCCESS; 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) static int wince_submit_transfer(struct usbi_transfer *itransfer)
{ {
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
@ -635,7 +623,6 @@ static int wince_submit_transfer(struct usbi_transfer *itransfer)
case LIBUSB_TRANSFER_TYPE_INTERRUPT: case LIBUSB_TRANSFER_TYPE_INTERRUPT:
return wince_submit_control_or_bulk_transfer(itransfer); return wince_submit_control_or_bulk_transfer(itransfer);
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
return wince_submit_iso_transfer(itransfer);
case LIBUSB_TRANSFER_TYPE_BULK_STREAM: case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
return LIBUSB_ERROR_NOT_SUPPORTED; return LIBUSB_ERROR_NOT_SUPPORTED;
default: default:
@ -763,7 +750,7 @@ static int wince_handle_events(
struct wince_transfer_priv* transfer_priv = NULL; struct wince_transfer_priv* transfer_priv = NULL;
POLL_NFDS_TYPE i = 0; POLL_NFDS_TYPE i = 0;
BOOL found = FALSE; BOOL found = FALSE;
struct usbi_transfer *transfer; struct usbi_transfer *itransfer;
DWORD io_size, io_result; DWORD io_size, io_result;
int r = LIBUSB_SUCCESS; int r = LIBUSB_SUCCESS;
@ -780,8 +767,8 @@ static int wince_handle_events(
// Because a Windows OVERLAPPED is used for poll emulation, // Because a Windows OVERLAPPED is used for poll emulation,
// a pollable fd is created and stored with each transfer // a pollable fd is created and stored with each transfer
usbi_mutex_lock(&ctx->flying_transfers_lock); usbi_mutex_lock(&ctx->flying_transfers_lock);
list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) {
transfer_priv = usbi_transfer_get_os_priv(transfer); transfer_priv = usbi_transfer_get_os_priv(itransfer);
if (transfer_priv->pollable_fd.fd == fds[i].fd) { if (transfer_priv->pollable_fd.fd == fds[i].fd) {
found = TRUE; found = TRUE;
break; break;
@ -796,7 +783,7 @@ static int wince_handle_events(
// let handle_callback free the event using the transfer wfd // 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 // 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. // 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) { } else if (found) {
usbi_err(ctx, "matching transfer for fd %d has not completed", fds[i]); usbi_err(ctx, "matching transfer for fd %d has not completed", fds[i]);
r = LIBUSB_ERROR_OTHER; 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 // Fall through and return real-time if monotonic read failed or was not detected @ init
case USBI_CLOCK_REALTIME: case USBI_CLOCK_REALTIME:
// We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx // 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 // 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) // functions and is at best of the order of 1 ms (or, usually, worse)
GetSystemTime(&st); GetSystemTime(&st);
SystemTimeToFileTime(&st, &filetime); SystemTimeToFileTime(&st, &filetime);
rtime.LowPart = filetime.dwLowDateTime; rtime.LowPart = filetime.dwLowDateTime;
rtime.HighPart = filetime.dwHighDateTime; rtime.HighPart = filetime.dwHighDateTime;
rtime.QuadPart -= epoch_time; rtime.QuadPart -= EPOCH_TIME;
tp->tv_sec = (long)(rtime.QuadPart / 10000000); tp->tv_sec = (long)(rtime.QuadPart / 10000000);
tp->tv_nsec = (long)((rtime.QuadPart % 10000000)*100); tp->tv_nsec = (long)((rtime.QuadPart % 10000000)*100);
return LIBUSB_SUCCESS; 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", "Windows CE",
0, 0,
wince_init, wince_init,
wince_exit, wince_exit,
NULL, /* set_option() */
wince_get_device_list, wince_get_device_list,
NULL, /* hotplug_poll */ NULL, /* hotplug_poll */
@ -893,6 +881,7 @@ const struct usbi_os_backend wince_backend = {
NULL, /* handle_transfer_completion() */ NULL, /* handle_transfer_completion() */
wince_clock_gettime, wince_clock_gettime,
0,
sizeof(struct wince_device_priv), sizeof(struct wince_device_priv),
0, 0,
sizeof(struct wince_transfer_priv), sizeof(struct wince_transfer_priv),

View File

@ -37,38 +37,23 @@
#define false FALSE #define false FALSE
#endif #endif
#define EPOCH_TIME UINT64_C(116444736000000000) // 1970.01.01 00:00:000 in MS Filetime
#if defined(__CYGWIN__ ) #if defined(__CYGWIN__ )
#define _stricmp strcasecmp #define _stricmp strcasecmp
#define _snprintf snprintf
#define _strdup strdup #define _strdup strdup
// _beginthreadex is MSVCRT => unavailable for cygwin. Fallback to using CreateThread // _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) #define _beginthreadex(a, b, c, d, e, f) CreateThread(a, b, (LPTHREAD_START_ROUTINE)c, d, e, (LPDWORD)f)
#endif #endif
#define safe_free(p) do {if (p != NULL) {free((void*)p); p = NULL;}} while(0) #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)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
#define safe_stricmp(str1, str2) _stricmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
#define safe_strncmp(str1, str2, count) strncmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<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)
#ifndef ARRAYSIZE #ifndef ARRAYSIZE
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif #endif
#define ERR_BUFFER_SIZE 256 #define ERR_BUFFER_SIZE 256
/* /*
* API macros - leveraged from libusb-win32 1.x * API macros - leveraged from libusb-win32 1.x
*/ */
@ -83,31 +68,35 @@
/* /*
* Macros for handling DLL themselves * Macros for handling DLL themselves
*/ */
#define DLL_HANDLE_NAME(name) __dll_##name##_handle
#define DLL_DECLARE_HANDLE(name) \ #define DLL_DECLARE_HANDLE(name) \
static HMODULE __dll_##name##_handle = NULL static HMODULE DLL_HANDLE_NAME(name) = NULL
#define DLL_GET_HANDLE(name) \ #define DLL_GET_HANDLE(name) \
do { \ do { \
__dll_##name##_handle = DLL_LOAD_LIBRARY(name); \ DLL_HANDLE_NAME(name) = DLL_LOAD_LIBRARY(name); \
if (!__dll_##name##_handle) \ if (!DLL_HANDLE_NAME(name)) \
return LIBUSB_ERROR_OTHER; \ return FALSE; \
} while (0) } while (0)
#define DLL_FREE_HANDLE(name) \ #define DLL_FREE_HANDLE(name) \
do { \ do { \
if (__dll_##name##_handle) { \ if (DLL_HANDLE_NAME(name)) { \
FreeLibrary(__dll_##name##_handle); \ FreeLibrary(DLL_HANDLE_NAME(name)); \
__dll_##name##_handle = NULL; \ DLL_HANDLE_NAME(name) = NULL; \
} \ } \
} while(0) } while (0)
/* /*
* Macros for handling functions within a DLL * 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) \ #define DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefixname, name, args) \
typedef ret (api * __dll_##name##_func_t)args; \ typedef ret (api * DLL_FUNC_NAME(name))args; \
static __dll_##name##_func_t prefixname = NULL static DLL_FUNC_NAME(name) prefixname = NULL
#define DLL_DECLARE_FUNC(api, ret, name, args) \ #define DLL_DECLARE_FUNC(api, ret, name, args) \
DLL_DECLARE_FUNC_PREFIXNAME(api, ret, name, 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) \ #define DLL_LOAD_FUNC_PREFIXNAME(dll, prefixname, name, ret_on_failure) \
do { \ do { \
HMODULE h = __dll_##dll##_handle; \ HMODULE h = DLL_HANDLE_NAME(dll); \
prefixname = (__dll_##name##_func_t)GetProcAddress(h, \ prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \
DLL_STRINGIFY(name)); \ DLL_STRINGIFY(name)); \
if (prefixname) \ if (prefixname) \
break; \ break; \
prefixname = (__dll_##name##_func_t)GetProcAddress(h, \ prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \
DLL_STRINGIFY(name) DLL_STRINGIFY(A)); \ DLL_STRINGIFY(name) DLL_STRINGIFY(A)); \
if (prefixname) \ if (prefixname) \
break; \ break; \
prefixname = (__dll_##name##_func_t)GetProcAddress(h, \ prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \
DLL_STRINGIFY(name) DLL_STRINGIFY(W)); \ DLL_STRINGIFY(name) DLL_STRINGIFY(W)); \
if (prefixname) \ if (prefixname) \
break; \ break; \
if (ret_on_failure) \ if (ret_on_failure) \
return LIBUSB_ERROR_NOT_FOUND; \ return FALSE; \
} while(0) } while (0)
#define DLL_LOAD_FUNC(dll, name, ret_on_failure) \ #define DLL_LOAD_FUNC(dll, name, ret_on_failure) \
DLL_LOAD_FUNC_PREFIXNAME(dll, name, name, ret_on_failure) DLL_LOAD_FUNC_PREFIXNAME(dll, name, name, ret_on_failure)

File diff suppressed because it is too large Load Diff

View File

@ -26,48 +26,85 @@
#pragma once #pragma once
// Missing from MinGW #include "windows_nt_shared_types.h"
#if !defined(FACILITY_SETUPAPI)
#define FACILITY_SETUPAPI 15
#endif
typedef struct USB_CONFIGURATION_DESCRIPTOR { /* Windows versions */
UCHAR bLength; enum windows_version {
UCHAR bDescriptorType; WINDOWS_UNDEFINED,
USHORT wTotalLength; WINDOWS_2000,
UCHAR bNumInterfaces; WINDOWS_XP,
UCHAR bConfigurationValue; WINDOWS_2003, // Also XP x64
UCHAR iConfiguration; WINDOWS_VISTA,
UCHAR bmAttributes; WINDOWS_7,
UCHAR MaxPower; WINDOWS_8,
} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR; 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); /* This call is only available from Vista */
void windows_common_exit(void); 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); unsigned long htab_hash(const char *str);
int windows_clock_gettime(int clk_id, struct timespec *tp); void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size);
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);
#if defined(ENABLE_LOGGING) #if defined(ENABLE_LOGGING)
const char *windows_error_str(DWORD retval); const char *windows_error_str(DWORD error_code);
#endif #endif

View File

@ -0,0 +1,147 @@
#pragma once
#include "windows_common.h"
#include <pshpack1.h>
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 <poppack.h>
#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.
};

View File

@ -24,19 +24,11 @@
#include <config.h> #include <config.h>
#include <windows.h> #include <windows.h>
#include <cfgmgr32.h>
#include <stdio.h> #include <stdio.h>
#include "libusbi.h" #include "libusbi.h"
#include "windows_common.h" #include "windows_common.h"
#include "windows_nt_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" #include "windows_usbdk.h"
#if !defined(STATUS_SUCCESS) #if !defined(STATUS_SUCCESS)
@ -53,7 +45,7 @@ typedef LONG NTSTATUS;
#endif #endif
#if !defined(USBD_SUCCESS) #if !defined(USBD_SUCCESS)
typedef int32_t USBD_STATUS; typedef LONG USBD_STATUS;
#define USBD_SUCCESS(Status) ((USBD_STATUS) (Status) >= 0) #define USBD_SUCCESS(Status) ((USBD_STATUS) (Status) >= 0)
#define USBD_PENDING(Status) ((ULONG) (Status) >> 30 == 1) #define USBD_PENDING(Status) ((ULONG) (Status) >> 30 == 1)
#define USBD_ERROR(Status) ((USBD_STATUS) (Status) < 0) #define USBD_ERROR(Status) ((USBD_STATUS) (Status) < 0)
@ -64,24 +56,6 @@ typedef int32_t USBD_STATUS;
#define USBD_STATUS_CANCELED ((USBD_STATUS) 0xc0010000) #define USBD_STATUS_CANCELED ((USBD_STATUS) 0xc0010000)
#endif #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) static inline struct usbdk_device_priv *_usbdk_device_priv(struct libusb_device *dev)
{ {
return (struct usbdk_device_priv *)dev->os_priv; return (struct usbdk_device_priv *)dev->os_priv;
@ -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); FARPROC api_ptr = GetProcAddress(usbdk_helper.module, api_name);
if (api_ptr == NULL) if (api_ptr == NULL)
usbi_err(ctx, "UsbDkHelper API %s not found, error %d", api_name, GetLastError()); usbi_err(ctx, "UsbDkHelper API %s not found: %s", api_name, windows_error_str(0));
return api_ptr; return api_ptr;
} }
@ -132,7 +106,7 @@ static int load_usbdk_helper_dll(struct libusb_context *ctx)
{ {
usbdk_helper.module = LoadLibraryA("UsbDkHelper"); usbdk_helper.module = LoadLibraryA("UsbDkHelper");
if (usbdk_helper.module == NULL) { 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; return LIBUSB_ERROR_NOT_FOUND;
} }
@ -198,44 +172,41 @@ error_unload:
static int usbdk_init(struct libusb_context *ctx) static int usbdk_init(struct libusb_context *ctx)
{ {
int r; SC_HANDLE managerHandle;
SC_HANDLE serviceHandle;
if (++concurrent_usage == 0) { // First init? managerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (managerHandle == NULL) {
backend_init(); usbi_warn(ctx, "failed to open service control manager: %s", windows_error_str(0));
return LIBUSB_ERROR_OTHER;
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();
} }
if (r != LIBUSB_SUCCESS) serviceHandle = OpenServiceA(managerHandle, "UsbDk", GENERIC_READ);
--concurrent_usage; // Not expected to call libusb_exit if we failed. 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, static int usbdk_get_session_id_for_device(struct libusb_context *ctx,
PUSB_DK_DEVICE_ID id, unsigned long *session_id) PUSB_DK_DEVICE_ID id, unsigned long *session_id)
{ {
char dev_identity[ARRAYSIZE(id->DeviceID) + ARRAYSIZE(id->InstanceID)]; char dev_identity[ARRAYSIZE(id->DeviceID) + ARRAYSIZE(id->InstanceID) + 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); usbi_warn(ctx, "cannot form device identity", id->DeviceID);
return LIBUSB_ERROR_NOT_SUPPORTED; 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->port_number = (uint8_t)info->Port;
dev->parent_dev = NULL; 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->device_address = (uint8_t)(info->Port + 1);
dev->num_configurations = info->DeviceDescriptor.bNumConfigurations; dev->num_configurations = info->DeviceDescriptor.bNumConfigurations;
dev->device_descriptor = info->DeviceDescriptor; memcpy(&dev->device_descriptor, &info->DeviceDescriptor, LIBUSB_DT_DEVICE_SIZE);
switch (info->Speed) { switch (info->Speed) {
case LowSpeed: case LowSpeed:
@ -333,7 +304,7 @@ static int usbdk_get_device_list(struct libusb_context *ctx, struct discovered_d
ULONG dev_number; ULONG dev_number;
PUSB_DK_DEVICE_INFO devices; PUSB_DK_DEVICE_INFO devices;
if(!usbdk_helper.GetDevicesList(&devices, &dev_number)) if (!usbdk_helper.GetDevicesList(&devices, &dev_number))
return LIBUSB_ERROR_OTHER; return LIBUSB_ERROR_OTHER;
for (i = 0; i < dev_number; i++) { for (i = 0; i < dev_number; i++) {
@ -374,26 +345,16 @@ func_exit:
return r; return r;
} }
static void usbdk_exit(void) static int usbdk_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer)
{
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)
{ {
struct usbdk_device_priv *priv = _usbdk_device_priv(dev); struct usbdk_device_priv *priv = _usbdk_device_priv(dev);
memcpy(buffer, &priv->info.DeviceDescriptor, DEVICE_DESC_LENGTH); memcpy(buffer, &priv->info.DeviceDescriptor, DEVICE_DESC_LENGTH);
*host_endian = 0;
return LIBUSB_SUCCESS; return LIBUSB_SUCCESS;
} }
static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) 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); struct usbdk_device_priv *priv = _usbdk_device_priv(dev);
PUSB_CONFIGURATION_DESCRIPTOR config_header; 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); size = min(config_header->wTotalLength, len);
memcpy(buffer, config_header, size); memcpy(buffer, config_header, size);
*host_endian = 0;
return (int)size; return (int)size;
} }
static inline int usbdk_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian) 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, 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) 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; return LIBUSB_ERROR_OTHER;
} }
priv->system_handle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle);
return LIBUSB_SUCCESS; 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); struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
if (!usbdk_helper.StopRedirect(priv->redirector_handle)) { if (!usbdk_helper.StopRedirect(priv->redirector_handle))
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); usbi_err(HANDLE_CTX(dev_handle), "Redirector shutdown failed");
usbi_err(ctx, "Redirector shutdown failed");
}
} }
static int usbdk_get_configuration(struct libusb_device_handle *dev_handle, int *config) 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) 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); struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
if (!usbdk_helper.SetAltsetting(priv->redirector_handle, iface, altsetting)) { 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) 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); struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
if (!usbdk_helper.ResetPipe(priv->redirector_handle, endpoint)) { 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) 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); struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
if (!usbdk_helper.ResetDevice(priv->redirector_handle)) { 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; 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) static void usbdk_destroy_device(struct libusb_device *dev)
{ {
struct usbdk_device_priv* p = _usbdk_device_priv(dev); struct usbdk_device_priv* p = _usbdk_device_priv(dev);
@ -536,12 +492,14 @@ static void usbdk_destroy_device(struct libusb_device *dev)
usbdk_release_config_descriptors(p, p->info.DeviceDescriptor.bNumConfigurations); 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 usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(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) { if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
safe_free(transfer_priv->IsochronousPacketsArray); 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 libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); struct libusb_context *ctx = TRANSFER_CTX(transfer);
struct winfd wfd; OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped;
ULONG Length;
TransferResult transResult; TransferResult transResult;
HANDLE sysHandle;
sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); transfer_priv->request.Buffer = (PVOID64)transfer->buffer;
wfd = usbi_create_fd(sysHandle, RW_READ, NULL, NULL);
// Always use the handle returned from usbi_create_fd (wfd.handle)
if (wfd.fd < 0)
return LIBUSB_ERROR_NO_MEM;
transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer;
transfer_priv->request.BufferLength = transfer->length; transfer_priv->request.BufferLength = transfer->length;
transfer_priv->request.TransferType = ControlTransferType; transfer_priv->request.TransferType = ControlTransferType;
transfer_priv->pollable_fd = INVALID_WINFD;
Length = (ULONG)transfer->length;
if (IS_XFERIN(transfer)) if (transfer->buffer[0] & LIBUSB_ENDPOINT_IN)
transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped);
else 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) { switch (transResult) {
case TransferSuccess: case TransferSuccess:
wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred);
wfd.overlapped->InternalHigh = (DWORD)Length;
break; break;
case TransferSuccessAsync: case TransferSuccessAsync:
break; break;
case TransferFailure: case TransferFailure:
usbi_err(ctx, "ControlTransfer failed: %s", windows_error_str(0)); usbi_err(ctx, "ControlTransfer failed: %s", windows_error_str(0));
usbi_free_fd(&wfd);
return LIBUSB_ERROR_IO; 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; 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 libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); struct libusb_context *ctx = TRANSFER_CTX(transfer);
struct winfd wfd; OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped;
TransferResult transferRes; 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.BufferLength = transfer->length;
transfer_priv->request.EndpointAddress = transfer->endpoint; 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; transfer_priv->request.TransferType = BulkTransferType;
break; break;
case LIBUSB_TRANSFER_TYPE_INTERRUPT: case LIBUSB_TRANSFER_TYPE_INTERRUPT:
transfer_priv->request.TransferType = IntertuptTransferType; transfer_priv->request.TransferType = InterruptTransferType;
break; break;
default: 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; 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)) 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 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) { switch (transferRes) {
case TransferSuccess: case TransferSuccess:
wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred);
break; break;
case TransferSuccessAsync: case TransferSuccessAsync:
break; break;
case TransferFailure: case TransferFailure:
usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0));
usbi_free_fd(&wfd);
return LIBUSB_ERROR_IO; 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; 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 libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); struct libusb_context *ctx = TRANSFER_CTX(transfer);
struct winfd wfd; OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped;
TransferResult transferRes; TransferResult transferRes;
int i; 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.BufferLength = transfer->length;
transfer_priv->request.EndpointAddress = transfer->endpoint; transfer_priv->request.EndpointAddress = transfer->endpoint;
transfer_priv->request.TransferType = IsochronousTransferType; transfer_priv->request.TransferType = IsochronousTransferType;
transfer_priv->request.IsochronousPacketsArraySize = transfer->num_iso_packets; transfer_priv->request.IsochronousPacketsArraySize = transfer->num_iso_packets;
transfer_priv->IsochronousPacketsArray = malloc(transfer->num_iso_packets * sizeof(ULONG64)); 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) { if (!transfer_priv->IsochronousPacketsArray) {
usbi_err(ctx, "Allocation of IsochronousPacketsArray is failed, %s", windows_error_str(0)); usbi_err(ctx, "Allocation of IsochronousPacketsArray failed");
return LIBUSB_ERROR_IO; return LIBUSB_ERROR_NO_MEM;
} }
transfer_priv->IsochronousResultsArray = malloc(transfer->num_iso_packets * sizeof(USB_DK_ISO_TRANSFER_RESULT)); 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) { if (!transfer_priv->IsochronousResultsArray) {
usbi_err(ctx, "Allocation of isochronousResultsArray is failed, %s", windows_error_str(0)); usbi_err(ctx, "Allocation of isochronousResultsArray failed");
free(transfer_priv->IsochronousPacketsArray); return LIBUSB_ERROR_NO_MEM;
return LIBUSB_ERROR_IO;
} }
for (i = 0; i < transfer->num_iso_packets; i++) for (i = 0; i < transfer->num_iso_packets; i++)
transfer_priv->IsochronousPacketsArray[i] = transfer->iso_packet_desc[i].length; 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)) 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 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) { switch (transferRes) {
case TransferSuccess: case TransferSuccess:
wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred);
break; break;
case TransferSuccessAsync: case TransferSuccessAsync:
break; break;
case TransferFailure: 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_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; 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; 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) static int usbdk_submit_transfer(struct usbi_transfer *itransfer)
{ {
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
int (*transfer_fn)(struct usbi_transfer *);
short events;
switch (transfer->type) { switch (transfer->type) {
case LIBUSB_TRANSFER_TYPE_CONTROL: 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_BULK:
case LIBUSB_TRANSFER_TYPE_INTERRUPT: case LIBUSB_TRANSFER_TYPE_INTERRUPT:
if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)) if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
return LIBUSB_ERROR_NOT_SUPPORTED; //TODO: Check whether we can support this in UsbDk return LIBUSB_ERROR_NOT_SUPPORTED; //TODO: Check whether we can support this in UsbDk
else events = IS_XFERIN(transfer) ? POLLIN : POLLOUT;
return usbdk_do_bulk_transfer(itransfer); transfer_fn = usbdk_do_bulk_transfer;
break;
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 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: default:
usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
return LIBUSB_ERROR_INVALID_PARAM; return LIBUSB_ERROR_INVALID_PARAM;
} }
return usbdk_do_submit_transfer(itransfer, events, transfer_fn);
} }
static int usbdk_abort_transfers(struct usbi_transfer *itransfer) static int usbdk_abort_transfers(struct usbi_transfer *itransfer)
{ {
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_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_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)) { if (pCancelIoEx != NULL) {
usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); // Use CancelIoEx if available to cancel just a single transfer
return LIBUSB_ERROR_NO_DEVICE; 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; 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; itransfer->transferred += io_size;
return LIBUSB_TRANSFER_COMPLETED; 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); struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
return &transfer_priv->pollable_fd; return transfer_priv->pollable_fd.fd;
} }
static DWORD usbdk_translate_usbd_status(USBD_STATUS UsbdStatus) 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; return NO_ERROR;
switch (UsbdStatus) { 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: case USBD_STATUS_TIMEOUT:
return ERROR_SEM_TIMEOUT; return ERROR_SEM_TIMEOUT;
case USBD_STATUS_CANCELED: case USBD_STATUS_CANCELED:
return ERROR_OPERATION_ABORTED; return ERROR_OPERATION_ABORTED;
default: 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 struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
|| GetOverlappedResult(pollable_fd->handle, pollable_fd->overlapped, io_size, false)) { // Regular async overlapped struct winfd *pollable_fd = &transfer_priv->pollable_fd;
struct libusb_transfer *ltransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer);
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer);
if (ltransfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { if (HasOverlappedIoCompletedSync(pollable_fd->overlapped) // Handle async requests that completed synchronously first
int i; || 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++) { for (i = 0; i < transfer_priv->request.IsochronousPacketsArraySize; i++) {
struct libusb_iso_packet_descriptor *lib_desc = &ltransfer->iso_packet_desc[i]; struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i];
switch (transfer_priv->IsochronousResultsArray[i].TransferResult) { switch (transfer_priv->IsochronousResultsArray[i].TransferResult) {
case STATUS_SUCCESS: 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_size = (DWORD)transfer_priv->request.Result.GenResult.BytesTransferred;
*io_result = usbdk_translate_usbd_status((USBD_STATUS) transfer_priv->request.Result.GenResult.UsbdStatus); *io_result = usbdk_translate_usbd_status((USBD_STATUS)transfer_priv->request.Result.GenResult.UsbdStatus);
} } else {
else {
*io_result = GetLastError(); *io_result = GetLastError();
} }
} }
static int usbdk_clock_gettime(int clk_id, struct timespec *tp) const struct windows_backend usbdk_backend = {
{
return windows_clock_gettime(clk_id, tp);
}
const struct usbi_os_backend usbdk_backend = {
"Windows",
USBI_CAP_HAS_HID_ACCESS,
usbdk_init, usbdk_init,
usbdk_exit, usbdk_exit,
usbdk_get_device_list, usbdk_get_device_list,
NULL,
usbdk_open, usbdk_open,
usbdk_close, usbdk_close,
usbdk_get_device_descriptor, usbdk_get_device_descriptor,
usbdk_get_active_config_descriptor, usbdk_get_active_config_descriptor,
usbdk_get_config_descriptor, usbdk_get_config_descriptor,
NULL, usbdk_get_config_descriptor_by_value,
usbdk_get_configuration, usbdk_get_configuration,
usbdk_set_configuration, usbdk_set_configuration,
usbdk_claim_interface, usbdk_claim_interface,
usbdk_release_interface, usbdk_release_interface,
usbdk_set_interface_altsetting, usbdk_set_interface_altsetting,
usbdk_clear_halt, usbdk_clear_halt,
usbdk_reset_device, 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_destroy_device,
usbdk_submit_transfer, usbdk_submit_transfer,
usbdk_cancel_transfer, usbdk_cancel_transfer,
windows_clear_transfer_priv, usbdk_clear_transfer_priv,
usbdk_copy_transfer_data,
windows_handle_events, usbdk_get_transfer_fd,
NULL, usbdk_get_overlapped_result,
usbdk_clock_gettime,
#if defined(USBI_TIMERFD_AVAILABLE)
NULL,
#endif
sizeof(struct usbdk_device_priv),
0,
sizeof(struct usbdk_transfer_priv),
}; };
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);
}

View File

@ -23,56 +23,13 @@
#pragma once #pragma once
typedef struct tag_USB_DK_DEVICE_ID { #include "windows_nt_common.h"
WCHAR DeviceID[MAX_DEVICE_ID_LEN];
WCHAR InstanceID[MAX_DEVICE_ID_LEN];
} USB_DK_DEVICE_ID, *PUSB_DK_DEVICE_ID;
static inline void UsbDkFillIDStruct(USB_DK_DEVICE_ID *ID, PCWCHAR DeviceID, PCWCHAR InstanceID) typedef struct USB_DK_CONFIG_DESCRIPTOR_REQUEST {
{
wcsncpy_s(ID->DeviceID, DeviceID, MAX_DEVICE_ID_LEN);
wcsncpy_s(ID->InstanceID, InstanceID, MAX_DEVICE_ID_LEN);
}
typedef struct tag_USB_DK_DEVICE_INFO {
USB_DK_DEVICE_ID ID;
ULONG64 FilterID;
ULONG64 Port;
ULONG64 Speed;
USB_DEVICE_DESCRIPTOR DeviceDescriptor;
} USB_DK_DEVICE_INFO, *PUSB_DK_DEVICE_INFO;
typedef struct tag_USB_DK_CONFIG_DESCRIPTOR_REQUEST {
USB_DK_DEVICE_ID ID; USB_DK_DEVICE_ID ID;
ULONG64 Index; ULONG64 Index;
} USB_DK_CONFIG_DESCRIPTOR_REQUEST, *PUSB_DK_CONFIG_DESCRIPTOR_REQUEST; } 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 { typedef enum {
TransferFailure = 0, TransferFailure = 0,
TransferSuccess, TransferSuccess,
@ -90,7 +47,7 @@ typedef enum {
typedef enum { typedef enum {
ControlTransferType, ControlTransferType,
BulkTransferType, BulkTransferType,
IntertuptTransferType, InterruptTransferType,
IsochronousTransferType IsochronousTransferType
} USB_DK_TRANSFER_TYPE; } USB_DK_TRANSFER_TYPE;

File diff suppressed because it is too large Load Diff

View File

@ -36,15 +36,14 @@
#endif #endif
// Missing from MSVC6 setupapi.h // Missing from MSVC6 setupapi.h
#if !defined(SPDRP_ADDRESS) #ifndef SPDRP_ADDRESS
#define SPDRP_ADDRESS 28 #define SPDRP_ADDRESS 28
#endif #endif
#if !defined(SPDRP_INSTALL_STATE) #ifndef SPDRP_INSTALL_STATE
#define SPDRP_INSTALL_STATE 34 #define SPDRP_INSTALL_STATE 34
#endif #endif
#define MAX_CTRL_BUFFER_LENGTH 4096 #define MAX_CTRL_BUFFER_LENGTH 4096
#define MAX_USB_DEVICES 256
#define MAX_USB_STRING_LENGTH 128 #define MAX_USB_STRING_LENGTH 128
#define MAX_HID_REPORT_SIZE 1024 #define MAX_HID_REPORT_SIZE 1024
#define MAX_HID_DESCRIPTOR_SIZE 256 #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/ff545978.aspx
// http://msdn.microsoft.com/en-us/library/ff545972.aspx // http://msdn.microsoft.com/en-us/library/ff545972.aspx
// http://msdn.microsoft.com/en-us/library/ff545982.aspx // http://msdn.microsoft.com/en-us/library/ff545982.aspx
#if !defined(GUID_DEVINTERFACE_USB_HOST_CONTROLLER) #ifndef GUID_DEVINTERFACE_USB_HOST_CONTROLLER
const GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = { 0x3ABF6F2D, 0x71C4, 0x462A, {0x8A, 0x92, 0x1E, 0x68, 0x61, 0xE6, 0xAF, 0x27} }; const GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = {0x3ABF6F2D, 0x71C4, 0x462A, {0x8A, 0x92, 0x1E, 0x68, 0x61, 0xE6, 0xAF, 0x27}};
#endif #endif
#if !defined(GUID_DEVINTERFACE_USB_DEVICE) #ifndef GUID_DEVINTERFACE_USB_DEVICE
const GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED} }; const GUID GUID_DEVINTERFACE_USB_DEVICE = {0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED}};
#endif #endif
#if !defined(GUID_DEVINTERFACE_USB_HUB) #ifndef GUID_DEVINTERFACE_USB_HUB
const GUID GUID_DEVINTERFACE_USB_HUB = { 0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8} }; const GUID GUID_DEVINTERFACE_USB_HUB = {0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8}};
#endif #endif
#if !defined(GUID_DEVINTERFACE_LIBUSB0_FILTER) #ifndef GUID_DEVINTERFACE_LIBUSB0_FILTER
const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = { 0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9} }; const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = {0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9}};
#endif #endif
@ -84,8 +83,6 @@ const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = { 0xF9F3FF14, 0xAE21, 0x48A0, {0x8
#define USB_API_WINUSBX 3 #define USB_API_WINUSBX 3
#define USB_API_HID 4 #define USB_API_HID 4
#define USB_API_MAX 5 #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) // 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 // 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_WINUSB 2
#define SUB_API_MAX 3 #define SUB_API_MAX 3
#define WINUSBX_DRV_NAMES {"libusbK", "libusb0", "WinUSB"}
struct windows_usb_api_backend { struct windows_usb_api_backend {
const uint8_t id; const uint8_t id;
const char *designation; const char * const designation;
const char **driver_name_list; // Driver name, without .sys, e.g. "usbccgp" const char * const * const driver_name_list; // Driver name, without .sys, e.g. "usbccgp"
const uint8_t nb_driver_names; const uint8_t nb_driver_names;
int (*init)(int sub_api, struct libusb_context *ctx); int (*init)(struct libusb_context *ctx);
int (*exit)(int sub_api); void (*exit)(void);
int (*open)(int sub_api, struct libusb_device_handle *dev_handle); int (*open)(int sub_api, struct libusb_device_handle *dev_handle);
void (*close)(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); 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]; extern const struct windows_usb_api_backend usb_api_backend[USB_API_MAX];
#define PRINT_UNSUPPORTED_API(fname) \ #define PRINT_UNSUPPORTED_API(fname) \
usbi_dbg("unsupported API call for '" \ usbi_dbg("unsupported API call for '%s' " \
#fname "' (unrecognized device driver)"); \ "(unrecognized device driver)", #fname)
return LIBUSB_ERROR_NOT_SUPPORTED;
#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 * 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_IN(request_type) ((request_type) & LIBUSB_ENDPOINT_IN)
#define LIBUSB_REQ_OUT(request_type) (!LIBUSB_REQ_IN(request_type)) #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 // 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) \ #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) \ #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_FEATURE HID_OUT_CTL_CODE(100)
#define IOCTL_HID_GET_INPUT_REPORT HID_OUT_CTL_CODE(104) #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 input_report_size;
uint16_t output_report_size; uint16_t output_report_size;
uint16_t feature_report_size; uint16_t feature_report_size;
uint16_t usage;
uint16_t usagePage;
WCHAR string[3][MAX_USB_STRING_LENGTH]; WCHAR string[3][MAX_USB_STRING_LENGTH];
uint8_t string_index[3]; // man, prod, ser uint8_t string_index[3]; // man, prod, ser
}; };
struct windows_device_priv { static inline struct winusb_device_priv *_device_priv(struct libusb_device *dev)
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)
{ {
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; int i;
p->depth = 0;
p->port = 0;
p->path = NULL;
p->apib = &usb_api_backend[USB_API_UNSUPPORTED]; p->apib = &usb_api_backend[USB_API_UNSUPPORTED];
p->sub_api = SUB_API_NOTSET; 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++) { 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].apib = &usb_api_backend[USB_API_UNSUPPORTED];
p->usb_interface[i].sub_api = SUB_API_NOTSET; 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; 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; int i;
safe_free(p->path); free(p->dev_id);
free(p->path);
if ((dev->num_configurations > 0) && (p->config_descriptor != NULL)) { if ((dev->num_configurations > 0) && (p->config_descriptor != NULL)) {
for (i = 0; i < dev->num_configurations; i++) for (i = 0; i < dev->num_configurations; i++)
safe_free(p->config_descriptor[i]); free(p->config_descriptor[i]);
} }
safe_free(p->config_descriptor); free(p->config_descriptor);
safe_free(p->hid); free(p->hid);
for (i = 0; i < USB_MAXINTERFACES; i++) { for (i = 0; i < USB_MAXINTERFACES; i++) {
safe_free(p->usb_interface[i].path); free(p->usb_interface[i].path);
safe_free(p->usb_interface[i].endpoint); free(p->usb_interface[i].endpoint);
} }
} }
struct interface_handle_t { static inline struct winusb_device_handle_priv *_device_handle_priv(
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(
struct libusb_device_handle *handle) 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 // used to match a device driver (including filter drivers) against a supported API
struct driver_lookup { struct driver_lookup {
char list[MAX_KEY_LENGTH + 1]; // REG_MULTI_SZ list of services (driver) names 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) 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 * 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 DWORD RETURN_TYPE;
typedef RETURN_TYPE CONFIGRET; typedef RETURN_TYPE CONFIGRET;
#define CR_SUCCESS 0x00000000 #define CR_SUCCESS 0x00000000
#define CR_NO_SUCH_DEVNODE 0x0000000D
#define USB_DEVICE_DESCRIPTOR_TYPE LIBUSB_DT_DEVICE /* Cfgmgr32 dependencies */
#define USB_CONFIGURATION_DESCRIPTOR_TYPE LIBUSB_DT_CONFIG DLL_DECLARE_HANDLE(Cfgmgr32);
#define USB_STRING_DESCRIPTOR_TYPE LIBUSB_DT_STRING DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG));
#define USB_INTERFACE_DESCRIPTOR_TYPE LIBUSB_DT_INTERFACE DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG));
#define USB_ENDPOINT_DESCRIPTOR_TYPE LIBUSB_DT_ENDPOINT
#define USB_REQUEST_GET_STATUS LIBUSB_REQUEST_GET_STATUS /* AdvAPI32 dependencies */
#define USB_REQUEST_CLEAR_FEATURE LIBUSB_REQUEST_CLEAR_FEATURE DLL_DECLARE_HANDLE(AdvAPI32);
#define USB_REQUEST_SET_FEATURE LIBUSB_REQUEST_SET_FEATURE DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD));
#define USB_REQUEST_SET_ADDRESS LIBUSB_REQUEST_SET_ADDRESS DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY));
#define USB_REQUEST_GET_DESCRIPTOR LIBUSB_REQUEST_GET_DESCRIPTOR
#define USB_REQUEST_SET_DESCRIPTOR LIBUSB_REQUEST_SET_DESCRIPTOR
#define USB_REQUEST_GET_CONFIGURATION LIBUSB_REQUEST_GET_CONFIGURATION
#define USB_REQUEST_SET_CONFIGURATION LIBUSB_REQUEST_SET_CONFIGURATION
#define USB_REQUEST_GET_INTERFACE LIBUSB_REQUEST_GET_INTERFACE
#define USB_REQUEST_SET_INTERFACE LIBUSB_REQUEST_SET_INTERFACE
#define USB_REQUEST_SYNC_FRAME LIBUSB_REQUEST_SYNCH_FRAME
#define USB_GET_NODE_INFORMATION 258 /* OLE32 dependency */
#define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 260 DLL_DECLARE_HANDLE(OLE32);
#define USB_GET_NODE_CONNECTION_NAME 261 DLL_DECLARE_FUNC_PREFIXED(WINAPI, HRESULT, p, IIDFromString, (LPCOLESTR, LPIID));
#define USB_GET_HUB_CAPABILITIES 271
#if !defined(USB_GET_NODE_CONNECTION_INFORMATION_EX) /* SetupAPI dependencies */
#define USB_GET_NODE_CONNECTION_INFORMATION_EX 274 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 #endif
#if !defined(USB_GET_HUB_CAPABILITIES_EX) #ifndef USB_GET_NODE_CONNECTION_INFORMATION_EX
#define USB_GET_HUB_CAPABILITIES_EX 276 #define USB_GET_NODE_CONNECTION_INFORMATION_EX 274
#endif #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 #define USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 279
#endif #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 #ifndef FILE_DEVICE_USB
#define FILE_DEVICE_USB FILE_DEVICE_UNKNOWN #define FILE_DEVICE_USB FILE_DEVICE_UNKNOWN
#endif #endif
#ifndef CTL_CODE #define USB_CTL_CODE(id) \
#define CTL_CODE(DeviceType, Function, Method, Access) \ CTL_CODE(FILE_DEVICE_USB, (id), METHOD_BUFFERED, FILE_ANY_ACCESS)
(((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
#endif #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 { typedef enum USB_CONNECTION_STATUS {
NoDeviceConnected, NoDeviceConnected,
@ -406,42 +338,25 @@ typedef enum USB_HUB_NODE {
UsbMIParent UsbMIParent
} USB_HUB_NODE; } 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 // Most of the structures below need to be packed
#pragma pack(push, 1) #include <pshpack1.h>
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 { typedef struct USB_INTERFACE_DESCRIPTOR {
UCHAR bLength; UCHAR bLength;
@ -455,103 +370,7 @@ typedef struct USB_INTERFACE_DESCRIPTOR {
UCHAR iInterface; UCHAR iInterface;
} USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR; } USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR;
typedef struct USB_CONFIGURATION_DESCRIPTOR_SHORT { typedef struct _USB_NODE_CONNECTION_INFORMATION_EX {
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 {
ULONG ConnectionIndex; ULONG ConnectionIndex;
USB_DEVICE_DESCRIPTOR DeviceDescriptor; USB_DEVICE_DESCRIPTOR DeviceDescriptor;
UCHAR CurrentConfigurationValue; UCHAR CurrentConfigurationValue;
@ -589,25 +408,7 @@ typedef struct _USB_NODE_CONNECTION_INFORMATION_EX_V2 {
USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS Flags; USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS Flags;
} USB_NODE_CONNECTION_INFORMATION_EX_V2, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2; } USB_NODE_CONNECTION_INFORMATION_EX_V2, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2;
typedef struct USB_HUB_CAP_FLAGS { #include <poppack.h>
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)
/* winusb.dll interface */ /* winusb.dll interface */
@ -619,36 +420,25 @@ typedef struct USB_HUB_CAPABILITIES_EX {
#define AUTO_FLUSH 0x06 #define AUTO_FLUSH 0x06
#define RAW_IO 0x07 #define RAW_IO 0x07
#define MAXIMUM_TRANSFER_SIZE 0x08 #define MAXIMUM_TRANSFER_SIZE 0x08
#define AUTO_SUSPEND 0x81
#define SUSPEND_DELAY 0x83
#define DEVICE_SPEED 0x01
#define LowSpeed 0x01
#define FullSpeed 0x02
#define HighSpeed 0x03
typedef enum USBD_PIPE_TYPE { typedef enum _USBD_PIPE_TYPE {
UsbdPipeTypeControl, UsbdPipeTypeControl,
UsbdPipeTypeIsochronous, UsbdPipeTypeIsochronous,
UsbdPipeTypeBulk, UsbdPipeTypeBulk,
UsbdPipeTypeInterrupt UsbdPipeTypeInterrupt
} USBD_PIPE_TYPE; } USBD_PIPE_TYPE;
typedef struct { #include <pshpack1.h>
USBD_PIPE_TYPE PipeType;
UCHAR PipeId;
USHORT MaximumPacketSize;
UCHAR Interval;
} WINUSB_PIPE_INFORMATION, *PWINUSB_PIPE_INFORMATION;
#pragma pack(1) typedef struct _WINUSB_SETUP_PACKET {
typedef struct { UCHAR RequestType;
UCHAR request_type; UCHAR Request;
UCHAR request; USHORT Value;
USHORT value; USHORT Index;
USHORT index; USHORT Length;
USHORT length;
} WINUSB_SETUP_PACKET, *PWINUSB_SETUP_PACKET; } WINUSB_SETUP_PACKET, *PWINUSB_SETUP_PACKET;
#pragma pack()
#include <poppack.h>
typedef void *WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE; typedef void *WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE;
@ -676,59 +466,10 @@ typedef BOOL (WINAPI *WinUsb_GetAssociatedInterface_t)(
UCHAR AssociatedInterfaceIndex, UCHAR AssociatedInterfaceIndex,
PWINUSB_INTERFACE_HANDLE AssociatedInterfaceHandle 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)( typedef BOOL (WINAPI *WinUsb_Initialize_t)(
HANDLE DeviceHandle, HANDLE DeviceHandle,
PWINUSB_INTERFACE_HANDLE InterfaceHandle 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)( typedef BOOL (WINAPI *WinUsb_ReadPipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle, WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID, UCHAR PipeID,
@ -737,6 +478,9 @@ typedef BOOL (WINAPI *WinUsb_ReadPipe_t)(
PULONG LengthTransferred, PULONG LengthTransferred,
LPOVERLAPPED Overlapped LPOVERLAPPED Overlapped
); );
typedef BOOL (WINAPI *WinUsb_ResetDevice_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle
);
typedef BOOL (WINAPI *WinUsb_ResetPipe_t)( typedef BOOL (WINAPI *WinUsb_ResetPipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle, WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID UCHAR PipeID
@ -752,12 +496,6 @@ typedef BOOL (WINAPI *WinUsb_SetPipePolicy_t)(
ULONG ValueLength, ULONG ValueLength,
PVOID Value PVOID Value
); );
typedef BOOL (WINAPI *WinUsb_SetPowerPolicy_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
ULONG PolicyType,
ULONG ValueLength,
PVOID Value
);
typedef BOOL (WINAPI *WinUsb_WritePipe_t)( typedef BOOL (WINAPI *WinUsb_WritePipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle, WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID, UCHAR PipeID,
@ -766,8 +504,59 @@ typedef BOOL (WINAPI *WinUsb_WritePipe_t)(
PULONG LengthTransferred, PULONG LengthTransferred,
LPOVERLAPPED Overlapped 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 */ /* /!\ These must match the ones from the official libusbk.h */
@ -814,8 +603,7 @@ typedef struct _KLIB_VERSION {
INT Minor; INT Minor;
INT Micro; INT Micro;
INT Nano; INT Nano;
} KLIB_VERSION; } KLIB_VERSION, *PKLIB_VERSION;
typedef KLIB_VERSION* PKLIB_VERSION;
typedef BOOL (WINAPI *LibK_GetProcAddress_t)( typedef BOOL (WINAPI *LibK_GetProcAddress_t)(
PVOID *ProcAddress, PVOID *ProcAddress,
@ -827,29 +615,72 @@ typedef VOID (WINAPI *LibK_GetVersion_t)(
PKLIB_VERSION Version 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 { struct winusb_interface {
bool initialized; bool initialized;
bool CancelIoEx_supported;
WinUsb_AbortPipe_t AbortPipe; WinUsb_AbortPipe_t AbortPipe;
WinUsb_ControlTransfer_t ControlTransfer; WinUsb_ControlTransfer_t ControlTransfer;
WinUsb_FlushPipe_t FlushPipe; WinUsb_FlushPipe_t FlushPipe;
WinUsb_Free_t Free; WinUsb_Free_t Free;
WinUsb_GetAssociatedInterface_t GetAssociatedInterface; 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_Initialize_t Initialize;
WinUsb_QueryDeviceInformation_t QueryDeviceInformation;
WinUsb_QueryInterfaceSettings_t QueryInterfaceSettings;
WinUsb_QueryPipe_t QueryPipe;
WinUsb_ReadPipe_t ReadPipe; WinUsb_ReadPipe_t ReadPipe;
WinUsb_ResetDevice_t ResetDevice;
WinUsb_ResetPipe_t ResetPipe; WinUsb_ResetPipe_t ResetPipe;
WinUsb_SetCurrentAlternateSetting_t SetCurrentAlternateSetting; WinUsb_SetCurrentAlternateSetting_t SetCurrentAlternateSetting;
WinUsb_SetPipePolicy_t SetPipePolicy; WinUsb_SetPipePolicy_t SetPipePolicy;
WinUsb_SetPowerPolicy_t SetPowerPolicy;
WinUsb_WritePipe_t WritePipe; 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 */ /* hid.dll interface */
@ -857,17 +688,19 @@ struct winusb_interface {
#define HIDP_STATUS_SUCCESS 0x110000 #define HIDP_STATUS_SUCCESS 0x110000
typedef void * PHIDP_PREPARSED_DATA; typedef void * PHIDP_PREPARSED_DATA;
#pragma pack(1) #include <pshpack1.h>
typedef struct {
typedef struct _HIDD_ATTIRBUTES {
ULONG Size; ULONG Size;
USHORT VendorID; USHORT VendorID;
USHORT ProductID; USHORT ProductID;
USHORT VersionNumber; USHORT VersionNumber;
} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; } HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
#pragma pack()
#include <poppack.h>
typedef USHORT USAGE; typedef USHORT USAGE;
typedef struct { typedef struct _HIDP_CAPS {
USAGE Usage; USAGE Usage;
USAGE UsagePage; USAGE UsagePage;
USHORT InputReportByteLength; USHORT InputReportByteLength;
@ -930,19 +763,16 @@ typedef struct _HIDP_VALUE_CAPS {
} HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS; } HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS;
DLL_DECLARE_HANDLE(hid); 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, 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_GetPreparsedData, (HANDLE, PHIDP_PREPARSED_DATA *));
DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_FreePreparsedData, (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_GetManufacturerString, (HANDLE, PVOID, ULONG));
DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetProductString, (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_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, LONG, HidP_GetCaps, (PHIDP_PREPARSED_DATA, PHIDP_CAPS));
DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetNumInputBuffers, (HANDLE, ULONG)); 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_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, HidD_FlushQueue, (HANDLE));
DLL_DECLARE_FUNC(WINAPI, BOOL, HidP_GetValueCaps, (HIDP_REPORT_TYPE, PHIDP_VALUE_CAPS, PULONG, PHIDP_PREPARSED_DATA)); DLL_DECLARE_FUNC(WINAPI, BOOL, HidP_GetValueCaps, (HIDP_REPORT_TYPE, PHIDP_VALUE_CAPS, PULONG, PHIDP_PREPARSED_DATA));

View File

@ -38,7 +38,7 @@ static size_t usbi_locale = 0;
* How to add a new \ref libusb_strerror() translation: * How to add a new \ref libusb_strerror() translation:
* <ol> * <ol>
* <li> Download the latest \c strerror.c from:<br> * <li> Download the latest \c strerror.c from:<br>
* https://raw.github.com/libusb/libusb/master/libusb/sterror.c </li> * https://raw.github.com/libusb/libusb/master/libusb/strerror.c </li>
* <li> Open the file in an UTF-8 capable editor </li> * <li> Open the file in an UTF-8 capable editor </li>
* <li> Add the 2 letter <a href="http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes">ISO 639-1</a> * <li> Add the 2 letter <a href="http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes">ISO 639-1</a>
* code for your locale at the end of \c usbi_locale_supported[]<br> * code for your locale at the end of \c usbi_locale_supported[]<br>
@ -60,7 +60,7 @@ static size_t usbi_locale = 0;
* </ol> * </ol>
*/ */
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] = { static const char* usbi_localized_errors[ARRAYSIZE(usbi_locale_supported)][LIBUSB_ERROR_COUNT] = {
{ /* English (en) */ { /* English (en) */
"Success", "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",
} }
}; };

View File

@ -7,12 +7,12 @@
#define LIBUSB_MINOR 0 #define LIBUSB_MINOR 0
#endif #endif
#ifndef LIBUSB_MICRO #ifndef LIBUSB_MICRO
#define LIBUSB_MICRO 21 #define LIBUSB_MICRO 23
#endif #endif
#ifndef LIBUSB_NANO #ifndef LIBUSB_NANO
#define LIBUSB_NANO 0 #define LIBUSB_NANO 0
#endif #endif
/* LIBUSB_RC is the release candidate suffix. Should normally be empty. */ /* LIBUSB_RC is the release candidate suffix. Should normally be empty. */
#ifndef LIBUSB_RC #ifndef LIBUSB_RC
#define LIBUSB_RC "" #define LIBUSB_RC "-rc1"
#endif #endif

View File

@ -1 +1 @@
#define LIBUSB_NANO 11156 #define LIBUSB_NANO 11367

View File

@ -67,6 +67,7 @@
<ClInclude Include="libusb\version_nano.h" /> <ClInclude Include="libusb\version_nano.h" />
<ClInclude Include="libusb\os\windows_common.h" /> <ClInclude Include="libusb\os\windows_common.h" />
<ClInclude Include="libusb\os\windows_nt_common.h" /> <ClInclude Include="libusb\os\windows_nt_common.h" />
<ClInclude Include="libusb\os\windows_nt_shared_types.h" />
<ClInclude Include="libusb\os\windows_usbdk.h" /> <ClInclude Include="libusb\os\windows_usbdk.h" />
<ClInclude Include="libusb\os\windows_winusb.h" /> <ClInclude Include="libusb\os\windows_winusb.h" />
</ItemGroup> </ItemGroup>

View File

@ -7,22 +7,21 @@ if [%Configuration%] NEQ [Release] goto debugx64
:debugx64 :debugx64
if [%Platform%] NEQ [x64] goto debugWin32 if [%Platform%] NEQ [x64] goto debugWin32
if [%Configuration%] NEQ [Debug] exit 0 if [%Configuration%] NEQ [Debug] exit 0
call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /Debug /x64 call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /Debug /x64 || exit /B
msbuild %libusb_2010% /p:Configuration=Debug,Platform=x64 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" msbuild %libusb_2010% /p:Configuration=Debug,Platform=x64 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" || exit /B
:releasex64 :releasex64
if [%Platform%] NEQ [x64] goto releaseWin32 if [%Platform%] NEQ [x64] goto releaseWin32
if [%Configuration%] NEQ [Release] exit 0 if [%Configuration%] NEQ [Release] exit 0
call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /Release /x64 call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /Release /x64 || exit /B
msbuild %libusb_2010% /p:Configuration=Release,Platform=x64 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" msbuild %libusb_2010% /p:Configuration=Release,Platform=x64 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" || exit /B
:debugWin32 :debugWin32
if [%Platform%] NEQ [Win32] exit 0 if [%Platform%] NEQ [Win32] exit 0
if [%Configuration%] NEQ [Debug] 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" msbuild %libusb_2010% /p:Configuration=Debug,Platform=Win32 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" || exit /B
:releaseWin32 :releaseWin32
if [%Platform%] NEQ [Win32] exit 0 if [%Platform%] NEQ [Win32] exit 0
if [%Configuration%] NEQ [Release] 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" msbuild %libusb_2010% /p:Configuration=Release,Platform=Win32 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" || exit /B

View File

@ -6,16 +6,18 @@
#endif #endif
/* Visual Studio 2015 and later defines timespec */ /* Visual Studio 2015 and later defines timespec */
#if defined(_MSC_VER) && (_MSC_VER >= 1900) #if (_MSC_VER >= 1900)
#define _TIMESPEC_DEFINED 1 #define _TIMESPEC_DEFINED 1
#endif #endif
/* Disable: warning C4200: nonstandard extension used : zero-sized array in struct/union */ /* Disable: warning C4200: nonstandard extension used : zero-sized array in struct/union */
#pragma warning(disable:4200) #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 */ /* 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 */ /* Disable: warning C4996: 'GetVersionA': was declared deprecated */
#pragma warning(disable: 4996) #pragma warning(disable:4996)
#if defined(_PREFAST_) #if defined(_PREFAST_)
/* Disable "Banned API" errors when using the MS's WDK OACR/Prefast */ /* Disable "Banned API" errors when using the MS's WDK OACR/Prefast */
@ -45,6 +47,5 @@
#define HAVE_MISSING_H #define HAVE_MISSING_H
#else #else
#define OS_WINDOWS 1 #define OS_WINDOWS 1
#define HAVE_SIGNAL_H 1
#define HAVE_SYS_TYPES_H 1 #define HAVE_SYS_TYPES_H 1
#endif #endif

View File

@ -3,28 +3,20 @@
::# you can pass the following arguments (case insensitive): ::# you can pass the following arguments (case insensitive):
::# - "DLL" to build a DLL instead of a static library ::# - "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) ::# - "/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 if Test%BUILD_ALT_DIR%==Test goto usage
::# process commandline parameters ::# process commandline parameters
set TARGET=LIBRARY set TARGET=LIBRARY
set STATIC_LIBC= set STATIC_LIBC=
set WITH_USBDK=
set version=1.0 set version=1.0
set PWD=%~dp0 set PWD=%~dp0
set BUILD_CMD=build -bcwgZ -M2 set BUILD_CMD=build /bcwgZ /M2
:more_args
if "%1" == "" goto no_more_args if "%1" == "" goto no_more_args
::# /I for case insensitive ::# /I for case insensitive
if /I Test%1==TestDLL set TARGET=DYNLINK if /I Test%1==TestDLL set TARGET=DYNLINK
if /I Test%1==Test/MT set STATIC_LIBC=1 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 :no_more_args
@ -53,13 +45,13 @@ set dstPath=%destType%\Release
:isDebug :isDebug
if exist %destType% goto md2 if exist %destType% goto md2
mkdir %destType% md %destType%
:md2 :md2
if exist %dstPath% goto md3 if exist %dstPath% goto md3
mkdir %dstPath% md %dstPath%
:md3 :md3
if exist %dstPath%\dll goto md4 if exist %dstPath%\dll goto md4
mkdir %dstPath%\dll md %dstPath%\dll
:md4 :md4
if exist %dstPath%\lib goto md5 if exist %dstPath%\lib goto md5
md %dstPath%\lib md %dstPath%\lib
@ -67,9 +59,12 @@ md %dstPath%\lib
if exist %dstPath%\examples goto md6 if exist %dstPath%\examples goto md6
md %dstPath%\examples md %dstPath%\examples
:md6 :md6
if exist %dstPath%\tests goto md7
md %dstPath%\tests
:md7
@echo on @echo on
@if /I NOT Test%1==TestDLL goto copylib if %TARGET%==LIBRARY goto copylib
copy %srcPath%\libusb-%version%.dll %dstPath%\dll copy %srcPath%\libusb-%version%.dll %dstPath%\dll
copy %srcPath%\libusb-%version%.pdb %dstPath%\dll copy %srcPath%\libusb-%version%.pdb %dstPath%\dll
:copylib :copylib
@ -77,49 +72,9 @@ copy %srcPath%\libusb-%version%.lib %dstPath%\lib
@echo off @echo off
if exist examples\listdevs_ddkbuild goto md7 if exist examples\getopt\getopt_ddkbuild goto md8
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 md examples\getopt\getopt_ddkbuild
:md9 :md8
cd examples\getopt\getopt_ddkbuild cd examples\getopt\getopt_ddkbuild
copy ..\..\..\msvc\getopt_sources sources >NUL 2>&1 copy ..\..\..\msvc\getopt_sources sources >NUL 2>&1
@ -129,9 +84,9 @@ copy ..\..\..\msvc\getopt_sources sources >NUL 2>&1
if errorlevel 1 goto builderror if errorlevel 1 goto builderror
cd ..\..\.. cd ..\..\..
if exist examples\fxload_ddkbuild goto md10 if exist examples\fxload_ddkbuild goto md9
md examples\fxload_ddkbuild md examples\fxload_ddkbuild
:md10 :md9
cd examples\fxload_ddkbuild cd examples\fxload_ddkbuild
copy ..\..\msvc\fxload_sources sources >NUL 2>&1 copy ..\..\msvc\fxload_sources sources >NUL 2>&1
@ -149,9 +104,9 @@ copy %srcPath%\fxload.pdb %dstPath%\examples
@echo off @echo off
if exist examples\hotplugtest_ddkbuild goto md11 if exist examples\hotplugtest_ddkbuild goto md10
md examples\hotplugtest_ddkbuild md examples\hotplugtest_ddkbuild
:md11 :md10
cd examples\hotplugtest_ddkbuild cd examples\hotplugtest_ddkbuild
copy ..\..\msvc\hotplugtest_sources sources >NUL 2>&1 copy ..\..\msvc\hotplugtest_sources sources >NUL 2>&1
@ -169,6 +124,86 @@ copy %srcPath%\hotplugtest.pdb %dstPath%\examples
@echo off @echo off
if exist examples\listdevs_ddkbuild goto md11
md examples\listdevs_ddkbuild
:md11
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\testlibusb_ddkbuild goto md12
md examples\testlibusb_ddkbuild
:md12
cd examples\testlibusb_ddkbuild
copy ..\..\msvc\testlibusb_sources sources >NUL 2>&1
@echo on
%BUILD_CMD%
@echo off
if errorlevel 1 goto builderror
cd ..\..
set srcPath=examples\testlibusb_ddkbuild\obj%BUILD_ALT_DIR%\%cpudir%
@echo on
copy %srcPath%\testlibusb.exe %dstPath%\examples
copy %srcPath%\testlibusb.pdb %dstPath%\examples
@echo off
if exist examples\xusb_ddkbuild goto md13
md examples\xusb_ddkbuild
:md13
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 tests\stress_ddkbuild goto md14
md tests\stress_ddkbuild
:md14
cd tests\stress_ddkbuild
copy ..\..\msvc\stress_sources sources >NUL 2>&1
@echo on
%BUILD_CMD%
@echo off
if errorlevel 1 goto builderror
cd ..\..
set srcPath=tests\stress_ddkbuild\obj%BUILD_ALT_DIR%\%cpudir%
@echo on
copy %srcPath%\stress.exe %dstPath%\tests
copy %srcPath%\stress.pdb %dstPath%\tests
@echo off
cd msvc cd msvc
goto done goto done

View File

@ -25,127 +25,45 @@
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
</ImportGroup> </ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> <ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup> <PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir> <IntDir>$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir> <OutDir>$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup>
<BuildLog>
<Path>$(IntDir)$(ProjectName).htm</Path>
</BuildLog>
<ClCompile> <ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>__GNU_LIBRARY__;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
</ClCompile>
<ClCompile Condition="'$(Configuration)'=='Debug'">
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<BuildLog>
<Path>$(IntDir)$(ProjectName).htm</Path>
</BuildLog>
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>true</MinimalRebuild>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel> </ClCompile>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <ClCompile Condition="'$(Configuration)'=='Release'">
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
</Link>
<Link Condition="'$(Configuration)'=='Debug'">
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<BuildLog>
<Path>$(IntDir)$(ProjectName).htm</Path>
</BuildLog>
<ClCompile>
<AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<BuildLog>
<Path>$(IntDir)$(ProjectName).htm</Path>
</BuildLog>
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
@ -153,16 +71,17 @@
<ClCompile Include="..\examples\fxload.c" /> <ClCompile Include="..\examples\fxload.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\examples\ezusb.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include=".\getopt_2010.vcxproj">
<Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include=".\libusb_static_2010.vcxproj"> <ProjectReference Include=".\libusb_static_2010.vcxproj">
<Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project> <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly> <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference> </ProjectReference>
<ProjectReference Include="getopt_2010.vcxproj">
<Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\examples\ezusb.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">

View File

@ -25,131 +25,46 @@
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset> <PlatformToolset>v110</PlatformToolset>
<WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
</ImportGroup> </ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> <ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup> <PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir> <IntDir>$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir> <OutDir>$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup>
<BuildLog>
<Path>$(IntDir)$(ProjectName).htm</Path>
</BuildLog>
<ClCompile> <ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>__GNU_LIBRARY__;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
</ClCompile>
<ClCompile Condition="'$(Configuration)'=='Debug'">
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<BuildLog>
<Path>$(IntDir)$(ProjectName).htm</Path>
</BuildLog>
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>true</MinimalRebuild>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel> </ClCompile>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <ClCompile Condition="'$(Configuration)'=='Release'">
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
</Link>
<Link Condition="'$(Configuration)'=='Debug'">
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<BuildLog>
<Path>$(IntDir)$(ProjectName).htm</Path>
</BuildLog>
<ClCompile>
<AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<BuildLog>
<Path>$(IntDir)$(ProjectName).htm</Path>
</BuildLog>
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
@ -157,16 +72,17 @@
<ClCompile Include="..\examples\fxload.c" /> <ClCompile Include="..\examples\fxload.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\examples\ezusb.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include=".\getopt_2012.vcxproj">
<Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include=".\libusb_static_2012.vcxproj"> <ProjectReference Include=".\libusb_static_2012.vcxproj">
<Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project> <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly> <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference> </ProjectReference>
<ProjectReference Include="getopt_2012.vcxproj">
<Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\examples\ezusb.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">

View File

@ -25,131 +25,46 @@
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120</PlatformToolset> <PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
</ImportGroup> </ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> <ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup> <PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir> <IntDir>$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir> <OutDir>$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup>
<BuildLog>
<Path>$(IntDir)$(ProjectName).htm</Path>
</BuildLog>
<ClCompile> <ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>__GNU_LIBRARY__;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
</ClCompile>
<ClCompile Condition="'$(Configuration)'=='Debug'">
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<BuildLog>
<Path>$(IntDir)$(ProjectName).htm</Path>
</BuildLog>
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>true</MinimalRebuild>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel> </ClCompile>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <ClCompile Condition="'$(Configuration)'=='Release'">
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
</Link>
<Link Condition="'$(Configuration)'=='Debug'">
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<BuildLog>
<Path>$(IntDir)$(ProjectName).htm</Path>
</BuildLog>
<ClCompile>
<AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<BuildLog>
<Path>$(IntDir)$(ProjectName).htm</Path>
</BuildLog>
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
@ -157,16 +72,17 @@
<ClCompile Include="..\examples\fxload.c" /> <ClCompile Include="..\examples\fxload.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\examples\ezusb.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include=".\getopt_2013.vcxproj">
<Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include=".\libusb_static_2013.vcxproj"> <ProjectReference Include=".\libusb_static_2013.vcxproj">
<Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project> <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly> <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference> </ProjectReference>
<ProjectReference Include="getopt_2013.vcxproj">
<Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\examples\ezusb.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">

View File

@ -25,131 +25,46 @@
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
</ImportGroup> </ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> <ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup> <PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir> <IntDir>$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir> <OutDir>$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup>
<BuildLog>
<Path>$(IntDir)$(ProjectName).htm</Path>
</BuildLog>
<ClCompile> <ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>__GNU_LIBRARY__;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
</ClCompile>
<ClCompile Condition="'$(Configuration)'=='Debug'">
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<BuildLog>
<Path>$(IntDir)$(ProjectName).htm</Path>
</BuildLog>
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>true</MinimalRebuild>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel> </ClCompile>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <ClCompile Condition="'$(Configuration)'=='Release'">
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
</Link>
<Link Condition="'$(Configuration)'=='Debug'">
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<BuildLog>
<Path>$(IntDir)$(ProjectName).htm</Path>
</BuildLog>
<ClCompile>
<AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<BuildLog>
<Path>$(IntDir)$(ProjectName).htm</Path>
</BuildLog>
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;__GNU_LIBRARY__;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
@ -157,16 +72,17 @@
<ClCompile Include="..\examples\fxload.c" /> <ClCompile Include="..\examples\fxload.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\examples\ezusb.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include=".\getopt_2015.vcxproj">
<Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include=".\libusb_static_2015.vcxproj"> <ProjectReference Include=".\libusb_static_2015.vcxproj">
<Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project> <Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly> <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference> </ProjectReference>
<ProjectReference Include="getopt_2015.vcxproj">
<Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\examples\ezusb.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">

View File

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>fxload</ProjectName>
<ProjectGuid>{9E166F7A-A793-9FB6-0A67-F0AED8AE8C88}</ProjectGuid>
<RootNamespace>examples</RootNamespace>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
<WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
<WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<IntDir>$(SolutionDir)..\$(Platform)\$(Configuration)\examples\$(ProjectName)\</IntDir>
<OutDir>$(SolutionDir)..\$(Platform)\$(Configuration)\examples\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>.;..\examples\getopt;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>__GNU_LIBRARY__;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
<ClCompile Condition="'$(Configuration)'=='Debug'">
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<MinimalRebuild>true</MinimalRebuild>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<ClCompile Condition="'$(Configuration)'=='Release'">
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Link Condition="'$(Configuration)'=='Debug'">
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\examples\ezusb.c" />
<ClCompile Include="..\examples\fxload.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\examples\ezusb.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include=".\getopt_2017.vcxproj">
<Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include=".\libusb_static_2017.vcxproj">
<Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

Some files were not shown because too many files have changed in this diff Show More